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