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