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.

1614 lines
42 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. forms.cxx
  6. Abstract:
  7. Printer Forms
  8. Author:
  9. Steve Kiraly (SteveKi) 11/20/95
  10. Lazar Ivanov (LazarI) Jun-2000 (major changes)
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "forms.hxx"
  16. DWORD pEntryFields[] = { IDD_FM_EF_WIDTH,
  17. IDD_FM_EF_HEIGHT,
  18. IDD_FM_EF_LEFT,
  19. IDD_FM_EF_RIGHT,
  20. IDD_FM_EF_TOP,
  21. IDD_FM_EF_BOTTOM,
  22. 0 };
  23. DWORD pTextFields[] = { IDD_FM_TX_WIDTH,
  24. IDD_FM_TX_HEIGHT,
  25. IDD_FM_TX_LEFT,
  26. IDD_FM_TX_RIGHT,
  27. IDD_FM_TX_TOP,
  28. IDD_FM_TX_BOTTOM,
  29. 0 };
  30. /*++
  31. Routine Name:
  32. TPropDriverExists
  33. Routine Description:
  34. Fix the server handle. This routine tries to use a
  35. server handle to enum the forms on the specified machine.
  36. Arguments:
  37. hPrintServer,
  38. pszServerName,
  39. bAdministrator,
  40. *phPrinter
  41. Return Value:
  42. Possible return values
  43. HANDLE_FIX_NOT_NEEDED
  44. HANDLE_FIXED_NEW_HANDLE_RETURNED
  45. HANDLE_NEEDS_FIXING_NO_PRINTERS_FOUND
  46. --*/
  47. UINT
  48. sFormsFixServerHandle(
  49. IN HANDLE hPrintServer,
  50. IN LPCTSTR pszServerName,
  51. IN BOOL bAdministrator,
  52. IN HANDLE *phPrinter
  53. )
  54. {
  55. // Check if server handle can be used.
  56. PFORM_INFO_1 pFormInfo;
  57. DWORD dwNumberOfForms;
  58. BOOL bStatus;
  59. bStatus = bEnumForms(
  60. hPrintServer,
  61. 1,
  62. (PBYTE *)&pFormInfo,
  63. &dwNumberOfForms );
  64. // Server handle succeeded.
  65. if( bStatus && dwNumberOfForms )
  66. {
  67. FreeMem(pFormInfo);
  68. return HANDLE_FIX_NOT_NEEDED;
  69. }
  70. // Enumerate the printers on the specified server looking for a printer.
  71. PRINTER_INFO_2 *pPrinterInfo2 = NULL;
  72. DWORD cPrinterInfo2 = 0;
  73. DWORD cbPrinterInfo2 = 0;
  74. DWORD dwFlags = PRINTER_ENUM_NAME;
  75. bStatus = VDataRefresh::bEnumPrinters(
  76. dwFlags,
  77. (LPTSTR)pszServerName,
  78. 2,
  79. (PVOID *)&pPrinterInfo2,
  80. &cbPrinterInfo2,
  81. &cPrinterInfo2);
  82. // If success and at least one printer was enumerated.
  83. if( bStatus && cPrinterInfo2 )
  84. {
  85. TStatus Status;
  86. Status DBGNOCHK = ERROR_INVALID_FUNCTION;
  87. DWORD dwAccess = 0;
  88. for( UINT i = 0; i < cPrinterInfo2; i++ )
  89. {
  90. // Attempt to open the printer using the specified access.
  91. dwAccess = 0;
  92. Status DBGCHK = TPrinter::sOpenPrinter(pPrinterInfo2[i].pPrinterName,
  93. &dwAccess,
  94. phPrinter);
  95. // Done if a valid printer handle was returned.
  96. if( Status == ERROR_SUCCESS )
  97. {
  98. break;
  99. }
  100. else
  101. {
  102. DBGMSG(DBG_WARN, ( "Error opening printer \"" TSTR "\".\n", pPrinterInfo2[i].pPrinterName));
  103. }
  104. }
  105. // Release the printer enumeration buffer.
  106. FreeMem(pPrinterInfo2);
  107. //
  108. // Return the new handle value. Note: Access privilage
  109. // may have changed.
  110. //
  111. DWORD dwAccessType;
  112. if( Status == ERROR_SUCCESS )
  113. {
  114. dwAccessType = bAdministrator ? PRINTER_ALL_ACCESS : PRINTER_READ;
  115. return (dwAccess == dwAccessType ?
  116. HANDLE_FIXED_NEW_HANDLE_RETURNED :
  117. HANDLE_FIXED_NEW_HANDLE_RETURNED_ACCESS_CHANGED);
  118. }
  119. }
  120. // Error no printers were found using the specifed server handle.
  121. return HANDLE_NEEDS_FIXING_NO_PRINTERS_FOUND;
  122. }
  123. PVOID
  124. FormsInit(
  125. IN LPCTSTR pszServerName,
  126. IN HANDLE hPrintServer,
  127. IN BOOL bAdministrator,
  128. IN LPCTSTR pszComputerName
  129. )
  130. {
  131. FORMS_DLG_DATA *pFormsDlgData = (FORMS_DLG_DATA *)AllocMem(sizeof(*pFormsDlgData));
  132. if( pFormsDlgData )
  133. {
  134. // initialize the forms dialog data here.
  135. ZeroMemory(pFormsDlgData, sizeof(*pFormsDlgData));
  136. // set the forms dialog data.
  137. pFormsDlgData->pServerName = (LPTSTR)pszServerName;
  138. pFormsDlgData->AccessGranted = bAdministrator;
  139. pFormsDlgData->hPrinter = hPrintServer;
  140. pFormsDlgData->bNeedClose = FALSE;
  141. pFormsDlgData->pszComputerName= pszComputerName;
  142. // get the current metric setting.
  143. pFormsDlgData->uMetricMeasurement = !((BOOL)GetProfileInt(TEXT( "intl" ), TEXT("iMeasure"), 0));
  144. // get decimal point setting.
  145. GetProfileString(TEXT( "intl" ), TEXT( "sDecimal" ), TEXT( "." ),
  146. pFormsDlgData->szDecimalPoint, ARRAYSIZE(pFormsDlgData->szDecimalPoint));
  147. // if this machine does not suport using a server handle to
  148. // administer forms, we need to attempt to acquire a printer handle
  149. // for the specified access and then remember to close the handle when this
  150. // dialog terminates.
  151. HANDLE hPrinter;
  152. UINT Status = sFormsFixServerHandle(pFormsDlgData->hPrinter, pszServerName, bAdministrator, &hPrinter);
  153. // there are three cases which can occurr.
  154. switch( Status )
  155. {
  156. case HANDLE_FIXED_NEW_HANDLE_RETURNED:
  157. pFormsDlgData->hPrinter = hPrinter;
  158. pFormsDlgData->bNeedClose = TRUE;
  159. break;
  160. case HANDLE_NEEDS_FIXING_NO_PRINTERS_FOUND:
  161. pFormsDlgData->hPrinter = NULL;
  162. pFormsDlgData->AccessGranted = FALSE;
  163. break;
  164. case HANDLE_FIXED_NEW_HANDLE_RETURNED_ACCESS_CHANGED:
  165. pFormsDlgData->hPrinter = hPrinter;
  166. pFormsDlgData->bNeedClose = TRUE;
  167. pFormsDlgData->AccessGranted = !pFormsDlgData->AccessGranted;
  168. break;
  169. case HANDLE_FIX_NOT_NEEDED:
  170. break;
  171. default:
  172. DBGMSG( DBG_TRACE, ( "Un handled case value HANDLE_FIX.\n" ) );
  173. break;
  174. }
  175. }
  176. return pFormsDlgData;
  177. }
  178. VOID
  179. FormsFini(
  180. PVOID p
  181. )
  182. {
  183. // Get pointer to forms data.
  184. FORMS_DLG_DATA *pFormsDlgData = (FORMS_DLG_DATA *)p;
  185. // Validate forms data pointer
  186. if( pFormsDlgData )
  187. {
  188. // If printer opened ok, then we must close it.
  189. if( pFormsDlgData->bNeedClose && pFormsDlgData->hPrinter )
  190. {
  191. ClosePrinter( pFormsDlgData->hPrinter );
  192. }
  193. // Release the forms enumeration.
  194. FreeMem(pFormsDlgData->pFormInfo);
  195. // Release the forms data
  196. FreeMem(pFormsDlgData);
  197. }
  198. }
  199. BOOL APIENTRY
  200. FormsDlg(
  201. HWND hwnd,
  202. UINT msg,
  203. WPARAM wparam,
  204. LPARAM lparam
  205. )
  206. {
  207. // clear the last error each time message is about to be
  208. // handled
  209. PFORMS_DLG_DATA pFormsDlgData =
  210. (WM_INITDIALOG == msg ? (PFORMS_DLG_DATA)lparam :
  211. (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA));
  212. if( pFormsDlgData )
  213. {
  214. pFormsDlgData->dwLastError = ERROR_SUCCESS;
  215. }
  216. // switch madness
  217. switch(msg)
  218. {
  219. case WM_INITDIALOG:
  220. return FormsInitDialog(hwnd, pFormsDlgData);
  221. case WM_COMMAND:
  222. switch( LOWORD( wparam ) )
  223. {
  224. case IDD_FM_PB_SAVEFORM:
  225. return FormsCommandAddForm(hwnd);
  226. case IDD_FM_PB_DELFORM:
  227. return FormsCommandDelForm(hwnd);
  228. case IDD_FM_LB_FORMS:
  229. switch (HIWORD(wparam))
  230. {
  231. case LBN_SELCHANGE:
  232. return FormsCommandFormsSelChange(hwnd);
  233. }
  234. break;
  235. case IDD_FM_EF_NAME:
  236. return FormsCommandNameChange(hwnd, wparam, lparam );
  237. case IDD_FM_RB_METRIC:
  238. case IDD_FM_RB_ENGLISH:
  239. return FormsCommandUnits(hwnd);
  240. case IDD_FM_CK_NEW_FORM:
  241. return FormsNewForms(hwnd);
  242. }
  243. }
  244. return FALSE;
  245. }
  246. LPTSTR
  247. AllocStr(
  248. LPCTSTR pszStr
  249. )
  250. {
  251. if( pszStr && *pszStr )
  252. {
  253. LPTSTR pszRet = (LPTSTR)AllocMem((lstrlen(pszStr) + 1) * sizeof(*pszRet));
  254. if( pszRet )
  255. {
  256. lstrcpy(pszRet, pszStr);
  257. return pszRet;
  258. }
  259. }
  260. return NULL;
  261. }
  262. VOID
  263. FreeStr(
  264. LPTSTR pszStr
  265. )
  266. {
  267. if( pszStr )
  268. {
  269. FreeMem((PVOID)pszStr);
  270. }
  271. }
  272. /* Grey Text
  273. *
  274. * If the window has an ID of -1, grey it.
  275. */
  276. BOOL CALLBACK GreyText( HWND hwnd, LPARAM lParam )
  277. {
  278. UNREFERENCED_PARAMETER( lParam );
  279. if( GetDlgCtrlID(hwnd) == (int)(USHORT)-1 )
  280. {
  281. EnableWindow(hwnd, FALSE);
  282. }
  283. return TRUE;
  284. }
  285. /* Macro: FORMSDIFFER
  286. *
  287. * Used to determine whether two forms have any differences between them.
  288. * The Names of the respective forms are not checked.
  289. */
  290. #define FORMSDIFFER( pFormInfoA, pFormInfoB ) \
  291. ( memcmp( &(pFormInfoA)->Size, &(pFormInfoB)->Size, sizeof (pFormInfoA)->Size ) \
  292. ||memcmp( &(pFormInfoA)->ImageableArea, &(pFormInfoB)->ImageableArea, \
  293. sizeof (pFormInfoA)->ImageableArea ) )
  294. /*
  295. * Initalize the forms dialog fields.
  296. */
  297. BOOL FormsInitDialog(HWND hwnd, PFORMS_DLG_DATA pFormsDlgData)
  298. {
  299. DWORD i;
  300. // Get forms dialog data.
  301. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pFormsDlgData);
  302. // Set the foms name limit text.
  303. SendDlgItemMessage(hwnd, IDD_FM_EF_NAME, EM_LIMITTEXT, FORMS_NAME_MAX, 0L);
  304. for( i = 0; pEntryFields[i]; i++ )
  305. {
  306. SendDlgItemMessage(hwnd, pEntryFields[i], EM_LIMITTEXT, FORMS_PARAM_MAX-1, 0L);
  307. }
  308. HWND hWndName;
  309. hWndName = GetDlgItem( hwnd, IDD_FM_EF_NAME );
  310. ::SetWindowLong(hWndName, GWL_STYLE, ::GetWindowLong(hWndName, GWL_STYLE) | WS_CLIPSIBLINGS);
  311. hWndName = GetDlgItem( hwnd, IDD_FM_DESC_GBOX );
  312. ::SetWindowLong(hWndName, GWL_STYLE, ::GetWindowLong(hWndName, GWL_STYLE) | WS_CLIPSIBLINGS);
  313. // Set the forms title name.
  314. SetFormsComputerName(hwnd, pFormsDlgData);
  315. // Read the forms data
  316. InitializeFormsData(hwnd, pFormsDlgData, FALSE);
  317. // Set up the units default based on the current international setting:
  318. pFormsDlgData->Units = pFormsDlgData->uMetricMeasurement;
  319. SETUNITS(hwnd, pFormsDlgData->Units);
  320. if( pFormsDlgData->cForms > 0 )
  321. {
  322. SetFormDescription(hwnd, &pFormsDlgData->pFormInfo[0], pFormsDlgData->Units);
  323. SendDlgItemMessage(hwnd, IDD_FM_LB_FORMS, LB_SETCURSEL, 0, 0L);
  324. }
  325. EnableWindow(GetDlgItem( hwnd, IDD_FM_EF_NAME ), FALSE);
  326. EnableWindow(GetDlgItem( hwnd, IDC_FORMNAME_LABEL ), FALSE);
  327. EnableWindow(GetDlgItem( hwnd, IDD_FM_TX_NEW_FORM ), FALSE);
  328. EnableWindow(GetDlgItem( hwnd, IDD_FM_PB_SAVEFORM ), FALSE);
  329. EnableWindow(GetDlgItem( hwnd, IDD_FM_TX_FORMS_DESC ), TRUE);
  330. if( FALSE == pFormsDlgData->AccessGranted )
  331. {
  332. EnableWindow(GetDlgItem(hwnd, IDD_FM_CK_NEW_FORM), FALSE);
  333. EnableWindow(GetDlgItem(hwnd, IDD_FM_TX_WIDTH), FALSE);
  334. EnableWindow(GetDlgItem(hwnd, IDD_FM_TX_HEIGHT), FALSE);
  335. EnableWindow(GetDlgItem(hwnd, IDD_FM_TX_LEFT), FALSE);
  336. EnableWindow(GetDlgItem(hwnd, IDD_FM_TX_RIGHT), FALSE);
  337. EnableWindow(GetDlgItem(hwnd, IDD_FM_TX_TOP), FALSE);
  338. EnableWindow(GetDlgItem(hwnd, IDD_FM_TX_BOTTOM), FALSE);
  339. // Handle is invalid disable all controls and set error text.
  340. if( !pFormsDlgData->hPrinter )
  341. {
  342. EnableWindow(GetDlgItem(hwnd, IDD_FM_RB_METRIC), FALSE);
  343. EnableWindow(GetDlgItem(hwnd, IDD_FM_RB_ENGLISH), FALSE);
  344. EnableWindow(GetDlgItem(hwnd, IDD_FM_RB_ENGLISH), FALSE);
  345. SetDlgItemTextFromResID(hwnd, IDC_SERVER_NAME, IDS_SERVER_NO_PRINTER_DEFINED);
  346. }
  347. }
  348. // Enable/Disable the dialog controls here
  349. EnableDialogFields(hwnd, pFormsDlgData);
  350. return FALSE;
  351. }
  352. /*
  353. *
  354. */
  355. BOOL FormsCommandAddForm(HWND hwnd)
  356. {
  357. PFORMS_DLG_DATA pFormsDlgData;
  358. INT PrevSel;
  359. FORM_INFO_1 NewFormInfo;
  360. INT i = -1;
  361. //
  362. // If the save form button is disable nothing to do. This
  363. // Check is needed for handling the apply button or ok
  364. // event in a property sheet.
  365. //
  366. if( !IsWindowEnabled(GetDlgItem(hwnd, IDD_FM_PB_SAVEFORM)) )
  367. {
  368. return TRUE;
  369. }
  370. ZeroMemory(&NewFormInfo, sizeof(NewFormInfo));
  371. pFormsDlgData = (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  372. NewFormInfo.pName = GetFormName(hwnd);
  373. if( !NewFormInfo.pName )
  374. {
  375. //
  376. // Out of memory.
  377. //
  378. iMessage( hwnd,
  379. IDS_ERR_FORMS_TITLE,
  380. IDS_ERR_GENERIC,
  381. MB_OK|MB_ICONSTOP,
  382. ERROR_OUTOFMEMORY,
  383. NULL );
  384. // save the last error, so the property sheet won't close
  385. pFormsDlgData->dwLastError = ERROR_OUTOFMEMORY;
  386. goto Cleanup;
  387. }
  388. //
  389. // Check if we are to save and existing form.
  390. //
  391. if( !Button_GetCheck(GetDlgItem(hwnd, IDD_FM_CK_NEW_FORM)) )
  392. {
  393. //
  394. // Check if the form is currently in the list.
  395. //
  396. i = GetFormIndex(NewFormInfo.pName, pFormsDlgData->pFormInfo, pFormsDlgData->cForms);
  397. if( i >= 0 )
  398. {
  399. //
  400. // Preserve the old data.
  401. //
  402. NewFormInfo.Flags = pFormsDlgData->pFormInfo[i].Flags;
  403. NewFormInfo.Size = pFormsDlgData->pFormInfo[i].Size;
  404. NewFormInfo.ImageableArea = pFormsDlgData->pFormInfo[i].ImageableArea;
  405. }
  406. }
  407. //
  408. // Get the form data from the controls & validate it.
  409. //
  410. UINT uIDFailed;
  411. if( !GetFormDescription(hwnd, &NewFormInfo, pFormsDlgData->Units, &uIDFailed) )
  412. {
  413. SetFocus(GetDlgItem(hwnd, uIDFailed));
  414. SendMessage(GetDlgItem(hwnd, uIDFailed), EM_SETSEL, 0, -1);
  415. //
  416. // Form validation failed. Set the focus info the correct control.
  417. //
  418. iMessage( hwnd,
  419. IDS_ERR_FORMS_TITLE,
  420. IDS_FORMS_INVALIDNUMBER,
  421. MB_OK|MB_ICONSTOP,
  422. kMsgNone,
  423. NULL );
  424. // save the last error, so the property sheet won't close
  425. pFormsDlgData->dwLastError = ERROR_INVALID_PARAMETER;
  426. goto Cleanup;
  427. }
  428. //
  429. // Check if we are to save and existing form.
  430. //
  431. if( i >= 0 && FORMSDIFFER(&pFormsDlgData->pFormInfo[i], &NewFormInfo) )
  432. {
  433. //
  434. // Call spooler to set the form data.
  435. //
  436. if( !SetForm(pFormsDlgData->hPrinter, NewFormInfo.pName, 1, (LPBYTE)&NewFormInfo) )
  437. {
  438. //
  439. // Display error message.
  440. //
  441. iMessage( hwnd,
  442. IDS_ERR_FORMS_TITLE,
  443. IDS_ERR_FORMS_COULDNOTSETFORM,
  444. MB_OK|MB_ICONSTOP,
  445. kMsgGetLastError,
  446. NULL,
  447. NewFormInfo.pName );
  448. // save the last error, so the property sheet won't close
  449. pFormsDlgData->dwLastError = GetLastError();
  450. }
  451. else
  452. {
  453. //
  454. // Insure we maintain the previous selection state.
  455. //
  456. i = ListBox_GetCurSel(GetDlgItem( hwnd, IDD_FM_LB_FORMS));
  457. InitializeFormsData(hwnd, pFormsDlgData, TRUE);
  458. ListBox_SetCurSel(GetDlgItem(hwnd, IDD_FM_LB_FORMS), i);
  459. //
  460. // Update controls.
  461. //
  462. SetFormDescription(hwnd, &NewFormInfo, pFormsDlgData->Units);
  463. FormChanged(pFormsDlgData); // notify whoever cares
  464. }
  465. goto Cleanup;
  466. }
  467. if( i < 0 && Button_GetCheck(GetDlgItem(hwnd, IDD_FM_CK_NEW_FORM)) )
  468. {
  469. //
  470. // Add form case.
  471. //
  472. if( (PrevSel = ListBox_GetCurSel(GetDlgItem(hwnd, IDD_FM_LB_FORMS))) < 0 )
  473. {
  474. PrevSel = 0;
  475. }
  476. //
  477. // Check if the new form name is not currently used.
  478. //
  479. LRESULT Status;
  480. Status = SendDlgItemMessage(hwnd,
  481. IDD_FM_LB_FORMS,
  482. LB_FINDSTRINGEXACT,
  483. (WPARAM)-1,
  484. (LPARAM)NewFormInfo.pName );
  485. //
  486. // If string was found.
  487. //
  488. if( Status != LB_ERR )
  489. {
  490. iMessage( hwnd,
  491. IDS_ERR_FORMS_TITLE,
  492. IDS_ERR_FORMS_NAMECONFLICT,
  493. MB_OK|MB_ICONEXCLAMATION,
  494. kMsgNone,
  495. NULL );
  496. // save the last error, so the property sheet won't close
  497. pFormsDlgData->dwLastError = ERROR_INVALID_PARAMETER;
  498. goto Cleanup;
  499. }
  500. if( AddForm(pFormsDlgData->hPrinter, 1, (LPBYTE)&NewFormInfo) )
  501. {
  502. InitializeFormsData(hwnd, pFormsDlgData, TRUE);
  503. // highlight the one we just added:
  504. i = GetFormIndex(NewFormInfo.pName, pFormsDlgData->pFormInfo, pFormsDlgData->cForms);
  505. // if we can't find it, restore the previous selection.
  506. // (This assumes that the last EnumForms returned the same buffer
  507. // as we had last time.)
  508. if( i < 0 )
  509. {
  510. i = (pFormsDlgData->cForms > (DWORD)PrevSel) ? PrevSel : 0;
  511. }
  512. if( pFormsDlgData->cForms > 0 )
  513. {
  514. SetFormDescription(hwnd, &pFormsDlgData->pFormInfo[i], pFormsDlgData->Units);
  515. SendDlgItemMessage(hwnd, IDD_FM_LB_FORMS, LB_SETCURSEL, i, 0L);
  516. }
  517. // the Add button is about to be greyed, it currently
  518. // has focus therefore we will shift the focus to the
  519. // edit box.
  520. SetFocus(GetDlgItem(hwnd, IDD_FM_EF_NAME));
  521. FormChanged(pFormsDlgData); // notify whoever cares
  522. }
  523. else
  524. {
  525. iMessage( hwnd,
  526. IDS_ERR_FORMS_TITLE,
  527. IDS_ERR_FORMS_COULDNOTADDFORM,
  528. MB_OK|MB_ICONSTOP,
  529. kMsgGetLastError,
  530. NULL,
  531. NewFormInfo.pName );
  532. // save the last error, so the property sheet won't close
  533. pFormsDlgData->dwLastError = GetLastError();
  534. }
  535. }
  536. Cleanup:
  537. if( NewFormInfo.pName )
  538. {
  539. FreeStr(NewFormInfo.pName);
  540. }
  541. EnableDialogFields(hwnd, pFormsDlgData);
  542. return TRUE;
  543. }
  544. /*
  545. *
  546. */
  547. BOOL FormsCommandDelForm(HWND hwnd)
  548. {
  549. PFORMS_DLG_DATA pFormsDlgData;
  550. DWORD i;
  551. DWORD TopIndex;
  552. DWORD Count;
  553. LPTSTR pFormName;
  554. pFormsDlgData = (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  555. ASSERT(pFormsDlgData);
  556. i = ListBox_GetCurSel(GetDlgItem(hwnd, IDD_FM_LB_FORMS));
  557. TopIndex = (DWORD)SendDlgItemMessage(hwnd, IDD_FM_LB_FORMS, LB_GETTOPINDEX, 0, 0L);
  558. pFormName = GetFormName(hwnd);
  559. if( DeleteForm(pFormsDlgData->hPrinter, pFormName) )
  560. {
  561. InitializeFormsData(hwnd, pFormsDlgData, TRUE);
  562. Count = (DWORD)SendDlgItemMessage(hwnd, IDD_FM_LB_FORMS, LB_GETCOUNT, 0, 0L);
  563. if( i >= Count )
  564. {
  565. i = ( Count-1 );
  566. }
  567. if( pFormsDlgData->cForms > 0 )
  568. {
  569. SetFormDescription(hwnd, &pFormsDlgData->pFormInfo[i], pFormsDlgData->Units);
  570. SendDlgItemMessage(hwnd, IDD_FM_LB_FORMS, LB_SETCURSEL, i, 0L);
  571. SendDlgItemMessage(hwnd, IDD_FM_LB_FORMS, LB_SETTOPINDEX, TopIndex, 0L);
  572. PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM )GetDlgItem(hwnd, IDD_FM_LB_FORMS), (LPARAM )TRUE);
  573. }
  574. FormChanged(pFormsDlgData); // notify whoever cares
  575. }
  576. else
  577. {
  578. iMessage( hwnd,
  579. IDS_ERR_FORMS_TITLE,
  580. IDS_ERR_FORMS_COULDNOTDELETEFORM,
  581. MB_OK|MB_ICONSTOP,
  582. kMsgGetLastError,
  583. NULL,
  584. pFormName );
  585. }
  586. if( pFormName )
  587. {
  588. FreeStr(pFormName);
  589. }
  590. EnableDialogFields( hwnd, pFormsDlgData );
  591. return TRUE;
  592. }
  593. /*
  594. *
  595. */
  596. BOOL FormsCommandFormsSelChange(HWND hwnd)
  597. {
  598. PFORMS_DLG_DATA pFormsDlgData;
  599. DWORD i;
  600. pFormsDlgData = (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  601. i = ListBox_GetCurSel(GetDlgItem(hwnd, IDD_FM_LB_FORMS));
  602. SetFormDescription(hwnd, &pFormsDlgData->pFormInfo[i], pFormsDlgData->Units);
  603. EnableDialogFields(hwnd, pFormsDlgData);
  604. return TRUE;
  605. }
  606. /*
  607. * User change the units of the currently selected form.
  608. */
  609. BOOL FormsCommandUnits(HWND hwnd)
  610. {
  611. PFORMS_DLG_DATA pFormsDlgData;
  612. INT i;
  613. FORM_INFO_1 FormInfo;
  614. //
  615. // Get dialog data.
  616. //
  617. pFormsDlgData = (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  618. ZeroMemory(&FormInfo, sizeof(FormInfo));
  619. if( pFormsDlgData->Units == GETUNITS(hwnd) )
  620. goto Cleanup;
  621. FormInfo.pName = GetFormName(hwnd);
  622. if( !FormInfo.pName )
  623. {
  624. //
  625. // Out of memory.
  626. //
  627. iMessage( hwnd,
  628. IDS_ERR_FORMS_TITLE,
  629. IDS_ERR_GENERIC,
  630. MB_OK|MB_ICONSTOP,
  631. ERROR_OUTOFMEMORY,
  632. NULL );
  633. goto Cleanup;
  634. }
  635. //
  636. // Check if the form is currently in the list.
  637. //
  638. i = GetFormIndex(FormInfo.pName, pFormsDlgData->pFormInfo, pFormsDlgData->cForms);
  639. if( i >= 0 )
  640. {
  641. //
  642. // Preserve the old data.
  643. //
  644. FormInfo.Flags = pFormsDlgData->pFormInfo[i].Flags;
  645. FormInfo.Size = pFormsDlgData->pFormInfo[i].Size;
  646. FormInfo.ImageableArea = pFormsDlgData->pFormInfo[i].ImageableArea;
  647. }
  648. //
  649. // Get the forms description.
  650. //
  651. UINT uIDFailed;
  652. if( GetFormDescription(hwnd, &FormInfo, pFormsDlgData->Units, &uIDFailed) )
  653. {
  654. //
  655. // Get and save the currently selected units.
  656. //
  657. pFormsDlgData->Units = GETUNITS(hwnd);
  658. //
  659. // Set the forms values.
  660. //
  661. SetValue(hwnd, IDD_FM_EF_WIDTH, FormInfo.Size.cx, pFormsDlgData->Units);
  662. SetValue(hwnd, IDD_FM_EF_HEIGHT, FormInfo.Size.cy, pFormsDlgData->Units);
  663. SetValue(hwnd, IDD_FM_EF_LEFT, FormInfo.ImageableArea.left, pFormsDlgData->Units);
  664. SetValue(hwnd, IDD_FM_EF_RIGHT, FormInfo.Size.cx - FormInfo.ImageableArea.right, pFormsDlgData->Units);
  665. SetValue(hwnd, IDD_FM_EF_TOP, FormInfo.ImageableArea.top, pFormsDlgData->Units);
  666. SetValue(hwnd, IDD_FM_EF_BOTTOM, FormInfo.Size.cy - FormInfo.ImageableArea.bottom, pFormsDlgData->Units);
  667. }
  668. else
  669. {
  670. SETUNITS(hwnd, pFormsDlgData->Units);
  671. SetFocus(GetDlgItem(hwnd, uIDFailed));
  672. SendMessage(GetDlgItem(hwnd, uIDFailed), EM_SETSEL, 0, -1);
  673. //
  674. // Form validation failed. Set the focus info the correct control.
  675. //
  676. iMessage( hwnd,
  677. IDS_ERR_FORMS_TITLE,
  678. IDS_FORMS_INVALIDNUMBER,
  679. MB_OK|MB_ICONSTOP,
  680. kMsgNone,
  681. NULL );
  682. }
  683. Cleanup:
  684. if( FormInfo.pName )
  685. {
  686. FreeStr(FormInfo.pName);
  687. }
  688. return TRUE;
  689. }
  690. /*
  691. *
  692. */
  693. VOID InitializeFormsData(HWND hwnd, PFORMS_DLG_DATA pFormsDlgData, BOOL ResetList)
  694. {
  695. LPFORM_INFO_1 pFormInfo;
  696. DWORD cForms;
  697. DWORD i;
  698. if( ResetList )
  699. {
  700. if( pFormsDlgData->pFormInfo )
  701. {
  702. FreeMem(pFormsDlgData->pFormInfo);
  703. }
  704. }
  705. pFormInfo = GetFormsList(pFormsDlgData->hPrinter, &cForms);
  706. if( !pFormInfo )
  707. {
  708. DBGMSG( DBG_WARNING, ( "GetFormsList failed.\n") );
  709. pFormsDlgData->pFormInfo = NULL;
  710. pFormsDlgData->cForms = 0;
  711. return;
  712. }
  713. pFormsDlgData->pFormInfo = pFormInfo;
  714. pFormsDlgData->cForms = cForms;
  715. if( ResetList )
  716. {
  717. ListBox_ResetContent(GetDlgItem( hwnd, IDD_FM_LB_FORMS));
  718. }
  719. for( i = 0; i < cForms; i++ )
  720. {
  721. SendDlgItemMessage(
  722. hwnd,
  723. IDD_FM_LB_FORMS,
  724. LB_INSERTSTRING,
  725. (WPARAM)-1,
  726. (LPARAM)(LPTSTR)pFormInfo[i].pName
  727. );
  728. }
  729. }
  730. /* GetFormsList
  731. *
  732. * This function works in exactly the same way as GetPortsList.
  733. * There's a good case for writing a generic EnumerateObject function
  734. * (Done!)
  735. */
  736. LPFORM_INFO_1 GetFormsList(HANDLE hPrinter, PDWORD pNumberOfForms)
  737. {
  738. PFORM_INFO_1 pFormInfo = NULL;
  739. TStatusB bStatus;
  740. bStatus DBGCHK = bEnumForms(hPrinter, 1, (PBYTE *)&pFormInfo, pNumberOfForms);
  741. if( bStatus && pFormInfo )
  742. {
  743. //
  744. // Sort the forms list.
  745. //
  746. qsort((PVOID )pFormInfo, (UINT)*pNumberOfForms, sizeof(*pFormInfo), CompareFormNames);
  747. }
  748. return pFormInfo;
  749. }
  750. /*
  751. * CompareFormNames
  752. */
  753. int _cdecl CompareFormNames( const void *p1, const void *p2 )
  754. {
  755. return lstrcmpi( ( (PFORM_INFO_1)p1 )->pName,
  756. ( (PFORM_INFO_1)p2 )->pName );
  757. }
  758. /*
  759. * SetFormsComputerName
  760. */
  761. VOID SetFormsComputerName( HWND hwnd, PFORMS_DLG_DATA pFormsDlgData )
  762. {
  763. //
  764. // Set the title to the name of this machine.
  765. //
  766. SetDlgItemText( hwnd, IDC_SERVER_NAME, pFormsDlgData->pszComputerName );
  767. }
  768. /*
  769. * SetFormDescription
  770. */
  771. VOID SetFormDescription( HWND hwnd, LPFORM_INFO_1 pFormInfo, BOOL Units )
  772. {
  773. SetDlgItemText( hwnd, IDD_FM_EF_NAME, pFormInfo->pName );
  774. SetValue( hwnd, IDD_FM_EF_WIDTH, pFormInfo->Size.cx, Units );
  775. SetValue( hwnd, IDD_FM_EF_HEIGHT, pFormInfo->Size.cy, Units );
  776. SetValue( hwnd, IDD_FM_EF_LEFT, pFormInfo->ImageableArea.left, Units );
  777. SetValue( hwnd, IDD_FM_EF_RIGHT, ( pFormInfo->Size.cx -
  778. pFormInfo->ImageableArea.right ), Units );
  779. SetValue( hwnd, IDD_FM_EF_TOP, pFormInfo->ImageableArea.top, Units );
  780. SetValue( hwnd, IDD_FM_EF_BOTTOM, ( pFormInfo->Size.cy -
  781. pFormInfo->ImageableArea.bottom ), Units );
  782. }
  783. /*
  784. * GetFormDescription
  785. */
  786. BOOL
  787. GetFormDescription(
  788. IN HWND hwnd,
  789. OUT LPFORM_INFO_1 pFormInfo,
  790. IN BOOL bDefaultMetric,
  791. OUT PUINT puIDFailed
  792. )
  793. {
  794. BOOL bReturn = FALSE;
  795. FORM_INFO_1 info;
  796. LONG lRight = pFormInfo->Size.cx - pFormInfo->ImageableArea.right;
  797. LONG lBottom = pFormInfo->Size.cy - pFormInfo->ImageableArea.bottom;
  798. *puIDFailed =
  799. !GetValue(hwnd, IDD_FM_EF_WIDTH, pFormInfo->Size.cx,
  800. bDefaultMetric, &info.Size.cx) ? IDD_FM_EF_WIDTH :
  801. !GetValue(hwnd, IDD_FM_EF_HEIGHT, pFormInfo->Size.cy,
  802. bDefaultMetric, &info.Size.cy) ? IDD_FM_EF_HEIGHT :
  803. !GetValue(hwnd, IDD_FM_EF_LEFT, pFormInfo->ImageableArea.left,
  804. bDefaultMetric, &info.ImageableArea.left) ? IDD_FM_EF_LEFT :
  805. !GetValue(hwnd, IDD_FM_EF_TOP, pFormInfo->ImageableArea.top,
  806. bDefaultMetric, &info.ImageableArea.top) ? IDD_FM_EF_TOP :
  807. !GetValue(hwnd, IDD_FM_EF_RIGHT, lRight,
  808. bDefaultMetric, &lRight) ? IDD_FM_EF_RIGHT :
  809. !GetValue(hwnd, IDD_FM_EF_BOTTOM, lBottom,
  810. bDefaultMetric, &lBottom) ? IDD_FM_EF_BOTTOM :
  811. 0;
  812. // validate top, left, rigt & bottom of the ImageableArea.
  813. if( 0 == *puIDFailed && info.ImageableArea.left >= info.Size.cx )
  814. {
  815. *puIDFailed = IDD_FM_EF_LEFT;
  816. }
  817. if( 0 == *puIDFailed && info.ImageableArea.top >= info.Size.cy )
  818. {
  819. *puIDFailed = IDD_FM_EF_TOP;
  820. }
  821. info.ImageableArea.right = info.Size.cx - lRight;
  822. if( 0 == *puIDFailed && info.ImageableArea.right <= info.ImageableArea.left )
  823. {
  824. *puIDFailed = IDD_FM_EF_RIGHT;
  825. }
  826. info.ImageableArea.bottom = info.Size.cy - lBottom;
  827. if( 0 == *puIDFailed && info.ImageableArea.bottom <= info.ImageableArea.top )
  828. {
  829. *puIDFailed = IDD_FM_EF_BOTTOM;
  830. }
  831. if( 0 == *puIDFailed )
  832. {
  833. pFormInfo->Size = info.Size;
  834. pFormInfo->ImageableArea = info.ImageableArea;
  835. bReturn = TRUE;
  836. }
  837. return bReturn;
  838. }
  839. /* GetFormIndex
  840. *
  841. * Searches an array of FORM_INFO structures for one with name pFormName.
  842. *
  843. * Return:
  844. *
  845. * The index of the form found, or -1 if the form is not found.
  846. */
  847. int GetFormIndex( LPTSTR pFormName, LPFORM_INFO_1 pFormInfo, DWORD cForms )
  848. {
  849. int i = 0;
  850. BOOL Found = FALSE;
  851. while( i < (int)cForms && !( Found = !lstrcmpi( pFormInfo[i].pName, pFormName ) ) )
  852. i++;
  853. if( Found )
  854. return i;
  855. else
  856. return -1;
  857. }
  858. /* GetFormName
  859. *
  860. * Returns a pointer to a newly allocated string containing the form name,
  861. * stripped of leading and trailing blanks.
  862. * Caller must remember to free up the string.
  863. *
  864. */
  865. LPTSTR GetFormName( HWND hwnd )
  866. {
  867. TCHAR FormName[FORMS_NAME_MAX+1];
  868. INT i = 0;
  869. PTCHAR pFormNameWithBlanksStripped;
  870. PTCHAR pReturnFormName = NULL;
  871. if( GetDlgItemText( hwnd, IDD_FM_EF_NAME, FormName, COUNTOF( FormName ) ) > 0 )
  872. {
  873. /* Step over any blank characters at the beginning:
  874. */
  875. while( FormName[i] && ( FormName[i] == TEXT(' ') ) )
  876. i++;
  877. if( FormName[i] )
  878. {
  879. pFormNameWithBlanksStripped = &FormName[i];
  880. /* Find the NULL terminator:
  881. */
  882. while( FormName[i] )
  883. i++;
  884. /* Now step back to find the last character that isn't a blank:
  885. */
  886. if( i > 0 )
  887. i--;
  888. while( ( i > 0 ) && ( FormName[i] == TEXT( ' ' ) ) )
  889. i--;
  890. FormName[i+1] = TEXT( '\0' );
  891. if( *pFormNameWithBlanksStripped )
  892. pReturnFormName = AllocStr( pFormNameWithBlanksStripped );
  893. }
  894. /* Otherwise, the name contains nothing but blanks. */
  895. }
  896. return pReturnFormName;
  897. }
  898. /*
  899. * SetValue
  900. */
  901. BOOL
  902. SetValue(
  903. HWND hwnd,
  904. DWORD uID,
  905. LONG lValueInPoint001mm,
  906. BOOL bMetric
  907. )
  908. {
  909. PFORMS_DLG_DATA pFormsDlgData = (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  910. ASSERT(pFormsDlgData);
  911. TCHAR szValue[FORMS_PARAM_MAX];
  912. BOOL bReturn = Value2String(pFormsDlgData, lValueInPoint001mm, bMetric, TRUE,
  913. ARRAYSIZE(szValue), szValue);
  914. if( bReturn )
  915. {
  916. bReturn = SetDlgItemText(hwnd, uID, szValue);
  917. }
  918. return bReturn;
  919. }
  920. /*
  921. * GetValue
  922. */
  923. BOOL
  924. GetValue(
  925. HWND hwnd,
  926. DWORD uID,
  927. LONG lCurrentValueInPoint001mm,
  928. BOOL bDefaultMetric,
  929. PLONG plValueInPoint001mm
  930. )
  931. {
  932. TCHAR szValue[FORMS_PARAM_MAX];
  933. szValue[0] = 0;
  934. GetDlgItemText(hwnd, uID, szValue, ARRAYSIZE(szValue));
  935. PFORMS_DLG_DATA pFormsDlgData = (PFORMS_DLG_DATA)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  936. return String2Value(pFormsDlgData, szValue, bDefaultMetric, lCurrentValueInPoint001mm, plValueInPoint001mm);
  937. }
  938. /*
  939. * SetDlgItemTextFromResID
  940. */
  941. VOID SetDlgItemTextFromResID(HWND hwnd, int idCtl, int idRes)
  942. {
  943. TCHAR string[kStrMax];
  944. LoadString(ghInst, idRes, string, ARRAYSIZE(string));
  945. SetDlgItemText(hwnd, idCtl, string);
  946. }
  947. /*
  948. *
  949. */
  950. VOID EnableDialogFields( HWND hwnd, PFORMS_DLG_DATA pFormsDlgData )
  951. {
  952. INT i;
  953. BOOL EnableEntryFields = TRUE;
  954. BOOL EnableAddButton = TRUE;
  955. BOOL EnableDeleteButton = TRUE;
  956. LPTSTR pFormName;
  957. // if new form check keep edit fields enabled.
  958. if( Button_GetCheck(GetDlgItem(hwnd, IDD_FM_CK_NEW_FORM)) )
  959. {
  960. vFormsEnableEditFields(hwnd, TRUE);
  961. return;
  962. }
  963. // if not granted all access access.
  964. if( FALSE == pFormsDlgData->AccessGranted == TRUE )
  965. {
  966. EnableWindow(GetDlgItem(hwnd, IDD_FM_EF_NAME), FALSE);
  967. EnableWindow(GetDlgItem(hwnd, IDC_FORMNAME_LABEL), FALSE);
  968. EnableEntryFields = FALSE;
  969. EnableAddButton = FALSE;
  970. EnableDeleteButton = FALSE;
  971. EnumChildWindows(hwnd, GreyText, 0);
  972. }
  973. /* else - See whether the Form Name is new:
  974. */
  975. else if( ( pFormName = GetFormName(hwnd) ) != NULL )
  976. {
  977. /* Now see if the name is already in the list:
  978. */
  979. i = GetFormIndex( pFormName, pFormsDlgData->pFormInfo,
  980. pFormsDlgData->cForms );
  981. if( i >= 0 )
  982. {
  983. /* Can't modify a built-in form:
  984. */
  985. if( pFormsDlgData->pFormInfo[i].Flags & FORM_BUILTIN )
  986. {
  987. EnableEntryFields = FALSE;
  988. EnableDeleteButton = FALSE;
  989. }
  990. else
  991. {
  992. EnableEntryFields = TRUE;
  993. EnableDeleteButton = TRUE;
  994. }
  995. /* Can't add a form with the same name:
  996. */
  997. EnableAddButton = FALSE;
  998. }
  999. else
  1000. {
  1001. EnableDeleteButton = FALSE;
  1002. }
  1003. FreeStr(pFormName);
  1004. }
  1005. else
  1006. {
  1007. /* Name field is blank: Can't add or delete:
  1008. */
  1009. EnableAddButton = FALSE;
  1010. EnableDeleteButton = FALSE;
  1011. }
  1012. // enable the edit fields.
  1013. vFormsEnableEditFields( hwnd, EnableEntryFields );
  1014. // enable the delete button
  1015. EnableWindow( GetDlgItem( hwnd, IDD_FM_PB_DELFORM ), EnableDeleteButton );
  1016. // enable the save form button
  1017. EnableWindow( GetDlgItem( hwnd, IDD_FM_PB_SAVEFORM ), EnableEntryFields );
  1018. }
  1019. /*++
  1020. Routine Name:
  1021. bEnumForms
  1022. Routine Description:
  1023. Enumerates the forms on the printer identified by handle.
  1024. Arguments:
  1025. IN HANDLE hPrinter,
  1026. IN DWORD dwLevel,
  1027. IN PBYTE *ppBuff,
  1028. IN PDWORD pcReturned
  1029. Return Value:
  1030. Pointer to forms array and count of forms in the array if
  1031. success, NULL ponter and zero number of forms if failure.
  1032. TRUE if success, FALSE if error.
  1033. --*/
  1034. BOOL
  1035. bEnumForms(
  1036. IN HANDLE hPrinter,
  1037. IN DWORD dwLevel,
  1038. IN PBYTE *ppBuff,
  1039. IN PDWORD pcReturned
  1040. )
  1041. {
  1042. BOOL bReturn = FALSE;
  1043. DWORD dwReturned = 0;
  1044. DWORD dwNeeded = 0;
  1045. PBYTE p = NULL;
  1046. TStatusB bStatus( DBG_WARN, ERROR_INSUFFICIENT_BUFFER );
  1047. // get buffer size for enum forms.
  1048. bStatus DBGNOCHK = EnumForms(
  1049. hPrinter,
  1050. dwLevel,
  1051. NULL,
  1052. 0,
  1053. &dwNeeded,
  1054. &dwReturned );
  1055. // check if the function returned the buffer size.
  1056. if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  1057. {
  1058. goto Cleanup;
  1059. }
  1060. // if buffer allocation fails.
  1061. if( (p = (PBYTE)AllocMem(dwNeeded) ) == NULL )
  1062. {
  1063. goto Cleanup;
  1064. }
  1065. // get the forms enumeration
  1066. bStatus DBGCHK = EnumForms(
  1067. hPrinter,
  1068. dwLevel,
  1069. p,
  1070. dwNeeded,
  1071. &dwNeeded,
  1072. &dwReturned );
  1073. // copy back the buffer pointer and count.
  1074. if( bStatus )
  1075. {
  1076. bReturn = TRUE;
  1077. *ppBuff = p;
  1078. *pcReturned = dwReturned;
  1079. }
  1080. Cleanup:
  1081. if( bReturn == FALSE )
  1082. {
  1083. // indicate failure.
  1084. *ppBuff = NULL;
  1085. *pcReturned = 0;
  1086. // release any allocated memory.
  1087. if( p )
  1088. {
  1089. FreeMem(p);
  1090. }
  1091. }
  1092. return bReturn;
  1093. }
  1094. /*
  1095. * Checked new forms check box.
  1096. */
  1097. BOOL
  1098. FormsNewForms(
  1099. IN HWND hWnd
  1100. )
  1101. {
  1102. // get Current check state.
  1103. BOOL bState = Button_GetCheck(GetDlgItem(hWnd, IDD_FM_CK_NEW_FORM));
  1104. // set the name edit field.
  1105. EnableWindow(GetDlgItem(hWnd, IDD_FM_EF_NAME), bState);
  1106. EnableWindow(GetDlgItem(hWnd, IDC_FORMNAME_LABEL), bState);
  1107. // set the new form text state.
  1108. EnableWindow(GetDlgItem(hWnd, IDD_FM_TX_NEW_FORM), bState);
  1109. // if enabling new form then the delete button should be disabled.
  1110. if( bState )
  1111. {
  1112. EnableWindow(GetDlgItem(hWnd, IDD_FM_PB_DELFORM), FALSE);
  1113. }
  1114. // Enable the edit fields.
  1115. vFormsEnableEditFields(hWnd, bState);
  1116. // if disabling new forms set edit fields based on
  1117. // current selection.
  1118. if( !bState )
  1119. {
  1120. FormsCommandFormsSelChange(hWnd);
  1121. }
  1122. return FALSE;
  1123. }
  1124. /*
  1125. * vFormsEnableEditFields
  1126. */
  1127. VOID
  1128. vFormsEnableEditFields(
  1129. IN HWND hWnd,
  1130. IN BOOL bState
  1131. )
  1132. {
  1133. UINT i;
  1134. for( i = 0; pEntryFields[i]; i++ )
  1135. {
  1136. EnableWindow( GetDlgItem( hWnd, pEntryFields[i] ), bState );
  1137. }
  1138. for( i = 0; pTextFields[i]; i++ )
  1139. {
  1140. EnableWindow( GetDlgItem( hWnd, pTextFields[i] ), bState );
  1141. }
  1142. }
  1143. //
  1144. // Enable the save form button when the name changes.
  1145. //
  1146. BOOL
  1147. FormsCommandNameChange(
  1148. IN HWND hWnd,
  1149. IN WPARAM wParam,
  1150. IN LPARAM lParam
  1151. )
  1152. {
  1153. BOOL bStatus;
  1154. LPTSTR pFormName = NULL;
  1155. LRESULT Status = TRUE;
  1156. switch( GET_WM_COMMAND_CMD(wParam, lParam) )
  1157. {
  1158. case EN_CHANGE:
  1159. // if the name edit box is not in the enabled state.
  1160. if( !IsWindowEnabled((HWND)lParam) )
  1161. {
  1162. bStatus = FALSE;
  1163. break;
  1164. }
  1165. // Get the form name from the edit control.
  1166. pFormName = GetFormName(hWnd);
  1167. // If a form name was returned.
  1168. if( pFormName )
  1169. {
  1170. // If the name has length then
  1171. // check if it's in the list.
  1172. if( lstrlen(pFormName) )
  1173. {
  1174. // Locate the form name in the list box.
  1175. Status = SendDlgItemMessage(
  1176. hWnd,
  1177. IDD_FM_LB_FORMS,
  1178. LB_FINDSTRINGEXACT,
  1179. (WPARAM)-1,
  1180. (LPARAM)pFormName);
  1181. }
  1182. // Insure we release the form name, since we have
  1183. // adopted the nemory.
  1184. if( pFormName )
  1185. {
  1186. FreeMem(pFormName);
  1187. }
  1188. }
  1189. // Set the save form enable state.
  1190. EnableWindow(GetDlgItem(hWnd, IDD_FM_PB_SAVEFORM), Status == LB_ERR ? TRUE : FALSE);
  1191. bStatus = TRUE;
  1192. break;
  1193. default:
  1194. bStatus = FALSE;
  1195. break;
  1196. }
  1197. return bStatus;
  1198. }
  1199. BOOL
  1200. String2Value(
  1201. IN PFORMS_DLG_DATA pFormsDlgData,
  1202. IN LPCTSTR pszValue,
  1203. IN BOOL bDefaultMetric,
  1204. IN LONG lCurrentValueInPoint001mm,
  1205. OUT PLONG plValueInPoint001mm
  1206. )
  1207. {
  1208. ASSERT(pFormsDlgData);
  1209. ASSERT(pszValue);
  1210. ASSERT(plValueInPoint001mm);
  1211. double dValue = 0.0;
  1212. *plValueInPoint001mm = 0;
  1213. BOOL bMetric = bDefaultMetric;
  1214. BOOL bResult = TRUE;
  1215. if( *pszValue )
  1216. {
  1217. // make a copy of the input string
  1218. TCHAR szValue[FORMS_PARAM_MAX];
  1219. lstrcpyn(szValue, pszValue, ARRAYSIZE(szValue));
  1220. // convert international decimal separator, if necessary:
  1221. if( *pFormsDlgData->szDecimalPoint != TEXT('.') )
  1222. {
  1223. TCHAR *p = szValue;
  1224. while( *p )
  1225. {
  1226. if( *p == *pFormsDlgData->szDecimalPoint )
  1227. {
  1228. *p = TEXT('.');
  1229. }
  1230. p++;
  1231. }
  1232. }
  1233. // convert to double, pGarbage should be "in" or "cm" (depends on metric)
  1234. TCHAR *pGarbage = NULL;
  1235. dValue = _tcstod(szValue, &pGarbage);
  1236. ASSERT(pGarbage);
  1237. // load the measurement strings from resource
  1238. TCHAR szUnitsIn[CCH_MAX_UNITS];
  1239. TCHAR szUnitsCm[CCH_MAX_UNITS];
  1240. bResult = LoadString(ghInst, IDS_INCHES, szUnitsIn, ARRAYSIZE(szUnitsIn)) &&
  1241. LoadString(ghInst, IDS_CENTIMETERS, szUnitsCm, ARRAYSIZE(szUnitsCm));
  1242. if( bResult )
  1243. {
  1244. // check to validate the converted number
  1245. if( dValue < 0.0 )
  1246. {
  1247. // negative values are invalid
  1248. bResult = FALSE;
  1249. }
  1250. else if( 0 == lstrcmpi(pGarbage, szUnitsIn) )
  1251. {
  1252. // enforce inches
  1253. bMetric = FALSE;
  1254. }
  1255. else if( 0 == lstrcmpi(pGarbage, szUnitsCm) )
  1256. {
  1257. // enforce centimeters
  1258. bMetric = TRUE;
  1259. }
  1260. else if( lstrlen(pGarbage) )
  1261. {
  1262. // pGarbage is neither "in" nor "cm" - error!
  1263. bResult = FALSE;
  1264. }
  1265. }
  1266. if( bResult )
  1267. {
  1268. TCHAR szCurrentValue[FORMS_PARAM_MAX];
  1269. // cut the garbage first
  1270. *pGarbage = 0;
  1271. // if the converted number is valid, check to see if not the
  1272. // same as the current one...
  1273. if( bMetric == bDefaultMetric &&
  1274. Value2String(pFormsDlgData, lCurrentValueInPoint001mm,
  1275. bDefaultMetric, FALSE, ARRAYSIZE(szCurrentValue), szCurrentValue) &&
  1276. 0 == lstrcmp(szCurrentValue, szValue) )
  1277. {
  1278. // it is the same. don't recalc, so we don't loose precision.
  1279. *plValueInPoint001mm = lCurrentValueInPoint001mm;
  1280. }
  1281. else
  1282. {
  1283. // calculate in point001mm
  1284. *plValueInPoint001mm = (DWORD)(dValue * (bMetric ? 100*100 : 254*100));
  1285. }
  1286. }
  1287. }
  1288. return bResult;
  1289. }
  1290. BOOL
  1291. Value2String(
  1292. IN PFORMS_DLG_DATA pFormsDlgData,
  1293. IN LONG lValueInPoint001mm,
  1294. IN BOOL bMetric,
  1295. IN BOOL bAppendMetric,
  1296. IN UINT cchMaxChars,
  1297. OUT LPTSTR szOutBuffer
  1298. )
  1299. {
  1300. ASSERT(pFormsDlgData);
  1301. ASSERT(szOutBuffer);
  1302. BOOL bReturn = FALSE;
  1303. static const TCHAR szFormat[] = TEXT("%d%s%02d%s");
  1304. static const TCHAR szFormat1[] = TEXT("%d%s%02d");
  1305. TCHAR szUnits[CCH_MAX_UNITS];
  1306. DWORD dwUnitsX100 = (DWORD)((lValueInPoint001mm / (bMetric ? 100.0 : 254.0)) + 0.5);
  1307. if( LoadString(ghInst, bMetric ? IDS_CENTIMETERS: IDS_INCHES, szUnits, ARRAYSIZE(szUnits)) )
  1308. {
  1309. wnsprintf(szOutBuffer, cchMaxChars, bAppendMetric ? szFormat : szFormat1,
  1310. dwUnitsX100 / 100, pFormsDlgData->szDecimalPoint, dwUnitsX100 % 100, szUnits);
  1311. bReturn = TRUE;
  1312. }
  1313. return bReturn;
  1314. }
  1315. VOID
  1316. FormChanged(
  1317. IN OUT PFORMS_DLG_DATA pFormsDlgData
  1318. )
  1319. {
  1320. // if part of property sheet this will notify the UI to
  1321. // call PSM_CANCELTOCLOSE
  1322. pFormsDlgData->bFormChanged = TRUE;
  1323. }
  1324. BOOL
  1325. Forms_IsThereCommitedChanges(
  1326. IN PVOID pFormsData
  1327. )
  1328. {
  1329. ASSERT(pFormsData);
  1330. PFORMS_DLG_DATA pFormsDlgData = (PFORMS_DLG_DATA)pFormsData;
  1331. return pFormsDlgData->bFormChanged;
  1332. }
  1333. DWORD
  1334. Forms_GetLastError(
  1335. IN PVOID pFormsData
  1336. )
  1337. {
  1338. ASSERT(pFormsData);
  1339. PFORMS_DLG_DATA pFormsDlgData = (PFORMS_DLG_DATA)pFormsData;
  1340. return pFormsDlgData->dwLastError;
  1341. }