Leaked source code of windows server 2003
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.

1351 lines
33 KiB

  1. // Copyright (c) 1995, Microsoft Corporation, all rights reserved
  2. //
  3. // edit.c
  4. // Remote Access Common Dialog APIs
  5. // List editor, string editor dialog routines
  6. //
  7. // 08/28/95 Steve Cobb
  8. #include "rasdlgp.h"
  9. //-----------------------------------------------------------------------------
  10. // Local datatypes (alphabetically)
  11. //-----------------------------------------------------------------------------
  12. // List editor dialog argument block.
  13. //
  14. typedef struct
  15. _LEARGS
  16. {
  17. // Caller's arguments to the stub API.
  18. //
  19. DTLLIST* pList;
  20. BOOL* pfCheck;
  21. DWORD dwMaxItemLen;
  22. TCHAR* pszTitle;
  23. TCHAR* pszItemLabel;
  24. TCHAR* pszListLabel;
  25. TCHAR* pszCheckLabel;
  26. TCHAR* pszDefaultItem;
  27. INT iSelInitial;
  28. DWORD* pdwHelp;
  29. DWORD dwfFlags;
  30. PDESTROYNODE pDestroyId;
  31. }
  32. LEARGS;
  33. // List editor dialog context block.
  34. //
  35. typedef struct
  36. _LEINFO
  37. {
  38. // Caller's arguments to the dialog.
  39. //
  40. LEARGS* pArgs;
  41. // Handle of this dialog and some of it's controls.
  42. //
  43. HWND hwndDlg;
  44. HWND hwndStItem;
  45. HWND hwndStList;
  46. HWND hwndPbAdd;
  47. HWND hwndPbReplace;
  48. HWND hwndPbUp;
  49. HWND hwndPbDown;
  50. HWND hwndPbDelete;
  51. HWND hwndPbOk;
  52. HWND hwndEb;
  53. HWND hwndLb;
  54. HWND hwndCb;
  55. // Convenient alternatives to (pInfo->pArgs->dwFlags & LEDFLAG_Sorted) and
  56. // (pInfo->pArgs->dwFlags & LEDFLAG_NoDeleteLastItem).
  57. //
  58. BOOL fSorted;
  59. BOOL fNoDeleteLast;
  60. // Button bitmaps.
  61. //
  62. HBITMAP hbmUp;
  63. HBITMAP hbmDown;
  64. // List of empty nodes whose node-IDs should be 'pDestroyId'ed if user
  65. // presses OK.
  66. //
  67. DTLLIST* pListDeletes;
  68. }
  69. LEINFO;
  70. // String Editor dialog arument block.
  71. //
  72. typedef struct
  73. _ZEARGS
  74. {
  75. /* Caller's aruments to the stub API.
  76. */
  77. TCHAR* pszIn;
  78. DWORD dwSidTitle;
  79. DWORD dwSidLabel;
  80. DWORD cbMax;
  81. DWORD dwHelpId;
  82. TCHAR** ppszOut;
  83. }
  84. ZEARGS;
  85. // String Editor dialog context block.
  86. //
  87. typedef struct
  88. _ZEINFO
  89. {
  90. // Caller's arguments to the stub API.
  91. //
  92. ZEARGS* pArgs;
  93. // Dialog and control handles.
  94. //
  95. HWND hwndDlg;
  96. HWND hwndEb;
  97. }
  98. ZEINFO;
  99. //-----------------------------------------------------------------------------
  100. // Local prototypes (alphabetically)
  101. //-----------------------------------------------------------------------------
  102. INT_PTR CALLBACK
  103. LeDlgProc(
  104. IN HWND hwnd,
  105. IN UINT unMsg,
  106. IN WPARAM wparam,
  107. IN LPARAM lparam );
  108. VOID
  109. LeAdd(
  110. IN LEINFO* pInfo );
  111. BOOL
  112. LeCommand(
  113. IN LEINFO* pInfo,
  114. IN WORD wNotification,
  115. IN WORD wId,
  116. IN HWND hwndCtrl );
  117. VOID
  118. LeDelete(
  119. IN LEINFO* pInfo );
  120. VOID
  121. LeDown(
  122. IN LEINFO* pInfo );
  123. VOID
  124. LeEnableUpAndDownButtons(
  125. IN LEINFO* pInfo );
  126. VOID
  127. LeExitNoMemory(
  128. IN LEINFO* pInfo );
  129. BOOL
  130. LeInit(
  131. IN HWND hwndDlg,
  132. IN LEARGS* pArgs );
  133. VOID
  134. LeItemTextFromListSelection(
  135. IN LEINFO* pInfo );
  136. VOID
  137. LeReplace(
  138. IN LEINFO* pInfo );
  139. BOOL
  140. LeSaveSettings(
  141. IN LEINFO* pInfo );
  142. VOID
  143. LeTerm(
  144. IN HWND hwndDlg );
  145. VOID
  146. LeUp(
  147. IN LEINFO* pInfo );
  148. INT_PTR CALLBACK
  149. ZeDlgProc(
  150. IN HWND hwnd,
  151. IN UINT unMsg,
  152. IN WPARAM wparam,
  153. IN LPARAM lparam );
  154. BOOL
  155. ZeCommand(
  156. IN ZEINFO* pInfo,
  157. IN WORD wNotification,
  158. IN WORD wId,
  159. IN HWND hwndCtrl );
  160. BOOL
  161. ZeInit(
  162. IN HWND hwndDlg,
  163. IN ZEARGS* pArgs );
  164. VOID
  165. ZeTerm(
  166. IN HWND hwndDlg );
  167. //-----------------------------------------------------------------------------
  168. // List Editor dialog entry point
  169. //-----------------------------------------------------------------------------
  170. BOOL
  171. ListEditorDlg(
  172. IN HWND hwndOwner,
  173. IN OUT DTLLIST* pList,
  174. IN OUT BOOL* pfCheck,
  175. IN DWORD dwMaxItemLen,
  176. IN TCHAR* pszTitle,
  177. IN TCHAR* pszItemLabel,
  178. IN TCHAR* pszListLabel,
  179. IN TCHAR* pszCheckLabel,
  180. IN TCHAR* pszDefaultItem,
  181. IN INT iSelInitial,
  182. IN DWORD* pdwHelp,
  183. IN DWORD dwfFlags,
  184. IN PDESTROYNODE pDestroyId )
  185. // Pops-up the List Editor dialog.
  186. //
  187. // 'HwndOwner' is the owner of the dialog. 'PList' is, on entry, the Psz
  188. // list to display initially, and on successful exit, the result list.
  189. // 'PfCheck' is the state of the check box or NULL for the non-checkbox
  190. // style. 'DwMaxItemLen' is the maximum length of an individual list
  191. // item. 'PszTitle' is the dialog title. 'PszItemLabel' is the label
  192. // (and hotkey) associated with the item box. 'PszListLabel' is the label
  193. // (and hotkey) associated with the list. 'PszCheckLabel' is the label
  194. // (and hotkey) associated with the checkbox. 'PszDefaultItem' is the
  195. // default contents of the edit box or for the selected list text.
  196. // 'ISelInitial' is the item the list to initally select. 'PdwHelp' is
  197. // the array of CID_LE_* help contexts to use. 'DwfFlags' indicates
  198. // LEDFLAG_* behavior options. 'PDestroyId' is the routine to use to
  199. // destroy node IDs when they are deleted or NULL if none.
  200. //
  201. // Returns true if user pressed OK and succeeded, false if he pressed
  202. // Cancel or encountered an error.
  203. //
  204. {
  205. INT_PTR nStatus;
  206. LEARGS args;
  207. TRACE( "ListEditorDlg" );
  208. args.pList = pList;
  209. args.pfCheck = pfCheck;
  210. args.dwMaxItemLen = dwMaxItemLen;
  211. args.pszTitle = pszTitle;
  212. args.pszItemLabel = pszItemLabel;
  213. args.pszListLabel = pszListLabel;
  214. args.pszCheckLabel = pszCheckLabel;
  215. args.pszDefaultItem = pszDefaultItem;
  216. args.iSelInitial = iSelInitial;
  217. args.pdwHelp = pdwHelp;
  218. args.dwfFlags = dwfFlags;
  219. args.pDestroyId = pDestroyId;
  220. nStatus =
  221. DialogBoxParam(
  222. g_hinstDll,
  223. (pfCheck)
  224. ? MAKEINTRESOURCE( DID_LE_ListEditor2 )
  225. : ((dwfFlags & LEDFLAG_Sorted)
  226. ? MAKEINTRESOURCE( DID_LE_ListEditor3 )
  227. : MAKEINTRESOURCE( DID_LE_ListEditor )),
  228. hwndOwner,
  229. LeDlgProc,
  230. (LPARAM )&args );
  231. if (nStatus == -1)
  232. {
  233. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  234. nStatus = FALSE;
  235. }
  236. return (nStatus) ? TRUE : FALSE;
  237. }
  238. //----------------------------------------------------------------------------
  239. // List Editor dialog routines
  240. // Listed alphabetically following dialog proc
  241. //----------------------------------------------------------------------------
  242. INT_PTR CALLBACK
  243. LeDlgProc(
  244. IN HWND hwnd,
  245. IN UINT unMsg,
  246. IN WPARAM wparam,
  247. IN LPARAM lparam )
  248. // DialogProc callback for the List Editor dialog. Parameters and return
  249. // value are as described for standard windows 'DialogProc's.
  250. //
  251. {
  252. #if 0
  253. TRACE4( "LeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  254. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  255. #endif
  256. switch (unMsg)
  257. {
  258. case WM_INITDIALOG:
  259. {
  260. return LeInit( hwnd, (LEARGS* )lparam );
  261. }
  262. case WM_HELP:
  263. case WM_CONTEXTMENU:
  264. {
  265. LEINFO* pInfo = (LEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  266. ASSERT( pInfo );
  267. ContextHelp( pInfo->pArgs->pdwHelp, hwnd, unMsg, wparam, lparam );
  268. break;
  269. }
  270. case WM_COMMAND:
  271. {
  272. LEINFO* pInfo = (LEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  273. ASSERT( pInfo );
  274. return LeCommand(
  275. pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  276. }
  277. case WM_DESTROY:
  278. {
  279. LeTerm( hwnd );
  280. break;
  281. }
  282. }
  283. return FALSE;
  284. }
  285. VOID
  286. LeAdd(
  287. IN LEINFO* pInfo )
  288. // Add button click handler. 'PInfo' is the dialog context.
  289. //
  290. {
  291. TCHAR* psz;
  292. psz = GetText( pInfo->hwndEb );
  293. if (!psz)
  294. {
  295. LeExitNoMemory( pInfo );
  296. return;
  297. }
  298. if (pInfo->pArgs->dwfFlags & LEDFLAG_Unique)
  299. {
  300. if (ListBox_IndexFromString( pInfo->hwndLb, psz ) >= 0)
  301. {
  302. MSGARGS msgargs;
  303. ZeroMemory( &msgargs, sizeof(msgargs) );
  304. msgargs.apszArgs[ 0 ] = psz;
  305. MsgDlg( pInfo->hwndDlg, SID_NotUnique, &msgargs );
  306. Edit_SetSel( pInfo->hwndEb, 0, -1 );
  307. SetFocus( pInfo->hwndEb );
  308. Free( psz );
  309. return;
  310. }
  311. }
  312. ListBox_SetCurSel( pInfo->hwndLb,
  313. ListBox_AddItem( pInfo->hwndLb, psz, 0 ) );
  314. Free( psz );
  315. LeEnableUpAndDownButtons( pInfo );
  316. EnableWindow( pInfo->hwndPbReplace, FALSE );
  317. if (!pInfo->fNoDeleteLast || ListBox_GetCount( pInfo->hwndLb ) > 1)
  318. {
  319. EnableWindow( pInfo->hwndPbDelete, TRUE );
  320. }
  321. SetWindowText( pInfo->hwndEb, TEXT("") );
  322. SetFocus( pInfo->hwndEb );
  323. }
  324. BOOL
  325. LeCommand(
  326. IN LEINFO* pInfo,
  327. IN WORD wNotification,
  328. IN WORD wId,
  329. IN HWND hwndCtrl )
  330. // Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
  331. // is the notification code of the command. 'wId' is the control/menu
  332. // identifier of the command. 'HwndCtrl' is the control window handle of
  333. // the command.
  334. //
  335. // Returns true if processed message, false otherwise.
  336. //
  337. {
  338. TRACE3( "LeCommand(n=%d,i=%d,c=$%x)",
  339. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  340. switch (wId)
  341. {
  342. case CID_LE_PB_Add:
  343. {
  344. LeAdd( pInfo );
  345. return TRUE;
  346. }
  347. case CID_LE_PB_Replace:
  348. {
  349. LeReplace( pInfo );
  350. return TRUE;
  351. }
  352. case CID_LE_PB_Up:
  353. {
  354. LeUp( pInfo );
  355. return TRUE;
  356. }
  357. case CID_LE_PB_Down:
  358. {
  359. LeDown( pInfo );
  360. return TRUE;
  361. }
  362. case CID_LE_PB_Delete:
  363. {
  364. LeDelete( pInfo );
  365. return TRUE;
  366. }
  367. case CID_LE_EB_Item:
  368. {
  369. if (wNotification == EN_SETFOCUS || wNotification == EN_UPDATE)
  370. {
  371. TCHAR* psz = GetText( pInfo->hwndEb );
  372. if (psz && lstrlen( psz ) > 0 && !IsAllWhite( psz ))
  373. {
  374. EnableWindow( pInfo->hwndPbAdd, TRUE );
  375. EnableWindow( pInfo->hwndPbReplace, TRUE );
  376. Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbAdd );
  377. }
  378. else
  379. {
  380. EnableWindow( pInfo->hwndPbAdd, FALSE );
  381. EnableWindow( pInfo->hwndPbReplace, FALSE );
  382. Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbOk );
  383. }
  384. Free0( psz );
  385. }
  386. return TRUE;
  387. }
  388. case CID_LE_LB_List:
  389. {
  390. if (wNotification == LBN_SELCHANGE)
  391. {
  392. LeEnableUpAndDownButtons( pInfo );
  393. if (ListBox_GetCurSel( pInfo->hwndLb ) >= 0)
  394. {
  395. LeItemTextFromListSelection( pInfo );
  396. }
  397. }
  398. return TRUE;
  399. }
  400. case CID_LE_CB_Promote:
  401. {
  402. if (wNotification == BN_SETFOCUS)
  403. {
  404. Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbOk );
  405. }
  406. return TRUE;
  407. }
  408. case IDOK:
  409. {
  410. EndDialog( pInfo->hwndDlg, LeSaveSettings( pInfo ) );
  411. return TRUE;
  412. }
  413. case IDCANCEL:
  414. {
  415. DTLLIST* pList;
  416. DTLNODE* pNode;
  417. TRACE( "Cancel pressed" );
  418. EndDialog( pInfo->hwndDlg, FALSE );
  419. return TRUE;
  420. }
  421. }
  422. return FALSE;
  423. }
  424. VOID
  425. LeDelete(
  426. IN LEINFO* pInfo )
  427. // Delete button click handler. 'PInfo' is the dialog context.
  428. //
  429. {
  430. INT i;
  431. INT c;
  432. i = ListBox_GetCurSel( pInfo->hwndLb );
  433. if (pInfo->pArgs->pDestroyId)
  434. {
  435. LONG_PTR lId = ListBox_GetItemData( pInfo->hwndLb, i );
  436. if (lId != 0)
  437. {
  438. DTLNODE* pNode;
  439. pNode = DtlCreateNode( NULL, lId );
  440. if (!pNode)
  441. {
  442. ErrorDlg( pInfo->hwndDlg, SID_OP_DisplayData,
  443. ERROR_NOT_ENOUGH_MEMORY, NULL );
  444. EndDialog( pInfo->hwndDlg, FALSE );
  445. return;
  446. }
  447. DtlAddNodeFirst( pInfo->pListDeletes, pNode );
  448. }
  449. }
  450. ListBox_DeleteString( pInfo->hwndLb, i );
  451. c = ListBox_GetCount( pInfo->hwndLb );
  452. if (c == 0)
  453. {
  454. EnableWindow( pInfo->hwndPbReplace, FALSE );
  455. EnableWindow( pInfo->hwndPbDelete, FALSE );
  456. SetFocus( pInfo->hwndEb );
  457. Edit_SetSel( pInfo->hwndEb, 0, -1 );
  458. }
  459. else
  460. {
  461. if (c == 1 && pInfo->fNoDeleteLast)
  462. {
  463. EnableWindow( pInfo->hwndPbDelete, FALSE );
  464. }
  465. if (i >= c)
  466. {
  467. i = c - 1;
  468. }
  469. ListBox_SetCurSel( pInfo->hwndLb, i );
  470. }
  471. LeEnableUpAndDownButtons( pInfo );
  472. if (IsWindowEnabled( GetFocus() ))
  473. {
  474. SetFocus( pInfo->hwndEb );
  475. Edit_SetSel( pInfo->hwndEb, 0, -1 );
  476. }
  477. }
  478. VOID
  479. LeDown(
  480. IN LEINFO* pInfo )
  481. // Down button click handler. 'PInfo' is the dialog context.
  482. //
  483. {
  484. TCHAR* psz;
  485. INT i;
  486. LONG_PTR lId;
  487. ASSERT( !pInfo->fSorted );
  488. i = ListBox_GetCurSel( pInfo->hwndLb );
  489. psz = ListBox_GetPsz( pInfo->hwndLb, i );
  490. if (!psz)
  491. {
  492. LeExitNoMemory( pInfo );
  493. return;
  494. }
  495. lId = ListBox_GetItemData( pInfo->hwndLb, i );
  496. ListBox_InsertString( pInfo->hwndLb, i + 2, psz );
  497. ListBox_SetItemData( pInfo->hwndLb, i + 2, lId );
  498. Free( psz );
  499. ListBox_DeleteString( pInfo->hwndLb, i );
  500. ListBox_SetCurSel( pInfo->hwndLb, i + 1 );
  501. if (i == ListBox_GetCount( pInfo->hwndLb ))
  502. {
  503. Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbUp );
  504. SetFocus( pInfo->hwndPbUp );
  505. }
  506. LeEnableUpAndDownButtons( pInfo );
  507. }
  508. VOID
  509. LeEnableUpAndDownButtons(
  510. IN LEINFO* pInfo )
  511. // Determine if the Up and Down operations make sense and enable/disable
  512. // the buttons as appropriate. 'PInfo' is the dialog context.
  513. //
  514. {
  515. INT i;
  516. INT c;
  517. if (pInfo->fSorted)
  518. {
  519. return;
  520. }
  521. i = ListBox_GetCurSel( pInfo->hwndLb );
  522. c = ListBox_GetCount( pInfo->hwndLb );
  523. EnableWindow( pInfo->hwndPbDown, (i < c - 1 ) );
  524. EnableWindow( pInfo->hwndPbUp, (i > 0) );
  525. }
  526. VOID
  527. LeExitNoMemory(
  528. IN LEINFO* pInfo )
  529. // End the dialog reporting a memory. 'PInfo' is the dialog context.
  530. //
  531. {
  532. ErrorDlg( pInfo->hwndDlg,
  533. SID_OP_DisplayData, ERROR_NOT_ENOUGH_MEMORY, NULL );
  534. EndDialog( pInfo->hwndDlg, FALSE );
  535. }
  536. BOOL
  537. LeInit(
  538. IN HWND hwndDlg,
  539. IN LEARGS* pArgs )
  540. // Called on WM_INITDIALOG. 'HwndDlg' is the handle of the phonebook
  541. // dialog window. 'PArgs' is caller's arguments as passed to the stub
  542. // API.
  543. //
  544. // Return false if focus was set, true otherwise, i.e. as defined for
  545. // WM_INITDIALOG.
  546. //
  547. {
  548. DWORD dwErr;
  549. LEINFO* pInfo;
  550. DTLNODE* pNode;
  551. INT c;
  552. TRACE( "LeInit" );
  553. // Allocate the dialog context block. Initialize minimally for proper
  554. // cleanup, then attach to the dialog window.
  555. //
  556. {
  557. pInfo = Malloc( sizeof(*pInfo) );
  558. if (!pInfo)
  559. {
  560. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  561. EndDialog( hwndDlg, FALSE );
  562. return TRUE;
  563. }
  564. ZeroMemory( pInfo, sizeof(*pInfo) );
  565. pInfo->pArgs = pArgs;
  566. pInfo->hwndDlg = hwndDlg;
  567. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  568. TRACE( "Context set" );
  569. }
  570. // Set up convenient shortcuts.
  571. //
  572. if (pArgs->dwfFlags & LEDFLAG_Sorted)
  573. {
  574. pInfo->fSorted = TRUE;
  575. }
  576. if (pArgs->dwfFlags & LEDFLAG_NoDeleteLastItem)
  577. {
  578. pInfo->fNoDeleteLast = TRUE;
  579. }
  580. pInfo->hwndStItem = GetDlgItem( hwndDlg, CID_LE_ST_Item );
  581. ASSERT( pInfo->hwndStItem );
  582. pInfo->hwndStList = GetDlgItem( hwndDlg, CID_LE_ST_List );
  583. ASSERT( pInfo->hwndStList );
  584. pInfo->hwndPbAdd = GetDlgItem( hwndDlg, CID_LE_PB_Add );
  585. ASSERT( pInfo->hwndPbAdd );
  586. pInfo->hwndPbReplace = GetDlgItem( hwndDlg, CID_LE_PB_Replace );
  587. ASSERT( pInfo->hwndPbReplace );
  588. pInfo->hwndPbDelete = GetDlgItem( hwndDlg, CID_LE_PB_Delete );
  589. ASSERT( pInfo->hwndPbDelete );
  590. pInfo->hwndPbOk = GetDlgItem( hwndDlg, IDOK );
  591. ASSERT( pInfo->hwndPbOk );
  592. pInfo->hwndEb = GetDlgItem( hwndDlg, CID_LE_EB_Item );
  593. ASSERT( pInfo->hwndEb );
  594. pInfo->hwndLb = GetDlgItem( hwndDlg, CID_LE_LB_List );
  595. ASSERT( pInfo->hwndLb );
  596. if (pArgs->pDestroyId)
  597. {
  598. // Create the empty list of deletions.
  599. //
  600. pInfo->pListDeletes = DtlCreateList( 0L );
  601. if (!pInfo->pListDeletes)
  602. {
  603. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  604. EndDialog( hwndDlg, FALSE );
  605. return TRUE;
  606. }
  607. }
  608. if (!pInfo->fSorted)
  609. {
  610. pInfo->hwndPbUp = GetDlgItem( hwndDlg, CID_LE_PB_Up );
  611. ASSERT( pInfo->hwndPbUp );
  612. pInfo->hwndPbDown = GetDlgItem( hwndDlg, CID_LE_PB_Down );
  613. ASSERT( pInfo->hwndPbDown );
  614. // Draw the graphical up and down arrow indicators.
  615. //
  616. pInfo->hbmUp = Button_CreateBitmap(
  617. pInfo->hwndPbUp, BMS_UpArrowOnRight );
  618. if (pInfo->hbmUp)
  619. {
  620. SendMessage( pInfo->hwndPbUp, BM_SETIMAGE, 0,
  621. (LPARAM )pInfo->hbmUp );
  622. }
  623. pInfo->hbmDown = Button_CreateBitmap(
  624. pInfo->hwndPbDown, BMS_DownArrowOnRight );
  625. if (pInfo->hbmDown)
  626. {
  627. SendMessage( pInfo->hwndPbDown, BM_SETIMAGE, 0,
  628. (LPARAM )pInfo->hbmDown );
  629. }
  630. }
  631. if (pArgs->pfCheck)
  632. {
  633. pInfo->hwndCb = GetDlgItem( hwndDlg, CID_LE_CB_Promote );
  634. ASSERT( pInfo->hwndCb );
  635. SetWindowText( pInfo->hwndCb, pArgs->pszCheckLabel );
  636. Button_SetCheck( pInfo->hwndCb, *pArgs->pfCheck );
  637. }
  638. Edit_LimitText( pInfo->hwndEb, pArgs->dwMaxItemLen );
  639. // Set caller-defined dialog title and labels.
  640. //
  641. SetWindowText( pInfo->hwndDlg, pArgs->pszTitle );
  642. SetWindowText( pInfo->hwndStItem, pArgs->pszItemLabel );
  643. SetWindowText( pInfo->hwndStList, pArgs->pszListLabel );
  644. // Fill the listbox.
  645. //
  646. for (pNode = DtlGetFirstNode( pArgs->pList );
  647. pNode;
  648. pNode = DtlGetNextNode( pNode ))
  649. {
  650. TCHAR* psz = (TCHAR* )DtlGetData( pNode );
  651. ASSERT( psz );
  652. ListBox_AddItem( pInfo->hwndLb, psz, (VOID* ) DtlGetNodeId( pNode ) );
  653. }
  654. c = ListBox_GetCount( pInfo->hwndLb );
  655. if (c > 0)
  656. {
  657. // Select item selected by caller.
  658. //
  659. ListBox_SetCurSelNotify( pInfo->hwndLb, pArgs->iSelInitial );
  660. LeEnableUpAndDownButtons( pInfo );
  661. if (c == 1 && pInfo->fNoDeleteLast)
  662. {
  663. EnableWindow( pInfo->hwndPbDelete, FALSE );
  664. }
  665. }
  666. else
  667. {
  668. // Empty list.
  669. //
  670. if (!pInfo->fSorted)
  671. {
  672. EnableWindow( pInfo->hwndPbUp, FALSE );
  673. EnableWindow( pInfo->hwndPbDown, FALSE );
  674. }
  675. EnableWindow( pInfo->hwndPbDelete, FALSE );
  676. }
  677. // Set default edit box contents, if any.
  678. //
  679. if (pArgs->pszDefaultItem)
  680. {
  681. SetWindowText( pInfo->hwndEb, pArgs->pszDefaultItem );
  682. Edit_SetSel( pInfo->hwndEb, 0, -1 );
  683. }
  684. else
  685. {
  686. EnableWindow( pInfo->hwndPbAdd, FALSE );
  687. EnableWindow( pInfo->hwndPbReplace, FALSE );
  688. }
  689. // Center dialog on the owner window.
  690. //
  691. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  692. // Add context help button to title bar. Dlgedit.exe doesn't currently
  693. // support this at resource edit time. When that's fixed set
  694. // DS_CONTEXTHELP there and remove this call.
  695. //
  696. AddContextHelpButton( hwndDlg );
  697. return TRUE;
  698. }
  699. VOID
  700. LeItemTextFromListSelection(
  701. IN LEINFO* pInfo )
  702. // Copies the currently selected item in the list to the edit box.
  703. // 'PInfo' is the dialog context.
  704. //
  705. {
  706. TCHAR* psz;
  707. INT iSel;
  708. iSel = ListBox_GetCurSel( pInfo->hwndLb );
  709. if (iSel >= 0)
  710. {
  711. psz = ListBox_GetPsz( pInfo->hwndLb, iSel );
  712. if (psz)
  713. {
  714. SetWindowText( pInfo->hwndEb, psz );
  715. Free( psz );
  716. return;
  717. }
  718. }
  719. SetWindowText( pInfo->hwndEb, TEXT("") );
  720. }
  721. VOID
  722. LeReplace(
  723. IN LEINFO* pInfo )
  724. // Replace button click handler. 'PInfo' is the dialog context.
  725. //
  726. {
  727. TCHAR* psz;
  728. INT i;
  729. LONG_PTR lId;
  730. psz = GetText( pInfo->hwndEb );
  731. if (!psz)
  732. {
  733. LeExitNoMemory( pInfo );
  734. return;
  735. }
  736. if (pInfo->pArgs->dwfFlags & LEDFLAG_Unique)
  737. {
  738. if (ListBox_IndexFromString( pInfo->hwndLb, psz ) >= 0)
  739. {
  740. MSGARGS msgargs;
  741. ZeroMemory( &msgargs, sizeof(msgargs) );
  742. msgargs.apszArgs[ 0 ] = psz;
  743. MsgDlg( pInfo->hwndDlg, SID_NotUnique, &msgargs );
  744. Edit_SetSel( pInfo->hwndEb, 0, -1 );
  745. SetFocus( pInfo->hwndEb );
  746. Free( psz );
  747. return;
  748. }
  749. }
  750. i = ListBox_GetCurSel( pInfo->hwndLb );
  751. lId = ListBox_GetItemData( pInfo->hwndLb, i );
  752. ListBox_DeleteString( pInfo->hwndLb, i );
  753. if (pInfo->fSorted)
  754. {
  755. i = ListBox_AddItem( pInfo->hwndLb, psz, (VOID* )lId );
  756. }
  757. else
  758. {
  759. ListBox_InsertString( pInfo->hwndLb, i, psz );
  760. ListBox_SetItemData( pInfo->hwndLb, i, lId );
  761. }
  762. Free( psz );
  763. ListBox_SetCurSel( pInfo->hwndLb, i );
  764. SetFocus( pInfo->hwndEb );
  765. SetWindowText( pInfo->hwndEb, TEXT("") );
  766. }
  767. BOOL
  768. LeSaveSettings(
  769. IN LEINFO* pInfo )
  770. // Saves dialog settings in the stub API caller's list. 'PInfo' is the
  771. // dialog context.
  772. //
  773. // Returns true if successful, false if does not validate.
  774. //
  775. {
  776. DWORD dwErr;
  777. DTLNODE* pNode;
  778. DTLLIST* pList;
  779. DTLLIST* pListNew;
  780. TCHAR* psz;
  781. LONG_PTR lId;
  782. INT c;
  783. INT i;
  784. // Make new list from list box contents.
  785. //
  786. do
  787. {
  788. pListNew = DtlCreateList( 0L );
  789. if (!pListNew)
  790. {
  791. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  792. break;
  793. }
  794. dwErr = 0;
  795. c = ListBox_GetCount( pInfo->hwndLb );
  796. for (i = 0; i < c; ++i)
  797. {
  798. psz = ListBox_GetPsz( pInfo->hwndLb, i );
  799. if (!psz)
  800. {
  801. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  802. break;
  803. }
  804. lId = ListBox_GetItemData( pInfo->hwndLb, i );
  805. ASSERT( lId>=0 );
  806. pNode = DtlCreateNode( psz, lId );
  807. if (!pNode)
  808. {
  809. Free( psz );
  810. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  811. break;
  812. }
  813. DtlAddNodeLast( pListNew, pNode );
  814. }
  815. }
  816. while (FALSE);
  817. if (dwErr != 0)
  818. {
  819. ErrorDlg( pInfo->hwndDlg, SID_OP_DisplayData, dwErr, NULL );
  820. DtlDestroyList( pListNew, DestroyPszNode );
  821. return FALSE;
  822. }
  823. // Free all data in the old list.
  824. //
  825. while (pNode = DtlGetFirstNode( pInfo->pArgs->pList ))
  826. {
  827. Free( (TCHAR* )DtlGetData( pNode ) );
  828. DtlDeleteNode( pInfo->pArgs->pList, pNode );
  829. }
  830. // Free the node-IDs in the list of deletions.
  831. //
  832. if (pInfo->pListDeletes)
  833. {
  834. while (pNode = DtlGetFirstNode( pInfo->pListDeletes ))
  835. {
  836. pInfo->pArgs->pDestroyId( (DTLNODE* )DtlGetNodeId( pNode ) );
  837. DtlDeleteNode( pInfo->pListDeletes, pNode );
  838. }
  839. }
  840. // Move the new list onto caller's list.
  841. //
  842. while (pNode = DtlGetFirstNode( pListNew ))
  843. {
  844. DtlRemoveNode( pListNew, pNode );
  845. DtlAddNodeLast( pInfo->pArgs->pList, pNode );
  846. }
  847. DtlDestroyList( pListNew, DestroyPszNode );
  848. // Tell caller what the checkbox setting is.
  849. //
  850. if (pInfo->pArgs->pfCheck)
  851. {
  852. *pInfo->pArgs->pfCheck = Button_GetCheck( pInfo->hwndCb );
  853. }
  854. return TRUE;
  855. }
  856. VOID
  857. LeTerm(
  858. IN HWND hwndDlg )
  859. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  860. //
  861. {
  862. LEINFO* pInfo = (LEINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  863. TRACE( "LeTerm" );
  864. if (pInfo)
  865. {
  866. if (pInfo->hbmUp)
  867. {
  868. DeleteObject( pInfo->hbmUp );
  869. }
  870. if (pInfo->hbmDown)
  871. {
  872. DeleteObject( pInfo->hbmDown );
  873. }
  874. DtlDestroyList( pInfo->pListDeletes, NULL );
  875. Free( pInfo );
  876. }
  877. }
  878. VOID
  879. LeUp(
  880. IN LEINFO* pInfo )
  881. // Up button click handler. 'PInfo' is the dialog context.
  882. //
  883. {
  884. TCHAR* psz;
  885. INT i;
  886. LONG_PTR lId;
  887. ASSERT( !pInfo->fSorted );
  888. i = ListBox_GetCurSel( pInfo->hwndLb );
  889. psz = ListBox_GetPsz( pInfo->hwndLb, i );
  890. if (!psz)
  891. {
  892. LeExitNoMemory( pInfo );
  893. return;
  894. }
  895. ListBox_InsertString( pInfo->hwndLb, i - 1, psz );
  896. Free( psz );
  897. lId = ListBox_GetItemData( pInfo->hwndLb, i + 1 );
  898. ListBox_DeleteString( pInfo->hwndLb, i + 1 );
  899. ListBox_SetItemData( pInfo->hwndLb, i - 1, lId );
  900. ListBox_SetCurSel( pInfo->hwndLb, i - 1 );
  901. if (i == 1)
  902. {
  903. Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbDown );
  904. SetFocus( pInfo->hwndPbDown );
  905. }
  906. LeEnableUpAndDownButtons( pInfo );
  907. }
  908. //-----------------------------------------------------------------------------
  909. // String Editor dialog entry point
  910. //-----------------------------------------------------------------------------
  911. BOOL
  912. StringEditorDlg(
  913. IN HWND hwndOwner,
  914. IN TCHAR* pszIn,
  915. IN DWORD dwSidTitle,
  916. IN DWORD dwSidLabel,
  917. IN DWORD cbMax,
  918. IN DWORD dwHelpId,
  919. IN OUT TCHAR** ppszOut )
  920. // Pops-up the String Editor dialog. 'PszIn' is the initial setting of
  921. // the edit box or NULL for blank. 'DwSidTitle' and 'dwSidLabel' are the
  922. // string resource IDs of the dialog title and edit box label. 'CbMax' is
  923. // the maximum length of the to allow or 0 for no limit. 'DwHelpId' is
  924. // the HID_* constant to associate with the label and edit field or -1 if
  925. // none.
  926. //
  927. // Returns true if user pressed OK and succeeded, false if he pressed
  928. // Cancel or encountered an error. If true, '*ppszNumber' is a heap block
  929. // with the edited result. It is caller's responsibility to Free the
  930. // returned block.
  931. //
  932. {
  933. INT_PTR nStatus;
  934. ZEARGS args;
  935. TRACE( "StringEditorDlg" );
  936. args.pszIn = pszIn;
  937. args.dwSidTitle = dwSidTitle;
  938. args.dwSidLabel = dwSidLabel;
  939. args.cbMax = cbMax;
  940. args.dwHelpId = dwHelpId;
  941. args.ppszOut = ppszOut;
  942. nStatus =
  943. (BOOL )DialogBoxParam(
  944. g_hinstDll,
  945. MAKEINTRESOURCE( DID_ZE_StringEditor ),
  946. hwndOwner,
  947. ZeDlgProc,
  948. (LPARAM )&args );
  949. if (nStatus == -1)
  950. {
  951. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  952. nStatus = FALSE;
  953. }
  954. return (nStatus) ? TRUE : FALSE;
  955. }
  956. //----------------------------------------------------------------------------
  957. // String Editor dialog routines
  958. // Listed alphabetically following dialog proc
  959. //----------------------------------------------------------------------------
  960. INT_PTR CALLBACK
  961. ZeDlgProc(
  962. IN HWND hwnd,
  963. IN UINT unMsg,
  964. IN WPARAM wparam,
  965. IN LPARAM lparam )
  966. // DialogProc callback for the Edit Phone Number dialog. Parameters and
  967. // return value are as described for standard windows 'DialogProc's.
  968. //
  969. {
  970. #if 0
  971. TRACE4( "ZeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  972. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  973. #endif
  974. switch (unMsg)
  975. {
  976. case WM_INITDIALOG:
  977. {
  978. return ZeInit( hwnd, (ZEARGS* )lparam );
  979. }
  980. case WM_HELP:
  981. case WM_CONTEXTMENU:
  982. {
  983. ZEINFO* pInfo;
  984. pInfo = (ZEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  985. if (pInfo && pInfo->pArgs->dwHelpId != (DWORD )-1)
  986. {
  987. DWORD adwZeHelp[ (2 + 1) * 2 ];
  988. ZeroMemory( adwZeHelp, sizeof(adwZeHelp) );
  989. adwZeHelp[ 0 ] = CID_ZE_ST_String;
  990. adwZeHelp[ 2 ] = CID_ZE_EB_String;
  991. adwZeHelp[ 1 ] = adwZeHelp[ 3 ] = pInfo->pArgs->dwHelpId;
  992. ContextHelp( adwZeHelp, hwnd, unMsg, wparam, lparam );
  993. break;
  994. }
  995. }
  996. case WM_COMMAND:
  997. {
  998. ZEINFO* pInfo = (ZEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  999. ASSERT( pInfo );
  1000. return ZeCommand(
  1001. pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  1002. }
  1003. case WM_DESTROY:
  1004. {
  1005. ZeTerm( hwnd );
  1006. break;
  1007. }
  1008. }
  1009. return FALSE;
  1010. }
  1011. BOOL
  1012. ZeCommand(
  1013. IN ZEINFO* pInfo,
  1014. IN WORD wNotification,
  1015. IN WORD wId,
  1016. IN HWND hwndCtrl )
  1017. // Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
  1018. // is the notification code of the command. 'wId' is the control/menu
  1019. // identifier of the command. 'HwndCtrl' is the control window handle of
  1020. // the command.
  1021. //
  1022. // Returns true if processed message, false otherwise.
  1023. //
  1024. {
  1025. TRACE3( "ZeCommand(n=%d,i=%d,c=$%x)",
  1026. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  1027. switch (wId)
  1028. {
  1029. case IDOK:
  1030. {
  1031. TRACE( "OK pressed" );
  1032. *pInfo->pArgs->ppszOut = GetText( pInfo->hwndEb );
  1033. EndDialog( pInfo->hwndDlg, (*pInfo->pArgs->ppszOut != NULL) );
  1034. return TRUE;
  1035. }
  1036. case IDCANCEL:
  1037. {
  1038. TRACE( "Cancel pressed" );
  1039. EndDialog( pInfo->hwndDlg, FALSE );
  1040. return TRUE;
  1041. }
  1042. }
  1043. return FALSE;
  1044. }
  1045. BOOL
  1046. ZeInit(
  1047. IN HWND hwndDlg,
  1048. IN ZEARGS* pArgs )
  1049. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  1050. // 'PArgs' is caller's arguments as passed to the stub API.
  1051. //
  1052. // Return false if focus was set, true otherwise, i.e. as defined for
  1053. // WM_INITDIALOG.
  1054. //
  1055. {
  1056. DWORD dwErr;
  1057. TCHAR* psz;
  1058. ZEINFO* pInfo;
  1059. TRACE( "ZeInit" );
  1060. // Allocate the dialog context block. Initialize minimally for proper
  1061. // cleanup, then attach to the dialog window.
  1062. //
  1063. {
  1064. pInfo = Malloc( sizeof(*pInfo) );
  1065. if (!pInfo)
  1066. {
  1067. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  1068. EndDialog( hwndDlg, FALSE );
  1069. return TRUE;
  1070. }
  1071. ZeroMemory( pInfo, sizeof(*pInfo) );
  1072. pInfo->pArgs = pArgs;
  1073. pInfo->hwndDlg = hwndDlg;
  1074. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  1075. TRACE( "Context set" );
  1076. }
  1077. pInfo->hwndEb = GetDlgItem( hwndDlg, CID_ZE_EB_String );
  1078. ASSERT( pInfo->hwndEb );
  1079. if (pArgs->cbMax > 0)
  1080. {
  1081. Edit_LimitText( pInfo->hwndEb, pArgs->cbMax );
  1082. }
  1083. psz = PszFromId( g_hinstDll, pArgs->dwSidTitle );
  1084. if (psz)
  1085. {
  1086. SetWindowText( hwndDlg, psz );
  1087. Free( psz );
  1088. }
  1089. psz = PszFromId( g_hinstDll, pArgs->dwSidLabel );
  1090. if (psz)
  1091. {
  1092. HWND hwndSt = GetDlgItem( hwndDlg, CID_ZE_ST_String );
  1093. ASSERT( hwndSt );
  1094. SetWindowText( hwndSt, psz );
  1095. Free( psz );
  1096. }
  1097. if (pArgs->pszIn)
  1098. {
  1099. SetWindowText( pInfo->hwndEb, pArgs->pszIn );
  1100. Edit_SetSel( pInfo->hwndEb, 0, -1 );
  1101. }
  1102. // Center dialog on the owner window.
  1103. //
  1104. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  1105. // Add context help button to title bar. Dlgedit.exe doesn't currently
  1106. // support this at resource edit time. When that's fixed set
  1107. // DS_CONTEXTHELP there and remove this call.
  1108. //
  1109. AddContextHelpButton( hwndDlg );
  1110. return TRUE;
  1111. }
  1112. VOID
  1113. ZeTerm(
  1114. IN HWND hwndDlg )
  1115. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  1116. //
  1117. {
  1118. ZEINFO* pInfo = (ZEINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  1119. TRACE( "ZeTerm" );
  1120. if (pInfo)
  1121. {
  1122. Free( pInfo );
  1123. }
  1124. }