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.

1039 lines
32 KiB

  1. // cctlww.cpp - commctl Unicode wrapper
  2. //-----------------------------------------------------------------
  3. // Microsoft Confidential
  4. // Copyright 1998 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Paul Chase Dempsey - mailto:[email protected]
  7. // August 3, 1998
  8. //----------------------------------------------------------------
  9. #include "header.h"
  10. #include <windowsx.h>
  11. #include <wchar.h>
  12. #include "cctlww.h"
  13. #define MAX_ITEM_STRING (MAX_PATH*2)
  14. #define Malloc(cb) lcMalloc((cb))
  15. #define Free(ptr) lcFree((ptr))
  16. // debug help: this var allows you to futz with the codepage under the debugger
  17. // if you change this to an MBCS codepage, set s_cb in W_cbchMaxAcp to 2.
  18. #ifdef _DEBUG
  19. UINT _CODEPAGE = CP_ACP;
  20. #else
  21. #define _CODEPAGE CP_ACP
  22. #endif
  23. //----------------------------------------------------------------
  24. // global data
  25. BOOL g_fAnsiAPIs = FALSE;
  26. BOOL g_fUnicodeListView = FALSE;
  27. BOOL g_fUnicodeTreeView = FALSE;
  28. BOOL g_fUnicodeTabCtrl = FALSE;
  29. // indexed by CCTLWINTYPE enum
  30. static const LPCWSTR rgwszClass[] = { WC_LISTVIEWW, WC_TREEVIEWW, WC_TABCONTROLW };
  31. static const LPCSTR rgszClass[] = { WC_LISTVIEWA, WC_TREEVIEWA, WC_TABCONTROLA };
  32. //----------------------------------------------------------------
  33. // private wrapper helpers
  34. BOOL IsListViewUnicode(HWND hwnd);
  35. BOOL IsTreeViewUnicode(HWND hwnd);
  36. BOOL IsTabCtrlUnicode(HWND hwnd);
  37. //----------------------------------------------------------------
  38. // Return max bytes per character in the system default codepage
  39. int WINAPI W_cbchMaxAcp()
  40. {
  41. static int s_cb = 0;
  42. if (s_cb)
  43. return s_cb;
  44. CPINFO cpi;
  45. if (GetCPInfo(GetACP(), &cpi))
  46. s_cb = cpi.MaxCharSize;
  47. else
  48. s_cb = 2; // worst case
  49. return s_cb;
  50. }
  51. //----------------------------------------------------------------
  52. HWND WINAPI W_CreateWindowEx (
  53. DWORD dwExStyle,
  54. LPCWSTR lpClassName,
  55. LPCWSTR lpWindowName,
  56. DWORD dwStyle,
  57. int X,
  58. int Y,
  59. int nWidth,
  60. int nHeight,
  61. HWND hWndParent ,
  62. HMENU hMenu,
  63. HINSTANCE hInstance,
  64. LPVOID lpParam,
  65. BOOL * pfUnicode /*out*/
  66. )
  67. {
  68. HWND hwnd = CreateWindowExW (dwExStyle, lpClassName, lpWindowName, dwStyle,
  69. X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
  70. if (NULL != hwnd)
  71. {
  72. if (pfUnicode)
  73. *pfUnicode = TRUE;
  74. return hwnd;
  75. }
  76. if (pfUnicode)
  77. *pfUnicode = FALSE;
  78. if (ERROR_CALL_NOT_IMPLEMENTED != ::GetLastError())
  79. {
  80. ASSERT(0); // shouldn't be writing CreateWindow that fail
  81. return 0;
  82. }
  83. char * pszClass = 0;
  84. char * pszWindow = 0;
  85. if ((DWORD_PTR)lpClassName >= 0xC00)
  86. {
  87. int cb = 1 + W_cbchMaxAcp()*lstrlenW(lpClassName);
  88. pszClass = (PSTR)_alloca(cb);
  89. WideCharToMultiByte(_CODEPAGE, 0, lpClassName, -1, pszClass, cb, 0, 0);
  90. }
  91. else // it's a class atom: pass it through
  92. pszClass = PSTR(lpClassName);
  93. if (lpWindowName && *lpWindowName)
  94. {
  95. int cb = 1 + W_cbchMaxAcp()*lstrlenW(lpWindowName);
  96. pszWindow = (PSTR)_alloca(cb);
  97. WideCharToMultiByte(_CODEPAGE, 0, lpWindowName, -1, pszWindow, cb, 0, 0);
  98. }
  99. else
  100. pszWindow = "";
  101. hwnd = CreateWindowExA (dwExStyle, pszClass, pszWindow, dwStyle,
  102. X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
  103. return hwnd;
  104. }
  105. //----------------------------------------------------------------
  106. void WINAPI W_SubClassWindow(HWND hwnd, LONG_PTR Proc, BOOL fUnicode)
  107. {
  108. if (fUnicode)
  109. {
  110. ASSERT(!g_fAnsiAPIs);
  111. SetWindowLongPtrW(hwnd, GWLP_WNDPROC, Proc);
  112. }
  113. else
  114. SetWindowLongPtrA(hwnd, GWLP_WNDPROC, Proc);
  115. }
  116. //----------------------------------------------------------------
  117. WNDPROC WINAPI W_GetWndProc(HWND hwnd, BOOL fUnicode)
  118. {
  119. if (fUnicode)
  120. {
  121. ASSERT(!g_fAnsiAPIs);
  122. return (WNDPROC) GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
  123. }
  124. else
  125. return (WNDPROC) GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
  126. }
  127. //----------------------------------------------------------------
  128. LRESULT WINAPI W_DelegateWindowProc (WNDPROC Proc, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  129. {
  130. if (IsWindowUnicode(hwnd))
  131. return CallWindowProcW(Proc, hwnd, msg, wParam, lParam);
  132. else
  133. return CallWindowProcA(Proc, hwnd, msg, wParam, lParam);
  134. }
  135. //----------------------------------------------------------------
  136. LRESULT WINAPI W_DefWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  137. {
  138. if (IsWindowUnicode(hwnd))
  139. return DefWindowProcW(hwnd, msg, wParam, lParam);
  140. else
  141. return DefWindowProcA(hwnd, msg, wParam, lParam);
  142. }
  143. //----------------------------------------------------------------
  144. LRESULT WINAPI W_DefDlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  145. {
  146. if (IsWindowUnicode(hwnd))
  147. return DefDlgProcW(hwnd, msg, wParam, lParam);
  148. else
  149. return DefDlgProcA(hwnd, msg, wParam, lParam);
  150. }
  151. //----------------------------------------------------------------
  152. BOOL WINAPI W_HasText(HWND hwnd)
  153. {
  154. return (GetWindowTextLength(hwnd) > 0);
  155. }
  156. //----------------------------------------------------------------
  157. int WINAPI W_GetTextLengthExact(HWND hwnd)
  158. {
  159. ASSERT(hwnd && IsWindow(hwnd));
  160. if (IsWindowUnicode(hwnd))
  161. {
  162. int cch1 = GetWindowTextLengthW(hwnd);
  163. #ifdef _DEBUG
  164. PWSTR psz = (PWSTR)_alloca((cch1+1)*2);
  165. int cch2 = GetWindowTextW(hwnd, psz, (cch1+1)*2);
  166. ASSERT(cch2 == lstrlenW(psz));
  167. #endif
  168. return cch1;
  169. }
  170. else
  171. {
  172. int cb1 = GetWindowTextLengthA(hwnd);
  173. PSTR psz = (PSTR)_alloca(cb1+1);
  174. int cb2 = GetWindowTextA(hwnd, psz, cb1+1);
  175. ASSERT(cb1 == cb2);
  176. return MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  177. }
  178. }
  179. //----------------------------------------------------------------
  180. int WINAPI W_GetWindowText (HWND hwnd, PWSTR psz, int cchMax)
  181. {
  182. ASSERT(hwnd && IsWindow(hwnd));
  183. int cch = 0;
  184. *psz = 0;
  185. if (IsWindowUnicode(hwnd))
  186. return GetWindowTextW(hwnd, psz, cchMax);
  187. int cb = W_cbchMaxAcp()*cchMax;
  188. PSTR pszA = (PSTR)_alloca(cb);
  189. cb = GetWindowTextA(hwnd, pszA, cb);
  190. if (cb)
  191. {
  192. cch = MultiByteToWideChar(CP_ACP, 0, pszA, -1, psz, cchMax);
  193. }
  194. else
  195. {
  196. *psz = 0;
  197. cch = 0;
  198. }
  199. return cch;
  200. }
  201. //----------------------------------------------------------------
  202. BOOL WINAPI W_SetWindowText (HWND hwnd, PCWSTR psz)
  203. {
  204. ASSERT(hwnd && IsWindow(hwnd));
  205. if (IsWindowUnicode(hwnd))
  206. return SetWindowTextW(hwnd, psz);
  207. int cb = 1 + W_cbchMaxAcp()*lstrlenW(psz);
  208. PSTR pszA = (PSTR)_alloca(cb);
  209. WideCharToMultiByte(CP_ACP, 0, psz, -1, pszA, cb, 0, 0);
  210. return SetWindowTextA(hwnd, pszA);
  211. }
  212. //----------------------------------------------------------------
  213. LRESULT WINAPI W_SendStringMessage(HWND hwnd, UINT msg, WPARAM wParam, PCWSTR psz)
  214. {
  215. ASSERT(hwnd && IsWindow(hwnd));
  216. if (IsWindowUnicode(hwnd))
  217. return SendMessageW(hwnd, msg, wParam, (LPARAM)psz);
  218. int cb = 1 + W_cbchMaxAcp()*lstrlenW(psz);
  219. PSTR pszA = (PSTR)_alloca(cb);
  220. WideCharToMultiByte(_Module.GetCodePage(), 0, psz, -1, pszA, cb, 0, 0);
  221. return SendMessageA(hwnd, msg, wParam, (LPARAM)pszA);
  222. }
  223. //----------------------------------------------------------------
  224. int WINAPI W_ComboBox_GetListText(HWND hwnd, PWSTR psz, int cchMax)
  225. {
  226. *psz = 0;
  227. int count = ComboBox_GetCount(hwnd);
  228. if (count <= 0)
  229. return 0;
  230. if (IsWindowUnicode(hwnd))
  231. {
  232. PWSTR pch = psz;
  233. int cchTotal = 0;
  234. for (int i = 0; i < count; i++)
  235. {
  236. int cch = (int)SendMessageW(hwnd, CB_GETLBTEXTLEN, (WPARAM)i, 0L);
  237. cchTotal += cch;
  238. if (cchTotal < cchMax-1)
  239. {
  240. SendMessageW(hwnd, CB_GETLBTEXT, (WPARAM)i, (LPARAM)pch);
  241. pch += cch;
  242. *pch++ = L'\n';
  243. cchTotal++;
  244. }
  245. else
  246. cchTotal -= cch;
  247. }
  248. if (cchTotal) --pch;
  249. *pch = 0;
  250. return (int)(pch - psz);
  251. }
  252. else
  253. {
  254. int cbMax = cchMax*W_cbchMaxAcp();
  255. PSTR pszA = (PSTR)Malloc(cbMax);
  256. if (NULL == pszA)
  257. return 0;
  258. PSTR pch = pszA;
  259. int cbTotal = 0;
  260. for (int i = 0; i < count; i++)
  261. {
  262. int cb = (int)SendMessageA(hwnd, CB_GETLBTEXTLEN, (WPARAM)i, 0L);
  263. cbTotal += cb;
  264. if (cbTotal < cbMax-1)
  265. {
  266. SendMessageA(hwnd, CB_GETLBTEXT, (WPARAM)i, (LPARAM)pch);
  267. pch += cb;
  268. *pch++ = '\n';
  269. cbTotal++;
  270. }
  271. else
  272. cbTotal -= cb;
  273. }
  274. if (cbTotal) --pch;
  275. *pch = 0;
  276. int iRet = MultiByteToWideChar(CP_ACP, 0, pszA, -1, psz, cchMax);
  277. Free(pszA);
  278. return iRet;
  279. }
  280. }
  281. //----------------------------------------------------------------
  282. int WINAPI W_ComboBox_SetListText (HWND hwnd, PWSTR psz, int cItemsMax)
  283. {
  284. ASSERT(hwnd && IsWindow(hwnd));
  285. int cItems = 0;
  286. psz = wcstok(psz, L"\n");
  287. while (psz && cItems < cItemsMax)
  288. {
  289. W_ComboBox_AddString(hwnd, psz);
  290. cItems++;
  291. psz = wcstok(NULL, L"\n");
  292. }
  293. return cItems;
  294. }
  295. //----------------------------------------------------------------
  296. int WINAPI W_CompareString(LCID lcid, DWORD dwFlags, PCWSTR str1, int cch1, PCWSTR str2, int cch2)
  297. {
  298. int iRet;
  299. if (g_fAnsiAPIs) goto _Ansi;
  300. iRet = CompareStringW(lcid, dwFlags, str1, cch1, str2, cch2);
  301. if (0 == iRet)
  302. {
  303. if (ERROR_CALL_NOT_IMPLEMENTED == GetLastError())
  304. {
  305. g_fAnsiAPIs = TRUE;
  306. goto _Ansi;
  307. }
  308. }
  309. return iRet;
  310. _Ansi:
  311. if (-1 == cch1)
  312. cch1 = lstrlenW(str1);
  313. if (-1 == cch2)
  314. cch2 = lstrlenW(str2);
  315. int cb = W_cbchMaxAcp();
  316. char *psz1 = (char*)Malloc(cch1*cb);
  317. char *psz2 = (char*)Malloc(cch2*cb);
  318. if (NULL == psz1 || NULL == psz2)
  319. {
  320. iRet = memcmp(str1, str2, min(cch1,cch2)*sizeof(WCHAR));
  321. if (0 == iRet)
  322. iRet = cch1-cch2;
  323. iRet += 2; // convert to CompareString ret codes
  324. }
  325. else
  326. {
  327. UINT cp = CodePageFromLCID(lcid);
  328. cch1 = WideCharToMultiByte(cp, 0, str1, cch1, psz1, cch1*cb, 0, 0);
  329. cch2 = WideCharToMultiByte(cp, 0, str2, cch2, psz2, cch2*cb, 0, 0);
  330. iRet = CompareStringA(lcid, dwFlags, psz1, cch1, psz2, cch2);
  331. }
  332. Free(psz1);
  333. Free(psz2);
  334. return iRet;
  335. }
  336. //----------------------------------------------------------------
  337. BOOL WINAPI W_IsListViewUnicode(HWND hwndLV)
  338. {
  339. ASSERT(hwndLV && IsWindow(hwndLV)); // can't call this unless you've created a LV
  340. if (g_fUnicodeListView)
  341. {
  342. ASSERT(IsWindowUnicode(hwndLV) || (g_fAnsiAPIs && ListView_GetUnicodeFormat(hwndLV)));
  343. return TRUE;
  344. }
  345. else
  346. {
  347. ASSERT(!g_fAnsiAPIs);
  348. ASSERT(!IsWindowUnicode(hwndLV));
  349. return FALSE;
  350. }
  351. }
  352. //----------------------------------------------------------------
  353. BOOL WINAPI W_IsTreeViewUnicode(HWND hwndTV)
  354. {
  355. ASSERT(hwndTV && IsWindow(hwndTV)); // can't call this unless you've created a TV
  356. if (g_fUnicodeTreeView)
  357. {
  358. ASSERT(IsWindowUnicode(hwndTV) || (g_fAnsiAPIs && TreeView_GetUnicodeFormat(hwndTV)));
  359. return TRUE;
  360. }
  361. else
  362. {
  363. ASSERT(!g_fAnsiAPIs);
  364. ASSERT(!IsWindowUnicode(hwndTV));
  365. return FALSE;
  366. }
  367. }
  368. //----------------------------------------------------------------
  369. BOOL WINAPI W_IsTabCtrlUnicode(HWND hwndTC)
  370. {
  371. ASSERT(hwndTC && IsWindow(hwndTC)); // can't call this unless you've created a TC
  372. if (g_fUnicodeTabCtrl)
  373. {
  374. ASSERT(IsWindowUnicode(hwndTC) || (g_fAnsiAPIs && TabCtrl_GetUnicodeFormat(hwndTC)));
  375. return TRUE;
  376. }
  377. else
  378. {
  379. ASSERT(!g_fAnsiAPIs);
  380. ASSERT(!IsWindowUnicode(hwndTC));
  381. return FALSE;
  382. }
  383. }
  384. //----------------------------------------------------------------
  385. HWND WINAPI W_CreateControlWindow (
  386. DWORD dwStyleEx,
  387. DWORD dwStyle,
  388. CCTLWINTYPE wt,
  389. LPCWSTR pwszName,
  390. int x, int y, int width, int height,
  391. HWND parent,
  392. HMENU menu,
  393. HINSTANCE inst,
  394. LPVOID lParam
  395. )
  396. {
  397. ASSERT(W_ListView == wt || W_TreeView == wt || W_TabCtrl == wt);
  398. HWND hwnd;
  399. if (g_fAnsiAPIs)
  400. goto _AnsiAPI;
  401. hwnd = CreateWindowExW(dwStyleEx, rgwszClass[wt], pwszName, dwStyle, x, y, width, height, parent, menu, inst, lParam);
  402. if (NULL == hwnd)
  403. {
  404. if (ERROR_CALL_NOT_IMPLEMENTED != ::GetLastError())
  405. {
  406. ASSERT(0); // shouldn't be writing CreateWindow that fail
  407. return 0;
  408. }
  409. g_fAnsiAPIs = TRUE;
  410. _AnsiAPI:
  411. char sz[MAX_PATH*2];
  412. sz[0] = 0;
  413. WideCharToMultiByte(_CODEPAGE, 0, pwszName, -1, sz, sizeof(sz), 0, 0);
  414. hwnd = CreateWindowExA(dwStyleEx, rgszClass[wt], sz, dwStyle, x, y, width, height, parent, menu, inst, lParam);
  415. }
  416. if (hwnd)
  417. {
  418. switch (wt)
  419. {
  420. case W_ListView:
  421. ListView_SetUnicodeFormat(hwnd, TRUE);
  422. if ( g_fAnsiAPIs )
  423. {
  424. g_fUnicodeListView = IsListViewUnicode(hwnd);
  425. ListView_SetUnicodeFormat(hwnd, g_fUnicodeListView); // ensure consistency
  426. }
  427. break;
  428. case W_TreeView:
  429. TreeView_SetUnicodeFormat(hwnd, TRUE);
  430. if ( g_fAnsiAPIs )
  431. {
  432. g_fUnicodeTreeView = IsTreeViewUnicode(hwnd);
  433. TreeView_SetUnicodeFormat(hwnd, g_fUnicodeTreeView); // ensure consistency
  434. }
  435. break;
  436. case W_TabCtrl:
  437. TabCtrl_SetUnicodeFormat(hwnd, TRUE);
  438. if ( g_fAnsiAPIs )
  439. {
  440. g_fUnicodeTabCtrl = IsTabCtrlUnicode(hwnd);
  441. TabCtrl_SetUnicodeFormat(hwnd, g_fUnicodeTabCtrl); // ensure consistency
  442. }
  443. break;
  444. }
  445. }
  446. #ifdef _DEBUG
  447. else
  448. {
  449. ASSERT(0);
  450. DWORD dwerr = ::GetLastError();
  451. }
  452. #endif
  453. return hwnd;
  454. }
  455. // use this for common controls on a dialog
  456. BOOL WINAPI W_EnableUnicode(HWND hwnd, CCTLWINTYPE wt)
  457. {
  458. if (IsWindowUnicode(hwnd))
  459. {
  460. switch (wt)
  461. {
  462. case W_ListView:
  463. ListView_SetUnicodeFormat(hwnd, TRUE);
  464. g_fUnicodeListView = TRUE;
  465. break;
  466. case W_TreeView:
  467. TreeView_SetUnicodeFormat(hwnd, TRUE);
  468. g_fUnicodeTreeView = TRUE;
  469. break;
  470. case W_TabCtrl:
  471. TabCtrl_SetUnicodeFormat(hwnd, TRUE);
  472. g_fUnicodeTabCtrl = TRUE;
  473. break;
  474. default: ASSERT(0); break;
  475. };
  476. return TRUE;
  477. }
  478. //else not unicode window
  479. switch (wt)
  480. {
  481. case W_ListView:
  482. if (g_fUnicodeListView)
  483. {
  484. ListView_SetUnicodeFormat(hwnd, TRUE);
  485. g_fUnicodeListView = IsListViewUnicode(hwnd);
  486. ListView_SetUnicodeFormat(hwnd, g_fUnicodeListView); // ensure consistency
  487. }
  488. return g_fUnicodeListView;
  489. break;
  490. case W_TreeView:
  491. if (g_fUnicodeTreeView)
  492. {
  493. TreeView_SetUnicodeFormat(hwnd, TRUE);
  494. g_fUnicodeTreeView = IsTreeViewUnicode(hwnd);
  495. TreeView_SetUnicodeFormat(hwnd, g_fUnicodeTreeView); // ensure consistency
  496. }
  497. return g_fUnicodeTreeView;
  498. break;
  499. case W_TabCtrl:
  500. if (g_fUnicodeTabCtrl)
  501. {
  502. TabCtrl_SetUnicodeFormat(hwnd, TRUE);
  503. g_fUnicodeTabCtrl = IsTabCtrlUnicode(hwnd);
  504. TabCtrl_SetUnicodeFormat(hwnd, g_fUnicodeTabCtrl); // ensure consistency
  505. }
  506. return g_fUnicodeTabCtrl;
  507. break;
  508. }
  509. return FALSE;
  510. }
  511. //================================================================
  512. // List View
  513. //================================================================
  514. BOOL IsListViewUnicode(HWND hwnd)
  515. {
  516. LV_ITEMW lvi;
  517. int ii; // item index
  518. BOOL fRet;
  519. ZeroMemory(&lvi, sizeof(lvi));
  520. lvi.mask = LVIF_TEXT;
  521. lvi.pszText = L" ";
  522. lvi.cchTextMax = 2;
  523. ii = (int)SendMessageA(hwnd, LVM_INSERTITEMW, 0, (LPARAM)&lvi);
  524. if (-1 == ii)
  525. return FALSE;
  526. // LVM_INSERTITEMW succeeds even in ANSI (unlike the tree view), so we have
  527. // to try LVM_GETITEMW to determine if we've really got Unicode support.
  528. WCHAR wsz[4];
  529. lvi.mask = LVIF_TEXT;
  530. lvi.iItem = ii;
  531. lvi.pszText = wsz;
  532. lvi.cchTextMax = 4;
  533. fRet = SendMessageA(hwnd, LVM_GETITEMW, 0, (LPARAM)&lvi)!=NULL;
  534. // clean up the test item we added
  535. SendMessageA(hwnd, LVM_DELETEITEM, (WPARAM)ii, 0);
  536. return fRet;
  537. }
  538. //----------------------------------------------------------------
  539. void WINAPI LV_ITEMAFromW (LV_ITEMA * pA, const LV_ITEMW *pW, BOOL fConvertString = TRUE)
  540. {
  541. pA->mask = pW->mask;
  542. pA->iItem = pW->iItem;
  543. pA->iSubItem = pW->iSubItem;
  544. pA->state = pW->state;
  545. pA->stateMask = pW->stateMask;
  546. if (fConvertString && pW->pszText && pA->pszText)
  547. WideCharToMultiByte(_Module.GetCodePage(), 0, pW->pszText, -1, pA->pszText, pA->cchTextMax, 0, 0);
  548. pA->iImage = pW->iImage;
  549. pA->lParam = pW->lParam;
  550. pA->iIndent = pW->iIndent;
  551. }
  552. //----------------------------------------------------------------
  553. void WINAPI LV_ITEMWFromA (const LV_ITEMA * pA, LV_ITEMW *pW, BOOL fConvertString = TRUE)
  554. {
  555. pW->mask = pA->mask;
  556. pW->iItem = pA->iItem;
  557. pW->iSubItem = pA->iSubItem;
  558. pW->state = pA->state;
  559. pW->stateMask = pA->stateMask;
  560. if (fConvertString && pW->pszText && pA->pszText)
  561. MultiByteToWideChar(_Module.GetCodePage(), 0, pA->pszText, -1, pW->pszText, pW->cchTextMax);
  562. pW->iImage = pA->iImage;
  563. pW->lParam = pA->lParam;
  564. pW->iIndent = pA->iIndent;
  565. }
  566. //----------------------------------------------------------------
  567. BOOL WINAPI ListView_ItemHelper(HWND hwnd, LV_ITEMW * pitem, UINT MsgW, UINT MsgA, BOOL fConvertIn, BOOL fConvertOut)
  568. {
  569. ASSERT(!g_fUnicodeListView);
  570. // if no text, all the rest is the same
  571. if (0 == (pitem->mask & LVIF_TEXT) || (LPSTR_TEXTCALLBACKW == pitem->pszText))
  572. return SendMessageA(hwnd, MsgA, 0, (LPARAM)pitem)!=NULL;
  573. BOOL fRet;
  574. LV_ITEMA item;
  575. char sz[MAX_ITEM_STRING+1];
  576. item.pszText = sz;
  577. item.cchTextMax = MAX_ITEM_STRING;
  578. LV_ITEMAFromW(&item, pitem, fConvertIn);
  579. fRet = SendMessageA(hwnd, MsgA, 0, (LPARAM)&item)!=NULL;
  580. if (fRet)
  581. LV_ITEMWFromA(&item, pitem, fConvertOut);
  582. return fRet;
  583. }
  584. //----------------------------------------------------------------
  585. BOOL WINAPI W_ListView_GetItem_fn(HWND hwnd, LV_ITEMW * pitem)
  586. {
  587. if (g_fUnicodeListView)
  588. return SendMessage(hwnd, LVM_GETITEMW, 0, (LPARAM)pitem)!=NULL;
  589. ASSERT(sizeof(LV_ITEMA) == sizeof(LV_ITEMW));
  590. if (!((pitem->mask & LVIF_TEXT) && pitem->pszText && (LPSTR_TEXTCALLBACKW != pitem->pszText)))
  591. return SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)pitem)!=NULL;
  592. return ListView_ItemHelper(hwnd, pitem, LVM_GETITEMW, LVM_GETITEMA, FALSE, TRUE);
  593. }
  594. //----------------------------------------------------------------
  595. BOOL WINAPI W_ListView_SetItem_fn(HWND hwnd, LV_ITEMW * pitem)
  596. {
  597. if (g_fUnicodeListView)
  598. return SendMessage(hwnd, LVM_SETITEMW, 0, (LPARAM)pitem)!=NULL;
  599. ASSERT(sizeof(LV_ITEMA) == sizeof(LV_ITEMW));
  600. if (!((pitem->mask & LVIF_TEXT) && pitem->pszText && (LPSTR_TEXTCALLBACKW != pitem->pszText)))
  601. return SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)pitem)!=NULL;
  602. return ListView_ItemHelper(hwnd, pitem, LVM_SETITEMW, LVM_SETITEMA, TRUE, FALSE)!=NULL;
  603. }
  604. //----------------------------------------------------------------
  605. int WINAPI W_ListView_InsertItem_fn(HWND hwnd, LV_ITEMW * pitem)
  606. {
  607. if (g_fUnicodeListView)
  608. return (int)SendMessage(hwnd, LVM_INSERTITEMW, 0, (LPARAM)pitem);
  609. ASSERT(sizeof(LV_ITEMA) == sizeof(LV_ITEMW));
  610. if (!((pitem->mask & LVIF_TEXT) && pitem->pszText && (LPSTR_TEXTCALLBACKW != pitem->pszText)))
  611. return (int)SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)pitem);
  612. return ListView_ItemHelper(hwnd, pitem, LVM_INSERTITEMW, LVM_INSERTITEMA, TRUE, FALSE);
  613. }
  614. //----------------------------------------------------------------
  615. int WINAPI W_ListView_FindItem_fn(HWND hwnd, int iStart, LV_FINDINFOW * plvfi)
  616. {
  617. ASSERT(0); //NOT IMPLEMENTED
  618. return -1;
  619. }
  620. //----------------------------------------------------------------
  621. int WINAPI W_ListView_GetStringWidth_fn(HWND hwndLV, LPCWSTR psz)
  622. {
  623. ASSERT(0); //NOT IMPLEMENTED
  624. return 0;
  625. }
  626. //----------------------------------------------------------------
  627. HWND WINAPI W_ListView_EditLabel_fn(HWND hwnd, int i)
  628. {
  629. return (HWND)SendMessage(hwnd, g_fUnicodeListView?LVM_EDITLABELW:LVM_EDITLABELA, (WPARAM)(int)(i), 0L);
  630. }
  631. //----------------------------------------------------------------
  632. BOOL WINAPI W_ListView_GetColumn_fn(HWND hwnd, int iCol, LV_COLUMNW * pcol)
  633. {
  634. ASSERT(0); // NYI
  635. return FALSE;
  636. }
  637. //----------------------------------------------------------------
  638. BOOL WINAPI W_ListView_SetColumn_fn(HWND hwnd, int iCol, LV_COLUMNW * pcol)
  639. {
  640. ASSERT(0); // NYI
  641. return FALSE;
  642. }
  643. //----------------------------------------------------------------
  644. int WINAPI W_ListView_InsertColumn_fn(HWND hwnd, int iCol, LV_COLUMNW * pcol)
  645. {
  646. if (g_fUnicodeListView)
  647. return (int)SendMessage(hwnd, LVM_INSERTCOLUMNW, (WPARAM)iCol, (LPARAM)pcol);
  648. ASSERT(sizeof(LV_COLUMNA)==sizeof(LV_COLUMNW));
  649. if (0 == (pcol->mask & LVIF_TEXT) || (LPSTR_TEXTCALLBACKW == pcol->pszText))
  650. return (int)SendMessageA(hwnd, LVM_INSERTCOLUMNA, (WPARAM)iCol, (LPARAM)pcol);
  651. LV_COLUMNA lvc;
  652. char sz[MAX_ITEM_STRING+1];
  653. memcpy(&lvc, pcol, sizeof(LV_COLUMNA));
  654. lvc.pszText = sz;
  655. lvc.cchTextMax = WideCharToMultiByte(_CODEPAGE, 0, pcol->pszText, -1, sz, MAX_ITEM_STRING, 0, 0);
  656. return (int)SendMessageA(hwnd, LVM_INSERTCOLUMNA, (WPARAM)iCol, (LPARAM)&lvc);
  657. }
  658. //----------------------------------------------------------------
  659. void WINAPI W_ListView_GetItemText_fn(HWND hwndLV, int i, int iSubItem_, LPWSTR pszText_, int cchTextMax_)
  660. {
  661. if (g_fUnicodeListView)
  662. {
  663. LV_ITEMW lvi;
  664. lvi.iSubItem = iSubItem_;
  665. lvi.cchTextMax = cchTextMax_;
  666. lvi.pszText = pszText_;
  667. SendMessage(hwndLV, LVM_GETITEMTEXTW, i, (LPARAM)&lvi);
  668. }
  669. else
  670. {
  671. int i2;
  672. LV_ITEMA lvi;
  673. char sz[MAX_ITEM_STRING+1];
  674. lvi.iSubItem = iSubItem_;
  675. lvi.cchTextMax = MAX_ITEM_STRING;
  676. lvi.pszText = sz;
  677. i2 = (int)SendMessage(hwndLV, LVM_GETITEMTEXTA, i, (LPARAM)&lvi);
  678. if (i2)
  679. {
  680. MultiByteToWideChar(_Module.GetCodePage(), 0, sz, -1, pszText_, cchTextMax_);
  681. }
  682. else
  683. {
  684. if (pszText_)
  685. *pszText_ = 0;
  686. }
  687. }
  688. }
  689. //----------------------------------------------------------------
  690. void WINAPI W_ListView_SetItemText_fn(HWND hwndLV, int i, int iSubItem_, LPCWSTR pszText_)
  691. {
  692. if (g_fUnicodeListView)
  693. {
  694. LV_ITEMW lvi;
  695. lvi.iSubItem = iSubItem_;
  696. lvi.pszText = (LPWSTR)pszText_;
  697. SendMessage(hwndLV, LVM_SETITEMTEXTW, i, (LPARAM)&lvi);
  698. }
  699. else
  700. {
  701. LV_ITEMA lvi;
  702. char sz[MAX_ITEM_STRING+1];
  703. lvi.iSubItem = iSubItem_;
  704. if (pszText_ && (LPSTR_TEXTCALLBACKW != pszText_))
  705. {
  706. WideCharToMultiByte(CP_ACP, 0, pszText_, -1, sz, MAX_ITEM_STRING, 0, 0);
  707. lvi.pszText = sz;
  708. }
  709. else
  710. lvi.pszText = (PSTR)pszText_;
  711. SendMessage(hwndLV, LVM_SETITEMTEXTA, i, (LPARAM)&lvi);
  712. }
  713. }
  714. //----------------------------------------------------------------
  715. BOOL WINAPI W_ListView_GetISearchString_fn(HWND hwndLV, LPWSTR lpsz)
  716. {
  717. if (g_fUnicodeListView)
  718. return SendMessage(hwndLV, LVM_GETISEARCHSTRINGW, 0, (LPARAM)(LPTSTR)lpsz)!=0;
  719. ASSERT(0); // NYI
  720. return FALSE;
  721. }
  722. //----------------------------------------------------------------
  723. BOOL WINAPI W_ListView_SetBkImage_fn(HWND hwnd, LPLVBKIMAGEW plvbki)
  724. {
  725. if (g_fUnicodeListView)
  726. return SendMessage(hwnd, LVM_SETBKIMAGEW, 0, (LPARAM)plvbki)!=0;
  727. ASSERT(0); // NYI
  728. return FALSE;
  729. }
  730. //----------------------------------------------------------------
  731. BOOL WINAPI W_ListView_GetBkImage_fn(HWND hwnd, LPLVBKIMAGEW plvbki)
  732. {
  733. if (g_fUnicodeListView)
  734. return SendMessage(hwnd, LVM_GETBKIMAGEW, 0, (LPARAM)plvbki)!=0;
  735. ASSERT(0); // NYI
  736. return FALSE;
  737. }
  738. //================================================================
  739. // Tree View
  740. //================================================================
  741. BOOL IsTreeViewUnicode(HWND hwnd)
  742. {
  743. TV_INSERTSTRUCTW tvis;
  744. ZeroMemory(&tvis, sizeof(tvis));
  745. tvis.hParent = TVI_ROOT;
  746. tvis.hInsertAfter = TVI_FIRST;
  747. tvis.item.mask = LVIF_TEXT;
  748. tvis.item.pszText = L" ";
  749. tvis.item.cchTextMax = 2;
  750. HTREEITEM hi = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
  751. if (NULL == hi)
  752. return FALSE;
  753. // if here, the insert succeeded
  754. // delete the item we added
  755. SendMessageA(hwnd, TVM_DELETEITEM, 0, (LPARAM)hi);
  756. return TRUE;
  757. }
  758. //----------------------------------------------------------------
  759. HTREEITEM WINAPI W_TreeView_InsertItem_fn(HWND hwnd, LPTV_INSERTSTRUCTW lpis)
  760. {
  761. if (g_fUnicodeTreeView)
  762. return (HTREEITEM)SendMessage(hwnd, TVM_INSERTITEMW, 0, (LPARAM)lpis);
  763. ASSERT(sizeof(TVINSERTSTRUCTA)==sizeof(TVINSERTSTRUCTW));
  764. if (!((lpis->item.mask & TVIF_TEXT) && lpis->item.pszText && (LPSTR_TEXTCALLBACKW != lpis->item.pszText)))
  765. return (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)lpis);
  766. HTREEITEM htitem;
  767. TVINSERTSTRUCTA tvisA;
  768. memcpy(&tvisA, lpis, sizeof(TVINSERTSTRUCTA));
  769. tvisA.item.cchTextMax = 1 + lstrlenW(lpis->item.pszText);
  770. tvisA.item.pszText = (PSTR)Malloc(tvisA.item.cchTextMax);
  771. if (NULL != tvisA.item.pszText)
  772. tvisA.item.cchTextMax = WideCharToMultiByte(_Module.GetCodePage(), 0, lpis->item.pszText, -1, tvisA.item.pszText, tvisA.item.cchTextMax, 0, 0);
  773. else
  774. tvisA.item.cchTextMax = 0;
  775. htitem = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&tvisA);
  776. if (tvisA.item.pszText)
  777. Free(tvisA.item.pszText);
  778. return htitem;
  779. }
  780. //----------------------------------------------------------------
  781. BOOL WINAPI W_TreeView_GetItem_fn(HWND hwnd, TV_ITEMW * pitem)
  782. {
  783. if (g_fUnicodeTreeView)
  784. return SendMessage(hwnd, TVM_GETITEMW, 0, (LPARAM)pitem)!=0;
  785. BOOL fRet = SendMessageA(hwnd, TVM_GETITEMA, 0, (LPARAM)pitem)!=0;
  786. if (fRet && (pitem->mask & TVIF_TEXT) && pitem->pszText && (LPSTR_TEXTCALLBACKW != pitem->pszText))
  787. {
  788. int cch = lstrlen((PSTR)pitem->pszText);
  789. PSTR psz = (PSTR)Malloc(cch+1);
  790. strcpy(psz, (PSTR)pitem->pszText);
  791. MultiByteToWideChar(_Module.GetCodePage(), 0, psz, -1, pitem->pszText, pitem->cchTextMax);
  792. Free(psz);
  793. }
  794. return fRet;
  795. }
  796. //----------------------------------------------------------------
  797. BOOL WINAPI W_TreeView_SetItem_fn(HWND hwnd, TV_ITEMW * pitem)
  798. {
  799. if (g_fUnicodeTreeView)
  800. return SendMessage(hwnd, TVM_SETITEMW, 0, (LPARAM)pitem)!=0;
  801. ASSERT(sizeof(TV_ITEMA)==sizeof(TV_ITEMW));
  802. if (0 == (pitem->mask & TVIF_TEXT) || (LPSTR_TEXTCALLBACKW == pitem->pszText))
  803. return SendMessageA(hwnd, TVM_SETITEMA, 0, (LPARAM)pitem)!=0;
  804. BOOL fRet;
  805. TV_ITEMA tviA;
  806. memcpy(&tviA, pitem, sizeof(TV_ITEMA));
  807. if (tviA.pszText)
  808. {
  809. tviA.cchTextMax = 1 + lstrlenW(pitem->pszText);
  810. tviA.pszText = (PSTR)Malloc(tviA.cchTextMax);
  811. if (NULL != tviA.pszText)
  812. tviA.cchTextMax = WideCharToMultiByte(_Module.GetCodePage(), 0, pitem->pszText, -1, tviA.pszText, tviA.cchTextMax, 0, 0);
  813. else
  814. tviA.cchTextMax = 0;
  815. }
  816. fRet = SendMessageA(hwnd, TVM_SETITEMA, 0, (LPARAM)&tviA)!=0;
  817. if (tviA.pszText)
  818. Free(tviA.pszText);
  819. return fRet;
  820. }
  821. //----------------------------------------------------------------
  822. HWND WINAPI W_TreeView_EditLabel_fn(HWND hwnd, HTREEITEM hitem)
  823. {
  824. return (HWND)SendMessage(hwnd, g_fUnicodeTreeView?TVM_EDITLABELW:TVM_EDITLABELA, 0, (LPARAM)(HTREEITEM)(hitem));
  825. }
  826. //----------------------------------------------------------------
  827. BOOL WINAPI W_TreeView_GetISearchString_fn(HWND hwndTV, LPWSTR lpsz)
  828. {
  829. if (g_fUnicodeTreeView)
  830. return SendMessage(hwndTV, TVM_GETISEARCHSTRINGW, 0, (LPARAM)(LPTSTR)lpsz)!=0;
  831. ASSERT(0); // NYI
  832. return FALSE;
  833. }
  834. //================================================================
  835. // Tab Control
  836. //================================================================
  837. BOOL IsTabCtrlUnicode(HWND hwnd)
  838. {
  839. int ii, jj;
  840. TC_ITEMW tci;
  841. ZeroMemory(&tci, sizeof(tci));
  842. tci.mask = TCIF_TEXT;
  843. tci.pszText = L"X";
  844. tci.cchTextMax = 2;
  845. ii = (int)(DWORD)SendMessageA(hwnd, TCM_INSERTITEMW, 0, (LPARAM)&tci);
  846. if (-1 == ii)
  847. return FALSE;
  848. ZeroMemory(&tci, sizeof(tci));
  849. tci.mask = TCIF_TEXT;
  850. tci.pszText = L"Y";
  851. tci.cchTextMax = 2;
  852. jj = (int)(DWORD)SendMessageA(hwnd, TCM_INSERTITEMW, 0, (LPARAM)&tci);
  853. if (-1 == jj || (jj == 0) )
  854. {
  855. if (ii >= 0)
  856. SendMessageA(hwnd, TCM_DELETEITEM, (WPARAM)ii, 0);
  857. if (jj >= 0)
  858. SendMessageA(hwnd, TCM_DELETEITEM, (WPARAM)jj, 0);
  859. return FALSE;
  860. }
  861. //
  862. // might have to try to get the item back like we must do the list view
  863. // delete the item we added
  864. SendMessageA(hwnd, TCM_DELETEITEM, (WPARAM)ii, 0);
  865. SendMessageA(hwnd, TCM_DELETEITEM, (WPARAM)jj, 0);
  866. return TRUE;
  867. }
  868. //----------------------------------------------------------------
  869. BOOL WINAPI W_TabCtrl_GetItem_fn(HWND hwnd, int iItem, TC_ITEMW * pitem)
  870. {
  871. if (g_fUnicodeTabCtrl)
  872. return SendMessage(hwnd, TCM_GETITEMW, (WPARAM)iItem, (LPARAM)pitem)!=0;
  873. if (0 == (TCIF_TEXT & pitem->mask))
  874. return SendMessageA(hwnd, TCM_GETITEMA, (WPARAM)iItem, (LPARAM)pitem)!=0;
  875. BOOL fRet = SendMessageA(hwnd, TCM_GETITEMA, 0, (LPARAM)pitem)!=0;
  876. if (fRet && (pitem->mask & TCIF_TEXT) && pitem->pszText && (LPSTR_TEXTCALLBACKW != pitem->pszText))
  877. {
  878. int cch = lstrlen((PSTR)pitem->pszText);
  879. PSTR psz = (PSTR)_alloca(cch+1);
  880. strcpy(psz, (PSTR)pitem->pszText);
  881. MultiByteToWideChar(_Module.GetCodePage(), 0, psz, -1, pitem->pszText, pitem->cchTextMax);
  882. }
  883. return fRet;
  884. }
  885. //----------------------------------------------------------------
  886. BOOL WINAPI W_TabCtrl_SetItem_fn(HWND hwnd, int iItem, TC_ITEMW * pitem)
  887. {
  888. if (g_fUnicodeTabCtrl)
  889. return SendMessage(hwnd, TCM_SETITEMW, (WPARAM)iItem, (LPARAM)pitem)!=0;
  890. if (0 == (TCIF_TEXT & pitem->mask))
  891. return SendMessageA(hwnd, TCM_SETITEMA, (WPARAM)iItem, (LPARAM)pitem)!=0;
  892. ASSERT(pitem->pszText);
  893. int cch = lstrlenW(pitem->pszText)*W_cbchMaxAcp() + 1;
  894. PSTR psz = (PSTR)_alloca(cch);
  895. WideCharToMultiByte(_Module.GetCodePage(), 0, pitem->pszText, -1, psz, cch, 0, 0);
  896. TC_ITEMA item;
  897. ASSERT(sizeof(TC_ITEMA)==sizeof(TC_ITEMW));
  898. memcpy(&item, pitem, sizeof(TC_ITEMA));
  899. item.pszText = psz;
  900. item.cchTextMax = cch;
  901. return SendMessageA(hwnd, TCM_SETITEMA, (WPARAM)iItem, (LPARAM)&item)!=0;
  902. }
  903. //----------------------------------------------------------------
  904. int WINAPI W_TabCtrl_InsertItem_fn(HWND hwnd, int iItem, TC_ITEMW * pitem)
  905. {
  906. if (g_fUnicodeTabCtrl)
  907. return (int)SendMessage(hwnd, TCM_INSERTITEMW, (WPARAM)iItem, (LPARAM)pitem);
  908. if (0 == (TCIF_TEXT & pitem->mask))
  909. return (int)SendMessageA(hwnd, TCM_INSERTITEMA, (WPARAM)iItem, (LPARAM)pitem);
  910. ASSERT(pitem->pszText);
  911. int cch = lstrlenW(pitem->pszText)*W_cbchMaxAcp() + 1;
  912. PSTR psz = (PSTR)_alloca(cch);
  913. WideCharToMultiByte(_CODEPAGE, 0, pitem->pszText, -1, psz, cch, 0, 0);
  914. TC_ITEMA item;
  915. ASSERT(sizeof(TC_ITEMA)==sizeof(TC_ITEMW));
  916. memcpy(&item, pitem, sizeof(TC_ITEMA));
  917. item.pszText = psz;
  918. item.cchTextMax = cch;
  919. return (int)SendMessageA(hwnd, TCM_INSERTITEMA, (WPARAM)iItem, (LPARAM)&item);
  920. }