172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_edit_view_win.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <locale> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <richedit.h> 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <textserv.h> 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "app/win/iat_patch_function.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/auto_reset.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/lazy_instance.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/app/chrome_command_ids.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_accessibility.h" 24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_popup_model.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/keyword_provider.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/command_updater.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/user_metrics.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/url_fixer_upper.h" 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url_model.h" 3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/location_bar/location_bar_view.h" 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/url_util.h" 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/escape.h" 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/skia_utils_win.h" 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/clipboard/clipboard.h" 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/clipboard/scoped_clipboard_writer.h" 43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "ui/base/dragdrop/drag_drop_types.h" 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/drag_source.h" 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/drop_target.h" 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/os_exchange_data.h" 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/os_exchange_data_provider_win.h" 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/keycodes/keyboard_codes.h" 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util_win.h" 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas.h" 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h" 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/controls/textfield/native_textfield_win.h" 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/drag_utils.h" 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/events/event_utils_win.h" 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/focus/focus_util_win.h" 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h" 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma comment(lib, "oleacc.lib") // Needed for accessibility support. 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma comment(lib, "riched20.lib") // Needed for the richedit control. 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompleteEditModel 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// A helper method for determining a valid DROPEFFECT given the allowed 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// DROPEFFECTS. We prefer copy over link. 69dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenDWORD CopyOrLinkDropEffect(DWORD effect) { 70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (effect & DROPEFFECT_COPY) 71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return DROPEFFECT_COPY; 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (effect & DROPEFFECT_LINK) 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return DROPEFFECT_LINK; 74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return DROPEFFECT_NONE; 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// A helper method for determining a valid drag operation given the allowed 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// operation. We prefer copy over link. 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint CopyOrLinkDragOperation(int drag_operation) { 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (drag_operation & ui::DragDropTypes::DRAG_COPY) 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ui::DragDropTypes::DRAG_COPY; 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (drag_operation & ui::DragDropTypes::DRAG_LINK) 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ui::DragDropTypes::DRAG_LINK; 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ui::DragDropTypes::DRAG_NONE; 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// The AutocompleteEditState struct contains enough information about the 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// AutocompleteEditModel and AutocompleteEditViewWin to save/restore a user's 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// typing, caret position, etc. across tab changes. We explicitly don't 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// preserve things like whether the popup was open as this might be weird. 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct AutocompleteEditState { 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AutocompleteEditState(const AutocompleteEditModel::State& model_state, 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const AutocompleteEditViewWin::State& view_state) 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : model_state(model_state), 95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen view_state(view_state) { 96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const AutocompleteEditModel::State model_state; 99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const AutocompleteEditViewWin::State view_state; 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Returns true if the current point is far enough from the origin that it 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// would be considered a drag. 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool IsDrag(const POINT& origin, const POINT& current) { 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return views::View::ExceededDragThreshold(current.x - origin.x, 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen current.y - origin.y); 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EditDropTarget is the IDropTarget implementation installed on 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompleteEditViewWin. EditDropTarget prefers URL over plain text. A drop 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of a URL replaces all the text of the edit and navigates immediately to the 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// URL. A drop of plain text from the same edit either copies or moves the 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// selected text, and a drop of plain text from a source other than the edit 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// does a paste and go. 117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass AutocompleteEditViewWin::EditDropTarget : public ui::DropTarget { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit EditDropTarget(AutocompleteEditViewWin* edit); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual DWORD OnDragEnter(IDataObject* data_object, 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD key_state, 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT cursor_position, 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD effect); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual DWORD OnDragOver(IDataObject* data_object, 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD key_state, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT cursor_position, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD effect); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnDragLeave(IDataObject* data_object); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual DWORD OnDrop(IDataObject* data_object, 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD key_state, 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT cursor_position, 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD effect); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If dragging a string, the drop highlight position of the edit is reset 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // based on the mouse position. 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateDropHighlightPosition(const POINT& cursor_screen_position); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Resets the visual drop indicates we install on the edit. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ResetDropHighlights(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The edit we're the drop target for. 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutocompleteEditViewWin* edit_; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If true, the drag session contains a URL. 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool drag_has_url_; 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If true, the drag session contains a string. If drag_has_url_ is true, 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this is false regardless of whether the clipboard has a string. 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool drag_has_string_; 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(EditDropTarget); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAutocompleteEditViewWin::EditDropTarget::EditDropTarget( 158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AutocompleteEditViewWin* edit) 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : ui::DropTarget(edit->m_hWnd), 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_(edit), 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_has_url_(false), 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_has_string_(false) { 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenDWORD AutocompleteEditViewWin::EditDropTarget::OnDragEnter( 166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen IDataObject* data_object, 167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD key_state, 168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen POINT cursor_position, 169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD effect) { 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::OSExchangeData os_data(new ui::OSExchangeDataProviderWin(data_object)); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_has_url_ = os_data.HasURL(); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_has_string_ = !drag_has_url_ && os_data.HasString(); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_has_url_) { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (edit_->in_drag()) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The edit we're associated with originated the drag. No point in 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // allowing the user to drop back on us. 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_has_url_ = false; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: it would be nice to visually show all the text is going to 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be replaced by selecting all, but this caused painting problems. In 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // particular the flashing caret would appear outside the edit! For now 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we stick with no visual indicator other than that shown own the mouse 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cursor. 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OnDragOver(data_object, key_state, cursor_position, effect); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenDWORD AutocompleteEditViewWin::EditDropTarget::OnDragOver( 189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen IDataObject* data_object, 190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD key_state, 191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen POINT cursor_position, 192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD effect) { 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_has_url_) 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CopyOrLinkDropEffect(effect); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_has_string_) { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateDropHighlightPosition(cursor_position); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (edit_->drop_highlight_position() == -1 && edit_->in_drag()) 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DROPEFFECT_NONE; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (edit_->in_drag()) { 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The edit we're associated with originated the drag. Do the normal drag 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // behavior. 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK((effect & DROPEFFECT_COPY) && (effect & DROPEFFECT_MOVE)); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (key_state & MK_CONTROL) ? DROPEFFECT_COPY : DROPEFFECT_MOVE; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our edit didn't originate the drag, only allow link or copy. 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CopyOrLinkDropEffect(effect); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DROPEFFECT_NONE; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutocompleteEditViewWin::EditDropTarget::OnDragLeave( 214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen IDataObject* data_object) { 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResetDropHighlights(); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenDWORD AutocompleteEditViewWin::EditDropTarget::OnDrop( 219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen IDataObject* data_object, 220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD key_state, 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen POINT cursor_position, 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD effect) { 223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen effect = OnDragOver(data_object, key_state, cursor_position, effect); 224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::OSExchangeData os_data(new ui::OSExchangeDataProviderWin(data_object)); 226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen views::DropTargetEvent event(os_data, cursor_position.x, cursor_position.y, 227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ui::DragDropTypes::DropEffectToDragOperation(effect)); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int drag_operation = edit_->OnPerformDropImpl(event, edit_->in_drag()); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!drag_has_url_) 232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ResetDropHighlights(); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutocompleteEditViewWin::EditDropTarget::UpdateDropHighlightPosition( 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const POINT& cursor_screen_position) { 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_has_string_) { 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT client_position = cursor_screen_position; 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ::ScreenToClient(edit_->m_hWnd, &client_position); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int drop_position = edit_->CharFromPos(client_position); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (edit_->in_drag()) { 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our edit originated the drag, don't allow a drop if over the selected 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // region. 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LONG sel_start, sel_end; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_->GetSel(sel_start, sel_end); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((sel_start != sel_end) && (drop_position >= sel_start) && 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (drop_position <= sel_end)) 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_position = -1; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A drop from a source other than the edit replaces all the text, so 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we don't show the drop location. See comment in OnDragEnter as to why 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we don't try and select all here. 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_position = -1; 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_->SetDropHighlightPosition(drop_position); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutocompleteEditViewWin::EditDropTarget::ResetDropHighlights() { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_has_string_) 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_->SetDropHighlightPosition(-1); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper classes 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteEditViewWin::ScopedFreeze::ScopedFreeze( 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutocompleteEditViewWin* edit, 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ITextDocument* text_object_model) 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : edit_(edit), 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_(text_object_model) { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Freeze the screen. 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_object_model_) { 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch long count; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_->Freeze(&count); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteEditViewWin::ScopedFreeze::~ScopedFreeze() { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unfreeze the screen. 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: If this destructor is reached while the edit is being destroyed (for 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // example, because we double-clicked the edit of a popup and caused it to 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // transform to an unconstrained window), it will no longer have an HWND, and 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text_object_model_ may point to a destroyed object, so do nothing here. 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (edit_->IsWindow() && text_object_model_) { 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch long count; 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_->Unfreeze(&count); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (count == 0) { 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We need to UpdateWindow() here in addition to InvalidateRect() because, 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // as far as I can tell, the edit likes to synchronously erase its 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // background when unfreezing, thus requiring us to synchronously redraw 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // if we don't want flicker. 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen edit_->InvalidateRect(NULL, false); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_->UpdateWindow(); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteEditViewWin::ScopedSuspendUndo::ScopedSuspendUndo( 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ITextDocument* text_object_model) 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : text_object_model_(text_object_model) { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Suspend Undo processing. 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_object_model_) 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_->Undo(tomSuspend, NULL); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteEditViewWin::ScopedSuspendUndo::~ScopedSuspendUndo() { 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Resume Undo processing. 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_object_model_) 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_->Undo(tomResume, NULL); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompleteEditViewWin 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These are used to hook the CRichEditCtrl's calls to BeginPaint() and 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EndPaint() and provide a memory DC instead. See OnPaint(). 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHWND edit_hwnd = NULL; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPAINTSTRUCT paint_struct; 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Intercepted method for BeginPaint(). Must use __stdcall convention. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHDC WINAPI BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) { 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!edit_hwnd || (hWnd != edit_hwnd)) 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ::BeginPaint(hWnd, lpPaint); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *lpPaint = paint_struct; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return paint_struct.hdc; 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Intercepted method for EndPaint(). Must use __stdcall convention. 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBOOL WINAPI EndPaintIntercept(HWND hWnd, const PAINTSTRUCT* lpPaint) { 337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return (edit_hwnd && (hWnd == edit_hwnd)) || ::EndPaint(hWnd, lpPaint); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a lazily initialized property bag accessor for saving our state in a 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabContents. 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPropertyAccessor<AutocompleteEditState>* GetStateAccessor() { 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static PropertyAccessor<AutocompleteEditState> state; 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return &state; 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass PaintPatcher { 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen PaintPatcher(); 350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ~PaintPatcher(); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void RefPatch(); 353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void DerefPatch(); 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t refcount_; 357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick app::win::IATPatchFunction begin_paint_; 358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick app::win::IATPatchFunction end_paint_; 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(PaintPatcher); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenPaintPatcher::PaintPatcher() : refcount_(0) { 364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 366dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenPaintPatcher::~PaintPatcher() { 367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(0U, refcount_); 368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PaintPatcher::RefPatch() { 371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (refcount_ == 0) { 372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!begin_paint_.is_patched()); 373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!end_paint_.is_patched()); 374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen begin_paint_.Patch(L"riched20.dll", "user32.dll", "BeginPaint", 375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &BeginPaintIntercept); 376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen end_paint_.Patch(L"riched20.dll", "user32.dll", "EndPaint", 377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &EndPaintIntercept); 378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ++refcount_; 380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PaintPatcher::DerefPatch() { 383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(begin_paint_.is_patched()); 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(end_paint_.is_patched()); 385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen --refcount_; 386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (refcount_ == 0) { 387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen begin_paint_.Unpatch(); 388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen end_paint_.Unpatch(); 389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbase::LazyInstance<PaintPatcher> g_paint_patcher(base::LINKER_INITIALIZED); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// twips are a unit of type measurement, and RichEdit controls use them 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to set offsets. 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTwipsPerInch = 1440; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteEditViewWin::AutocompleteEditViewWin( 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Font& font, 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutocompleteEditController* controller, 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ToolbarModel* toolbar_model, 404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LocationBarView* parent_view, 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND hwnd, 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CommandUpdater* command_updater, 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool popup_window_mode, 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const views::View* location_bar) 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : model_(new AutocompleteEditModel(this, controller, profile)), 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup_view_(new AutocompletePopupContentsView(font, this, model_.get(), 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile, location_bar)), 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_(controller), 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_view_(parent_view), 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toolbar_model_(toolbar_model), 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command_updater_(command_updater), 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup_window_mode_(popup_window_mode), 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch force_hidden_(false), 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_click_(), 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_double_click_(false), 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double_click_time_(0), 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch can_discard_mousemove_(false), 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ignore_ime_messages_(false), 424201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch delete_at_end_pressed_(false), 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch font_(font), 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_(false), 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_drag_(false), 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initiated_drag_(false), 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_highlight_position_(-1), 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor( 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ToolbarModel::NONE, LocationBarView::BACKGROUND))), 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch security_level_(ToolbarModel::NONE), 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_(NULL) { 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Dummy call to a function exported by riched20.dll to ensure it sets up an 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // import dependency on the dll. 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateTextServices(NULL, NULL, NULL); 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_.cpMin = -1; 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_paint_patcher.Pointer()->RefPatch(); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Create(hwnd, 0, 0, 0, l10n_util::GetExtendedStyles()); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetReadOnly(popup_window_mode_); 4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetFont(font_.GetNativeFont()); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: Do not use SetWordBreakProcEx() here, that is no longer supported as 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of Rich Edit 2.0 onward. 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<LPARAM>(&WordBreakProc)); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the metrics for the font. 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HDC dc = ::GetDC(NULL); 4533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SelectObject(dc, font_.GetNativeFont()); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TEXTMETRIC tm = {0}; 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetTextMetrics(dc, &tm); 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const float kXHeightRatio = 0.7f; // The ratio of a font's x-height to its 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cap height. Sadly, Windows doesn't 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // provide a true value for a font's 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // x-height in its text metrics, so we 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // approximate. 4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick font_x_height_ = static_cast<int>((static_cast<float>(font_.GetBaseline() - 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tm.tmInternalLeading) * kXHeightRatio) + 0.5); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The distance from the top of the field to the desired baseline of the 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // rendered text. 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int kTextBaseline = popup_window_mode_ ? 15 : 18; 4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick font_y_adjustment_ = kTextBaseline - font_.GetBaseline(); 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the number of twips per pixel, which we need below to offset our text 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // by the desired number of pixels. 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const long kTwipsPerPixel = kTwipsPerInch / GetDeviceCaps(dc, LOGPIXELSY); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ::ReleaseDC(NULL, dc); 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the default character style -- adjust to our desired baseline. 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARFORMAT cf = {0}; 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cf.dwMask = CFM_OFFSET; 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cf.yOffset = -font_y_adjustment_ * kTwipsPerPixel; 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetDefaultCharFormat(cf); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetBackgroundColor(background_color_); 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // By default RichEdit has a drop target. Revoke it so that we can install our 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // own. Revoke takes care of deleting the existing one. 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RevokeDragDrop(m_hWnd); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Register our drop target. RichEdit appears to invoke RevokeDropTarget when 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // done so that we don't have to explicitly. 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!popup_window_mode_) { 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<EditDropTarget> drop_target = new EditDropTarget(this); 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RegisterDragDrop(m_hWnd, drop_target.get()); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteEditViewWin::~AutocompleteEditViewWin() { 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::current()->Notify( 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<AutocompleteEditViewWin>(this), 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::NoDetails()); 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Explicitly release the text object model now that we're done with it, and 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // before we free the library. If the library gets unloaded before this 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // released, it becomes garbage. 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_object_model_->Release(); 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We balance our reference count and unpatch when the last instance has 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // been destroyed. This prevents us from relying on the AtExit or static 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // destructor sequence to do our unpatching, which is generally fragile. 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_paint_patcher.Pointer()->DerefPatch(); 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenviews::View* AutocompleteEditViewWin::parent_view() const { 511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return parent_view_; 512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 513dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint AutocompleteEditViewWin::WidthOfTextAfterCursor() { 5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHARRANGE selection; 5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetSelection(selection); 5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const int start = std::max(0, static_cast<int>(selection.cpMax - 1)); 5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return WidthNeededToDisplay(GetText().substr(start)); 519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickgfx::Font AutocompleteEditViewWin::GetFont() { 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return font_; 5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SaveStateToTab(TabContents* tab) { 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(tab); 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const AutocompleteEditModel::State model_state( 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->GetStateForTabSwitch()); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE selection; 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(selection); 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetStateAccessor()->SetProperty(tab->property_bag(), 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutocompleteEditState( 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_state, 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch State(selection, saved_selection_for_focus_change_))); 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::Update( 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* tab_for_state_restoring) { 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool visibly_changed_permanent_text = 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->UpdatePermanentText(toolbar_model_->GetText()); 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ToolbarModel::SecurityLevel security_level = 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toolbar_model_->GetSecurityLevel(); 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool changed_security_level = (security_level != security_level_); 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bail early when no visible state will actually change (prevents an 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // unnecessary ScopedFreeze, and thus UpdateWindow()). 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!changed_security_level && !visibly_changed_permanent_text && 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !tab_for_state_restoring) 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update our local state as desired. We set security_level_ here so it will 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already be correct before we get to any RevertAll()s below and use it. 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch security_level_ = security_level; 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we're switching to a new tab, restore its state, if any. 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_for_state_restoring) { 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure we reset our own state first. The new tab may not have any 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // saved state, or it may not have had input in progress, in which case we 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // won't overwrite all our local state. 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RevertAll(); 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const AutocompleteEditState* state = GetStateAccessor()->GetProperty( 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_for_state_restoring->property_bag()); 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state) { 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->RestoreState(state->model_state); 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Restore user's selection. We do this after restoring the user_text 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // above so we're selecting in the correct string. 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(state->view_state.selection); 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_ = 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state->view_state.saved_selection_for_focus_change; 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (visibly_changed_permanent_text) { 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Not switching tabs, just updating the permanent text. (In the case where 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we _were_ switching tabs, the RevertAll() above already drew the new 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // permanent text.) 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tweak: if the edit was previously nonempty and had all the text selected, 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // select all the new text. This makes one particular case better: the 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // user clicks in the box to change it right before the permanent URL is 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // changed. Since the new URL is still fully selected, the user's typing 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will replace the edit contents as they'd intended. 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: The selection can be longer than the text length if the edit is in 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in rich text mode and the user has selected the "phantom newline" at the 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // end, so use ">=" instead of "==" to see if all the text is selected. In 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // theory we prevent this case from ever occurring, but this is still safe. 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(sel); 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool was_reversed = (sel.cpMin > sel.cpMax); 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool was_sel_all = (sel.cpMin != sel.cpMax) && 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IsSelectAllForRange(sel); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RevertAll(); 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (was_sel_all) 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectAll(was_reversed); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (changed_security_level) { 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only the security style changed, nothing else. Redraw our text using it. 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EmphasizeURLComponents(); 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OpenURL(const GURL& url, 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition disposition, 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition, 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& alternate_nav_url, 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t selected_line, 61372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& keyword) { 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we navigate, we first revert to the unedited state, then if necessary 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // synchronously change the permanent text to the new URL. If we don't freeze 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // here, the user could potentially see a flicker of the current URL before 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the new one reappears, which would look glitchy. 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->OpenURL(url, disposition, transition, alternate_nav_url, 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch selected_line, keyword); 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 AutocompleteEditViewWin::GetText() const { 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int len = GetTextLength() + 1; 62872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 str; 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindowText(WriteInto(&str, len), len); 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return str; 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::IsEditingOrEmpty() const { 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return model_->user_input_in_progress() || (GetTextLength() == 0); 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AutocompleteEditViewWin::GetIcon() const { 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IsEditingOrEmpty() ? 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toolbar_model_->GetIcon(); 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompleteEditViewWin::SetUserText(const string16& text) { 6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetUserText(text, text, true); 6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 64772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompleteEditViewWin::SetUserText(const string16& text, 64872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& display_text, 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool update_popup) { 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->SetUserText(text); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_.cpMin = -1; 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowTextAndCaretPos(display_text, display_text.length()); 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_popup) 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdatePopup(); 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextChanged(); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompleteEditViewWin::SetWindowTextAndCaretPos(const string16& text, 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t caret_pos) { 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowText(text.c_str()); 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PlaceCaretAt(caret_pos); 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SetForcedQuery() { 66672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16 current_text(GetText()); 6673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const size_t start = current_text.find_first_not_of(kWhitespaceWide); 66872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (start == string16::npos || (current_text[start] != '?')) 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetUserText(L"?"); 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetSelection(current_text.length(), start + 1); 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::IsSelectAll() { 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE selection; 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(selection); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IsSelectAllForRange(selection); 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 680201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool AutocompleteEditViewWin::DeleteAtEndPressed() { 681201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return delete_at_end_pressed_; 682201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 683201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 68472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompleteEditViewWin::GetSelectionBounds(string16::size_type* start, 68572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16::size_type* end) { 6863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHARRANGE selection; 6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetSel(selection); 6883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *start = static_cast<size_t>(selection.cpMin); 6893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *end = static_cast<size_t>(selection.cpMax); 6903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SelectAll(bool reversed) { 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (reversed) 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(GetTextLength(), 0); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(0, GetTextLength()); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::RevertAll() { 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClosePopup(); 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->Revert(); 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_.cpMin = -1; 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextChanged(); 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::UpdatePopup() { 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->SetInputInProgress(true); 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!model_->has_focus()) { 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we're in the midst of losing focus, don't rerun autocomplete. This 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can happen when losing focus causes the IME to cancel/finalize a 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // composition. We still want to note that user input is in progress, we 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // just don't want to do anything else. 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that in this case the ScopedFreeze above was unnecessary; however, 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we're inside the callstack of OnKillFocus(), which has already frozen the 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // edit, so this will never result in an unnecessary UpdateWindow() call. 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't inline autocomplete when: 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * The user is deleting text 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * The caret/selection isn't at the end of the text 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * The user has just pasted in something that replaced all the text 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * The user is trying to compose something in an IME 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(sel); 7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model_->StartAutocomplete(sel.cpMax != sel.cpMin, 73121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen (sel.cpMax < GetTextLength()) || IsImeComposing()); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::ClosePopup() { 735dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->StopAutocomplete(); 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SetFocus() { 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ::SetFocus(m_hWnd); 740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_->GetWidget()->NotifyAccessibilityEvent( 741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_, 742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ui::AccessibilityTypes::EVENT_FOCUS, 743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen false); 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIAccessible* AutocompleteEditViewWin::GetIAccessible() { 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!autocomplete_accessibility_) { 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CComObject<AutocompleteAccessibility>* accessibility = NULL; 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!SUCCEEDED(CComObject<AutocompleteAccessibility>::CreateInstance( 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &accessibility)) || !accessibility) 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Wrap the created object in a smart pointer so it won't leak. 754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<IAccessible> accessibility_comptr(accessibility); 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!SUCCEEDED(accessibility->Initialize(this))) 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy to the class smart pointer, and notify that an instance of 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IAccessible was allocated for m_hWnd. 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch autocomplete_accessibility_ = accessibility_comptr; 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotifyWinEvent(EVENT_OBJECT_CREATE, m_hWnd, OBJID_CLIENT, CHILDID_SELF); 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Detach to leave ref counting to the caller. 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return autocomplete_accessibility_.Detach(); 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SetDropHighlightPosition(int position) { 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drop_highlight_position_ != position) { 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RepaintDropHighlight(drop_highlight_position_); 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_highlight_position_ = position; 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RepaintDropHighlight(drop_highlight_position_); 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::MoveSelectedText(int new_position) { 77672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16 selected_text(GetSelectedText()); 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(sel); 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK((sel.cpMax != sel.cpMin) && (new_position >= 0) && 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (new_position <= GetTextLength())); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Nuke the selected text. 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceSel(L"", TRUE); 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // And insert it into the new location. 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_position >= sel.cpMin) 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_position -= (sel.cpMax - sel.cpMin); 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PlaceCaretAt(new_position); 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceSel(selected_text.c_str(), TRUE); 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::InsertText(int position, 79872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& text) { 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK((position >= 0) && (position <= GetTextLength())); 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(position, position); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceSel(text.c_str()); 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnTemporaryTextMaybeChanged( 80872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& display_text, 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool save_original_selection) { 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (save_original_selection) 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(original_selection_); 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set new text and cursor position. Sometimes this does extra work (e.g. 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the new text and the old text are identical), but it's only called 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the user manually changes the selected line in the popup, so that's 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not really a problem. Also, even when the text hasn't changed we'd want to 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // update the caret, because if the user had the cursor in the middle of the 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text and then arrowed to another entry with the same text, we'd still want 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to move the caret. 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowTextAndCaretPos(display_text, display_text.length()); 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextChanged(); 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::OnInlineAutocompleteTextMaybeChanged( 82672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& display_text, 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t user_text_length) { 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the text and selection. Because this can be called repeatedly while 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // typing, we've careful not to freeze the edit unless we really need to. 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Also, unlike in the temporary text case above, here we don't want to update 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the caret/selection unless we have to, since this might make the user's 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // caret position change without warning during typing. 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (display_text == GetText()) 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowText(display_text.c_str()); 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set a reversed selection to keep the caret in the same position, which 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // avoids scrolling the user's text. 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(static_cast<LONG>(display_text.length()), 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<LONG>(user_text_length)); 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextChanged(); 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnRevertTemporaryText() { 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(original_selection_); 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextChanged(); 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnBeforePossibleChange() { 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record our state. 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_before_change_ = GetText(); 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(sel_before_change_); 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::OnAfterPossibleChange() { 85872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OnAfterPossibleChangeInternal(false); 85972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 86072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 86172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool AutocompleteEditViewWin::OnAfterPossibleChangeInternal( 86272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool force_text_changed) { 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Prevent the user from selecting the "phantom newline" at the end of the 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // edit. If they try, we just silently move the end of the selection back to 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the end of the real text. 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE new_sel; 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(new_sel); 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int length = GetTextLength(); 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((new_sel.cpMin > length) || (new_sel.cpMax > length)) { 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_sel.cpMin > length) 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_sel.cpMin = length; 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_sel.cpMax > length) 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_sel.cpMax = length; 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(new_sel); 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 87672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const bool selection_differs = 87772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ((new_sel.cpMin != new_sel.cpMax) || 87872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (sel_before_change_.cpMin != sel_before_change_.cpMax)) && 87972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ((new_sel.cpMin != sel_before_change_.cpMin) || 88072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (new_sel.cpMax != sel_before_change_.cpMax)); 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if the text or selection have changed since OnBeforePossibleChange(). 88372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16 new_text(GetText()); 88472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const bool text_differs = (new_text != text_before_change_) || 88572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen force_text_changed; 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the user has deleted text, we don't allow inline autocomplete. Make 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sure to not flag cases like selecting part of the text and then pasting 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (or typing) the prefix of that selection. (We detect these by making 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sure the caret, which should be after any insertion, hasn't moved 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // forward of the old selection start.) 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool just_deleted_text = 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (text_before_change_.length() > new_text.length()) && 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (new_sel.cpMin <= std::min(sel_before_change_.cpMin, 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sel_before_change_.cpMax)); 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const bool something_changed = model_->OnAfterPossibleChange( 898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_text, new_sel.cpMin, new_sel.cpMax, selection_differs, 899ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen text_differs, just_deleted_text, !IsImeComposing()); 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (selection_differs) 9024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch controller_->OnSelectionBoundsChanged(); 9034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (something_changed && text_differs) 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextChanged(); 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 907731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (text_differs) { 908731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Note that a TEXT_CHANGED event implies that the cursor/selection 909731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // probably changed too, so we don't need to send both. 910ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_->GetWidget()->NotifyAccessibilityEvent( 911ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); 912731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (selection_differs) { 913731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Notify assistive technology that the cursor or selection changed. 914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_->GetWidget()->NotifyAccessibilityEvent( 915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_, ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true); 916201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else if (delete_at_end_pressed_) { 917dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->OnChanged(); 918731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 919731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return something_changed; 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::NativeView AutocompleteEditViewWin::GetNativeView() const { 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return m_hWnd; 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCommandUpdater* AutocompleteEditViewWin::GetCommandUpdater() { 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command_updater_; 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 931ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompleteEditViewWin::SetInstantSuggestion(const string16& suggestion, 932ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool animate_to_complete) { 933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_view_->SetInstantSuggestion(suggestion, animate_to_complete); 9343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 9353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint AutocompleteEditViewWin::TextWidth() const { 9373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return WidthNeededToDisplay(GetText()); 9383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 9393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 940dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstring16 AutocompleteEditViewWin::GetInstantSuggestion() const { 941dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return parent_view_->GetInstantSuggestion(); 942dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 943dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 94472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool AutocompleteEditViewWin::IsImeComposing() const { 94572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool ime_composing = false; 94672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HIMC context = ImmGetContext(m_hWnd); 94772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (context) { 94872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0); 94972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ImmReleaseContext(m_hWnd, context); 95072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 95172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ime_composing; 95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenviews::View* AutocompleteEditViewWin::AddToView(views::View* parent) { 95572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::NativeViewHost* host = new views::NativeViewHost; 95672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent->AddChildView(host); 95772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen host->set_focus_view(parent); 95872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen host->Attach(GetNativeView()); 95972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return host; 96072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 96172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 962dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint AutocompleteEditViewWin::OnPerformDrop( 963dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const views::DropTargetEvent& event) { 964dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return OnPerformDropImpl(event, false); 965dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 966dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 967dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint AutocompleteEditViewWin::OnPerformDropImpl( 968dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const views::DropTargetEvent& event, 969dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool in_drag) { 970dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const ui::OSExchangeData& data = event.data(); 971dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 972dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (data.HasURL()) { 973dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL url; 974dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 title; 975dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (data.GetURLAndTitle(&url, &title)) { 976dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetUserText(UTF8ToWide(url.spec())); 977dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model()->AcceptInput(CURRENT_TAB, true); 978dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return CopyOrLinkDragOperation(event.source_operations()); 979dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 980dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (data.HasString()) { 981dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int string_drop_position = drop_highlight_position(); 982dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 text; 983dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((string_drop_position != -1 || !in_drag) && data.GetString(&text)) { 984dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(string_drop_position == -1 || 985dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ((string_drop_position >= 0) && 986dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (string_drop_position <= GetTextLength()))); 987dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (in_drag) { 988dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (event.source_operations()== ui::DragDropTypes::DRAG_MOVE) 989dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MoveSelectedText(string_drop_position); 990dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else 991dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen InsertText(string_drop_position, text); 992dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 993dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen PasteAndGo(CollapseWhitespace(text, true)); 994dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 995dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return CopyOrLinkDragOperation(event.source_operations()); 996dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 997dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 998dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 999dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ui::DragDropTypes::DRAG_NONE; 1000dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1001dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 100272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompleteEditViewWin::PasteAndGo(const string16& text) { 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CanPasteAndGo(text)) 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->PasteAndGo(); 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::SkipDefaultKeyEventProcessing( 1008ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const views::KeyEvent& event) { 1009ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ui::KeyboardCode key = event.key_code(); 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't process ALT + numpad digit as accelerators, they are used for 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entering special characters. We do translate alt-home. 1012ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event.IsAltDown() && (key != ui::VKEY_HOME) && 1013ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::NativeTextfieldWin::IsNumPadDigit(key, 1014ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::IsExtendedKey(event))) 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Skip accelerators for key combinations omnibox wants to crack. This list 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should be synced with OnKeyDownOnlyWritable() (but for tab which is dealt 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with above in LocationBarView::SkipDefaultKeyEventProcessing). 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We cannot return true for all keys because we still need to handle some 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // accelerators (e.g., F5 for reload the page should work even when the 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Omnibox gets focused). 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (key) { 102572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_ESCAPE: { 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return model_->OnEscapeKeyPressed(); 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_RETURN: 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_UP: 103472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_DOWN: 1035ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return !event.IsAltDown(); 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_DELETE: 103872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_INSERT: 1039ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return !event.IsAltDown() && event.IsShiftDown() && 1040ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !event.IsControlDown(); 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_X: 104372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_V: 1044ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return !event.IsAltDown() && event.IsControlDown(); 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_BACK: 104772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ui::VKEY_OEM_PLUS: 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::HandleExternalMsg(UINT msg, 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags, 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& screen_point) { 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (msg == WM_CAPTURECHANGED) { 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(msg, 0, NULL); 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CPoint client_point(screen_point); 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ::MapWindowPoints(NULL, m_hWnd, &client_point, 1); 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(msg, flags, MAKELPARAM(client_point.x, client_point.y)); 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::IsCommandIdChecked(int command_id) const { 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::IsCommandIdEnabled(int command_id) const { 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (command_id) { 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_UNDO: return !!CanUndo(); 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDC_CUT: return !!CanCut(); 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDC_COPY: return !!CanCopy(); 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDC_PASTE: return !!CanPaste(); 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_PASTE_AND_GO: return CanPasteAndGo(GetClipboardText()); 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_SELECT_ALL: return !!CanSelectAll(); 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_EDIT_SEARCH_ENGINES: 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command_updater_->IsCommandEnabled(IDC_EDIT_SEARCH_ENGINES); 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::GetAcceleratorForCommandId( 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int command_id, 109072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::Accelerator* accelerator) { 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return parent_view_->GetWidget()->GetAccelerator(command_id, accelerator); 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool AutocompleteEditViewWin::IsItemForCommandIdDynamic(int command_id) const { 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No need to change the default IDS_PASTE_AND_GO label unless this is a 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // search. 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return command_id == IDS_PASTE_AND_GO; 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 AutocompleteEditViewWin::GetLabelForCommandId( 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int command_id) const { 1102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(IDS_PASTE_AND_GO, command_id); 11033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return l10n_util::GetStringUTF16(model_->is_paste_and_search() ? 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO); 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::ExecuteCommand(int command_id) { 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (command_id == IDS_PASTE_AND_GO) { 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This case is separate from the switch() below since we don't want to wrap 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it in OnBefore/AfterPossibleChange() calls. 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->PasteAndGo(); 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (command_id) { 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_UNDO: 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Undo(); 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDC_CUT: 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cut(); 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDC_COPY: 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Copy(); 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDC_PASTE: 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Paste(); 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_SELECT_ALL: 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectAll(false); 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case IDS_EDIT_SEARCH_ENGINES: 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command_updater_->ExecuteCommand(IDC_EDIT_SEARCH_ENGINES); 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CALLBACK AutocompleteEditViewWin::WordBreakProc(LPTSTR edit_text, 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int current_pos, 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_bytes, 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int action) { 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(pkasting): http://b/1111308 We should let other people, like ICU and 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GURL, do the work for us here instead of writing all this ourselves. 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sadly, even though the MSDN docs claim that the third parameter here is a 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // number of characters, they lie. It's a number of bytes. 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int length = num_bytes / sizeof(wchar_t); 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // With no clear guidance from the MSDN docs on how to handle "not found" in 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the "find the nearest xxx..." cases below, I cap the return values at 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // [0, length]. Since one of these (0) is also a valid position, the return 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // values are thus ambiguous :( 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (action) { 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find nearest character before current position that begins a word. 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_LEFT: 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_MOVEWORDLEFT: { 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_pos < 2) { 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Either current_pos == 0, so we have a "not found" case and return 0, 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // or current_pos == 1, and the only character before this position is 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // at 0. 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look for a delimiter before the previous character; the previous word 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // starts immediately after. (If we looked for a delimiter before the 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current character, we could stop on the immediate prior character, 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // which would mean we'd return current_pos -- which isn't "before the 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current position".) 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int prev_delim = 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WordBreakProc(edit_text, current_pos - 1, num_bytes, WB_LEFTBREAK); 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((prev_delim == 0) && 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !WordBreakProc(edit_text, 0, num_bytes, WB_ISDELIMITER)) { 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Got back 0, but position 0 isn't a delimiter. This was a "not 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // found" 0, so return one of our own. 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return prev_delim + 1; 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find nearest character after current position that begins a word. 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_RIGHT: 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_MOVEWORDRIGHT: { 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (WordBreakProc(edit_text, current_pos, num_bytes, WB_ISDELIMITER)) { 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The current character is a delimiter, so the next character starts 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a new word. Done. 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return current_pos + 1; 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look for a delimiter after the current character; the next word starts 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // immediately after. 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int next_delim = 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WordBreakProc(edit_text, current_pos, num_bytes, WB_RIGHTBREAK); 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (next_delim == length) { 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Didn't find a delimiter. Return length to signal "not found". 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return length; 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return next_delim + 1; 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Determine if the current character delimits words. 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_ISDELIMITER: 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !!(WordBreakProc(edit_text, current_pos, num_bytes, WB_CLASSIFY) & 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WBF_BREAKLINE); 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return the classification of the current character. 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_CLASSIFY: 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsWhitespace(edit_text[current_pos])) { 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Whitespace normally breaks words, but the MSDN docs say that we must 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not break on the CRs in a "CR, LF" or a "CR, CR, LF" sequence. Just 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // check for an arbitrarily long sequence of CRs followed by LF and 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // report "not a delimiter" for the current CR in that case. 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while ((current_pos < (length - 1)) && 1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (edit_text[current_pos] == 0x13)) { 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (edit_text[++current_pos] == 0x10) 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return WBF_ISWHITE; 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return WBF_BREAKLINE | WBF_ISWHITE; 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Punctuation normally breaks words, but the first two characters in 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // "://" (end of scheme) should not be breaks, so that "http://" will be 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // treated as one word. 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ispunct(edit_text[current_pos], std::locale()) && 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !SchemeEnd(edit_text, current_pos, length) && 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !SchemeEnd(edit_text, current_pos - 1, length)) 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return WBF_BREAKLINE; 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Normal character, no flags. 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Finds nearest delimiter before current position. 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_LEFTBREAK: 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = current_pos - 1; i >= 0; --i) { 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (WordBreakProc(edit_text, i, num_bytes, WB_ISDELIMITER)) 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i; 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Finds nearest delimiter after current position. 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case WB_RIGHTBREAK: 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = current_pos + 1; i < length; ++i) { 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (WordBreakProc(edit_text, i, num_bytes, WB_ISDELIMITER)) 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i; 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return length; 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::SchemeEnd(LPTSTR edit_text, 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int current_pos, 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int length) { 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (current_pos >= 0) && 1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((length - current_pos) > 2) && 1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (edit_text[current_pos] == ':') && 1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (edit_text[current_pos + 1] == '/') && 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (edit_text[current_pos + 2] == '/'); 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't let alt-enter beep. Not sure this is necessary, as the standard 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // alt-enter will hit DiscardWMSysChar() and get thrown away, and 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ctrl-alt-enter doesn't seem to reach here for some reason? At least not on 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // my system... still, this is harmless and maybe necessary in other locales. 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ch == VK_RETURN && (flags & KF_ALTDOWN)) 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Escape is processed in OnKeyDown. Don't let any WM_CHAR messages propagate 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as we don't want the RichEdit to do anything funky. 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ch == VK_ESCAPE && !(flags & KF_ALTDOWN)) 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ch == VK_TAB) { 1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't add tabs to the input. 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleKeystroke(GetCurrentMessage()->message, ch, repeat_count, flags); 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnContextMenu(HWND window, const CPoint& point) { 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildContextMenu(); 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (point.x == -1 || point.y == -1) { 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch POINT p; 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetCaretPos(&p); 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MapWindowPoints(HWND_DESKTOP, &p, 1); 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_->RunContextMenuAt(gfx::Point(p)); 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_->RunContextMenuAt(gfx::Point(point)); 1308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnCopy() { 131272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 text(GetSelectedText()); 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text.empty()) 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url; 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool write_url = false; 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(sel); 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetSel() doesn't preserve selection direction, so sel.cpMin will always be 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the smaller value. 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->AdjustTextForCopy(sel.cpMin, IsSelectAll(), &text, &url, &write_url); 132372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ScopedClipboardWriter scw(g_browser_process->clipboard()); 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scw.WriteText(text); 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (write_url) { 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scw.WriteBookmark(text, url.spec()); 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scw.WriteHyperlink(EscapeForHTML(text), url.spec()); 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnCut() { 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnCopy(); 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This replace selection will have no effect (even on the undo stack) if the 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current selection is empty. 1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceSel(L"", true); 1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1339c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AutocompleteEditViewWin::OnGetObject(UINT uMsg, 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam) { 1342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Accessibility readers will send an OBJID_CLIENT message. 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (lparam == OBJID_CLIENT) { 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Re-attach for internal re-usage of accessibility pointer. 1345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch autocomplete_accessibility_.Attach(GetIAccessible()); 1346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (autocomplete_accessibility_) { 1348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return LresultFromObject(IID_IAccessible, wparam, 1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch autocomplete_accessibility_); 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1355c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AutocompleteEditViewWin::OnImeComposition(UINT message, 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam) { 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ignore_ime_messages_) { 1359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This message was sent while we're in the middle of meddling with the 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // underlying edit control. If we handle it below, OnAfterPossibleChange() 1361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can get bogus text for the edit, and rerun autocomplete, destructively 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // modifying the result set that we're in the midst of using. For example, 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if SetWindowTextAndCaretPos() was called due to the user clicking an 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entry in the popup, we're in the middle of executing SetSelectedLine(), 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and changing the results can cause checkfailures. 1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DefWindowProc(message, wparam, lparam); 1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT result = DefWindowProc(message, wparam, lparam); 137272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Force an IME composition confirmation operation to trigger the text_changed 137372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // code in OnAfterPossibleChange(), even if identical contents are confirmed, 137472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // to make sure the model can update its internal states correctly. 137572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnAfterPossibleChangeInternal((lparam & GCS_RESULTSTR) != 0); 1376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 1377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnKeyDown(TCHAR key, 1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT repeat_count, 1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags) { 1382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch delete_at_end_pressed_ = false; 1383201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (OnKeyDownAllModes(key, repeat_count, flags)) 1385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 1386731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1387731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Make sure that we handle system key events like Alt-F4. 1388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (popup_window_mode_) { 1389731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DefWindowProc(GetCurrentMessage()->message, key, MAKELPARAM(repeat_count, 1390731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick flags)); 1391731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 1392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1393731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1394731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (OnKeyDownOnlyWritable(key, repeat_count, flags)) 1395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CRichEditCtrl changes its text on WM_KEYDOWN instead of WM_CHAR for many 1398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // different keys (backspace, ctrl-v, ...), so we call this in both cases. 1399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleKeystroke(GetCurrentMessage()->message, key, repeat_count, flags); 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnKeyUp(TCHAR key, 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT repeat_count, 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags) { 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (key == VK_CONTROL) 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->OnControlKeyChanged(false); 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On systems with RTL input languages, ctrl+shift toggles the reading order 1409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (depending on which shift key is pressed). But by default the CRichEditCtrl 1410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only changes the current reading order, and as soon as the user deletes all 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the text, or we call SetWindowText(), it reverts to the "default" order. 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To work around this, if the user hits ctrl+shift, we pass it to 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DefWindowProc() while the edit is empty, which toggles the default reading 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // order; then we restore the user's input. 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(flags & KF_ALTDOWN) && 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (((key == VK_CONTROL) && (GetKeyState(VK_SHIFT) < 0)) || 1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((key == VK_SHIFT) && (GetKeyState(VK_CONTROL) < 0)))) { 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 saved_text(GetText()); 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE saved_sel; 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(saved_sel); 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowText(L""); 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_KEYUP, key, MAKELPARAM(repeat_count, flags)); 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowText(saved_text.c_str()); 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(saved_sel); 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnKillFocus(HWND focus_wnd) { 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (m_hWnd == focus_wnd) { 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Focus isn't actually leaving. 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This must be invoked before ClosePopup. 1444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->OnWillKillFocus(focus_wnd); 14453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close the popup. 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClosePopup(); 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the user's existing selection to restore it later. 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(saved_selection_for_focus_change_); 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tell the model to reset itself. 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->OnKillFocus(); 1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Let the CRichEditCtrl do its default handling. This will complete any 1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in-progress IME composition. We must do this after setting has_focus_ to 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // false so that UpdatePopup() will know not to rerun autocomplete. 1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_KILLFOCUS, reinterpret_cast<WPARAM>(focus_wnd), 0); 1460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cancel any user selection and scroll the text back to the beginning of the 1462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URL. We have to do this after calling DefWindowProc() because otherwise 1463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // an in-progress IME composition will be completed at the new caret position, 1464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // resulting in the string jumping unexpectedly to the front of the edit. 1465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PlaceCaretAt(0); 1466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) { 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the double click info for later triple-click detection. 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_double_click_ = true; 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double_click_point_ = point; 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double_click_time_ = GetCurrentMessage()->time; 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = false; 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Modifying the selection counts as accepting any inline autocompletion, so 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // track "changes" made by clicking the mouse button. 1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_LBUTTONDBLCLK, keys, 1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y)); 1481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gaining_focus_.reset(); // See NOTE in OnMouseActivate(). 1484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnLButtonDown(UINT keys, const CPoint& point) { 1487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TrackMousePosition(kLeft, point); 1488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (gaining_focus_.get()) { 1489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When Chrome was already the activated app, we haven't reached 1490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnSetFocus() yet. When we get there, don't restore the saved selection, 1491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // since it will just screw up the user's interaction with the edit. 1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_.cpMin = -1; 1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Crazy hack: In this particular case, the CRichEditCtrl seems to have an 1495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // internal flag that discards the next WM_LBUTTONDOWN without processing 1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it, so that clicks on the edit when its owning app is not activated are 1497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // eaten rather than processed (despite whatever the return value of 1498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DefWindowProc(WM_MOUSEACTIVATE, ...) may say). This behavior is 1499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // confusing and we want the click to be treated normally. So, to reset the 1500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CRichEditCtrl's internal flag, we pass it an extra WM_LBUTTONDOWN here 1501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (as well as a matching WM_LBUTTONUP, just in case we'd be confusing some 1502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // kind of state tracking otherwise). 1503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_LBUTTONDOWN, keys, MAKELPARAM(point.x, point.y)); 1504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_LBUTTONUP, keys, MAKELPARAM(point.x, point.y)); 1505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check for triple click, then reset tracker. Should be safe to subtract 1508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // double_click_time_ from the current message's time even if the timer has 1509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // wrapped in between. 1510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool is_triple_click = tracking_double_click_ && 151172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::NativeTextfieldWin::IsDoubleClick(double_click_point_, point, 151272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetCurrentMessage()->time - double_click_time_); 1513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_double_click_ = false; 1514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!gaining_focus_.get() && !is_triple_click) 1516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnPossibleDrag(point); 1517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Modifying the selection counts as accepting any inline autocompletion, so 1520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // track "changes" made by clicking the mouse button. 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_LBUTTONDOWN, keys, 1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(ClipXCoordToVisibleText(point.x, is_triple_click), 1525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch point.y)); 1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gaining_focus_.reset(); 1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnLButtonUp(UINT keys, const CPoint& point) { 1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // default processing should happen first so we can see the result of the 1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // selection 1534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_LBUTTONUP, keys, 1536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y)); 1537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectAllIfNecessary(kLeft, point); 1539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_click_[kLeft] = false; 1541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = false; 1543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnMButtonDblClk(UINT /*keys*/, 1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& /*point*/) { 1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gaining_focus_.reset(); // See NOTE in OnMouseActivate(). 1548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // By default, the edit responds to middle-clicks by capturing the mouse and 1550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ignoring all subsequent events until it receives another click (of any of 1551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the left, middle, or right buttons). This bizarre behavior is not only 1552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // useless but can cause the UI to appear unresponsive if a user accidentally 1553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // middle-clicks the edit (instead of a tab above it), so we purposefully eat 1554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this message (instead of calling SetMsgHandled(false)) to avoid triggering 1555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this. 1556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnMButtonDown(UINT /*keys*/, 1559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& /*point*/) { 1560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_double_click_ = false; 1561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See note in OnMButtonDblClk above. 1563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnMButtonUp(UINT /*keys*/, 1566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& /*point*/) { 1567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = false; 1568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See note in OnMButtonDblClk above. 1570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1572c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AutocompleteEditViewWin::OnMouseActivate(HWND window, 1573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT hit_test, 1574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT mouse_message) { 1575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, give other handlers a chance to handle the message to see if we are 1576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // actually going to activate and gain focus. 1577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT result = DefWindowProc(WM_MOUSEACTIVATE, 1578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<WPARAM>(window), 1579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(hit_test, mouse_message)); 1580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check if we're getting focus from a click. We have to do this here rather 1581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // than in OnXButtonDown() since in many scenarios OnSetFocus() will be 1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // reached before OnXButtonDown(), preventing us from detecting this properly 1583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // there. Also in those cases, we need to already know in OnSetFocus() that 1584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we should not restore the saved selection. 1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!model_->has_focus() && 1586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((mouse_message == WM_LBUTTONDOWN || mouse_message == WM_RBUTTONDOWN)) && 1587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (result == MA_ACTIVATE)) { 1588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!gaining_focus_.get()); 1589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gaining_focus_.reset(new ScopedFreeze(this, GetTextObjectModel())); 1590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: Despite |mouse_message| being WM_XBUTTONDOWN here, we're not 1591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // guaranteed to call OnXButtonDown() later! Specifically, if this is the 1592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // second click of a double click, we'll reach here but later call 1593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnXButtonDblClk(). Make sure |gaining_focus_| gets reset both places, 1594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // or we'll have visual glitchiness and then DCHECK failures. 1595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't restore saved selection, it will just screw up our interaction 1597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with this edit. 1598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_.cpMin = -1; 1599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 1601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnMouseMove(UINT keys, const CPoint& point) { 1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (possible_drag_) { 1605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartDragIfNecessary(point); 1606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't fall through to default mouse handling, otherwise a second 1607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // drag session may start. 1608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (tracking_click_[kLeft] && !IsDrag(click_point_[kLeft], point)) 1612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_click_[kLeft] = false; 1615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return quickly if this can't change the selection/cursor, so we don't 1617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // create a ScopedFreeze (and thus do an UpdateWindow()) on every 1618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WM_MOUSEMOVE. 1619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(keys & MK_LBUTTON)) { 1620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_MOUSEMOVE, keys, MAKELPARAM(point.x, point.y)); 1621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clamp the selection to the visible text so the user can't drag to select 1625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the "phantom newline". In theory we could achieve this by clipping the X 1626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // coordinate, but in practice the edit seems to behave nondeterministically 1627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with similar sequences of clipped input coordinates fed to it. Maybe it's 1628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // reading the mouse cursor position directly? 1629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This solution has a minor visual flaw, however: if there's a visible cursor 1631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // at the edge of the text (only true when there's no selection), dragging the 1632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // mouse around outside that edge repaints the cursor on every WM_MOUSEMOVE 1633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // instead of allowing it to blink normally. To fix this, we special-case 1634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this exact case and discard the WM_MOUSEMOVE messages instead of passing 1635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them along. 1636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // But even this solution has a flaw! (Argh.) In the case where the user has 1638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a selection that starts at the edge of the edit, and proceeds to the middle 1639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the edit, and the user is dragging back past the start edge to remove 1640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the selection, there's a redraw problem where the change between having the 1641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // last few bits of text still selected and having nothing selected can be 1642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // slow to repaint (which feels noticeably strange). This occurs if you only 1643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // let the edit receive a single WM_MOUSEMOVE past the edge of the text. I 1644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // think on each WM_MOUSEMOVE the edit is repainting its previous state, then 1645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // updating its internal variables to the new state but not repainting. To 1646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fix this, we allow one more WM_MOUSEMOVE through after the selection has 1647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // supposedly been shrunk to nothing; this makes the edit redraw the selection 1648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // quickly so it feels smooth. 1649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE selection; 1650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(selection); 1651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool possibly_can_discard_mousemove = 1652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (selection.cpMin == selection.cpMax) && 1653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (((selection.cpMin == 0) && 1654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (ClipXCoordToVisibleText(point.x, false) > point.x)) || 1655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((selection.cpMin == GetTextLength()) && 1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (ClipXCoordToVisibleText(point.x, false) < point.x))); 1657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!can_discard_mousemove_ || !possibly_can_discard_mousemove) { 1658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch can_discard_mousemove_ = possibly_can_discard_mousemove; 1659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force the Y coordinate to the center of the clip rect. The edit 1662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // behaves strangely when the cursor is dragged vertically: if the cursor 1663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is in the middle of the text, drags inside the clip rect do nothing, 1664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and drags outside the clip rect act as if the cursor jumped to the 1665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // left edge of the text. When the cursor is at the right edge, drags of 1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // just a few pixels vertically end up selecting the "phantom newline"... 1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sometimes. 1668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RECT r; 1669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetRect(&r); 1670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_MOUSEMOVE, keys, 1671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(point.x, (r.bottom - r.top) / 2)); 1672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnPaint(HDC bogus_hdc) { 1677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to paint over the top of the edit. If we simply let the edit do 1678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // its default painting, then do ours into the window DC, the screen is 1679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // updated in between and we can get flicker. To avoid this, we force the 1680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // edit to paint into a memory DC, which we also paint onto, then blit the 1681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // whole thing to the screen. 1682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't paint if not necessary. 1684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CRect paint_clip_rect; 1685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetUpdateRect(&paint_clip_rect, true)) 1686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Begin painting, and create a memory DC for the edit to paint into. 1689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CPaintDC paint_dc(m_hWnd); 1690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CDC memory_dc(CreateCompatibleDC(paint_dc)); 1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CRect rect; 1692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetClientRect(&rect); 1693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: This next call uses |paint_dc| instead of |memory_dc| because 1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |memory_dc| contains a 1x1 monochrome bitmap by default, which will cause 1695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |memory_bitmap| to be monochrome, which isn't what we want. 1696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CBitmap memory_bitmap(CreateCompatibleBitmap(paint_dc, rect.Width(), 1697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rect.Height())); 1698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HBITMAP old_bitmap = memory_dc.SelectBitmap(memory_bitmap); 1699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tell our intercept functions to supply our memory DC to the edit when it 1701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tries to call BeginPaint(). 1702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The sane way to do this would be to use WM_PRINTCLIENT to ask the edit to 1704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // paint into our desired DC. Unfortunately, the Rich Edit 3.0 that ships 1705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with Windows 2000/XP/Vista doesn't handle WM_PRINTCLIENT correctly; it 1706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // treats it just like WM_PAINT and calls BeginPaint(), ignoring our provided 1707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DC. The Rich Edit 6.0 that ships with Office 2007 handles this better, but 1708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // has other issues, and we can't redistribute that DLL anyway. So instead, 1709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we use this scary hack. 1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: It's possible to get nested paint calls (!) (try setting the 1712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // permanent URL to something longer than the edit width, then selecting the 1713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // contents of the edit, typing a character, and hitting <esc>), so we can't 1714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DCHECK(!edit_hwnd_) here. Instead, just save off the old HWND, which most 1715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the time will be NULL. 1716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND old_edit_hwnd = edit_hwnd; 1717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_hwnd = m_hWnd; 1718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint_struct = paint_dc.m_ps; 1719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint_struct.hdc = memory_dc; 1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_PAINT, reinterpret_cast<WPARAM>(bogus_hdc), 0); 1721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make the selection look better. 1723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EraseTopOfSelection(&memory_dc, rect, paint_clip_rect); 1724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw a slash through the scheme if this is insecure. 1726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (insecure_scheme_component_.is_nonempty()) 1727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DrawSlashForInsecureScheme(memory_dc, rect, paint_clip_rect); 1728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the drop highlight. 1730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drop_highlight_position_ != -1) 1731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DrawDropHighlight(memory_dc, rect, paint_clip_rect); 1732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Blit the memory DC to the actual paint DC and clean up. 1734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BitBlt(paint_dc, rect.left, rect.top, rect.Width(), rect.Height(), memory_dc, 1735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rect.left, rect.top, SRCCOPY); 1736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memory_dc.SelectBitmap(old_bitmap); 1737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch edit_hwnd = old_edit_hwnd; 1738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnPaste() { 1741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Replace the selection if we have something to paste. 174272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16 text(GetClipboardText()); 1743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text.empty()) { 174472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Record this paste, so we can do different behavior. 174572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen model_->on_paste(); 1746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force a Paste operation to trigger the text_changed code in 1747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnAfterPossibleChange(), even if identical contents are pasted into the 1748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text box. 1749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_before_change_.clear(); 1750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceSel(text.c_str(), true); 1751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnRButtonDblClk(UINT /*keys*/, 1755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& /*point*/) { 1756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gaining_focus_.reset(); // See NOTE in OnMouseActivate(). 1757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnRButtonDown(UINT /*keys*/, 1761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& point) { 1762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TrackMousePosition(kRight, point); 1763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_double_click_ = false; 1764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = false; 1765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gaining_focus_.reset(); 1766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnRButtonUp(UINT /*keys*/, const CPoint& point) { 1770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectAllIfNecessary(kRight, point); 1771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_click_[kRight] = false; 1772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnSetFocus(HWND focus_wnd) { 1776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::FocusManager* focus_manager = parent_view_->GetFocusManager(); 1777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (focus_manager) { 1778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify the FocusManager that the focused view is now the location bar 1779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (our parent view). 1780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch focus_manager->SetFocusedView(parent_view_); 1781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->OnSetFocus(GetKeyState(VK_CONTROL) < 0); 1786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Restore saved selection if available. 1788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (saved_selection_for_focus_change_.cpMin != -1) { 1789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(saved_selection_for_focus_change_); 1790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch saved_selection_for_focus_change_.cpMin = -1; 1791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1796c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AutocompleteEditViewWin::OnSetText(const wchar_t* text) { 1797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignore all IME messages while we process this WM_SETTEXT message. 1798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When SetWindowText() is called while an IME is composing text, the IME 1799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // calls SendMessage() to send a WM_IME_COMPOSITION message. When we receive 1800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this WM_IME_COMPOSITION message, we update the omnibox and may call 1801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SetWindowText() again. To stop this recursive message-handler call, we 1802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // stop updating the omnibox while we process a WM_SETTEXT message. 1803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We wouldn't need to do this update anyway, because either we're in the 1804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // middle of updating the omnibox already or the caller of SetWindowText() 1805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is going to update the omnibox next. 1806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutoReset<bool> auto_reset_ignore_ime_messages(&ignore_ime_messages_, true); 1807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DefWindowProc(WM_SETTEXT, 0, reinterpret_cast<LPARAM>(text)); 1808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnSysChar(TCHAR ch, 1811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT repeat_count, 1812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags) { 1813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Nearly all alt-<xxx> combos result in beeping rather than doing something 1814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // useful, so we discard most. Exceptions: 1815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * ctrl-alt-<xxx>, which is sometimes important, generates WM_CHAR instead 1816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of WM_SYSCHAR, so it doesn't need to be handled here. 1817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * alt-space gets translated by the default WM_SYSCHAR handler to a 1818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WM_SYSCOMMAND to open the application context menu, so we need to allow 1819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it through. 1820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ch == VK_SPACE) 1821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnWindowPosChanging(WINDOWPOS* window_pos) { 1825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (force_hidden_) 1826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_pos->flags &= ~SWP_SHOWWINDOW; 1827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(true); 1828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1830c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBOOL AutocompleteEditViewWin::OnMouseWheel(UINT flags, 1831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch short delta, 1832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CPoint point) { 1833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Forward the mouse-wheel message to the window under the mouse. 1834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!views::RerouteMouseWheel(m_hWnd, MAKEWPARAM(flags, delta), 1835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(point.x, point.y))) 1836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMsgHandled(false); 1837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::HandleKeystroke(UINT message, 1841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TCHAR key, 1842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT repeat_count, 1843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags) { 1844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (key == ui::VKEY_HOME || key == ui::VKEY_END) { 1848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DefWindowProc() might reset the keyboard layout when it receives a 1849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // keydown event for VKEY_HOME or VKEY_END. When the window was created 1850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with WS_EX_LAYOUTRTL and the current keyboard layout is not a RTL one, 1851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if the input text is pure LTR text, the layout changes to the first RTL 1852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // keyboard layout in keyboard layout queue; if the input text is 1853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bidirectional text, the layout changes to the keyboard layout of the 1854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first RTL character in input text. When the window was created without 1855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WS_EX_LAYOUTRTL and the current keyboard layout is not a LTR one, if the 1856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // input text is pure RTL text, the layout changes to English; if the input 1857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text is bidirectional text, the layout changes to the keyboard layout of 1858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the first LTR character in input text. Such keyboard layout change 1859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // behavior is surprising and inconsistent with keyboard behavior 1860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // elsewhere, so reset the layout in this case. 1861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HKL layout = GetKeyboardLayout(0); 1862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(message, key, MAKELPARAM(repeat_count, flags)); 1863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ActivateKeyboardLayout(layout, KLF_REORDER); 1864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(message, key, MAKELPARAM(repeat_count, flags)); 1866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CRichEditCtrl automatically turns on IMF_AUTOKEYBOARD when the user 1869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // inputs an RTL character, making it difficult for the user to control 1870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // what language is set as they type. Force this off to make the edit's 1871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // behavior more stable. 1872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int lang_options = SendMessage(EM_GETLANGOPTIONS, 0, 0); 1873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (lang_options & IMF_AUTOKEYBOARD) 1874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendMessage(EM_SETLANGOPTIONS, 0, lang_options & ~IMF_AUTOKEYBOARD); 1875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::OnKeyDownOnlyWritable(TCHAR key, 1880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT repeat_count, 1881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags) { 1882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: Annoyingly, ctrl-alt-<key> generates WM_KEYDOWN rather than 1883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WM_SYSKEYDOWN, so we need to check (flags & KF_ALTDOWN) in various places 1884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in this function even with a WM_SYSKEYDOWN handler. 1885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If adding a new key that could possibly be an accelerator then you'll need 18873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // to update LocationBarView::SkipDefaultKeyEventProcessing() as well. 1888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count = repeat_count; 1889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (key) { 18903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case VK_RIGHT: 18913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(sky): figure out RTL. 18923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (base::i18n::IsRTL()) 18933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 18943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick { 18953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHARRANGE selection; 18963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetSel(selection); 18973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return (selection.cpMin == selection.cpMax) && 18983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick (selection.cpMin == GetTextLength()) && 1899dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->CommitSuggestedText(true); 19003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 19013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_RETURN: 1903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->AcceptInput((flags & KF_ALTDOWN) ? 1904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NEW_FOREGROUND_TAB : CURRENT_TAB, false); 1905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_PRIOR: 1908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_NEXT: 1909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch count = model_->result().size(); 1910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // FALL THROUGH 1911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_UP: 1912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_DOWN: 1913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignore alt + numpad, but treat alt + (non-numpad) like (non-numpad). 1914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((flags & KF_ALTDOWN) && !(flags & KF_EXTENDED)) 1915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->OnUpOrDownKeyPressed(((key == VK_PRIOR) || (key == VK_UP)) ? 1918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch -count : count); 1919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Hijacking Editing Commands 1922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We hijack the keyboard short-cuts for Cut, Copy, and Paste here so that 1924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // they go through our clipboard routines. This allows us to be smarter 1925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // about how we interact with the clipboard and avoid bugs in the 1926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CRichEditCtrl. If we didn't hijack here, the edit control would handle 1927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // these internally with sending the WM_CUT, WM_COPY, or WM_PASTE messages. 1928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cut: Shift-Delete and Ctrl-x are treated as cut. Ctrl-Shift-Delete and 1930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ctrl-Shift-x are not treated as cut even though the underlying 1931201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // CRichTextEdit would treat them as such. Also note that we bring 1932201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // up 'clear browsing data' on control-shift-delete. 1933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy: Ctrl-Insert and Ctrl-c is treated as copy. Shift-Ctrl-c is not. 1934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (This is handled in OnKeyDownAllModes().) 1935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paste: Shift-Insert and Ctrl-v are treated as paste. Ctrl-Shift-Insert 1936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and Ctrl-Shift-v are not. 1937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This behavior matches most, but not all Windows programs, and largely 1939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // conforms to what users expect. 1940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_DELETE: 1942201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (flags & KF_ALTDOWN) 1943201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return false; 1944201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (GetKeyState(VK_SHIFT) >= 0) { 1945201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (GetKeyState(VK_CONTROL) >= 0) { 1946201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch CHARRANGE selection; 1947201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch GetSel(selection); 1948201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch delete_at_end_pressed_ = ((selection.cpMin == selection.cpMax) && 1949201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch (selection.cpMin == GetTextLength())); 1950201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1952201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 1953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetKeyState(VK_CONTROL) >= 0) { 1954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cut text if possible. 1955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE selection; 1956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(selection); 1957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selection.cpMin != selection.cpMax) { 1958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cut(); 1961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1963dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (model_->popup_model()->IsOpen()) { 1964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is a bit overloaded, but we hijack Shift-Delete in this 1965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case to delete the current item from the pop-up. We prefer 1966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cutting to this when possible since that's the behavior more 1967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // people expect from Shift-Delete, and it's more commonly useful. 1968dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->popup_model()->TryDeletingCurrentItem(); 1969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'X': 1975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((flags & KF_ALTDOWN) || (GetKeyState(VK_CONTROL) >= 0)) 1976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetKeyState(VK_SHIFT) >= 0) { 1978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cut(); 1981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 1982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_INSERT: 1986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignore insert by itself, so we don't turn overtype mode on/off. 1987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(flags & KF_ALTDOWN) && (GetKeyState(VK_SHIFT) >= 0) && 1988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (GetKeyState(VK_CONTROL) >= 0)) 1989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // FALL THROUGH 1991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'V': 1992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((flags & KF_ALTDOWN) || 1993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (GetKeyState((key == 'V') ? VK_CONTROL : VK_SHIFT) >= 0)) 1994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetKeyState((key == 'V') ? VK_SHIFT : VK_CONTROL) >= 0) { 1996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 1997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 1998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Paste(); 1999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 2000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_BACK: { 2004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((flags & KF_ALTDOWN) || model_->is_keyword_hint() || 2005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->keyword().empty()) 2006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 2009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE selection; 2010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(selection); 2011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((selection.cpMin != selection.cpMax) || (selection.cpMin != 0)) 2012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're showing a keyword and the user pressed backspace at the beginning 2016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the text. Delete the selected keyword. 2017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 2018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->ClearKeyword(GetText()); 2019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_TAB: { 202372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (model_->is_keyword_hint()) { 2024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Accept the keyword. 2025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 2026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->AcceptKeyword(); 202772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (!IsCaretAtEnd()) { 202872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ScopedFreeze freeze(this, GetTextObjectModel()); 202972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnBeforePossibleChange(); 203072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PlaceCaretAt(GetTextLength()); 203172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnAfterPossibleChange(); 2032201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else { 2033dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->CommitSuggestedText(true); 2034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 0xbb: // Ctrl-'='. Triggers subscripting (even in plain text mode). 2039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't use VK_OEM_PLUS in case the macro isn't defined. 2040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (e.g., we don't have this symbol in embeded environment). 2041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 2044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::OnKeyDownAllModes(TCHAR key, 2049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT repeat_count, 2050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT flags) { 2051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See KF_ALTDOWN comment atop OnKeyDownOnlyWritable(). 2052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (key) { 2054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_CONTROL: 2055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->OnControlKeyChanged(true); 2056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case VK_INSERT: 2059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'C': 2060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See more detailed comments in OnKeyDownOnlyWritable(). 2061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((flags & KF_ALTDOWN) || (GetKeyState(VK_CONTROL) >= 0)) 2062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetKeyState(VK_SHIFT) >= 0) 2064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Copy(); 2065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 2068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::GetSelection(CHARRANGE& sel) const { 2073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(sel); 2074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if we need to reverse the direction of the selection. 2076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ITextDocument* const text_object_model = GetTextObjectModel(); 2077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_object_model) 2078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<ITextSelection> selection; 2080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const HRESULT hr = text_object_model->GetSelection(selection.Receive()); 2081dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(S_OK, hr); 2082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch long flags; 2083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch selection->GetFlags(&flags); 2084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (flags & tomSelStartActive) 2085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::swap(sel.cpMin, sel.cpMax); 2086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 208872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 AutocompleteEditViewWin::GetSelectedText() const { 2089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Figure out the length of the selection. 2090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 2091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(sel); 2092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Grab the selected text. 209472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 str; 2095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelText(WriteInto(&str, sel.cpMax - sel.cpMin + 1)); 2096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return str; 2097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SetSelection(LONG start, LONG end) { 2100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSel(start, end); 2101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (start <= end) 2103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to reverse the direction of the selection. 2106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ITextDocument* const text_object_model = GetTextObjectModel(); 2107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_object_model) 2108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<ITextSelection> selection; 2110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const HRESULT hr = text_object_model->GetSelection(selection.Receive()); 2111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(S_OK, hr); 2112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch selection->SetFlags(tomSelStartActive); 2113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 211572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompleteEditViewWin::PlaceCaretAt(string16::size_type pos) { 2116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(static_cast<LONG>(pos), static_cast<LONG>(pos)); 2117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompleteEditViewWin::IsSelectAllForRange(const CHARRANGE& sel) const { 2120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int text_length = GetTextLength(); 2121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ((sel.cpMin == 0) && (sel.cpMax >= text_length)) || 2122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((sel.cpMax == 0) && (sel.cpMin >= text_length)); 2123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2125c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLONG AutocompleteEditViewWin::ClipXCoordToVisibleText( 2126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LONG x, bool is_triple_click) const { 2127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clip the X coordinate to the left edge of the text. Careful: 2128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // PosFromChar(0) may return a negative X coordinate if the beginning of the 2129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text has scrolled off the edit, so don't go past the clip rect's edge. 2130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PARAFORMAT2 pf2; 2131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetParaFormat(pf2); 2132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculation of the clipped coordinate is more complicated if the paragraph 2133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // layout is RTL layout, or if there is RTL characters inside the LTR layout 2134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // paragraph. 2135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool ltr_text_in_ltr_layout = !(pf2.wEffects & PFE_RTLPARA) && 2136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !base::i18n::StringContainsStrongRTLChars(GetText()); 2137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int length = GetTextLength(); 2138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RECT r; 2139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetRect(&r); 2140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The values returned by PosFromChar() seem to refer always 2141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the left edge of the character's bounding box. 2142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const LONG first_position_x = PosFromChar(0).x; 2143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LONG min_x = first_position_x; 2144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ltr_text_in_ltr_layout) { 2145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 1; i < length; ++i) 2146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch min_x = std::min(min_x, PosFromChar(i).x); 2147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const LONG left_bound = std::max(r.left, min_x); 2149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // PosFromChar(length) is a phantom character past the end of the text. It is 2150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not necessarily a right bound; in RTL controls it may be a left bound. So 2151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // treat it as a right bound only if it is to the right of the first 2152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // character. 2153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LONG right_bound = r.right; 2154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LONG end_position_x = PosFromChar(length).x; 2155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (end_position_x >= first_position_x) { 2156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right_bound = std::min(right_bound, end_position_x); // LTR case. 2157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 215821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // For trailing characters that are 2 pixels wide or less (like "l" in some 2159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fonts), we have a problem: 2160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * Clicks on any pixel within the character will place the cursor before 2161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the character. 2162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * Clicks on the pixel just after the character will not allow triple- 2163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // click to work properly (true for any last character width). 2164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So, we move to the last pixel of the character when this is a 2165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // triple-click, and moving to one past the last pixel in all other 2166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // scenarios. This way, all clicks that can move the cursor will place it at 2167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the end of the text, but triple-click will still work. 2168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (x < left_bound) { 2169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (is_triple_click && ltr_text_in_ltr_layout) ? left_bound - 1 : 2170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left_bound; 2171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((length == 0) || (x < right_bound)) 2173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return x; 2174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return is_triple_click ? (right_bound - 1) : right_bound; 2175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::EmphasizeURLComponents() { 2178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ITextDocument* const text_object_model = GetTextObjectModel(); 2179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, text_object_model); 2180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedSuspendUndo suspend_undo(text_object_model); 2181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the selection. 2183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE saved_sel; 2184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(saved_sel); 2185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See whether the contents are a URL with a non-empty host portion, which we 2187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should emphasize. To check for a URL, rather than using the type returned 2188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // by Parse(), ask the model, which will check the desired page transition for 2189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this input. This can tell us whether an UNKNOWN input string is going to 2190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be treated as a search or a navigation, and is the same method the Paste 2191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // And Go system uses. 2192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_parse::Component scheme, host; 2193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutocompleteInput::ParseForEmphasizeComponents( 2194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetText(), model_->GetDesiredTLD(), &scheme, &host); 2195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool emphasize = model_->CurrentTextIsURL() && (host.len > 0); 2196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the baseline emphasis. 2198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARFORMAT cf = {0}; 2199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cf.dwMask = CFM_COLOR; 2200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we're going to emphasize parts of the text, then the baseline state 2201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should be "de-emphasized". If not, then everything should be rendered in 2202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the standard text color. 2203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor( 2204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch security_level_, 2205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch emphasize ? LocationBarView::DEEMPHASIZED_TEXT : LocationBarView::TEXT)); 2206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: Don't use SetDefaultCharFormat() instead of the below; that sets the 2207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // format that will get applied to text added in the future, not to text 2208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already in the edit. 2209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectAll(false); 2210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionCharFormat(cf); 2211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (emphasize) { 2213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We've found a host name, give it more emphasis. 2214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor( 2215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch security_level_, LocationBarView::TEXT)); 2216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(host.begin, host.end()); 2217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionCharFormat(cf); 2218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Emphasize the scheme for security UI display purposes (if necessary). 2221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch insecure_scheme_component_.reset(); 2222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!model_->user_input_in_progress() && scheme.is_nonempty() && 2223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (security_level_ != ToolbarModel::NONE)) { 2224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (security_level_ == ToolbarModel::SECURITY_ERROR) { 2225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch insecure_scheme_component_.begin = scheme.begin; 2226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch insecure_scheme_component_.len = scheme.len; 2227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor( 2229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch security_level_, LocationBarView::SECURITY_TEXT)); 2230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelection(scheme.begin, scheme.end()); 2231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionCharFormat(cf); 2232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Restore the selection. 2235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(saved_sel); 2236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::EraseTopOfSelection( 2239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CDC* dc, const CRect& client_rect, const CRect& paint_clip_rect) { 2240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find the area we care about painting. We could calculate the rect 2241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // containing just the selected portion, but there's no harm in simply erasing 2242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the whole top of the client area, and at least once I saw us manage to 2243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // select the "phantom newline" briefly, which looks very weird if not clipped 2244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // off at the same height. 2245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CRect erase_rect(client_rect.left, client_rect.top, client_rect.right, 2246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_rect.top + font_y_adjustment_); 2247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch erase_rect.IntersectRect(erase_rect, paint_clip_rect); 2248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Erase to the background color. 2250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!erase_rect.IsRectNull()) 2251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dc->FillSolidRect(&erase_rect, background_color_); 2252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::DrawSlashForInsecureScheme( 2255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HDC hdc, 2256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CRect& client_rect, 2257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CRect& paint_clip_rect) { 2258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(insecure_scheme_component_.is_nonempty()); 2259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculate the rect, in window coordinates, containing the portion of the 2261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // scheme where we'll be drawing the slash. Vertically, we draw across one 2262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // x-height of text, plus an additional 3 stroke diameters (the stroke width 2263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // plus a half-stroke width of space between the stroke and the text, both 2264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // above and below the text). 2265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int font_top = client_rect.top + font_y_adjustment_; 2266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkScalar kStrokeWidthPixels = SkIntToScalar(2); 2267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int kAdditionalSpaceOutsideFont = 2268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(ceil(kStrokeWidthPixels * 1.5f)); 2269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CRect scheme_rect(PosFromChar(insecure_scheme_component_.begin).x, 22703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick font_top + font_.GetBaseline() - font_x_height_ - 2271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kAdditionalSpaceOutsideFont, 2272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PosFromChar(insecure_scheme_component_.end()).x, 22733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick font_top + font_.GetBaseline() + 2274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kAdditionalSpaceOutsideFont); 2275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clip to the portion we care about and translate to canvas coordinates 2277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (see the canvas creation below) for use later. 2278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CRect canvas_clip_rect, canvas_paint_clip_rect; 2279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas_clip_rect.IntersectRect(scheme_rect, client_rect); 2280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas_paint_clip_rect.IntersectRect(canvas_clip_rect, paint_clip_rect); 2281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (canvas_paint_clip_rect.IsRectNull()) 2282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // We don't need to paint any of this region, so just bail early. 2283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas_clip_rect.OffsetRect(-scheme_rect.left, -scheme_rect.top); 2284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas_paint_clip_rect.OffsetRect(-scheme_rect.left, -scheme_rect.top); 2285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a paint context for drawing the antialiased stroke. 2287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkPaint paint; 2288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setAntiAlias(true); 2289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setStrokeWidth(kStrokeWidthPixels); 2290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setStrokeCap(SkPaint::kRound_Cap); 2291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a canvas as large as |scheme_rect| to do our drawing, and initialize 2293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it to fully transparent so any antialiasing will look nice when painted 2294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // atop the edit. 2295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CanvasSkia canvas(scheme_rect.Width(), scheme_rect.Height(), false); 2296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.getDevice()->accessBitmap(true).eraseARGB(0, 0, 0, 0); 2297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculate the start and end of the stroke, which are just the lower left 2299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and upper right corners of the canvas, inset by the radius of the endcap 2300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so we don't clip the endcap off. 2301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkScalar kEndCapRadiusPixels = kStrokeWidthPixels / SkIntToScalar(2); 2302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkPoint start_point = { 2303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kEndCapRadiusPixels, 2304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(scheme_rect.Height()) - kEndCapRadiusPixels }; 2305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkPoint end_point = { 2306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(scheme_rect.Width()) - kEndCapRadiusPixels, 2307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kEndCapRadiusPixels }; 2308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculate the selection rectangle in canvas coordinates, which we'll use 2310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to clip the stroke so we can draw the unselected and selected portions. 2311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 2312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(sel); 2313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkRect selection_rect = { 2314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(PosFromChar(sel.cpMin).x - scheme_rect.left), 2315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(0), 2316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(PosFromChar(sel.cpMax).x - scheme_rect.left), 2317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(scheme_rect.Height()) }; 2318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the unselected portion of the stroke. 2320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.save(); 2321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selection_rect.isEmpty() || 2322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.clipRect(selection_rect, SkRegion::kDifference_Op)) { 2323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setColor(LocationBarView::GetColor(security_level_, 2324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LocationBarView::SECURITY_TEXT)); 2325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.drawLine(start_point.fX, start_point.fY, 2326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch end_point.fX, end_point.fY, paint); 2327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.restore(); 2329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the selected portion of the stroke. 2331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!selection_rect.isEmpty() && canvas.clipRect(selection_rect)) { 2332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setColor(LocationBarView::GetColor(security_level_, 2333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LocationBarView::SELECTED_TEXT)); 2334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.drawLine(start_point.fX, start_point.fY, 2335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch end_point.fX, end_point.fY, paint); 2336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now copy what we drew to the target HDC. 2339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.getTopPlatformDevice().drawToHDC(hdc, 2340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scheme_rect.left + canvas_paint_clip_rect.left - canvas_clip_rect.left, 2341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(scheme_rect.top, client_rect.top) + canvas_paint_clip_rect.top - 2342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas_clip_rect.top, &canvas_paint_clip_rect); 2343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutocompleteEditViewWin::DrawDropHighlight(HDC hdc, 2346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const CRect& client_rect, 2347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const CRect& paint_clip_rect) { 2348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_NE(-1, drop_highlight_position_); 2349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int highlight_y = client_rect.top + font_y_adjustment_; 2351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int highlight_x = PosFromChar(drop_highlight_position_).x - 1; 2352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CRect highlight_rect(highlight_x, 2353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch highlight_y, 2354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch highlight_x + 1, 23553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick highlight_y + font_.GetHeight()); 2356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clip the highlight to the region being painted. 2358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CRect clip_rect; 2359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch clip_rect.IntersectRect(highlight_rect, paint_clip_rect); 2360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (clip_rect.IsRectNull()) 2361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HGDIOBJ last_pen = SelectObject(hdc, CreatePen(PS_SOLID, 1, RGB(0, 0, 0))); 2364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MoveToEx(hdc, clip_rect.left, clip_rect.top, NULL); 2365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LineTo(hdc, clip_rect.left, clip_rect.bottom); 2366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteObject(SelectObject(hdc, last_pen)); 2367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::TextChanged() { 2370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 2371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EmphasizeURLComponents(); 2372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen model_->OnChanged(); 2373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 AutocompleteEditViewWin::GetClipboardText() const { 2376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try text format. 237772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::Clipboard* clipboard = g_browser_process->clipboard(); 237872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), 237972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::Clipboard::BUFFER_STANDARD)) { 238072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 text; 238172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &text); 2382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: Unlike in the find popup and textfield view, here we completely 2384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // remove whitespace strings containing newlines. We assume users are 2385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // most likely pasting in URLs that may have been split into multiple 2386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // lines in terminals, email programs, etc., and so linebreaks indicate 2387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // completely bogus whitespace that would just cause the input to be 2388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // invalid. 2389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CollapseWhitespace(text, true); 2390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try bookmark format. 2393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It is tempting to try bookmark format first, but the URL we get out of a 2395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bookmark has been cannonicalized via GURL. This means if a user copies 2396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and pastes from the URL bar to itself, the text will get fixed up and 2397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cannonicalized, which is not what the user expects. By pasting in this 2398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // order, we are sure to paste what the user copied. 239972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (clipboard->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(), 240072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::Clipboard::BUFFER_STANDARD)) { 2401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_str; 2402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch clipboard->ReadBookmark(NULL, &url_str); 2403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // pass resulting url string through GURL to normalize 2404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url(url_str); 2405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.is_valid()) 2406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return UTF8ToWide(url.spec()); 2407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return string16(); 2410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 241272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool AutocompleteEditViewWin::CanPasteAndGo(const string16& text) const { 2413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !popup_window_mode_ && model_->CanPasteAndGo(text); 2414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2416c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochITextDocument* AutocompleteEditViewWin::GetTextObjectModel() const { 2417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_object_model_) { 2418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is lazily initialized, instead of being initialized in the 2419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // constructor, in order to avoid hurting startup performance. 2420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::win::ScopedComPtr<IRichEditOle, NULL> ole_interface; 2421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ole_interface.Attach(GetOleInterface()); 2422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ole_interface) { 2423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ole_interface.QueryInterface( 2424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch __uuidof(ITextDocument), 2425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<void**>(&text_object_model_)); 2426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return text_object_model_; 2429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::StartDragIfNecessary(const CPoint& point) { 243272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (initiated_drag_ || !IsDrag(click_point_[kLeft], point)) 2433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::OSExchangeData data; 2436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD supported_modes = DROPEFFECT_COPY; 2438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE sel; 2440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSelection(sel); 2441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're about to start a drag session, but the edit is expecting a mouse up 2443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that it uses to reset internal state. If we don't send a mouse up now, 2444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the mouse moves back into the edit the edit will reset the selection. 2445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So, we send the event now which resets the selection. We then restore the 2446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // selection and start the drag. We always send lbuttonup as otherwise we 2447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // might trigger a context menu (right up). This seems scary, but doesn't 2448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // seem to cause problems. 2449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 2450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 2451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DefWindowProc(WM_LBUTTONUP, 0, 2452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAKELPARAM(click_point_[kLeft].x, click_point_[kLeft].y)); 2453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(sel); 2454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16 start_text(GetText()); 245772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 text_to_write(GetSelectedText()); 2458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url; 2459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool write_url; 2460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool is_all_selected = IsSelectAllForRange(sel); 2461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |sel| was set by GetSelection(), which preserves selection direction, so 2463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sel.cpMin may not be the smaller value. 2464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model()->AdjustTextForCopy(std::min(sel.cpMin, sel.cpMax), is_all_selected, 2465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &text_to_write, &url, &write_url); 2466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (write_url) { 246872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 title; 2469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap favicon; 2470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (is_all_selected) 2471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->GetDataForURLExport(&url, &title, &favicon); 2472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_utils::SetURLAndDragImage(url, title, favicon, &data); 2473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch supported_modes |= DROPEFFECT_LINK; 2474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("Omnibox_DragURL"), 2475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->profile()); 2476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 2477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch supported_modes |= DROPEFFECT_MOVE; 2478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("Omnibox_DragString"), 2479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->profile()); 2480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data.SetString(text_to_write); 2483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 248472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<ui::DragSource> drag_source(new ui::DragSource); 2485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD dropped_mode; 2486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutoReset<bool> auto_reset_in_drag(&in_drag_, true); 248772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data), 248872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen drag_source, supported_modes, &dropped_mode) == 248972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DRAGDROP_S_DROP) { 2490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((dropped_mode == DROPEFFECT_MOVE) && (start_text == GetText())) { 2491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedFreeze freeze(this, GetTextObjectModel()); 2492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBeforePossibleChange(); 2493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetSelectionRange(sel); 2494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceSel(L"", true); 2495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnAfterPossibleChange(); 2496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // else case, not a move or it was a move and the drop was on us. 2498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the drop was on us, EditDropTarget took care of the move so that 2499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we don't have to delete the text. 2500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = false; 2501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 2502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Drag was canceled or failed. The mouse may still be down and 2503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // over us, in which case we need possible_drag_ to remain true so 2504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that we don't forward mouse move events to the edit which will 2505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // start another drag. 2506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: we didn't use mouse capture during the mouse down as DoDragDrop 2508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // does its own capture. 2509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CPoint cursor_location; 2510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetCursorPos(&cursor_location); 2511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CRect client_rect; 2513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetClientRect(&client_rect); 2514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CPoint client_origin_on_screen(client_rect.left, client_rect.top); 2516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClientToScreen(&client_origin_on_screen); 2517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_rect.MoveToXY(client_origin_on_screen.x, 2518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_origin_on_screen.y); 2519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = (client_rect.PtInRect(cursor_location) && 2520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((GetKeyState(VK_LBUTTON) != 0) || 2521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (GetKeyState(VK_MBUTTON) != 0) || 2522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (GetKeyState(VK_RBUTTON) != 0))); 2523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initiated_drag_ = true; 2526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_click_[kLeft] = false; 2527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::OnPossibleDrag(const CPoint& point) { 2530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (possible_drag_) 2531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch click_point_[kLeft] = point; 2534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initiated_drag_ = false; 2535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHARRANGE selection; 2537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetSel(selection); 2538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selection.cpMin != selection.cpMax) { 2539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const POINT min_sel_location(PosFromChar(selection.cpMin)); 2540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const POINT max_sel_location(PosFromChar(selection.cpMax)); 2541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: we don't consider the y location here as we always pass a 2542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // y-coordinate in the middle to the default handler which always triggers 2543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a drag regardless of the y-coordinate. 2544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = (point.x >= min_sel_location.x) && 2545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (point.x < max_sel_location.x); 2546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::RepaintDropHighlight(int position) { 2550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((position != -1) && (position <= GetTextLength())) { 2551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const POINT min_loc(PosFromChar(position)); 2552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_, 25533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick min_loc.x + 2, font_.GetHeight() + font_y_adjustment_}; 2554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InvalidateRect(&highlight_bounds, false); 2555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::BuildContextMenu() { 2559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (context_menu_contents_.get()) 2560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 256272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen context_menu_contents_.reset(new ui::SimpleMenuModel(this)); 2563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set up context menu. 2564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (popup_window_mode_) { 2565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDC_COPY, IDS_COPY); 2566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 2567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDS_UNDO, IDS_UNDO); 2568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddSeparator(); 2569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDC_CUT, IDS_CUT); 2570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDC_COPY, IDS_COPY); 2571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDC_PASTE, IDS_PASTE); 2572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetContextualLabel() will override this next label with the 2573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IDS_PASTE_AND_SEARCH label as needed. 2574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDS_PASTE_AND_GO, 2575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDS_PASTE_AND_GO); 2576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddSeparator(); 2577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDS_SELECT_ALL, IDS_SELECT_ALL); 2578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddSeparator(); 2579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_contents_->AddItemWithStringId(IDS_EDIT_SEARCH_ENGINES, 2580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDS_EDIT_SEARCH_ENGINES); 2581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_.reset(new views::Menu2(context_menu_contents_.get())); 2583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::SelectAllIfNecessary(MouseButton button, 2586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& point) { 2587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the user has clicked and released to give us focus, select all. 2588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tracking_click_[button] && 258972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen !IsDrag(click_point_[button], point)) { 2590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Select all in the reverse direction so as not to scroll the caret 2591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // into view and shift the contents jarringly. 2592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SelectAll(true); 2593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possible_drag_ = false; 2594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompleteEditViewWin::TrackMousePosition(MouseButton button, 2598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CPoint& point) { 2599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (gaining_focus_.get()) { 2600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This click is giving us focus, so we need to track how much the mouse 2601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // moves to see if it's a drag or just a click. Clicks should select all 2602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the text. 2603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracking_click_[button] = true; 2604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch click_point_[button] = point; 2605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 26073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 26083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint AutocompleteEditViewWin::GetHorizontalMargin() const { 26093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick RECT rect; 26103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetRect(&rect); 26113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick RECT client_rect; 26123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetClientRect(&client_rect); 26133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return (rect.left - client_rect.left) + (client_rect.right - rect.right); 26143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 26153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 26163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint AutocompleteEditViewWin::WidthNeededToDisplay( 261772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& text) const { 26183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Use font_.GetStringWidth() instead of 26193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is 26203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // apparently buggy. In both LTR UI and RTL UI with left-to-right layout, 26213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // PosFromChar(i) might return 0 when i is greater than 1. 26223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return font_.GetStringWidth(text) + GetHorizontalMargin(); 26233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 262421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 262572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool AutocompleteEditViewWin::IsCaretAtEnd() const { 262672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen long length = GetTextLength(); 262772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHARRANGE sel; 262872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetSelection(sel); 262972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return sel.cpMin == sel.cpMax && sel.cpMin == length; 263021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 2631