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.

712 lines
22 KiB

  1. /*
  2. * Windows Calendar
  3. * Copyright (c) 1985 by Microsoft Corporation, all rights reserved.
  4. * Written by Mark L. Chamberlin, consultant to Microsoft.
  5. *
  6. ****** calinit.c
  7. *
  8. */
  9. #include "cal.h"
  10. #include "string.h"
  11. #define DOTIMER
  12. //- OBM_RGARROW & OBM_LFARROW: Use the new arrows instead of old ones.
  13. #define OBM_RGARROW 32751
  14. #define OBM_LFARROW 32750
  15. extern INT cchLongDateMax;
  16. extern INT cchTimeMax;
  17. extern BOOL f24Time;
  18. #define GSM(SM) GetSystemMetrics(SM)
  19. BOOL APIENTRY ProcessShellOptions(
  20. LPSTR lpszCmdLine);
  21. /**** CalInit ****/
  22. BOOL APIENTRY CalInit (
  23. HANDLE hInstance,
  24. HANDLE hPrevInstance,
  25. LPSTR lpszCmdLine,
  26. INT cmdShow)
  27. {
  28. BITMAP bmBell;
  29. WNDCLASS WndClass;
  30. HDC hDC;
  31. TEXTMETRIC Metrics;
  32. INT i;
  33. INT cyUseable;
  34. CHAR *pch;
  35. INT cchRemaining, cch, cxWnd2C, cyWnd2C;
  36. HANDLE hStrings;
  37. INT tm, TimeSetting;
  38. INT BlankWidth; /* width (in pixels) of a blank char */
  39. CHAR * pszFilterSpec = vszFilterSpec; /* temp. var. for creating filter text */
  40. CHAR sz[10];
  41. CHAR *psz=sz;
  42. INT iHeight;
  43. INT iWidth;
  44. /* Remember our instance handle. */
  45. vhInstance = hInstance;
  46. /* Assume this string is longer for initialization. */
  47. vfHour24 = FALSE;
  48. TimeSetting = GTS_12HOUR;
  49. /* determine time setting from "International" section of win.ini */
  50. tm = 1;
  51. if (tm=GetProfileInt("intl", "iTime", tm))
  52. if (tm = 1)
  53. {
  54. TimeSetting = GTS_24HOUR;
  55. vfHour24 = TRUE;
  56. }
  57. InitTimeDate(vhInstance, TimeSetting);
  58. InitLongTimeDate(TimeSetting);
  59. /* Load strings from resource file. */
  60. hStrings=LocalAlloc(LPTR, cchRemaining=CCHSTRINGSMAX);
  61. pch=(CHAR *)(hStrings);
  62. if (!pch)
  63. return (FALSE);
  64. for (i=0; i<CSTRINGS; i++)
  65. {
  66. cch=1+LoadString(hInstance, i, pch, cchRemaining);
  67. /* If LoadString failed, not enough memory. */
  68. if (cch < 2)
  69. {
  70. MessageBeep(0);
  71. return FALSE;
  72. }
  73. vrgsz [i] = pch;
  74. pch += cch;
  75. /* If we run out of space it means that CCHSTRINGSMAX is too small.
  76. This should only happen when someone changes the strings in the
  77. .RC file, and returning FALSE should prevent them from shipping
  78. the new version without increasing CCHSTRINGSMAX (and possibly
  79. the initial heap size in the .DEF file).
  80. Note - we fail on the boundary condition that cchRemaining == 0
  81. because last loadstring will trim the size of the string loaded
  82. to be <= cchRemaining.
  83. */
  84. if ((cchRemaining -= cch) <= 0)
  85. return (FALSE);
  86. }
  87. //- CalInit: Eliminate Realloc because it seems to trash string pointers.
  88. //- Only lose 800 bytes anyway.
  89. //- LocalReAlloc(hStrings, CCHSTRINGSMAX-cchRemaining, LPTR);
  90. //- MergeStr: Changed to string to avoid crossing word boundries.
  91. strncpy (vszMergeStr, vrgsz [IDS_MERGE1], 2);
  92. /* Get default Page Setup stuff. */
  93. for (i=IDS_HEADER; i<=IDS_BOTTOM; i++)
  94. LoadString(hInstance, i, chPageText[i-IDS_HEADER], PT_LEN);
  95. /* Allocate the DRs. */
  96. if (!AllocDr ())
  97. return FALSE;
  98. /* Create the brushes. */
  99. if (!CreateBrushes ())
  100. /* Destroy any brushes that were created on failure. */
  101. return CalTerminate(0);
  102. /* construct default filter string in the required format for
  103. * the new FileOpen and FileSaveAs dialogs
  104. */
  105. lstrcpy(vszFilterSpec, vszFilterText);
  106. pszFilterSpec += lstrlen (vszFilterSpec) + 1;
  107. lstrcpy(pszFilterSpec++, "*");
  108. lstrcpy(pszFilterSpec, vszFileExtension);
  109. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  110. lstrcpy(pszFilterSpec, vszAllFiles);
  111. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  112. lstrcpy(pszFilterSpec, "*.*");
  113. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  114. *pszFilterSpec = '\0';
  115. *vszCustFilterSpec = '\0';
  116. /* Get cursors. */
  117. if (!(vhcsrArrow = LoadCursor (NULL, IDC_ARROW)))
  118. return CalTerminate(0);
  119. if (!(vhcsrIbeam = LoadCursor (NULL, IDC_IBEAM)))
  120. return CalTerminate(0);
  121. if (!(vhcsrWait = LoadCursor (NULL, IDC_WAIT)))
  122. return CalTerminate(0);
  123. if (hPrevInstance == NULL)
  124. {
  125. /* There is no previous instance, so we must register our
  126. * window classes.
  127. */
  128. FillBuf ((BYTE *)&WndClass, sizeof (WNDCLASS), 0);
  129. if (!(WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(1))))
  130. return CalTerminate(0);
  131. WndClass.lpszMenuName = MAKEINTRESOURCE(1);
  132. WndClass.lpszClassName = "CalWndMain",
  133. WndClass.hInstance = hInstance;
  134. WndClass.style = CS_VREDRAW | CS_HREDRAW |
  135. CS_DBLCLKS | CS_BYTEALIGNCLIENT;
  136. WndClass.lpfnWndProc = CalWndProc;
  137. /* Register CalWndMain. */
  138. if (!RegisterClass (&WndClass))
  139. return CalTerminate(0);
  140. WndClass.lpszMenuName = NULL;
  141. WndClass.lpszClassName = "CalWndSub";
  142. /* Register CalWndSub. */
  143. if (!RegisterClass (&WndClass))
  144. return CalTerminate(0);
  145. }
  146. /* Load in the accelerators. */
  147. vhAccel=LoadAccelerators(hInstance, MAKEINTRESOURCE(1));
  148. if (!vhAccel)
  149. return CalTerminate(0);
  150. /* Get bitmaps.
  151. * If LoadBitmaps returns false, must delete those that were loaded.
  152. */
  153. if (!LoadBitmaps(hInstance))
  154. return CalTerminate(1);
  155. /* Get a screen DC. */
  156. hDC=GetDC(NULL);
  157. /* Fetch the text metrics of the system font. */
  158. GetTextMetrics (hDC, &Metrics);
  159. /* Create a memory DC for BitBlts. */
  160. vhDCMemory=CreateCompatibleDC(hDC);
  161. ReleaseDC (NULL, hDC);
  162. if (!vhDCMemory)
  163. return CalTerminate(1);
  164. /* Remember the text metrics we care about. */
  165. vcyFont = Metrics.tmHeight;
  166. vcxFont = Metrics.tmAveCharWidth;
  167. vcxFontMax = Metrics.tmMaxCharWidth;
  168. vcyDescent = Metrics.tmDescent;
  169. vcyExtLead = Metrics.tmExternalLeading;
  170. if (vcyExtLead == 0)
  171. vcyExtLead=max(1, vcyFont/8);
  172. vcyLineToLine=vcyExtLead+vcyFont;
  173. /* Fetch some system metrics. */
  174. vcxBorder = GSM(SM_CXBORDER);
  175. vcyBorder = GSM(SM_CYBORDER);
  176. vcxVScrollBar = GSM(SM_CXVSCROLL);
  177. vcxHScrollBar = GSM(SM_CXHSCROLL);
  178. vcyHScrollBar = GSM(SM_CYHSCROLL);
  179. /* Find out how big the the bell bitmap is. */
  180. GetObject(vhbmBell, sizeof(BITMAP), &bmBell);
  181. vcxBell = bmBell.bmWidth;
  182. vcyBell = bmBell.bmHeight;
  183. /* Calculate the window heights. All heights are client rectangle
  184. heights, except for vcyWnd1, which includes the top and bottom
  185. borders.
  186. */
  187. vcyWnd2A=max(vcyExtLead + vcyLineToLine,
  188. vcyHScrollBar + 2 * vcyBorder);
  189. vcyWnd2BTop=vcyBorder+vcyExtLead+2*vcyLineToLine;
  190. /* Note - the assumption is that numeric digits will not have
  191. descenders. Therefore, we subtract out the descent when
  192. calculating the space below the date digits in the monthly
  193. calendar display.
  194. */
  195. /* changed from 6 to 9 */
  196. vcyWnd2BBot = 9*(6*vcyBorder+max(vcyBorder-vcyDescent, 0)
  197. +vcyFont)+vcyBorder;
  198. #ifdef DISABLE
  199. cyT = 11*vcyLineToLine+vcyBorder+vcyBorder;
  200. if (vcyWnd2BBot < cyT)
  201. vcyWnd2BBot = cyT;
  202. #endif
  203. /* The idea is to make the boxes not look very different in size
  204. on the last week of the month for the 4, 5, and 6 week cases.
  205. */
  206. vcyWnd2BBot++;
  207. vcyWnd2B = vcyWnd2BTop + vcyWnd2BBot + vcyHScrollBar; /* last item added lsr */
  208. cyWnd2C = CLNNOTES * vcyLineToLine;
  209. vcyWnd1 = vcyBorder + (vycoNotesBox = vcyWnd2A + vcyWnd2B)
  210. + vcyBorder + vcyExtLead + cyWnd2C + vcyBorder;
  211. /* Calculate the window widths. All widths are client rectangle
  212. widths, except for vcxWnd1, which includes the left and right
  213. borders.
  214. The width is determined by:
  215. Needed for Wnd2A in day mode:
  216. "<border> <time> <left arrow><border><right arrow>
  217. Wednesday, September 25, 1985 <border>"
  218. Needed for Wnd2B in day mode:
  219. "<border> <Bell> <time> <40 chars appointment description> \
  220. <scroll bar>"
  221. Note that the right border of the scroll bar aligns with the right
  222. border of Wnd1, so it shouldn't be added in twice.
  223. */
  224. vcxWnd1 = max(
  225. /* width of header */
  226. (cchLongDateMax + cchTimeMax + 4) * vcxFont
  227. + 2 * vcxHScrollBar + 3 * vcxBorder,
  228. /* width of line of display */
  229. vcxBorder + vcxBell + (40 + 4 + cchTimeMax)
  230. * vcxFont +vcxVScrollBar);
  231. vcxWnd2A = vcxWnd1 - 2 * vcxBorder ;
  232. /* Note that by adding in vcxBorder here we force the right
  233. border of the scroll bar to align with the border of the
  234. enclosing window Wnd1.
  235. */
  236. vcxWnd2B = vcxWnd2A - vcxVScrollBar + vcxBorder;
  237. /* Note - we know there are at least 40+4+1+cchTimeMax characters (from the width of
  238. wnd1) and we assume that the rest of the stuff (like the scroll
  239. bar and alarm bell bitmap totals at least one extra character
  240. (a very safe assumption).
  241. Leave room to the right of the last character for showing the
  242. caret when the edit control is full (the caret is vcxBorder
  243. pixels wide).
  244. */
  245. cxWnd2C = (40 + 4 + 1 + cchTimeMax) * vcxFont + vcxBorder;
  246. /* Calculate some x coordinates within Wnd2A. */
  247. #ifdef BUG_8560
  248. vxcoLeftArrowMax = (vxcoLeftArrowFirst = (7 + cchTimeMax) * vcxFont) + vcxHScrollBar;
  249. vxcoRightArrowMax = (vxcoRightArrowFirst = vxcoLeftArrowMax + vcxBorder)+ vcxHScrollBar;
  250. #else
  251. vxcoLeftArrowMax = (vxcoLeftArrowFirst = (7 + cchTimeMax) * vcxFont) + vcxHScrollBar + vcxBorder;
  252. vxcoRightArrowMax = (vxcoRightArrowFirst = vxcoLeftArrowMax)+ vcxHScrollBar + vcxBorder;
  253. #endif
  254. hDC=GetDC(NULL);
  255. vxcoDate = vxcoRightArrowMax + vcxFont;
  256. /* Calculate some coordinates within wnd2B for day mode. */
  257. GetTimeSz ( SAMPLETIME, psz);
  258. MGetTextExtent(hDC, vszBlank, 1, &iHeight, &iWidth);
  259. BlankWidth = iWidth;
  260. MGetTextExtent(hDC, psz, 1, &iHeight, &iWidth);
  261. //- KLUDGE: Divide the width of a character by two because it seems to
  262. //- be too large.
  263. //- TEMP: vxcoBell = iWidth;
  264. //- TEMP: vxcoApptTime = vxcoBell + vcxBell + iWidth;
  265. vxcoBell = iWidth / 2;
  266. vxcoApptTime = vxcoBell + vcxBell + iWidth / 2;
  267. MGetTextExtent(hDC, psz, 6, &iHeight, &iWidth);
  268. vxcoAmPm = vxcoApptTime + iWidth -1;
  269. cchTimeMax = 2*vcxFontMax / BlankWidth;
  270. /* Release the the DC. */
  271. ReleaseDC (NULL, hDC);
  272. /* Calculate the x boundaries of the appointment descriptions.
  273. Leave room to the right of the last character for showing the
  274. caret when the edit control is full (the caret is vcxBorder
  275. pixels wide).
  276. */
  277. /*
  278. vxcoQdMax = (vxcoQdFirst = vxcoAmPm + 3 * vcxFont)
  279. + CCHQDMAX * vcxFont + vcxBorder;
  280. */
  281. //- KLUDGE: vxcoQdFirst = vxcoAmPm + 3 * vcxFontMax;
  282. vxcoQdFirst = vxcoAmPm + 6 * vcxFontMax;
  283. /* This formula limits the Moving edit control to what is visible
  284. and not to a number of characters. The -2 at the end is simply
  285. so the caret is not flush with the scrollbar. c-kraigb */
  286. vxcoQdMax=vcxWnd1 - vcxBorder - GSM(SM_CXVSCROLL)-2;
  287. /* Calculate the number of ln and the y boundaries of the appointment
  288. descriptions. Subtract out the top and bottom borders, and subtract
  289. out the external leading before the first ln to see how much useable
  290. space there is. Then divide to see how many ln will fit, and
  291. split the extra pixels between the top and the bottom.
  292. */
  293. cyUseable = vcyWnd2B - 2 * vcyBorder - vcyExtLead;
  294. vlnLast = (vcln = cyUseable / vcyLineToLine) - 1;
  295. vycoQdMax = (vycoQdFirst = 2 + (cyUseable % vcyLineToLine) / 2)
  296. + vcln * vcyLineToLine;
  297. /* Create window CalWnd0. */
  298. if(!(vhwnd0 = CreateWindow("CalWndMain",
  299. NULL,
  300. WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
  301. min(vcxWnd1+GSM(SM_CXFRAME)*2+vcxFont*3,
  302. GSM(SM_CXSCREEN)),
  303. min(vcyWnd1+GSM(SM_CYCAPTION)+ GSM(SM_CYFRAME)*2+
  304. GSM(SM_CYMENU)+(vcyFont*2),
  305. GSM(SM_CYSCREEN)),
  306. NULL, NULL,
  307. hInstance, NULL)))
  308. return CalTerminate(2);
  309. /* Create window CalWnd1. */
  310. if (!(vhwnd1 = CreateWindow ( "CalWndSub",
  311. NULL,
  312. WS_VISIBLE | WS_CHILD | WS_BORDER,
  313. XcoWnd1 (), YcoWnd1 (), vcxWnd1, vcyWnd1,
  314. vhwnd0, NULL, hInstance, NULL)))
  315. {
  316. DestroyWindow(vhwnd0);
  317. return FALSE;
  318. }
  319. /* Create window CalWnd2A. */
  320. if (!(vhwnd2A = CreateWindow ( "CalWndSub",
  321. NULL,
  322. WS_VISIBLE | WS_CHILD,
  323. 0, 0, vcxWnd2A, vcyWnd2A,
  324. vhwnd1, NULL, hInstance, NULL)))
  325. {
  326. DestroyWindow(vhwnd0);
  327. return FALSE;
  328. }
  329. #ifndef BUG_8560
  330. /* Create the scrollbar control as a child of hwnd2A */
  331. if (!(vhScrollWnd = CreateWindow ( "scrollbar",
  332. NULL,
  333. WS_VISIBLE | WS_CHILD | SBS_HORZ,
  334. vxcoLeftArrowFirst, 0, (vcxHScrollBar + vcxBorder)<<1, vcyWnd2A,
  335. vhwnd2A, (HMENU)IDHORZSCROLL, hInstance, NULL)))
  336. {
  337. DestroyWindow(vhwnd0);
  338. return FALSE;
  339. }
  340. #endif
  341. /* Create window CalWnd2B. Note - use width of vcxWnd1 - vcxBorder
  342. in order to overlay the right border of the scroll bar with the
  343. right border of Wnd1.
  344. */
  345. if (!(vhwnd2B = CreateWindow ( "CalWndSub",
  346. NULL,
  347. WS_VISIBLE | WS_CHILD | WS_VSCROLL| WS_HSCROLL,
  348. 0, vcyWnd2A, vcxWnd1 - vcxBorder, vcyWnd2B,
  349. vhwnd1, NULL, hInstance, NULL)))
  350. {
  351. DestroyWindow(vhwnd0);
  352. return FALSE;
  353. }
  354. hmScrollMax = 0;
  355. vmScrollPos = 0;
  356. vmScrollMax = 0;
  357. hmScrollPos = 0;
  358. /* Create window CalWnd2C. */
  359. if (!(vhwnd2C = CreateWindow ( "Edit",
  360. NULL,
  361. WS_VISIBLE | WS_CHILD | ES_MULTILINE,
  362. vxcoWnd2C = (vcxWnd2A - cxWnd2C) / 2,
  363. vycoWnd2C = vcyWnd1 - 2 * vcyBorder - cyWnd2C,
  364. cxWnd2C, cyWnd2C,
  365. vhwnd1, (HMENU)IDECNOTES, hInstance, NULL)))
  366. {
  367. DestroyWindow(vhwnd0);
  368. return FALSE;
  369. }
  370. /* limit text in notes area to number of chars that fit.
  371. * this is done to get around a bug in edit controls when
  372. * you paste in text which has tabs.
  373. * 05-Oct-1987. davidhab.
  374. */
  375. #if VARIABLENOTELENGTH
  376. SendMessage(vhwnd2C, EM_LIMITTEXT, (cyWnd2C / vcyFont) * (cxWnd2C / vcxFont)*2, 0L);
  377. #else
  378. SendMessage(vhwnd2C, EM_LIMITTEXT, CBNOTESMAX, 0L);
  379. #endif
  380. /* Create window CalWnd3. c-kraigb : ES_AUTOHSCROLL added to allow
  381. more text in the appointment area without having to alter the
  382. size of the entire layout.*/
  383. if (!(vhwnd3 = CreateWindow ( "Edit",
  384. NULL,
  385. WS_CHILD | ES_AUTOHSCROLL,
  386. 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
  387. vhwnd2B, (HMENU)IDECQD, hInstance, NULL)))
  388. {
  389. DestroyWindow(vhwnd0);
  390. return FALSE;
  391. }
  392. /* Limit the Appoinment Edit to it's maximum. 80 chars should be
  393. sufficient for all intensive purposes , c-kraigb
  394. */
  395. SendMessage(vhwnd3, EM_LIMITTEXT, CCHQDMAX, 0L);
  396. /* Make all the files look closed. */
  397. for (i=0; i < CFILE; i++)
  398. hFile[i]=-1;
  399. /* Get a handle for the tdd. Note - the tdd will get initialized
  400. when we call CleanSlate or LoadCal below.
  401. */
  402. //- Calinit: Changed Allocation because of bug in LocalReAlloc.
  403. //- vhlmTdd = LocalAlloc (LMEM_MOVEABLE, 0);
  404. /* Fetch the current date and time. */
  405. ReadClock(&vd3Cur, &vftCur.tm);
  406. vftCur.dt = DtFromPd3 (&vd3Cur);
  407. /* Set up the timer event for updating the time and date. */
  408. #ifdef DOTIMER
  409. if (!SetTimer (vhwnd0, 0, 1000, NULL))
  410. {
  411. AlertBox (vrgsz[IDS_NOTIMER], (CHAR *)NULL,
  412. MB_SYSTEMMODAL | MB_OK | MB_ICONHAND);
  413. DestroyWindow(vhwnd0);
  414. return FALSE;
  415. }
  416. #endif /* #ifdef DOTIMER */
  417. /* init. some fields of the OPENFILENAME struct used by fileopen and
  418. * filesaveas
  419. */
  420. /* changed to sizeof instead of constant. 18 Jan 1991 clarkc */
  421. vOFN.lStructSize = sizeof(OPENFILENAME);
  422. vOFN.hwndOwner = vhwnd0;
  423. vOFN.lpstrFileTitle = 0;
  424. vOFN.nMaxCustFilter = CCHFILTERMAX;
  425. vOFN.nFilterIndex = vFilterIndex;
  426. vOFN.nMaxFile = CCHFILESPECMAX;
  427. vOFN.lpfnHook = NULL;
  428. /* init fields of the PRINTDLG structure */
  429. /* changed to sizeof instead of constant. 18 Jan 1991 clarkc */
  430. vPD.lStructSize = sizeof(PRINTDLG);
  431. vPD.hwndOwner = vhwnd0;
  432. vPD.hDevMode = NULL;
  433. vPD.hDevNames = NULL;
  434. vPD.hDC = NULL;
  435. vPD.Flags = PD_NOSELECTION | PD_NOPAGENUMS; /* disable "pages" and "Selection" radiobuttons */
  436. vPD.nFromPage = 0;
  437. vPD.nToPage = 0;
  438. vPD.nMinPage = 0;
  439. vPD.nMaxPage = 0;
  440. vPD.nCopies = 1;
  441. /* determine the message number to be used for communication with
  442. * Find dialog
  443. */
  444. if (!(vHlpMsg = RegisterWindowMessage (HELPMSGSTRING)))
  445. return FALSE;
  446. /* Prevent grabbing of focus if we are coming up iconic. */
  447. vfNoGrabFocus = (cmdShow == SW_SHOWMINNOACTIVE);
  448. /* Initialize according to values from win.ini */
  449. CalWinIniChange();
  450. if (ProcessShellOptions(lpszCmdLine))
  451. {
  452. PostMessage(vhwnd0, WM_CLOSE, 0, 0L);
  453. return (TRUE);
  454. }
  455. else if (*lpszCmdLine == '\0') /* Not invoked with a file. */
  456. {
  457. CleanSlate (TRUE);
  458. }
  459. else
  460. {
  461. /* Try to load the file. */
  462. AddDefExt(lpszCmdLine);
  463. hFile [IDFILEORIGINAL] = MOpenFile (lpszCmdLine,
  464. (OFSTRUCT FAR *)&OFStruct [IDFILEORIGINAL], OF_READ);
  465. LoadCal ();
  466. }
  467. /* If we didn't grab the focus we need to set up vhwndFocus so
  468. we correctly set the focus when we get activated later on.
  469. Initially we are in day mode with the focus on the appointment
  470. edit control.
  471. */
  472. if (vfNoGrabFocus)
  473. {
  474. vhwndFocus = vhwnd3;
  475. vfNoGrabFocus = FALSE;
  476. }
  477. /* Make the windows visible. */
  478. ShowWindow (vhwnd0, cmdShow);
  479. return (TRUE);
  480. }
  481. BOOL APIENTRY ProcessShellOptions(
  482. LPSTR lpszCmdLine)
  483. {
  484. CHAR szFileName[80];
  485. AnsiUpper(lpszCmdLine);
  486. if (*lpszCmdLine != '/' || *lpszCmdLine != 'P')
  487. return FALSE;
  488. lpszCmdLine += 2;
  489. // skip blanks
  490. while (*lpszCmdLine == ' ' || *lpszCmdLine == '\t')
  491. lpszCmdLine++;
  492. if (!*lpszCmdLine)
  493. return FALSE;
  494. /* Get the filename. */
  495. lstrcpy(szFileName, lpszCmdLine);
  496. AddDefExt(szFileName);
  497. hFile[IDFILEORIGINAL] = MOpenFile (szFileName, &OFStruct [IDFILEORIGINAL],
  498. OF_READ);
  499. if (hFile[IDFILEORIGINAL] == -1)
  500. {
  501. AlertBox (vszCannotReadFile, szFileName, MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION);
  502. return TRUE;
  503. }
  504. LoadCal();
  505. // need to set the first and last dates for which appts have to be
  506. // printed.
  507. // Since the data structures are utterly incomprehensible,
  508. // the following method appeared to provide the easiest solution
  509. vdtFrom = DTFIRST; // from 1/1/1980
  510. vdtTo = DTLAST; // to December 31, 2099.
  511. FSearchTdd (vdtFrom, &vitddFirst); // first day in the file
  512. FSearchTdd (vdtTo, &vitddMax); // last day in the file
  513. Print ();
  514. return TRUE;
  515. }
  516. /**** AllocDr ****/
  517. BOOL APIENTRY AllocDr ()
  518. {
  519. register INT i;
  520. for (i=0; i < CDR; i++)
  521. {
  522. /* Note - the DRs get marked free by New. */
  523. if (!(vrghlmDr [i] = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, CBDRMAX)))
  524. return FALSE;
  525. }
  526. return TRUE;
  527. }
  528. /**** Return TRUE iff all bitmaps loaded. If we fail to load any bitmap,
  529. DeleteBitmaps will deleted the ones already loaded. */
  530. BOOL APIENTRY LoadBitmaps(HANDLE hInstance)
  531. {
  532. vhbmLeftArrow = LoadBitmap (NULL, MAKEINTRESOURCE (OBM_LFARROW));
  533. vhbmRightArrow = LoadBitmap (NULL, MAKEINTRESOURCE (OBM_RGARROW));
  534. vhbmBell = LoadBitmap (hInstance, MAKEINTRESOURCE(1));
  535. return (vhbmBell && vhbmLeftArrow && vhbmRightArrow);
  536. }
  537. /**** Delete bitmaps that have been loaded. Depends on handles having been
  538. initialized to 0. */
  539. VOID APIENTRY DeleteBitmaps()
  540. {
  541. if (vhbmBell)
  542. DeleteObject(vhbmBell);
  543. if (vhbmLeftArrow)
  544. DeleteObject(vhbmLeftArrow);
  545. if (vhbmRightArrow)
  546. DeleteObject(vhbmRightArrow);
  547. }
  548. /**** Destroy Global Objects.
  549. iLevel determines which objects will be deleted.
  550. Always returns FALSE */
  551. BOOL APIENTRY CalTerminate(INT iLevel)
  552. {
  553. /* Note case statement falls thru every arm. */
  554. switch (iLevel)
  555. {
  556. case 2:
  557. DeleteDC (vhDCMemory);
  558. case 1:
  559. DeleteBitmaps();
  560. case 0:
  561. DestroyBrushes();
  562. }
  563. /* Leave handy value in ax for calinit to return. */
  564. return FALSE;
  565. }