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.

2450 lines
92 KiB

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // propdlg.c
  4. //
  5. // The Properties dialog for MS Office.
  6. //
  7. // Change history:
  8. //
  9. // Date Who What
  10. // --------------------------------------------------------------------------
  11. // 06/09/94 B. Wentz Created file
  12. // 01/16/95 martinth Finished sticky dlg stuff.
  13. // We have to call ApplyStickyDlgCoor
  14. // in the first WM_INITDIALOG, don't ask me why,
  15. // but otherwise we have redraw problems. Likewise,
  16. // we have to call SetStickyDlgCoor in the first
  17. // PSN_RESET/PSN_APPLY, I have no idea why, since
  18. // the main dialog shouldn't have been deleted but
  19. // it is. Thus we have to add calls everywhere.
  20. // Could it be that the tabs are getting deleted
  21. // one by one and the dialog changes size? Dunno.
  22. // But this works, so change at your own risk!;-)
  23. // 07/08/96 MikeHill Ignore unsupported (non-UDTYPE) properties.
  24. ////////////////////////////////////////////////////////////////////////////////
  25. #include "priv.h"
  26. #pragma hdrstop
  27. int ScanDateNums(TCHAR *pch, TCHAR *pszSep, unsigned int aiNum[], int cNum, int iYear);
  28. BOOL PASCAL FConvertDate(LPTSTR lpstz, DWORD cchMax, LPFILETIME lpft);
  29. #include "propdlg.h"
  30. #include "strings.h"
  31. #include "msohelp.h"
  32. // Max size of time/date string
  33. #define TIMEDATEMAX 256
  34. // Check button actions
  35. #define CLEAR 0
  36. #define CHECKED 1
  37. #define GREYED 2
  38. // Number of property sheet pages
  39. #define PAGESMAX 5
  40. // Max size for "short" temp buffers
  41. #define SHORTBUFMAX 128
  42. // The pages
  43. #define itabCUSTOM 0
  44. #define itabFIRST itabCUSTOM
  45. // Defines for printing file sizes
  46. #define DELIMITER TEXT(',')
  47. #define iszBYTES 0
  48. #define iszORDERKB 1
  49. #define iszORDERMB 2
  50. #define iszORDERGB 3
  51. #define iszORDERTB 4
  52. static TCHAR rgszOrders[iszORDERTB+1][SHORTBUFMAX];
  53. // "bytes", // iszBYTES
  54. // "KB", // iszORDERKB
  55. // "MB", // iszORDERMB
  56. // "GB", // iszORDERGB
  57. // "TB" // iszORDERTB
  58. // note that szBYTES is defined above...
  59. #define iszPAGES 1
  60. #define iszPARA 2
  61. #define iszLINES 3
  62. #define iszWORDS 4
  63. #define iszCHARS 5
  64. #define iszSLIDES 6
  65. #define iszNOTES 7
  66. #define iszHIDDENSLIDES 8
  67. #define iszMMCLIPS 9
  68. #define iszFORMAT 10
  69. // Strings for the statistics listbox
  70. static TCHAR rgszStats[iszFORMAT+1][SHORTBUFMAX];
  71. // "Bytes:", // iszBYTES
  72. // "Pages:", // iszPAGES
  73. // "Paragraphs:", // iszPARA
  74. // "Lines:", // iszLINES
  75. // "Words:", // iszWORDS
  76. // "Characters:", // iszCHARS
  77. // "Slides:", // iszSLIDES
  78. // "Notes:", // iszNOTES
  79. // "Hidden Slides:", // iszHIDDENSLIDES
  80. // "Multimedia Clips:", // iszMMCLIPS
  81. // "Presentation Format:"// iszFORMAT
  82. #define BASE10 10
  83. // Number of pre-defined custom names
  84. #define NUM_BUILTIN_CUSTOM_NAMES 27
  85. #define iszTEXT 0
  86. #define iszDATE 1
  87. #define iszNUM 2
  88. #define iszBOOL 3
  89. #define iszUNKNOWN 4
  90. // Strings for the types of user-defined properties
  91. static TCHAR rgszTypes[iszUNKNOWN+1][SHORTBUFMAX];
  92. // "Text", // iszTEXT
  93. // "Date", // iszDATE
  94. // "Number", // iszNUM
  95. // "Yes or No", // iszBOOL
  96. // "Unknown" // iszUNKNOWN
  97. #define iszNAME 0
  98. #define iszVAL 1
  99. #define iszTYPE 2
  100. // Strings for the column headings for the statistics tab
  101. static TCHAR rgszStatHeadings[iszVAL+1][SHORTBUFMAX];
  102. // "Statistic Name", // iszNAME
  103. // "Value" // iszVAL
  104. // Strings for the column headings for custom tab
  105. static TCHAR rgszHeadings[iszTYPE+1][SHORTBUFMAX];
  106. // "Property Name", // iszNAME
  107. // "Value", // iszVAL
  108. // "Type" // iszTYPE
  109. #define iszTRUE 0
  110. #define iszFALSE 1
  111. // Strings for Booleans
  112. static TCHAR rgszBOOL[iszFALSE+1][SHORTBUFMAX];
  113. // "Yes", // iszTRUE
  114. // "No" // iszFALSE
  115. #define iszADD 0
  116. #define iszMODIFY 1
  117. // Strings for the Add button
  118. static TCHAR rgszAdd[iszMODIFY+1][SHORTBUFMAX];
  119. // "Add", // iszADD
  120. // "Modify" // iszMODIFY
  121. #define iszVALUE 0
  122. #define iszSOURCE 1
  123. // Strings for the source/value caption
  124. static TCHAR rgszValue[iszSOURCE+1][SHORTBUFMAX];
  125. // "Value:", // iszVALUE
  126. // "Source:" // iszSOURCE
  127. // Date formatting codes
  128. #define MMDDYY TEXT('0')
  129. #define DDMMYY TEXT('1')
  130. #define YYMMDD TEXT('2')
  131. #define OLEEPOCH 1900
  132. #define SYSEPOCH 1601
  133. #define ONECENTURY 100
  134. #define YEARINCENTURY(year) ((year) % ONECENTURY)
  135. #define CENTURYFROMYEAR(year) ((year) - YEARINCENTURY(year))
  136. //
  137. // Global data, to be deleted when FShowOfficePropDlg exits
  138. //
  139. static LPTSTR glpstzName;
  140. static LPTSTR glpstzValue;
  141. static int giLinkIcon;
  142. static int giInvLinkIcon;
  143. static int giBlankIcon;
  144. static HBRUSH hBrushPropDlg = NULL;
  145. const TCHAR g_szHelpFile[] = TEXT("windows.hlp");
  146. //
  147. // Internal prototypes
  148. //
  149. INT_PTR CALLBACK FGeneralDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  150. INT_PTR CALLBACK FSummaryDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  151. INT_PTR CALLBACK FStatisticsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  152. INT_PTR CALLBACK FCustomDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  153. INT_PTR CALLBACK FContentsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  154. INT_PTR CALLBACK FPropHeaderDlgProc (HWND hwnd, UINT message, LONG lParam);
  155. //static int CALLBACK ListViewCompareFunc(LPARAM, LPARAM, LPARAM);
  156. void PASCAL SetEditValLpsz (LPPROPVARIANT lppropvar, HWND hdlg, DWORD dwID );
  157. BOOL PASCAL GetEditValLpsz (LPPROPVARIANT lppropvar, HWND hDlg, DWORD dwId);
  158. BOOL PASCAL FAllocAndGetValLpstz (HWND hDlg, DWORD dwId, LPTSTR *lplpstz);
  159. BOOL PASCAL FAllocString (LPTSTR *lplpstz, DWORD cb);
  160. void PASCAL ClearEditControl (HWND hDlg, DWORD dwId);
  161. UDTYPES PASCAL UdtypesGetNumberType (LPTSTR lpstz, NUM *lpnumval,
  162. BOOL (*lpfnFSzToNum)(NUM *, LPTSTR));
  163. void PASCAL PrintTimeInDlg (HWND hDlg, DWORD dwId, FILETIME *pft);
  164. void PASCAL PrintEditTimeInDlg (HWND hDlg, FILETIME *pft);
  165. void PASCAL PopulateUDListView (HWND hWnd, LPUDOBJ lpUDObj);
  166. void PASCAL AddUDPropToListView (LPUDOBJ lpUDObj, HWND hWnd, LPTSTR lpszName, LPPROPVARIANT lppropvar, int iItem,
  167. BOOL fLink, BOOL fLinkInvalid, BOOL fMakeVisible);
  168. VOID PASCAL InitListView (HWND hDlg, int irgLast, TCHAR rgsz[][SHORTBUFMAX], BOOL fImageList);
  169. WORD PASCAL WUdtypeToSz (LPPROPVARIANT lppropvar, LPTSTR sz, DWORD cchMax,
  170. BOOL (*lpfnFNumToSz)(NUM *, LPTSTR, DWORD));
  171. BOOL PASCAL FSwapControls (HWND hWndVal, HWND hWndLinkVal, HWND hWndBoolTrue, HWND hWndBoolFalse, HWND hWndGroup, HWND hWndType, HWND hWndValText, BOOL fLink, BOOL fBool);
  172. VOID PASCAL PopulateControls (LPUDOBJ lpUDObj, LPTSTR szName, DWORD cLinks, DWQUERYLD lpfnDwQueryLinkData, HWND hDlg,
  173. HWND hWndName, HWND hWndVal, HWND hWndValText, HWND hWndLink, HWND hWndLinkVal, HWND hWndType,
  174. HWND hWndBoolTrue, HWND hWndBoolFalse, HWND hWndGroup, HWND hWndAdd, HWND hWndDelete, BOOL *pfLink, BOOL *pfAdd);
  175. BOOL PASCAL FSetupAddButton (DWORD iszType, BOOL fLink, BOOL *pfAdd, HWND hWndAdd, HWND hWndVal, HWND hWndName, HWND hDlg);
  176. BOOL PASCAL FCreateListOfLinks (DWORD cLinks, DWQUERYLD lpfnDwQueryLinkData, HWND hWndLinkVal);
  177. BOOL PASCAL FSetTypeControl (UDTYPES udtype, HWND hWndType);
  178. void PASCAL DeleteItem (LPUDOBJ lpUDObj, HWND hWndLV, int iItem, TCHAR sz[]);
  179. void PASCAL ResetTypeControl (HWND hDlg, DWORD dwId, DWORD *piszType);
  180. BOOL PASCAL FDisplayConversionWarning (HWND hDlg);
  181. BOOL PASCAL FLoadTextStrings (void);
  182. BOOL FGetCustomPropFromDlg(LPALLOBJS lpallobjs, HWND hDlg);
  183. VOID SetCustomDlgDefButton(HWND hDlg, int IDNew);
  184. INT PASCAL ISavePropDlgChanges(LPALLOBJS, HWND, HWND);
  185. /* WinHelp stuff. */
  186. static const DWORD rgIdhGeneral[] =
  187. {
  188. IDD_ITEMICON, IDH_GENERAL_ICON,
  189. IDD_NAME, IDH_GENERAL_NAME_BY_ICON,
  190. IDD_FILETYPE, IDH_GENERAL_FILETYPE,
  191. IDD_FILETYPE_LABEL, IDH_GENERAL_FILETYPE,
  192. IDD_LOCATION, IDH_GENERAL_LOCATION,
  193. IDD_LOCATION_LABEL, IDH_GENERAL_LOCATION,
  194. IDD_FILESIZE, IDH_GENERAL_FILESIZE,
  195. IDD_FILESIZE_LABEL, IDH_GENERAL_FILESIZE,
  196. IDD_FILENAME, IDH_GENERAL_MSDOSNAME,
  197. IDD_FILENAME_LABEL, IDH_GENERAL_MSDOSNAME,
  198. IDD_CREATED, IDH_GENERAL_CREATED,
  199. IDD_CREATED_LABEL, IDH_GENERAL_CREATED,
  200. IDD_LASTMODIFIED, IDH_GENERAL_MODIFIED,
  201. IDD_LASTMODIFIED_LABEL, IDH_GENERAL_MODIFIED,
  202. IDD_LASTACCESSED, IDH_GENERAL_ACCESSED,
  203. IDD_LASTACCESSED_LABEL, IDH_GENERAL_ACCESSED,
  204. IDD_ATTRIBUTES_LABEL, IDH_GENERAL_ATTRIBUTES,
  205. IDD_READONLY, IDH_GENERAL_READONLY,
  206. IDD_HIDDEN, IDH_GENERAL_HIDDEN,
  207. IDD_ARCHIVE, IDH_GENERAL_ARCHIVE,
  208. IDD_SYSTEM, IDH_GENERAL_SYSTEM
  209. };
  210. static const DWORD rgIdhSummary[] =
  211. {
  212. IDD_SUMMARY_TITLE, IDH_SUMMARY_TITLE,
  213. IDD_SUMMARY_TITLE_LABEL, IDH_SUMMARY_TITLE,
  214. IDD_SUMMARY_SUBJECT, IDH_SUMMARY_SUBJECT,
  215. IDD_SUMMARY_SUBJECT_LABEL, IDH_SUMMARY_SUBJECT,
  216. IDD_SUMMARY_AUTHOR, IDH_SUMMARY_AUTHOR,
  217. IDD_SUMMARY_AUTHOR_LABEL, IDH_SUMMARY_AUTHOR,
  218. IDD_SUMMARY_MANAGER, IDH_SUMMARY_MANAGER,
  219. IDD_SUMMARY_MANAGER_LABEL, IDH_SUMMARY_MANAGER,
  220. IDD_SUMMARY_COMPANY, IDH_SUMMARY_COMPANY,
  221. IDD_SUMMARY_COMPANY_LABEL, IDH_SUMMARY_COMPANY,
  222. IDD_SUMMARY_CATEGORY, IDH_SUMMARY_CATEGORY,
  223. IDD_SUMMARY_CATEGORY_LABEL, IDH_SUMMARY_CATEGORY,
  224. IDD_SUMMARY_KEYWORDS, IDH_SUMMARY_KEYWORDS,
  225. IDD_SUMMARY_KEYWORDS_LABEL, IDH_SUMMARY_KEYWORDS,
  226. IDD_SUMMARY_COMMENTS, IDH_SUMMARY_COMMENTS,
  227. IDD_SUMMARY_COMMENTS_LABEL, IDH_SUMMARY_COMMENTS,
  228. IDD_SUMMARY_TEMPLATE, IDH_SUMMARY_TEMPLATE,
  229. IDD_SUMMARY_TEMPLATETEXT, IDH_SUMMARY_TEMPLATE,
  230. IDD_SUMMARY_SAVEPREVIEW, IDH_SUMMARY_SAVEPREVIEW
  231. };
  232. static const DWORD rgIdhStatistics[] =
  233. {
  234. IDD_STATISTICS_CREATED, IDH_STATISTICS_CREATED,
  235. IDD_STATISTICS_CREATED_LABEL, IDH_STATISTICS_CREATED,
  236. IDD_STATISTICS_CHANGED, IDH_STATISTICS_MODIFIED,
  237. IDD_STATISTICS_CHANGED_LABEL, IDH_STATISTICS_MODIFIED,
  238. IDD_STATISTICS_ACCESSED, IDH_STATISTICS_ACCESSED,
  239. IDD_STATISTICS_ACCESSED_LABEL, IDH_STATISTICS_ACCESSED,
  240. IDD_STATISTICS_LASTPRINT, IDH_STATISTICS_LASTPRINT,
  241. IDD_STATISTICS_LASTPRINT_LABEL, IDH_STATISTICS_LASTPRINT,
  242. IDD_STATISTICS_LASTSAVEBY, IDH_STATISTICS_LASTSAVEBY,
  243. IDD_STATISTICS_LASTSAVEBY_LABEL, IDH_STATISTICS_LASTSAVEBY,
  244. IDD_STATISTICS_REVISION, IDH_STATISTICS_REVISION,
  245. IDD_STATISTICS_REVISION_LABEL, IDH_STATISTICS_REVISION,
  246. IDD_STATISTICS_TOTALEDIT, IDH_STATISTICS_TOTALEDIT,
  247. IDD_STATISTICS_TOTALEDIT_LABEL, IDH_STATISTICS_TOTALEDIT,
  248. IDD_STATISTICS_LVLABEL, IDH_STATISTICS_LISTVIEW,
  249. IDD_STATISTICS_LISTVIEW, IDH_STATISTICS_LISTVIEW
  250. };
  251. static const DWORD rgIdhContents[] =
  252. {
  253. IDD_CONTENTS_LISTBOX_LABEL, IDH_CONTENTS_LISTBOX,
  254. IDD_CONTENTS_LISTBOX, IDH_CONTENTS_LISTBOX
  255. };
  256. static const DWORD rgIdhCustom[] =
  257. {
  258. IDD_CUSTOM_NAME, IDH_CUSTOM_NAME,
  259. IDD_CUSTOM_NAME_LABEL, IDH_CUSTOM_NAME,
  260. IDD_CUSTOM_TYPE, IDH_CUSTOM_TYPE,
  261. IDD_CUSTOM_TYPE_LABEL, IDH_CUSTOM_TYPE,
  262. IDD_CUSTOM_VALUE, IDH_CUSTOM_VALUE,
  263. IDD_CUSTOM_VALUETEXT, IDH_CUSTOM_VALUE,
  264. IDD_CUSTOM_LINKVALUE, IDH_CUSTOM_LINKVALUE,
  265. IDD_CUSTOM_BOOLTRUE, IDH_CUSTOM_BOOLYES,
  266. IDD_CUSTOM_BOOLFALSE, IDH_CUSTOM_BOOLYES,
  267. IDD_CUSTOM_ADD, IDH_CUSTOM_ADDBUTTON,
  268. IDD_CUSTOM_DELETE, IDH_CUSTOM_DELETEBUTTON,
  269. IDD_CUSTOM_LINK, IDH_CUSTOM_LINKCHECK,
  270. IDD_CUSTOM_LISTVIEW, IDH_CUSTOM_LISTVIEW,
  271. IDD_CUSTOM_LISTVIEW_LABEL, IDH_CUSTOM_LISTVIEW
  272. };
  273. void FOfficeInitPropInfo(PROPSHEETPAGE * lpPsp, DWORD dwFlags, LPARAM lParam, LPFNPSPCALLBACK pfnCallback)
  274. {
  275. lpPsp[itabCUSTOM-itabFIRST].dwSize = sizeof(PROPSHEETPAGE);
  276. lpPsp[itabCUSTOM-itabFIRST].dwFlags = dwFlags;
  277. lpPsp[itabCUSTOM-itabFIRST].hInstance = g_hmodThisDll;
  278. lpPsp[itabCUSTOM-itabFIRST].pszTemplate = MAKEINTRESOURCE (IDD_CUSTOM);
  279. lpPsp[itabCUSTOM-itabFIRST].pszIcon = NULL;
  280. lpPsp[itabCUSTOM-itabFIRST].pszTitle = NULL;
  281. lpPsp[itabCUSTOM-itabFIRST].pfnDlgProc = FCustomDlgProc;
  282. lpPsp[itabCUSTOM-itabFIRST].pfnCallback = pfnCallback;
  283. lpPsp[itabCUSTOM-itabFIRST].pcRefParent = NULL;
  284. lpPsp[itabCUSTOM-itabFIRST].lParam = lParam;
  285. }
  286. ////////////////////////////////////////////////////////////////////////////////
  287. //
  288. // Attach
  289. //
  290. // Purpose:
  291. // Assigns HPROPSHEETPAGE to appropriate data block member.
  292. //
  293. ////////////////////////////////////////////////////////////////////////////////
  294. BOOL FAttach( LPALLOBJS lpallobjs, PROPSHEETPAGE* ppsp, HPROPSHEETPAGE hPage )
  295. {
  296. #define ASSIGN_PAGE_HANDLE( pfn, phpage ) \
  297. if( ppsp->pfnDlgProc == pfn ) { *(phpage) = hPage ; return TRUE ; }
  298. ASSIGN_PAGE_HANDLE( FCustomDlgProc, &lpallobjs->lpUDObj->m_hPage );
  299. return FALSE;
  300. }
  301. ////////////////////////////////////////////////////////////////////////////////
  302. //
  303. // PropPageInit
  304. //
  305. // Purpose:
  306. // Keep track which pages have been init, such that we can know when we
  307. // can do the apply.
  308. //
  309. ////////////////////////////////////////////////////////////////////////////////
  310. void PropPageInit(LPALLOBJS lpallobjs, int iPage)
  311. {
  312. if (iPage > lpallobjs->iMaxPageInit)
  313. lpallobjs->iMaxPageInit = iPage;
  314. }
  315. ////////////////////////////////////////////////////////////////////////////////
  316. //
  317. // ApplyChangesBackToFile
  318. //
  319. // Purpose:
  320. // See if this is now the time to apply the changes back to the file
  321. //
  322. ////////////////////////////////////////////////////////////////////////////////
  323. BOOL ApplyChangesBackToFile(
  324. HWND hDlg,
  325. BOOL bFinalEdit /* user clicked OK rather than Apply*/,
  326. LPALLOBJS lpallobjs,
  327. int iPage)
  328. {
  329. HRESULT hres;
  330. BOOL fOK = FALSE;
  331. LPSTORAGE lpStg;
  332. WCHAR wszPath[ MAX_PATH ];
  333. if (iPage != lpallobjs->iMaxPageInit)
  334. return TRUE; // no errors
  335. hres = StringCchCopy(wszPath, ARRAYSIZE(wszPath), lpallobjs->szPath);
  336. if (SUCCEEDED(hres))
  337. {
  338. hres = StgOpenStorageEx(wszPath,STGM_READWRITE|STGM_SHARE_EXCLUSIVE,STGFMT_ANY,0,NULL,NULL,
  339. &IID_IStorage, (void**)&lpStg );
  340. }
  341. if (SUCCEEDED(hres) && lpStg)
  342. {
  343. fOK = (BOOL)DwOfficeSaveProperties( lpStg,
  344. lpallobjs->lpSIObj,
  345. lpallobjs->lpDSIObj,
  346. lpallobjs->lpUDObj,
  347. 0, // Flags
  348. STGM_READWRITE | STGM_SHARE_EXCLUSIVE
  349. );
  350. // Release the Storage (we don't need to commit it;
  351. // it's in dicrect-mode).
  352. lpStg->lpVtbl->Release (lpStg);
  353. lpStg= NULL;
  354. //
  355. // if we did properly save out the properties, than we should
  356. // clear the we have changed things flag...
  357. //
  358. if (fOK)
  359. {
  360. lpallobjs->fPropDlgChanged = FALSE;
  361. lpallobjs->fPropDlgPrompted = FALSE;
  362. }
  363. } // if (SUCCEEDED(hres) && lpStorage)
  364. if (!fOK)
  365. {
  366. UINT nMsgFlags = bFinalEdit ? MB_OKCANCEL /* give option to not dismiss page*/ : MB_OK;
  367. if (ShellMessageBox(g_hmodThisDll, GetParent(hDlg),
  368. MAKEINTRESOURCE(idsErrorOnSave), NULL,
  369. nMsgFlags | MB_ICONHAND, PathFindFileName(lpallobjs->szPath)) == IDOK)
  370. {
  371. fOK = TRUE;
  372. }
  373. PropSheet_UnChanged(GetParent(hDlg), hDlg);
  374. }
  375. return fOK;
  376. } // ApplyChangesBackToFile
  377. int gOKButtonID; // need this to store the ID of the OK button, since it's not in the dlg template
  378. ////////////////////////////////////////////////////////////////////////////////
  379. //
  380. // FCustomDlgProc
  381. //
  382. // Purpose:
  383. // Custom tab control
  384. //
  385. ////////////////////////////////////////////////////////////////////////////////
  386. INT_PTR CALLBACK FCustomDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  387. {
  388. LPALLOBJS lpallobjs = (LPALLOBJS)GetWindowLongPtr(hDlg, DWLP_USER);
  389. switch (message)
  390. {
  391. case WM_INITDIALOG:
  392. {
  393. PROPSHEETPAGE *ppspDlg = (PROPSHEETPAGE *) lParam;
  394. int irg;
  395. HICON hIcon, hInvIcon;
  396. lpallobjs = (LPALLOBJS)ppspDlg->lParam;
  397. PropPageInit(lpallobjs, itabCUSTOM);
  398. SetWindowLongPtr(hDlg, DWLP_USER, ppspDlg->lParam);
  399. gOKButtonID = LOWORD(SendMessage(hDlg, DM_GETDEFID, 0L, 0L));
  400. AssertSz ((sizeof(NUM) == (sizeof(FILETIME))), TEXT("Ok, who changed base type sizes?"));
  401. //
  402. // Fill out the Name dropdown
  403. //
  404. for (irg = 0; irg < NUM_BUILTIN_CUSTOM_NAMES; ++irg)
  405. {
  406. if (CchGetString( idsCustomName1+ irg,
  407. lpallobjs->CDP_sz,
  408. sizeof(lpallobjs->CDP_sz))
  409. )
  410. {
  411. SendDlgItemMessage(hDlg, IDD_CUSTOM_NAME, CB_ADDSTRING, 0, (LPARAM)lpallobjs->CDP_sz);
  412. }
  413. // else, just don't add it
  414. }
  415. //
  416. // Fill out the type drop-down & select the text type
  417. //
  418. for (irg = 0; irg <= iszBOOL; irg++)
  419. {
  420. SendDlgItemMessage(hDlg, IDD_CUSTOM_TYPE, CB_ADDSTRING, 0, (LPARAM) rgszTypes[irg]);
  421. }
  422. ResetTypeControl (hDlg, IDD_CUSTOM_TYPE, &lpallobjs->CDP_iszType);
  423. //
  424. // Set the link checkbox to be off.
  425. //
  426. lpallobjs->CDP_fLink = FALSE;
  427. SendDlgItemMessage( hDlg,
  428. IDD_CUSTOM_LINK,
  429. BM_SETCHECK,
  430. (WPARAM) lpallobjs->CDP_fLink,
  431. 0
  432. );
  433. ShowWindow( GetDlgItem( hDlg, IDD_CUSTOM_LINK ), SW_HIDE );
  434. SendDlgItemMessage( hDlg,
  435. IDD_CUSTOM_VALUETEXT,
  436. WM_SETTEXT,
  437. 0,
  438. (LPARAM) rgszValue[iszVALUE]
  439. );
  440. //
  441. // Hang on to the window handle of the value edit control & others
  442. //
  443. lpallobjs->CDP_hWndVal = GetDlgItem (hDlg, IDD_CUSTOM_VALUE);
  444. lpallobjs->CDP_hWndName = GetDlgItem (hDlg, IDD_CUSTOM_NAME);
  445. lpallobjs->CDP_hWndLinkVal = GetDlgItem (hDlg, IDD_CUSTOM_LINKVALUE);
  446. lpallobjs->CDP_hWndValText = GetDlgItem (hDlg, IDD_CUSTOM_VALUETEXT);
  447. lpallobjs->CDP_hWndBoolTrue = GetDlgItem (hDlg, IDD_CUSTOM_BOOLTRUE);
  448. lpallobjs->CDP_hWndBoolFalse = GetDlgItem (hDlg, IDD_CUSTOM_BOOLFALSE);
  449. lpallobjs->CDP_hWndGroup = GetDlgItem (hDlg, IDD_CUSTOM_GBOX);
  450. lpallobjs->CDP_hWndAdd = GetDlgItem (hDlg, IDD_CUSTOM_ADD);
  451. lpallobjs->CDP_hWndDelete = GetDlgItem (hDlg, IDD_CUSTOM_DELETE);
  452. lpallobjs->CDP_hWndType = GetDlgItem (hDlg, IDD_CUSTOM_TYPE);
  453. lpallobjs->CDP_hWndCustomLV = GetDlgItem(hDlg, IDD_CUSTOM_LISTVIEW);
  454. InitListView (lpallobjs->CDP_hWndCustomLV, iszTYPE, rgszHeadings, TRUE);
  455. //
  456. // Initially disable the Add & Delete buttons
  457. //
  458. EnableWindow (lpallobjs->CDP_hWndAdd, FALSE);
  459. EnableWindow (lpallobjs->CDP_hWndDelete, FALSE);
  460. lpallobjs->CDP_fAdd = TRUE;
  461. //
  462. // Don't let the user enter too much text
  463. // If you change this value, you must change the buffer
  464. // size (szDate) in FConvertDate
  465. //
  466. SendMessage (lpallobjs->CDP_hWndVal, EM_LIMITTEXT, BUFMAX-1, 0);
  467. SendMessage (lpallobjs->CDP_hWndName, EM_LIMITTEXT, BUFMAX-1, 0);
  468. //
  469. // Add the link icon to the image list
  470. //
  471. hIcon = LoadIcon (g_hmodThisDll, MAKEINTRESOURCE (IDD_LINK_ICON));
  472. hInvIcon = LoadIcon (g_hmodThisDll, MAKEINTRESOURCE (IDD_INVLINK_ICON));
  473. if (hIcon != NULL)
  474. {
  475. lpallobjs->CDP_hImlS = ListView_GetImageList( lpallobjs->CDP_hWndCustomLV, TRUE );
  476. giLinkIcon = MsoImageList_ReplaceIcon( lpallobjs->CDP_hImlS, -1, hIcon );
  477. Assert ((giLinkIcon != -1));
  478. giInvLinkIcon = MsoImageList_ReplaceIcon (lpallobjs->CDP_hImlS, -1, hInvIcon);
  479. Assert ((giInvLinkIcon != -1));
  480. }
  481. else
  482. {
  483. DebugSz (TEXT("Icon load failed"));
  484. }
  485. //
  486. // Make a temporary copy of the custom data
  487. //
  488. FMakeTmpUDProps (lpallobjs->lpUDObj);
  489. //
  490. // Fill in the list view box with any data from the object
  491. //
  492. PopulateUDListView (lpallobjs->CDP_hWndCustomLV, lpallobjs->lpUDObj);
  493. //
  494. // See if the client supports links - turn off checkbox if they don't
  495. //
  496. lpallobjs->CDP_cLinks = 0;
  497. if (!lpallobjs->CDP_cLinks)
  498. {
  499. EnableWindow (GetDlgItem (hDlg, IDD_CUSTOM_LINK), FALSE);
  500. EnableWindow (lpallobjs->CDP_hWndLinkVal, FALSE);
  501. }
  502. return TRUE;
  503. break;
  504. }
  505. case WM_CTLCOLORBTN :
  506. case WM_CTLCOLORDLG :
  507. case WM_CTLCOLORSTATIC :
  508. if (hBrushPropDlg == NULL)
  509. break;
  510. DeleteObject(hBrushPropDlg);
  511. if ((hBrushPropDlg = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) == NULL)
  512. break;
  513. SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNFACE));
  514. SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT));
  515. return (INT_PTR) hBrushPropDlg;
  516. case WM_SYSCOLORCHANGE:
  517. PostMessage(lpallobjs->CDP_hWndCustomLV, WM_SYSCOLORCHANGE, wParam, lParam);
  518. return TRUE;
  519. break;
  520. //
  521. // This message is posted when ever the user does something with the
  522. // Name field. That allows the system to finish what they are doing
  523. // and fill in the edit field if they have to. See bug 2820.
  524. //
  525. case WM_USER+0x1000:
  526. if (!(lpallobjs->CDP_fLink && (lpallobjs->lpfnDwQueryLinkData == NULL)))
  527. {
  528. lpallobjs->CDP_iszType = (int)SendMessage (lpallobjs->CDP_hWndType, CB_GETCURSEL, 0, 0);
  529. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  530. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  531. {
  532. LPUDPROP lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, glpstzName);
  533. if (lpudp != NULL)
  534. {
  535. if (lpallobjs->CDP_fAdd)
  536. {
  537. SendMessage (lpallobjs->CDP_hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  538. lpallobjs->CDP_fAdd = FALSE;
  539. }
  540. }
  541. }
  542. EnableWindow(lpallobjs->CDP_hWndDelete, FALSE); // If the user touches the Name field, disable Delete button
  543. // Are we showing an invalid link?
  544. if (lpallobjs->CDP_fLink && !IsWindowEnabled(GetDlgItem(hDlg,IDD_CUSTOM_LINK)))
  545. {
  546. // Turn off the link checkbox
  547. lpallobjs->CDP_fLink = FALSE;
  548. SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) lpallobjs->CDP_fLink, 0);
  549. if (lpallobjs->CDP_cLinks) // Could be that the app is allowing links
  550. EnableWindow (GetDlgItem (hDlg, IDD_CUSTOM_LINK), TRUE);
  551. // Clear the value window
  552. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  553. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  554. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, FALSE, FALSE);
  555. }
  556. }
  557. return(TRUE);
  558. break;
  559. case WM_COMMAND :
  560. switch (HIWORD (wParam))
  561. {
  562. case BN_CLICKED :
  563. switch (LOWORD (wParam))
  564. {
  565. case IDD_CUSTOM_ADD :
  566. if (FGetCustomPropFromDlg(lpallobjs, hDlg))
  567. {
  568. PropSheet_Changed(GetParent(hDlg), hDlg);
  569. }
  570. return(FALSE); // return 0 'cuz we process the message
  571. break;
  572. case IDD_CUSTOM_DELETE :
  573. // Assert (fItemSel);
  574. // fItemSel = FALSE; // We're about to delete it!
  575. DeleteItem (lpallobjs->lpUDObj, lpallobjs->CDP_hWndCustomLV, lpallobjs->CDP_iItem, lpallobjs->CDP_sz);
  576. // Turn off the link checkbox if it was on.
  577. lpallobjs->CDP_fLink = FALSE;
  578. SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) lpallobjs->CDP_fLink, 0);
  579. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  580. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  581. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, FALSE, FALSE);
  582. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  583. ResetTypeControl (hDlg, IDD_CUSTOM_TYPE, &lpallobjs->CDP_iszType);
  584. SendMessage(lpallobjs->CDP_hWndName, CB_SETEDITSEL, 0, MAKELPARAM(0,-1)); // Select entire string
  585. SendMessage(lpallobjs->CDP_hWndName, WM_CLEAR, 0, 0);
  586. SetFocus(lpallobjs->CDP_hWndName);
  587. // lpallobjs->fPropDlgChanged = TRUE;
  588. PropSheet_Changed(GetParent(hDlg), hDlg);
  589. return(FALSE); // return 0 'cuz we process the message
  590. break;
  591. case IDD_CUSTOM_LINK :
  592. {
  593. BOOL fMod = FALSE;
  594. // Should never get a message from a disabled control
  595. Assert (lpallobjs->CDP_cLinks);
  596. lpallobjs->CDP_fLink = !lpallobjs->CDP_fLink;
  597. SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) lpallobjs->CDP_fLink, 0);
  598. // If the link box is checked, the value edit needs to change
  599. // to a combobox filled with link data
  600. if (lpallobjs->CDP_fLink)
  601. {
  602. Assert ((lpallobjs->lpfnDwQueryLinkData != NULL));
  603. FCreateListOfLinks (lpallobjs->CDP_cLinks, lpallobjs->lpfnDwQueryLinkData, lpallobjs->CDP_hWndLinkVal);
  604. SendMessage (lpallobjs->CDP_hWndLinkVal, CB_SETCURSEL, 0, 0);
  605. FSetTypeControl ((*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKTYPE, 0, NULL, NULL), lpallobjs->CDP_hWndType);
  606. }
  607. else
  608. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  609. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  610. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, lpallobjs->CDP_fLink, FALSE);
  611. // HACK, we don't want FSetupAddButton to change the text of the add
  612. // button
  613. if (!lpallobjs->CDP_fAdd)
  614. fMod = lpallobjs->CDP_fAdd = TRUE;
  615. // Set up the "Add" button correctly
  616. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  617. if (fMod)
  618. lpallobjs->CDP_fAdd = FALSE;
  619. return(FALSE); // return 0 'cuz we process the message
  620. break;
  621. }
  622. case IDD_CUSTOM_BOOLTRUE:
  623. case IDD_CUSTOM_BOOLFALSE:
  624. {
  625. BOOL fMod = FALSE;
  626. lpallobjs->CDP_iszType = (int)SendMessage (lpallobjs->CDP_hWndType, CB_GETCURSEL, 0, 0);
  627. // HACK, we don't want FSetupAddButton to change the text of the add
  628. // button
  629. if (!lpallobjs->CDP_fAdd)
  630. fMod = lpallobjs->CDP_fAdd = TRUE;
  631. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  632. if (fMod)
  633. lpallobjs->CDP_fAdd = FALSE;
  634. return(FALSE);
  635. }
  636. default:
  637. return(TRUE);
  638. }
  639. case CBN_CLOSEUP:
  640. // Hack!!
  641. // We need to post a message to ourselves to check if the user's
  642. // actions entered text in the edit field.
  643. PostMessage(hDlg, WM_USER+0x1000, 0L, 0L);
  644. return(FALSE);
  645. case CBN_SELCHANGE :
  646. switch (LOWORD (wParam))
  647. {
  648. case IDD_CUSTOM_NAME :
  649. // Hack!!
  650. // We need to post a message to ourselves to check if the user's
  651. // actions entered text in the edit field.
  652. PostMessage(hDlg, WM_USER+0x1000, 0L, 0L);
  653. return(FALSE); // return 0 'cuz we process the message
  654. break;
  655. case IDD_CUSTOM_TYPE :
  656. {
  657. BOOL fMod = FALSE;
  658. // If the user picks the Boolean type from the combo box,
  659. // we must replace the edit control for the value
  660. // with radio buttons. If the Link checkbox is set,
  661. // the type depends on the link value, not user selection
  662. lpallobjs->CDP_iszType = (int)SendMessage ((HWND) lParam, CB_GETCURSEL, 0, 0);
  663. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  664. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, lpallobjs->CDP_fLink, (lpallobjs->CDP_iszType == iszBOOL));
  665. // HACK: FSwapControls() resets the type selection to be
  666. // the first one (since all other clients need that to
  667. // happen). In this case, the user has selected a new
  668. // type, so we need to force it manually to what they picked.
  669. SendMessage (lpallobjs->CDP_hWndType, CB_SETCURSEL, lpallobjs->CDP_iszType, 0);
  670. // HACK: FSetupAddButton will change the Add button to
  671. // say "Add" if lpallobjs->CDP_fAdd is FALSE. Since we just changed
  672. // the button to "Modify", fake it out to not change
  673. // the Add button by flipping lpallobjs->CDP_fAdd, then flipping it back.
  674. if (!lpallobjs->CDP_fAdd)
  675. fMod = lpallobjs->CDP_fAdd = TRUE;
  676. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  677. if (fMod)
  678. lpallobjs->CDP_fAdd = FALSE;
  679. return(FALSE); // return 0 'cuz we process the message
  680. }
  681. case IDD_CUSTOM_LINKVALUE :
  682. // If the user has the "Link" box checked and starts picking
  683. // link values, make sure that the "Type" combobox is updated
  684. // to the type of the static value of the link.
  685. {
  686. DWORD irg;
  687. AssertSz (lpallobjs->CDP_fLink, TEXT("Link box must be checked in order for this dialog to be visible!"));
  688. // Get the link value from the combobox, and store
  689. // the link name and static value.
  690. irg = (int)SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETCURSEL, 0, 0);
  691. Assert ((lpallobjs->lpfnDwQueryLinkData != NULL));
  692. // REVIEW: If apps really need the name, we can get it here....
  693. FSetTypeControl ((*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKTYPE, irg, NULL, NULL), lpallobjs->CDP_hWndType);
  694. return(FALSE); // return 0 'cuz we process the message
  695. }
  696. default:
  697. return TRUE; // we didn't process message
  698. }
  699. case CBN_EDITCHANGE: // The user typed their own
  700. switch (LOWORD (wParam))
  701. {
  702. case IDD_CUSTOM_NAME :
  703. // Hack!!
  704. // We need to post a message to ourselves to check if the user's
  705. // actions entered text in the edit field.
  706. PostMessage(hDlg, WM_USER+0x1000, 0L, 0L);
  707. return(FALSE); // return 0 'cuz we process the message
  708. break;
  709. default:
  710. return(TRUE);
  711. break;
  712. }
  713. case EN_UPDATE :
  714. switch (LOWORD (wParam))
  715. {
  716. case IDD_CUSTOM_VALUE :
  717. {
  718. BOOL fMod = FALSE;
  719. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  720. {
  721. LPUDPROP lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, glpstzName);
  722. if (lpudp != NULL)
  723. {
  724. if (lpallobjs->CDP_fAdd)
  725. {
  726. SendMessage (lpallobjs->CDP_hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  727. lpallobjs->CDP_fAdd = FALSE;
  728. }
  729. }
  730. // HACK: FSetupAddButton will change the Add button to
  731. // say "Add" if lpallobjs->CDP_fAdd is FALSE. Since we just changed
  732. // the button to "Modify", fake it out to not change
  733. // the Add button by flipping lpallobjs->CDP_fAdd, then flipping it back.
  734. if (!lpallobjs->CDP_fAdd)
  735. fMod = lpallobjs->CDP_fAdd = TRUE;
  736. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  737. if (fMod)
  738. lpallobjs->CDP_fAdd = FALSE;
  739. }
  740. return(FALSE); // return 0 'cuz we process the message
  741. }
  742. default:
  743. return TRUE; // we didn't process message
  744. }
  745. case EN_KILLFOCUS :
  746. switch (LOWORD (wParam))
  747. {
  748. // If the user finishes entering text in the Name edit control,
  749. // be really cool and check to see if the name they entered
  750. // is a property that is already defined. If it is,
  751. // change the Add button to Modify.
  752. case IDD_CUSTOM_NAME :
  753. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  754. {
  755. LPUDPROP lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, glpstzName);
  756. if (lpudp != NULL)
  757. {
  758. if (lpallobjs->CDP_fAdd)
  759. {
  760. SendMessage (lpallobjs->CDP_hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  761. lpallobjs->CDP_fAdd = FALSE;
  762. }
  763. }
  764. }
  765. return FALSE;
  766. default:
  767. return TRUE;
  768. }
  769. default:
  770. return TRUE;
  771. } // switch
  772. case WM_DESTROY:
  773. MsoImageList_Destroy(lpallobjs->CDP_hImlS);
  774. return FALSE;
  775. case WM_NOTIFY :
  776. switch (((NMHDR FAR *) lParam)->code)
  777. {
  778. case LVN_ITEMCHANGING :
  779. // If an item is gaining focus, put it in the edit controls at
  780. // the top of the dialog.
  781. if (((NM_LISTVIEW FAR *) lParam)->uNewState & LVIS_SELECTED)
  782. {
  783. Assert ((((NM_LISTVIEW FAR *) lParam) != NULL));
  784. lpallobjs->CDP_iItem = ((NM_LISTVIEW FAR *) lParam)->iItem;
  785. ListView_GetItemText (lpallobjs->CDP_hWndCustomLV, lpallobjs->CDP_iItem, 0, lpallobjs->CDP_sz, BUFMAX);
  786. PopulateControls (lpallobjs->lpUDObj, lpallobjs->CDP_sz, lpallobjs->CDP_cLinks, lpallobjs->lpfnDwQueryLinkData, hDlg,
  787. GetDlgItem (hDlg, IDD_CUSTOM_NAME), lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndValText,
  788. GetDlgItem (hDlg, IDD_CUSTOM_LINK), lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndType,
  789. lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse, lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndDelete, &lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd);
  790. return FALSE;
  791. }
  792. return TRUE;
  793. break;
  794. case PSN_APPLY :
  795. if (IsWindowEnabled(lpallobjs->CDP_hWndAdd))
  796. FGetCustomPropFromDlg(lpallobjs, hDlg);
  797. // Swap the temp copy to be the real copy.
  798. FDeleteTmpUDProps (lpallobjs->lpUDObj);
  799. if (FUserDefShouldSave (lpallobjs->lpUDObj)
  800. || lpallobjs->fPropDlgChanged )
  801. {
  802. if( !ApplyChangesBackToFile(hDlg, (BOOL)((PSHNOTIFY*)lParam)->lParam, lpallobjs, itabCUSTOM) )
  803. {
  804. PostMessage( GetParent(hDlg), PSM_SETCURSEL, (WPARAM)-1, (LPARAM)lpallobjs->lpUDObj->m_hPage );
  805. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE );
  806. return TRUE;
  807. }
  808. }
  809. return PSNRET_NOERROR;
  810. case PSN_RESET :
  811. if (lpallobjs->fPropDlgChanged && !lpallobjs->fPropDlgPrompted)
  812. {
  813. if (ISavePropDlgChanges(lpallobjs, hDlg, ((NMHDR FAR *)lParam)->hwndFrom) != IDNO)
  814. {
  815. return(TRUE);
  816. }
  817. }
  818. // User cancelled the changes, so just delete the tmp stuff.
  819. FSwapTmpUDProps (lpallobjs->lpUDObj);
  820. FDeleteTmpUDProps (lpallobjs->lpUDObj);
  821. return TRUE;
  822. case PSN_SETACTIVE :
  823. return TRUE;
  824. default:
  825. break;
  826. } // switch
  827. break;
  828. case WM_CONTEXTMENU:
  829. WinHelp((HANDLE)wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR)rgIdhCustom);
  830. break;
  831. case WM_HELP:
  832. WinHelp(((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)rgIdhCustom);
  833. break;
  834. } // switch
  835. return FALSE;
  836. } // FCustomDlgProc
  837. //
  838. // FGetCustomPropFromDlg
  839. //
  840. // Purpose: To get a custom property from the dialog.
  841. // I.e. the user hit Add/Modify.
  842. //
  843. BOOL FGetCustomPropFromDlg(LPALLOBJS lpallobjs, HWND hDlg)
  844. {
  845. UDTYPES udtype;
  846. NUM dbl;
  847. LPVOID lpv;
  848. int iItemT;
  849. LPTSTR lpstzName;
  850. LPVOID lpvSaveAsDword;
  851. DWORD cch;
  852. BOOL f;
  853. lpstzName = NULL;
  854. cch = 0;
  855. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  856. {
  857. LPUDPROP lpudp;
  858. lpallobjs->CDP_fLink = FALSE; // just to be sure.
  859. Assert(lpallobjs->CDP_fLink == TRUE || lpallobjs->CDP_fLink == FALSE);
  860. // HACK: If the user enters a name that is already
  861. // a property name, the default action of the object
  862. // is to replace the data, treating it as an update.
  863. // This will cause there to be 2 names in the listview
  864. // though unless we just update the original one. So, first
  865. // see if the new name is in the list already, and if
  866. // it is, find it in the listview and set up to update it.
  867. lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, glpstzName);
  868. if (lpudp != NULL)
  869. {
  870. LV_FINDINFO lvfi;
  871. lvfi.flags = LVFI_STRING;
  872. lvfi.psz = glpstzName;
  873. iItemT = ListView_FindItem (lpallobjs->CDP_hWndCustomLV, -1, &lvfi);
  874. }
  875. else
  876. {
  877. iItemT = -1;
  878. }
  879. // Let's get the type, since this might be a MODIFY case
  880. lpallobjs->CDP_iszType = (int)SendMessage(lpallobjs->CDP_hWndType, CB_GETCURSEL,0, 0);
  881. // If the user has checked the link box, then the value
  882. // must come from the client.
  883. if (lpallobjs->CDP_fLink)
  884. {
  885. DWORD irg;
  886. // Get the link name from the combobox, and store
  887. // the link name and static value.
  888. irg = (int)SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETCURSEL, 0, 0);
  889. Assert ((lpallobjs->lpfnDwQueryLinkData != NULL));
  890. Assert (((irg < lpallobjs->CDP_cLinks) && ((int) irg >= 0)));
  891. cch = (DWORD)SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETLBTEXTLEN, irg, 0)+1; // Include the null-terminator
  892. if (!FAllocString (&lpstzName, cch))
  893. return(FALSE);
  894. SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETLBTEXT, irg, (LPARAM) lpstzName );
  895. // Set up the static type and value for display
  896. // in the listbox
  897. udtype = (UDTYPES) (*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKTYPE, irg, NULL, lpstzName);
  898. (*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKVAL, irg, &lpv, lpstzName);
  899. //
  900. // HACK alert
  901. //
  902. // We want lpv to point to the value, not to be overloaded in the case of a dword or bool.
  903. //
  904. if ((udtype == wUDdw) || (udtype == wUDbool))
  905. {
  906. lpvSaveAsDword = lpv; // Really a DWORD
  907. lpv = &lpvSaveAsDword;
  908. }
  909. }
  910. else
  911. {
  912. if (lpallobjs->CDP_iszType != iszBOOL)
  913. {
  914. if (!FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_VALUE, &glpstzValue))
  915. return(FALSE);
  916. }
  917. // Convert the type in the combobox to a UDTYPES
  918. switch (lpallobjs->CDP_iszType)
  919. {
  920. case iszTEXT :
  921. udtype = wUDlpsz;
  922. (LPTSTR) lpv = glpstzValue;
  923. break;
  924. case iszNUM :
  925. udtype = UdtypesGetNumberType (glpstzValue, &dbl,
  926. ((LPUDINFO)lpallobjs->lpUDObj->m_lpData)->lpfnFSzToNum);
  927. switch (udtype)
  928. {
  929. case wUDdw :
  930. lpv = (DWORD *) &dbl;
  931. break;
  932. case wUDfloat :
  933. (NUM *) lpv = &dbl;
  934. break;
  935. default :
  936. (LPTSTR) lpv = glpstzValue;
  937. // If the user doesn't want to convert the value to text, they can press "Cancel" and try again.
  938. if (FDisplayConversionWarning (hDlg))
  939. {
  940. SetFocus(lpallobjs->CDP_hWndType);
  941. return(FALSE);
  942. }
  943. udtype = wUDlpsz;
  944. } // switch (udtype)
  945. break;
  946. case iszDATE :
  947. if (FConvertDate (glpstzValue, lstrlen(glpstzValue) + 1, (LPFILETIME) &dbl))
  948. {
  949. udtype = wUDdate;
  950. (NUM *) lpv = &dbl;
  951. }
  952. else
  953. {
  954. udtype = wUDlpsz;
  955. (LPTSTR) lpv = glpstzValue;
  956. // If the user doesn't want to convert the value to text, they can press "Cancel" and try again.
  957. if (FDisplayConversionWarning (hDlg))
  958. {
  959. SetFocus(lpallobjs->CDP_hWndType);
  960. return(FALSE);
  961. }
  962. }
  963. break;
  964. case iszBOOL :
  965. {
  966. udtype = wUDbool;
  967. f = (BOOL)(SendMessage (lpallobjs->CDP_hWndBoolTrue, BM_GETSTATE, 0, 0) & BST_CHECKED);
  968. lpv = &f;
  969. break;
  970. }
  971. default :
  972. AssertSz (0,TEXT("IDD_CUSTOM_TYPE combobox is whacked!"));
  973. udtype = wUDinvalid;
  974. } // switch (lpallobjs->CDP_iszType)
  975. } // if (lpallobjs->CDP_fLink) ... else
  976. // If we got valid input, add the property to the object
  977. // and listbox.
  978. if (udtype != wUDinvalid)
  979. {
  980. // The PropVariant created when we add this property.
  981. LPPROPVARIANT lppropvar = NULL;
  982. // The link data (link name itself) would have
  983. // been stored above if the property was a link.
  984. // This stores the static value that will eventually
  985. // appear in the list view.
  986. lppropvar = LppropvarUserDefAddProp (lpallobjs->lpUDObj, glpstzName, lpv, udtype,
  987. (lpstzName != NULL) ? lpstzName : NULL,
  988. (lpstzName != NULL) ? TRUE : FALSE, FALSE);
  989. // HACK alert
  990. //
  991. // Here we want lpv be overloaded in the case of a dword or bool, since
  992. // AddUDPropToListView calls WUdtypeToSz which assumes lpv is overloaded.
  993. //
  994. if ((udtype == wUDdw) || (udtype == wUDbool))
  995. {
  996. lpv = *(LPVOID *)lpv;
  997. }
  998. if (lppropvar)
  999. {
  1000. AddUDPropToListView (lpallobjs->lpUDObj, lpallobjs->CDP_hWndCustomLV, glpstzName, lppropvar, iItemT, lpallobjs->CDP_fLink, fTrue, fTrue);
  1001. }
  1002. // For links, dealloc the buffer.
  1003. if (lpallobjs->CDP_fLink)
  1004. {
  1005. LocalFree(lpv);
  1006. lpv = NULL;
  1007. }
  1008. // Clear out the edit fields and disable the Add button again
  1009. SetCustomDlgDefButton(hDlg, gOKButtonID);
  1010. EnableWindow (lpallobjs->CDP_hWndAdd, FALSE);
  1011. SendMessage(lpallobjs->CDP_hWndName, CB_SETEDITSEL, 0, MAKELPARAM(0,-1)); // Select entire string
  1012. SendMessage(lpallobjs->CDP_hWndName, WM_CLEAR, 0, 0);
  1013. EnableWindow (lpallobjs->CDP_hWndDelete, FALSE);
  1014. // See bug 213
  1015. // if (fLink)
  1016. // {
  1017. // fLink = !fLink;
  1018. // SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) fLink, 0);
  1019. // }
  1020. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal,
  1021. lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  1022. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType,
  1023. lpallobjs->CDP_hWndValText, lpallobjs->CDP_fLink, lpallobjs->CDP_iszType == iszBOOL);
  1024. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1025. // wUDbool doesn't use the edit control....
  1026. if (lpallobjs->CDP_iszType != iszBOOL)
  1027. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  1028. } // if (udtype != wUDinvalid)
  1029. SendDlgItemMessage(hDlg, IDD_CUSTOM_TYPE, CB_SETCURSEL, lpallobjs->CDP_iszType,0);
  1030. SetFocus(lpallobjs->CDP_hWndName);
  1031. // lpallobjs->fPropDlgChanged = TRUE;
  1032. if (lpstzName != NULL)
  1033. {
  1034. LocalFree(lpstzName);
  1035. }
  1036. return(TRUE);
  1037. }
  1038. return(FALSE);
  1039. }
  1040. /////////////////////////////////////////////////////////////////////////
  1041. //
  1042. // SetCustomDlgDefButton
  1043. //
  1044. // Set the new default button
  1045. //
  1046. /////////////////////////////////////////////////////////////////////////
  1047. VOID SetCustomDlgDefButton(HWND hDlg, int IDNew)
  1048. {
  1049. int IDOld;
  1050. if ((IDOld = LOWORD(SendMessage(hDlg, DM_GETDEFID, 0L, 0L))) != IDNew)
  1051. {
  1052. // Set the new default push button's control ID.
  1053. SendMessage(hDlg, DM_SETDEFID, IDNew, 0L);
  1054. // Set the new style.
  1055. SendDlgItemMessage(hDlg, IDNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE,0));
  1056. SendDlgItemMessage(hDlg, IDOld, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE,0));
  1057. }
  1058. }
  1059. ////////////////////////////////////////////////////////////////////////////////
  1060. //
  1061. // FAllocAndGetValLpstz
  1062. //
  1063. // Purpose:
  1064. // Gets the value from the edit box into the local buffer.
  1065. //
  1066. ////////////////////////////////////////////////////////////////////////////////
  1067. BOOL PASCAL FAllocAndGetValLpstz (
  1068. HWND hDlg, // Handle of dialog control is in
  1069. DWORD dwId, // Id of control
  1070. LPTSTR *lplpstz) // Buffer
  1071. {
  1072. DWORD cch;
  1073. cch = (DWORD)SendDlgItemMessage (hDlg, dwId, WM_GETTEXTLENGTH, 0, 0);
  1074. cch++;
  1075. if (FAllocString (lplpstz, cch))
  1076. {
  1077. // Get the entry. Remember to null-terminate it.
  1078. cch = (DWORD)SendDlgItemMessage (hDlg, dwId, WM_GETTEXT, cch, (LPARAM) *lplpstz );
  1079. (*lplpstz)[cch] = TEXT('\0');
  1080. return TRUE;
  1081. }
  1082. return FALSE;
  1083. } // FAllocAndGetValLpstz
  1084. ////////////////////////////////////////////////////////////////////////////////
  1085. //
  1086. // FAllocString
  1087. //
  1088. // Purpose:
  1089. // Allocates a string big enough to to hold cch char's. Only allocates if needed.
  1090. //
  1091. ////////////////////////////////////////////////////////////////////////////////
  1092. BOOL PASCAL FAllocString (
  1093. LPTSTR *lplpstz,
  1094. DWORD cch)
  1095. {
  1096. // Figure out how many bytes we need to allocate.
  1097. DWORD cbNew = (cch * sizeof(TCHAR));
  1098. // And how many bytes we need to free.
  1099. DWORD cbOld = *lplpstz == NULL
  1100. ? 0
  1101. : (lstrlen (*lplpstz) + 1) * sizeof(TCHAR);
  1102. // If we need to free or allocate data.
  1103. if (*lplpstz == NULL || cbNew > cbOld)
  1104. {
  1105. LPTSTR lpszNew;
  1106. // Allocate the new data.
  1107. lpszNew = LocalAlloc( LPTR, cbNew);
  1108. if (lpszNew == NULL)
  1109. {
  1110. return FALSE;
  1111. }
  1112. // Free the old data.
  1113. if (*lplpstz != NULL)
  1114. {
  1115. LocalFree(*lplpstz);
  1116. }
  1117. *lplpstz = lpszNew;
  1118. }
  1119. // Make this a valid (empty) string.
  1120. **lplpstz = TEXT('\0');
  1121. return TRUE;
  1122. } // FAllocString
  1123. ////////////////////////////////////////////////////////////////////////////////
  1124. //
  1125. // ClearEditControl
  1126. //
  1127. // Purpose:
  1128. // Clears any text from an edit control
  1129. //
  1130. ////////////////////////////////////////////////////////////////////////////////
  1131. void PASCAL
  1132. ClearEditControl
  1133. (HWND hDlg, // Dialog handle
  1134. DWORD dwId) // Id of edit control
  1135. {
  1136. // Really cheesey. Clear the edit control by selecting
  1137. // everything then clearing the selection
  1138. if (dwId == 0)
  1139. {
  1140. SendMessage (hDlg, EM_SETSEL, 0, -1);
  1141. SendMessage (hDlg, WM_CLEAR, 0, 0);
  1142. }
  1143. else
  1144. {
  1145. SendDlgItemMessage (hDlg, dwId, EM_SETSEL, 0, -1);
  1146. SendDlgItemMessage (hDlg, dwId, WM_CLEAR, 0, 0);
  1147. }
  1148. } // ClearEditControl
  1149. ////////////////////////////////////////////////////////////////////////////////
  1150. //
  1151. // UdtypesGetNumberType
  1152. //
  1153. // Purpose:
  1154. // Gets the number type from the string and returns the value, either
  1155. // a float or dword in numval.
  1156. //
  1157. ////////////////////////////////////////////////////////////////////////////////
  1158. UDTYPES PASCAL
  1159. UdtypesGetNumberType
  1160. (LPTSTR lpstz, // String containing the number
  1161. NUM *lpnumval, // The value of the number
  1162. BOOL (*lpfnFSzToNum)(NUM *, LPTSTR)) // Sz To Num routine, can be null
  1163. {
  1164. TCHAR *pc;
  1165. errno = 0;
  1166. *(DWORD *) lpnumval = wcstol(lpstz, &pc, 10);
  1167. if ((!errno) && (*pc == TEXT('\0')))
  1168. return wUDdw;
  1169. // Try doing a float conversion if int fails
  1170. if (lpfnFSzToNum != NULL)
  1171. {
  1172. if ((*lpfnFSzToNum)(lpnumval, lpstz))
  1173. return wUDfloat;
  1174. }
  1175. return wUDinvalid;
  1176. } // UdtypesGetNumberType
  1177. ////////////////////////////////////////////////////////////////////////////////
  1178. //
  1179. // YearIndexFromShortDateFormat
  1180. //
  1181. //
  1182. // Determines the zero-based position index of the year component
  1183. // of a textual representation of the date based on the specified date format.
  1184. // This value may be used as the iYear arg to ScanDateNums function.
  1185. //
  1186. ////////////////////////////////////////////////////////////////////////////////
  1187. int YearIndexFromShortDateFormat( TCHAR chFmt )
  1188. {
  1189. switch( chFmt )
  1190. {
  1191. case MMDDYY:
  1192. case DDMMYY:
  1193. return 2;
  1194. case YYMMDD:
  1195. return 0;
  1196. }
  1197. return -1;
  1198. }
  1199. ////////////////////////////////////////////////////////////////////////////////
  1200. //
  1201. // IsGregorian
  1202. //
  1203. // Purpose:
  1204. // Reports whether the specified calendar is a gregorian calendar.
  1205. //
  1206. ////////////////////////////////////////////////////////////////////////////////
  1207. BOOL IsGregorian( CALID calid )
  1208. {
  1209. switch (calid)
  1210. {
  1211. case CAL_GREGORIAN:
  1212. case CAL_GREGORIAN_US:
  1213. case CAL_GREGORIAN_ME_FRENCH:
  1214. case CAL_GREGORIAN_ARABIC:
  1215. case CAL_GREGORIAN_XLIT_ENGLISH:
  1216. case CAL_GREGORIAN_XLIT_FRENCH:
  1217. return TRUE;
  1218. // these are non-gregorian:
  1219. //case CAL_JAPAN
  1220. //case CAL_TAIWAN
  1221. //case CAL_KOREA
  1222. //case CAL_HIJRI
  1223. //case CAL_THAI
  1224. //case CAL_HEBREW
  1225. }
  1226. return FALSE;
  1227. }
  1228. ////////////////////////////////////////////////////////////////////////////////
  1229. //
  1230. // GregorianYearFromAbbreviatedYear
  1231. //
  1232. // Purpose:
  1233. // Based on current locale settings, calculates the year corresponding to the
  1234. // specified 1- or 2-digit abbreviated value.
  1235. //
  1236. ////////////////////////////////////////////////////////////////////////////////
  1237. int GregorianYearFromAbbreviatedYear( LCID lcid, CALID calid, int nAbbreviatedYear )
  1238. {
  1239. TCHAR szData[16];
  1240. LONG nYearHigh = -1;
  1241. int nBaseCentury;
  1242. int nYearInCentury = 0;
  1243. // We're handling two-digit values for gregorian calendars only
  1244. if (nAbbreviatedYear < 100)
  1245. {
  1246. // We don't support non-gregorian date windowing here
  1247. // because that would be insanely complex and prone to error -ccooney 2000/02/04
  1248. if( !IsGregorian( calid )
  1249. || !GetCalendarInfo( lcid, calid, CAL_ITWODIGITYEARMAX|CAL_RETURN_NUMBER,
  1250. NULL, 0, &nYearHigh ) )
  1251. {
  1252. // In the absence of a default, use 2029 as the cutoff, just like monthcal.
  1253. nYearHigh = 2029;
  1254. }
  1255. //
  1256. // Copy the century of nYearHigh into nAbbreviatedYear.
  1257. //
  1258. nAbbreviatedYear += (nYearHigh - nYearHigh % 100);
  1259. //
  1260. // If it exceeds the max, then drop to previous century.
  1261. //
  1262. if (nAbbreviatedYear > nYearHigh)
  1263. nAbbreviatedYear -= 100;
  1264. }
  1265. return nAbbreviatedYear;
  1266. }
  1267. ////////////////////////////////////////////////////////////////////////////////
  1268. //
  1269. // FConvertDate
  1270. //
  1271. // Purpose:
  1272. // Converts the given string to a date.
  1273. //
  1274. ////////////////////////////////////////////////////////////////////////////////
  1275. BOOL
  1276. PASCAL
  1277. FConvertDate(
  1278. LPTSTR lpstz, // String having the date
  1279. DWORD cchMax,
  1280. LPFILETIME lpft // The date in FILETIME format
  1281. )
  1282. {
  1283. FILETIME ft;
  1284. SYSTEMTIME st;
  1285. TCHAR szSep[3];
  1286. TCHAR szFmt[10];
  1287. TCHAR szCalID[8];
  1288. unsigned int ai[3];
  1289. int iYear =-1; // index of ai member that represents the year value
  1290. CALID calid;
  1291. TCHAR szDate[256];
  1292. TCHAR szMonth[256];
  1293. TCHAR *pch;
  1294. TCHAR *pchT;
  1295. DWORD cch;
  1296. DWORD i;
  1297. if (!(GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_IDATE, szFmt, ARRAYSIZE(szFmt))) ||
  1298. !(GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SDATE, szSep, ARRAYSIZE(szSep))) ||
  1299. !(GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ICALENDARTYPE, szCalID, ARRAYSIZE(szCalID))) )
  1300. return FALSE;
  1301. iYear = YearIndexFromShortDateFormat(szFmt[0]);
  1302. // Augh! It's an stz so we need to pass the DWORDs at the start
  1303. if (!ScanDateNums(lpstz, szSep, ai, sizeof(ai)/sizeof(unsigned int),iYear))
  1304. {
  1305. // Could be that the string contains the short version of the month, e.g. 03-Mar-95
  1306. StringCchCopy( szDate, ARRAYSIZE(szDate), lpstz ); // don't care if it truncates
  1307. pch = szDate;
  1308. // Let's get to the first character of the month, if there is one
  1309. while(((IsCharAlphaNumeric(*pch) && !IsCharAlpha(*pch)) || (*pch == szSep[0])) && (*pch != 0))
  1310. {
  1311. ++pch;
  1312. }
  1313. // If we got to the end of the string, there really was an error
  1314. if (*pch == 0)
  1315. return(FALSE);
  1316. // Let's find the length of the month string
  1317. pchT = pch+1;
  1318. while ((*pchT != szSep[0]) && (*pchT != 0))
  1319. {
  1320. ++pchT;
  1321. }
  1322. cch = (DWORD)(pchT - pch);
  1323. // Loop through all the months and see if we match one
  1324. // There can be 13 months
  1325. for (i = 1; i <= 13; ++i)
  1326. {
  1327. if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME1+i-1,
  1328. szMonth, ARRAYSIZE(szMonth)))
  1329. {
  1330. return(FALSE);
  1331. }
  1332. if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH,
  1333. pch, cch, szMonth, lstrlen(szMonth)) == 2)
  1334. {
  1335. break;
  1336. }
  1337. }
  1338. if (i > 13)
  1339. return(FALSE);
  1340. // We found the month. wsprintf zero-terminates
  1341. if (FAILED(StringCchPrintf(pch, cch, TEXT("%u"), i)))
  1342. return(FALSE);
  1343. pch += lstrlen( pch );
  1344. while (*pch++ = *(pch+1));
  1345. // Try and convert again
  1346. if (!ScanDateNums(szDate, szSep, ai, 3, iYear))
  1347. return(FALSE);
  1348. } // if (!ScanDateNums(lpstz, szSep, ai, 3))
  1349. ZeroMemory(&st, sizeof(st));
  1350. switch (szFmt[0])
  1351. {
  1352. case MMDDYY:
  1353. st.wMonth = (WORD)ai[0];
  1354. st.wDay = (WORD)ai[1];
  1355. st.wYear = (WORD)ai[2];
  1356. break;
  1357. case DDMMYY:
  1358. st.wDay = (WORD)ai[0];
  1359. st.wMonth = (WORD)ai[1];
  1360. st.wYear = (WORD)ai[2];
  1361. break;
  1362. case YYMMDD:
  1363. st.wYear = (WORD)ai[0];
  1364. st.wMonth = (WORD)ai[1];
  1365. st.wDay = (WORD)ai[2];
  1366. break;
  1367. default:
  1368. return FALSE;
  1369. }
  1370. if (st.wYear < ONECENTURY)
  1371. {
  1372. calid = wcstol( szCalID, NULL, 10 );
  1373. st.wYear = (WORD)GregorianYearFromAbbreviatedYear(
  1374. LOCALE_USER_DEFAULT, calid, st.wYear );
  1375. }
  1376. if (!SystemTimeToFileTime (&st, &ft))
  1377. return(FALSE);
  1378. return(LocalFileTimeToFileTime(&ft, lpft));
  1379. } // FConvertDate
  1380. ////////////////////////////////////////////////////////////////////////////////
  1381. //
  1382. // PopulateUDListView
  1383. //
  1384. // Purpose:
  1385. // Populates the entire ListView with the User-defined properties
  1386. // in the given object.
  1387. //
  1388. ////////////////////////////////////////////////////////////////////////////////
  1389. void PASCAL
  1390. PopulateUDListView
  1391. (HWND hWnd, // Handle of list view window
  1392. LPUDOBJ lpUDObj) // UD Prop object
  1393. {
  1394. LPUDITER lpudi;
  1395. LPPROPVARIANT lppropvar;
  1396. BOOL fLink;
  1397. BOOL fLinkInvalid;
  1398. // Iterate through the list of user-defined properties, adding each
  1399. // one to the listview.
  1400. for( lpudi = LpudiUserDefCreateIterator (lpUDObj);
  1401. FUserDefIteratorValid (lpudi);
  1402. FUserDefIteratorNext (lpudi)
  1403. )
  1404. {
  1405. // Get the name of this property.
  1406. LPTSTR tszPropertyName = LpszUserDefIteratorName( lpudi );
  1407. // If the property has no name, or the name indicates that it
  1408. // is a hidden property, then move on to the next property.
  1409. if( tszPropertyName == NULL
  1410. ||
  1411. *tszPropertyName == HIDDENPREFIX )
  1412. {
  1413. continue;
  1414. }
  1415. lppropvar = LppropvarUserDefGetIteratorVal (lpudi, &fLink, &fLinkInvalid);
  1416. if (lppropvar == NULL)
  1417. return;
  1418. // If this isn't a supported type, don't display it.
  1419. if( !ISUDTYPE(lppropvar->vt) )
  1420. continue;
  1421. //
  1422. // In the Shell, we want all links to show up as invalid, so set that here...
  1423. //
  1424. fLinkInvalid = TRUE;
  1425. AddUDPropToListView (lpUDObj, hWnd, LpszUserDefIteratorName (lpudi ), lppropvar, -1, fLink, fLinkInvalid, FALSE);
  1426. } // for( lpudi = LpudiUserDefCreateIterator (lpUDObj); ...
  1427. FUserDefDestroyIterator (&lpudi);
  1428. } // PopulateUDListView
  1429. ////////////////////////////////////////////////////////////////////////////////
  1430. //
  1431. // AddUDPropToListView
  1432. //
  1433. // Purpose:
  1434. // Adds the given property to the list view or updates an existing one
  1435. // if iItem >= 0
  1436. //
  1437. ////////////////////////////////////////////////////////////////////////////////
  1438. void PASCAL AddUDPropToListView (
  1439. LPUDOBJ lpUDObj,
  1440. HWND hWnd, // Handle of list view
  1441. LPTSTR lpszName, // Name of property
  1442. LPPROPVARIANT lppropvar, // The property value.
  1443. int iItem, // Index to add item at
  1444. BOOL fLink, // Indicates the value is a link
  1445. BOOL fLinkInvalid, // Is the link invalid?
  1446. BOOL fMakeVisible) // Should the property be forced to be visible
  1447. {
  1448. LV_ITEM lvi;
  1449. TCHAR sz[BUFMAX];
  1450. WORD irg;
  1451. BOOL fSuccess;
  1452. BOOL fUpdate;
  1453. // If iItem >= 0, then the item should be updated, otherwise,
  1454. // it should be added.
  1455. if (fUpdate = (iItem >= 0))
  1456. {
  1457. lvi.iItem = iItem;
  1458. if (fLink)
  1459. lvi.iImage = (fLinkInvalid) ? giInvLinkIcon : giLinkIcon;
  1460. else
  1461. lvi.iImage = giBlankIcon;
  1462. lvi.mask = LVIF_IMAGE;
  1463. lvi.iSubItem = iszNAME;
  1464. fSuccess = ListView_SetItem (hWnd, &lvi);
  1465. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  1466. }
  1467. else
  1468. {
  1469. // This always adds to the end of the list....
  1470. lvi.iItem = ListView_GetItemCount (hWnd);
  1471. // First add the label to the list
  1472. lvi.iSubItem = iszNAME;
  1473. lvi.pszText = lpszName;
  1474. if (fLink)
  1475. lvi.iImage = (fLinkInvalid) ? giInvLinkIcon : giLinkIcon;
  1476. else
  1477. lvi.iImage = giBlankIcon;
  1478. lvi.mask = LVIF_TEXT | LVIF_IMAGE;
  1479. lvi.iItem = ListView_InsertItem (hWnd, &lvi);
  1480. if (lvi.iItem == 0)
  1481. ListView_SetItemState(hWnd, 0, LVIS_FOCUSED, LVIS_FOCUSED);
  1482. }
  1483. // Convert the data to a string and print it
  1484. lvi.mask = LVIF_TEXT;
  1485. irg = WUdtypeToSz (lppropvar, sz, BUFMAX, ((LPUDINFO)lpUDObj->m_lpData)->lpfnFNumToSz);
  1486. lvi.pszText = sz;
  1487. lvi.iSubItem = iszVAL;
  1488. fSuccess = ListView_SetItem (hWnd, &lvi);
  1489. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  1490. // Put the type in the listview
  1491. lvi.iSubItem = iszTYPE;
  1492. lvi.pszText = (LPTSTR) rgszTypes[irg];
  1493. fSuccess = ListView_SetItem (hWnd, &lvi);
  1494. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  1495. if (fMakeVisible)
  1496. {
  1497. fSuccess = ListView_EnsureVisible(hWnd, lvi.iItem, FALSE);
  1498. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  1499. }
  1500. } // AddUDPropToListView
  1501. ////////////////////////////////////////////////////////////////////////////////
  1502. //
  1503. // InitListView
  1504. //
  1505. // Purpose:
  1506. // Initializes a list view control
  1507. //
  1508. ////////////////////////////////////////////////////////////////////////////////
  1509. void PASCAL
  1510. InitListView
  1511. (HWND hWndLV, // Handle of parent dialog
  1512. int irgLast, // Index of last column in array
  1513. TCHAR rgsz[][SHORTBUFMAX], // Array of column headings
  1514. BOOL fImageList) // Should the listview have an image list
  1515. {
  1516. HICON hIcon;
  1517. RECT rect;
  1518. HIMAGELIST hImlS;
  1519. LV_COLUMN lvc;
  1520. int irg;
  1521. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  1522. lvc.fmt = LVCFMT_LEFT;
  1523. // Initially force all columns to be the same size & fill the control.
  1524. GetClientRect(hWndLV, &rect);
  1525. // Subtract fudge factor
  1526. lvc.cx = (rect.right-rect.left)/(irgLast+1)-(GetSystemMetrics(SM_CXVSCROLL)/(irgLast+1));
  1527. // Add in all the columns.
  1528. for (irg = 0; irg <= irgLast; irg++)
  1529. {
  1530. lvc.pszText = rgsz[irg];
  1531. lvc.iSubItem = irg;
  1532. ListView_InsertColumn (hWndLV, irg, &lvc);
  1533. }
  1534. if (!fImageList)
  1535. return;
  1536. hIcon = LoadIcon (g_hmodThisDll, MAKEINTRESOURCE (IDD_BLANK_ICON));
  1537. if (hIcon != NULL)
  1538. {
  1539. hImlS = MsoImageList_Create (16, 16, TRUE, ICONSMAX, 0);
  1540. ListView_SetImageList (hWndLV, hImlS, LVSIL_SMALL);
  1541. giBlankIcon = MsoImageList_ReplaceIcon (hImlS, -1, hIcon);
  1542. Assert ((giBlankIcon != -1));
  1543. }
  1544. } // InitListView
  1545. ////////////////////////////////////////////////////////////////////////////////
  1546. //
  1547. // FSwapControls
  1548. //
  1549. // Purpose:
  1550. // Swaps the controls needed to display link info.
  1551. //
  1552. ////////////////////////////////////////////////////////////////////////////////
  1553. BOOL PASCAL
  1554. FSwapControls
  1555. (HWND hWndVal, // Handle of Value window
  1556. HWND hWndLinkVal, // Handle of Link Value Combo box
  1557. HWND hWndBoolTrue, // Handle of True radio button
  1558. HWND hWndBoolFalse, // Handle of False radio button
  1559. HWND hWndGroup, // Handle of Group box
  1560. HWND hWndType, // Handle of Type window
  1561. HWND hWndValText,
  1562. BOOL fLink, // Flag indicating a link
  1563. BOOL fBool) // Flag indicating a bool
  1564. {
  1565. if (fLink)
  1566. {
  1567. SendMessage (hWndValText, WM_SETTEXT, 0, (LPARAM) rgszValue[iszSOURCE]);
  1568. ShowWindow (hWndVal, SW_HIDE);
  1569. ShowWindow (hWndBoolTrue, SW_HIDE);
  1570. ShowWindow (hWndBoolFalse, SW_HIDE);
  1571. ShowWindow (hWndGroup, SW_HIDE);
  1572. ShowWindow (hWndLinkVal, SW_SHOW);
  1573. EnableWindow (hWndType, FALSE);
  1574. ClearEditControl (hWndVal, 0);
  1575. }
  1576. else
  1577. {
  1578. SendMessage (hWndValText, WM_SETTEXT, 0, (LPARAM) rgszValue[iszVALUE]);
  1579. ShowWindow (hWndLinkVal, SW_HIDE);
  1580. EnableWindow (hWndType, TRUE);
  1581. if (fBool)
  1582. {
  1583. ShowWindow (hWndVal, SW_HIDE);
  1584. ShowWindow (hWndBoolTrue, SW_SHOW);
  1585. ShowWindow (hWndBoolFalse, SW_SHOW);
  1586. ShowWindow (hWndGroup, SW_SHOW);
  1587. SendMessage (hWndBoolTrue, BM_SETCHECK, (WPARAM) CHECKED, 0);
  1588. SendMessage (hWndBoolFalse, BM_SETCHECK, (WPARAM) CLEAR, 0);
  1589. SendMessage (hWndType, CB_SETCURSEL, iszBOOL, 0);
  1590. ClearEditControl (hWndVal, 0);
  1591. }
  1592. else
  1593. {
  1594. ShowWindow (hWndVal, SW_SHOW);
  1595. EnableWindow(hWndVal, TRUE);
  1596. ShowWindow (hWndBoolTrue, SW_HIDE);
  1597. ShowWindow (hWndBoolFalse, SW_HIDE);
  1598. ShowWindow (hWndGroup, SW_HIDE);
  1599. SendMessage (hWndType, CB_SETCURSEL, iszTEXT, 0);
  1600. }
  1601. }
  1602. return TRUE;
  1603. } // FSwapControls
  1604. ////////////////////////////////////////////////////////////////////////////////
  1605. //
  1606. // PopulateControls
  1607. //
  1608. // Purpose:
  1609. // Populates the edit controls with the appropriate date from the object
  1610. //
  1611. ////////////////////////////////////////////////////////////////////////////////
  1612. VOID PASCAL PopulateControls (
  1613. LPUDOBJ lpUDObj, // Pointer to object
  1614. LPTSTR szName, // Name of the item to populate controls with
  1615. DWORD cLinks, // Number of links
  1616. DWQUERYLD lpfnDwQueryLinkData, // Pointer to app link callback
  1617. HWND hDlg, // Handle of the dialog
  1618. HWND hWndName, // Handle of the Name window
  1619. HWND hWndVal, // Handle of Value window
  1620. HWND hWndValText, // Handle of Value LTEXT
  1621. HWND hWndLink, // Handle of Link checkbox
  1622. HWND hWndLinkVal, // Handle of Link Value window
  1623. HWND hWndType, // Handle of Type window
  1624. HWND hWndBoolTrue, // Handle of True radio button
  1625. HWND hWndBoolFalse, // Handle of False radio button
  1626. HWND hWndGroup, // Handle of Group window
  1627. HWND hWndAdd, // Handle of Add button
  1628. HWND hWndDelete, // Handle of Delete button
  1629. BOOL *pfLink, // Indicates that the value is a link
  1630. BOOL *pfAdd) // Indicates the state of the Add button
  1631. {
  1632. UDTYPES udtype;
  1633. LPVOID lpv;
  1634. LPPROPVARIANT lppropvar; // A property from the UDObj linked-list.
  1635. BOOL f,fT;
  1636. TCHAR sz[BUFMAX];
  1637. LPUDPROP lpudp;
  1638. // Grab the type for the string and set up the dialog to have the right
  1639. // controls to display it.
  1640. udtype = UdtypesUserDefType (lpUDObj, szName);
  1641. AssertSz ((udtype != wUDinvalid), TEXT("User defined properties or ListView corrupt"));
  1642. // Get a name-specified property from the UD linked-list.
  1643. lppropvar = LppropvarUserDefGetPropVal (lpUDObj, szName, pfLink, &fT);
  1644. Assert (lppropvar != NULL || udtype == wUDbool || udtype == wUDdw);
  1645. if (lppropvar == NULL)
  1646. return;
  1647. lpv = LpvoidUserDefGetPropVal (lpUDObj, szName, UD_STATIC | UD_PTRWIZARD, pfLink, &fT);
  1648. Assert((lpv != NULL) || (udtype == wUDbool) || (udtype == wUDdw));
  1649. FSwapControls (hWndVal, hWndLinkVal, hWndBoolTrue, hWndBoolFalse, hWndGroup, hWndType, hWndValText, *pfLink, (udtype == wUDbool));
  1650. SendMessage (hWndType, CB_SETCURSEL, (WPARAM) WUdtypeToSz (lppropvar, (TCHAR *) sz, BUFMAX,
  1651. ((LPUDINFO)lpUDObj->m_lpData)->lpfnFNumToSz), 0);
  1652. SendMessage (hWndLink, BM_SETCHECK, (WPARAM) *pfLink, 0);
  1653. if (cLinks) // Let's make sure we enable the window if links are allowed
  1654. EnableWindow(hWndLink, TRUE);
  1655. if (*pfLink)
  1656. {
  1657. FCreateListOfLinks (cLinks, lpfnDwQueryLinkData, hWndLinkVal);
  1658. lpv = LpvoidUserDefGetPropVal (lpUDObj, szName, UD_LINK | UD_PTRWIZARD, pfLink, &fT);
  1659. Assert (lpv != NULL || udtype == wUDbool || udtype == wUDdw);
  1660. AssertSz ((lpv != NULL), TEXT("Dialog is corrupt in respect to Custom Properties database"));
  1661. // This code is added for bug 188 and the code is ugly !! :)
  1662. lpudp = LpudpropFindMatchingName (lpUDObj, szName);
  1663. if ((lpudp != NULL) && (lpudp->fLinkInvalid))
  1664. {
  1665. SetCustomDlgDefButton(hDlg, IDD_CUSTOM_DELETE);
  1666. SendMessage(hWndName, WM_SETTEXT, 0, (LPARAM)szName);
  1667. SendMessage(hWndVal, WM_SETTEXT, 0, (LPARAM)lpv);
  1668. EnableWindow(hWndDelete, TRUE);
  1669. EnableWindow(hWndAdd, FALSE);
  1670. EnableWindow(hWndLink, FALSE);
  1671. EnableWindow(hWndType, FALSE);
  1672. ShowWindow(hWndLinkVal, SW_HIDE);
  1673. ShowWindow(hWndVal, SW_SHOW);
  1674. EnableWindow(hWndVal, FALSE);
  1675. return;
  1676. }
  1677. // Select the current link for this property in the combobox. If the link
  1678. // name no longer exists (there's some contrived cases where this can
  1679. // happen) then this will select nothing.
  1680. SendMessage (hWndLinkVal, CB_SELECTSTRING, 0, (LPARAM) lpv);
  1681. EnableWindow(hWndLink, TRUE);
  1682. }
  1683. else if (udtype == wUDbool)
  1684. {
  1685. SendMessage ((lpv) ? hWndBoolTrue : hWndBoolFalse, BM_SETCHECK, CHECKED, 0);
  1686. SendMessage ((lpv) ? hWndBoolFalse : hWndBoolTrue, BM_SETCHECK, CLEAR, 0);
  1687. EnableWindow(hWndType, TRUE);
  1688. }
  1689. else
  1690. {
  1691. SendMessage (hWndVal, WM_SETTEXT, 0, (LPARAM) sz);
  1692. EnableWindow (hWndVal, TRUE);
  1693. EnableWindow(hWndType, TRUE);
  1694. }
  1695. if (*pfAdd)
  1696. {
  1697. SendMessage (hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  1698. *pfAdd = FALSE;
  1699. }
  1700. // HACK: Because the EN_UPDATE handler for hWndName checks fAdd to
  1701. // see if the button should be set to Add, when we set the text
  1702. // in the edit control, the button will change to Add unless
  1703. // fAdd is set to TRUE. Temporarily set the flag to TRUE to force
  1704. // the button to not change. Restore the original value after the
  1705. // text has been set.
  1706. f = *pfAdd;
  1707. *pfAdd = TRUE;
  1708. SendMessage (hWndName, WM_SETTEXT, 0, (LPARAM) szName);
  1709. *pfAdd = f;
  1710. // If we can fill the data in the controls, turn on the
  1711. // Delete button too.
  1712. EnableWindow (hWndDelete, TRUE);
  1713. SetCustomDlgDefButton(hDlg, gOKButtonID);
  1714. EnableWindow (hWndAdd, FALSE);
  1715. } // PopulateControls
  1716. ////////////////////////////////////////////////////////////////////////////////
  1717. //
  1718. // FSetupAddButton
  1719. //
  1720. // Purpose:
  1721. // Sets up the Add button correctly based on the type & flags.
  1722. //
  1723. ////////////////////////////////////////////////////////////////////////////////
  1724. BOOL PASCAL
  1725. FSetupAddButton
  1726. (DWORD iszType, // Index of the type in combobox
  1727. BOOL fLink, // Indicates a link
  1728. BOOL *pfAdd, // Indicates if the Add button is showing
  1729. HWND hWndAdd, // Handle of Add button
  1730. HWND hWndVal, // Handle of value button
  1731. HWND hWndName, // Handle of Name
  1732. HWND hDlg) // Handle of dialog
  1733. {
  1734. // Once the user starts typing, we can enable the Add button
  1735. // if there is text in the name & the value (unless this
  1736. // is a link or boolean, in which case we don't care about
  1737. // the value).
  1738. BOOL f;
  1739. if ((iszType != iszBOOL) && (!fLink))
  1740. {
  1741. if (SendMessage (hWndVal, EM_LINELENGTH, 0, 0) != 0)
  1742. {
  1743. f = (SendMessage (hWndName, WM_GETTEXTLENGTH, 0, 0) != 0);
  1744. if (f)
  1745. SetCustomDlgDefButton(hDlg, IDD_CUSTOM_ADD);
  1746. else
  1747. SetCustomDlgDefButton(hDlg, gOKButtonID);
  1748. EnableWindow (hWndAdd, f);
  1749. }
  1750. else
  1751. {
  1752. SetCustomDlgDefButton(hDlg, gOKButtonID);
  1753. EnableWindow (hWndAdd, FALSE);
  1754. }
  1755. }
  1756. // If it's a bool or link, just check to see that the name
  1757. // has stuff in it.
  1758. else
  1759. {
  1760. f = SendMessage (hWndName, WM_GETTEXTLENGTH, 0, 0) != 0;
  1761. if (f)
  1762. SetCustomDlgDefButton(hDlg, IDD_CUSTOM_ADD);
  1763. else
  1764. SetCustomDlgDefButton(hDlg, gOKButtonID);
  1765. EnableWindow (hWndAdd, f);
  1766. }
  1767. if (!*pfAdd)
  1768. {
  1769. SendMessage (hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszADD]);
  1770. *pfAdd = TRUE;
  1771. }
  1772. return TRUE;
  1773. } // FSetupAddButton
  1774. ////////////////////////////////////////////////////////////////////////////////
  1775. //
  1776. // WUdtypeToSz
  1777. //
  1778. // Purpose:
  1779. // Converts the given type into a string representation. Returns the
  1780. // index in the type combobox of the type.
  1781. //
  1782. ////////////////////////////////////////////////////////////////////////////////
  1783. WORD PASCAL WUdtypeToSz (
  1784. LPPROPVARIANT lppropvar, // Value with the type to be converted.
  1785. LPTSTR psz, // Buffer to put converted val in
  1786. DWORD cchMax, // Size of buffer (in chars)
  1787. BOOL (*lpfnFNumToSz)(NUM *, LPTSTR, DWORD))
  1788. {
  1789. SYSTEMTIME st;
  1790. WORD irg;
  1791. FILETIME ft;
  1792. Assert (lppropvar != NULL);
  1793. switch (lppropvar->vt)
  1794. {
  1795. case wUDlpsz :
  1796. StringCchCopy(psz, cchMax, lppropvar->pwszVal ); // don't care if it truncates
  1797. irg = iszTEXT;
  1798. break;
  1799. case wUDdate :
  1800. if (FScanMem((LPBYTE)&lppropvar->filetime,
  1801. 0, sizeof(FILETIME))) // if the date struct is all 0's
  1802. {
  1803. *psz = 0; // display the empty string
  1804. }
  1805. else if (!FileTimeToLocalFileTime(&lppropvar->filetime, &ft)
  1806. || !FileTimeToSystemTime (&ft, &st)
  1807. || (!GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, psz, cchMax)))
  1808. {
  1809. #ifdef DEBUG
  1810. DWORD dwErr = GetLastError();
  1811. #endif DEBUG
  1812. irg = iszUNKNOWN;
  1813. *psz = 0;
  1814. break;
  1815. }
  1816. irg = iszDATE;
  1817. break;
  1818. case wUDdw :
  1819. Assert(cchMax >= 11);
  1820. Assert(lppropvar->vt == VT_I4);
  1821. StringCchPrintf(psz, cchMax, TEXT("%ld"), lppropvar->lVal); // don't care if it truncates
  1822. irg = iszNUM;
  1823. break;
  1824. case wUDfloat :
  1825. if (lpfnFNumToSz != NULL)
  1826. irg = (*lpfnFNumToSz)((NUM*)&lppropvar->dblVal, psz, cchMax) ? iszNUM : iszUNKNOWN;
  1827. else
  1828. {
  1829. irg = iszUNKNOWN;
  1830. *psz = 0;
  1831. }
  1832. break;
  1833. case wUDbool :
  1834. // don't care if it truncates
  1835. StringCchCopy( psz, cchMax, lppropvar->boolVal ? (LPTSTR) &rgszBOOL[iszTRUE] : (LPTSTR) &rgszBOOL[iszFALSE] );
  1836. irg = iszBOOL;
  1837. break;
  1838. default :
  1839. irg = iszUNKNOWN;
  1840. } // switch
  1841. return irg;
  1842. } // WUdtypeToSz
  1843. ////////////////////////////////////////////////////////////////////////////////
  1844. //
  1845. // FCreateListOfLinks
  1846. //
  1847. // Purpose:
  1848. // Creates the dropdown list of linkable items.
  1849. //
  1850. ////////////////////////////////////////////////////////////////////////////////
  1851. BOOL PASCAL FCreateListOfLinks(
  1852. DWORD cLinks, // Number of links
  1853. DWQUERYLD lpfnDwQueryLinkData, // Link data callback
  1854. HWND hWndLinkVal) // Link Value window handle
  1855. {
  1856. DWORD irg;
  1857. LPTSTR lpstz;
  1858. // If the combobox is already filled, don't fill it
  1859. if (irg = (int)SendMessage(hWndLinkVal, CB_GETCOUNT,0, 0))
  1860. {
  1861. Assert(irg == cLinks);
  1862. return(TRUE);
  1863. }
  1864. lpstz = NULL;
  1865. // Call back the client app to get the list of linkable
  1866. // values, and put them in the value combobox.
  1867. for (irg = 0; irg < cLinks; irg++)
  1868. {
  1869. lpstz = (TCHAR *) ((*lpfnDwQueryLinkData) (QLD_LINKNAME, irg, &lpstz, NULL));
  1870. if (lpstz != NULL)
  1871. {
  1872. SendMessage (hWndLinkVal, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) lpstz);
  1873. LocalFree(lpstz);
  1874. // REVIEW: We probably ought to figure out a way to be more efficient here....
  1875. }
  1876. }
  1877. return TRUE;
  1878. } // FCreateListOfLinks
  1879. ////////////////////////////////////////////////////////////////////////////////
  1880. //
  1881. // FSetTypeControl
  1882. //
  1883. // Purpose:
  1884. // Sets the type control to have the given type selected.
  1885. //
  1886. ////////////////////////////////////////////////////////////////////////////////
  1887. BOOL PASCAL FSetTypeControl (
  1888. UDTYPES udtype, // Type to set the type to
  1889. HWND hWndType) // Handle of type control
  1890. {
  1891. WORD iType;
  1892. switch (udtype)
  1893. {
  1894. case wUDlpsz :
  1895. iType = iszTEXT;
  1896. break;
  1897. case wUDfloat :
  1898. case wUDdw :
  1899. iType = iszNUM;
  1900. break;
  1901. case wUDbool :
  1902. iType = iszBOOL;
  1903. break;
  1904. case wUDdate :
  1905. iType = iszDATE;
  1906. break;
  1907. default:
  1908. return FALSE;
  1909. }
  1910. SendMessage (hWndType, CB_SETCURSEL, (WPARAM) iType, 0);
  1911. return TRUE;
  1912. } // FSetTypeControl
  1913. ////////////////////////////////////////////////////////////////////////////////
  1914. //
  1915. // DeleteItem
  1916. //
  1917. // Purpose:
  1918. // Deletes an item from the UD object and the listview.
  1919. //
  1920. ////////////////////////////////////////////////////////////////////////////////
  1921. void PASCAL DeleteItem (
  1922. LPUDOBJ lpUDObj,
  1923. HWND hWndLV,
  1924. int iItem,
  1925. TCHAR sz[])
  1926. {
  1927. int i;
  1928. ListView_DeleteItem (hWndLV, iItem);
  1929. FUserDefDeleteProp (lpUDObj, sz);
  1930. // We just nuked the item with the focus, so let's get the new one
  1931. // if there are still items in the listview
  1932. if ((i = ListView_GetItemCount(hWndLV)) != 0)
  1933. {
  1934. // Figure out the index of the item to get the focus
  1935. i = (i == iItem) ? iItem - 1 : iItem;
  1936. ListView_SetItemState(hWndLV, i, LVIS_FOCUSED, LVIS_FOCUSED);
  1937. }
  1938. } // DeleteItem
  1939. ////////////////////////////////////////////////////////////////////////////////
  1940. //
  1941. // ResetTypeControl
  1942. //
  1943. // Purpose:
  1944. // Resets the value of the type control to Text.
  1945. //
  1946. ////////////////////////////////////////////////////////////////////////////////
  1947. void PASCAL ResetTypeControl (
  1948. HWND hDlg, // Handle of dialog
  1949. DWORD dwId, // Id of control
  1950. DWORD *piszType) // The type we've reset to
  1951. {
  1952. SendDlgItemMessage (hDlg, dwId, CB_SETCURSEL, iszTEXT, 0);
  1953. *piszType = iszTEXT;
  1954. } // ResetTypeControl
  1955. ////////////////////////////////////////////////////////////////////////////////
  1956. //
  1957. // FDisplayConversionWarning
  1958. //
  1959. // Purpose:
  1960. // Displays a warning about types being converted. Returns TRUE if
  1961. // the user presses "Cancel"
  1962. //
  1963. ////////////////////////////////////////////////////////////////////////////////
  1964. BOOL PASCAL FDisplayConversionWarning(HWND hDlg) // Handle of parent window
  1965. {
  1966. return (IdDoAlert(hDlg, idsPEWarningText, MB_ICONEXCLAMATION | MB_OKCANCEL) == IDCANCEL);
  1967. } // FDisplayConversionWarning
  1968. ////////////////////////////////////////////////////////////////////////////////
  1969. //
  1970. // LoadTextStrings
  1971. //
  1972. // Purpose:
  1973. // Loads all of the text needed by the dialogs from the DLL.
  1974. //
  1975. ////////////////////////////////////////////////////////////////////////////////
  1976. BOOL PASCAL FLoadTextStrings (void)
  1977. {
  1978. register int cLoads = 0;
  1979. register int cAttempts = 0;
  1980. // CchGetString returns a cch, so make it into a 1 or 0
  1981. // then add up the results,making sure we load as many as
  1982. // we try.
  1983. cLoads += (CchGetString (idsPEB, rgszOrders[iszBYTES], SHORTBUFMAX) && TRUE);
  1984. cAttempts++;
  1985. cLoads += (CchGetString (idsPEKB, rgszOrders[iszORDERKB], SHORTBUFMAX) && TRUE);
  1986. cAttempts++;
  1987. cLoads += (CchGetString (idsPEMB, rgszOrders[iszORDERMB], SHORTBUFMAX) && TRUE);
  1988. cAttempts++;
  1989. cLoads += (CchGetString (idsPEGB, rgszOrders[iszORDERGB], SHORTBUFMAX) && TRUE);
  1990. cAttempts++;
  1991. cLoads += (CchGetString (idsPETB, rgszOrders[iszORDERTB], SHORTBUFMAX) && TRUE);
  1992. cAttempts++;
  1993. cLoads += (CchGetString (idsPEBytes, rgszStats[iszBYTES], SHORTBUFMAX) && TRUE);
  1994. cAttempts++;
  1995. cLoads += (CchGetString (idsPEPages, rgszStats[iszPAGES], SHORTBUFMAX) && TRUE);
  1996. cAttempts++;
  1997. cLoads += (CchGetString (idsPEPara, rgszStats[iszPARA], SHORTBUFMAX) && TRUE);
  1998. cAttempts++;
  1999. cLoads += (CchGetString (idsPELines, rgszStats[iszLINES], SHORTBUFMAX) && TRUE);
  2000. cAttempts++;
  2001. cLoads += (CchGetString (idsPEWords, rgszStats[iszWORDS], SHORTBUFMAX) && TRUE);
  2002. cAttempts++;
  2003. cLoads += (CchGetString (idsPEChars, rgszStats[iszCHARS], SHORTBUFMAX) && TRUE);
  2004. cAttempts++;
  2005. cLoads += (CchGetString (idsPESlides, rgszStats[iszSLIDES], SHORTBUFMAX) && TRUE);
  2006. cAttempts++;
  2007. cLoads += (CchGetString (idsPENotes, rgszStats[iszNOTES], SHORTBUFMAX) && TRUE);
  2008. cAttempts++;
  2009. cLoads += (CchGetString (idsPEHiddenSlides, rgszStats[iszHIDDENSLIDES], SHORTBUFMAX) && TRUE);
  2010. cAttempts++;
  2011. cLoads += (CchGetString (idsPEMMClips, rgszStats[iszMMCLIPS], SHORTBUFMAX) && TRUE);
  2012. cAttempts++;
  2013. cLoads += (CchGetString (idsPEFormat, rgszStats[iszFORMAT], SHORTBUFMAX) && TRUE);
  2014. cAttempts++;
  2015. cLoads += (CchGetString (idsPEText, rgszTypes[iszTEXT], SHORTBUFMAX) && TRUE);
  2016. cAttempts++;
  2017. cLoads += (CchGetString (idsPEDate, rgszTypes[iszDATE], SHORTBUFMAX) && TRUE);
  2018. cAttempts++;
  2019. cLoads += (CchGetString (idsPENumber, rgszTypes[iszNUM], SHORTBUFMAX) && TRUE);
  2020. cAttempts++;
  2021. cLoads += (CchGetString (idsPEBool, rgszTypes[iszBOOL], SHORTBUFMAX) && TRUE);
  2022. cAttempts++;
  2023. cLoads += (CchGetString (idsPEUnknown, rgszTypes[iszUNKNOWN], SHORTBUFMAX) && TRUE);
  2024. cAttempts++;
  2025. cLoads += (CchGetString (idsPEStatName, rgszStatHeadings[iszNAME], SHORTBUFMAX) && TRUE);
  2026. cAttempts++;
  2027. cLoads += (CchGetString (idsPEValue, rgszStatHeadings[iszVAL], SHORTBUFMAX) && TRUE);
  2028. cAttempts++;
  2029. cLoads += (CchGetString (idsPEPropName, rgszHeadings[iszNAME], SHORTBUFMAX) && TRUE);
  2030. cAttempts++;
  2031. cLoads += (CchGetString (idsPEValue, rgszHeadings[iszVAL], SHORTBUFMAX) && TRUE);
  2032. cAttempts++;
  2033. cLoads += (CchGetString (idsPEType, rgszHeadings[iszTYPE], SHORTBUFMAX) && TRUE);
  2034. cAttempts++;
  2035. cLoads += (CchGetString (idsPETrue, rgszBOOL[iszTRUE], SHORTBUFMAX) && TRUE);
  2036. cAttempts++;
  2037. cLoads += (CchGetString (idsPEFalse, rgszBOOL[iszFALSE], SHORTBUFMAX) && TRUE);
  2038. cAttempts++;
  2039. cLoads += (CchGetString (idsPEAdd, rgszAdd[iszADD], SHORTBUFMAX) && TRUE);
  2040. cAttempts++;
  2041. cLoads += (CchGetString (idsPEModify, rgszAdd[iszMODIFY], SHORTBUFMAX) && TRUE);
  2042. cAttempts++;
  2043. cLoads += (CchGetString (idsPESource, rgszValue[iszSOURCE], SHORTBUFMAX) && TRUE);
  2044. cAttempts++;
  2045. cLoads += (CchGetString (idsPEValueColon, rgszValue[iszVALUE], BUFMAX) && TRUE);
  2046. cAttempts++;
  2047. return (cLoads == cAttempts);
  2048. } // LoadTextStrings
  2049. //
  2050. // Function: ISavePropDlgChanges
  2051. //
  2052. // Parameters:
  2053. //
  2054. // hwndDlg - dialog window handle
  2055. // hwndFrom - window handle from the NMHDR struct (see code above)
  2056. //
  2057. // Returns:
  2058. //
  2059. // TRUE since we handled the message.
  2060. //
  2061. // History:
  2062. //
  2063. // Created 09/16/94 martinth
  2064. //
  2065. int PASCAL ISavePropDlgChanges(LPALLOBJS lpallobjs, HWND hwndDlg, HWND hwndFrom)
  2066. {
  2067. TCHAR sz[BUFMAX];
  2068. int iRet = IDABORT; // MessageBox return.
  2069. LRESULT lRet = 0L; // (FALSE == dismiss property sheet).
  2070. if (CchGetString(idsCustomWarning, sz, ARRAYSIZE(sz)) == 0)
  2071. return(FALSE);
  2072. lpallobjs->fPropDlgPrompted = TRUE; // no warning next time!
  2073. iRet = MessageBox( hwndDlg, sz, TEXT("Warning"),
  2074. MB_ICONEXCLAMATION | MB_YESNOCANCEL );
  2075. switch( iRet )
  2076. {
  2077. case IDYES:
  2078. PropSheet_Apply(hwndFrom); // Let's get them changes
  2079. break;
  2080. // case IDNO: // do nothing
  2081. case IDCANCEL: // cancel and disallow sheet destroy.
  2082. lRet = TRUE;
  2083. break;
  2084. }
  2085. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, lRet );
  2086. return iRet;
  2087. }