OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 5 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
6 | 6 |
7 #include <locale> | 7 #include <locale> |
8 | 8 |
9 #include "base/base_drag_source.h" | 9 #include "base/base_drag_source.h" |
10 #include "base/clipboard.h" | 10 #include "base/clipboard.h" |
11 #include "base/iat_patch.h" | 11 #include "base/iat_patch.h" |
12 #include "base/lazy_instance.h" | |
12 #include "base/ref_counted.h" | 13 #include "base/ref_counted.h" |
13 #include "base/scoped_clipboard_writer.h" | 14 #include "base/scoped_clipboard_writer.h" |
14 #include "base/string_util.h" | 15 #include "base/string_util.h" |
15 #include "chrome/app/chrome_dll_resource.h" | 16 #include "chrome/app/chrome_dll_resource.h" |
16 #include "chrome/browser/autocomplete/autocomplete_accessibility.h" | 17 #include "chrome/browser/autocomplete/autocomplete_accessibility.h" |
17 #include "chrome/browser/autocomplete/autocomplete_popup.h" | 18 #include "chrome/browser/autocomplete/autocomplete_popup.h" |
18 #include "chrome/browser/autocomplete/edit_drop_target.h" | 19 #include "chrome/browser/autocomplete/edit_drop_target.h" |
19 #include "chrome/browser/autocomplete/keyword_provider.h" | 20 #include "chrome/browser/autocomplete/keyword_provider.h" |
20 #include "chrome/browser/browser_process.h" | 21 #include "chrome/browser/browser_process.h" |
21 #include "chrome/browser/command_updater.h" | 22 #include "chrome/browser/command_updater.h" |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
626 if (text_object_model_) | 627 if (text_object_model_) |
627 text_object_model_->Undo(tomResume, NULL); | 628 text_object_model_->Undo(tomResume, NULL); |
628 } | 629 } |
629 | 630 |
630 /////////////////////////////////////////////////////////////////////////////// | 631 /////////////////////////////////////////////////////////////////////////////// |
631 // AutocompleteEditView | 632 // AutocompleteEditView |
632 | 633 |
633 // TODO (jcampan): these colors should be derived from the system colors to | 634 // TODO (jcampan): these colors should be derived from the system colors to |
634 // ensure they show properly. Bug #948807. | 635 // ensure they show properly. Bug #948807. |
635 // Colors used to emphasize the scheme in the URL. | 636 // Colors used to emphasize the scheme in the URL. |
636 static const COLORREF kSecureSchemeColor = RGB(0, 150, 20); | 637 |
637 static const COLORREF kInsecureSchemeColor = RGB(200, 0, 0); | 638 namespace { |
639 | |
640 const COLORREF kSecureSchemeColor = RGB(0, 150, 20); | |
641 const COLORREF kInsecureSchemeColor = RGB(200, 0, 0); | |
638 | 642 |
639 // Colors used to strike-out the scheme when it is insecure. | 643 // Colors used to strike-out the scheme when it is insecure. |
640 static const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0); | 644 const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0); |
641 static const SkColor kSchemeSelectedStrikeoutColor = | 645 const SkColor kSchemeSelectedStrikeoutColor = |
642 SkColorSetRGB(255, 255, 255); | 646 SkColorSetRGB(255, 255, 255); |
643 | 647 |
644 // These are used to hook the CRichEditCtrl's calls to BeginPaint() and | 648 // These are used to hook the CRichEditCtrl's calls to BeginPaint() and |
645 // EndPaint() and provide a memory DC instead. See OnPaint(). | 649 // EndPaint() and provide a memory DC instead. See OnPaint(). |
646 static HWND edit_hwnd = NULL; | 650 HWND edit_hwnd = NULL; |
647 static PAINTSTRUCT paint_struct; | 651 PAINTSTRUCT paint_struct; |
652 | |
653 HDC BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) { | |
654 if (!edit_hwnd || (hWnd != edit_hwnd)) | |
655 return ::BeginPaint(hWnd, lpPaint); | |
656 | |
657 *lpPaint = paint_struct; | |
658 return paint_struct.hdc; | |
659 } | |
660 | |
661 BOOL EndPaintIntercept(HWND hWnd, const PAINTSTRUCT* lpPaint) { | |
662 return (edit_hwnd && (hWnd == edit_hwnd)) ? | |
663 true : ::EndPaint(hWnd, lpPaint); | |
664 } | |
648 | 665 |
649 // Returns a lazily initialized property bag accessor for saving our state in a | 666 // Returns a lazily initialized property bag accessor for saving our state in a |
650 // TabContents. | 667 // TabContents. |
651 static PropertyAccessor<AutocompleteEditState>* GetStateAccessor() { | 668 PropertyAccessor<AutocompleteEditState>* GetStateAccessor() { |
652 static PropertyAccessor<AutocompleteEditState> state; | 669 static PropertyAccessor<AutocompleteEditState> state; |
653 return &state; | 670 return &state; |
654 } | 671 } |
655 | 672 |
673 class PaintPatcher { | |
amit
2009/02/26 15:00:32
maybe derive privately from RefCounted and just ca
| |
674 public: | |
675 PaintPatcher() : refcount_(0) { } | |
676 ~PaintPatcher() { DCHECK(refcount_ == 0); } | |
677 | |
678 void RefPatch() { | |
679 if (refcount_ == 0) { | |
680 DCHECK(!begin_paint_.is_patched()); | |
681 DCHECK(!end_paint_.is_patched()); | |
682 begin_paint_.Patch(L"riched20.dll", "user32.dll", "BeginPaint", | |
683 &BeginPaintIntercept); | |
684 end_paint_.Patch(L"riched20.dll", "user32.dll", "EndPaint", | |
685 &EndPaintIntercept); | |
686 } | |
687 ++refcount_; | |
688 } | |
689 | |
690 void DerefPatch() { | |
691 DCHECK(begin_paint_.is_patched()); | |
692 DCHECK(end_paint_.is_patched()); | |
693 --refcount_; | |
694 if (refcount_ == 0) { | |
695 begin_paint_.Unpatch(); | |
696 end_paint_.Unpatch(); | |
697 } | |
698 } | |
699 | |
700 private: | |
amit
2009/02/26 15:00:32
DISABLE_COPY_AND_ASSIGN
| |
701 size_t refcount_; | |
702 iat_patch::IATPatchFunction begin_paint_; | |
703 iat_patch::IATPatchFunction end_paint_; | |
704 }; | |
705 | |
706 base::LazyInstance<PaintPatcher> g_paint_patcher(base::LINKER_INITIALIZED); | |
707 | |
708 } // namespace | |
709 | |
656 AutocompleteEditView::AutocompleteEditView( | 710 AutocompleteEditView::AutocompleteEditView( |
657 const ChromeFont& font, | 711 const ChromeFont& font, |
658 AutocompleteEditController* controller, | 712 AutocompleteEditController* controller, |
659 ToolbarModel* toolbar_model, | 713 ToolbarModel* toolbar_model, |
660 views::View* parent_view, | 714 views::View* parent_view, |
661 HWND hwnd, | 715 HWND hwnd, |
662 Profile* profile, | 716 Profile* profile, |
663 CommandUpdater* command_updater, | 717 CommandUpdater* command_updater, |
664 bool popup_window_mode) | 718 bool popup_window_mode) |
665 : model_(new AutocompleteEditModel(this, controller, profile)), | 719 : model_(new AutocompleteEditModel(this, controller, profile)), |
(...skipping 12 matching lines...) Expand all Loading... | |
678 possible_drag_(false), | 732 possible_drag_(false), |
679 in_drag_(false), | 733 in_drag_(false), |
680 initiated_drag_(false), | 734 initiated_drag_(false), |
681 drop_highlight_position_(-1), | 735 drop_highlight_position_(-1), |
682 background_color_(0), | 736 background_color_(0), |
683 scheme_security_level_(ToolbarModel::NORMAL) { | 737 scheme_security_level_(ToolbarModel::NORMAL) { |
684 model_->set_popup_model(popup_model_.get()); | 738 model_->set_popup_model(popup_model_.get()); |
685 | 739 |
686 saved_selection_for_focus_change_.cpMin = -1; | 740 saved_selection_for_focus_change_.cpMin = -1; |
687 | 741 |
688 // Statics used for global patching of riched20.dll. | 742 g_paint_patcher.Pointer()->RefPatch(); |
689 static HMODULE richedit_module = NULL; | |
690 static iat_patch::IATPatchFunction patch_begin_paint; | |
691 static iat_patch::IATPatchFunction patch_end_paint; | |
692 | |
693 if (!richedit_module) { | |
694 richedit_module = LoadLibrary(L"riched20.dll"); | |
695 if (richedit_module) { | |
696 DCHECK(!patch_begin_paint.is_patched()); | |
697 patch_begin_paint.Patch(richedit_module, "user32.dll", "BeginPaint", | |
698 &BeginPaintIntercept); | |
699 DCHECK(!patch_end_paint.is_patched()); | |
700 patch_end_paint.Patch(richedit_module, "user32.dll", "EndPaint", | |
701 &EndPaintIntercept); | |
702 } | |
703 } | |
704 | 743 |
705 Create(hwnd, 0, 0, 0, l10n_util::GetExtendedStyles()); | 744 Create(hwnd, 0, 0, 0, l10n_util::GetExtendedStyles()); |
706 SetReadOnly(popup_window_mode_); | 745 SetReadOnly(popup_window_mode_); |
707 SetFont(font_.hfont()); | 746 SetFont(font_.hfont()); |
708 | 747 |
709 // NOTE: Do not use SetWordBreakProcEx() here, that is no longer supported as | 748 // NOTE: Do not use SetWordBreakProcEx() here, that is no longer supported as |
710 // of Rich Edit 2.0 onward. | 749 // of Rich Edit 2.0 onward. |
711 SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, | 750 SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, |
712 reinterpret_cast<LPARAM>(&WordBreakProc)); | 751 reinterpret_cast<LPARAM>(&WordBreakProc)); |
713 | 752 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
780 scoped_refptr<EditDropTarget> drop_target = new EditDropTarget(this); | 819 scoped_refptr<EditDropTarget> drop_target = new EditDropTarget(this); |
781 RegisterDragDrop(m_hWnd, drop_target.get()); | 820 RegisterDragDrop(m_hWnd, drop_target.get()); |
782 } | 821 } |
783 } | 822 } |
784 | 823 |
785 AutocompleteEditView::~AutocompleteEditView() { | 824 AutocompleteEditView::~AutocompleteEditView() { |
786 NotificationService::current()->Notify( | 825 NotificationService::current()->Notify( |
787 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, | 826 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, |
788 Source<AutocompleteEditView>(this), | 827 Source<AutocompleteEditView>(this), |
789 NotificationService::NoDetails()); | 828 NotificationService::NoDetails()); |
829 | |
830 // We balance our reference count and unpatch when the last instance has | |
831 // been destroyed. This prevents us from relying on the AtExit or static | |
832 // destructor sequence to do our unpatching, which is generally fragile. | |
833 g_paint_patcher.Pointer()->DerefPatch(); | |
790 } | 834 } |
791 | 835 |
792 void AutocompleteEditView::SaveStateToTab(TabContents* tab) { | 836 void AutocompleteEditView::SaveStateToTab(TabContents* tab) { |
793 DCHECK(tab); | 837 DCHECK(tab); |
794 | 838 |
795 const AutocompleteEditModel::State model_state( | 839 const AutocompleteEditModel::State model_state( |
796 model_->GetStateForTabSwitch()); | 840 model_->GetStateForTabSwitch()); |
797 | 841 |
798 CHARRANGE selection; | 842 CHARRANGE selection; |
799 GetSelection(selection); | 843 GetSelection(selection); |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1367 bool AutocompleteEditView::SchemeEnd(LPTSTR edit_text, | 1411 bool AutocompleteEditView::SchemeEnd(LPTSTR edit_text, |
1368 int current_pos, | 1412 int current_pos, |
1369 int length) { | 1413 int length) { |
1370 return (current_pos >= 0) && | 1414 return (current_pos >= 0) && |
1371 ((length - current_pos) > 2) && | 1415 ((length - current_pos) > 2) && |
1372 (edit_text[current_pos] == ':') && | 1416 (edit_text[current_pos] == ':') && |
1373 (edit_text[current_pos + 1] == '/') && | 1417 (edit_text[current_pos + 1] == '/') && |
1374 (edit_text[current_pos + 2] == '/'); | 1418 (edit_text[current_pos + 2] == '/'); |
1375 } | 1419 } |
1376 | 1420 |
1377 // static | |
1378 HDC AutocompleteEditView::BeginPaintIntercept(HWND hWnd, | |
1379 LPPAINTSTRUCT lpPaint) { | |
1380 if (!edit_hwnd || (hWnd != edit_hwnd)) | |
1381 return ::BeginPaint(hWnd, lpPaint); | |
1382 | |
1383 *lpPaint = paint_struct; | |
1384 return paint_struct.hdc; | |
1385 } | |
1386 | |
1387 // static | |
1388 BOOL AutocompleteEditView::EndPaintIntercept(HWND hWnd, | |
1389 const PAINTSTRUCT* lpPaint) { | |
1390 return (edit_hwnd && (hWnd == edit_hwnd)) ? | |
1391 true : ::EndPaint(hWnd, lpPaint); | |
1392 } | |
1393 | |
1394 void AutocompleteEditView::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { | 1421 void AutocompleteEditView::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { |
1395 // Don't let alt-enter beep. Not sure this is necessary, as the standard | 1422 // Don't let alt-enter beep. Not sure this is necessary, as the standard |
1396 // alt-enter will hit DiscardWMSysChar() and get thrown away, and | 1423 // alt-enter will hit DiscardWMSysChar() and get thrown away, and |
1397 // ctrl-alt-enter doesn't seem to reach here for some reason? At least not on | 1424 // ctrl-alt-enter doesn't seem to reach here for some reason? At least not on |
1398 // my system... still, this is harmless and maybe necessary in other locales. | 1425 // my system... still, this is harmless and maybe necessary in other locales. |
1399 if (ch == VK_RETURN && (flags & KF_ALTDOWN)) | 1426 if (ch == VK_RETURN && (flags & KF_ALTDOWN)) |
1400 return; | 1427 return; |
1401 | 1428 |
1402 // Escape is processed in OnKeyDown. Don't let any WM_CHAR messages propagate | 1429 // Escape is processed in OnKeyDown. Don't let any WM_CHAR messages propagate |
1403 // as we don't want the RichEdit to do anything funky. | 1430 // as we don't want the RichEdit to do anything funky. |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2458 } | 2485 } |
2459 | 2486 |
2460 void AutocompleteEditView::RepaintDropHighlight(int position) { | 2487 void AutocompleteEditView::RepaintDropHighlight(int position) { |
2461 if ((position != -1) && (position <= GetTextLength())) { | 2488 if ((position != -1) && (position <= GetTextLength())) { |
2462 const POINT min_loc(PosFromChar(position)); | 2489 const POINT min_loc(PosFromChar(position)); |
2463 const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_, | 2490 const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_, |
2464 min_loc.x + 2, font_ascent_ + font_descent_ + font_y_adjustment_}; | 2491 min_loc.x + 2, font_ascent_ + font_descent_ + font_y_adjustment_}; |
2465 InvalidateRect(&highlight_bounds, false); | 2492 InvalidateRect(&highlight_bounds, false); |
2466 } | 2493 } |
2467 } | 2494 } |
OLD | NEW |