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.

689 lines
20 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /***************************************************************************/
  4. /****************** Basic Class Dialog Handlers ****************************/
  5. /***************************************************************************/
  6. BOOL fFillListBoxFromSzList (HWND, WORD, SZ);
  7. BOOL fFreeListBoxEntries (HWND, WORD);
  8. BOOL fUpdateStatus(HWND, WORD, INT);
  9. SZ szGetSzListFromListBox (HWND, WORD);
  10. /*
  11. ** Author:
  12. ** Sunil Pai, 8/21/91, Adapted from Win3.1 setup code.
  13. **
  14. ** Purpose:
  15. ** Dual Listbox Dialog procedure for templates with two listboxes
  16. ** exchanging selection items. This is implemented with owner draw
  17. ** list boxes.
  18. **
  19. ** Control IDs:
  20. ** The Listbox controls must have the id IDC_LIST1 and IDC_LIST2.
  21. ** Pushbuttons recognized are IDC_O, IDC_C, IDC_M, IDC_H, IDC_X, and IDC_B.
  22. ** In addition to these the following IDs are processed:
  23. ** - IDC_A: To move a selected item(s) in listbox1 to listbox2
  24. ** - IDC_R: To move a selected item(s) in listbox2 to listbox1
  25. ** - IDC_S: To move all items in listbox1 to listbox2
  26. **
  27. ** Initialization:
  28. ** The symbol $(ListItemsIn) is a list of strings to insert into the
  29. ** listbox 1. The symbol $(ListItemOut) is a list of strings to insert
  30. ** into listbox 2. Items can be added to listbox2 or removed to
  31. ** listbox1. All items can be shifted to listbox2 using the Add All
  32. ** button.
  33. **
  34. ** The $(ListItemsIn) and $(ListItemsOut can be:
  35. **
  36. ** a) A Simple List:
  37. ** {$(ListElem1), $(ListElem2)...}
  38. **
  39. ** b) A Compound List:
  40. **
  41. ** { {$(ListItem1Data), $(ListItem1Aux1), $(ListItem1Aux2)...},
  42. ** {$(ListItem2Data), $(ListItem2Aux1), $(ListItem2Aux2)...},
  43. ** ...
  44. ** }
  45. **
  46. ** In the case of a compound list the $(ListItemnData) field is displayed
  47. ** in the listbox. When any item is selected the selection displays the
  48. ** fields in the selection in the status fields in the dialog.
  49. ** - ListItemnData is displayed in the IDC_TEXT1 field if present
  50. ** - ListItemnAux1 is displayed in the IDC_TEXT2 field if present
  51. ** - ListItemnAux2 is displayed in the IDC_TEXT3 field if present
  52. ** ...
  53. **
  54. ** Termination:
  55. ** The items in listbox2 are returned in
  56. ** $(ListItemsOut). The id of the Pushbutton (eg IDC_C) which caused
  57. ** termination is converted to a string and stored in the symbol
  58. **
  59. *****************************************************************************/
  60. INT_PTR APIENTRY FGstDualDlgProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  61. {
  62. CHP rgchNum[10];
  63. SZ szList;
  64. INT i, nCount;
  65. WORD idc, idcSrc, idcDst;
  66. LONG lItem;
  67. RGSZ rgszItem;
  68. PSZ pszItem;
  69. switch (wMsg)
  70. {
  71. case WM_INITDIALOG:
  72. AssertDataSeg();
  73. if( wMsg == WM_INITDIALOG ) {
  74. FCenterDialogOnDesktop(hdlg);
  75. }
  76. // Find the List Items In and initialise the first list box
  77. if ((szList = SzFindSymbolValueInSymTab("ListItemsIn")) == (SZ)NULL)
  78. {
  79. Assert(fFalse);
  80. return(fTrue);
  81. }
  82. if(!fFillListBoxFromSzList (hdlg, IDC_LIST1, szList))
  83. {
  84. EvalAssert(fFreeListBoxEntries (hdlg, IDC_LIST1));
  85. Assert(fFalse);
  86. return(fTrue);
  87. }
  88. // Find the List Items Out and initialise the second list box
  89. if ((szList = SzFindSymbolValueInSymTab("ListItemsOut")) == (SZ)NULL)
  90. {
  91. Assert(fFalse);
  92. return(fTrue);
  93. }
  94. if(!fFillListBoxFromSzList (hdlg, IDC_LIST2, szList))
  95. {
  96. EvalAssert(fFreeListBoxEntries (hdlg, IDC_LIST1));
  97. EvalAssert(fFreeListBoxEntries (hdlg, IDC_LIST2));
  98. Assert(fFalse);
  99. return(fTrue);
  100. }
  101. // The following are done in the windows code, but I believe some of
  102. // them restrict us when we are building a general procedure like this
  103. // Initialise state of controls in the dialog
  104. // SendMessage(GetDlgItem(hdlg, IDC_LIST1), LB_SETCURSEL, 0, 0L);
  105. // EvalAssert(fUpdateStatus(hdlg, IDC_LIST1, 0));
  106. // EnableWindow(GetDlgItem(hdlg,IDC_C), fFalse);
  107. EnableWindow(GetDlgItem(hdlg,IDC_A), fFalse);
  108. EnableWindow(GetDlgItem(hdlg,IDC_R), fFalse);
  109. // SetFocus(GetDlgItem(hdlg, IDC_S));
  110. // SendMessage(hdlg, DM_SETDEFID, IDC_S, 0L);
  111. //
  112. // Return
  113. //
  114. return(fTrue);
  115. case STF_REINITDIALOG:
  116. return(fTrue);
  117. // case STF_DLG_ACTIVATE:
  118. // case WM_MOUSEACTIVATE:
  119. // if (FActiveStackTop())
  120. // break;
  121. // EvalAssert(FInactivateHelp());
  122. // SetWindowPos(hdlg, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  123. // /* fall through */
  124. // case STF_UILIB_ACTIVATE:
  125. // EvalAssert(FActivateStackTop());
  126. // return(fTrue);
  127. case WM_CLOSE:
  128. PostMessage(
  129. hdlg,
  130. WM_COMMAND,
  131. MAKELONG(IDC_X, BN_CLICKED),
  132. 0L
  133. );
  134. return(fTrue);
  135. case WM_COMMAND:
  136. switch(idc = LOWORD(wParam))
  137. {
  138. case IDC_LIST1:
  139. case IDC_LIST2:
  140. nCount = (INT)SendDlgItemMessage(hdlg, idc, LB_GETSELCOUNT, 0, 0L);
  141. EnableWindow(GetDlgItem(hdlg, (idc == IDC_LIST1) ? IDC_A : IDC_R),
  142. nCount ? fTrue : fFalse
  143. );
  144. switch (HIWORD(wParam))
  145. {
  146. case LBN_SELCHANGE:
  147. i = (INT)SendDlgItemMessage(hdlg, idc, LB_GETCURSEL, 0, 0L);
  148. if (i >= 0)
  149. EvalAssert(fUpdateStatus(hdlg, idc, i));
  150. break;
  151. default:
  152. return fFalse;
  153. }
  154. break;
  155. case IDC_A:
  156. case IDC_R:
  157. {
  158. #define MAXSEL 500 // if memory allocation fails
  159. PINT sel,sels;
  160. INT lowmemsels[MAXSEL];
  161. if (idc == IDC_A)
  162. {
  163. idcSrc = IDC_LIST1;
  164. idcDst = IDC_LIST2;
  165. }
  166. else
  167. {
  168. idcSrc = IDC_LIST2;
  169. idcDst = IDC_LIST1;
  170. }
  171. nCount = (INT)SendDlgItemMessage(hdlg,idcSrc,LB_GETSELCOUNT,0,0);
  172. if(nCount <= 0) {
  173. break;
  174. }
  175. if(sels = SAlloc(nCount*sizeof(INT))) {
  176. sel = sels;
  177. } else {
  178. sel = lowmemsels;
  179. nCount = MAXSEL;
  180. }
  181. nCount = (INT)SendDlgItemMessage(hdlg,
  182. idcSrc,
  183. LB_GETSELITEMS,
  184. nCount,
  185. (LPARAM)sel
  186. );
  187. if(nCount <= 0) {
  188. if(sels) {
  189. SFree(sels);
  190. sels = NULL;
  191. }
  192. break;
  193. }
  194. // dup everything over to the other list
  195. SendDlgItemMessage(hdlg, idcSrc, WM_SETREDRAW, fFalse, 0L);
  196. SendDlgItemMessage(hdlg, idcDst, WM_SETREDRAW, fFalse, 0L);
  197. for (i = 0; i < nCount; i++)
  198. {
  199. SendDlgItemMessage(hdlg, idcSrc, LB_GETTEXT, sel[i],
  200. (LPARAM)&lItem);
  201. SendDlgItemMessage(hdlg, idcDst, LB_ADDSTRING, 0,
  202. (LPARAM)lItem);
  203. }
  204. SendDlgItemMessage(hdlg, idcDst, WM_SETREDRAW, fTrue, 0L);
  205. InvalidateRect(GetDlgItem(hdlg, idcDst), NULL, fTrue);
  206. // and delete the source stuff (backwards to get order right)
  207. for (i = nCount - 1; i >= 0; i--)
  208. SendDlgItemMessage(hdlg, idcSrc, LB_DELETESTRING,
  209. sel[i], 0L);
  210. SendDlgItemMessage(hdlg, idcSrc, WM_SETREDRAW, fTrue, 0L);
  211. InvalidateRect(GetDlgItem(hdlg, idcSrc), NULL, fTrue);
  212. if (idc == IDC_A)
  213. {
  214. if ((INT)SendDlgItemMessage(hdlg, IDC_LIST1,
  215. LB_GETCOUNT, 0, 0L) <= 0)
  216. {
  217. EnableWindow(GetDlgItem(hdlg,IDC_S),fFalse);
  218. }
  219. else
  220. EnableWindow(GetDlgItem(hdlg,IDC_S),fTrue);
  221. }
  222. else
  223. EnableWindow(GetDlgItem(hdlg,IDC_S),fTrue);
  224. if ((INT)SendDlgItemMessage(hdlg, IDC_LIST2,
  225. LB_GETCOUNT, 0, 0L) <= 0)
  226. {
  227. EnableWindow(GetDlgItem(hdlg,IDC_C),fFalse);
  228. SetFocus(GetDlgItem(hdlg, IDC_S));
  229. SendMessage(hdlg, DM_SETDEFID, IDC_S, 0L);
  230. }
  231. else
  232. {
  233. EnableWindow(GetDlgItem(hdlg,IDC_C),fTrue);
  234. SetFocus(GetDlgItem(hdlg, IDC_C));
  235. SendMessage(hdlg, DM_SETDEFID, IDC_C, 0L);
  236. }
  237. EnableWindow(GetDlgItem(hdlg,idc),fFalse);
  238. if(sels) {
  239. SFree(sels);
  240. sels = NULL;
  241. }
  242. return fFalse;
  243. }
  244. case IDC_S:
  245. nCount = (INT)SendDlgItemMessage(hdlg, IDC_LIST1, LB_GETCOUNT, 0, 0L);
  246. SendDlgItemMessage(hdlg, IDC_LIST2, WM_SETREDRAW, fFalse, 0L);
  247. for (i = 0; i < nCount; i++)
  248. {
  249. SendDlgItemMessage(hdlg, IDC_LIST1, LB_GETTEXT, i,
  250. (LPARAM)&lItem);
  251. SendDlgItemMessage(hdlg, IDC_LIST2, LB_ADDSTRING, 0,
  252. (LPARAM)lItem);
  253. }
  254. SendDlgItemMessage(hdlg, IDC_LIST1, LB_RESETCONTENT, 0, 0L);
  255. SendDlgItemMessage(hdlg, IDC_LIST2, WM_SETREDRAW, fTrue, 0L);
  256. InvalidateRect(GetDlgItem(hdlg, IDC_LIST2), NULL, fFalse);
  257. EnableWindow(GetDlgItem(hdlg,IDC_C),fTrue);
  258. EnableWindow(GetDlgItem(hdlg,IDC_A),fFalse);
  259. EnableWindow(GetDlgItem(hdlg,IDC_S),fFalse);
  260. SetFocus(GetDlgItem(hdlg, IDC_C));
  261. SendMessage(hdlg, DM_SETDEFID, IDC_C, 0L);
  262. return fFalse;
  263. case IDCANCEL:
  264. if (LOWORD(wParam) == IDCANCEL) {
  265. if (!GetDlgItem(hdlg, IDC_B) || HIWORD(GetKeyState(VK_CONTROL)) || HIWORD(GetKeyState(VK_SHIFT)) || HIWORD(GetKeyState(VK_MENU)))
  266. {
  267. break;
  268. }
  269. wParam = IDC_B;
  270. }
  271. case IDC_O:
  272. case IDC_C:
  273. case IDC_M:
  274. case IDC_B:
  275. case IDC_X:
  276. case IDC_BTN0:
  277. case IDC_BTN1: case IDC_BTN2: case IDC_BTN3:
  278. case IDC_BTN4: case IDC_BTN5: case IDC_BTN6:
  279. case IDC_BTN7: case IDC_BTN8: case IDC_BTN9:
  280. // Indicate the Button selected.
  281. _itoa((INT)wParam, rgchNum, 10);
  282. while (!FAddSymbolValueToSymTab("ButtonPressed", rgchNum))
  283. if (!FHandleOOM(hdlg))
  284. {
  285. DestroyWindow(GetParent(hdlg));
  286. return(fTrue);
  287. }
  288. // Fetch the list from first list and put it into ListItemsIn
  289. EvalAssert((szList = szGetSzListFromListBox(hdlg, IDC_LIST1)) != (SZ) NULL) ;
  290. while (!FAddSymbolValueToSymTab("ListItemsIn", szList))
  291. if (!FHandleOOM(hdlg))
  292. {
  293. DestroyWindow(GetParent(hdlg));
  294. return(fTrue);
  295. }
  296. // Fetch the list from second list and put it into ListItemsIn
  297. EvalAssert((szList = szGetSzListFromListBox(hdlg, IDC_LIST2)) != (SZ) NULL) ;
  298. while (!FAddSymbolValueToSymTab("ListItemsOut", szList))
  299. if (!FHandleOOM(hdlg))
  300. {
  301. DestroyWindow(GetParent(hdlg));
  302. return(fTrue);
  303. }
  304. PostMessage(GetParent(hdlg), (WORD)STF_UI_EVENT, 0, 0L);
  305. break;
  306. }
  307. break;
  308. case WM_COMPAREITEM:
  309. #define lpci ((LPCOMPAREITEMSTRUCT)lParam)
  310. return(CrcStringCompareI((SZ) *((RGSZ)lpci->itemData1),
  311. (SZ) *((RGSZ)lpci->itemData2)
  312. )
  313. );
  314. case WM_CHARTOITEM:
  315. {
  316. HWND hLB;
  317. INT i, j, nCount;
  318. LONG_PTR lItem;
  319. CHP chpBuf1[2], chpBuf2[2]; //used because we only have str cmp
  320. chpBuf1[1] = chpBuf2[1] = 0;
  321. chpBuf1[0] = (CHAR)LOWORD(wParam);
  322. // See if we need to process this character at all
  323. if (CrcStringCompareI(chpBuf1, " ") == crcSecondHigher)
  324. return -1; //tell windows to do its default key processing
  325. // Extract the list box handle and the index of the current
  326. // selection item
  327. hLB = (HWND)lParam;
  328. i = HIWORD(wParam);
  329. // Find the number of items in the list
  330. nCount = (INT)SendMessage(hLB, LB_GETCOUNT, 0, 0L);
  331. // From the next item downwards (circularly) look at all the
  332. // items to see if the char is the same as the first char in the
  333. // list box display item.
  334. for (j = 1; j < nCount; j++)
  335. {
  336. // get the data here
  337. SendMessage(hLB, LB_GETTEXT, (i + j) % nCount, (LPARAM)&lItem);
  338. // make a dummy string
  339. chpBuf2[0] = (*((RGSZ) lItem))[0];
  340. // do a case insensitive cmp of key and string
  341. if (CrcStringCompareI(chpBuf1, chpBuf2) == crcEqual)
  342. break;
  343. }
  344. return ((j == nCount) ? -2 : (i +j) % nCount);
  345. break;
  346. }
  347. case WM_DRAWITEM:
  348. #define lpDrawItem ((LPDRAWITEMSTRUCT)lParam)
  349. if (lpDrawItem->itemState & ODS_SELECTED) {
  350. SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  351. SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHT));
  352. }
  353. else{
  354. SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_WINDOWTEXT));
  355. SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_WINDOW));
  356. }
  357. if (lpDrawItem->itemID != (UINT)-1){
  358. if (pszItem = rgszItem = (RGSZ) lpDrawItem->itemData ) {
  359. ExtTextOut(lpDrawItem->hDC,
  360. lpDrawItem->rcItem.left,
  361. lpDrawItem->rcItem.top,
  362. ETO_OPAQUE, &lpDrawItem->rcItem,
  363. (SZ)(*pszItem), lstrlen((SZ)(*pszItem)), NULL);
  364. }
  365. if (lpDrawItem->itemState & ODS_FOCUS) {
  366. DrawFocusRect(lpDrawItem->hDC, &lpDrawItem->rcItem);
  367. }
  368. }
  369. else {
  370. RECT rc;
  371. if ( (lpDrawItem->itemAction & ODA_FOCUS) &&
  372. (SendMessage( GetDlgItem( hdlg, (int)wParam ), LB_GETITEMRECT, (WPARAM)0, (LPARAM)&rc ) != LB_ERR)
  373. ) {
  374. DrawFocusRect(lpDrawItem->hDC, &rc);
  375. }
  376. }
  377. return( fTrue );
  378. case STF_DESTROY_DLG:
  379. EvalAssert(fFreeListBoxEntries (hdlg, IDC_LIST1));
  380. EvalAssert(fFreeListBoxEntries (hdlg, IDC_LIST2));
  381. PostMessage(GetParent(hdlg), (WORD)STF_DUAL_DLG_DESTROYED, 0, 0L);
  382. DestroyWindow(hdlg);
  383. return(fTrue);
  384. }
  385. return(fFalse);
  386. }
  387. /*
  388. ** Author:
  389. ** Sunil Pai
  390. **
  391. ** Purpose:
  392. ** To fill an owner draw listbox from a simple/compound list
  393. **
  394. ** Arguments:
  395. ** hdlg: The handle to the dialog having the owner draw listbox
  396. ** idc: The ID of the listbox
  397. ** szList: A simple/compound list
  398. **
  399. ** Returns:
  400. ** fTrue: If Initialization succeeds.
  401. ** fFalse: If Initialization fails.
  402. **
  403. ****************************************************************************/
  404. BOOL fFillListBoxFromSzList (HWND hdlg, WORD idc, SZ szList)
  405. {
  406. RGSZ rgszList, rgszElement;
  407. PSZ pszList, pszElement;
  408. // List Value is {{...}, {...}, {...}...}
  409. //
  410. // 1. First construct a ptr array to all the list elements
  411. //
  412. while ((pszList = rgszList = RgszFromSzListValue(szList)) == (RGSZ)NULL)
  413. if (!FHandleOOM(hdlg))
  414. {
  415. DestroyWindow(GetParent(hdlg));
  416. return(fFalse);
  417. }
  418. // 2. Each array element in turn could be a list. So for each element
  419. // construct an ptr array and use this ptr array to initialise the
  420. // the list box elements.
  421. while (*pszList)
  422. {
  423. while ((pszElement = rgszElement = RgszFromSzListValue(*pszList)) == (RGSZ)NULL)
  424. if (!FHandleOOM(hdlg))
  425. {
  426. EvalAssert(FFreeRgsz(rgszList));
  427. DestroyWindow(GetParent(hdlg));
  428. return(fFalse);
  429. }
  430. SendDlgItemMessage(hdlg, idc, LB_ADDSTRING, 0,
  431. (LPARAM)pszElement);
  432. pszList++;
  433. }
  434. // 3. Free the list array and then exit.
  435. //
  436. EvalAssert(FFreeRgsz(rgszList));
  437. return(fTrue);
  438. }
  439. /*
  440. ** Author:
  441. ** Sunil Pai
  442. **
  443. ** Purpose:
  444. ** To extract the listbox elements from the listbox and free the memory
  445. ** used to build the elements.
  446. **
  447. ** Arguments:
  448. ** hdlg: The handle to the dialog having the owner draw listbox
  449. ** idc: The ID of the listbox
  450. **
  451. ** Returns:
  452. ** fTrue: If freeing succeeds.
  453. ** fFalse: If freeing fails.
  454. **
  455. ****************************************************************************/
  456. BOOL fFreeListBoxEntries (HWND hdlg, WORD idc)
  457. {
  458. INT i, nCount;
  459. LONG_PTR lItem;
  460. // 1. Get count of the entries in the list box
  461. //
  462. nCount = (INT)SendDlgItemMessage(hdlg, idc, LB_GETCOUNT, 0, 0L);
  463. // 2. For each element in the list box, fetch the element and free
  464. // the rgsz structure associated with it.
  465. for (i = 0; i < nCount; i++)
  466. {
  467. EvalAssert(SendDlgItemMessage(hdlg, idc, LB_GETTEXT,
  468. (WPARAM)i, (LPARAM)&lItem) != LB_ERR);
  469. EvalAssert(FFreeRgsz((RGSZ)lItem));
  470. }
  471. return(fTrue);
  472. }
  473. /*
  474. ** Author:
  475. ** Sunil Pai
  476. **
  477. ** Purpose:
  478. ** To fill the status fields whenever a selection is made in either of
  479. ** the list boxes
  480. **
  481. ** Arguments:
  482. ** hdlg: The handle to the dialog having the owner draw listbox
  483. ** idc: The ID of the listbox
  484. ** n: The selected elements position in the listbox
  485. **
  486. ** Returns:
  487. ** fTrue: If the Update succeeds.
  488. ** fFalse: If the Update fails.
  489. **
  490. ****************************************************************************/
  491. BOOL fUpdateStatus(HWND hdlg, WORD idc, INT n)
  492. {
  493. LONG_PTR lItem;
  494. RGSZ rgszElement;
  495. PSZ pszElement;
  496. WORD idcStatus;
  497. SendDlgItemMessage(hdlg, idc, LB_GETTEXT, n, (LPARAM)&lItem);
  498. pszElement = rgszElement = (RGSZ)lItem;
  499. idcStatus = IDC_STATUS1;
  500. while (*pszElement != (SZ)NULL && GetDlgItem(hdlg, idcStatus))
  501. SetDlgItemText (hdlg, idcStatus++,*pszElement++);
  502. return fTrue;
  503. }
  504. /*
  505. ** Author:
  506. ** Sunil Pai
  507. **
  508. ** Purpose:
  509. ** To build a list from all the elements in the specified owner draw
  510. ** listbox
  511. **
  512. ** Arguments:
  513. ** hdlg: The handle to the dialog having the owner draw listbox
  514. ** idc: The ID of the listbox
  515. **
  516. ** Returns:
  517. ** SZ Pointer to list (can be empty {})
  518. ** NULL if error occured.
  519. **
  520. ****************************************************************************/
  521. SZ szGetSzListFromListBox (HWND hdlg, WORD idc)
  522. {
  523. HWND hLB;
  524. INT i, nCount;
  525. LONG_PTR lItem;
  526. RGSZ rgsz;
  527. SZ szList;
  528. // Get the number of items in the list box and the handle to the list box
  529. nCount = (INT) SendDlgItemMessage(hdlg, idc, LB_GETCOUNT, 0, 0L);
  530. hLB = GetDlgItem(hdlg, idc);
  531. // Allocate a rgsz structure to hold all the items from the list box
  532. // and initialize it
  533. while ((rgsz = (RGSZ)SAlloc((nCount + 1) * sizeof(SZ)))
  534. == (RGSZ)NULL)
  535. if (!FHandleOOM(hdlg))
  536. {
  537. DestroyWindow(GetParent(hdlg));
  538. return((SZ)NULL);
  539. }
  540. rgsz[nCount] = (SZ)NULL;
  541. // For all the items in the list box get the item involved. Each item
  542. // is itself an RGSZ structure which needs to be converted into a list
  543. // before we put it into the RGSZ structure initialized above.
  544. for (i = 0; i < nCount; i++)
  545. {
  546. SendMessage(hLB, LB_GETTEXT, i, (LPARAM)&lItem);
  547. while ((rgsz[i] = SzListValueFromRgsz((RGSZ)lItem)) == (SZ)NULL)
  548. if (!FHandleOOM(hdlg))
  549. {
  550. DestroyWindow(GetParent(hdlg));
  551. return((SZ)NULL);
  552. }
  553. }
  554. // Construct a list from the RGSZ list structure, free the rgsz structure
  555. // and return the list formed
  556. while ((szList = SzListValueFromRgsz(rgsz)) == (SZ)NULL)
  557. if (!FHandleOOM(hdlg))
  558. {
  559. DestroyWindow(GetParent(hdlg));
  560. return((SZ)NULL);
  561. }
  562. EvalAssert(FFreeRgsz(rgsz));
  563. return (szList);
  564. }