Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

348 lines
15 KiB

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