1
0

addressEditbox.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. #define OEMRESOURCE
  2. #include "./addressEditbox.h"
  3. #include "./common.h"
  4. #include <richedit.h>
  5. #include <strsafe.h>
  6. #define NAEF_USERFLAGSMASK 0x00FFFFFF
  7. #define NAEF_UNICODE 0x01000000
  8. typedef struct __ADDRESSEDITBOX
  9. {
  10. WNDPROC originalProc;
  11. UINT flags;
  12. DWORD dblclkTime; LPWSTR rollbackText;
  13. } ADDRESSEDITBOX;
  14. #define ADDRESSEDITBOX_PROP L"NullsoftAddressEditbox"
  15. #define GetEditbox(__hwnd) ((ADDRESSEDITBOX*)GetProp((__hwnd), ADDRESSEDITBOX_PROP))
  16. static LRESULT CALLBACK AddressEditbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  17. static INT CALLBACK AddressEditbox_WordBreakProc(LPWSTR pszText, INT iCurrent, INT cchLen, INT code);
  18. static INT CALLBACK AddressEditbox_WordBreakProc2(LPWSTR pszText, INT iCurrent, INT cchLen, INT code);
  19. BOOL AddressEditbox_AttachWindow(HWND hEditbox)
  20. {
  21. if (!IsWindow(hEditbox))
  22. return FALSE;
  23. ADDRESSEDITBOX *editbox = (ADDRESSEDITBOX*)GetProp(hEditbox, ADDRESSEDITBOX_PROP);
  24. if (NULL != editbox) return TRUE;
  25. editbox = (ADDRESSEDITBOX*)calloc(1, sizeof(ADDRESSEDITBOX));
  26. if (NULL == editbox) return FALSE;
  27. ZeroMemory(editbox, sizeof(ADDRESSEDITBOX));
  28. if (IsWindowUnicode(hEditbox))
  29. editbox->flags |= NAEF_UNICODE;
  30. editbox->originalProc = (WNDPROC)(LONG_PTR)((0 != (NAEF_UNICODE & editbox->flags)) ?
  31. SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)AddressEditbox_WindowProc) :
  32. SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)AddressEditbox_WindowProc));
  33. if (NULL == editbox->originalProc || !SetProp(hEditbox, ADDRESSEDITBOX_PROP, editbox))
  34. {
  35. if (NULL != editbox->originalProc)
  36. {
  37. if (0 != (NAEF_UNICODE & editbox->flags))
  38. SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
  39. else
  40. SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
  41. }
  42. free(editbox);
  43. return FALSE;
  44. }
  45. SendMessage(hEditbox, EM_SETWORDBREAKPROC, 0, (LPARAM)AddressEditbox_WordBreakProc);
  46. if (FAILED(LoginBox_GetWindowText(hEditbox, &editbox->rollbackText, NULL)))
  47. editbox->rollbackText = NULL;
  48. return TRUE;
  49. }
  50. static void AddressEditbox_Detach(HWND hwnd)
  51. {
  52. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  53. RemoveProp(hwnd, ADDRESSEDITBOX_PROP);
  54. if (NULL == editbox)
  55. return;
  56. if (NULL != editbox->originalProc)
  57. {
  58. if (0 != (NAEF_UNICODE & editbox->flags))
  59. SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
  60. else
  61. SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
  62. }
  63. free(editbox);
  64. }
  65. static LRESULT AddressEditbox_CallOrigWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  66. {
  67. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  68. if (NULL == editbox || NULL == editbox->originalProc)
  69. {
  70. return (0 != (NAEF_UNICODE & editbox->flags)) ?
  71. DefWindowProcW(hwnd, uMsg, wParam, lParam) :
  72. DefWindowProcA(hwnd, uMsg, wParam, lParam);
  73. }
  74. return (0 != (NAEF_UNICODE & editbox->flags)) ?
  75. CallWindowProcW(editbox->originalProc, hwnd, uMsg, wParam, lParam) :
  76. CallWindowProcA(editbox->originalProc, hwnd, uMsg, wParam, lParam);
  77. }
  78. static void AddressEditbox_SelectReplacementBlock(HWND hwnd, LPCWSTR pszText)
  79. {
  80. INT begin(-1), end(-1);
  81. if (NULL != pszText)
  82. {
  83. LPCWSTR cursor = pszText;
  84. while(L'\0' != *cursor)
  85. {
  86. if (-1 == begin)
  87. {
  88. if (REPLACE_MARKER_BEGIN == *cursor)
  89. begin = (INT)(INT_PTR)(cursor - pszText);
  90. }
  91. else if (REPLACE_MARKER_END == *cursor)
  92. {
  93. end = (INT)(INT_PTR)(cursor - pszText) + 1;
  94. break;
  95. }
  96. cursor = CharNext(cursor);
  97. }
  98. if (-1 == begin || -1 == end)
  99. {
  100. begin = (INT)(INT_PTR)(cursor - pszText);
  101. end = begin + 1;
  102. }
  103. }
  104. SendMessage(hwnd, EM_SETSEL, begin, end);
  105. }
  106. static void AddressEditbox_ResetText(HWND hwnd)
  107. {
  108. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  109. if (NULL != editbox)
  110. {
  111. AddressEditbox_CallOrigWindowProc(hwnd, WM_SETTEXT, 0, (LPARAM)editbox->rollbackText);
  112. AddressEditbox_SelectReplacementBlock(hwnd, editbox->rollbackText);
  113. }
  114. }
  115. static BOOL AddressEditbox_IsDelimiterChar(WCHAR testChar)
  116. {
  117. WORD info;
  118. if (FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &testChar, 1, &info))
  119. return 0;
  120. if (0 != ((C1_SPACE | C1_PUNCT | C1_CNTRL | C1_BLANK) & info) &&
  121. REPLACE_MARKER_BEGIN != testChar && REPLACE_MARKER_END != testChar)
  122. {
  123. return TRUE;
  124. }
  125. return FALSE;
  126. }
  127. static INT AddressEditbox_FindLeft(LPCWSTR pszText, INT iCurrent, INT cchLen)
  128. {
  129. if (iCurrent <= 0)
  130. return 0;
  131. LPCWSTR pszCursor = &pszText[iCurrent];
  132. BOOL charDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
  133. for(;;)
  134. {
  135. pszCursor = CharPrev(pszText, pszCursor);
  136. if (charDelim != AddressEditbox_IsDelimiterChar(*pszCursor))
  137. return (INT)(INT_PTR)(CharNext(pszCursor) - pszText);
  138. if (pszCursor == pszText)
  139. break;
  140. }
  141. return 0;
  142. }
  143. static INT AddressEditbox_FindRight(LPCWSTR pszText, INT iCurrent, INT cchLen)
  144. {
  145. if (iCurrent >= cchLen)
  146. return cchLen;
  147. LPCWSTR pszEnd = &pszText[cchLen];
  148. LPCWSTR pszCursor = &pszText[iCurrent];
  149. if (iCurrent > 0)
  150. pszCursor = CharNext(pszCursor);
  151. BOOL charDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
  152. for(;;)
  153. {
  154. pszCursor = CharNext(pszCursor);
  155. if (pszCursor >= pszEnd)
  156. break;
  157. if (charDelim != AddressEditbox_IsDelimiterChar(*pszCursor))
  158. return (INT)(INT_PTR)(pszCursor - pszText);
  159. }
  160. return cchLen;
  161. }
  162. static INT AddressEditbox_FindWordLeft(LPCWSTR pszText, INT iCurrent, INT cchLen, BOOL fRightCtrl)
  163. {
  164. if (iCurrent < 2)
  165. return 0;
  166. LPCWSTR pszCursor = &pszText[iCurrent];
  167. if (FALSE == fRightCtrl)
  168. pszCursor = CharPrev(pszText, pszCursor);
  169. BOOL prevCharDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
  170. for(;;)
  171. {
  172. pszCursor = CharPrev(pszText, pszCursor);
  173. if (TRUE == AddressEditbox_IsDelimiterChar(*pszCursor))
  174. {
  175. if (FALSE == prevCharDelim)
  176. return (INT)(INT_PTR)(CharNext(pszCursor) - pszText);
  177. prevCharDelim = TRUE;
  178. }
  179. else
  180. prevCharDelim = FALSE;
  181. if (pszCursor == pszText)
  182. break;
  183. }
  184. return 0;
  185. }
  186. static INT AddressEditbox_FindWordRight(LPCWSTR pszText, INT iCurrent, INT cchLen)
  187. {
  188. if ( iCurrent >= (cchLen - 1))
  189. return cchLen;
  190. LPCWSTR pszEnd = &pszText[cchLen];
  191. LPCWSTR pszCursor = &pszText[iCurrent];
  192. BOOL prevCharDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
  193. for(;;)
  194. {
  195. pszCursor = CharNext(pszCursor);
  196. if (pszCursor >= pszEnd)
  197. break;
  198. if (prevCharDelim != AddressEditbox_IsDelimiterChar(*pszCursor))
  199. {
  200. prevCharDelim = TRUE;
  201. return (INT)(INT_PTR)(pszCursor - pszText);
  202. }
  203. else
  204. prevCharDelim = FALSE;
  205. }
  206. return cchLen;
  207. }
  208. static INT CALLBACK AddressEditbox_WordBreakProc(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
  209. {
  210. switch(code)
  211. {
  212. case WB_ISDELIMITER: return (iCurrent < 0) ? 0 : ((iCurrent > cchLen) ? (cchLen + 1) : AddressEditbox_IsDelimiterChar(pszText[iCurrent]));
  213. case WB_LEFT: return AddressEditbox_FindLeft(pszText, iCurrent, cchLen);
  214. case WB_RIGHT: return AddressEditbox_FindRight(pszText, iCurrent, cchLen);
  215. case WB_MOVEWORDLEFT: return AddressEditbox_FindWordLeft(pszText, iCurrent, cchLen, FALSE);
  216. case WB_MOVEWORDRIGHT: return AddressEditbox_FindWordRight(pszText, iCurrent, cchLen);
  217. }
  218. return 0;
  219. }
  220. static INT CALLBACK AddressEditbox_WordBreakProcOverrideLeft(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
  221. {
  222. switch(code)
  223. {
  224. case WB_LEFT: return AddressEditbox_FindWordLeft(pszText, iCurrent, cchLen, FALSE);
  225. case WB_RIGHT: return AddressEditbox_FindWordRight(pszText, iCurrent, cchLen);
  226. }
  227. return AddressEditbox_WordBreakProc(pszText, iCurrent, cchLen, code);
  228. }
  229. static INT CALLBACK AddressEditbox_WordBreakProcOverrideRight(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
  230. {
  231. switch(code)
  232. {
  233. case WB_LEFT: return AddressEditbox_FindWordLeft(pszText, iCurrent, cchLen, TRUE);
  234. case WB_RIGHT: return AddressEditbox_FindWordRight(pszText, iCurrent, cchLen);
  235. }
  236. return AddressEditbox_WordBreakProc(pszText, iCurrent, cchLen, code);
  237. }
  238. static void AddressEditbox_OnDestroy(HWND hwnd)
  239. {
  240. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  241. WNDPROC originalProc = editbox->originalProc;
  242. BOOL fUnicode = (0 != (NAEF_UNICODE & editbox->flags));
  243. AddressEditbox_Detach(hwnd);
  244. if (NULL != originalProc)
  245. {
  246. if (FALSE != fUnicode)
  247. CallWindowProcW(originalProc, hwnd, WM_DESTROY, 0, 0L);
  248. else
  249. CallWindowProcA(originalProc, hwnd, WM_DESTROY, 0, 0L);
  250. }
  251. }
  252. static LRESULT AddressEditbox_OnGetDlgCode(HWND hwnd, INT vKey, MSG* pMsg)
  253. {
  254. LRESULT result = AddressEditbox_CallOrigWindowProc(hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)pMsg);
  255. switch(vKey)
  256. {
  257. case VK_ESCAPE:
  258. return result |= DLGC_WANTALLKEYS;
  259. }
  260. result &= ~DLGC_HASSETSEL;
  261. return result;
  262. }
  263. static void AddressEditbox_OnLButtonDown(HWND hwnd, UINT vKey, POINTS pts)
  264. {
  265. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  266. if (NULL != editbox)
  267. {
  268. DWORD clickTime = GetTickCount();
  269. if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + GetDoubleClickTime()))
  270. {
  271. SendMessage(hwnd, EM_SETSEL, 0, -1);
  272. return;
  273. }
  274. }
  275. AddressEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONDOWN, (WPARAM)vKey, *((LPARAM*)&pts));
  276. }
  277. static void AddressEditbox_OnLButtonDblClk(HWND hwnd, UINT vKey, POINTS pts)
  278. {
  279. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  280. if (NULL == editbox) return;
  281. DWORD clickTime = GetTickCount();
  282. if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + 2*GetDoubleClickTime()))
  283. {
  284. INT r = (INT)SendMessage(hwnd, EM_CHARFROMPOS, 0, *(LPARAM*)&pts);
  285. r = LOWORD(r);
  286. SendMessage(hwnd, EM_SETSEL, (WPARAM)r, (LPARAM)r);
  287. editbox->dblclkTime = 0;
  288. }
  289. else
  290. {
  291. editbox->dblclkTime = clickTime;
  292. }
  293. INT f, l;
  294. SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
  295. if (f != l) return;
  296. AddressEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONDBLCLK, (WPARAM)vKey, *((LPARAM*)&pts));
  297. }
  298. static void AddressEditbox_DeleteWord(HWND hwnd, UINT vKey, UINT state)
  299. {
  300. BOOL resetVisible = FALSE;
  301. INT first, last;
  302. SendMessage(hwnd, EM_GETSEL, (WPARAM)&first, (LPARAM)&last);
  303. if (first == last)
  304. {
  305. UINT windowStyle = GetWindowStyle(hwnd);
  306. if (0 != (WS_VISIBLE & windowStyle))
  307. {
  308. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  309. resetVisible = TRUE;
  310. }
  311. SendMessage(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
  312. INT newFirst, newLast;
  313. SendMessage(hwnd, EM_GETSEL, (WPARAM)&newFirst, (LPARAM)&newLast);
  314. if (newFirst != first || newLast != last)
  315. SendMessage(hwnd, EM_SETSEL, (WPARAM)first, (LPARAM)newLast);
  316. }
  317. SendMessage(hwnd, EM_REPLACESEL, TRUE, NULL);
  318. if (FALSE != resetVisible)
  319. {
  320. UINT windowStyle = GetWindowStyle(hwnd);
  321. if (0 == (WS_VISIBLE & windowStyle))
  322. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  323. InvalidateRect(hwnd, NULL, FALSE);
  324. }
  325. }
  326. static void AddressEditbox_OnKeyDown(HWND hwnd, UINT vKey, UINT state)
  327. {
  328. EDITWORDBREAKPROC fnOrigBreak = NULL;
  329. if(0 != (0x8000 & GetAsyncKeyState(VK_CONTROL)))
  330. {
  331. switch(vKey)
  332. {
  333. case VK_LEFT:
  334. case VK_RIGHT:
  335. fnOrigBreak = (EDITWORDBREAKPROC)SendMessage(hwnd, EM_GETWORDBREAKPROC, 0, 0L);
  336. if (AddressEditbox_WordBreakProc == fnOrigBreak)
  337. {
  338. EDITWORDBREAKPROC fnOverride = (VK_LEFT == vKey) ?
  339. AddressEditbox_WordBreakProcOverrideLeft : AddressEditbox_WordBreakProcOverrideRight;
  340. SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)fnOverride);
  341. }
  342. break;
  343. case VK_DELETE:
  344. AddressEditbox_DeleteWord(hwnd, VK_RIGHT, state);
  345. return;
  346. case VK_BACK:
  347. AddressEditbox_DeleteWord(hwnd, VK_LEFT, state);
  348. return;
  349. }
  350. }
  351. AddressEditbox_CallOrigWindowProc(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
  352. if (NULL != fnOrigBreak)
  353. SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)fnOrigBreak);
  354. }
  355. static void AddressEditbox_OnChar(HWND hwnd, UINT vKey, UINT state)
  356. {
  357. if (0 != (0x8000 & GetAsyncKeyState(VK_CONTROL)))
  358. {
  359. UINT scanCode = (HIWORD(state) & 0x00FF);
  360. vKey = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK);
  361. }
  362. switch(vKey)
  363. {
  364. case VK_ESCAPE: AddressEditbox_ResetText(hwnd); return;
  365. }
  366. AddressEditbox_CallOrigWindowProc(hwnd, WM_CHAR, (WPARAM)vKey, (LPARAM)state);
  367. }
  368. static BOOL AddressEditbox_RemoveBadChars(LPCWSTR pszText, LPWSTR *bufferOut)
  369. {
  370. LPWSTR buffer = NULL;
  371. if (NULL == pszText) return FALSE;
  372. const WCHAR szBadChars[] = { L'\r', L'\n', L'\t', L'\0'};
  373. BOOL fDetected = FALSE;
  374. for (LPCWSTR p = pszText; L'\0' != *p && FALSE == fDetected; p++)
  375. {
  376. for (LPCWSTR b = szBadChars; L'\0' != *b; b++)
  377. {
  378. if (*p == *b)
  379. {
  380. fDetected = TRUE;
  381. break;
  382. }
  383. }
  384. }
  385. if (FALSE == fDetected)
  386. return FALSE;
  387. if (NULL == bufferOut)
  388. return TRUE;
  389. INT cchText = lstrlen(pszText);
  390. buffer = LoginBox_MallocString(cchText + 1);
  391. if (NULL == buffer) return FALSE;
  392. LPCWSTR s = pszText;
  393. LPWSTR d = buffer;
  394. LPCWSTR b;
  395. for(;;)
  396. {
  397. for (b = szBadChars; L'\0' != *b && *s != *b; b++);
  398. if(L'\0' != *b)
  399. {
  400. if (L'\t' == *b)
  401. {
  402. *d = L' ';
  403. d++;
  404. }
  405. }
  406. else
  407. {
  408. *d = *s;
  409. d++;
  410. }
  411. if (L'\0' == *s)
  412. break;
  413. s++;
  414. }
  415. *bufferOut = buffer;
  416. return TRUE;
  417. }
  418. static LRESULT AddressEditbox_OnSetText(HWND hwnd, LPCWSTR pszText)
  419. {
  420. LPWSTR buffer;
  421. if (FALSE == AddressEditbox_RemoveBadChars(pszText, &buffer))
  422. buffer = NULL;
  423. else
  424. pszText = buffer;
  425. LRESULT result = AddressEditbox_CallOrigWindowProc(hwnd, WM_SETTEXT, 0, (LPARAM)pszText);
  426. ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
  427. if (NULL != editbox)
  428. {
  429. LoginBox_FreeString(editbox->rollbackText);
  430. editbox->rollbackText = LoginBox_CopyString(pszText);
  431. AddressEditbox_SelectReplacementBlock(hwnd, pszText);
  432. }
  433. if (NULL != buffer)
  434. LoginBox_FreeString(buffer);
  435. return result;
  436. }
  437. static LRESULT AddressEditbox_OnReplaceSel(HWND hwnd, BOOL fUndo, LPCWSTR pszText)
  438. {
  439. LPWSTR buffer;
  440. if (FALSE == AddressEditbox_RemoveBadChars(pszText, &buffer))
  441. buffer = NULL;
  442. else
  443. pszText = buffer;
  444. LRESULT result = AddressEditbox_CallOrigWindowProc(hwnd, EM_REPLACESEL, (WPARAM)fUndo, (LPARAM)pszText);
  445. if (NULL != buffer)
  446. LoginBox_FreeString(buffer);
  447. return result;
  448. }
  449. static void AddressEditbox_ReplaceText(HWND hwnd, LPCWSTR pszText, BOOL fUndo, BOOL fScrollCaret)
  450. {
  451. UINT windowStyle = GetWindowStyle(hwnd);
  452. if (0 != (WS_VISIBLE & windowStyle))
  453. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
  454. SendMessage(hwnd, EM_REPLACESEL, (WPARAM)fUndo, (LPARAM)pszText);
  455. if (FALSE != fScrollCaret)
  456. {
  457. INT f, l;
  458. SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
  459. SendMessage(hwnd, EM_SETSEL, (WPARAM)f, (LPARAM)l);
  460. }
  461. if (0 != (WS_VISIBLE & windowStyle))
  462. {
  463. windowStyle = GetWindowStyle(hwnd);
  464. if (0 == (WS_VISIBLE & windowStyle))
  465. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
  466. InvalidateRect(hwnd, NULL, FALSE);
  467. }
  468. }
  469. static void AddressEditbox_OnPaste(HWND hwnd)
  470. {
  471. IDataObject *pObject;
  472. HRESULT hr = OleGetClipboard(&pObject);
  473. if (SUCCEEDED(hr))
  474. {
  475. FORMATETC fmt = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  476. STGMEDIUM stgm;
  477. hr = pObject->GetData(&fmt, &stgm);
  478. if(S_OK == hr)
  479. {
  480. LPCWSTR pClipboard = (LPCWSTR)GlobalLock(stgm.hGlobal);
  481. AddressEditbox_ReplaceText(hwnd, pClipboard, TRUE, TRUE);
  482. GlobalUnlock(stgm.hGlobal);
  483. ReleaseStgMedium(&stgm);
  484. }
  485. else
  486. {
  487. fmt.cfFormat = CF_TEXT;
  488. hr = pObject->GetData(&fmt, &stgm);
  489. if(S_OK == hr)
  490. {
  491. LPCSTR pClipboardAnsi = (LPCSTR)GlobalLock(stgm.hGlobal);
  492. LPWSTR pClipboard;
  493. if (FAILED(LoginBox_MultiByteToWideChar(CP_ACP, 0, pClipboardAnsi, -1, &pClipboard)))
  494. pClipboard = NULL;
  495. AddressEditbox_ReplaceText(hwnd, pClipboard, TRUE, TRUE);
  496. LoginBox_FreeString(pClipboard);
  497. GlobalUnlock(stgm.hGlobal);
  498. ReleaseStgMedium(&stgm);
  499. }
  500. }
  501. pObject->Release();
  502. }
  503. }
  504. static LRESULT AddressEditbox_OnFindWordBreak(HWND hwnd, INT code, INT start)
  505. {
  506. EDITWORDBREAKPROC fnBreak = (EDITWORDBREAKPROC)SendMessage(hwnd, EM_GETWORDBREAKPROC, 0, 0L);
  507. if (NULL == fnBreak) return 0;
  508. UINT cchText = GetWindowTextLength(hwnd);
  509. if (0 == cchText) return 0;
  510. LPWSTR pszText = LoginBox_MallocString(cchText + 1);
  511. if (NULL == pszText) return 0;
  512. LRESULT result = 0;
  513. cchText = GetWindowText(hwnd, pszText, cchText + 1);
  514. if (0 != cchText)
  515. {
  516. result = fnBreak(pszText, start, cchText, code);
  517. }
  518. LoginBox_FreeString(pszText);
  519. return result;
  520. }
  521. static LRESULT CALLBACK AddressEditbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  522. {
  523. switch(uMsg)
  524. {
  525. case WM_DESTROY: AddressEditbox_OnDestroy(hwnd); return 0;
  526. case WM_GETDLGCODE: return AddressEditbox_OnGetDlgCode(hwnd, (INT)wParam, (MSG*)lParam);
  527. case WM_LBUTTONDOWN: AddressEditbox_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
  528. case WM_LBUTTONDBLCLK: AddressEditbox_OnLButtonDblClk(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
  529. case WM_KEYDOWN: AddressEditbox_OnKeyDown(hwnd, (UINT)wParam, (UINT)lParam); return 0;
  530. case WM_CHAR: AddressEditbox_OnChar(hwnd, (UINT)wParam, (UINT)lParam); return 0;
  531. case WM_SETTEXT: return AddressEditbox_OnSetText(hwnd, (LPCWSTR)lParam);
  532. case WM_PASTE: AddressEditbox_OnPaste(hwnd); return 1;
  533. case EM_REPLACESEL: AddressEditbox_OnReplaceSel(hwnd, (BOOL)wParam, (LPCWSTR)lParam); return 0;
  534. case EM_FINDWORDBREAK: return AddressEditbox_OnFindWordBreak(hwnd, (INT)wParam, (INT)lParam);
  535. }
  536. return AddressEditbox_CallOrigWindowProc(hwnd, uMsg, wParam, lParam);
  537. }