autocomp.h
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 15k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /* Copyright 1996 Microsoft */
  2. #ifndef _AUTOCOMP_HPP_
  3. #define _AUTOCOMP_HPP_
  4. #include "accdel.h"
  5. #include "asuggest.h"
  6. // TODO List:
  7. // 1. Convert AutoComplete to be a Free Threaded object and move it and all it's
  8. //    lists into MultiApartment model.
  9. // 2. Get thread out of ThreadPool API in shlwapi.dll instead of creating thead our
  10. //    selves.
  11. // 3. See if SHWaitForSendMessageThread() will cause a lock if bg thread is in SendMessage().
  12. //    If so, make sure the bg loop's hard loop doesn't call SendMessage() in this case without
  13. //    first looking for QUIT message.
  14. // WARNING On Usage:
  15. //   This object is marked Apartment model and this abuses COM.  These are rules 
  16. // that need to be followed to prevent bugs.  This object will be used within three scopes.  
  17. // The first scope is the caller doing: 1a) CoInitialize(), 1b) CoCreateInstance(). 
  18. // 1c) p->Init(), 1d) p->Release(), 1e) CoUninitialize().
  19. // The second scope is the object doing: 2a) Subclass();AddRef(), 2b) WM_DESTROY;Release();
  20. // 1c) p->Init(), 1d) p->Release(), 1e) CoUninitialize().
  21. // The third scope is the background thread doing: 3a) (in thread proc) CoInitialize(), 
  22. // 3b) CoUninitialize(). 
  23. // This object requires that 1E come after 2B and that should be the only requirement
  24. // for the use of this object.
  25. //
  26. // PRIVATE
  27. //
  28. #define AC_LIST_GROWTH_CONST         50
  29. const WCHAR CH_WILDCARD = L'1';    // indicates a wildcard search
  30. //
  31. // Debug Flags
  32. //
  33. #define AC_WARNING          TF_WARNING + TF_AUTOCOMPLETE
  34. #define AC_ERROR            TF_ERROR   + TF_AUTOCOMPLETE
  35. #define AC_GENERAL          TF_GENERAL + TF_AUTOCOMPLETE
  36. #define AC_FUNC             TF_FUNC    + TF_AUTOCOMPLETE
  37. // Enable test regkey
  38. #define ALLOW_ALWAYS_DROP_UP
  39. //
  40. // WndProc messages to the dropdown window
  41. //
  42. enum
  43. {
  44.     AM_BUTTONCLICK = WM_APP + 400,
  45.     AM_UPDATESCROLLPOS,
  46. };
  47. #define ACO_UNINITIALIZED       0x80000000    // if autocomplete options have not been initialized
  48. //
  49. // PUBLIC
  50. //
  51. HRESULT SHUseDefaultAutoComplete(HWND hwndEdit, 
  52.                                IBrowserService * pbs,       IN  OPTIONAL
  53.                                IAutoComplete2 ** ppac,      OUT OPTIONAL
  54.                                IShellService ** ppssACLISF, OUT OPTIONAL
  55.                                BOOL fUseCMDMRU);
  56. // Forward references
  57. class CAutoComplete;
  58. class CACString* CreateACString(LPCWSTR pszStr);
  59. //+-------------------------------------------------------------------------
  60. // CACString - Autocomplete string shared by foreground & background threads
  61. //--------------------------------------------------------------------------
  62. class CACString
  63. {
  64. public:
  65.     ULONG AddRef();
  66.     ULONG Release();
  67.     LPCWSTR GetStr() const { return m_sz; }
  68.     LPCWSTR GetStrToCompare() const { return m_sz + m_iIgnore; }
  69.     int GetLength() const { return m_cChars; }
  70.     int GetLengthToCompare() const { return m_cChars - m_iIgnore; }
  71.     const WCHAR& operator [] (int nIndex) const { return m_sz[nIndex]; }
  72.     operator LPCWSTR() { return m_sz; }
  73.     BOOL HasPrefix() { return m_iIgnore; }
  74.     BOOL PrefixLength() { return m_iIgnore; }
  75.     // Note, the following compare functions ignore the prefix of the CACString
  76.     int StrCmpI(LPCWSTR psz) { return ::StrCmpI(m_sz + m_iIgnore, psz); }
  77.     int StrCmpI(CACString& r) { return ::StrCmpI(m_sz + m_iIgnore, r.m_sz + r.m_iIgnore); }
  78.     int StrCmpNI(LPCWSTR psz, int cch) { return ::StrCmpNI(m_sz + m_iIgnore, psz, cch); }
  79. protected:
  80.     friend CACString* CreateACString(LPCWSTR pszStr, int iIgnore);
  81.     // Prevent creation on stack
  82.     CACString();
  83.     // Member variables
  84.     ULONG m_dwRefCount;  // reference count
  85.     int   m_cChars;      // length of string (excluding null)
  86.     int   m_iIgnore;     // # prefix characters to ignore when comparing strings
  87.     WCHAR m_sz[1];       // first character of the string
  88. };
  89. //+-------------------------------------------------------------------------
  90. // CACThread - Autocomplete thread that runs in the background
  91. //--------------------------------------------------------------------------
  92. class CACThread : public IUnknown
  93. {
  94. public:
  95.     // *** IUnknown ***
  96.     virtual STDMETHODIMP_(ULONG) AddRef();
  97.     virtual STDMETHODIMP_(ULONG) Release();
  98.     virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  99.                 CACThread(CAutoComplete& rAutoComp);
  100.                ~CACThread();
  101.     BOOL        Init(IEnumString* pes, IACList* pacl);
  102.     void        GotFocus(); 
  103.     void        LostFocus();
  104.     BOOL        HasFocus() { return m_fWorkItemQueued != 0; }
  105.     BOOL        StartSearch(LPCWSTR pszSearch, DWORD dwOptions);
  106.     void        StopSearch();
  107.     void        SyncShutDownBGThread();
  108.     BOOL        IsDisabled() { return m_fDisabled; }
  109.     // Helper functions
  110.     static BOOL MatchesSpecialPrefix(LPCWSTR pszSearch);
  111.     static int  GetSpecialPrefixLen(LPCWSTR psz);
  112. protected:
  113.     DWORD           m_dwRefCount;
  114.     CAutoComplete*  m_pAutoComp;     // portion of autocomplete that runs on main thread
  115.     LONG            m_fWorkItemQueued; // if request made to shlwapi thread pool
  116.     LONG            m_idThread;
  117.     HANDLE          m_hCreateEvent;  // thread startup syncronizatrion
  118.     BOOL            m_fDisabled:1;   // is autocomplete disabled?
  119.     LPWSTR          m_pszSearch;     // String we are currently searching for
  120.     HDPA            m_hdpa_list;     // list of completions
  121.     IEnumString*    m_pes;           // Used internally for real AutoComplete functionality.
  122.     IACList*        m_pacl;          // Additional methods for autocomplete lists (optional).
  123.     void        _SendAsyncShutDownMsg();
  124.     void        _FreeThreadData();
  125.     HRESULT     _ThreadLoop();
  126.     void        _Search(LPWSTR pszSearch, DWORD dwOptions);
  127.     BOOL        _AddToList(LPTSTR pszUrl, int cchMatch);
  128.     void        _DoExpand(LPCWSTR pszSearch);
  129.     static DWORD WINAPI _ThreadProc(LPVOID lpv);
  130.     static int CALLBACK _DpaCompare(LPVOID p1, LPVOID p2, LPARAM lParam);
  131. };
  132. //+-------------------------------------------------------------------------
  133. // CAutoComplete - Main autocomplete class that runs on the main UI thread
  134. //--------------------------------------------------------------------------
  135. class CAutoComplete
  136.                 : public IAutoComplete2
  137.                 , public IAutoCompleteDropDown
  138.                 , public IEnumString
  139.                 , public CDelegateAccessibleImpl
  140. {
  141. public:
  142.     //////////////////////////////////////////////////////
  143.     // Public Interfaces
  144.     //////////////////////////////////////////////////////
  145.     
  146.     // *** IUnknown ***
  147.     virtual STDMETHODIMP_(ULONG) AddRef();
  148.     virtual STDMETHODIMP_(ULONG) Release();
  149.     virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  150.     // *** IEnumString ***
  151.     virtual STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
  152.     virtual STDMETHODIMP Skip(ULONG celt) { return E_NOTIMPL; }
  153.     virtual STDMETHODIMP Reset();
  154.     virtual STDMETHODIMP Clone(IEnumString **ppenum) { return E_NOTIMPL; }
  155.     // *** IAutoComplete ***
  156.     virtual STDMETHODIMP Init(HWND hwnd, IUnknown *punkACL, LPCOLESTR pwszRegKeyPath, LPCOLESTR pwszQuickCompleteString);
  157.     virtual STDMETHODIMP Enable(BOOL fEnable);
  158.     // *** IAutoComplete2 ***
  159.     virtual STDMETHODIMP SetOptions(DWORD dwFlag);
  160.     virtual STDMETHODIMP GetOptions(DWORD* pdwFlag);
  161.     // *** IAutoCompleteDropDown ***
  162.     virtual STDMETHODIMP GetDropDownStatus(DWORD *pdwFlags, LPWSTR *ppwszString);
  163.     virtual STDMETHODIMP ResetEnumerator();
  164.     // *** IAccessible ***
  165.     STDMETHODIMP get_accName(VARIANT varChild, BSTR  *pszName);
  166. protected:
  167.     // Methods called by the background thread
  168.     friend CACThread;
  169.     void SearchComplete(HDPA hdpa, BOOL fLimitReached) { PostMessage(m_hwndEdit, m_uMsgSearchComplete, fLimitReached, (LPARAM)hdpa); }
  170.     BOOL IsEnabled();
  171.     // Constructor / Destructor (protected so we can't create on stack)
  172.     CAutoComplete();
  173.     ~CAutoComplete();
  174.     // Instance creator
  175.     friend HRESULT CAutoComplete_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
  176.     BOOL _Init();
  177.     // Private variables
  178.     DWORD           m_dwRefCount;
  179.     CACThread*      m_pThread;              // background autocomplete thread
  180.     TCHAR           m_szQuickComplete[MAX_PATH];
  181.     TCHAR           m_szRegKeyPath[MAX_PATH];
  182.     DWORD           m_dwFlags;
  183.     HWND            m_hwndEdit;
  184.     HWND            m_hwndCombo;            // if m_hwndEdit is part of a combobox
  185.     LPTSTR          m_pszCurrent;
  186.     int             m_iCurrent;
  187.     DWORD           m_dwLastSearchFlags;
  188.     WNDPROC         m_pOldListViewWndProc;
  189.     IEnumString *   m_pes;                  // Used internally for real AutoComplete functionality.
  190.     IACList *       m_pacl;                 // Additional methods for autocomplete lists (optional).
  191.     HDPA            m_hdpa;                 // sorted completions list
  192.     LPWSTR          m_pszLastSearch;        // string last sent for completion
  193.     int             m_iFirstMatch;          // first match in list (-1 if no matches)
  194.     int             m_iLastMatch;           // last match in list (-1 if no matches)
  195.     int             m_iAppended;            // item completed in the edit box
  196.     BITBOOL         m_fNeedNewList:1;       // last search was truncated
  197.     BITBOOL         m_fDropDownResized:1;   // user has resized drop down
  198.     BITBOOL         m_fAppended:1;          // if something currently appended
  199.     BITBOOL         m_fSearchForAdded:1;    // if last item in dpa is "Search for <>"
  200.     BITBOOL         m_fSearchFor:1;         // if "Search for <>" is to be displayed
  201.     BITBOOL         m_fImeCandidateOpen:1;  // if the IME's candidate window is visible
  202.     DWORD           m_dwOptions;            // autocomplete options (ACO_*)
  203.     EDITWORDBREAKPROC m_oldEditWordBreakProc; // original word break proc for m_hwndEdit
  204.     // Member variables for drop-down auto-suggest window
  205.     HWND            m_hwndDropDown;         // Shows completions in drop-down window
  206.     HWND            m_hwndList;             // Shows completions in drop-down window
  207.     HWND            m_hwndScroll;           // scrollbar
  208.     HWND            m_hwndGrip;             // gripper for resizing the dropdown
  209.     int             m_nStatusHeight;        // height of status in drop-down
  210.     int             m_nDropWidth;           // width of drop-down window
  211.     int             m_nDropHeight;          // height of drop-down window
  212.     int             m_cxGripper;            // width/height of gripper
  213.     BITBOOL         m_fDroppedUp:1;         // if dropdown is over top the edit box
  214. #ifdef ALLOW_ALWAYS_DROP_UP
  215.     BITBOOL         m_fAlwaysDropUp:1;      // TEST regkey to always drop up
  216. #endif
  217.     BITBOOL         m_fSettingText:1;       // if setting the edit text
  218.     BITBOOL         m_fInHotTracking:1;     // if new selection is due to hot-tracking 
  219.     // Member Variables used for external IEnumString
  220.     IEnumString *   m_pesExtern;            // Used internally for real AutoComplete functionality.
  221.     LPTSTR          m_szEnumString;
  222.     // Registered messages sent to edit window
  223.     UINT            m_uMsgSearchComplete;
  224.     UINT            m_uMsgItemActivate;
  225.     static HHOOK    s_hhookMouse;           // windows hook installed when drop-down visible
  226.     static HWND     s_hwndDropDown;         // dropdown currently visible
  227.     static BOOL     s_fNoActivate;          // keep topmost-window from losing activation
  228.     void        _OnSearchComplete(HDPA hdpa, BOOL fLimitReached);
  229.     BOOL        _GetItem(int iIndex, LPWSTR pswText, int cchMax, BOOL fDisplayName);
  230.     void        _UpdateCompletion(LPCWSTR pszTyped, int iChanged, BOOL fAppend);
  231.     void        _HideDropDown();
  232.     void        _ShowDropDown();
  233.     void        _PositionDropDown();
  234.     void        _SeeWhatsEnabled();
  235.     BOOL        _IsAutoSuggestEnabled() { return m_dwOptions & ACO_AUTOSUGGEST; }
  236.     BOOL        _IsRTLReadingEnabled() { return m_dwOptions & ACO_RTLREADING; }
  237.     BOOL        _IsAutoAppendEnabled() { return (m_dwOptions & ACO_AUTOAPPEND) || (m_dwOptions & ACO_UNINITIALIZED); }
  238.     BOOL        _IsComboboxDropped() { return (m_hwndCombo && ComboBox_GetDroppedState(m_hwndCombo)); }
  239.     void        _UpdateGrip();
  240.     void        _UpdateScrollbar();
  241.     static BOOL _IsWhack(TCHAR ch);
  242.     static BOOL _IsBreakChar(WCHAR wch);
  243.     BOOL        _WantToAppendResults();
  244.     int         _JumpToNextBreak(int iLoc, DWORD dwFlags);
  245.     BOOL        _CursorMovement(WPARAM wParam);
  246.     void        _RemoveCompletion();
  247.     void        _GetEditText();
  248.     void        _SetEditText(LPCWSTR psz);
  249.     void        _UpdateText(int iStartSel, int iEndSel, LPCTSTR pszCurrent, LPCTSTR pszNew);
  250.     BOOL        _OnKeyDown(WPARAM wParam);
  251.     LRESULT     _OnChar(WPARAM wParam, LPARAM lParam);
  252.     void        _StartCompletion(BOOL fAppend, BOOL fEvenIfEmpty = FALSE);
  253.     BOOL        _StartSearch(LPCWSTR pszSearch);
  254.     void        _StopSearch();
  255.     BOOL        _ResetSearch();
  256.     void        _GotFocus();
  257.     LPTSTR      _QuickEnter();
  258.     BOOL        _AppendNext(BOOL fAppendToWhack);
  259.     BOOL        _AppendPrevious(BOOL fAppendToWhack);
  260.     void        _Append(CACString& rStr, BOOL fAppendToWhack);
  261.     BOOL        _SetQuickCompleteStrings(LPCOLESTR pcszRegKeyPath, LPCOLESTR pcszQuickCompleteString);
  262.     void        _SubClassParent(HWND hwnd);
  263.     void        _UnSubClassParent(HWND hwnd);
  264.     LRESULT     _DropDownWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
  265.     LRESULT     _EditWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
  266.     LRESULT     _ListViewWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
  267.     static int  _DPADestroyCallback(LPVOID p, LPVOID d);
  268.     static void _FreeDPAPtrs(HDPA hdpa);
  269.     static int CALLBACK EditWordBreakProcW(LPWSTR lpch, int ichCurrent, int cch, int code);
  270.     static LRESULT CALLBACK s_EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  271.     static LRESULT CALLBACK s_DropDownWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  272.     static LRESULT CALLBACK s_ListViewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  273.     static LRESULT CALLBACK s_ParentWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  274.     static LRESULT CALLBACK s_GripperWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  275.     static LRESULT CALLBACK s_MouseHook(int nCode, WPARAM wParam, LPARAM lParam);
  276. };
  277. #endif