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.

3546 lines
131 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. #include <winnls.h>
  28. #include <prsht.h>
  29. #include <commctrl.h>
  30. #include <shlwapi.h>
  31. #include <shlapip.h>
  32. #include "propdlg.h"
  33. #include "strings.h"
  34. #include "msohelp.h"
  35. // Max size of time/date string
  36. #define TIMEDATEMAX 256
  37. // Check button actions
  38. #define CLEAR 0
  39. #define CHECKED 1
  40. #define GREYED 2
  41. // Number of property sheet pages
  42. #define PAGESMAX 5
  43. // Max size for "short" temp buffers
  44. #define SHORTBUFMAX 128
  45. // The pages
  46. #ifdef _ABBREVIATED_DOCPROP_
  47. #define itabCUSTOM 0
  48. #define itabFIRST itabCUSTOM
  49. #else //_ABBREVIATED_DOCPROP_
  50. #define itabGENERAL 0
  51. #define itabSUMMARY 1
  52. #define itabSTATISTICS 2
  53. #define itabCONTENTS 3
  54. #define itabCUSTOM 4
  55. #define itabFIRST itabSUMMARY
  56. #endif //_ABBREVIATED_DOCPROP_
  57. // Defines for printing file sizes
  58. #define DELIMITER TEXT(',')
  59. #define iszBYTES 0
  60. #define iszORDERKB 1
  61. #define iszORDERMB 2
  62. #define iszORDERGB 3
  63. #define iszORDERTB 4
  64. static TCHAR rgszOrders[iszORDERTB+1][SHORTBUFMAX];
  65. // "bytes", // iszBYTES
  66. // "KB", // iszORDERKB
  67. // "MB", // iszORDERMB
  68. // "GB", // iszORDERGB
  69. // "TB" // iszORDERTB
  70. // note that szBYTES is defined above...
  71. #define iszPAGES 1
  72. #define iszPARA 2
  73. #define iszLINES 3
  74. #define iszWORDS 4
  75. #define iszCHARS 5
  76. #define iszSLIDES 6
  77. #define iszNOTES 7
  78. #define iszHIDDENSLIDES 8
  79. #define iszMMCLIPS 9
  80. #define iszFORMAT 10
  81. // Strings for the statistics listbox
  82. static TCHAR rgszStats[iszFORMAT+1][SHORTBUFMAX];
  83. // "Bytes:", // iszBYTES
  84. // "Pages:", // iszPAGES
  85. // "Paragraphs:", // iszPARA
  86. // "Lines:", // iszLINES
  87. // "Words:", // iszWORDS
  88. // "Characters:", // iszCHARS
  89. // "Slides:", // iszSLIDES
  90. // "Notes:", // iszNOTES
  91. // "Hidden Slides:", // iszHIDDENSLIDES
  92. // "Multimedia Clips:", // iszMMCLIPS
  93. // "Presentation Format:"// iszFORMAT
  94. #define BASE10 10
  95. // Number of pre-defined custom names
  96. #define NUM_BUILTIN_CUSTOM_NAMES 27
  97. #define iszTEXT 0
  98. #define iszDATE 1
  99. #define iszNUM 2
  100. #define iszBOOL 3
  101. #define iszUNKNOWN 4
  102. // Strings for the types of user-defined properties
  103. static TCHAR rgszTypes[iszUNKNOWN+1][SHORTBUFMAX];
  104. // "Text", // iszTEXT
  105. // "Date", // iszDATE
  106. // "Number", // iszNUM
  107. // "Yes or No", // iszBOOL
  108. // "Unknown" // iszUNKNOWN
  109. #define iszNAME 0
  110. #define iszVAL 1
  111. #define iszTYPE 2
  112. // Strings for the column headings for the statistics tab
  113. static TCHAR rgszStatHeadings[iszVAL+1][SHORTBUFMAX];
  114. // "Statistic Name", // iszNAME
  115. // "Value" // iszVAL
  116. // Strings for the column headings for custom tab
  117. static TCHAR rgszHeadings[iszTYPE+1][SHORTBUFMAX];
  118. // "Property Name", // iszNAME
  119. // "Value", // iszVAL
  120. // "Type" // iszTYPE
  121. #define iszTRUE 0
  122. #define iszFALSE 1
  123. // Strings for Booleans
  124. static TCHAR rgszBOOL[iszFALSE+1][SHORTBUFMAX];
  125. // "Yes", // iszTRUE
  126. // "No" // iszFALSE
  127. #define iszADD 0
  128. #define iszMODIFY 1
  129. // Strings for the Add button
  130. static TCHAR rgszAdd[iszMODIFY+1][SHORTBUFMAX];
  131. // "Add", // iszADD
  132. // "Modify" // iszMODIFY
  133. #define iszVALUE 0
  134. #define iszSOURCE 1
  135. // Strings for the source/value caption
  136. static TCHAR rgszValue[iszSOURCE+1][SHORTBUFMAX];
  137. // "Value:", // iszVALUE
  138. // "Source:" // iszSOURCE
  139. // Date formatting codes
  140. #define MMDDYY TEXT('0')
  141. #define DDMMYY TEXT('1')
  142. #define YYMMDD TEXT('2')
  143. #define OLEEPOCH 1900
  144. #define SYSEPOCH 1601
  145. #define ONECENTURY 100
  146. #define YEARINCENTURY(year) ((year) % ONECENTURY)
  147. #define CENTURYFROMYEAR(year) ((year) - YEARINCENTURY(year))
  148. //
  149. // Global data, to be deleted when FShowOfficePropDlg exits
  150. //
  151. static LPTSTR glpstzName;
  152. static LPTSTR glpstzValue;
  153. static int giLinkIcon;
  154. static int giInvLinkIcon;
  155. static int giBlankIcon;
  156. static HBRUSH hBrushPropDlg = NULL;
  157. const TCHAR g_szHelpFile[] = TEXT("windows.hlp");
  158. //
  159. // Internal prototypes
  160. //
  161. INT_PTR CALLBACK FGeneralDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  162. INT_PTR CALLBACK FSummaryDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  163. INT_PTR CALLBACK FStatisticsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  164. INT_PTR CALLBACK FCustomDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  165. INT_PTR CALLBACK FContentsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  166. INT_PTR CALLBACK FPropHeaderDlgProc (HWND hwnd, UINT message, LONG lParam);
  167. //static int CALLBACK ListViewCompareFunc(LPARAM, LPARAM, LPARAM);
  168. void PASCAL SetEditValLpsz (LPPROPVARIANT lppropvar, HWND hdlg, DWORD dwID );
  169. BOOL PASCAL GetEditValLpsz (LPPROPVARIANT lppropvar, HWND hDlg, DWORD dwId);
  170. BOOL PASCAL FAllocAndGetValLpstz (HWND hDlg, DWORD dwId, LPTSTR *lplpstz);
  171. BOOL PASCAL FAllocString (LPTSTR *lplpstz, DWORD cb);
  172. void PASCAL ClearEditControl (HWND hDlg, DWORD dwId);
  173. UDTYPES PASCAL UdtypesGetNumberType (LPTSTR lpstz, NUM *lpnumval,
  174. BOOL (*lpfnFSzToNum)(NUM *, LPTSTR));
  175. void PASCAL PrintTimeInDlg (HWND hDlg, DWORD dwId, FILETIME *pft);
  176. void PASCAL PrintEditTimeInDlg (HWND hDlg, FILETIME *pft);
  177. void PASCAL AddItemToListView (HWND hWnd, DWORD_PTR dw, const TCHAR *lpsz, BOOL fString);
  178. void PASCAL PopulateUDListView (HWND hWnd, LPUDOBJ lpUDObj);
  179. void PASCAL AddUDPropToListView (LPUDOBJ lpUDObj, HWND hWnd, LPTSTR lpszName, LPPROPVARIANT lppropvar, int iItem,
  180. BOOL fLink, BOOL fLinkInvalid, BOOL fMakeVisible);
  181. VOID PASCAL InitListView (HWND hDlg, int irgLast, TCHAR rgsz[][SHORTBUFMAX], BOOL fImageList);
  182. WORD PASCAL WUdtypeToSz (LPPROPVARIANT lppropvar, LPTSTR sz, DWORD cchMax,
  183. BOOL (*lpfnFNumToSz)(NUM *, LPTSTR, DWORD));
  184. BOOL PASCAL FSwapControls (HWND hWndVal, HWND hWndLinkVal, HWND hWndBoolTrue, HWND hWndBoolFalse, HWND hWndGroup, HWND hWndType, HWND hWndValText, BOOL fLink, BOOL fBool);
  185. VOID PASCAL PopulateControls (LPUDOBJ lpUDObj, LPTSTR szName, DWORD cLinks, DWQUERYLD lpfnDwQueryLinkData, HWND hDlg,
  186. HWND hWndName, HWND hWndVal, HWND hWndValText, HWND hWndLink, HWND hWndLinkVal, HWND hWndType,
  187. HWND hWndBoolTrue, HWND hWndBoolFalse, HWND hWndGroup, HWND hWndAdd, HWND hWndDelete, BOOL *pfLink, BOOL *pfAdd);
  188. BOOL PASCAL FSetupAddButton (DWORD iszType, BOOL fLink, BOOL *pfAdd, HWND hWndAdd, HWND hWndVal, HWND hWndName, HWND hDlg);
  189. BOOL PASCAL FCreateListOfLinks (DWORD cLinks, DWQUERYLD lpfnDwQueryLinkData, HWND hWndLinkVal);
  190. BOOL PASCAL FSetTypeControl (UDTYPES udtype, HWND hWndType);
  191. void PASCAL DeleteItem (LPUDOBJ lpUDObj, HWND hWndLV, int iItem, TCHAR sz[]);
  192. void PASCAL ResetTypeControl (HWND hDlg, DWORD dwId, DWORD *piszType);
  193. BOOL PASCAL FDisplayConversionWarning (HWND hDlg);
  194. BOOL PASCAL FLoadTextStrings (void);
  195. BOOL FGetCustomPropFromDlg(LPALLOBJS lpallobjs, HWND hDlg);
  196. VOID SetCustomDlgDefButton(HWND hDlg, int IDNew);
  197. INT PASCAL ISavePropDlgChanges(LPALLOBJS, HWND, HWND);
  198. /* WinHelp stuff. */
  199. static const DWORD rgIdhGeneral[] =
  200. {
  201. IDD_ITEMICON, IDH_GENERAL_ICON,
  202. IDD_NAME, IDH_GENERAL_NAME_BY_ICON,
  203. IDD_FILETYPE, IDH_GENERAL_FILETYPE,
  204. IDD_FILETYPE_LABEL, IDH_GENERAL_FILETYPE,
  205. IDD_LOCATION, IDH_GENERAL_LOCATION,
  206. IDD_LOCATION_LABEL, IDH_GENERAL_LOCATION,
  207. IDD_FILESIZE, IDH_GENERAL_FILESIZE,
  208. IDD_FILESIZE_LABEL, IDH_GENERAL_FILESIZE,
  209. IDD_FILENAME, IDH_GENERAL_MSDOSNAME,
  210. IDD_FILENAME_LABEL, IDH_GENERAL_MSDOSNAME,
  211. IDD_CREATED, IDH_GENERAL_CREATED,
  212. IDD_CREATED_LABEL, IDH_GENERAL_CREATED,
  213. IDD_LASTMODIFIED, IDH_GENERAL_MODIFIED,
  214. IDD_LASTMODIFIED_LABEL, IDH_GENERAL_MODIFIED,
  215. IDD_LASTACCESSED, IDH_GENERAL_ACCESSED,
  216. IDD_LASTACCESSED_LABEL, IDH_GENERAL_ACCESSED,
  217. IDD_ATTRIBUTES_LABEL, IDH_GENERAL_ATTRIBUTES,
  218. IDD_READONLY, IDH_GENERAL_READONLY,
  219. IDD_HIDDEN, IDH_GENERAL_HIDDEN,
  220. IDD_ARCHIVE, IDH_GENERAL_ARCHIVE,
  221. IDD_SYSTEM, IDH_GENERAL_SYSTEM
  222. };
  223. static const DWORD rgIdhSummary[] =
  224. {
  225. IDD_SUMMARY_TITLE, IDH_SUMMARY_TITLE,
  226. IDD_SUMMARY_TITLE_LABEL, IDH_SUMMARY_TITLE,
  227. IDD_SUMMARY_SUBJECT, IDH_SUMMARY_SUBJECT,
  228. IDD_SUMMARY_SUBJECT_LABEL, IDH_SUMMARY_SUBJECT,
  229. IDD_SUMMARY_AUTHOR, IDH_SUMMARY_AUTHOR,
  230. IDD_SUMMARY_AUTHOR_LABEL, IDH_SUMMARY_AUTHOR,
  231. IDD_SUMMARY_MANAGER, IDH_SUMMARY_MANAGER,
  232. IDD_SUMMARY_MANAGER_LABEL, IDH_SUMMARY_MANAGER,
  233. IDD_SUMMARY_COMPANY, IDH_SUMMARY_COMPANY,
  234. IDD_SUMMARY_COMPANY_LABEL, IDH_SUMMARY_COMPANY,
  235. IDD_SUMMARY_CATEGORY, IDH_SUMMARY_CATEGORY,
  236. IDD_SUMMARY_CATEGORY_LABEL, IDH_SUMMARY_CATEGORY,
  237. IDD_SUMMARY_KEYWORDS, IDH_SUMMARY_KEYWORDS,
  238. IDD_SUMMARY_KEYWORDS_LABEL, IDH_SUMMARY_KEYWORDS,
  239. IDD_SUMMARY_COMMENTS, IDH_SUMMARY_COMMENTS,
  240. IDD_SUMMARY_COMMENTS_LABEL, IDH_SUMMARY_COMMENTS,
  241. IDD_SUMMARY_TEMPLATE, IDH_SUMMARY_TEMPLATE,
  242. IDD_SUMMARY_TEMPLATETEXT, IDH_SUMMARY_TEMPLATE,
  243. IDD_SUMMARY_SAVEPREVIEW, IDH_SUMMARY_SAVEPREVIEW
  244. };
  245. static const DWORD rgIdhStatistics[] =
  246. {
  247. IDD_STATISTICS_CREATED, IDH_STATISTICS_CREATED,
  248. IDD_STATISTICS_CREATED_LABEL, IDH_STATISTICS_CREATED,
  249. IDD_STATISTICS_CHANGED, IDH_STATISTICS_MODIFIED,
  250. IDD_STATISTICS_CHANGED_LABEL, IDH_STATISTICS_MODIFIED,
  251. IDD_STATISTICS_ACCESSED, IDH_STATISTICS_ACCESSED,
  252. IDD_STATISTICS_ACCESSED_LABEL, IDH_STATISTICS_ACCESSED,
  253. IDD_STATISTICS_LASTPRINT, IDH_STATISTICS_LASTPRINT,
  254. IDD_STATISTICS_LASTPRINT_LABEL, IDH_STATISTICS_LASTPRINT,
  255. IDD_STATISTICS_LASTSAVEBY, IDH_STATISTICS_LASTSAVEBY,
  256. IDD_STATISTICS_LASTSAVEBY_LABEL, IDH_STATISTICS_LASTSAVEBY,
  257. IDD_STATISTICS_REVISION, IDH_STATISTICS_REVISION,
  258. IDD_STATISTICS_REVISION_LABEL, IDH_STATISTICS_REVISION,
  259. IDD_STATISTICS_TOTALEDIT, IDH_STATISTICS_TOTALEDIT,
  260. IDD_STATISTICS_TOTALEDIT_LABEL, IDH_STATISTICS_TOTALEDIT,
  261. IDD_STATISTICS_LVLABEL, IDH_STATISTICS_LISTVIEW,
  262. IDD_STATISTICS_LISTVIEW, IDH_STATISTICS_LISTVIEW
  263. };
  264. static const DWORD rgIdhContents[] =
  265. {
  266. IDD_CONTENTS_LISTBOX_LABEL, IDH_CONTENTS_LISTBOX,
  267. IDD_CONTENTS_LISTBOX, IDH_CONTENTS_LISTBOX
  268. };
  269. static const DWORD rgIdhCustom[] =
  270. {
  271. IDD_CUSTOM_NAME, IDH_CUSTOM_NAME,
  272. IDD_CUSTOM_NAME_LABEL, IDH_CUSTOM_NAME,
  273. IDD_CUSTOM_TYPE, IDH_CUSTOM_TYPE,
  274. IDD_CUSTOM_TYPE_LABEL, IDH_CUSTOM_TYPE,
  275. IDD_CUSTOM_VALUE, IDH_CUSTOM_VALUE,
  276. IDD_CUSTOM_VALUETEXT, IDH_CUSTOM_VALUE,
  277. IDD_CUSTOM_LINKVALUE, IDH_CUSTOM_LINKVALUE,
  278. IDD_CUSTOM_BOOLTRUE, IDH_CUSTOM_BOOLYES,
  279. IDD_CUSTOM_BOOLFALSE, IDH_CUSTOM_BOOLYES,
  280. IDD_CUSTOM_ADD, IDH_CUSTOM_ADDBUTTON,
  281. IDD_CUSTOM_DELETE, IDH_CUSTOM_DELETEBUTTON,
  282. IDD_CUSTOM_LINK, IDH_CUSTOM_LINKCHECK,
  283. IDD_CUSTOM_LISTVIEW, IDH_CUSTOM_LISTVIEW,
  284. IDD_CUSTOM_LISTVIEW_LABEL, IDH_CUSTOM_LISTVIEW
  285. };
  286. void FOfficeInitPropInfo(PROPSHEETPAGE * lpPsp, DWORD dwFlags, LPARAM lParam, LPFNPSPCALLBACK pfnCallback)
  287. {
  288. #ifndef _ABBREVIATED_DOCPROP_
  289. lpPsp[itabSUMMARY-itabFIRST].dwSize = sizeof(PROPSHEETPAGE);
  290. lpPsp[itabSUMMARY-itabFIRST].dwFlags = dwFlags;
  291. lpPsp[itabSUMMARY-itabFIRST].hInstance = g_hmodThisDll;
  292. lpPsp[itabSUMMARY-itabFIRST].pszTemplate = MAKEINTRESOURCE (IDD_SUMMARY);
  293. lpPsp[itabSUMMARY-itabFIRST].pszIcon = NULL;
  294. lpPsp[itabSUMMARY-itabFIRST].pszTitle = NULL;
  295. lpPsp[itabSUMMARY-itabFIRST].pfnDlgProc = FSummaryDlgProc;
  296. lpPsp[itabSUMMARY-itabFIRST].pfnCallback = pfnCallback;
  297. lpPsp[itabSUMMARY-itabFIRST].pcRefParent = NULL;
  298. lpPsp[itabSUMMARY-itabFIRST].lParam = lParam;
  299. lpPsp[itabSTATISTICS-itabFIRST].dwSize = sizeof(PROPSHEETPAGE);
  300. lpPsp[itabSTATISTICS-itabFIRST].dwFlags = dwFlags;
  301. lpPsp[itabSTATISTICS-itabFIRST].hInstance = g_hmodThisDll;
  302. lpPsp[itabSTATISTICS-itabFIRST].pszTemplate = MAKEINTRESOURCE (IDD_STATISTICS);
  303. lpPsp[itabSTATISTICS-itabFIRST].pszIcon = NULL;
  304. lpPsp[itabSTATISTICS-itabFIRST].pszTitle = NULL;
  305. lpPsp[itabSTATISTICS-itabFIRST].pfnDlgProc = FStatisticsDlgProc;
  306. lpPsp[itabSTATISTICS-itabFIRST].pfnCallback = pfnCallback;
  307. lpPsp[itabSTATISTICS-itabFIRST].pcRefParent = NULL;
  308. lpPsp[itabSTATISTICS-itabFIRST].lParam = lParam;
  309. lpPsp[itabCONTENTS-itabFIRST].dwSize = sizeof(PROPSHEETPAGE);
  310. lpPsp[itabCONTENTS-itabFIRST].dwFlags = dwFlags;
  311. lpPsp[itabCONTENTS-itabFIRST].hInstance = g_hmodThisDll;
  312. lpPsp[itabCONTENTS-itabFIRST].pszTemplate = MAKEINTRESOURCE (IDD_CONTENTS);
  313. lpPsp[itabCONTENTS-itabFIRST].pszIcon = NULL;
  314. lpPsp[itabCONTENTS-itabFIRST].pszTitle = NULL;
  315. lpPsp[itabCONTENTS-itabFIRST].pfnDlgProc = FContentsDlgProc;
  316. lpPsp[itabCONTENTS-itabFIRST].pfnCallback = pfnCallback;
  317. lpPsp[itabCONTENTS-itabFIRST].pcRefParent = NULL;
  318. lpPsp[itabCONTENTS-itabFIRST].lParam = lParam;
  319. #endif // _ABBREVIATED_DOCPROP_
  320. lpPsp[itabCUSTOM-itabFIRST].dwSize = sizeof(PROPSHEETPAGE);
  321. lpPsp[itabCUSTOM-itabFIRST].dwFlags = dwFlags;
  322. lpPsp[itabCUSTOM-itabFIRST].hInstance = g_hmodThisDll;
  323. lpPsp[itabCUSTOM-itabFIRST].pszTemplate = MAKEINTRESOURCE (IDD_CUSTOM);
  324. lpPsp[itabCUSTOM-itabFIRST].pszIcon = NULL;
  325. lpPsp[itabCUSTOM-itabFIRST].pszTitle = NULL;
  326. lpPsp[itabCUSTOM-itabFIRST].pfnDlgProc = FCustomDlgProc;
  327. lpPsp[itabCUSTOM-itabFIRST].pfnCallback = pfnCallback;
  328. lpPsp[itabCUSTOM-itabFIRST].pcRefParent = NULL;
  329. lpPsp[itabCUSTOM-itabFIRST].lParam = lParam;
  330. }
  331. ////////////////////////////////////////////////////////////////////////////////
  332. //
  333. // Attach
  334. //
  335. // Purpose:
  336. // Assigns HPROPSHEETPAGE to appropriate data block member.
  337. //
  338. ////////////////////////////////////////////////////////////////////////////////
  339. BOOL FAttach( LPALLOBJS lpallobjs, PROPSHEETPAGE* ppsp, HPROPSHEETPAGE hPage )
  340. {
  341. #define ASSIGN_PAGE_HANDLE( pfn, phpage ) \
  342. if( ppsp->pfnDlgProc == pfn ) { *(phpage) = hPage ; return TRUE ; }
  343. #if _ABBREVIATED_DOCPROP_
  344. ASSIGN_PAGE_HANDLE( FCustomDlgProc, &lpallobjs->lpUDObj->m_hPage );
  345. #else // _ABBREVIATED_DOCPROP_
  346. ASSIGN_PAGE_HANDLE( FSummaryDlgProc, &lpallobjs->lpSIObj->m_hPage );
  347. ASSIGN_PAGE_HANDLE( FStatisticsDlgProc, &lpallobjs->lpDSIObj->m_hPage );
  348. ASSIGN_PAGE_HANDLE( FCustomDlgProc, &lpallobjs->lpUDObj->m_hPage );
  349. #endif // _ABBREVIATED_DOCPROP_
  350. return FALSE;
  351. }
  352. ////////////////////////////////////////////////////////////////////////////////
  353. //
  354. // PropPageInit
  355. //
  356. // Purpose:
  357. // Keep track which pages have been init, such that we can know when we
  358. // can do the apply.
  359. //
  360. ////////////////////////////////////////////////////////////////////////////////
  361. void PropPageInit(LPALLOBJS lpallobjs, int iPage)
  362. {
  363. if (iPage > lpallobjs->iMaxPageInit)
  364. lpallobjs->iMaxPageInit = iPage;
  365. }
  366. ////////////////////////////////////////////////////////////////////////////////
  367. //
  368. // ApplyChangesBackToFile
  369. //
  370. // Purpose:
  371. // See if this is now the time to apply the changes back to the file
  372. //
  373. ////////////////////////////////////////////////////////////////////////////////
  374. BOOL ApplyChangesBackToFile(
  375. HWND hDlg,
  376. BOOL bFinalEdit /* user clicked OK rather than Apply*/,
  377. LPALLOBJS lpallobjs,
  378. int iPage)
  379. {
  380. HRESULT hres;
  381. BOOL fOK = FALSE;
  382. LPSTORAGE lpStg;
  383. WCHAR wszPath[ MAX_PATH ];
  384. if (iPage != lpallobjs->iMaxPageInit)
  385. return TRUE; // no errors
  386. #ifdef UNICODE
  387. lstrcpyn(wszPath, lpallobjs->szPath, ARRAYSIZE(wszPath));
  388. #else
  389. MultiByteToWideChar(CP_ACP, 0, lpallobjs->szPath, -1, wszPath, ARRAYSIZE(wszPath));
  390. #endif
  391. #ifdef WINNT
  392. hres = StgOpenStorageEx(wszPath,STGM_READWRITE|STGM_SHARE_EXCLUSIVE,STGFMT_ANY,0,NULL,NULL,
  393. &IID_IStorage, (void**)&lpStg );
  394. #else
  395. hres = StgOpenStorage(wszPath, NULL, STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0L, &lpStg );
  396. #endif
  397. if (SUCCEEDED(hres) && lpStg)
  398. {
  399. MESSAGE(TEXT("Now trying to save out properties"));
  400. fOK = (BOOL)DwOfficeSaveProperties( lpStg,
  401. lpallobjs->lpSIObj,
  402. lpallobjs->lpDSIObj,
  403. lpallobjs->lpUDObj,
  404. 0, // Flags
  405. STGM_READWRITE | STGM_SHARE_EXCLUSIVE
  406. );
  407. // Release the Storage (we don't need to commit it;
  408. // it's in dicrect-mode).
  409. lpStg->lpVtbl->Release (lpStg);
  410. lpStg= NULL;
  411. //
  412. // if we did properly save out the properties, than we should
  413. // clear the we have changed things flag...
  414. //
  415. if (fOK)
  416. {
  417. lpallobjs->fPropDlgChanged = FALSE;
  418. lpallobjs->fPropDlgPrompted = FALSE;
  419. }
  420. } // if (SUCCEEDED(hres) && lpStorage)
  421. if (!fOK)
  422. {
  423. UINT nMsgFlags = bFinalEdit ? MB_OKCANCEL /* give option to not dismiss page*/ : MB_OK;
  424. if (ShellMessageBox(g_hmodThisDll, GetParent(hDlg),
  425. MAKEINTRESOURCE(idsErrorOnSave), NULL,
  426. nMsgFlags | MB_ICONHAND, PathFindFileName(lpallobjs->szPath)) == IDOK)
  427. {
  428. fOK = TRUE;
  429. }
  430. PropSheet_UnChanged(GetParent(hDlg), hDlg);
  431. }
  432. return fOK;
  433. } // ApplyChangesBackToFile
  434. ////////////////////////////////////////////////////////////////////////////////
  435. //
  436. // FSummaryDlgProc
  437. //
  438. // Purpose:
  439. // Summary window dialog handler.
  440. //
  441. ////////////////////////////////////////////////////////////////////////////////
  442. #ifndef _ABBREVIATED_DOCPROP_
  443. INT_PTR CALLBACK FSummaryDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  444. {
  445. DWORD dwMask;
  446. DWORD dwT;
  447. LPALLOBJS lpallobjs = (LPALLOBJS)GetWindowLongPtr(hDlg, DWLP_USER);
  448. switch (message)
  449. {
  450. case WM_INITDIALOG :
  451. {
  452. PROPSHEETPAGE *ppspDlg = (PROPSHEETPAGE *) lParam;
  453. LPSIOBJ lpSIObj; // All SumInfo data
  454. LPDSIOBJ lpDSIObj; // All DocSumInfo (first section)
  455. LPPROPVARIANT rgpropvarSumInfo, rgpropvarDocSumInfo;
  456. lpallobjs = (LPALLOBJS)ppspDlg->lParam;
  457. PropPageInit(lpallobjs, itabSUMMARY);
  458. SetWindowLongPtr(hDlg, DWLP_USER, ppspDlg->lParam);
  459. lpSIObj = lpallobjs->lpSIObj;
  460. lpDSIObj = lpallobjs->lpDSIObj;
  461. dwMask = lpallobjs->dwMask;
  462. //
  463. // Validate our data.
  464. //
  465. if ((lpSIObj == NULL) ||
  466. (lpSIObj->m_lpData == NULL) ||
  467. (lpDSIObj == NULL) ||
  468. (lpDSIObj->m_lpData == NULL))
  469. {
  470. AssertSz (0, TEXT("Bad object data in Summary dlg"));
  471. return FALSE;
  472. }
  473. //
  474. // Since we'll be referencing the PropVariants a lot, get
  475. // a pointer directly to them.
  476. //
  477. rgpropvarSumInfo = GETSINFO(lpSIObj)->rgpropvar;
  478. rgpropvarDocSumInfo = GETSINFO(lpDSIObj)->rgpropvar;
  479. //
  480. // Copy the properties from the PropVariants to the Edit controls.
  481. //
  482. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_TITLE ], hDlg, IDD_SUMMARY_TITLE);
  483. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_SUBJECT ], hDlg, IDD_SUMMARY_SUBJECT);
  484. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_AUTHOR ], hDlg, IDD_SUMMARY_AUTHOR);
  485. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_COMMENTS ], hDlg, IDD_SUMMARY_COMMENTS);
  486. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_KEYWORDS ], hDlg, IDD_SUMMARY_KEYWORDS);
  487. //
  488. // Show the name of the template, if it exists, otherwise
  489. // don't even show the field.
  490. //
  491. if (rgpropvarSumInfo[ PVSI_TEMPLATE ].vt == VT_LPTSTR)
  492. {
  493. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_TEMPLATE ], hDlg, IDD_SUMMARY_TEMPLATE);
  494. }
  495. else
  496. {
  497. EnableWindow (GetDlgItem (hDlg, IDD_SUMMARY_TEMPLATETEXT), SW_HIDE);
  498. }
  499. SetEditValLpsz (&rgpropvarDocSumInfo[ PVDSI_CATEGORY ], hDlg, IDD_SUMMARY_CATEGORY);
  500. SetEditValLpsz (&rgpropvarDocSumInfo[ PVDSI_COMPANY ], hDlg, IDD_SUMMARY_COMPANY);
  501. SetEditValLpsz (&rgpropvarDocSumInfo[ PVDSI_MANAGER ], hDlg, IDD_SUMMARY_MANAGER);
  502. SetEditValLpsz (&rgpropvarSumInfo[ PVSI_COMMENTS ], hDlg, IDD_SUMMARY_COMMENTS);
  503. if (dwMask & OSPD_NOSAVEPREVIEW)
  504. {
  505. ShowWindow(GetDlgItem(hDlg, IDD_SUMMARY_SAVEPREVIEW), SW_HIDE);
  506. }
  507. else
  508. {
  509. if (!GETSINFO(lpSIObj)->fSaveSINail)
  510. GETSINFO(lpSIObj)->fSaveSINail = (dwMask & OSPD_SAVEPREVIEW_ON);
  511. #ifdef SHELL
  512. if (!GETSINFO(lpSIObj)->fSaveSINail)
  513. EnableWindow (GetDlgItem (hDlg, IDD_SUMMARY_SAVEPREVIEW), FALSE);
  514. else
  515. #endif
  516. SendDlgItemMessage(hDlg, IDD_SUMMARY_SAVEPREVIEW, BM_SETCHECK,
  517. (WPARAM) GETSINFO(lpSIObj)->fSaveSINail,0);
  518. }
  519. lpallobjs->fPropDlgChanged = FALSE; // It might have been set by the EN_UPDATE check, so let's reset it here
  520. }
  521. return TRUE;
  522. case WM_CTLCOLOREDIT :
  523. if ((HWND)lParam != GetDlgItem(hDlg, IDD_SUMMARY_TEMPLATE)) // only change color for the
  524. break; // the template
  525. case WM_CTLCOLORDLG :
  526. case WM_CTLCOLORSTATIC :
  527. if (hBrushPropDlg == NULL)
  528. break;
  529. DeleteObject(hBrushPropDlg);
  530. if ((hBrushPropDlg = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) == NULL)
  531. break;
  532. SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNFACE));
  533. SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT));
  534. return (INT_PTR) hBrushPropDlg;
  535. case WM_COMMAND:
  536. {
  537. BOOL fNailChanged = FALSE;
  538. AssertSz( (lpallobjs != NULL && lpallobjs->lpSIObj != NULL),
  539. TEXT("Invalid global structure in WM_COMMAND" ));
  540. if ((HIWORD (wParam) == BN_CLICKED) && (LOWORD(wParam) == IDD_SUMMARY_SAVEPREVIEW))
  541. {
  542. GETSINFO(lpallobjs->lpSIObj)->fSaveSINail = !GETSINFO(lpallobjs->lpSIObj)->fSaveSINail;
  543. OfficeDirtySIObj (lpallobjs->lpSIObj, TRUE);
  544. fNailChanged = TRUE;
  545. }
  546. if (HIWORD (wParam) == EN_UPDATE
  547. ||
  548. fNailChanged)
  549. {
  550. lpallobjs->fPropDlgChanged = TRUE;
  551. PropSheet_Changed(GetParent(hDlg), hDlg);
  552. }
  553. break;
  554. }
  555. case WM_NOTIFY :
  556. switch (((NMHDR FAR *) lParam)->code)
  557. {
  558. case PSN_APPLY :
  559. //
  560. // Save what user entered.
  561. //
  562. {
  563. LPSIOBJ lpSIObj; // All SumInfo data
  564. LPDSIOBJ lpDSIObj; // All DocSumInfo data
  565. BOOL fSIChanged = FALSE; // The SumInfo properties have changed
  566. BOOL fDSIChanged = FALSE; // The DocSumInfo properties have changed
  567. // SumInfo and DocSumInfo properties.
  568. LPPROPVARIANT rgpropvarSumInfo, rgpropvarDocSumInfo;
  569. lpSIObj = lpallobjs->lpSIObj;
  570. rgpropvarSumInfo = GETSINFO(lpSIObj)->rgpropvar;
  571. lpDSIObj = lpallobjs->lpDSIObj;
  572. rgpropvarDocSumInfo = GETDSINFO(lpDSIObj)->rgpropvar;
  573. fSIChanged |= GetEditValLpsz (&rgpropvarSumInfo[PVSI_TITLE], hDlg, IDD_SUMMARY_TITLE);
  574. fSIChanged |= GetEditValLpsz (&rgpropvarSumInfo[PVSI_SUBJECT], hDlg, IDD_SUMMARY_SUBJECT);
  575. fSIChanged |= GetEditValLpsz (&rgpropvarSumInfo[PVSI_AUTHOR], hDlg, IDD_SUMMARY_AUTHOR);
  576. fSIChanged |= GetEditValLpsz (&rgpropvarSumInfo[PVSI_COMMENTS], hDlg, IDD_SUMMARY_COMMENTS);
  577. fSIChanged |= GetEditValLpsz (&rgpropvarSumInfo[PVSI_KEYWORDS], hDlg, IDD_SUMMARY_KEYWORDS);
  578. fSIChanged |= GetEditValLpsz (&rgpropvarSumInfo[PVSI_TEMPLATE], hDlg, IDD_SUMMARY_TEMPLATE);
  579. fDSIChanged |= GetEditValLpsz (&rgpropvarDocSumInfo[PVDSI_CATEGORY], hDlg, IDD_SUMMARY_CATEGORY);
  580. fDSIChanged |= GetEditValLpsz (&rgpropvarDocSumInfo[PVDSI_MANAGER], hDlg, IDD_SUMMARY_MANAGER);
  581. fDSIChanged |= GetEditValLpsz (&rgpropvarDocSumInfo[PVDSI_COMPANY], hDlg, IDD_SUMMARY_COMPANY);
  582. if (fSIChanged)
  583. {
  584. OfficeDirtySIObj (lpSIObj, TRUE);
  585. }
  586. if (fDSIChanged)
  587. {
  588. OfficeDirtyDSIObj (lpDSIObj, TRUE);
  589. }
  590. MESSAGE (TEXT("PSN_APPLY - Summary Page"));
  591. if (FSumInfoShouldSave (lpSIObj)
  592. || FDocSumShouldSave (lpDSIObj)
  593. || lpallobjs->fPropDlgChanged )
  594. {
  595. ApplyChangesBackToFile(hDlg, (BOOL)((PSHNOTIFY*)lParam)->lParam, lpallobjs, itabSUMMARY);
  596. }
  597. }
  598. return TRUE;
  599. case PSN_QUERYCANCEL:
  600. if (lpallobjs->fPropDlgChanged && !lpallobjs->fPropDlgPrompted)
  601. ISavePropDlgChanges(lpallobjs, hDlg, ((NMHDR FAR *)lParam)->hwndFrom);
  602. return TRUE;
  603. case PSN_SETACTIVE :
  604. return TRUE;
  605. } // switch (WM_NOTIFY)
  606. break;
  607. case WM_CLOSE:
  608. //
  609. // This page contains multi-line edit controls, which swallow
  610. // the ESC key but generat a WM_CLOSE. We need to pass this
  611. // message on to our parent (the property sheet) so that it is
  612. // handled correctly...
  613. //
  614. PostMessage( GetParent(hDlg), WM_CLOSE, wParam, lParam );
  615. break;
  616. case WM_CONTEXTMENU:
  617. WinHelp((HANDLE)wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR)rgIdhSummary);
  618. break;
  619. case WM_HELP:
  620. WinHelp(((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)rgIdhSummary);
  621. break;
  622. } // switch (message)
  623. return FALSE;
  624. } // FSummaryDlgProc
  625. #endif //_ABBREVIATED_DOCPROP_
  626. ////////////////////////////////////////////////////////////////////////////////
  627. //
  628. // FStatisticsDlgProc
  629. //
  630. // Purpose;
  631. // Displays the Statistics dialog
  632. //
  633. ////////////////////////////////////////////////////////////////////////////////
  634. #ifndef _ABBREVIATED_DOCPROP_
  635. INT_PTR CALLBACK FStatisticsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  636. {
  637. HWND hWndLV;
  638. LPSIOBJ lpSIObj; // All SumInfo data.
  639. LPDSIOBJ lpDSIObj; // All DocSumInfo data.
  640. LPPROPVARIANT rgpropvarSumInfo, rgpropvarDocSumInfo;
  641. HANDLE hFile;
  642. FILETIME ftTime;
  643. DWORD dwT;
  644. BOOL fListData; // Did we stick some data in the listview??
  645. switch (message)
  646. {
  647. case WM_INITDIALOG :
  648. {
  649. PROPSHEETPAGE *ppspDlg = (PROPSHEETPAGE *) lParam;
  650. LPALLOBJS lpallobjs = (LPALLOBJS)ppspDlg->lParam;
  651. // Page does not do apply so don't worry
  652. // PropPageInit(lpallobjs, itabSTATISTICS);
  653. lpSIObj = lpallobjs->lpSIObj; // Get the summary object.
  654. lpDSIObj = lpallobjs->lpDSIObj; // Get the doc sum. object.
  655. if (lpSIObj->m_lpData == NULL ||
  656. lpDSIObj->m_lpData == NULL)
  657. {
  658. MESSAGE (TEXT("Invalid SumInfo or DocSumInfo object"));
  659. return FALSE;
  660. }
  661. rgpropvarSumInfo = GETSINFO(lpSIObj)->rgpropvar;
  662. rgpropvarDocSumInfo = GETSINFO(lpDSIObj)->rgpropvar;
  663. // Let the app update the stats if they provided a callback
  664. if (((LPSINFO) ((LPOFFICESUMINFO) lpSIObj)->m_lpData)->lpfnFUpdateStats != NULL)
  665. (*(((LPSINFO) ((LPOFFICESUMINFO) lpSIObj)->m_lpData)->lpfnFUpdateStats))(
  666. GetFocus(),
  667. lpSIObj, lpDSIObj);
  668. hWndLV = GetDlgItem(hDlg, IDD_STATISTICS_LISTVIEW);
  669. InitListView (hWndLV, iszVAL, rgszStatHeadings, FALSE);
  670. // Last saved by
  671. if (rgpropvarSumInfo[ PVSI_LASTAUTHOR ].vt == VT_LPTSTR)
  672. {
  673. SendDlgItemMessage
  674. (hDlg, IDD_STATISTICS_LASTSAVEBY, WM_SETTEXT, 0,
  675. (LPARAM) rgpropvarSumInfo[ PVSI_LASTAUTHOR ].pszVal);
  676. }
  677. // Revision #
  678. if (rgpropvarSumInfo[ PVSI_REVNUMBER ].vt == VT_LPTSTR)
  679. {
  680. SendDlgItemMessage
  681. (hDlg, IDD_STATISTICS_REVISION, WM_SETTEXT, 0,
  682. (LPARAM) rgpropvarSumInfo[ PVSI_REVNUMBER ].pszVal);
  683. }
  684. fListData = FALSE;
  685. if (rgpropvarSumInfo[ PVSI_PAGECOUNT ].vt == VT_I4)
  686. {
  687. AddItemToListView (hWndLV, rgpropvarSumInfo[ PVSI_PAGECOUNT ].lVal,
  688. rgszStats[iszPAGES], FALSE);
  689. fListData = TRUE;
  690. }
  691. if (rgpropvarDocSumInfo[ PVDSI_SLIDECOUNT ].vt == VT_I4)
  692. {
  693. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_SLIDECOUNT ].lVal,
  694. rgszStats[iszSLIDES], FALSE);
  695. fListData = TRUE;
  696. }
  697. if (rgpropvarDocSumInfo[ PVDSI_PARACOUNT ].vt == VT_I4)
  698. {
  699. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_PARACOUNT ].lVal,
  700. rgszStats[iszPARA], FALSE);
  701. fListData = TRUE;
  702. }
  703. if (rgpropvarDocSumInfo[ PVDSI_LINECOUNT ].vt == VT_I4)
  704. {
  705. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_LINECOUNT ].lVal,
  706. rgszStats[iszLINES], FALSE);
  707. fListData = TRUE;
  708. }
  709. if (rgpropvarSumInfo[ PVSI_WORDCOUNT ].vt == VT_I4)
  710. {
  711. AddItemToListView (hWndLV, rgpropvarSumInfo[ PVSI_WORDCOUNT ].lVal,
  712. rgszStats[iszWORDS], FALSE);
  713. fListData = TRUE;
  714. }
  715. if (rgpropvarSumInfo[ PVSI_CHARCOUNT ].vt == VT_I4)
  716. {
  717. AddItemToListView (hWndLV, rgpropvarSumInfo[ PVSI_CHARCOUNT ].lVal,
  718. rgszStats[iszCHARS], FALSE);
  719. fListData = TRUE;
  720. }
  721. if (rgpropvarDocSumInfo[ PVDSI_BYTECOUNT ].vt == VT_I4)
  722. {
  723. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_BYTECOUNT ].lVal,
  724. rgszStats[iszBYTES], FALSE);
  725. fListData = TRUE;
  726. }
  727. if (rgpropvarDocSumInfo[ PVDSI_NOTECOUNT ].vt == VT_I4)
  728. {
  729. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_NOTECOUNT ].lVal,
  730. rgszStats[iszNOTES], FALSE);
  731. fListData = TRUE;
  732. }
  733. if (rgpropvarDocSumInfo[ PVDSI_HIDDENCOUNT ].vt == VT_I4)
  734. {
  735. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_HIDDENCOUNT ].lVal,
  736. rgszStats[iszHIDDENSLIDES], FALSE);
  737. fListData = TRUE;
  738. }
  739. if (rgpropvarDocSumInfo[ PVDSI_MMCLIPCOUNT ].vt == VT_I4)
  740. {
  741. AddItemToListView (hWndLV, rgpropvarDocSumInfo[ PVDSI_MMCLIPCOUNT ].lVal,
  742. rgszStats[iszMMCLIPS], FALSE);
  743. fListData = TRUE;
  744. }
  745. if (rgpropvarDocSumInfo[ PVDSI_PRESFORMAT ].vt == VT_LPTSTR)
  746. {
  747. AddItemToListView (hWndLV, (DWORD_PTR) rgpropvarDocSumInfo[ PVDSI_PRESFORMAT ].pszVal,
  748. rgszStats[iszFORMAT], TRUE);
  749. fListData = TRUE;
  750. }
  751. if (!fListData)
  752. {
  753. ShowWindow(GetDlgItem(hDlg, IDD_LINE_2), SW_HIDE);
  754. ShowWindow(GetDlgItem(hDlg, IDD_STATISTICS_LVLABEL), SW_HIDE);
  755. ShowWindow(hWndLV, SW_HIDE);
  756. hWndLV = NULL;
  757. }
  758. if (!lpallobjs->fFiledataInit)
  759. {
  760. hFile = FindFirstFile(lpallobjs->szPath, &lpallobjs->filedata);
  761. lpallobjs->fFiledataInit = TRUE;
  762. if (hFile != INVALID_HANDLE_VALUE)
  763. {
  764. FindClose(hFile);
  765. lpallobjs->fFindFileSuccess = TRUE;
  766. }
  767. }
  768. if (lpallobjs->fFindFileSuccess)
  769. {
  770. // Last Access
  771. PrintTimeInDlg (hDlg, IDD_STATISTICS_ACCESSED, &(lpallobjs->filedata.ftLastAccessTime));
  772. // Last modified
  773. PrintTimeInDlg (hDlg, IDD_STATISTICS_CHANGED, &(lpallobjs->filedata.ftLastWriteTime));
  774. }
  775. // Create Time
  776. if (rgpropvarSumInfo[ PVSI_CREATE_DTM ].vt == VT_FILETIME)
  777. {
  778. PrintTimeInDlg(hDlg, IDD_STATISTICS_CREATED,
  779. &rgpropvarSumInfo[ PVSI_CREATE_DTM ].filetime);
  780. }
  781. // Last Printed Time
  782. if (rgpropvarSumInfo[ PVSI_LASTPRINTED ].vt == VT_FILETIME)
  783. {
  784. PrintTimeInDlg(hDlg, IDD_STATISTICS_LASTPRINT,
  785. &rgpropvarSumInfo[ PVSI_LASTPRINTED ].filetime);
  786. }
  787. // Total Edit Time
  788. // If we are not allowing time tracking display 0 minutes
  789. if (GETSINFO(lpSIObj)->fNoTimeTracking)
  790. {
  791. ftTime.dwLowDateTime = 0;
  792. ftTime.dwHighDateTime = 0;
  793. PrintEditTimeInDlg(hDlg, &ftTime);
  794. }
  795. else if (rgpropvarSumInfo[ PVSI_EDITTIME ].vt == VT_FILETIME)
  796. {
  797. PrintEditTimeInDlg(hDlg, &rgpropvarSumInfo[ PVSI_EDITTIME ].filetime);
  798. }
  799. // lpallobjs->fPropDlgChanged = FALSE;
  800. }
  801. return TRUE;
  802. case WM_CTLCOLORBTN :
  803. case WM_CTLCOLOREDIT :
  804. case WM_CTLCOLORDLG :
  805. case WM_CTLCOLORSTATIC :
  806. if (hBrushPropDlg == NULL)
  807. break;
  808. DeleteObject(hBrushPropDlg);
  809. if ((hBrushPropDlg = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) == NULL)
  810. break;
  811. SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNFACE));
  812. SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT));
  813. return (INT_PTR) hBrushPropDlg;
  814. case WM_SYSCOLORCHANGE:
  815. hWndLV = GetDlgItem(hDlg, IDD_STATISTICS_LISTVIEW);
  816. PostMessage(hWndLV, WM_SYSCOLORCHANGE, wParam, lParam);
  817. return TRUE;
  818. break;
  819. case WM_NOTIFY :
  820. switch (((NMHDR FAR *) lParam)->code)
  821. {
  822. case PSN_SETACTIVE :
  823. return TRUE;
  824. case PSN_RESET:
  825. case PSN_APPLY:
  826. MESSAGE (TEXT("PSN_APPLY - Statistics Page"));
  827. return TRUE;
  828. } // switch
  829. break;
  830. case WM_CONTEXTMENU:
  831. WinHelp((HANDLE)wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR)rgIdhStatistics);
  832. break;
  833. case WM_HELP:
  834. WinHelp(((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)rgIdhStatistics);
  835. break;
  836. } // switch
  837. return FALSE;
  838. } // FStatisticsDlgProc
  839. #endif //_ABBREVIATED_DOCPROP_
  840. ////////////////////////////////////////////////////////////////////////////////
  841. //
  842. // FContentsDlgProc
  843. //
  844. // Purpose:
  845. // Display the contents dialog
  846. //
  847. ////////////////////////////////////////////////////////////////////////////////
  848. #ifndef _ABBREVIATED_DOCPROP_
  849. INT_PTR CALLBACK FContentsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  850. {
  851. LPDSIOBJ lpDSIObj; // All DocSumInfo data.
  852. LPPROPVARIANT rgpropvarDocSumInfo; // Just the DocSumInfo properties.
  853. switch (message)
  854. {
  855. case WM_INITDIALOG :
  856. {
  857. BOOL fInitDialogSuccess = TRUE;
  858. PROPSHEETPAGE *ppspDlg = (PROPSHEETPAGE *)lParam;
  859. SHORT cT;
  860. LRESULT lError;
  861. TCHAR *psz;
  862. TCHAR ch;
  863. ULONG cHeadings; // Number of document headings
  864. ULONG cDocParts; // Total count of document parts.
  865. LPPROPVARIANT rgpropvarHeadings; // The Variant|Vector of heading pairs
  866. LPTSTR *rglptstrDocParts; // The document parts.
  867. ULONG ulHeadingIndex; // Index into rgpropvarHeadings
  868. ULONG ulTotalDocPartIndex; // Index into rglptstrDocParts
  869. ULONG ulSubDocPartIndex; // Index into rglptstrDocParts for the current heading
  870. ULONG cbDocPart = 0; // # bytes in a particular docpart.
  871. LPTSTR tszDocumentPart = NULL; // One DocPart with a pre-pending tab.
  872. lpDSIObj = ((LPALLOBJS)ppspDlg->lParam)->lpDSIObj; // Get the document sum. object.
  873. // Validate our objects.
  874. if (lpDSIObj == NULL || lpDSIObj->m_lpData == NULL)
  875. return FALSE;
  876. // Get to the DocSumInfo properties.
  877. rgpropvarDocSumInfo = GETDSINFO(lpDSIObj)->rgpropvar;
  878. // See if we have any headings.
  879. if (rgpropvarDocSumInfo[ PVDSI_HEADINGPAIR ].vt != (VT_VECTOR | VT_VARIANT))
  880. {
  881. // Nothing to display.
  882. return FALSE;
  883. }
  884. // Get the Heading-Pair array and count. Validate the size of the array.
  885. cHeadings = rgpropvarDocSumInfo[ PVDSI_HEADINGPAIR ].capropvar.cElems;
  886. rgpropvarHeadings = rgpropvarDocSumInfo[ PVDSI_HEADINGPAIR ].capropvar.pElems;
  887. if (cHeadings == 0)
  888. {
  889. goto ExitCaseWM_INITDIALOG;
  890. }
  891. if (cHeadings & 0x1)
  892. {
  893. // This is an invalid array; the elements always come in (heading,count) pairs,
  894. // so there should be an even number of elements in the array.
  895. MESSAGE (TEXT("Invalid Headings array (should be an even number of elements)"));
  896. goto ExitCaseWM_INITDIALOG;
  897. }
  898. // Get the DocParts array and its size. All elements of this array are LPTSTRs.
  899. // Note that this array need not exist.
  900. cDocParts = 0;
  901. if (rgpropvarDocSumInfo[ PVDSI_DOCPARTS ].vt == (VT_VECTOR | VT_LPTSTR))
  902. {
  903. rglptstrDocParts = (LPTSTR*) rgpropvarDocSumInfo[ PVDSI_DOCPARTS ].calpstr.pElems;
  904. cDocParts = rgpropvarDocSumInfo[ PVDSI_DOCPARTS ].calpstr.cElems;
  905. }
  906. // Loop through the Heading-Pair array. For each heading, we'll write it
  907. // to the list box, and then use the associated count to write Document Parts
  908. // to the list box. We'll stop when we've processed the array, or when
  909. // fInitDialogSuccess goes FALSE.
  910. ulTotalDocPartIndex = 0;
  911. for (ulHeadingIndex = 0;
  912. (ulHeadingIndex < cHeadings) && fInitDialogSuccess;
  913. ulHeadingIndex+=2)
  914. {
  915. // Verify that the next two elements in the Heading-Pair array are
  916. // a string and a Long.
  917. if (rgpropvarHeadings[ ulHeadingIndex ].vt != VT_LPTSTR
  918. ||
  919. rgpropvarHeadings[ ulHeadingIndex + 1 ].vt != VT_I4)
  920. {
  921. MESSAGE (TEXT("Invalid Heading Pair type"));
  922. fInitDialogSuccess = FALSE;
  923. break;
  924. }
  925. // Write the Heading to the list box.
  926. lError = SendDlgItemMessage (
  927. hDlg, IDD_CONTENTS_LISTBOX, LB_ADDSTRING, (WPARAM) 0,
  928. (LPARAM) rgpropvarHeadings[ ulHeadingIndex ].pszVal );
  929. if (lError == LB_ERR || lError == LB_ERRSPACE)
  930. {
  931. MESSAGE(TEXT("Could not write to list box"));
  932. fInitDialogSuccess = FALSE;
  933. break;
  934. }
  935. // Verify that the DocParts we've written so far, plus those we're about
  936. // to write, don't exceed the total in the DocParts array.
  937. if (ulTotalDocPartIndex + rgpropvarHeadings[ ulHeadingIndex + 1 ].lVal
  938. > cDocParts)
  939. {
  940. MESSAGE (TEXT("Invalid doc-part count for heading"));
  941. fInitDialogSuccess = FALSE;
  942. break;
  943. }
  944. // Now loop through the document parts that are associated with this
  945. // heading. We'll insert a tab character in front of each string
  946. // so that the display looks better. We'll stop when we've processed
  947. // all the DocParts under this heading, or when fInitDialogSuccess goes
  948. // FALSE;
  949. for (ulSubDocPartIndex = ulTotalDocPartIndex;
  950. fInitDialogSuccess
  951. && (ulSubDocPartIndex
  952. < ulTotalDocPartIndex + rgpropvarHeadings[ ulHeadingIndex + 1 ].lVal);
  953. ulSubDocPartIndex++)
  954. {
  955. // Determine how big the DocumentPart string is, including a NULL
  956. // terminator, and including a tab character that we're going to insert.
  957. cbDocPart // Count the characters.
  958. #ifdef UNICODE
  959. = CchTszLen (rglptstrDocParts[ ulSubDocPartIndex ]) + 2;
  960. #else
  961. = CchAnsiSzLen (rglptstrDocParts[ ulSubDocPartIndex ]) + 2;
  962. #endif
  963. cbDocPart *= sizeof(TCHAR); // Convert to a *byte* count.
  964. // Alloc a buffer which will hold a tab character followed by the DocPart string.
  965. // Since there's no easy way to add cleanup code for this case block,
  966. // we must ensure that we free this buffer before any break could possibly
  967. // occur.
  968. tszDocumentPart = PvMemAlloc (cbDocPart);
  969. if (tszDocumentPart == NULL)
  970. {
  971. AssertSz (0, TEXT("Couldn't alloc memory for doc-part display"));
  972. fInitDialogSuccess = FALSE;
  973. break;
  974. }
  975. // Put the tab in the new string, followed by the DocPart string.
  976. *tszDocumentPart = TEXT('\t');
  977. PbMemCopy(&tszDocumentPart[1],
  978. rglptstrDocParts[ ulSubDocPartIndex ],
  979. cbDocPart - sizeof(TCHAR)); // Subtract the size of the tab
  980. // Write the result to the list box, and free the temporary string.
  981. lError = SendDlgItemMessage (
  982. hDlg, IDD_CONTENTS_LISTBOX, LB_ADDSTRING, (WPARAM) 0,
  983. (LPARAM) tszDocumentPart);
  984. if (tszDocumentPart != NULL)
  985. {
  986. VFreeMemP (tszDocumentPart, cbDocPart);
  987. tszDocumentPart = NULL;
  988. cbDocPart = 0;
  989. }
  990. if (lError == LB_ERR || lError == LB_ERRSPACE)
  991. {
  992. AssertSz (0, TEXT("Could not write to list box"));
  993. fInitDialogSuccess = FALSE;
  994. break;
  995. }
  996. } // for (ulSubDocPartIndex = ulTotalDocPartIndex; ...
  997. // Add the cont for all the doc-parts that we just displayed
  998. // to the total.
  999. ulTotalDocPartIndex = ulSubDocPartIndex;
  1000. } // for (ulHeadingIndex = 0; ulHeadingIndex < cHeadings; ulHeadingIndex++)
  1001. fInitDialogSuccess = TRUE;
  1002. ExitCaseWM_INITDIALOG:
  1003. // Now that the headings and document-parts are in the dialog,
  1004. // we don't need to hold on to them any longer.
  1005. PropVariantClear (&GETDSINFO(lpDSIObj)->rgpropvar[PVDSI_HEADINGPAIR]);
  1006. PropVariantClear (&GETDSINFO(lpDSIObj)->rgpropvar[PVDSI_DOCPARTS]);
  1007. return fInitDialogSuccess;
  1008. } // end - case WM_INITDIALOG
  1009. case WM_CTLCOLORBTN :
  1010. case WM_CTLCOLORDLG :
  1011. case WM_CTLCOLORSTATIC :
  1012. if (hBrushPropDlg == NULL)
  1013. break;
  1014. DeleteObject(hBrushPropDlg);
  1015. if ((hBrushPropDlg = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) == NULL)
  1016. break;
  1017. SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNFACE));
  1018. SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT));
  1019. return (INT_PTR) hBrushPropDlg;
  1020. case WM_NOTIFY :
  1021. switch (((NMHDR FAR *) lParam)->code)
  1022. {
  1023. case PSN_SETACTIVE :
  1024. return TRUE;
  1025. case PSN_RESET:
  1026. case PSN_APPLY:
  1027. MESSAGE (TEXT("PSN_APPLY - Contents Page"));
  1028. return TRUE;
  1029. } // switch
  1030. break;
  1031. case WM_CONTEXTMENU:
  1032. WinHelp((HANDLE)wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR)rgIdhContents);
  1033. break;
  1034. case WM_HELP:
  1035. WinHelp(((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)rgIdhContents);
  1036. break;
  1037. } // switch
  1038. return FALSE;
  1039. } // FContentsDlgProc
  1040. #endif // _ABBREVIATED_DOCPROP_
  1041. int gOKButtonID; // need this to store the ID of the OK button, since it's not in the dlg template
  1042. ////////////////////////////////////////////////////////////////////////////////
  1043. //
  1044. // FCustomDlgProc
  1045. //
  1046. // Purpose:
  1047. // Custom tab control
  1048. //
  1049. ////////////////////////////////////////////////////////////////////////////////
  1050. INT_PTR CALLBACK FCustomDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1051. {
  1052. LPALLOBJS lpallobjs = (LPALLOBJS)GetWindowLongPtr(hDlg, DWLP_USER);
  1053. switch (message)
  1054. {
  1055. case WM_INITDIALOG:
  1056. {
  1057. PROPSHEETPAGE *ppspDlg = (PROPSHEETPAGE *) lParam;
  1058. int irg;
  1059. HICON hIcon, hInvIcon;
  1060. lpallobjs = (LPALLOBJS)ppspDlg->lParam;
  1061. PropPageInit(lpallobjs, itabCUSTOM);
  1062. SetWindowLongPtr(hDlg, DWLP_USER, ppspDlg->lParam);
  1063. gOKButtonID = LOWORD(SendMessage(hDlg, DM_GETDEFID, 0L, 0L));
  1064. AssertSz ((sizeof(NUM) == (sizeof(FILETIME))), TEXT("Ok, who changed base type sizes?"));
  1065. //
  1066. // Fill out the Name dropdown
  1067. //
  1068. for (irg = 0; irg < NUM_BUILTIN_CUSTOM_NAMES; ++irg)
  1069. {
  1070. if (!CchGetString( idsCustomName1+ irg,
  1071. lpallobjs->CDP_sz,
  1072. sizeof(lpallobjs->CDP_sz))
  1073. )
  1074. {
  1075. return(FALSE);
  1076. }
  1077. SendDlgItemMessage(hDlg, IDD_CUSTOM_NAME, CB_ADDSTRING, 0, (LPARAM)lpallobjs->CDP_sz);
  1078. }
  1079. //
  1080. // Fill out the type drop-down & select the text type
  1081. //
  1082. for (irg = 0; irg <= iszBOOL; irg++)
  1083. {
  1084. SendDlgItemMessage(hDlg, IDD_CUSTOM_TYPE, CB_ADDSTRING, 0, (LPARAM) rgszTypes[irg]);
  1085. }
  1086. ResetTypeControl (hDlg, IDD_CUSTOM_TYPE, &lpallobjs->CDP_iszType);
  1087. //
  1088. // Set the link checkbox to be off.
  1089. //
  1090. lpallobjs->CDP_fLink = FALSE;
  1091. SendDlgItemMessage( hDlg,
  1092. IDD_CUSTOM_LINK,
  1093. BM_SETCHECK,
  1094. (WPARAM) lpallobjs->CDP_fLink,
  1095. 0
  1096. );
  1097. #ifndef __CUSTOM_LINK_ENABLED__
  1098. ShowWindow( GetDlgItem( hDlg, IDD_CUSTOM_LINK ), SW_HIDE );
  1099. #endif __CUSTOM_LINK_ENABLED__
  1100. SendDlgItemMessage( hDlg,
  1101. IDD_CUSTOM_VALUETEXT,
  1102. WM_SETTEXT,
  1103. 0,
  1104. (LPARAM) rgszValue[iszVALUE]
  1105. );
  1106. //
  1107. // Hang on to the window handle of the value edit control & others
  1108. //
  1109. lpallobjs->CDP_hWndVal = GetDlgItem (hDlg, IDD_CUSTOM_VALUE);
  1110. lpallobjs->CDP_hWndName = GetDlgItem (hDlg, IDD_CUSTOM_NAME);
  1111. lpallobjs->CDP_hWndLinkVal = GetDlgItem (hDlg, IDD_CUSTOM_LINKVALUE);
  1112. lpallobjs->CDP_hWndValText = GetDlgItem (hDlg, IDD_CUSTOM_VALUETEXT);
  1113. lpallobjs->CDP_hWndBoolTrue = GetDlgItem (hDlg, IDD_CUSTOM_BOOLTRUE);
  1114. lpallobjs->CDP_hWndBoolFalse = GetDlgItem (hDlg, IDD_CUSTOM_BOOLFALSE);
  1115. lpallobjs->CDP_hWndGroup = GetDlgItem (hDlg, IDD_CUSTOM_GBOX);
  1116. lpallobjs->CDP_hWndAdd = GetDlgItem (hDlg, IDD_CUSTOM_ADD);
  1117. lpallobjs->CDP_hWndDelete = GetDlgItem (hDlg, IDD_CUSTOM_DELETE);
  1118. lpallobjs->CDP_hWndType = GetDlgItem (hDlg, IDD_CUSTOM_TYPE);
  1119. lpallobjs->CDP_hWndCustomLV = GetDlgItem(hDlg, IDD_CUSTOM_LISTVIEW);
  1120. InitListView (lpallobjs->CDP_hWndCustomLV, iszTYPE, rgszHeadings, TRUE);
  1121. //
  1122. // Initially disable the Add & Delete buttons
  1123. //
  1124. EnableWindow (lpallobjs->CDP_hWndAdd, FALSE);
  1125. EnableWindow (lpallobjs->CDP_hWndDelete, FALSE);
  1126. lpallobjs->CDP_fAdd = TRUE;
  1127. //
  1128. // Don't let the user enter too much text
  1129. // If you change this value, you must change the buffer
  1130. // size (szDate) in FConvertDate
  1131. //
  1132. SendMessage (lpallobjs->CDP_hWndVal, EM_LIMITTEXT, BUFMAX-1, 0);
  1133. SendMessage (lpallobjs->CDP_hWndName, EM_LIMITTEXT, BUFMAX-1, 0);
  1134. //
  1135. // Add the link icon to the image list
  1136. //
  1137. hIcon = LoadIcon (g_hmodThisDll, MAKEINTRESOURCE (IDD_LINK_ICON));
  1138. hInvIcon = LoadIcon (g_hmodThisDll, MAKEINTRESOURCE (IDD_INVLINK_ICON));
  1139. if (hIcon != NULL)
  1140. {
  1141. lpallobjs->CDP_hImlS = ListView_GetImageList( lpallobjs->CDP_hWndCustomLV, TRUE );
  1142. giLinkIcon = MsoImageList_ReplaceIcon( lpallobjs->CDP_hImlS, -1, hIcon );
  1143. Assert ((giLinkIcon != -1));
  1144. giInvLinkIcon = MsoImageList_ReplaceIcon (lpallobjs->CDP_hImlS, -1, hInvIcon);
  1145. Assert ((giInvLinkIcon != -1));
  1146. }
  1147. else
  1148. {
  1149. DebugSz (TEXT("Icon load failed"));
  1150. }
  1151. //
  1152. // Make a temporary copy of the custom data
  1153. //
  1154. FMakeTmpUDProps (lpallobjs->lpUDObj);
  1155. //
  1156. // Fill in the list view box with any data from the object
  1157. //
  1158. PopulateUDListView (lpallobjs->CDP_hWndCustomLV, lpallobjs->lpUDObj);
  1159. //
  1160. // See if the client supports links - turn off checkbox if they don't
  1161. //
  1162. lpallobjs->CDP_cLinks =
  1163. #ifdef __CUSTOM_LINK_ENABLED__
  1164. (lpallobjs->lpfnDwQueryLinkData != NULL) ?
  1165. (*lpallobjs->lpfnDwQueryLinkData) (QLD_CLINKS, 0, NULL, NULL) :
  1166. #endif __CUSTOM_LINK_ENABLED__
  1167. 0;
  1168. if (!lpallobjs->CDP_cLinks)
  1169. {
  1170. EnableWindow (GetDlgItem (hDlg, IDD_CUSTOM_LINK), FALSE);
  1171. EnableWindow (lpallobjs->CDP_hWndLinkVal, FALSE);
  1172. }
  1173. // lpallobjs->fPropDlgChanged = FALSE;
  1174. // fItemSel = FALSE;
  1175. return TRUE;
  1176. break;
  1177. }
  1178. case WM_CTLCOLORBTN :
  1179. case WM_CTLCOLORDLG :
  1180. case WM_CTLCOLORSTATIC :
  1181. if (hBrushPropDlg == NULL)
  1182. break;
  1183. DeleteObject(hBrushPropDlg);
  1184. if ((hBrushPropDlg = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) == NULL)
  1185. break;
  1186. SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNFACE));
  1187. SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT));
  1188. return (INT_PTR) hBrushPropDlg;
  1189. case WM_SYSCOLORCHANGE:
  1190. PostMessage(lpallobjs->CDP_hWndCustomLV, WM_SYSCOLORCHANGE, wParam, lParam);
  1191. return TRUE;
  1192. break;
  1193. //
  1194. // This message is posted when ever the user does something with the
  1195. // Name field. That allows the system to finish what they are doing
  1196. // and fill in the edit field if they have to. See bug 2820.
  1197. //
  1198. case WM_USER+0x1000:
  1199. if (!(lpallobjs->CDP_fLink && (lpallobjs->lpfnDwQueryLinkData == NULL)))
  1200. {
  1201. lpallobjs->CDP_iszType = (int)SendMessage (lpallobjs->CDP_hWndType, CB_GETCURSEL, 0, 0);
  1202. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1203. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  1204. {
  1205. LPUDPROP lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, (LPTSTR)PSTR (glpstzName));
  1206. if (lpudp != NULL)
  1207. {
  1208. if (lpallobjs->CDP_fAdd)
  1209. {
  1210. SendMessage (lpallobjs->CDP_hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  1211. lpallobjs->CDP_fAdd = FALSE;
  1212. }
  1213. }
  1214. }
  1215. EnableWindow(lpallobjs->CDP_hWndDelete, FALSE); // If the user touches the Name field, disable Delete button
  1216. // Are we showing an invalid link?
  1217. if (lpallobjs->CDP_fLink && !IsWindowEnabled(GetDlgItem(hDlg,IDD_CUSTOM_LINK)))
  1218. {
  1219. // Turn off the link checkbox
  1220. lpallobjs->CDP_fLink = FALSE;
  1221. SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) lpallobjs->CDP_fLink, 0);
  1222. if (lpallobjs->CDP_cLinks) // Could be that the app is allowing links
  1223. EnableWindow (GetDlgItem (hDlg, IDD_CUSTOM_LINK), TRUE);
  1224. // Clear the value window
  1225. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  1226. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  1227. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, FALSE, FALSE);
  1228. }
  1229. }
  1230. return(TRUE);
  1231. break;
  1232. case WM_COMMAND :
  1233. switch (HIWORD (wParam))
  1234. {
  1235. case BN_CLICKED :
  1236. switch (LOWORD (wParam))
  1237. {
  1238. case IDD_CUSTOM_ADD :
  1239. if (FGetCustomPropFromDlg(lpallobjs, hDlg))
  1240. {
  1241. PropSheet_Changed(GetParent(hDlg), hDlg);
  1242. }
  1243. return(FALSE); // return 0 'cuz we process the message
  1244. break;
  1245. case IDD_CUSTOM_DELETE :
  1246. // Assert (fItemSel);
  1247. // fItemSel = FALSE; // We're about to delete it!
  1248. DeleteItem (lpallobjs->lpUDObj, lpallobjs->CDP_hWndCustomLV, lpallobjs->CDP_iItem, lpallobjs->CDP_sz);
  1249. // Turn off the link checkbox if it was on.
  1250. lpallobjs->CDP_fLink = FALSE;
  1251. SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) lpallobjs->CDP_fLink, 0);
  1252. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  1253. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  1254. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, FALSE, FALSE);
  1255. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1256. ResetTypeControl (hDlg, IDD_CUSTOM_TYPE, &lpallobjs->CDP_iszType);
  1257. SendMessage(lpallobjs->CDP_hWndName, CB_SETEDITSEL, 0, MAKELPARAM(0,-1)); // Select entire string
  1258. SendMessage(lpallobjs->CDP_hWndName, WM_CLEAR, 0, 0);
  1259. SetFocus(lpallobjs->CDP_hWndName);
  1260. // lpallobjs->fPropDlgChanged = TRUE;
  1261. PropSheet_Changed(GetParent(hDlg), hDlg);
  1262. return(FALSE); // return 0 'cuz we process the message
  1263. break;
  1264. case IDD_CUSTOM_LINK :
  1265. {
  1266. BOOL fMod = FALSE;
  1267. // Should never get a message from a disabled control
  1268. Assert (lpallobjs->CDP_cLinks);
  1269. lpallobjs->CDP_fLink = !lpallobjs->CDP_fLink;
  1270. SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) lpallobjs->CDP_fLink, 0);
  1271. // If the link box is checked, the value edit needs to change
  1272. // to a combobox filled with link data
  1273. if (lpallobjs->CDP_fLink)
  1274. {
  1275. Assert ((lpallobjs->lpfnDwQueryLinkData != NULL));
  1276. FCreateListOfLinks (lpallobjs->CDP_cLinks, lpallobjs->lpfnDwQueryLinkData, lpallobjs->CDP_hWndLinkVal);
  1277. SendMessage (lpallobjs->CDP_hWndLinkVal, CB_SETCURSEL, 0, 0);
  1278. FSetTypeControl ((*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKTYPE, 0, NULL, NULL), lpallobjs->CDP_hWndType);
  1279. }
  1280. else
  1281. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  1282. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  1283. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, lpallobjs->CDP_fLink, FALSE);
  1284. // HACK, we don't want FSetupAddButton to change the text of the add
  1285. // button
  1286. if (!lpallobjs->CDP_fAdd)
  1287. fMod = lpallobjs->CDP_fAdd = TRUE;
  1288. // Set up the "Add" button correctly
  1289. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1290. if (fMod)
  1291. lpallobjs->CDP_fAdd = FALSE;
  1292. return(FALSE); // return 0 'cuz we process the message
  1293. break;
  1294. }
  1295. case IDD_CUSTOM_BOOLTRUE:
  1296. case IDD_CUSTOM_BOOLFALSE:
  1297. {
  1298. BOOL fMod = FALSE;
  1299. lpallobjs->CDP_iszType = (int)SendMessage (lpallobjs->CDP_hWndType, CB_GETCURSEL, 0, 0);
  1300. // HACK, we don't want FSetupAddButton to change the text of the add
  1301. // button
  1302. if (!lpallobjs->CDP_fAdd)
  1303. fMod = lpallobjs->CDP_fAdd = TRUE;
  1304. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1305. if (fMod)
  1306. lpallobjs->CDP_fAdd = FALSE;
  1307. return(FALSE);
  1308. }
  1309. default:
  1310. return(TRUE);
  1311. }
  1312. case CBN_CLOSEUP:
  1313. // Hack!!
  1314. // We need to post a message to ourselves to check if the user's
  1315. // actions entered text in the edit field.
  1316. PostMessage(hDlg, WM_USER+0x1000, 0L, 0L);
  1317. return(FALSE);
  1318. case CBN_SELCHANGE :
  1319. switch (LOWORD (wParam))
  1320. {
  1321. case IDD_CUSTOM_NAME :
  1322. // Hack!!
  1323. // We need to post a message to ourselves to check if the user's
  1324. // actions entered text in the edit field.
  1325. PostMessage(hDlg, WM_USER+0x1000, 0L, 0L);
  1326. return(FALSE); // return 0 'cuz we process the message
  1327. break;
  1328. case IDD_CUSTOM_TYPE :
  1329. {
  1330. BOOL fMod = FALSE;
  1331. // If the user picks the Boolean type from the combo box,
  1332. // we must replace the edit control for the value
  1333. // with radio buttons. If the Link checkbox is set,
  1334. // the type depends on the link value, not user selection
  1335. lpallobjs->CDP_iszType = (int)SendMessage ((HWND) lParam, CB_GETCURSEL, 0, 0);
  1336. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  1337. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType, lpallobjs->CDP_hWndValText, lpallobjs->CDP_fLink, (lpallobjs->CDP_iszType == iszBOOL));
  1338. // HACK: FSwapControls() resets the type selection to be
  1339. // the first one (since all other clients need that to
  1340. // happen). In this case, the user has selected a new
  1341. // type, so we need to force it manually to what they picked.
  1342. SendMessage (lpallobjs->CDP_hWndType, CB_SETCURSEL, lpallobjs->CDP_iszType, 0);
  1343. // HACK: FSetupAddButton will change the Add button to
  1344. // say "Add" if lpallobjs->CDP_fAdd is FALSE. Since we just changed
  1345. // the button to "Modify", fake it out to not change
  1346. // the Add button by flipping lpallobjs->CDP_fAdd, then flipping it back.
  1347. if (!lpallobjs->CDP_fAdd)
  1348. fMod = lpallobjs->CDP_fAdd = TRUE;
  1349. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1350. if (fMod)
  1351. lpallobjs->CDP_fAdd = FALSE;
  1352. return(FALSE); // return 0 'cuz we process the message
  1353. }
  1354. case IDD_CUSTOM_LINKVALUE :
  1355. // If the user has the "Link" box checked and starts picking
  1356. // link values, make sure that the "Type" combobox is updated
  1357. // to the type of the static value of the link.
  1358. {
  1359. DWORD irg;
  1360. AssertSz (lpallobjs->CDP_fLink, TEXT("Link box must be checked in order for this dialog to be visible!"));
  1361. // Get the link value from the combobox, and store
  1362. // the link name and static value.
  1363. irg = (int)SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETCURSEL, 0, 0);
  1364. Assert ((lpallobjs->lpfnDwQueryLinkData != NULL));
  1365. // REVIEW: If apps really need the name, we can get it here....
  1366. FSetTypeControl ((*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKTYPE, irg, NULL, NULL), lpallobjs->CDP_hWndType);
  1367. return(FALSE); // return 0 'cuz we process the message
  1368. }
  1369. default:
  1370. return TRUE; // we didn't process message
  1371. }
  1372. case CBN_EDITCHANGE: // The user typed their own
  1373. switch (LOWORD (wParam))
  1374. {
  1375. case IDD_CUSTOM_NAME :
  1376. // Hack!!
  1377. // We need to post a message to ourselves to check if the user's
  1378. // actions entered text in the edit field.
  1379. PostMessage(hDlg, WM_USER+0x1000, 0L, 0L);
  1380. return(FALSE); // return 0 'cuz we process the message
  1381. break;
  1382. default:
  1383. return(TRUE);
  1384. break;
  1385. }
  1386. case EN_UPDATE :
  1387. switch (LOWORD (wParam))
  1388. {
  1389. case IDD_CUSTOM_VALUE :
  1390. {
  1391. BOOL fMod = FALSE;
  1392. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  1393. {
  1394. LPUDPROP lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, (LPTSTR)PSTR (glpstzName));
  1395. if (lpudp != NULL)
  1396. {
  1397. if (lpallobjs->CDP_fAdd)
  1398. {
  1399. SendMessage (lpallobjs->CDP_hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  1400. lpallobjs->CDP_fAdd = FALSE;
  1401. }
  1402. }
  1403. // HACK: FSetupAddButton will change the Add button to
  1404. // say "Add" if lpallobjs->CDP_fAdd is FALSE. Since we just changed
  1405. // the button to "Modify", fake it out to not change
  1406. // the Add button by flipping lpallobjs->CDP_fAdd, then flipping it back.
  1407. if (!lpallobjs->CDP_fAdd)
  1408. fMod = lpallobjs->CDP_fAdd = TRUE;
  1409. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1410. if (fMod)
  1411. lpallobjs->CDP_fAdd = FALSE;
  1412. }
  1413. return(FALSE); // return 0 'cuz we process the message
  1414. }
  1415. default:
  1416. return TRUE; // we didn't process message
  1417. }
  1418. case EN_KILLFOCUS :
  1419. switch (LOWORD (wParam))
  1420. {
  1421. // If the user finishes entering text in the Name edit control,
  1422. // be really cool and check to see if the name they entered
  1423. // is a property that is already defined. If it is,
  1424. // change the Add button to Modify.
  1425. case IDD_CUSTOM_NAME :
  1426. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  1427. {
  1428. LPUDPROP lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, (LPTSTR)PSTR (glpstzName));
  1429. if (lpudp != NULL)
  1430. {
  1431. if (lpallobjs->CDP_fAdd)
  1432. {
  1433. SendMessage (lpallobjs->CDP_hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  1434. lpallobjs->CDP_fAdd = FALSE;
  1435. }
  1436. }
  1437. }
  1438. return FALSE;
  1439. default:
  1440. return TRUE;
  1441. }
  1442. default:
  1443. return TRUE;
  1444. } // switch
  1445. case WM_DESTROY:
  1446. MsoImageList_Destroy(lpallobjs->CDP_hImlS);
  1447. return FALSE;
  1448. case WM_NOTIFY :
  1449. switch (((NMHDR FAR *) lParam)->code)
  1450. {
  1451. case LVN_ITEMCHANGING :
  1452. // If an item is gaining focus, put it in the edit controls at
  1453. // the top of the dialog.
  1454. if (((NM_LISTVIEW FAR *) lParam)->uNewState & LVIS_SELECTED)
  1455. {
  1456. Assert ((((NM_LISTVIEW FAR *) lParam) != NULL));
  1457. lpallobjs->CDP_iItem = ((NM_LISTVIEW FAR *) lParam)->iItem;
  1458. ListView_GetItemText (lpallobjs->CDP_hWndCustomLV, lpallobjs->CDP_iItem, 0, lpallobjs->CDP_sz, BUFMAX);
  1459. PopulateControls (lpallobjs->lpUDObj, lpallobjs->CDP_sz, lpallobjs->CDP_cLinks, lpallobjs->lpfnDwQueryLinkData, hDlg,
  1460. GetDlgItem (hDlg, IDD_CUSTOM_NAME), lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndValText,
  1461. GetDlgItem (hDlg, IDD_CUSTOM_LINK), lpallobjs->CDP_hWndLinkVal, lpallobjs->CDP_hWndType,
  1462. lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse, lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndDelete, &lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd);
  1463. return FALSE;
  1464. }
  1465. return TRUE;
  1466. break;
  1467. #ifdef OFFICE_96
  1468. case LVN_COLUMNCLICK:
  1469. // We only sort the name column
  1470. if (((LPARAM)((NM_LISTVIEW *)lParam)->iSubItem == 0))
  1471. ListView_SortItems(((NM_LISTVIEW *) lParam)->hdr.lpallobjs->CDP_hWndFrom, ListViewCompareFunc,0);
  1472. return TRUE;
  1473. #endif
  1474. case PSN_APPLY :
  1475. if (IsWindowEnabled(lpallobjs->CDP_hWndAdd))
  1476. FGetCustomPropFromDlg(lpallobjs, hDlg);
  1477. // Swap the temp copy to be the real copy.
  1478. FDeleteTmpUDProps (lpallobjs->lpUDObj);
  1479. MESSAGE (TEXT("PSN_APPLY - Custom Page"));
  1480. if (FUserDefShouldSave (lpallobjs->lpUDObj)
  1481. || lpallobjs->fPropDlgChanged )
  1482. {
  1483. if( !ApplyChangesBackToFile(hDlg, (BOOL)((PSHNOTIFY*)lParam)->lParam, lpallobjs, itabCUSTOM) )
  1484. {
  1485. PostMessage( GetParent(hDlg), PSM_SETCURSEL, (WPARAM)-1, (LPARAM)lpallobjs->lpUDObj->m_hPage );
  1486. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE );
  1487. return TRUE;
  1488. }
  1489. }
  1490. return PSNRET_NOERROR;
  1491. case PSN_RESET :
  1492. if (lpallobjs->fPropDlgChanged && !lpallobjs->fPropDlgPrompted)
  1493. {
  1494. if (ISavePropDlgChanges(lpallobjs, hDlg, ((NMHDR FAR *)lParam)->hwndFrom) != IDNO)
  1495. {
  1496. return(TRUE);
  1497. }
  1498. }
  1499. // User cancelled the changes, so just delete the tmp stuff.
  1500. FSwapTmpUDProps (lpallobjs->lpUDObj);
  1501. FDeleteTmpUDProps (lpallobjs->lpUDObj);
  1502. return TRUE;
  1503. case PSN_SETACTIVE :
  1504. return TRUE;
  1505. default:
  1506. break;
  1507. } // switch
  1508. break;
  1509. case WM_CONTEXTMENU:
  1510. WinHelp((HANDLE)wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR)rgIdhCustom);
  1511. break;
  1512. case WM_HELP:
  1513. WinHelp(((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)rgIdhCustom);
  1514. break;
  1515. } // switch
  1516. return FALSE;
  1517. } // FCustomDlgProc
  1518. //
  1519. // FGetCustomPropFromDlg
  1520. //
  1521. // Purpose: To get a custom property from the dialog.
  1522. // I.e. the user hit Add/Modify.
  1523. //
  1524. BOOL FGetCustomPropFromDlg(LPALLOBJS lpallobjs, HWND hDlg)
  1525. {
  1526. UDTYPES udtype;
  1527. NUM dbl;
  1528. LPVOID lpv;
  1529. int iItemT;
  1530. LPTSTR lpstzName;
  1531. LPVOID lpvSaveAsDword;
  1532. DWORD cch;
  1533. BOOL f;
  1534. lpstzName = NULL;
  1535. cch = 0;
  1536. if (FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_NAME, &glpstzName))
  1537. {
  1538. LPUDPROP lpudp;
  1539. #ifdef __CUSTOM_LINK_ENABLED__
  1540. lpallobjs->CDP_fLink = SendDlgItemMessage(hDlg, IDD_CUSTOM_LINK, BM_GETCHECK, 0, 0);
  1541. #else
  1542. lpallobjs->CDP_fLink = FALSE; // just to be sure.
  1543. #endif __CUSTOM_LINK_ENABLED__
  1544. Assert(lpallobjs->CDP_fLink == TRUE || lpallobjs->CDP_fLink == FALSE);
  1545. // HACK: If the user enters a name that is already
  1546. // a property name, the default action of the object
  1547. // is to replace the data, treating it as an update.
  1548. // This will cause there to be 2 names in the listview
  1549. // though unless we just update the original one. So, first
  1550. // see if the new name is in the list already, and if
  1551. // it is, find it in the listview and set up to update it.
  1552. lpudp = LpudpropFindMatchingName (lpallobjs->lpUDObj, (LPTSTR)PSTR (glpstzName));
  1553. if (lpudp != NULL)
  1554. {
  1555. LV_FINDINFO lvfi;
  1556. lvfi.flags = LVFI_STRING;
  1557. lvfi.psz = (LPTSTR) PSTR (glpstzName);
  1558. iItemT = ListView_FindItem (lpallobjs->CDP_hWndCustomLV, -1, &lvfi);
  1559. // If the property is being modified and the link
  1560. // box is not checked, we need to remove the link
  1561. // data and the IMoniker from the object.
  1562. // if (!lpallobjs->CDP_fLink)
  1563. // {
  1564. // FUserDefAddProp (lpallobjs->lpUDObj, PSTR (glpstzName), NULL,
  1565. // wUDlpsz, TRUE, FALSE, FALSE);
  1566. // FUserDefAddProp (lpallobjs->lpUDObj, PSTR (glpstzName), NULL,
  1567. // wUDlpsz, FALSE, FALSE, TRUE);
  1568. // }
  1569. }
  1570. else
  1571. iItemT = -1;
  1572. // Let's get the type, since this might be a MODIFY case
  1573. lpallobjs->CDP_iszType = (int)SendMessage(lpallobjs->CDP_hWndType, CB_GETCURSEL,0, 0);
  1574. // If the user has checked the link box, then the value
  1575. // must come from the client.
  1576. if (lpallobjs->CDP_fLink)
  1577. {
  1578. DWORD irg;
  1579. // Get the link name from the combobox, and store
  1580. // the link name and static value.
  1581. irg = (int)SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETCURSEL, 0, 0);
  1582. Assert ((lpallobjs->lpfnDwQueryLinkData != NULL));
  1583. Assert (((irg < lpallobjs->CDP_cLinks) && ((int) irg >= 0)));
  1584. cch = (DWORD)SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETLBTEXTLEN, irg, 0)+1; // Include the null-terminator
  1585. if (!FAllocString (&lpstzName, cch))
  1586. return(FALSE);
  1587. SendMessage (lpallobjs->CDP_hWndLinkVal, CB_GETLBTEXT, irg, (LPARAM) PSTR (lpstzName));
  1588. // Set up the static type and value for display
  1589. // in the listbox
  1590. udtype = (UDTYPES) (*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKTYPE, irg, NULL, (LPTSTR)PSTR (lpstzName));
  1591. (*lpallobjs->lpfnDwQueryLinkData) (QLD_LINKVAL, irg, &lpv, (LPTSTR)PSTR (lpstzName));
  1592. //
  1593. // HACK alert
  1594. //
  1595. // We want lpv to point to the value, not to be overloaded in the case of a dword or bool.
  1596. //
  1597. if ((udtype == wUDdw) || (udtype == wUDbool))
  1598. {
  1599. lpvSaveAsDword = lpv; // Really a DWORD
  1600. lpv = &lpvSaveAsDword;
  1601. }
  1602. // Add the link name itself to the object
  1603. // FUserDefAddProp (lpallobjs->lpUDObj, PSTR (glpstzName), PSTR (lpstzName),
  1604. // wUDlpsz, TRUE, FALSE, FALSE);
  1605. } // if (lpallobjs->CDP_fLink)
  1606. else
  1607. {
  1608. if (lpallobjs->CDP_iszType != iszBOOL)
  1609. {
  1610. if (!FAllocAndGetValLpstz (hDlg, IDD_CUSTOM_VALUE, &glpstzValue))
  1611. return(FALSE);
  1612. }
  1613. // Convert the type in the combobox to a UDTYPES
  1614. switch (lpallobjs->CDP_iszType)
  1615. {
  1616. case iszTEXT :
  1617. udtype = wUDlpsz;
  1618. (LPTSTR) lpv = (LPTSTR)PSTR (glpstzValue);
  1619. break;
  1620. case iszNUM :
  1621. udtype = UdtypesGetNumberType (glpstzValue, &dbl,
  1622. ((LPUDINFO)lpallobjs->lpUDObj->m_lpData)->lpfnFSzToNum);
  1623. switch (udtype)
  1624. {
  1625. case wUDdw :
  1626. lpv = (DWORD *) &dbl;
  1627. break;
  1628. case wUDfloat :
  1629. (NUM *) lpv = &dbl;
  1630. break;
  1631. default :
  1632. (LPTSTR) lpv = (LPTSTR)PSTR (glpstzValue);
  1633. // If the user doesn't want to convert the value to text, they can press "Cancel" and try again.
  1634. if (FDisplayConversionWarning (hDlg))
  1635. {
  1636. SetFocus(lpallobjs->CDP_hWndType);
  1637. return(FALSE);
  1638. }
  1639. udtype = wUDlpsz;
  1640. } // switch (udtype)
  1641. break;
  1642. case iszDATE :
  1643. if (FConvertDate (glpstzValue, (LPFILETIME) &dbl))
  1644. {
  1645. udtype = wUDdate;
  1646. (NUM *) lpv = &dbl;
  1647. }
  1648. else
  1649. {
  1650. udtype = wUDlpsz;
  1651. (LPTSTR) lpv = (LPTSTR)PSTR (glpstzValue);
  1652. // If the user doesn't want to convert the value to text, they can press "Cancel" and try again.
  1653. if (FDisplayConversionWarning (hDlg))
  1654. {
  1655. SetFocus(lpallobjs->CDP_hWndType);
  1656. return(FALSE);
  1657. }
  1658. }
  1659. break;
  1660. case iszBOOL :
  1661. {
  1662. udtype = wUDbool;
  1663. f = (BOOL)(SendMessage (lpallobjs->CDP_hWndBoolTrue, BM_GETSTATE, 0, 0) & BST_CHECKED);
  1664. lpv = &f;
  1665. break;
  1666. }
  1667. default :
  1668. AssertSz (0,TEXT("IDD_CUSTOM_TYPE combobox is whacked!"));
  1669. udtype = wUDinvalid;
  1670. } // switch (lpallobjs->CDP_iszType)
  1671. } // if (lpallobjs->CDP_fLink) ... else
  1672. // If we got valid input, add the property to the object
  1673. // and listbox.
  1674. if (udtype != wUDinvalid)
  1675. {
  1676. // The PropVariant created when we add this property.
  1677. LPPROPVARIANT lppropvar = NULL;
  1678. // The link data (link name itself) would have
  1679. // been stored above if the property was a link.
  1680. // This stores the static value that will eventually
  1681. // appear in the list view.
  1682. lppropvar = LppropvarUserDefAddProp (lpallobjs->lpUDObj, glpstzName, lpv, udtype,
  1683. (lpstzName != NULL) ? lpstzName : NULL,
  1684. (lpstzName != NULL) ? TRUE : FALSE, FALSE);
  1685. // HACK alert
  1686. //
  1687. // Here we want lpv be overloaded in the case of a dword or bool, since
  1688. // AddUDPropToListView calls WUdtypeToSz which assumes lpv is overloaded.
  1689. //
  1690. if ((udtype == wUDdw) || (udtype == wUDbool))
  1691. {
  1692. lpv = *(LPVOID *)lpv;
  1693. }
  1694. if (lppropvar)
  1695. AddUDPropToListView (lpallobjs->lpUDObj, lpallobjs->CDP_hWndCustomLV, (LPTSTR)PSTR (glpstzName), lppropvar, iItemT, lpallobjs->CDP_fLink, fTrue, fTrue);
  1696. // For links, dealloc the buffer.
  1697. if (lpallobjs->CDP_fLink)
  1698. DeallocValue (&lpv, udtype);
  1699. // Clear out the edit fields and disable the Add button again
  1700. SetCustomDlgDefButton(hDlg, gOKButtonID);
  1701. EnableWindow (lpallobjs->CDP_hWndAdd, FALSE);
  1702. SendMessage(lpallobjs->CDP_hWndName, CB_SETEDITSEL, 0, MAKELPARAM(0,-1)); // Select entire string
  1703. SendMessage(lpallobjs->CDP_hWndName, WM_CLEAR, 0, 0);
  1704. EnableWindow (lpallobjs->CDP_hWndDelete, FALSE);
  1705. // See bug 213
  1706. // if (fLink)
  1707. // {
  1708. // fLink = !fLink;
  1709. // SendDlgItemMessage (hDlg, IDD_CUSTOM_LINK, BM_SETCHECK, (WPARAM) fLink, 0);
  1710. // }
  1711. FSwapControls (lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndLinkVal,
  1712. lpallobjs->CDP_hWndBoolTrue, lpallobjs->CDP_hWndBoolFalse,
  1713. lpallobjs->CDP_hWndGroup, lpallobjs->CDP_hWndType,
  1714. lpallobjs->CDP_hWndValText, lpallobjs->CDP_fLink, lpallobjs->CDP_iszType == iszBOOL);
  1715. FSetupAddButton (lpallobjs->CDP_iszType, lpallobjs->CDP_fLink, &lpallobjs->CDP_fAdd, lpallobjs->CDP_hWndAdd, lpallobjs->CDP_hWndVal, lpallobjs->CDP_hWndName, hDlg);
  1716. // wUDbool doesn't use the edit control....
  1717. if (lpallobjs->CDP_iszType != iszBOOL)
  1718. ClearEditControl (lpallobjs->CDP_hWndVal, 0);
  1719. } // if (udtype != wUDinvalid)
  1720. SendDlgItemMessage(hDlg, IDD_CUSTOM_TYPE, CB_SETCURSEL, lpallobjs->CDP_iszType,0);
  1721. SetFocus(lpallobjs->CDP_hWndName);
  1722. // lpallobjs->fPropDlgChanged = TRUE;
  1723. if (lpstzName != NULL)
  1724. VFreeMemP(lpstzName, CBTSTR (lpstzName));
  1725. return(TRUE);
  1726. }
  1727. return(FALSE);
  1728. }
  1729. /////////////////////////////////////////////////////////////////////////
  1730. //
  1731. // SetCustomDlgDefButton
  1732. //
  1733. // Set the new default button
  1734. //
  1735. /////////////////////////////////////////////////////////////////////////
  1736. VOID SetCustomDlgDefButton(HWND hDlg, int IDNew)
  1737. {
  1738. int IDOld;
  1739. if ((IDOld = LOWORD(SendMessage(hDlg, DM_GETDEFID, 0L, 0L))) != IDNew)
  1740. {
  1741. // Set the new default push button's control ID.
  1742. SendMessage(hDlg, DM_SETDEFID, IDNew, 0L);
  1743. // Set the new style.
  1744. SendDlgItemMessage(hDlg, IDNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE,0));
  1745. SendDlgItemMessage(hDlg, IDOld, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE,0));
  1746. }
  1747. }
  1748. #ifdef OFFICE_96
  1749. ////////////////////////////////////////////////////////////////////////////////
  1750. //
  1751. // ListViewCompareFunc
  1752. //
  1753. // Purpose:
  1754. // Compares two items in a listview
  1755. // We only sort the name column.
  1756. //
  1757. // Returns
  1758. // A negative value if item 1 should come before item 2
  1759. // A positive value if item 1 should come after item 2
  1760. // Zero if the two items are equivalent
  1761. //
  1762. ////////////////////////////////////////////////////////////////////////////////
  1763. int CALLBACK ListViewCompareFunc
  1764. (
  1765. LPARAM lParam1, // lParam of the LV_ITEM struct (property name)
  1766. LPARAM lParam2, // lParam of the LV_ITEM struct (property name)
  1767. LPARAM lParamSort) // Index of column to sore
  1768. {
  1769. return(lstrcmp((LPTSTR)lParam1, (LPTSTR)lParam2));
  1770. }
  1771. #endif
  1772. ////////////////////////////////////////////////////////////////////////////////
  1773. //
  1774. // PrintTimeInDlg
  1775. //
  1776. // Purpose:
  1777. // Prints the locale-specific time representation in control in the dialog.
  1778. //
  1779. ////////////////////////////////////////////////////////////////////////////////
  1780. #ifndef _ABBREVIATED_DOCPROP_
  1781. void PASCAL
  1782. PrintTimeInDlg (
  1783. HWND hDlg, // Dialog handle
  1784. DWORD dwId, // Control id
  1785. LPFILETIME lpft) // The time
  1786. {
  1787. SYSTEMTIME st;
  1788. TCHAR szBuf[80], szTmp[64];
  1789. const TCHAR *c_szSpace = TEXT(" ");
  1790. if ((lpft != NULL) && (lpft->dwLowDateTime != 0) && (lpft->dwHighDateTime != 0))
  1791. {
  1792. FILETIME ft;
  1793. FileTimeToLocalFileTime(lpft, &ft); // get in local time
  1794. FileTimeToSystemTime(&ft, &st);
  1795. GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szBuf,ARRAYSIZE(szBuf));
  1796. // don't bother with the time if it is NULL
  1797. if (st.wHour || st.wMinute || st.wSecond)
  1798. {
  1799. lstrcat(szBuf, c_szSpace);
  1800. GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, szTmp, ARRAYSIZE(szTmp));
  1801. lstrcat(szBuf, szTmp);
  1802. }
  1803. SetDlgItemText(hDlg, dwId, szBuf);
  1804. }
  1805. } // PrintTimeInDlg
  1806. #endif //_ABBREVIATED_DOCPROP_
  1807. ////////////////////////////////////////////////////////////////////////////////
  1808. //
  1809. // PrintEditTimeInDlg
  1810. //
  1811. // Purpose:
  1812. // Prints the total edit time in the dialog.
  1813. //
  1814. ////////////////////////////////////////////////////////////////////////////////
  1815. #ifndef _ABBREVIATED_DOCPROP_
  1816. void PASCAL PrintEditTimeInDlg (
  1817. HWND hDlg, // Dialog handle
  1818. LPFILETIME lpft) // The time
  1819. {
  1820. TCHAR sz[100];
  1821. // Remember that the 64 bit number in lpft is units of 100ns
  1822. VFtToSz(lpft, sz, ARRAYSIZE(sz), TRUE);
  1823. SetDlgItemText(hDlg, IDD_STATISTICS_TOTALEDIT, sz);
  1824. } // PrintEditTimeInDlg
  1825. #endif _ABBREVIATED_DOCPROP_
  1826. ////////////////////////////////////////////////////////////////////////////////
  1827. //
  1828. // SetEditValLpsz
  1829. //
  1830. // Purpose:
  1831. // If this PropVariant holds a LPTSTR, it is written
  1832. // to the caller-specified Edit Control. If it is not
  1833. // an LPTSTR, it is not treated as an error (it might
  1834. // simply be a VT_EMPTY ... a non-existent property).
  1835. //
  1836. ////////////////////////////////////////////////////////////////////////////////
  1837. #ifndef _ABBREVIATED_DOCPROP_
  1838. void PASCAL SetEditValLpsz(
  1839. LPPROPVARIANT lppropvar, // PropVariant
  1840. HWND hDlg, // Dialog handle
  1841. DWORD dwID ) // Edit control ID
  1842. {
  1843. if (lppropvar->vt == VT_LPTSTR)
  1844. {
  1845. SendDlgItemMessage
  1846. (hDlg, dwID, WM_SETTEXT, 0, (LPARAM) lppropvar->pszVal);
  1847. PropVariantClear( lppropvar );
  1848. }
  1849. }
  1850. #endif
  1851. ////////////////////////////////////////////////////////////////////////////////
  1852. //
  1853. // GetEditValLpsz
  1854. //
  1855. // Purpose:
  1856. // Reads the string from the caller-specified edit
  1857. // control, and loads it into a PropVariant.
  1858. // If the Edit control says that it has not been
  1859. // modified, then we don't read anything, and
  1860. // return FALSE.
  1861. //
  1862. ////////////////////////////////////////////////////////////////////////////////
  1863. #ifndef _ABBREVIATED_DOCPROP_
  1864. BOOL PASCAL GetEditValLpsz(
  1865. LPPROPVARIANT lppropvar, // Sum info PropVariants
  1866. HWND hDlg, // Dialog handle
  1867. DWORD dwId) // Edit control id
  1868. {
  1869. BOOL fChanged = FALSE;
  1870. DWORD cb, cch;
  1871. // Did the data change?
  1872. if ((BOOL) SendDlgItemMessage (hDlg, dwId, EM_GETMODIFY, 0, 0))
  1873. {
  1874. LPTSTR tszNew;
  1875. // Yes, it changed. Ask the Edit control how big the
  1876. // string is.
  1877. cch = (DWORD)SendDlgItemMessage (hDlg, dwId, WM_GETTEXTLENGTH, 0, 0);
  1878. cb = ( cch + 1 ) * sizeof (TCHAR); // Includes the NULL.
  1879. // Allocate a new string for this PropVariant, and set
  1880. // the VT.
  1881. if ( !(tszNew = CoTaskMemAlloc (cb)))
  1882. {
  1883. goto Exit;
  1884. }
  1885. PropVariantClear( lppropvar );
  1886. lppropvar->vt = VT_LPTSTR;
  1887. (LPTSTR) lppropvar->pszVal = tszNew;
  1888. // Get the string from the edit control into the buffer
  1889. // (the size of the buffer in characters is cch+1, including
  1890. // the NULL).
  1891. SendDlgItemMessage (hDlg, dwId, WM_GETTEXT, (WPARAM) cch+1,
  1892. (LPARAM) lppropvar->pszVal);
  1893. fChanged = TRUE;
  1894. } // if ((BOOL) SendDlgItemMessage (hDlg, dwId, EM_GETMODIFY, 0, 0))
  1895. // ----
  1896. // Exit
  1897. // ----
  1898. Exit:
  1899. return (fChanged);
  1900. } // GetEditValLpsz
  1901. #endif //_ABBREVIATED_DOCPROP_
  1902. ////////////////////////////////////////////////////////////////////////////////
  1903. //
  1904. // FAllocAndGetValLpstz
  1905. //
  1906. // Purpose:
  1907. // Gets the value from the edit box into the local buffer.
  1908. //
  1909. ////////////////////////////////////////////////////////////////////////////////
  1910. BOOL PASCAL FAllocAndGetValLpstz (
  1911. HWND hDlg, // Handle of dialog control is in
  1912. DWORD dwId, // Id of control
  1913. LPTSTR *lplpstz) // Buffer
  1914. {
  1915. DWORD cch;
  1916. cch = (DWORD)SendDlgItemMessage (hDlg, dwId, WM_GETTEXTLENGTH, 0, 0);
  1917. cch++;
  1918. if (FAllocString (lplpstz, cch))
  1919. {
  1920. // Get the entry. Remember to null-terminate it.
  1921. cch = (DWORD)SendDlgItemMessage (hDlg, dwId, WM_GETTEXT, cch, (LPARAM) PSTR (*lplpstz));
  1922. ((LPTSTR)(PSTR (*lplpstz)))[cch] = TEXT('\0');
  1923. return TRUE;
  1924. }
  1925. return FALSE;
  1926. } // FAllocAndGetValLpstz
  1927. ////////////////////////////////////////////////////////////////////////////////
  1928. //
  1929. // FAllocString
  1930. //
  1931. // Purpose:
  1932. // Allocates a string big enough to to hold cch char's. Only allocates if needed.
  1933. //
  1934. ////////////////////////////////////////////////////////////////////////////////
  1935. BOOL PASCAL FAllocString (
  1936. LPTSTR *lplpstz,
  1937. DWORD cch)
  1938. {
  1939. // Figure out how many bytes we need to allocate.
  1940. DWORD cbNew = (cch * sizeof(TCHAR));
  1941. // And how many bytes we need to free.
  1942. DWORD cbOld = *lplpstz == NULL
  1943. ? 0
  1944. : (CchTszLen (*lplpstz) + 1) * sizeof(TCHAR);
  1945. // If we need to free or allocate data.
  1946. if (*lplpstz == NULL || cbNew > cbOld)
  1947. {
  1948. LPTSTR lpszNew;
  1949. // Allocate the new data.
  1950. lpszNew = PvMemAlloc(cbNew);
  1951. if (lpszNew == NULL)
  1952. {
  1953. return FALSE;
  1954. }
  1955. // Free the old data.
  1956. if (*lplpstz != NULL)
  1957. VFreeMemP(*lplpstz, cbOld);
  1958. *lplpstz = lpszNew;
  1959. }
  1960. // Make this a valid (empty) string.
  1961. **lplpstz = TEXT('\0');
  1962. return TRUE;
  1963. } // FAllocString
  1964. ////////////////////////////////////////////////////////////////////////////////
  1965. //
  1966. // ClearEditControl
  1967. //
  1968. // Purpose:
  1969. // Clears any text from an edit control
  1970. //
  1971. ////////////////////////////////////////////////////////////////////////////////
  1972. void PASCAL
  1973. ClearEditControl
  1974. (HWND hDlg, // Dialog handle
  1975. DWORD dwId) // Id of edit control
  1976. {
  1977. // Really cheesey. Clear the edit control by selecting
  1978. // everything then clearing the selection
  1979. if (dwId == 0)
  1980. {
  1981. SendMessage (hDlg, EM_SETSEL, 0, -1);
  1982. SendMessage (hDlg, WM_CLEAR, 0, 0);
  1983. }
  1984. else
  1985. {
  1986. SendDlgItemMessage (hDlg, dwId, EM_SETSEL, 0, -1);
  1987. SendDlgItemMessage (hDlg, dwId, WM_CLEAR, 0, 0);
  1988. }
  1989. } // ClearEditControl
  1990. ////////////////////////////////////////////////////////////////////////////////
  1991. //
  1992. // UdtypesGetNumberType
  1993. //
  1994. // Purpose:
  1995. // Gets the number type from the string and returns the value, either
  1996. // a float or dword in numval.
  1997. //
  1998. ////////////////////////////////////////////////////////////////////////////////
  1999. UDTYPES PASCAL
  2000. UdtypesGetNumberType
  2001. (LPTSTR lpstz, // String containing the number
  2002. NUM *lpnumval, // The value of the number
  2003. BOOL (*lpfnFSzToNum)(NUM *, LPTSTR)) // Sz To Num routine, can be null
  2004. {
  2005. TCHAR *pc;
  2006. errno = 0;
  2007. *(DWORD *) lpnumval = strtol ((LPTSTR)PSTR (lpstz), &pc, 10);
  2008. if ((!errno) && (*pc == TEXT('\0')))
  2009. return wUDdw;
  2010. // Try doing a float conversion if int fails
  2011. if (lpfnFSzToNum != NULL)
  2012. {
  2013. if ((*lpfnFSzToNum)(lpnumval, (LPTSTR)PSTR(lpstz)))
  2014. return wUDfloat;
  2015. }
  2016. return wUDinvalid;
  2017. } // UdtypesGetNumberType
  2018. ////////////////////////////////////////////////////////////////////////////////
  2019. //
  2020. // YearIndexFromShortDateFormat
  2021. //
  2022. //
  2023. // Determines the zero-based position index of the year component
  2024. // of a textual representation of the date based on the specified date format.
  2025. // This value may be used as the iYear arg to ScanDateNums function.
  2026. //
  2027. ////////////////////////////////////////////////////////////////////////////////
  2028. int YearIndexFromShortDateFormat( TCHAR chFmt )
  2029. {
  2030. switch( chFmt )
  2031. {
  2032. case MMDDYY:
  2033. case DDMMYY:
  2034. return 2;
  2035. case YYMMDD:
  2036. return 0;
  2037. }
  2038. return -1;
  2039. }
  2040. ////////////////////////////////////////////////////////////////////////////////
  2041. //
  2042. // IsGregorian
  2043. //
  2044. // Purpose:
  2045. // Reports whether the specified calendar is a gregorian calendar.
  2046. //
  2047. ////////////////////////////////////////////////////////////////////////////////
  2048. BOOL IsGregorian( CALID calid )
  2049. {
  2050. switch (calid)
  2051. {
  2052. case CAL_GREGORIAN:
  2053. case CAL_GREGORIAN_US:
  2054. case CAL_GREGORIAN_ME_FRENCH:
  2055. case CAL_GREGORIAN_ARABIC:
  2056. case CAL_GREGORIAN_XLIT_ENGLISH:
  2057. case CAL_GREGORIAN_XLIT_FRENCH:
  2058. return TRUE;
  2059. // these are non-gregorian:
  2060. //case CAL_JAPAN
  2061. //case CAL_TAIWAN
  2062. //case CAL_KOREA
  2063. //case CAL_HIJRI
  2064. //case CAL_THAI
  2065. //case CAL_HEBREW
  2066. }
  2067. return FALSE;
  2068. }
  2069. ////////////////////////////////////////////////////////////////////////////////
  2070. //
  2071. // GregorianYearFromAbbreviatedYear
  2072. //
  2073. // Purpose:
  2074. // Based on current locale settings, calculates the year corresponding to the
  2075. // specified 1- or 2-digit abbreviated value.
  2076. //
  2077. ////////////////////////////////////////////////////////////////////////////////
  2078. int GregorianYearFromAbbreviatedYear( LCID lcid, CALID calid, int nAbbreviatedYear )
  2079. {
  2080. TCHAR szData[16];
  2081. LONG nYearHigh = -1;
  2082. int nBaseCentury;
  2083. int nYearInCentury = 0;
  2084. // We're handling two-digit values for gregorian calendars only
  2085. if (nAbbreviatedYear < 100)
  2086. {
  2087. // We don't support non-gregorian date windowing here
  2088. // because that would be insanely complex and prone to error -ccooney 2000/02/04
  2089. if( !IsGregorian( calid )
  2090. || !GetCalendarInfo( lcid, calid, CAL_ITWODIGITYEARMAX|CAL_RETURN_NUMBER,
  2091. NULL, 0, &nYearHigh ) )
  2092. {
  2093. // In the absence of a default, use 2029 as the cutoff, just like monthcal.
  2094. nYearHigh = 2029;
  2095. }
  2096. //
  2097. // Copy the century of nYearHigh into nAbbreviatedYear.
  2098. //
  2099. nAbbreviatedYear += (nYearHigh - nYearHigh % 100);
  2100. //
  2101. // If it exceeds the max, then drop to previous century.
  2102. //
  2103. if (nAbbreviatedYear > nYearHigh)
  2104. nAbbreviatedYear -= 100;
  2105. }
  2106. return nAbbreviatedYear;
  2107. }
  2108. ////////////////////////////////////////////////////////////////////////////////
  2109. //
  2110. // FConvertDate
  2111. //
  2112. // Purpose:
  2113. // Converts the given string to a date.
  2114. //
  2115. ////////////////////////////////////////////////////////////////////////////////
  2116. BOOL PASCAL FConvertDate
  2117. (LPTSTR lpstz, // String having the date
  2118. LPFILETIME lpft) // The date in FILETIME format
  2119. {
  2120. FILETIME ft;
  2121. SYSTEMTIME st;
  2122. TCHAR szSep[3];
  2123. TCHAR szFmt[10];
  2124. TCHAR szCalID[8];
  2125. unsigned int ai[3];
  2126. int iYear =-1; // index of ai member that represents the year value
  2127. CALID calid;
  2128. TCHAR szDate[256];
  2129. TCHAR szMonth[256];
  2130. TCHAR *pch;
  2131. TCHAR *pchT;
  2132. DWORD cch;
  2133. DWORD i;
  2134. if (!(GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_IDATE, szFmt, ARRAYSIZE(szFmt))) ||
  2135. !(GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SDATE, szSep, ARRAYSIZE(szSep))) ||
  2136. !(GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ICALENDARTYPE, szCalID, ARRAYSIZE(szCalID))) )
  2137. return FALSE;
  2138. iYear = YearIndexFromShortDateFormat(szFmt[0]);
  2139. // Augh! It's an stz so we need to pass the DWORDs at the start
  2140. if (!ScanDateNums(lpstz, szSep, ai, sizeof(ai)/sizeof(unsigned int),iYear))
  2141. {
  2142. // Could be that the string contains the short version of the month, e.g. 03-Mar-95
  2143. PbMemCopy(szDate, lpstz, CBTSTR(lpstz));
  2144. pch = szDate;
  2145. // Let's get to the first character of the month, if there is one
  2146. while((isdigit(*pch) || (*pch == szSep[0])) && (*pch != 0))
  2147. ++pch;
  2148. // If we got to the end of the string, there really was an error
  2149. if (*pch == 0)
  2150. return(FALSE);
  2151. // Let's find the length of the month string
  2152. pchT = pch+1;
  2153. while ((*pchT != szSep[0]) && (*pchT != 0))
  2154. ++pchT;
  2155. cch = (DWORD)(pchT - pch);
  2156. // Loop through all the months and see if we match one
  2157. // There can be 13 months
  2158. for (i = 1; i <= 13; ++i)
  2159. {
  2160. if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME1+i-1,
  2161. szMonth, ARRAYSIZE(szMonth)))
  2162. return(FALSE);
  2163. if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH,
  2164. pch, cch, szMonth, CchTszLen(szMonth)) == 2)
  2165. break;
  2166. }
  2167. if (i > 13)
  2168. return(FALSE);
  2169. // We found the month. wsprintf zero-terminates
  2170. cch = wsprintf(pch, TEXT("%u"), i);
  2171. pch += cch;
  2172. while (*pch++ = *(pch+1));
  2173. // Try and convert again
  2174. if (!ScanDateNums(szDate, szSep, ai, 3, iYear))
  2175. return(FALSE);
  2176. } // if (!ScanDateNums(lpstz, szSep, ai, 3))
  2177. FillBuf (&st, 0, sizeof(st));
  2178. switch (szFmt[0])
  2179. {
  2180. case MMDDYY:
  2181. st.wMonth = (WORD)ai[0];
  2182. st.wDay = (WORD)ai[1];
  2183. st.wYear = (WORD)ai[2];
  2184. break;
  2185. case DDMMYY:
  2186. st.wDay = (WORD)ai[0];
  2187. st.wMonth = (WORD)ai[1];
  2188. st.wYear = (WORD)ai[2];
  2189. break;
  2190. case YYMMDD:
  2191. st.wYear = (WORD)ai[0];
  2192. st.wMonth = (WORD)ai[1];
  2193. st.wDay = (WORD)ai[2];
  2194. break;
  2195. default:
  2196. return FALSE;
  2197. }
  2198. if (st.wYear < ONECENTURY)
  2199. {
  2200. calid = strtol( szCalID, NULL, 10 );
  2201. st.wYear = (WORD)GregorianYearFromAbbreviatedYear(
  2202. LOCALE_USER_DEFAULT, calid, st.wYear );
  2203. }
  2204. if (!SystemTimeToFileTime (&st, &ft))
  2205. return(FALSE);
  2206. return(LocalFileTimeToFileTime(&ft, lpft));
  2207. } // FConvertDate
  2208. ////////////////////////////////////////////////////////////////////////////////
  2209. //
  2210. // PopulateUDListView
  2211. //
  2212. // Purpose:
  2213. // Populates the entire ListView with the User-defined properties
  2214. // in the given object.
  2215. //
  2216. ////////////////////////////////////////////////////////////////////////////////
  2217. void PASCAL
  2218. PopulateUDListView
  2219. (HWND hWnd, // Handle of list view window
  2220. LPUDOBJ lpUDObj) // UD Prop object
  2221. {
  2222. LPUDITER lpudi;
  2223. LPPROPVARIANT lppropvar;
  2224. BOOL fLink;
  2225. BOOL fLinkInvalid;
  2226. // Iterate through the list of user-defined properties, adding each
  2227. // one to the listview.
  2228. for( lpudi = LpudiUserDefCreateIterator (lpUDObj);
  2229. FUserDefIteratorValid (lpudi);
  2230. FUserDefIteratorNext (lpudi)
  2231. )
  2232. {
  2233. // Get the name of this property.
  2234. LPTSTR tszPropertyName
  2235. = LpszUserDefIteratorName( lpudi, 1, (LPTSTR) UD_PTRWIZARD );
  2236. // If the property has no name, or the name indicates that it
  2237. // is a hidden property, then move on to the next property.
  2238. if( tszPropertyName == NULL
  2239. ||
  2240. *tszPropertyName == HIDDENPREFIX )
  2241. {
  2242. continue;
  2243. }
  2244. lppropvar = LppropvarUserDefGetIteratorVal (lpudi, &fLink, &fLinkInvalid);
  2245. if (lppropvar == NULL)
  2246. return;
  2247. // If this isn't a supported type, don't display it.
  2248. if( !ISUDTYPE(lppropvar->vt) )
  2249. continue;
  2250. #ifdef SHELL
  2251. //
  2252. // In the Shell, we want all links to show up as invalid, so set that here...
  2253. //
  2254. fLinkInvalid = TRUE;
  2255. #endif
  2256. AddUDPropToListView (lpUDObj, hWnd, LpszUserDefIteratorName (lpudi, 1, (TCHAR *) UD_PTRWIZARD),
  2257. lppropvar, -1, fLink, fLinkInvalid, FALSE);
  2258. } // for( lpudi = LpudiUserDefCreateIterator (lpUDObj); ...
  2259. FUserDefDestroyIterator (&lpudi);
  2260. } // PopulateUDListView
  2261. ////////////////////////////////////////////////////////////////////////////////
  2262. //
  2263. // AddUDPropToListView
  2264. //
  2265. // Purpose:
  2266. // Adds the given property to the list view or updates an existing one
  2267. // if iItem >= 0
  2268. //
  2269. ////////////////////////////////////////////////////////////////////////////////
  2270. void PASCAL AddUDPropToListView (
  2271. LPUDOBJ lpUDObj,
  2272. HWND hWnd, // Handle of list view
  2273. LPTSTR lpszName, // Name of property
  2274. LPPROPVARIANT lppropvar, // The property value.
  2275. int iItem, // Index to add item at
  2276. BOOL fLink, // Indicates the value is a link
  2277. BOOL fLinkInvalid, // Is the link invalid?
  2278. BOOL fMakeVisible) // Should the property be forced to be visible
  2279. {
  2280. LV_ITEM lvi;
  2281. TCHAR sz[BUFMAX];
  2282. WORD irg;
  2283. BOOL fSuccess;
  2284. BOOL fUpdate;
  2285. // If iItem >= 0, then the item should be updated, otherwise,
  2286. // it should be added.
  2287. if (fUpdate = (iItem >= 0))
  2288. {
  2289. lvi.iItem = iItem;
  2290. if (fLink)
  2291. lvi.iImage = (fLinkInvalid) ? giInvLinkIcon : giLinkIcon;
  2292. else
  2293. lvi.iImage = giBlankIcon;
  2294. lvi.mask = LVIF_IMAGE;
  2295. lvi.iSubItem = iszNAME;
  2296. fSuccess = ListView_SetItem (hWnd, &lvi);
  2297. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  2298. }
  2299. else
  2300. {
  2301. // This always adds to the end of the list....
  2302. lvi.iItem = ListView_GetItemCount (hWnd);
  2303. // First add the label to the list
  2304. lvi.iSubItem = iszNAME;
  2305. lvi.pszText = lpszName;
  2306. if (fLink)
  2307. lvi.iImage = (fLinkInvalid) ? giInvLinkIcon : giLinkIcon;
  2308. else
  2309. lvi.iImage = giBlankIcon;
  2310. lvi.mask = LVIF_TEXT | LVIF_IMAGE;
  2311. lvi.iItem = ListView_InsertItem (hWnd, &lvi);
  2312. if (lvi.iItem == 0)
  2313. ListView_SetItemState(hWnd, 0, LVIS_FOCUSED, LVIS_FOCUSED);
  2314. }
  2315. // Convert the data to a string and print it
  2316. lvi.mask = LVIF_TEXT;
  2317. irg = WUdtypeToSz (lppropvar, sz, BUFMAX, ((LPUDINFO)lpUDObj->m_lpData)->lpfnFNumToSz);
  2318. lvi.pszText = sz;
  2319. lvi.iSubItem = iszVAL;
  2320. fSuccess = ListView_SetItem (hWnd, &lvi);
  2321. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  2322. // Put the type in the listview
  2323. lvi.iSubItem = iszTYPE;
  2324. lvi.pszText = (LPTSTR) rgszTypes[irg];
  2325. fSuccess = ListView_SetItem (hWnd, &lvi);
  2326. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  2327. if (fMakeVisible)
  2328. {
  2329. fSuccess = ListView_EnsureVisible(hWnd, lvi.iItem, FALSE);
  2330. Assert (fSuccess); // We don't *really* care, just want to know when it happens
  2331. }
  2332. // if (fUpdate)
  2333. // {
  2334. // ListView_RedrawItems (hWnd, lvi.iItem, lvi.iItem);
  2335. // UpdateWindow (hWnd);
  2336. // }
  2337. } // AddUDPropToListView
  2338. ////////////////////////////////////////////////////////////////////////////////
  2339. //
  2340. // AddItemToListView
  2341. //
  2342. // Purpose:
  2343. // Adds the given string and number to the end of a listview
  2344. //
  2345. ////////////////////////////////////////////////////////////////////////////////
  2346. void PASCAL
  2347. AddItemToListView
  2348. (HWND hWnd, // ListView handle
  2349. DWORD_PTR dw, // Number to add
  2350. const TCHAR *lpsz, // String to add
  2351. BOOL fString) // Indicates if dw is actually a string
  2352. {
  2353. LV_ITEM lvi;
  2354. TCHAR sz[BUFMAX];
  2355. BOOL fSuccess;
  2356. if (!fString)
  2357. // _itoa (dw, sz, BASE10);
  2358. wsprintf(sz, TEXT("%lu"), dw);
  2359. // This always adds to the end of the list....
  2360. lvi.iItem = ListView_GetItemCount (hWnd);
  2361. // First add the label to the list
  2362. lvi.mask = LVIF_TEXT;
  2363. lvi.iSubItem = iszNAME;
  2364. lvi.pszText = (LPTSTR) lpsz;
  2365. lvi.iItem = ListView_InsertItem (hWnd, &lvi);
  2366. if (lvi.iItem == 0) // Adding the 1st item
  2367. ListView_SetItemState(hWnd, 0, LVIS_FOCUSED, LVIS_FOCUSED);
  2368. Assert ((lvi.iItem != -1));
  2369. // Then add the value
  2370. lvi.mask = LVIF_TEXT;
  2371. lvi.iSubItem = iszVAL;
  2372. lvi.pszText = (fString) ? (LPTSTR) dw : sz;
  2373. fSuccess = ListView_SetItem (hWnd, &lvi);
  2374. Assert (fSuccess);
  2375. } // AddItemToListView
  2376. ////////////////////////////////////////////////////////////////////////////////
  2377. //
  2378. // InitListView
  2379. //
  2380. // Purpose:
  2381. // Initializes a list view control
  2382. //
  2383. ////////////////////////////////////////////////////////////////////////////////
  2384. void PASCAL
  2385. InitListView
  2386. (HWND hWndLV, // Handle of parent dialog
  2387. int irgLast, // Index of last column in array
  2388. TCHAR rgsz[][SHORTBUFMAX], // Array of column headings
  2389. BOOL fImageList) // Should the listview have an image list
  2390. {
  2391. HICON hIcon;
  2392. RECT rect;
  2393. HIMAGELIST hImlS;
  2394. LV_COLUMN lvc;
  2395. int irg;
  2396. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  2397. lvc.fmt = LVCFMT_LEFT;
  2398. // Initially force all columns to be the same size & fill the control.
  2399. GetClientRect(hWndLV, &rect);
  2400. // Subtract fudge factor
  2401. lvc.cx = (rect.right-rect.left)/(irgLast+1)-(GetSystemMetrics(SM_CXVSCROLL)/(irgLast+1));
  2402. // Add in all the columns.
  2403. for (irg = 0; irg <= irgLast; irg++)
  2404. {
  2405. lvc.pszText = rgsz[irg];
  2406. lvc.iSubItem = irg;
  2407. ListView_InsertColumn (hWndLV, irg, &lvc);
  2408. }
  2409. if (!fImageList)
  2410. return;
  2411. hIcon = LoadIcon (g_hmodThisDll, MAKEINTRESOURCE (IDD_BLANK_ICON));
  2412. if (hIcon != NULL)
  2413. {
  2414. hImlS = MsoImageList_Create (16, 16, TRUE, ICONSMAX, 0);
  2415. ListView_SetImageList (hWndLV, hImlS, LVSIL_SMALL);
  2416. giBlankIcon = MsoImageList_ReplaceIcon (hImlS, -1, hIcon);
  2417. Assert ((giBlankIcon != -1));
  2418. }
  2419. } // InitListView
  2420. ////////////////////////////////////////////////////////////////////////////////
  2421. //
  2422. // FSwapControls
  2423. //
  2424. // Purpose:
  2425. // Swaps the controls needed to display link info.
  2426. //
  2427. ////////////////////////////////////////////////////////////////////////////////
  2428. BOOL PASCAL
  2429. FSwapControls
  2430. (HWND hWndVal, // Handle of Value window
  2431. HWND hWndLinkVal, // Handle of Link Value Combo box
  2432. HWND hWndBoolTrue, // Handle of True radio button
  2433. HWND hWndBoolFalse, // Handle of False radio button
  2434. HWND hWndGroup, // Handle of Group box
  2435. HWND hWndType, // Handle of Type window
  2436. HWND hWndValText,
  2437. BOOL fLink, // Flag indicating a link
  2438. BOOL fBool) // Flag indicating a bool
  2439. {
  2440. if (fLink)
  2441. {
  2442. SendMessage (hWndValText, WM_SETTEXT, 0, (LPARAM) rgszValue[iszSOURCE]);
  2443. ShowWindow (hWndVal, SW_HIDE);
  2444. ShowWindow (hWndBoolTrue, SW_HIDE);
  2445. ShowWindow (hWndBoolFalse, SW_HIDE);
  2446. ShowWindow (hWndGroup, SW_HIDE);
  2447. ShowWindow (hWndLinkVal, SW_SHOW);
  2448. EnableWindow (hWndType, FALSE);
  2449. ClearEditControl (hWndVal, 0);
  2450. }
  2451. else
  2452. {
  2453. SendMessage (hWndValText, WM_SETTEXT, 0, (LPARAM) rgszValue[iszVALUE]);
  2454. ShowWindow (hWndLinkVal, SW_HIDE);
  2455. EnableWindow (hWndType, TRUE);
  2456. if (fBool)
  2457. {
  2458. ShowWindow (hWndVal, SW_HIDE);
  2459. ShowWindow (hWndBoolTrue, SW_SHOW);
  2460. ShowWindow (hWndBoolFalse, SW_SHOW);
  2461. ShowWindow (hWndGroup, SW_SHOW);
  2462. SendMessage (hWndBoolTrue, BM_SETCHECK, (WPARAM) CHECKED, 0);
  2463. SendMessage (hWndBoolFalse, BM_SETCHECK, (WPARAM) CLEAR, 0);
  2464. SendMessage (hWndType, CB_SETCURSEL, iszBOOL, 0);
  2465. ClearEditControl (hWndVal, 0);
  2466. }
  2467. else
  2468. {
  2469. ShowWindow (hWndVal, SW_SHOW);
  2470. EnableWindow(hWndVal, TRUE);
  2471. ShowWindow (hWndBoolTrue, SW_HIDE);
  2472. ShowWindow (hWndBoolFalse, SW_HIDE);
  2473. ShowWindow (hWndGroup, SW_HIDE);
  2474. SendMessage (hWndType, CB_SETCURSEL, iszTEXT, 0);
  2475. }
  2476. }
  2477. return TRUE;
  2478. } // FSwapControls
  2479. ////////////////////////////////////////////////////////////////////////////////
  2480. //
  2481. // PopulateControls
  2482. //
  2483. // Purpose:
  2484. // Populates the edit controls with the appropriate date from the object
  2485. //
  2486. ////////////////////////////////////////////////////////////////////////////////
  2487. VOID PASCAL PopulateControls (
  2488. LPUDOBJ lpUDObj, // Pointer to object
  2489. LPTSTR szName, // Name of the item to populate controls with
  2490. DWORD cLinks, // Number of links
  2491. DWQUERYLD lpfnDwQueryLinkData, // Pointer to app link callback
  2492. HWND hDlg, // Handle of the dialog
  2493. HWND hWndName, // Handle of the Name window
  2494. HWND hWndVal, // Handle of Value window
  2495. HWND hWndValText, // Handle of Value LTEXT
  2496. HWND hWndLink, // Handle of Link checkbox
  2497. HWND hWndLinkVal, // Handle of Link Value window
  2498. HWND hWndType, // Handle of Type window
  2499. HWND hWndBoolTrue, // Handle of True radio button
  2500. HWND hWndBoolFalse, // Handle of False radio button
  2501. HWND hWndGroup, // Handle of Group window
  2502. HWND hWndAdd, // Handle of Add button
  2503. HWND hWndDelete, // Handle of Delete button
  2504. BOOL *pfLink, // Indicates that the value is a link
  2505. BOOL *pfAdd) // Indicates the state of the Add button
  2506. {
  2507. UDTYPES udtype;
  2508. LPVOID lpv;
  2509. LPPROPVARIANT lppropvar; // A property from the UDObj linked-list.
  2510. BOOL f,fT;
  2511. TCHAR sz[BUFMAX];
  2512. LPUDPROP lpudp;
  2513. // Grab the type for the string and set up the dialog to have the right
  2514. // controls to display it.
  2515. udtype = UdtypesUserDefType (lpUDObj, szName);
  2516. AssertSz ((udtype != wUDinvalid), TEXT("User defined properties or ListView corrupt"));
  2517. // Get a name-specified property from the UD linked-list.
  2518. lppropvar = LppropvarUserDefGetPropVal (lpUDObj, szName, pfLink, &fT);
  2519. Assert (lppropvar != NULL || udtype == wUDbool || udtype == wUDdw);
  2520. if (lppropvar == NULL)
  2521. return;
  2522. lpv = LpvoidUserDefGetPropVal (lpUDObj, szName, 1, NULL, UD_STATIC | UD_PTRWIZARD, pfLink, &fT);
  2523. Assert((lpv != NULL) || (udtype == wUDbool) || (udtype == wUDdw));
  2524. FSwapControls (hWndVal, hWndLinkVal, hWndBoolTrue, hWndBoolFalse, hWndGroup, hWndType, hWndValText, *pfLink, (udtype == wUDbool));
  2525. SendMessage (hWndType, CB_SETCURSEL, (WPARAM) WUdtypeToSz (lppropvar, (TCHAR *) sz, BUFMAX,
  2526. ((LPUDINFO)lpUDObj->m_lpData)->lpfnFNumToSz), 0);
  2527. SendMessage (hWndLink, BM_SETCHECK, (WPARAM) *pfLink, 0);
  2528. if (cLinks) // Let's make sure we enable the window if links are allowed
  2529. EnableWindow(hWndLink, TRUE);
  2530. if (*pfLink)
  2531. {
  2532. FCreateListOfLinks (cLinks, lpfnDwQueryLinkData, hWndLinkVal);
  2533. lpv = LpvoidUserDefGetPropVal (lpUDObj, szName, 1, NULL, UD_LINK | UD_PTRWIZARD, pfLink, &fT);
  2534. Assert (lpv != NULL || udtype == wUDbool || udtype == wUDdw);
  2535. // if (lpfnDwQueryLinkData == NULL)
  2536. // {
  2537. // SetCustomDlgDefButton(hDlg, gOKButtonID);
  2538. // EnableWindow (hWndAdd, FALSE);
  2539. // SendMessage (hWndLinkVal, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) lpv);
  2540. // }
  2541. AssertSz ((lpv != NULL), TEXT("Dialog is corrupt in respect to Custom Properties database"));
  2542. // This code is added for bug 188 and the code is ugly !! :)
  2543. lpudp = LpudpropFindMatchingName (lpUDObj, szName);
  2544. if ((lpudp != NULL) && (lpudp->fLinkInvalid))
  2545. {
  2546. SetCustomDlgDefButton(hDlg, IDD_CUSTOM_DELETE);
  2547. SendMessage(hWndName, WM_SETTEXT, 0, (LPARAM)szName);
  2548. SendMessage(hWndVal, WM_SETTEXT, 0, (LPARAM)lpv);
  2549. EnableWindow(hWndDelete, TRUE);
  2550. EnableWindow(hWndAdd, FALSE);
  2551. EnableWindow(hWndLink, FALSE);
  2552. EnableWindow(hWndType, FALSE);
  2553. ShowWindow(hWndLinkVal, SW_HIDE);
  2554. ShowWindow(hWndVal, SW_SHOW);
  2555. EnableWindow(hWndVal, FALSE);
  2556. return;
  2557. }
  2558. // Select the current link for this property in the combobox. If the link
  2559. // name no longer exists (there's some contrived cases where this can
  2560. // happen) then this will select nothing.
  2561. SendMessage (hWndLinkVal, CB_SELECTSTRING, 0, (LPARAM) lpv);
  2562. EnableWindow(hWndLink, TRUE);
  2563. }
  2564. else if (udtype == wUDbool)
  2565. {
  2566. SendMessage ((lpv) ? hWndBoolTrue : hWndBoolFalse, BM_SETCHECK, CHECKED, 0);
  2567. SendMessage ((lpv) ? hWndBoolFalse : hWndBoolTrue, BM_SETCHECK, CLEAR, 0);
  2568. EnableWindow(hWndType, TRUE);
  2569. }
  2570. else
  2571. {
  2572. SendMessage (hWndVal, WM_SETTEXT, 0, (LPARAM) sz);
  2573. EnableWindow (hWndVal, TRUE);
  2574. EnableWindow(hWndType, TRUE);
  2575. }
  2576. if (*pfAdd)
  2577. {
  2578. SendMessage (hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszMODIFY]);
  2579. *pfAdd = FALSE;
  2580. }
  2581. // HACK: Because the EN_UPDATE handler for hWndName checks fAdd to
  2582. // see if the button should be set to Add, when we set the text
  2583. // in the edit control, the button will change to Add unless
  2584. // fAdd is set to TRUE. Temporarily set the flag to TRUE to force
  2585. // the button to not change. Restore the original value after the
  2586. // text has been set.
  2587. f = *pfAdd;
  2588. *pfAdd = TRUE;
  2589. SendMessage (hWndName, WM_SETTEXT, 0, (LPARAM) szName);
  2590. *pfAdd = f;
  2591. // If we can fill the data in the controls, turn on the
  2592. // Delete button too.
  2593. // fItemSel = TRUE;
  2594. EnableWindow (hWndDelete, TRUE);
  2595. SetCustomDlgDefButton(hDlg, gOKButtonID);
  2596. EnableWindow (hWndAdd, FALSE);
  2597. } // PopulateControls
  2598. ////////////////////////////////////////////////////////////////////////////////
  2599. //
  2600. // FSetupAddButton
  2601. //
  2602. // Purpose:
  2603. // Sets up the Add button correctly based on the type & flags.
  2604. //
  2605. ////////////////////////////////////////////////////////////////////////////////
  2606. BOOL PASCAL
  2607. FSetupAddButton
  2608. (DWORD iszType, // Index of the type in combobox
  2609. BOOL fLink, // Indicates a link
  2610. BOOL *pfAdd, // Indicates if the Add button is showing
  2611. HWND hWndAdd, // Handle of Add button
  2612. HWND hWndVal, // Handle of value button
  2613. HWND hWndName, // Handle of Name
  2614. HWND hDlg) // Handle of dialog
  2615. {
  2616. // Once the user starts typing, we can enable the Add button
  2617. // if there is text in the name & the value (unless this
  2618. // is a link or boolean, in which case we don't care about
  2619. // the value).
  2620. BOOL f;
  2621. if ((iszType != iszBOOL) && (!fLink))
  2622. {
  2623. if (SendMessage (hWndVal, EM_LINELENGTH, 0, 0) != 0)
  2624. {
  2625. f = (SendMessage (hWndName, WM_GETTEXTLENGTH, 0, 0) != 0);
  2626. if (f)
  2627. SetCustomDlgDefButton(hDlg, IDD_CUSTOM_ADD);
  2628. else
  2629. SetCustomDlgDefButton(hDlg, gOKButtonID);
  2630. EnableWindow (hWndAdd, f);
  2631. }
  2632. else
  2633. {
  2634. SetCustomDlgDefButton(hDlg, gOKButtonID);
  2635. EnableWindow (hWndAdd, FALSE);
  2636. }
  2637. }
  2638. // If it's a bool or link, just check to see that the name
  2639. // has stuff in it.
  2640. else
  2641. {
  2642. f = SendMessage (hWndName, WM_GETTEXTLENGTH, 0, 0) != 0;
  2643. if (f)
  2644. SetCustomDlgDefButton(hDlg, IDD_CUSTOM_ADD);
  2645. else
  2646. SetCustomDlgDefButton(hDlg, gOKButtonID);
  2647. EnableWindow (hWndAdd, f);
  2648. }
  2649. if (!*pfAdd)
  2650. {
  2651. SendMessage (hWndAdd, WM_SETTEXT, 0, (LPARAM) rgszAdd[iszADD]);
  2652. *pfAdd = TRUE;
  2653. }
  2654. return TRUE;
  2655. } // FSetupAddButton
  2656. ////////////////////////////////////////////////////////////////////////////////
  2657. //
  2658. // WUdtypeToSz
  2659. //
  2660. // Purpose:
  2661. // Converts the given type into a string representation. Returns the
  2662. // index in the type combobox of the type.
  2663. //
  2664. ////////////////////////////////////////////////////////////////////////////////
  2665. WORD PASCAL WUdtypeToSz (
  2666. LPPROPVARIANT lppropvar, // Value with the type to be converted.
  2667. LPTSTR sz, // Buffer to put converted val in
  2668. DWORD cchMax, // Size of buffer (in chars)
  2669. BOOL (*lpfnFNumToSz)(NUM *, LPTSTR, DWORD))
  2670. {
  2671. SYSTEMTIME st;
  2672. WORD irg;
  2673. FILETIME ft;
  2674. Assert (lppropvar != NULL);
  2675. switch (lppropvar->vt)
  2676. {
  2677. case wUDlpsz :
  2678. PbSzNCopy (sz, lppropvar->pwszVal, cchMax);
  2679. irg = iszTEXT;
  2680. break;
  2681. case wUDdate :
  2682. if (FScanMem((LPBYTE)&lppropvar->filetime,
  2683. 0, sizeof(FILETIME))) // if the date struct is all 0's
  2684. {
  2685. *sz = 0; // display the empty string
  2686. }
  2687. else if (!FileTimeToLocalFileTime(&lppropvar->filetime, &ft)
  2688. || !FileTimeToSystemTime (&ft, &st)
  2689. || (!GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, sz, cchMax)))
  2690. {
  2691. #ifdef DEBUG
  2692. DWORD dwErr = GetLastError();
  2693. #endif DEBUG
  2694. irg = iszUNKNOWN;
  2695. *sz = 0;
  2696. break;
  2697. }
  2698. irg = iszDATE;
  2699. break;
  2700. case wUDdw :
  2701. Assert(cchMax >= 11);
  2702. Assert(lppropvar->vt == VT_I4);
  2703. wsprintf (sz, TEXT("%ld"), lppropvar->lVal);
  2704. irg = iszNUM;
  2705. break;
  2706. case wUDfloat :
  2707. if (lpfnFNumToSz != NULL)
  2708. irg = (*lpfnFNumToSz)((NUM*)&lppropvar->dblVal, sz, cchMax) ? iszNUM : iszUNKNOWN;
  2709. else
  2710. {
  2711. irg = iszUNKNOWN;
  2712. *sz = 0;
  2713. }
  2714. break;
  2715. case wUDbool :
  2716. PbSzNCopy (sz,
  2717. lppropvar->boolVal ? (LPTSTR) &rgszBOOL[iszTRUE] : (LPTSTR) &rgszBOOL[iszFALSE],
  2718. cchMax);
  2719. irg = iszBOOL;
  2720. break;
  2721. default :
  2722. irg = iszUNKNOWN;
  2723. } // switch
  2724. return irg;
  2725. } // WUdtypeToSz
  2726. ////////////////////////////////////////////////////////////////////////////////
  2727. //
  2728. // FCreateListOfLinks
  2729. //
  2730. // Purpose:
  2731. // Creates the dropdown list of linkable items.
  2732. //
  2733. ////////////////////////////////////////////////////////////////////////////////
  2734. BOOL PASCAL FCreateListOfLinks(
  2735. DWORD cLinks, // Number of links
  2736. DWQUERYLD lpfnDwQueryLinkData, // Link data callback
  2737. HWND hWndLinkVal) // Link Value window handle
  2738. {
  2739. DWORD irg;
  2740. LPTSTR lpstz;
  2741. // If the combobox is already filled, don't fill it
  2742. if (irg = (int)SendMessage(hWndLinkVal, CB_GETCOUNT,0, 0))
  2743. {
  2744. Assert(irg == cLinks);
  2745. return(TRUE);
  2746. }
  2747. lpstz = NULL;
  2748. // Call back the client app to get the list of linkable
  2749. // values, and put them in the value combobox.
  2750. for (irg = 0; irg < cLinks; irg++)
  2751. {
  2752. lpstz = (TCHAR *) ((*lpfnDwQueryLinkData) (QLD_LINKNAME, irg, &lpstz, NULL));
  2753. if (lpstz != NULL)
  2754. {
  2755. SendMessage (hWndLinkVal, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) PSTR (lpstz));
  2756. VFreeMemP(lpstz, CBTSTR(lpstz));
  2757. // REVIEW: We probably ought to figure out a way to be more efficient here....
  2758. }
  2759. }
  2760. return TRUE;
  2761. } // FCreateListOfLinks
  2762. ////////////////////////////////////////////////////////////////////////////////
  2763. //
  2764. // FSetTypeControl
  2765. //
  2766. // Purpose:
  2767. // Sets the type control to have the given type selected.
  2768. //
  2769. ////////////////////////////////////////////////////////////////////////////////
  2770. BOOL PASCAL FSetTypeControl (
  2771. UDTYPES udtype, // Type to set the type to
  2772. HWND hWndType) // Handle of type control
  2773. {
  2774. WORD iType;
  2775. switch (udtype)
  2776. {
  2777. case wUDlpsz :
  2778. iType = iszTEXT;
  2779. break;
  2780. case wUDfloat :
  2781. case wUDdw :
  2782. iType = iszNUM;
  2783. break;
  2784. case wUDbool :
  2785. iType = iszBOOL;
  2786. break;
  2787. case wUDdate :
  2788. iType = iszDATE;
  2789. break;
  2790. default:
  2791. return FALSE;
  2792. }
  2793. SendMessage (hWndType, CB_SETCURSEL, (WPARAM) iType, 0);
  2794. return TRUE;
  2795. } // FSetTypeControl
  2796. ////////////////////////////////////////////////////////////////////////////////
  2797. //
  2798. // DeleteItem
  2799. //
  2800. // Purpose:
  2801. // Deletes an item from the UD object and the listview.
  2802. //
  2803. ////////////////////////////////////////////////////////////////////////////////
  2804. void PASCAL DeleteItem (
  2805. LPUDOBJ lpUDObj,
  2806. HWND hWndLV,
  2807. int iItem,
  2808. TCHAR sz[])
  2809. {
  2810. int i;
  2811. ListView_DeleteItem (hWndLV, iItem);
  2812. FUserDefDeleteProp (lpUDObj, sz);
  2813. // We just nuked the item with the focus, so let's get the new one
  2814. // if there are still items in the listview
  2815. if ((i = ListView_GetItemCount(hWndLV)) != 0)
  2816. {
  2817. // Figure out the index of the item to get the focus
  2818. i = (i == iItem) ? iItem - 1 : iItem;
  2819. ListView_SetItemState(hWndLV, i, LVIS_FOCUSED, LVIS_FOCUSED);
  2820. }
  2821. } // DeleteItem
  2822. ////////////////////////////////////////////////////////////////////////////////
  2823. //
  2824. // ResetTypeControl
  2825. //
  2826. // Purpose:
  2827. // Resets the value of the type control to Text.
  2828. //
  2829. ////////////////////////////////////////////////////////////////////////////////
  2830. void PASCAL ResetTypeControl (
  2831. HWND hDlg, // Handle of dialog
  2832. DWORD dwId, // Id of control
  2833. DWORD *piszType) // The type we've reset to
  2834. {
  2835. SendDlgItemMessage (hDlg, dwId, CB_SETCURSEL, iszTEXT, 0);
  2836. *piszType = iszTEXT;
  2837. } // ResetTypeControl
  2838. ////////////////////////////////////////////////////////////////////////////////
  2839. //
  2840. // FDisplayConversionWarning
  2841. //
  2842. // Purpose:
  2843. // Displays a warning about types being converted. Returns TRUE if
  2844. // the user presses "Cancel"
  2845. //
  2846. ////////////////////////////////////////////////////////////////////////////////
  2847. BOOL PASCAL FDisplayConversionWarning(HWND hDlg) // Handle of parent window
  2848. {
  2849. return (IdDoAlert(hDlg, idsPEWarningText, MB_ICONEXCLAMATION | MB_OKCANCEL) == IDCANCEL);
  2850. } // FDisplayConversionWarning
  2851. ////////////////////////////////////////////////////////////////////////////////
  2852. //
  2853. // LoadTextStrings
  2854. //
  2855. // Purpose:
  2856. // Loads all of the text needed by the dialogs from the DLL.
  2857. //
  2858. ////////////////////////////////////////////////////////////////////////////////
  2859. BOOL PASCAL FLoadTextStrings (void)
  2860. {
  2861. register int cLoads = 0;
  2862. register int cAttempts = 0;
  2863. // CchGetString returns a cch, so make it into a 1 or 0
  2864. // then add up the results,making sure we load as many as
  2865. // we try.
  2866. cLoads += (CchGetString (idsPEB, rgszOrders[iszBYTES], SHORTBUFMAX) && TRUE);
  2867. cAttempts++;
  2868. cLoads += (CchGetString (idsPEKB, rgszOrders[iszORDERKB], SHORTBUFMAX) && TRUE);
  2869. cAttempts++;
  2870. cLoads += (CchGetString (idsPEMB, rgszOrders[iszORDERMB], SHORTBUFMAX) && TRUE);
  2871. cAttempts++;
  2872. cLoads += (CchGetString (idsPEGB, rgszOrders[iszORDERGB], SHORTBUFMAX) && TRUE);
  2873. cAttempts++;
  2874. cLoads += (CchGetString (idsPETB, rgszOrders[iszORDERTB], SHORTBUFMAX) && TRUE);
  2875. cAttempts++;
  2876. cLoads += (CchGetString (idsPEBytes, rgszStats[iszBYTES], SHORTBUFMAX) && TRUE);
  2877. cAttempts++;
  2878. cLoads += (CchGetString (idsPEPages, rgszStats[iszPAGES], SHORTBUFMAX) && TRUE);
  2879. cAttempts++;
  2880. cLoads += (CchGetString (idsPEPara, rgszStats[iszPARA], SHORTBUFMAX) && TRUE);
  2881. cAttempts++;
  2882. cLoads += (CchGetString (idsPELines, rgszStats[iszLINES], SHORTBUFMAX) && TRUE);
  2883. cAttempts++;
  2884. cLoads += (CchGetString (idsPEWords, rgszStats[iszWORDS], SHORTBUFMAX) && TRUE);
  2885. cAttempts++;
  2886. cLoads += (CchGetString (idsPEChars, rgszStats[iszCHARS], SHORTBUFMAX) && TRUE);
  2887. cAttempts++;
  2888. cLoads += (CchGetString (idsPESlides, rgszStats[iszSLIDES], SHORTBUFMAX) && TRUE);
  2889. cAttempts++;
  2890. cLoads += (CchGetString (idsPENotes, rgszStats[iszNOTES], SHORTBUFMAX) && TRUE);
  2891. cAttempts++;
  2892. cLoads += (CchGetString (idsPEHiddenSlides, rgszStats[iszHIDDENSLIDES], SHORTBUFMAX) && TRUE);
  2893. cAttempts++;
  2894. cLoads += (CchGetString (idsPEMMClips, rgszStats[iszMMCLIPS], SHORTBUFMAX) && TRUE);
  2895. cAttempts++;
  2896. cLoads += (CchGetString (idsPEFormat, rgszStats[iszFORMAT], SHORTBUFMAX) && TRUE);
  2897. cAttempts++;
  2898. cLoads += (CchGetString (idsPEText, rgszTypes[iszTEXT], SHORTBUFMAX) && TRUE);
  2899. cAttempts++;
  2900. cLoads += (CchGetString (idsPEDate, rgszTypes[iszDATE], SHORTBUFMAX) && TRUE);
  2901. cAttempts++;
  2902. cLoads += (CchGetString (idsPENumber, rgszTypes[iszNUM], SHORTBUFMAX) && TRUE);
  2903. cAttempts++;
  2904. cLoads += (CchGetString (idsPEBool, rgszTypes[iszBOOL], SHORTBUFMAX) && TRUE);
  2905. cAttempts++;
  2906. cLoads += (CchGetString (idsPEUnknown, rgszTypes[iszUNKNOWN], SHORTBUFMAX) && TRUE);
  2907. cAttempts++;
  2908. cLoads += (CchGetString (idsPEStatName, rgszStatHeadings[iszNAME], SHORTBUFMAX) && TRUE);
  2909. cAttempts++;
  2910. cLoads += (CchGetString (idsPEValue, rgszStatHeadings[iszVAL], SHORTBUFMAX) && TRUE);
  2911. cAttempts++;
  2912. cLoads += (CchGetString (idsPEPropName, rgszHeadings[iszNAME], SHORTBUFMAX) && TRUE);
  2913. cAttempts++;
  2914. cLoads += (CchGetString (idsPEValue, rgszHeadings[iszVAL], SHORTBUFMAX) && TRUE);
  2915. cAttempts++;
  2916. cLoads += (CchGetString (idsPEType, rgszHeadings[iszTYPE], SHORTBUFMAX) && TRUE);
  2917. cAttempts++;
  2918. cLoads += (CchGetString (idsPETrue, rgszBOOL[iszTRUE], SHORTBUFMAX) && TRUE);
  2919. cAttempts++;
  2920. cLoads += (CchGetString (idsPEFalse, rgszBOOL[iszFALSE], SHORTBUFMAX) && TRUE);
  2921. cAttempts++;
  2922. cLoads += (CchGetString (idsPEAdd, rgszAdd[iszADD], SHORTBUFMAX) && TRUE);
  2923. cAttempts++;
  2924. cLoads += (CchGetString (idsPEModify, rgszAdd[iszMODIFY], SHORTBUFMAX) && TRUE);
  2925. cAttempts++;
  2926. cLoads += (CchGetString (idsPESource, rgszValue[iszSOURCE], SHORTBUFMAX) && TRUE);
  2927. cAttempts++;
  2928. cLoads += (CchGetString (idsPEValueColon, rgszValue[iszVALUE], BUFMAX) && TRUE);
  2929. cAttempts++;
  2930. return (cLoads == cAttempts);
  2931. } // LoadTextStrings
  2932. //
  2933. // Function: ISavePropDlgChanges
  2934. //
  2935. // Parameters:
  2936. //
  2937. // hwndDlg - dialog window handle
  2938. // hwndFrom - window handle from the NMHDR struct (see code above)
  2939. //
  2940. // Returns:
  2941. //
  2942. // TRUE since we handled the message.
  2943. //
  2944. // History:
  2945. //
  2946. // Created 09/16/94 martinth
  2947. //
  2948. int PASCAL ISavePropDlgChanges(LPALLOBJS lpallobjs, HWND hwndDlg, HWND hwndFrom)
  2949. {
  2950. TCHAR sz[BUFMAX];
  2951. int iRet = IDABORT; // MessageBox return.
  2952. LRESULT lRet = 0L; // (FALSE == dismiss property sheet).
  2953. if (CchGetString(idsCustomWarning, sz, ARRAYSIZE(sz)) == 0)
  2954. return(FALSE);
  2955. lpallobjs->fPropDlgPrompted = TRUE; // no warning next time!
  2956. iRet = MessageBox( hwndDlg, sz, TEXT("Warning"),
  2957. MB_ICONEXCLAMATION | MB_YESNOCANCEL );
  2958. switch( iRet )
  2959. {
  2960. case IDYES:
  2961. PropSheet_Apply(hwndFrom); // Let's get them changes
  2962. break;
  2963. // case IDNO: // do nothing
  2964. case IDCANCEL: // cancel and disallow sheet destroy.
  2965. lRet = TRUE;
  2966. break;
  2967. }
  2968. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, lRet );
  2969. return iRet;
  2970. }