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.

2713 lines
84 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* Touched by : Diane K. Oh */
  4. /* On Date : June 11, 1992 */
  5. /* Revision remarks by Diane K. Oh ext #15201 */
  6. /* This file has been changed to comply with the Unicode standard */
  7. /* Following is a quick overview of what I have done. */
  8. /* */
  9. /* Was Changed it into Remark */
  10. /* === =============== ====== */
  11. /* CHAR TCHAR if it refers to text */
  12. /* LPCHAR & LPSTR LPTSTR if it refers to text */
  13. /* PSTR & NPSTR LPTSTR if it refers to text */
  14. /* "..." TEXT("...") compile time macro resolves it */
  15. /* '...' TEXT('...') same */
  16. /* */
  17. /* strlen lstrlen compile time macro resolves it */
  18. /* */
  19. /* Notes: */
  20. /* */
  21. /* 1. Added LPTSTR typecast before MAKEINTRESOURCE to remove warning */
  22. /* 2. Size was multiplied by sizeof(TCHAR) when allocating strings. */
  23. /* 3. WinMain has not been Unicode enabled so lpCmdLine parameter */
  24. /* remains as LPSTR type. */
  25. /* 4. Changed typecast from FARPROC to LPCFHOOKPROC to remove warning */
  26. /* */
  27. /****************************************************************************/
  28. #include <windows.h> /* required for all Windows applications */
  29. #include <stdlib.h>
  30. #include "commdlg.h"
  31. #include "shellapi.h"
  32. #include "clock.h" /* specific to this program */
  33. #if defined(JAPAN)
  34. #include <dlgs.h>
  35. #endif
  36. BOOL InitApplication (HANDLE);
  37. HRGN CreateEllipticWndRgn(HWND,LPRECT);
  38. LRESULT FAR PASCAL MainWndProc (HWND, UINT, WPARAM, LPARAM);
  39. #if defined(JAPAN)
  40. #define NATIVE_CHARSET SHIFTJIS_CHARSET
  41. UINT APIENTRY ExceptVerticalFont(HWND, UINT, UINT, LONG);
  42. #endif
  43. HANDLE hInst; /* current instance */
  44. void ParseSavedWindow(LPTSTR szBuf, PRECT pRect );
  45. void NEAR PASCAL DeleteTools (void);
  46. void NEAR PASCAL PrintShadowText (register HDC hDC, int nx, int ny, int sizex, int sizey, LPTSTR pszStr, int nStrLen, HDC hOffScrnDC);
  47. void NEAR PASCAL ClockSize (register HWND hWnd,int newWidth,int newHeight,WORD SizeWord);
  48. void NEAR PASCAL ClockTimerInterval (HWND hWnd);
  49. void NEAR PASCAL CompClockDim (void);
  50. void NEAR PASCAL ClockTimer (HWND hWnd);
  51. void NEAR PASCAL FormatTimeStr (void);
  52. void NEAR PASCAL ClockPaint (HWND hWnd, register HDC hDC, int hint);
  53. void NEAR PASCAL DrawFace (HDC hDC);
  54. void NEAR PASCAL DrawFatHand (register HDC hDC, int pos, HPEN hPen, BOOL hHand);
  55. void NEAR PASCAL DrawHand (register HDC hDC, int pos, HPEN hPen, int scale, int patMode);
  56. void NEAR PASCAL DrawIconBorder (HWND hWnd, register HDC hDC);
  57. void NEAR PASCAL FormatDateStr (xDATE *pDate, BOOL bRealShort);
  58. void NEAR PASCAL SizeFont (HWND hWnd, int newHeight, int newWidth);
  59. void NEAR PASCAL SetMenuBar (HWND hWnd);
  60. void NEAR PASCAL FormatInit (VOID);
  61. VOID NEAR PASCAL SaveClockOptions (HWND hWnd);
  62. void NEAR PASCAL ResetWinTitle (HWND hWnd);
  63. void NEAR PASCAL CreateTools (void);
  64. void NEAR PASCAL ClockCreate (HWND hWnd);
  65. TIME oTime;
  66. xDATE oDate;
  67. CLOCKDISPSTRUCT ClockDisp;
  68. LOGFONT FontStruct;
  69. typedef struct
  70. {
  71. SHORT x;
  72. SHORT y;
  73. } TRIG;
  74. #define FNOSHAD_MONOCHROME 1
  75. #define FNOSHAD_USERSAYSNO 2
  76. short fNoShadow = 0;
  77. BOOL bUtc = FALSE;
  78. BOOL bFirst = TRUE;
  79. BOOL bColor = TRUE;
  80. BOOL fShadedHands = FALSE;
  81. BOOL bNewFont = TRUE;
  82. BOOL bCantHide = FALSE;
  83. BOOL bTmpHide = FALSE;
  84. BOOL fDisplay = FALSE;
  85. TCHAR szBuffer[BUFLEN]; /* buffer for stringtable stuff */
  86. TCHAR szAppName[BUFLEN];
  87. TCHAR szIniFile[20];
  88. TCHAR szDfltFontFile[20];
  89. TCHAR szSection[30];
  90. TCHAR szFontFileKey[20];
  91. HBRUSH hbrColorWindow;
  92. HBRUSH hbrBtnHighlight;
  93. HBRUSH hbrForeground;
  94. HBRUSH hbrBlobColor;
  95. HFONT hFont = NULL;
  96. HFONT hFontDate = NULL;
  97. #define bDisplayDate (!ClockDisp.bNoDate && !ClockDisp.bIconic)
  98. RECT clockRect;
  99. RECT rCoordRect;
  100. TRIG clockCenter;
  101. HPEN hpenForeground;
  102. HPEN hpenShadow;
  103. HPEN hpenBackground;
  104. HPEN hpenBlobHlt;
  105. HPEN hpenRed;
  106. HCURSOR hCurWait;
  107. /* win.ini strings... Don't internationalize */
  108. TCHAR szMaximized[] = TEXT("Maximized");
  109. TCHAR szOptions[] = TEXT("Options");
  110. TCHAR szPosition[] = TEXT("Position");
  111. TCHAR szNoShadow[] = TEXT("NoShadow");
  112. #if defined(JAPAN)
  113. TCHAR szCharSet[] = TEXT("Charset");
  114. #endif
  115. int TimerID = 1; /* number used for timer-id */
  116. int clockRadius;
  117. int HorzRes;
  118. int VertRes;
  119. int aspectD;
  120. int aspectN;
  121. extern TRIG CirTab[];
  122. TRIG FAR *lpcirTab = CirTab;
  123. #if defined(JAPAN) || defined(KOREA)
  124. UINT FAR PASCAL ExceptVerticalFont(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  125. #endif
  126. void MoveTo (HDC hdc, int x, int y)
  127. {
  128. MoveToEx (hdc, x, y, NULL);
  129. }
  130. INT MyAtoi (LPTSTR Str)
  131. {
  132. CHAR szAnsi [160];
  133. BOOL fDefCharUsed;
  134. #ifdef UNICODE
  135. WideCharToMultiByte (CP_ACP, 0, Str, -1, szAnsi, 160, NULL, &fDefCharUsed);
  136. return (atoi (szAnsi));
  137. #else
  138. return (atoi (Str));
  139. #endif
  140. }
  141. /****************************************************************************
  142. FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  143. PURPOSE: calls initialization function, processes message loop
  144. COMMENTS:
  145. Windows recognizes this function by name as the initial entry point
  146. for the program. This function calls the application initialization
  147. routine, if no other instance of the program is running, and always
  148. calls the instance initialization routine. It then executes a message
  149. retrieval and dispatch loop that is the top-level control structure
  150. for the remainder of execution. The loop is terminated when a WM_QUIT
  151. message is received, at which time this function exits the application
  152. instance by returning the value passed by PostQuitMessage().
  153. If this function must abort before entering the message loop, it
  154. returns the conventional value NULL.
  155. ****************************************************************************/
  156. int APIENTRY WinMain (HINSTANCE hInstance,
  157. HINSTANCE hPrevInstance,
  158. LPSTR lpCmdLine,
  159. int nCmdShow)
  160. {
  161. MSG msg; /* message */
  162. HDC hDC;
  163. HWND hWnd;
  164. HMENU hMenu;
  165. int iMaximized;
  166. TCHAR szParseStr [80];
  167. TIME nTime;
  168. LPTSTR szTooMany;
  169. TCHAR szTopmost [80];
  170. #ifdef JAPAN
  171. int i;
  172. #endif
  173. UNREFERENCED_PARAMETER( lpCmdLine );
  174. hInst = hInstance;
  175. FormatInit ();
  176. if (!InitApplication (hInstance)) /* Initialize shared things */
  177. return (FALSE); /* Exits if unable to initialize */
  178. /* Perform initializations that apply to a specific instance */
  179. LoadString (hInstance, IDS_APPNAME, szAppName, BUFLEN);
  180. LoadString (hInstance, IDS_USNAME, szSection, 30);
  181. LoadString (hInstance, IDS_INIFILE, szIniFile, 20);
  182. ClockCreate ((HWND)NULL);
  183. hDC = GetDC (NULL);
  184. if ((UINT)GetDeviceCaps (hDC, NUMCOLORS) <= 2)
  185. fNoShadow = FNOSHAD_MONOCHROME;
  186. ReleaseDC (NULL, hDC);
  187. if (GetPrivateProfileInt (szSection, szNoShadow, 0, szIniFile))
  188. fNoShadow |= FNOSHAD_USERSAYSNO;
  189. /* get window position and size from ini file */
  190. GetPrivateProfileString (szSection, szPosition, TEXT(""), szParseStr,
  191. 80, szIniFile);
  192. ParseSavedWindow (szParseStr, &rCoordRect);
  193. hWnd = CreateWindow (szSection, /* The class name. */
  194. szSection, /* The window instance name. */
  195. WS_TILEDWINDOW,
  196. rCoordRect.left, rCoordRect.top,
  197. rCoordRect.right, rCoordRect.bottom,
  198. NULL,
  199. NULL,
  200. hInstance,
  201. NULL);
  202. // Loop if control panel time being changed.
  203. GetTime (&oTime);
  204. do
  205. {
  206. GetTime (&nTime);
  207. }
  208. while (nTime.second == oTime.second && nTime.minute == oTime.minute &&
  209. nTime.hour24 == oTime.hour24);
  210. GetDate (&oDate);
  211. if (!SetTimer (hWnd, TimerID, OPEN_TLEN, 0L))
  212. {
  213. /* Windows only supports 16 public timers */
  214. szTooMany = (LPTSTR) LocalAlloc (LPTR, 160 * sizeof(TCHAR));
  215. LoadString (hInstance, IDS_TOOMANY, szTooMany, 160);
  216. MessageBox ((HWND)NULL, szTooMany, szBuffer, MB_OK | MB_ICONHAND | MB_SYSTEMMODAL);
  217. DeleteTools ();
  218. return (FALSE);
  219. }
  220. /* get font choice from ini file */
  221. #ifdef JAPAN
  222. lstrcpy (szDfltFontFile, TEXT("System"));
  223. #else
  224. LoadString (hInstance, IDS_FONTFILE, szDfltFontFile, 20);
  225. #endif
  226. LoadString (hInstance, IDS_FONTCHOICE, szFontFileKey, 20);
  227. GetPrivateProfileString (szSection, szFontFileKey, szDfltFontFile,
  228. FontStruct.lfFaceName, 20, szIniFile);
  229. FontStruct.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
  230. #ifdef JAPAN
  231. if (!(i = GetPrivateProfileInt(szSection, szCharSet,
  232. ANSI_CHARSET, szIniFile)))
  233. FontStruct.lfCharSet = ANSI_CHARSET;
  234. else
  235. FontStruct.lfCharSet = i;
  236. #else
  237. FontStruct.lfCharSet = ANSI_CHARSET;
  238. #endif
  239. FontStruct.lfWeight = FW_NORMAL;
  240. FontStruct.lfQuality = DEFAULT_QUALITY;
  241. FontStruct.lfUnderline = FALSE;
  242. FontStruct.lfStrikeOut = FALSE;
  243. FontStruct.lfEscapement = 0;
  244. FontStruct.lfOrientation = 0;
  245. FontStruct.lfOutPrecision = OUT_DEFAULT_PRECIS;
  246. FontStruct.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  247. #ifdef JAPAN
  248. /* We can use only NATIVE_CHARSET */
  249. if (FontStruct.lfCharSet != NATIVE_CHARSET)
  250. {
  251. FontStruct.lfCharSet = NATIVE_CHARSET;
  252. lstrcpy (FontStruct.lfFaceName, TEXT("System"));
  253. }
  254. #endif
  255. /* get clock options from ini file */
  256. GetPrivateProfileString (szSection, szOptions, TEXT(""), szParseStr, 80, szIniFile);
  257. ParseSavedFlags (szParseStr, &ClockDisp);
  258. FormatTimeStr ();
  259. FormatDateStr (&oDate, ClockDisp.bIconic);
  260. hMenu = GetMenu (hWnd);
  261. /* Check the default menu item either analog or digital */
  262. CheckMenuItem (hMenu, ClockDisp.wFormat, MF_BYCOMMAND | MF_CHECKED);
  263. if (ClockDisp.wFormat == IDM_ANALOG)
  264. EnableMenuItem( hMenu, IDM_SETFONT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  265. if (!ClockDisp.bNoSeconds)
  266. {
  267. CheckMenuItem (hMenu, IDM_SECONDS, MF_BYCOMMAND | MF_CHECKED);
  268. ClockTimerInterval (hWnd);
  269. }
  270. if (!ClockDisp.bNoDate)
  271. {
  272. CheckMenuItem (hMenu, IDM_DATE, MF_BYCOMMAND | MF_CHECKED);
  273. ResetWinTitle (hWnd);
  274. }
  275. hMenu = GetSystemMenu (hWnd, FALSE);
  276. AppendMenu (hMenu, MF_SEPARATOR, 0, NULL);
  277. LoadString (hInstance, IDS_TOPMOST, szTopmost, 79);
  278. if (ClockDisp.bTopMost)
  279. {
  280. AppendMenu (hMenu, MF_ENABLED | MF_CHECKED | MF_STRING, IDM_TOPMOST,
  281. szTopmost);
  282. SetWindowPos (hWnd, (HWND)-1, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  283. }
  284. else
  285. AppendMenu (hMenu, MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST,
  286. szTopmost);
  287. if (ClockDisp.bNoTitle)
  288. SetMenuBar (hWnd);
  289. if (!ClockDisp.bIconic)
  290. {
  291. iMaximized = GetPrivateProfileInt (szSection, szMaximized, 0, szIniFile);
  292. if (iMaximized)
  293. ShowWindow (hWnd, SW_MAXIMIZE);
  294. else
  295. {
  296. ShowWindow (hWnd, nCmdShow);
  297. GetWindowRect (hWnd, &rCoordRect);
  298. }
  299. }
  300. else
  301. ShowWindow (hWnd, SW_MINIMIZE);
  302. /* Acquire and dispatch messages until a WM_QUIT message is received. */
  303. while (GetMessage (&msg, /* message structure */
  304. NULL, /* handle of window receiving the message */
  305. 0, /* lowest message to examine */
  306. 0)) /* highest message to examine */
  307. {
  308. TranslateMessage (&msg); /* Translates virtual key codes */
  309. DispatchMessage (&msg); /* Dispatches message to window */
  310. }
  311. return (int)(msg.wParam); /* Returns the value from PostQuitMessage */
  312. hPrevInstance; //UNUSED
  313. nCmdShow; //UNUSED
  314. }
  315. /****************************************************************************
  316. FUNCTION: InitApplication(HANDLE)
  317. PURPOSE: Initializes window data and registers window class
  318. COMMENTS:
  319. This function is called at initialization time only if no other
  320. instances of the application are running. This function performs
  321. initialization tasks that can be done once for any number of running
  322. instances.
  323. In this case, we initialize a window class by filling out a data
  324. structure of type WNDCLASS and calling the Windows RegisterClass()
  325. function. Since all instances of this application use the same window
  326. class, we only need to do this when the first instance is initialized.
  327. ****************************************************************************/
  328. BOOL InitApplication (HANDLE hInstance) /* current instance */
  329. {
  330. WNDCLASS ClockClass;
  331. /* Fill in window class structure with parameters that describe the */
  332. /* main window. */
  333. ClockClass.cbClsExtra = ClockClass.cbWndExtra = 0;
  334. ClockClass.lpszClassName = TEXT("Clock");
  335. ClockClass.lpszMenuName = TEXT("Clock"); //szSection;
  336. ClockClass.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  337. ClockClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  338. ClockClass.hInstance = hInstance;
  339. ClockClass.lpfnWndProc = MainWndProc;
  340. ClockClass.hCursor = LoadCursor (NULL, IDC_ARROW);
  341. ClockClass.hIcon = NULL;
  342. /* Register the window class and return success/failure code. */
  343. return (RegisterClass (&ClockClass));
  344. }
  345. /****************************************************************************
  346. FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  347. PURPOSE: Processes messages
  348. MESSAGES:
  349. WM_COMMAND - application menu (About dialog box)
  350. WM_DESTROY - destroy window
  351. ****************************************************************************/
  352. LRESULT APIENTRY MainWndProc (HWND hWnd, /* window handle */
  353. UINT message, /* type of message */
  354. WPARAM wParam, /* additional information */
  355. LPARAM lParam) /* additional information */
  356. {
  357. HMENU hMenu;
  358. PAINTSTRUCT ps;
  359. switch (message)
  360. {
  361. case WM_COMMAND:
  362. switch (LOWORD (wParam))
  363. {
  364. case IDM_ANALOG:
  365. case IDM_DIGITAL:
  366. if (LOWORD (wParam) != ClockDisp.wFormat)
  367. {
  368. /* Switch flag to other choice */
  369. hMenu = GetMenu(hWnd);
  370. CheckMenuItem(hMenu, ClockDisp.wFormat, MF_BYCOMMAND | MF_UNCHECKED);
  371. CheckMenuItem(hMenu, ClockDisp.wFormat = (WORD)wParam, MF_BYCOMMAND | MF_CHECKED);
  372. if (wParam == IDM_ANALOG)
  373. EnableMenuItem (hMenu, IDM_SETFONT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  374. else
  375. EnableMenuItem (hMenu, IDM_SETFONT, MF_BYCOMMAND | MF_ENABLED);
  376. ResetWinTitle (hWnd);
  377. InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  378. }
  379. break;
  380. case IDM_SETFONT:
  381. {
  382. CHOOSEFONT cf;
  383. short cy, nOldFontHeight;
  384. #ifdef JAPAN
  385. /* Win 3.1 */
  386. LOGFONT OldFontStruct;
  387. #endif
  388. /* calls the font chooser (in commdlg)
  389. */
  390. cf.lStructSize = sizeof (CHOOSEFONT);
  391. cf.hwndOwner = hWnd;
  392. cf.hInstance = hInst;
  393. cf.lpTemplateName = (LPTSTR) MAKEINTRESOURCE(IDD_FONT);
  394. cf.hDC = NULL;
  395. cf.lpLogFont = &FontStruct;
  396. FontStruct.lfItalic = 0;
  397. FontStruct.lfWeight = FW_NORMAL;
  398. cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT |
  399. #ifdef JAPAN
  400. CF_NOSIMULATIONS | CF_ENABLETEMPLATE |
  401. #else
  402. CF_NOSIMULATIONS | CF_ANSIONLY | CF_ENABLETEMPLATE |
  403. #endif
  404. CF_NOVECTORFONTS;
  405. #if defined(JAPAN)
  406. /* except vertical font from list */
  407. cf.Flags |= CF_ENABLEHOOK;
  408. cf.lpfnHook = (LPCFHOOKPROC)ExceptVerticalFont;
  409. #else
  410. cf.lpfnHook = (LPCFHOOKPROC) NULL;
  411. #endif
  412. #ifdef JAPAN
  413. /* Win 3.1 */
  414. OldFontStruct = FontStruct;
  415. #endif
  416. nOldFontHeight = (short) FontStruct.lfHeight;
  417. cy = HIWORD (GetDialogBaseUnits ());
  418. /* 36 is the (height - 1) of the stc5 static control in font.dlg template */
  419. if (((36 * cy) / 8) < -FontStruct.lfHeight)
  420. FontStruct.lfHeight = -((36 * cy) / 8);
  421. if (ChooseFont (&cf))
  422. {
  423. #if defined(JAPAN) || defined(KOREA)
  424. /* We can use only NATIVE_CHARSET */
  425. if (FontStruct.lfCharSet != NATIVE_CHARSET)
  426. {
  427. FontStruct = OldFontStruct;
  428. break;
  429. }
  430. #endif
  431. /* write new font info to ini file */
  432. WritePrivateProfileString (szSection, szFontFileKey,
  433. FontStruct.lfFaceName, szIniFile);
  434. bNewFont = TRUE;
  435. InvalidateRect(hWnd, NULL, TRUE);
  436. }
  437. else /* restore old height */
  438. FontStruct.lfHeight = nOldFontHeight;
  439. break;
  440. }
  441. case IDM_UTC:
  442. hMenu = GetMenu(hWnd);
  443. if (!bUtc)
  444. {
  445. bUtc = TRUE;
  446. CheckMenuItem(hMenu, IDM_UTC, MF_BYCOMMAND | MF_CHECKED);
  447. }
  448. else
  449. {
  450. bUtc = FALSE;
  451. CheckMenuItem (hMenu, IDM_UTC, MF_BYCOMMAND | MF_UNCHECKED);
  452. }
  453. // call FormatInit to add or remove am/pm string (utc
  454. // doesn't have it, non-utc does)
  455. FormatInit();
  456. ResetWinTitle (hWnd);
  457. FormatTimeStr ();
  458. bNewFont = TRUE;
  459. InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  460. ClockTimer (hWnd);
  461. break;
  462. case IDM_NOTITLE:
  463. goto toggle_title;
  464. case IDM_SECONDS:
  465. /* toggle seconds option
  466. */
  467. hMenu = GetMenu (hWnd);
  468. if (ClockDisp.bNoSeconds)
  469. {
  470. CheckMenuItem (hMenu, IDM_SECONDS, MF_BYCOMMAND | MF_CHECKED);
  471. ClockDisp.bNoSeconds = FALSE;
  472. }
  473. else
  474. {
  475. CheckMenuItem (hMenu, IDM_SECONDS, MF_BYCOMMAND | MF_UNCHECKED);
  476. ClockDisp.bNoSeconds = TRUE;
  477. }
  478. ClockTimerInterval (hWnd);
  479. FormatTimeStr ();
  480. bNewFont = TRUE;
  481. InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  482. break;
  483. case IDM_DATE:
  484. /* toggles date option
  485. */
  486. hMenu = GetMenu (hWnd);
  487. if (ClockDisp.bNoDate)
  488. {
  489. CheckMenuItem (hMenu, IDM_DATE, MF_BYCOMMAND | MF_CHECKED);
  490. ClockDisp.bNoDate = FALSE;
  491. }
  492. else
  493. {
  494. CheckMenuItem (hMenu, IDM_DATE, MF_BYCOMMAND | MF_UNCHECKED);
  495. ClockDisp.bNoDate = TRUE;
  496. }
  497. bNewFont = TRUE;
  498. if (ClockDisp.wFormat == IDM_DIGITAL)
  499. InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
  500. else
  501. ResetWinTitle (hWnd);
  502. break;
  503. case IDM_ABOUT:
  504. ShellAbout(hWnd, szAppName, TEXT(""), LoadIcon(hInst, TEXT("cckk")));
  505. break;
  506. default:
  507. goto defproc;
  508. }
  509. break;
  510. case WM_MOUSEACTIVATE:
  511. /* right button temporarily hides the window if topmost is
  512. * enabled (window re-appears when right button is released).
  513. * When this happens, we don't want to activate the clock window
  514. * just before hiding it (it would look really bad), so we
  515. * intercept the activate message.
  516. */
  517. if (GetAsyncKeyState (VK_RBUTTON) & 0x8000)
  518. return (MA_NOACTIVATE);
  519. else
  520. goto defproc;
  521. break;
  522. case WM_INITMENU:
  523. bCantHide = TRUE;
  524. goto defproc;
  525. case WM_MENUSELECT:
  526. if (LOWORD (lParam) == -1 && HIWORD(lParam) == 0)
  527. bCantHide = FALSE;
  528. goto defproc;
  529. case WM_RBUTTONDOWN:
  530. case WM_NCRBUTTONDOWN:
  531. /* right button temporarily hides the window, if the window
  532. * is topmost, and if no menu is currently "active"
  533. */
  534. if (!bTmpHide && ClockDisp.bTopMost && !bCantHide)
  535. {
  536. ShowWindow (hWnd, SW_HIDE);
  537. SetCapture (hWnd);
  538. bTmpHide = TRUE;
  539. }
  540. break;
  541. case WM_RBUTTONUP:
  542. case WM_NCRBUTTONUP:
  543. /* if window is currently hidden, right button up brings it
  544. * back. Must make sure we show it in its previous state - ie:
  545. * minimized, maximized or normal.
  546. */
  547. if (bTmpHide)
  548. {
  549. ReleaseCapture ();
  550. if (ClockDisp.bIconic)
  551. ShowWindow (hWnd, SW_SHOWMINNOACTIVE);
  552. else if (IsZoomed (hWnd))
  553. ShowWindow (hWnd, SW_SHOWMAXIMIZED);
  554. else
  555. ShowWindow (hWnd, SW_SHOWNOACTIVATE);
  556. bTmpHide = FALSE;
  557. }
  558. break;
  559. case WM_KEYDOWN:
  560. /* ESC key toggles the menu/title bar (just like a double click
  561. * on the client area of the window.
  562. */
  563. if ((wParam == VK_ESCAPE) && !(HIWORD (lParam) & 0x4000))
  564. goto toggle_title;
  565. break;
  566. case WM_NCLBUTTONDBLCLK:
  567. if (!ClockDisp.bNoTitle)
  568. /* if we have title bars etc. let the normal sutff take place */
  569. goto defproc;
  570. /* else: no title bars, then this is actually a request to bring
  571. * the title bars back...
  572. */
  573. /* fall through */
  574. case WM_LBUTTONDBLCLK:
  575. toggle_title:
  576. fDisplay = FALSE;
  577. ClockDisp.bNoTitle = (ClockDisp.bNoTitle ? FALSE : TRUE);
  578. SetMenuBar (hWnd);
  579. break;
  580. case WM_NCHITTEST:
  581. /* if we have no title/menu bar, clicking and dragging the client
  582. * area moves the window. To do this, return HTCAPTION.
  583. * Note dragging not allowed if window maximized, or if caption
  584. * bar is present.
  585. */
  586. wParam = DefWindowProc(hWnd, message, wParam, lParam);
  587. if (ClockDisp.bNoTitle && (wParam == HTCLIENT) && !IsZoomed(hWnd))
  588. return HTCAPTION;
  589. else
  590. return wParam;
  591. case WM_SIZE:
  592. bNewFont = TRUE;
  593. ClockSize(hWnd, (int) LOWORD (lParam), (int) HIWORD (lParam), (WORD) wParam);
  594. UpdateWindow(hWnd);
  595. break;
  596. case WM_QUERYDRAGICON:
  597. return (LRESULT) LoadIcon (hInst, TEXT("cckk"));
  598. case WM_DESTROY:
  599. {
  600. HCURSOR hTempCursor;
  601. KillTimer (hWnd, TimerID);
  602. DeleteTools ();
  603. if (hFont)
  604. DeleteObject (hFont);
  605. if (hFontDate)
  606. DeleteObject (hFontDate);
  607. if (ClockDisp.hBitmap)
  608. DeleteObject (ClockDisp.hBitmap);
  609. SetCapture (hWnd);
  610. hTempCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  611. SaveClockOptions (hWnd);
  612. PostQuitMessage (0);
  613. break;
  614. }
  615. case WM_WININICHANGE:
  616. FormatInit ();
  617. FormatDateStr (&oDate, ClockDisp.bIconic);
  618. ResetWinTitle (hWnd);
  619. FormatTimeStr ();
  620. bNewFont = TRUE;
  621. InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  622. break;
  623. case WM_PAINT:
  624. /* 25-Mar-1987. Added to force total repaint to solve
  625. * problem of garbage under second hand when hidden
  626. * by menu or popup.
  627. */
  628. InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  629. fDisplay = FALSE;
  630. BeginPaint (hWnd, &ps);
  631. ClockPaint (hWnd, ps.hdc, REPAINT);
  632. EndPaint (hWnd, &ps);
  633. break;
  634. case WM_TIMECHANGE:
  635. /* Redraw. */
  636. oDate.day = 0;
  637. InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  638. /* fall through */
  639. case WM_TIMER:
  640. ClockTimer (hWnd);
  641. break;
  642. case WM_SYSCOMMAND:
  643. switch (wParam)
  644. {
  645. case SC_MINIMIZE:
  646. if (!IsZoomed (hWnd))
  647. GetWindowRect (hWnd, &rCoordRect);
  648. if (ClockDisp.bTopMost)
  649. {
  650. ClockDisp.bTopMost = FALSE;
  651. PostMessage (hWnd, WM_SYSCOMMAND, IDM_TOPMOST, 0L);
  652. }
  653. break;
  654. case SC_MAXIMIZE:
  655. if (!IsIconic (hWnd))
  656. GetWindowRect (hWnd, &rCoordRect);
  657. break;
  658. case IDM_TOPMOST:
  659. {
  660. /* toggles topmost option
  661. */
  662. hMenu = GetSystemMenu (hWnd, FALSE);
  663. if (ClockDisp.bTopMost)
  664. {
  665. CheckMenuItem (hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_UNCHECKED);
  666. SetWindowPos (hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  667. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  668. ClockDisp.bTopMost = FALSE;
  669. }
  670. else
  671. {
  672. CheckMenuItem (hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_CHECKED);
  673. SetWindowPos (hWnd, HWND_TOPMOST, 0, 0, 0, 0,
  674. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  675. ClockDisp.bTopMost = TRUE;
  676. }
  677. break;
  678. }
  679. }
  680. return (DefWindowProc(hWnd, message, wParam, lParam));
  681. break;
  682. case WM_SYSCOLORCHANGE:
  683. DeleteTools ();
  684. CreateTools ();
  685. break;
  686. case WM_ERASEBKGND:
  687. {
  688. RECT rect;
  689. HBRUSH hBr;
  690. DWORD rgbCol;
  691. HDC hDC;
  692. GetClientRect (hWnd, &rect);
  693. hDC = GetDC (hWnd);
  694. SetBkMode (hDC, OPAQUE);
  695. /* Make a temp brush to color the background. This is to
  696. * force use of a solid color so the hand motion is painted
  697. * correctly.
  698. */
  699. rgbCol = GetNearestColor(hDC, GetSysColor(COLOR_BTNFACE));
  700. /* CHECK RETURN VALUE!! */
  701. hBr = CreateSolidBrush(rgbCol);
  702. FillRect((HDC)wParam, &rect, hBr);
  703. ReleaseDC (hWnd, hDC);
  704. DeleteObject(hBr);
  705. break;
  706. }
  707. case WM_ENDSESSION:
  708. if (wParam)
  709. SaveClockOptions (hWnd);
  710. break;
  711. default: /* Passes it on if unproccessed */
  712. defproc:
  713. return (DefWindowProc (hWnd, message, wParam, lParam));
  714. }
  715. return (0);
  716. }
  717. /*
  718. * ResetWinTitle() - Sets the window title with the date if appropriate
  719. *
  720. * The date is part of the window text when the clock is minimized, or when
  721. * it is analog, and the date option is selected.
  722. */
  723. void NEAR PASCAL ResetWinTitle (HWND hWnd)
  724. {
  725. TCHAR szNewTitle[BUFLEN+20];
  726. if (((ClockDisp.wFormat == IDM_DIGITAL) && !ClockDisp.bIconic)
  727. || ClockDisp.bNoDate)
  728. SetWindowText (hWnd, szAppName); /* no date in title if digital */
  729. else
  730. {
  731. wsprintf (szNewTitle, TEXT("%s - %s"), szAppName, ClockDisp.szDate);
  732. SetWindowText (hWnd, szNewTitle);
  733. }
  734. }
  735. void NEAR PASCAL CreateTools (void)
  736. {
  737. #define BLOB_COLOR RGB (0,128,128)
  738. hbrForeground = CreateSolidBrush (GetSysColor (COLOR_BTNSHADOW));
  739. hbrColorWindow = CreateSolidBrush (GetSysColor (COLOR_BTNFACE));
  740. hbrBtnHighlight= CreateSolidBrush (GetSysColor (COLOR_BTNHIGHLIGHT));
  741. hbrBlobColor = CreateSolidBrush (BLOB_COLOR);
  742. hpenForeground = CreatePen (0, 1, GetSysColor (COLOR_WINDOWTEXT));
  743. hpenShadow = CreatePen (0, 1, GetSysColor (COLOR_BTNSHADOW));
  744. hpenBackground = CreatePen (0, 1, GetSysColor (COLOR_BTNFACE));
  745. hpenBlobHlt = CreatePen (0, 1, RGB (0,255,255));
  746. hpenRed = CreatePen (0, 1, RGB (255, 0, 0));
  747. hCurWait = LoadCursor (NULL, IDC_WAIT);
  748. }
  749. void NEAR PASCAL ClockCreate (HWND hWnd)
  750. {
  751. register HDC hDC;
  752. int HorzSize;
  753. int VertSize;
  754. hDC = GetDC (hWnd);
  755. VertRes = GetDeviceCaps (hDC, VERTRES);
  756. HorzRes = GetDeviceCaps (hDC, HORZRES);
  757. VertSize= GetDeviceCaps (hDC, VERTSIZE);
  758. HorzSize= GetDeviceCaps (hDC, HORZSIZE);
  759. ReleaseDC (hWnd, hDC);
  760. aspectN = MulDiv (VertRes, 100, VertSize);
  761. aspectD = MulDiv (HorzRes, 100, HorzSize);
  762. CreateTools ();
  763. }
  764. /*
  765. * ClockTimerInterval()
  766. *
  767. * Sets the timer interval. Two things affect this interval:
  768. * 1) if the window is iconic, or
  769. * 2) if Seconds option has been disabled
  770. * In both cases, timer ticks occur every half-minute. Otherwise, timer
  771. * every half-second.
  772. * Gets the flags from ClockDisp structure.
  773. */
  774. void PASCAL ClockTimerInterval (HWND hWnd)
  775. {
  776. if (ClockDisp.bIconic || ClockDisp.bNoSeconds)
  777. {
  778. /* Update once every 1/2 minute in the iconic state, or if
  779. * seconds display suppressed
  780. */
  781. KillTimer (hWnd, TimerID);
  782. SetTimer (hWnd, TimerID, (WORD)ICON_TLEN, 0L);
  783. }
  784. else
  785. {
  786. /* Update every 1/2 second in the opened state. */
  787. KillTimer (hWnd, TimerID);
  788. SetTimer (hWnd, TimerID, OPEN_TLEN, 0L);
  789. }
  790. }
  791. /*
  792. * ClockTimer()
  793. *
  794. * msg - timer ID
  795. *
  796. * Called by windows to tell CLOCK there has been a time change.
  797. *
  798. */
  799. void NEAR PASCAL ClockTimer (HWND hWnd)
  800. {
  801. HDC hDC;
  802. TIME nTime;
  803. xDATE nDate;
  804. GetTime (&nTime);
  805. GetDate (&nDate);
  806. if (fDisplay)
  807. return;
  808. if (ClockDisp.bNoSeconds || ClockDisp.bIconic)
  809. {
  810. KillTimer (hWnd, TimerID);
  811. SetTimer (hWnd, TimerID, (WORD)(61 - nTime.second) * 100, 0L);
  812. }
  813. /* It's possible to change any part of the system at any time
  814. * through the Control Panel. So we check everything.
  815. */
  816. if (((nTime.second == oTime.second) || ClockDisp.bIconic || ClockDisp.bNoSeconds) &&
  817. (nTime.minute == oTime.minute) &&
  818. (nTime.hour24 == oTime.hour24) &&
  819. ((nDate.day == oDate.day &&
  820. nDate.month == oDate.month &&
  821. nDate.year == oDate.year ) || ClockDisp.bNoDate))
  822. return;
  823. hDC = GetDC (hWnd);
  824. ClockPaint (hWnd, hDC, HANDPAINT);
  825. ReleaseDC (hWnd, hDC);
  826. }
  827. VOID GetTime (TIME * pTime)
  828. {
  829. SYSTEMTIME st;
  830. if (bUtc)
  831. GetSystemTime (&st);
  832. else
  833. GetLocalTime (&st);
  834. if (st.wHour > 11)
  835. pTime->ampm = 1;
  836. else
  837. pTime->ampm = 0;
  838. if (st.wHour == 0 && !ClockDisp.wTimeFormat)
  839. st.wHour = 12;
  840. pTime->hour = st.wHour;
  841. pTime->hour24 = pTime->hour12 = st.wHour;
  842. if (pTime->hour12 > 12)
  843. pTime->hour12 -= 12;
  844. pTime->minute = st.wMinute;
  845. pTime->second = st.wSecond;
  846. }
  847. void NEAR GetDate (xDATE * pDate)
  848. {
  849. SYSTEMTIME st;
  850. if (bUtc)
  851. GetSystemTime(&st);
  852. else
  853. GetLocalTime(&st);
  854. pDate->day= st.wDay;
  855. pDate->month= st.wMonth;
  856. pDate->year= st.wYear;
  857. }
  858. /*
  859. * FormatTimeStr()
  860. *
  861. * Creates a template for the time, based on options in the ClockDisp
  862. * structure. ie: seconds or no seconds, AM/PM string, etc.
  863. * The result is used in ExtTextOut calls to determine the size of the
  864. * time string.
  865. * Note that this is based on the assumption that digits are fixed pitch
  866. * (and so '8' is used as a dummy digit).
  867. * Bad things will happen if the selected font has proportional digits!!!
  868. */
  869. void NEAR PASCAL FormatTimeStr (void)
  870. {
  871. LPTSTR pstr;
  872. int i;
  873. TCHAR szAMPM[MAX_AMPM_LEN];
  874. TCHAR szTime[MAX_TIME_SEP + MAX_AMPM_LEN + 8];
  875. int iAMPMLen;
  876. pstr = ClockDisp.szTimeFmt;
  877. if (!ClockDisp.bIconic)
  878. {
  879. /*
  880. * Build the widest possible AM/PM string.
  881. * This assumes the widest proportional character is M.
  882. */
  883. iAMPMLen = ClockDisp.nMaxAMPMLen;
  884. for (i = 0; i < iAMPMLen; i++)
  885. {
  886. szAMPM[i] = TEXT('M');
  887. }
  888. if (ClockDisp.wAMPMPosition && iAMPMLen)
  889. {
  890. /*
  891. * Length includes a space, so write the space to the
  892. * buffer instead of the M.
  893. */
  894. szAMPM[i - 1] = TEXT(' ');
  895. }
  896. szAMPM[i] = TEXT('\0');
  897. /*
  898. * Get the Time string.
  899. */
  900. wsprintf (szTime, TEXT("88%c88"), ClockDisp.szTimeSep[0]);
  901. if (!ClockDisp.bNoSeconds)
  902. {
  903. wsprintf (szTime + 5, TEXT("%c88"), ClockDisp.szTimeSep[0]);
  904. }
  905. lstrcat (szTime, TEXT(" "));
  906. /*
  907. * Build the actual format string in the proper order.
  908. */
  909. if (ClockDisp.wAMPMPosition)
  910. {
  911. lstrcpy (pstr, szAMPM);
  912. lstrcat (pstr, szTime);
  913. }
  914. else
  915. {
  916. lstrcpy (pstr, szTime);
  917. lstrcat (pstr, szAMPM);
  918. }
  919. }
  920. else
  921. {
  922. /*
  923. * Icon - only show hours and minutes.
  924. */
  925. wsprintf (pstr, TEXT("88%c88"), ClockDisp.szTimeSep[0] );
  926. }
  927. /*
  928. * Remove trailing space, if necessary.
  929. */
  930. ClockDisp.nTimeLen = lstrlen (pstr);
  931. if (pstr[ClockDisp.nTimeLen - 1] == TEXT(' '))
  932. {
  933. ClockDisp.nTimeLen--;
  934. pstr[ClockDisp.nTimeLen] = TEXT('\0');
  935. }
  936. }
  937. /*
  938. * ClockPaint()
  939. */
  940. void NEAR PASCAL ClockPaint (HWND hWnd, register HDC hDC, int hint)
  941. {
  942. int hour;
  943. RECT Rect;
  944. TIME nTime;
  945. xDATE nDate;
  946. TCHAR szTime[6];
  947. HDC hTmpDC = NULL;
  948. HBITMAP hOldBM;
  949. HFONT h;
  950. GetTime (&nTime);
  951. GetDate (&nDate);
  952. if ((nDate.day != oDate.day) ||
  953. (nDate.month != oDate.month) ||
  954. (nDate.year != oDate.year))
  955. {
  956. /* new date - so reformat date string */
  957. FormatDateStr (&nDate, ClockDisp.bIconic);
  958. ResetWinTitle (hWnd);
  959. bNewFont = TRUE;
  960. }
  961. if (ClockDisp.wFormat == IDM_DIGITAL)
  962. {
  963. /*******************/
  964. /* Digital Display */
  965. /*******************/
  966. /* Is the font ready yet? */
  967. if (!hFont || bNewFont)
  968. {
  969. GetClientRect (hWnd, &Rect);
  970. /* Create a suitable font */
  971. SizeFont (hWnd, Rect.bottom - Rect.top, Rect.right - Rect.left);
  972. bNewFont = FALSE;
  973. }
  974. if (hFont)
  975. h = SelectObject (hDC, hFont);
  976. else
  977. h = 0;
  978. SetBkColor (hDC, GetSysColor (COLOR_BTNFACE));
  979. SetTextAlign (hDC, TA_LEFT);
  980. if (ClockDisp.wShdwOff && (hTmpDC = CreateCompatibleDC (hDC)))
  981. {
  982. /* we will want to print shadowed text. Attempt to allocate
  983. * the offscreen DC and bitmap for this.
  984. */
  985. if (!(hOldBM = SelectObject (hTmpDC, ClockDisp.hBitmap)))
  986. {
  987. /* select failed. Perhaps the bitmap was discarded.
  988. * So attempt to reallocate a bitmap
  989. */
  990. DeleteObject (ClockDisp.hBitmap);
  991. ClockDisp.hBitmap = CreateDiscardableBitmap (hDC,
  992. 2*ClockDisp.nSizeChar + 2*ClockDisp.wShdwOff,
  993. ClockDisp.nSizeY);
  994. if (!ClockDisp.hBitmap ||
  995. !(hOldBM = SelectObject (hTmpDC, ClockDisp.hBitmap)))
  996. {
  997. /* either we couldn't re-allocate the bitmap, or the
  998. * select failed again (ie: not because the bitmap
  999. * was discarded). Either way, we can't use an offscreen.
  1000. */
  1001. DeleteDC (hTmpDC);
  1002. hTmpDC = NULL;
  1003. }
  1004. }
  1005. if (hTmpDC)
  1006. {
  1007. /* we can use our offscreen. Prepare it for use.
  1008. */
  1009. if (hFont)
  1010. SelectObject (hTmpDC, hFont);
  1011. SetBkColor (hTmpDC, GetSysColor (COLOR_BTNFACE));
  1012. SetTextAlign (hTmpDC, TA_LEFT);
  1013. }
  1014. }
  1015. if (hint == REPAINT || ClockDisp.bIconic)
  1016. {
  1017. SelectObject (hDC, hbrColorWindow);
  1018. /* Set old values as undefined, so entire clock updated. */
  1019. oTime.hour24 = 25;
  1020. oTime.minute = 60;
  1021. oTime.ampm = 2;
  1022. oDate.day = 0;
  1023. /* paint the separators */
  1024. PrintShadowText (hDC,
  1025. ClockDisp.nPosSep1,
  1026. ClockDisp.nPosY,
  1027. ClockDisp.nSizeSep,
  1028. ClockDisp.nSizeY,
  1029. &ClockDisp.szTimeSep[0],
  1030. 1,
  1031. hTmpDC);
  1032. if (!ClockDisp.bIconic && !ClockDisp.bNoSeconds)
  1033. PrintShadowText (hDC,
  1034. ClockDisp.nPosSep2,
  1035. ClockDisp.nPosY,
  1036. ClockDisp.nSizeSep,
  1037. ClockDisp.nSizeY,
  1038. &ClockDisp.szTimeSep[0],
  1039. 1,
  1040. hTmpDC);
  1041. }
  1042. if (!ClockDisp.bIconic)
  1043. {
  1044. if (ClockDisp.wAMPMPosition)
  1045. {
  1046. /*
  1047. * AM/PM - Prefix.
  1048. */
  1049. if ((oTime.ampm != nTime.ampm) || (oTime.hour24 != nTime.hour24))
  1050. {
  1051. Rect.left = ClockDisp.nPosAMPM;
  1052. Rect.top = ClockDisp.nPosY;
  1053. Rect.right = ClockDisp.nPosHr + ClockDisp.nSizeChar;
  1054. Rect.bottom = ClockDisp.nPosY + ClockDisp.nSizeY;
  1055. FillRect (hDC, &Rect, hbrColorWindow);
  1056. }
  1057. }
  1058. else
  1059. {
  1060. /*
  1061. * AM/PM - Suffix.
  1062. */
  1063. if (oTime.ampm != nTime.ampm)
  1064. {
  1065. PrintShadowText (hDC,
  1066. ClockDisp.nPosAMPM,
  1067. ClockDisp.nPosY,
  1068. ClockDisp.nSizeAMPM,
  1069. ClockDisp.nSizeY,
  1070. ClockDisp.szAMPM[nTime.ampm],
  1071. lstrlen (ClockDisp.szAMPM[nTime.ampm]),
  1072. hTmpDC);
  1073. }
  1074. }
  1075. }
  1076. if (!ClockDisp.bIconic && !ClockDisp.bNoSeconds)
  1077. {
  1078. /* paint the seconds */
  1079. szTime[0] = TEXT('0') + nTime.second / 10;
  1080. szTime[1] = TEXT('0') + nTime.second % 10;
  1081. PrintShadowText (hDC,
  1082. ClockDisp.nPosSec,
  1083. ClockDisp.nPosY,
  1084. 2 * ClockDisp.nSizeChar,
  1085. ClockDisp.nSizeY,
  1086. szTime,
  1087. 2,
  1088. hTmpDC);
  1089. }
  1090. if (oTime.minute != nTime.minute)
  1091. {
  1092. /* paint the minutes */
  1093. szTime[0] = TEXT('0') + nTime.minute / 10;
  1094. szTime[1] = TEXT('0') + nTime.minute % 10;
  1095. PrintShadowText (hDC,
  1096. ClockDisp.nPosMin,
  1097. ClockDisp.nPosY,
  1098. 2 * ClockDisp.nSizeChar,
  1099. ClockDisp.nSizeY,
  1100. szTime,
  1101. 2,
  1102. hTmpDC);
  1103. }
  1104. if (oTime.hour24 != nTime.hour24)
  1105. {
  1106. /* paint the hours */
  1107. if (ClockDisp.wTimeFormat)
  1108. hour = nTime.hour24;
  1109. else
  1110. hour = nTime.hour12;
  1111. szTime[0] = TEXT('0') + hour / 10;
  1112. szTime[1] = TEXT('0') + hour % 10;
  1113. /* Kill Leading zero if needed. */
  1114. if (ClockDisp.wTimeLZero == 0 && szTime[0] == TEXT('0'))
  1115. {
  1116. PrintShadowText (hDC,
  1117. ClockDisp.nPosHr + ClockDisp.nSizeChar,
  1118. ClockDisp.nPosY,
  1119. ClockDisp.nSizeChar,
  1120. ClockDisp.nSizeY,
  1121. szTime + 1,
  1122. 1,
  1123. hTmpDC);
  1124. if ((oTime.hour12 > 9) ||
  1125. (ClockDisp.wTimeFormat && (oTime.hour24 > 9)))
  1126. {
  1127. /* if we just switched from 12 to 1 (or 11 to 0),
  1128. * erase leading 1
  1129. */
  1130. Rect.left = ClockDisp.nPosHr;
  1131. Rect.top = ClockDisp.nPosY;
  1132. Rect.right = ClockDisp.nPosHr + ClockDisp.nSizeChar;
  1133. Rect.bottom = ClockDisp.nPosY + ClockDisp.nSizeY;
  1134. FillRect (hDC, &Rect, hbrColorWindow);
  1135. }
  1136. }
  1137. else
  1138. {
  1139. PrintShadowText (hDC,
  1140. ClockDisp.nPosHr,
  1141. ClockDisp.nPosY,
  1142. 2 * ClockDisp.nSizeChar,
  1143. ClockDisp.nSizeY,
  1144. szTime,
  1145. 2,
  1146. hTmpDC);
  1147. }
  1148. }
  1149. if (ClockDisp.wAMPMPosition && !ClockDisp.bIconic)
  1150. {
  1151. if ((oTime.ampm != nTime.ampm) || (oTime.hour24 != nTime.hour24))
  1152. {
  1153. int hh;
  1154. if (ClockDisp.wTimeFormat)
  1155. hour = nTime.hour24;
  1156. else
  1157. hour = nTime.hour12;
  1158. szTime[0] = TEXT('0') + hour / 10;
  1159. /* Kill Leading zero if needed. */
  1160. if (ClockDisp.wTimeLZero == 0 && szTime[0] == TEXT('0'))
  1161. hh = ClockDisp.nSizeChar;
  1162. else
  1163. hh = 0;
  1164. PrintShadowText (hDC,
  1165. ClockDisp.nPosAMPM + hh,
  1166. ClockDisp.nPosY,
  1167. ClockDisp.nSizeAMPM,
  1168. ClockDisp.nSizeY,
  1169. ClockDisp.szAMPM[nTime.ampm],
  1170. lstrlen (ClockDisp.szAMPM[nTime.ampm]),
  1171. hTmpDC);
  1172. }
  1173. }
  1174. if (hTmpDC)
  1175. {
  1176. SelectObject (hDC, hOldBM);
  1177. DeleteDC (hTmpDC);
  1178. hTmpDC = NULL;
  1179. }
  1180. if ((oDate.day != nDate.day ||
  1181. oDate.month != nDate.month ||
  1182. oDate.year != nDate.year) && bDisplayDate)
  1183. {
  1184. /* paint the date - first erase old string, 'cause new string
  1185. * may be shorter. Problem: we no longer know the extent of
  1186. * the old string, so paint the whole x-extent of the clock
  1187. * window. Don't worry, this doesn't happen too often. */
  1188. GetClientRect (hWnd, &Rect);
  1189. Rect.top = ClockDisp.nPosDateY;
  1190. Rect.bottom = ClockDisp.nPosDateY + ClockDisp.nSizeDateY;
  1191. FillRect (hDC, &Rect, hbrColorWindow);
  1192. if (hFontDate)
  1193. h = SelectObject (hDC, hFontDate);
  1194. else
  1195. h = 0;
  1196. PrintShadowText (hDC,
  1197. ClockDisp.nPosDateX,
  1198. ClockDisp.nPosDateY,
  1199. ClockDisp.nSizeDateX,
  1200. ClockDisp.nSizeDateY,
  1201. ClockDisp.szDate,
  1202. ClockDisp.nDateLen,
  1203. hTmpDC);
  1204. }
  1205. if (h)
  1206. SelectObject(hDC, h);
  1207. }
  1208. else
  1209. {
  1210. /******************/
  1211. /* Analog display */
  1212. /******************/
  1213. if (hint == REPAINT)
  1214. {
  1215. SetBkMode (hDC, TRANSPARENT);
  1216. DrawFace (hDC);
  1217. if (!ClockDisp.bIconic)
  1218. {
  1219. DrawFatHand (hDC, oTime.hour * 5 + (oTime.minute / 12), hpenForeground, HHAND);
  1220. DrawFatHand (hDC, oTime.minute, hpenForeground, MHAND);
  1221. }
  1222. else
  1223. {
  1224. DrawHand (hDC, oTime.hour * 5 + (oTime.minute / 12), hpenForeground, HOURSCALE, R2_COPYPEN);
  1225. DrawHand (hDC, oTime.minute, hpenForeground, MINUTESCALE, R2_COPYPEN);
  1226. }
  1227. if (!ClockDisp.bIconic && !ClockDisp.bNoSeconds)
  1228. /* Draw the second hand. */
  1229. DrawHand (hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT);
  1230. /* NOTE: Don't update oTime in this case! */
  1231. if (ClockDisp.bIconic)
  1232. DrawIconBorder (hWnd, hDC);
  1233. return;
  1234. }
  1235. else if (hint == HANDPAINT)
  1236. {
  1237. SetBkMode(hDC, TRANSPARENT);
  1238. if ((!ClockDisp.bIconic && !ClockDisp.bNoSeconds) && nTime.second != oTime.second)
  1239. /* Erase the old second hand. */
  1240. DrawHand (hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT);
  1241. if (nTime.minute != oTime.minute || nTime.hour != oTime.hour)
  1242. {
  1243. if (ClockDisp.bIconic)
  1244. {
  1245. DrawHand (hDC, oTime.minute, hpenBackground, MINUTESCALE, R2_COPYPEN);
  1246. DrawHand (hDC, oTime.hour * 5 + (oTime.minute / 12), hpenBackground, HOURSCALE, R2_COPYPEN);
  1247. DrawHand (hDC, nTime.minute, hpenForeground, MINUTESCALE, R2_COPYPEN);
  1248. DrawHand (hDC, nTime.hour * 5 + (nTime.minute / 12), hpenForeground, HOURSCALE, R2_COPYPEN);
  1249. }
  1250. else
  1251. {
  1252. DrawFatHand (hDC, oTime.hour * 5 + (oTime.minute/12), hpenBackground, HHAND);
  1253. DrawFatHand (hDC, oTime.minute, hpenBackground, MHAND);
  1254. DrawFatHand (hDC, (nTime.hour) * 5 + (nTime.minute / 12), hpenForeground, HHAND);
  1255. DrawFatHand (hDC, nTime.minute, hpenForeground, MHAND);
  1256. }
  1257. }
  1258. if ((!ClockDisp.bIconic && !ClockDisp.bNoSeconds) && nTime.second != oTime.second)
  1259. /* Draw new second hand */
  1260. DrawHand (hDC, nTime.second, hpenBackground, SECONDSCALE, R2_NOT);
  1261. }
  1262. }
  1263. if (ClockDisp.bIconic)
  1264. DrawIconBorder (hWnd, hDC);
  1265. oTime = nTime;
  1266. oDate = nDate;
  1267. }
  1268. void Adjust (POINT * rgpt, INT cPoint, INT iDelta)
  1269. {
  1270. INT i;
  1271. for (i = 0; i < cPoint; i++)
  1272. {
  1273. rgpt[i].x += iDelta;
  1274. rgpt[i].y += iDelta;
  1275. }
  1276. }
  1277. /*
  1278. * DrawFatHand() - Draws either hour or minute hand.
  1279. */
  1280. void NEAR PASCAL DrawFatHand (register HDC hDC, int pos, HPEN hPen, BOOL hHand)
  1281. {
  1282. register int m;
  1283. int n;
  1284. int scale;
  1285. TRIG tip;
  1286. TRIG stip;
  1287. BOOL fErase;
  1288. SetROP2 (hDC, 13);
  1289. fErase = (hPen == hpenBackground);
  1290. SelectObject (hDC, hPen);
  1291. scale = hHand ? 7 : 5;
  1292. n = (pos + 15) % 60;
  1293. m = MulDiv (clockRadius, scale, 100);
  1294. stip.y = (SHORT) MulDiv (lpcirTab[n].y, m, 8000);
  1295. stip.x = (SHORT) MulDiv (lpcirTab[n].x, m, 8000);
  1296. scale = hHand ? 65 : 80;
  1297. tip.y = (SHORT) MulDiv (lpcirTab[pos % 60].y, MulDiv (clockRadius, scale, 100), 8000);
  1298. tip.x = (SHORT) MulDiv (lpcirTab[pos % 60].x, MulDiv (clockRadius, scale, 100), 8000);
  1299. {
  1300. POINT rgpt[4];
  1301. HBRUSH hbrInit;
  1302. rgpt[0].x = clockCenter.x + stip.x;
  1303. rgpt[0].y = clockCenter.y + stip.y;
  1304. rgpt[1].x = clockCenter.x + tip.x;
  1305. rgpt[1].y = clockCenter.y + tip.y;
  1306. rgpt[2].x = clockCenter.x - stip.x;
  1307. rgpt[2].y = clockCenter.y - stip.y;
  1308. scale = hHand ? 15 : 20;
  1309. n = (pos + 30) % 60;
  1310. m = MulDiv (clockRadius, scale, 100);
  1311. tip.y = (SHORT) MulDiv (lpcirTab[n].y, m, 8000);
  1312. tip.x = (SHORT) MulDiv (lpcirTab[n].x, m, 8000);
  1313. rgpt[3].x = clockCenter.x + tip.x;
  1314. rgpt[3].y = clockCenter.y + tip.y;
  1315. SelectObject (hDC, GetStockObject (NULL_PEN));
  1316. if (fErase)
  1317. {
  1318. hbrInit = SelectObject (hDC, hbrColorWindow);
  1319. }
  1320. if (fShadedHands)
  1321. {
  1322. Adjust (rgpt, 4, -2);
  1323. if (!fErase)
  1324. {
  1325. hbrInit = SelectObject (hDC, hbrBtnHighlight);
  1326. }
  1327. Polygon(hDC, rgpt, 4);
  1328. if (!fErase)
  1329. {
  1330. SelectObject (hDC, hbrForeground);
  1331. }
  1332. Adjust (rgpt, 4, 4);
  1333. Polygon (hDC, rgpt, 4);
  1334. Adjust (rgpt, 4, -2);
  1335. }
  1336. if (!fErase)
  1337. {
  1338. SelectObject (hDC, hbrBlobColor);
  1339. }
  1340. Polygon (hDC, rgpt, 4);
  1341. /*
  1342. * if we selected a brush in, reset it now.
  1343. */
  1344. if (fErase || fShadedHands) {
  1345. SelectObject(hDC, hbrInit);
  1346. }
  1347. }
  1348. }
  1349. /*
  1350. * DrawFace()
  1351. */
  1352. void NEAR PASCAL DrawFace(HDC hDC)
  1353. {
  1354. int i;
  1355. RECT tRect;
  1356. TRIG * ppt;
  1357. int blobHeight, blobWidth;
  1358. blobWidth = MulDiv (MAXBLOBWIDTH, (clockRect.right - clockRect.left), HorzRes);
  1359. blobHeight = MulDiv (blobWidth, aspectN, aspectD);
  1360. if (blobHeight < 2)
  1361. blobHeight = 1;
  1362. if (blobWidth < 2)
  1363. blobWidth = 2;
  1364. InflateRect (&clockRect, -(blobHeight >> 1), -(blobWidth >> 1));
  1365. clockRadius = (int) ((clockRect.right - clockRect.left-8) >> 1);
  1366. clockCenter.y = (SHORT) (clockRect.top + ((clockRect.bottom - clockRect.top) >> 1) - 1);
  1367. clockCenter.x = (SHORT) (clockRect.left + clockRadius+3);
  1368. for (i = 0; i < 60; i++)
  1369. {
  1370. ppt = lpcirTab + i;
  1371. tRect.top = MulDiv (ppt->y, clockRadius, 8000) + clockCenter.y;
  1372. tRect.left = MulDiv (ppt->x, clockRadius, 8000) + clockCenter.x;
  1373. fShadedHands = FALSE;
  1374. if (i % 5)
  1375. {
  1376. /* Draw a dot. */
  1377. if (blobWidth > 2 && blobHeight >= 2)
  1378. {
  1379. fShadedHands = TRUE;
  1380. tRect.right = tRect.left + 2;
  1381. tRect.bottom = tRect.top + 2;
  1382. FillRect (hDC, &tRect, GetStockObject (WHITE_BRUSH));
  1383. OffsetRect (&tRect, -1, -1);
  1384. FillRect (hDC, &tRect, hbrForeground);
  1385. tRect.left++;
  1386. tRect.top++;
  1387. FillRect (hDC, &tRect, hbrColorWindow);
  1388. }
  1389. }
  1390. else if (!ClockDisp.bIconic)
  1391. {
  1392. tRect.right = tRect.left + blobWidth;
  1393. tRect.bottom = tRect.top + blobHeight;
  1394. OffsetRect (&tRect, -(blobWidth >> 1) , -(blobHeight >> 1));
  1395. SelectObject (hDC, GetStockObject (BLACK_PEN));
  1396. SelectObject (hDC, hbrBlobColor);
  1397. Rectangle (hDC, tRect.left, tRect.top, tRect.right, tRect.bottom);
  1398. SelectObject (hDC, hpenBlobHlt);
  1399. MoveTo (hDC, tRect.left, tRect.bottom-1);
  1400. LineTo (hDC, tRect.left, tRect.top);
  1401. LineTo (hDC, tRect.right-1, tRect.top);
  1402. }
  1403. else
  1404. {
  1405. PatBlt (hDC, tRect.left, tRect.top, 2, 2, BLACKNESS);
  1406. PatBlt (hDC, tRect.left, tRect.top, 1, 1, WHITENESS);
  1407. }
  1408. }
  1409. InflateRect (&clockRect, (blobHeight >> 1), (blobWidth >> 1));
  1410. }
  1411. /*
  1412. * DrawIconBorder() - Draws a Border around either icon-clock.
  1413. */
  1414. void NEAR PASCAL DrawIconBorder (HWND hWnd, register HDC hDC)
  1415. {
  1416. RECT Rect;
  1417. /* draws a "sunk-in" border, ie: double black outline top and left,
  1418. * single white outline bottom and right.
  1419. */
  1420. GetClientRect (hWnd, &Rect);
  1421. SelectObject (hDC, GetStockObject (BLACK_PEN));
  1422. MoveTo (hDC, Rect.left, Rect.top + 1);
  1423. LineTo (hDC, Rect.left, Rect.bottom - 1);
  1424. MoveTo (hDC, Rect.left+1, Rect.bottom - 1);
  1425. LineTo (hDC, Rect.right - 1, Rect.bottom - 1);
  1426. MoveTo (hDC, Rect.right - 1, Rect.bottom - 2);
  1427. LineTo (hDC, Rect.right - 1, Rect.top);
  1428. MoveTo (hDC, Rect.right - 2, Rect.top);
  1429. LineTo (hDC, Rect.left, Rect.top);
  1430. MoveTo (hDC, Rect.left + 2, Rect.top + 2);
  1431. LineTo (hDC, Rect.left + 2, Rect.bottom - 3);
  1432. LineTo (hDC, Rect.right - 3, Rect.bottom - 3);
  1433. LineTo (hDC, Rect.right - 3, Rect.top + 2);
  1434. LineTo (hDC, Rect.left + 2, Rect.top + 2);
  1435. SelectObject (hDC, hpenRed);
  1436. MoveTo (hDC, Rect.left + 1, Rect.top + 1);
  1437. LineTo (hDC, Rect.left + 1, Rect.bottom - 2);
  1438. LineTo (hDC, Rect.right - 2, Rect.bottom - 2);
  1439. LineTo (hDC, Rect.right - 2, Rect.top + 1);
  1440. LineTo (hDC, Rect.left + 1, Rect.top + 1);
  1441. }
  1442. /*
  1443. * FormatDateStr() - prepare the formatted date string
  1444. *
  1445. * parameters:
  1446. * xDATE *pDate - structure contains current date
  1447. * BOOL bRealShort - if TRUE, the year is not added to the string (ie:
  1448. * only use the day and the month)
  1449. *
  1450. * This will format the given date according to the format specified
  1451. * by the current Locale, and place the result in ClockDisp.szDate.
  1452. */
  1453. void NEAR PASCAL FormatDateStr (xDATE * pDate, BOOL bRealShort)
  1454. {
  1455. register int i = 0, j = 0;
  1456. BOOL bLead;
  1457. TCHAR cSep;
  1458. while (ClockDisp.szDateFmt[i] && (j < MAX_DATE_LEN - 1))
  1459. {
  1460. bLead = FALSE;
  1461. switch (cSep = ClockDisp.szDateFmt[i++])
  1462. {
  1463. case TEXT('d'):
  1464. while (ClockDisp.szDateFmt[i] == TEXT('d'))
  1465. {
  1466. bLead = TRUE;
  1467. i++;
  1468. }
  1469. if (bLead || (pDate->day / 10))
  1470. ClockDisp.szDate[j++] = TEXT('0') + pDate->day / 10;
  1471. ClockDisp.szDate[j++] = TEXT('0') + pDate->day % 10;
  1472. break;
  1473. case TEXT('M'):
  1474. while (ClockDisp.szDateFmt[i] == TEXT('M'))
  1475. {
  1476. bLead = TRUE;
  1477. i++;
  1478. }
  1479. if (bLead || (pDate->month / 10))
  1480. ClockDisp.szDate[j++] = TEXT('0') + pDate->month / 10;
  1481. ClockDisp.szDate[j++] = TEXT('0') + pDate->month % 10;
  1482. break;
  1483. case TEXT('y'):
  1484. i++;
  1485. if (ClockDisp.szDateFmt[i] == TEXT('y'))
  1486. {
  1487. bLead = TRUE;
  1488. i+=2;
  1489. }
  1490. if (bLead && !bRealShort)
  1491. {
  1492. ClockDisp.szDate[j++] = (pDate->year < 2000 ? TEXT('1') : TEXT('2'));
  1493. ClockDisp.szDate[j++] = (pDate->year < 2000 ? TEXT('9') : TEXT('0'));
  1494. }
  1495. if (!bRealShort)
  1496. {
  1497. ClockDisp.szDate[j++] = TEXT('0') + (pDate->year % 100) / 10;
  1498. ClockDisp.szDate[j++] = TEXT('0') + (pDate->year % 100) % 10;
  1499. }
  1500. break;
  1501. default:
  1502. /* copy the current character into the formatted string - it
  1503. * is a separator. BUT: don't copy a separator into the
  1504. * very first position (could happen if the year comes first,
  1505. * but we're not using the year)
  1506. */
  1507. if (j)
  1508. ClockDisp.szDate[j++] = cSep;
  1509. break;
  1510. }
  1511. }
  1512. while ((ClockDisp.szDate[j-1] < TEXT('0')) || (ClockDisp.szDate[j-1] > TEXT('9')))
  1513. j--;
  1514. ClockDisp.szDate[j] = TEXT('\0');
  1515. ClockDisp.nDateLen = j;
  1516. }
  1517. /*
  1518. * PrintShadowText()
  1519. *
  1520. * Parameters:
  1521. * HDC hdc - the window DC
  1522. * int nx, ny, sizex, sizey - position and extent of bounding box
  1523. * PSTR pszStr - actual string to print
  1524. * int nStrLen - length of pszStr
  1525. * HDC hOffScrnDC - an offscreen DC used to paint the shadowed text.
  1526. * If this is NULL, the text is not shadowed.
  1527. * Assumes the bitmap associated with this DC can
  1528. * contain 2 digits. If the specified bounding box
  1529. * does not fit in the bitmap, the shadowed text is
  1530. * painted directly to the window DC (may cause flashing)
  1531. *
  1532. * Shadowed text is: a white highlight top and left, dark highlight bottom
  1533. * and right. The character itself is painted the same color as the background
  1534. * (so only noticeable if both highlights are noticeable).
  1535. */
  1536. void NEAR PASCAL PrintShadowText (register HDC hDC, int nx, int ny,
  1537. int sizex, int sizey, LPTSTR pszStr,
  1538. int nStrLen, HDC hOffScrnDC)
  1539. {
  1540. RECT Rect;
  1541. register WORD Shadow;
  1542. if (!hOffScrnDC || fNoShadow)
  1543. {
  1544. /* If no valid offscreen DC is provided, then we can NOT print
  1545. * shadowed text. Simply print the normal font.
  1546. */
  1547. SetTextColor (hDC, GetSysColor (COLOR_BTNTEXT));
  1548. Rect.top = ny;
  1549. Rect.bottom = ny + sizey;
  1550. Rect.left = nx;
  1551. Rect.right = nx + sizex;
  1552. ExtTextOut (hDC, nx, ny, ETO_OPAQUE | ETO_CLIPPED, &Rect,
  1553. pszStr, nStrLen, NULL);
  1554. }
  1555. else if (sizex > 2 * ClockDisp.nSizeChar)
  1556. {
  1557. /* print the shadowed text (but don't use offscreen bitmap because
  1558. * the string is too long to fit)
  1559. */
  1560. Shadow = ClockDisp.wShdwOff;
  1561. SetTextColor (hDC, GetSysColor (COLOR_BTNHIGHLIGHT));
  1562. Rect.top = ny - Shadow;
  1563. Rect.bottom = ny + sizey + Shadow;
  1564. Rect.left = nx - Shadow;
  1565. Rect.right = nx + sizex + Shadow;
  1566. ExtTextOut (hDC, nx - Shadow, ny - Shadow,
  1567. ETO_OPAQUE | ETO_CLIPPED, &Rect, pszStr, nStrLen, NULL);
  1568. SetBkMode (hDC, TRANSPARENT);
  1569. SetTextColor (hDC, GetSysColor (COLOR_BTNSHADOW));
  1570. ExtTextOut (hDC, nx + Shadow, ny + Shadow,
  1571. ETO_CLIPPED, &Rect, pszStr, nStrLen, NULL);
  1572. SetTextColor (hDC, GetSysColor (COLOR_BTNFACE));
  1573. ExtTextOut (hDC, nx, ny, ETO_CLIPPED, &Rect, pszStr, nStrLen, NULL);
  1574. }
  1575. else
  1576. {
  1577. /* use the off-screen bitmap, and print shadowed text. */
  1578. Shadow = ClockDisp.wShdwOff;
  1579. Rect.left = 0;
  1580. Rect.right = sizex + 2* Shadow;
  1581. Rect.top = 0;
  1582. Rect.bottom = sizey + 2* Shadow;
  1583. SetTextColor (hOffScrnDC, GetSysColor (COLOR_BTNHIGHLIGHT));
  1584. ExtTextOut (hOffScrnDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, &Rect, pszStr,
  1585. nStrLen, NULL);
  1586. SetBkMode (hOffScrnDC, TRANSPARENT);
  1587. SetTextColor (hOffScrnDC, GetSysColor (COLOR_BTNSHADOW));
  1588. ExtTextOut (hOffScrnDC, 2 * Shadow, 2* Shadow,
  1589. ETO_CLIPPED, &Rect, pszStr, nStrLen, NULL);
  1590. SetTextColor (hOffScrnDC, GetSysColor (COLOR_BTNFACE));
  1591. ExtTextOut (hOffScrnDC, Shadow, Shadow,
  1592. ETO_CLIPPED, &Rect, pszStr, nStrLen, NULL);
  1593. BitBlt (hDC, nx-Shadow, ny-Shadow,
  1594. Rect.right, Rect.bottom, hOffScrnDC, 0, 0, SRCCOPY);
  1595. }
  1596. }
  1597. /*
  1598. * SizeFont() - size font according to window size
  1599. *
  1600. * Only useful in digital mode.
  1601. * Create a font that will fit the current time format (based on the
  1602. * time template). Center the string, set up the positions for the
  1603. * different components of the time string.
  1604. * Do the same for the date, unless that option is disabled.
  1605. * 2 results:
  1606. * fonts are created. The font handles are stored in global variables
  1607. * string is positioned. Results are stored in the ClockDisp structure
  1608. * (ie: starting positions and extents)
  1609. */
  1610. void NEAR PASCAL SizeFont(HWND hWnd, int newHeight, int newWidth)
  1611. {
  1612. register HDC hDC;
  1613. SIZE sizeTimeExt;
  1614. SIZE sizeDateExt;
  1615. int nzExts[ 15 ];
  1616. #ifdef JAPAN // #1208:6/1/93:
  1617. int bFit;
  1618. LOGFONT wkFontStruct;
  1619. #endif
  1620. int nOldFit, nFit, i;
  1621. int nAMPMIndx = 0;
  1622. int iAMPMLen;
  1623. int DesiredWidth;
  1624. int DesiredHeight;
  1625. int InitialHeight;
  1626. HCURSOR hOldCur;
  1627. HFONT h;
  1628. if (ClockDisp.wFormat == IDM_DIGITAL)
  1629. {
  1630. hOldCur = SetCursor (hCurWait);
  1631. hDC = GetDC(hWnd);
  1632. if (hFont != NULL)
  1633. DeleteObject (hFont);
  1634. if (ClockDisp.bIconic) /* Adjust for fat border */
  1635. {
  1636. newWidth -= 4;
  1637. newHeight -= 4;
  1638. }
  1639. /* use up 7/8 of the x-extent of the window */
  1640. DesiredWidth = (newWidth * 7) / 8;
  1641. if (bDisplayDate)
  1642. /* display the date with the time - time only occupied a third
  1643. * of the screen height
  1644. */
  1645. DesiredHeight = 3 * newHeight / 8;
  1646. else
  1647. /* no date - time occupies two-thirds the screen height */
  1648. DesiredHeight = 7 * newHeight / 8;
  1649. if (ClockDisp.bIconic) /* Readjust for fat border */
  1650. {
  1651. newWidth += 4;
  1652. newHeight += 4;
  1653. }
  1654. /* create initial font real big, for more precision in calculations.
  1655. * This will give us an extent for out string, we can then figure
  1656. * out the correct font height to fit the string (using a ratio).
  1657. */
  1658. InitialHeight = 1000;
  1659. FontStruct.lfWidth = 0; /* don't stretch fonts */
  1660. FontStruct.lfHeight = -InitialHeight;
  1661. #ifdef JAPAN
  1662. /* In Win 3.0 if the following were not done some unexpected font
  1663. * maybe selected in special cases. Especially in Japan with
  1664. * vertical writing.
  1665. */
  1666. FontStruct.lfEscapement = 0;
  1667. FontStruct.lfOrientation = 0;
  1668. #endif
  1669. #if defined(JAPAN) || defined(KOREA)
  1670. /* We can use only NATIVE_CHARSET */
  1671. if (FontStruct.lfCharSet != NATIVE_CHARSET)
  1672. {
  1673. FontStruct.lfCharSet = NATIVE_CHARSET;
  1674. lstrcpy (FontStruct.lfFaceName, TEXT("System"));
  1675. }
  1676. #endif
  1677. hFont = CreateFontIndirect(&FontStruct);
  1678. if (hFont)
  1679. h = SelectObject(hDC, hFont);
  1680. else
  1681. h = 0;
  1682. GetTextExtentPoint (hDC, ClockDisp.szTimeFmt, ClockDisp.nTimeLen, &sizeTimeExt);
  1683. if (bDisplayDate)
  1684. GetTextExtentPoint (hDC, ClockDisp.szDate, ClockDisp.nDateLen, &sizeDateExt);
  1685. if (h)
  1686. SelectObject(hDC, h);
  1687. /* compute appropriate font for time string:
  1688. * establish a ratio current size to required size.
  1689. * This may yield a font too tall to fit the window, so limit
  1690. * the font height.
  1691. */
  1692. FontStruct.lfHeight = -MulDiv (InitialHeight, DesiredWidth,
  1693. sizeTimeExt.cx);
  1694. if (-FontStruct.lfHeight > DesiredHeight)
  1695. FontStruct.lfHeight = -DesiredHeight;
  1696. // pre-initialize nzExts in case this for loop doesn't execute
  1697. // (in really small cy cases).
  1698. for (i = 0; i < 15; nzExts[i] = 0, i++);
  1699. #ifdef JAPAN // #1208:6/1/93:
  1700. bFit = FALSE;
  1701. wkFontStruct = FontStruct;
  1702. #endif
  1703. for (nOldFit = 0, nFit = -1; FontStruct.lfHeight < 0;)
  1704. {
  1705. nOldFit = nFit;
  1706. /* little loop to take care of round-off errors, which may
  1707. * cause our initial "guess" to be slightly too large. So
  1708. * check that the string fits (in most cases it will),
  1709. * otherwise, re-create the font in a slightly smaller size.
  1710. */
  1711. if (hFont)
  1712. DeleteObject (hFont);
  1713. hFont = CreateFontIndirect(&FontStruct);
  1714. if (hFont)
  1715. h = SelectObject(hDC, hFont);
  1716. else
  1717. h = 0;
  1718. GetTextExtentExPoint (hDC, ClockDisp.szTimeFmt, ClockDisp.nTimeLen,
  1719. DesiredWidth, &nFit, nzExts, &sizeTimeExt);
  1720. if (h)
  1721. SelectObject(hDC, h);
  1722. if (nFit == ClockDisp.nTimeLen) /* if string fits, exit loop */
  1723. #ifdef JAPAN // #1208:6/1/93:
  1724. {
  1725. bFit = TRUE;
  1726. break;
  1727. }
  1728. #else
  1729. break;
  1730. #endif
  1731. FontStruct.lfHeight += 2; /* remember height is negative! */
  1732. }
  1733. #ifdef JAPAN // #1208:6/1/93: Change display font fit iconic
  1734. if (!bFit && ClockDisp.bIconic)
  1735. {
  1736. wkFontStruct.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
  1737. lstrcpy (wkFontStruct.lfFaceName, TEXT(" "));
  1738. for (nOldFit = 0, nFit = -1; wkFontStruct.lfHeight < 0;)
  1739. {
  1740. nOldFit = nFit;
  1741. if (hFont)
  1742. DeleteObject (hFont);
  1743. hFont = CreateFontIndirect(&wkFontStruct);
  1744. if (hFont)
  1745. h = SelectObject(hDC, hFont);
  1746. else
  1747. h = 0;
  1748. GetTextExtentExPoint( hDC, ClockDisp.szTimeFmt,
  1749. ClockDisp.nTimeLen, DesiredWidth, &nFit, nzExts, &sizeTimeExt );
  1750. if (h)
  1751. SelectObject(hDC, h);
  1752. if (nFit == ClockDisp.nTimeLen)
  1753. break;
  1754. wkFontStruct.lfHeight += 2;
  1755. }
  1756. }
  1757. #endif
  1758. /* compute placement and extents */
  1759. iAMPMLen = ClockDisp.nMaxAMPMLen;
  1760. if (!ClockDisp.bIconic && ClockDisp.wAMPMPosition && iAMPMLen)
  1761. {
  1762. ClockDisp.nSizeChar = nzExts[iAMPMLen] - nzExts[iAMPMLen-1];
  1763. ClockDisp.nPosAMPM = (newWidth - sizeTimeExt.cx) / 2;
  1764. ClockDisp.nSizeAMPM = nzExts[iAMPMLen-2];
  1765. ClockDisp.nSizeSep = nzExts[iAMPMLen+2] - nzExts[iAMPMLen+1];
  1766. ClockDisp.nPosHr = ClockDisp.nPosAMPM + nzExts[iAMPMLen-1];
  1767. ClockDisp.nPosSep1 = ClockDisp.nPosAMPM + nzExts[iAMPMLen+1];
  1768. ClockDisp.nPosMin = ClockDisp.nPosAMPM + nzExts[iAMPMLen+2];
  1769. if (!ClockDisp.bNoSeconds)
  1770. {
  1771. ClockDisp.nPosSep2 = ClockDisp.nPosAMPM + nzExts[iAMPMLen+4];
  1772. ClockDisp.nPosSec = ClockDisp.nPosAMPM + nzExts[iAMPMLen+5];
  1773. }
  1774. }
  1775. else
  1776. {
  1777. ClockDisp.nSizeChar = nzExts[0];
  1778. ClockDisp.nSizeSep = nzExts[2] - nzExts[1];
  1779. ClockDisp.nPosHr = (newWidth - sizeTimeExt.cx) / 2;
  1780. ClockDisp.nPosSep1 = ClockDisp.nPosHr + nzExts[ 1 ];
  1781. ClockDisp.nPosMin = ClockDisp.nPosHr + nzExts[2];
  1782. if (!ClockDisp.bIconic)
  1783. {
  1784. if (!ClockDisp.bNoSeconds)
  1785. {
  1786. ClockDisp.nPosSep2 = ClockDisp.nPosHr + nzExts[4];
  1787. ClockDisp.nPosSec = ClockDisp.nPosHr + nzExts[5];
  1788. if (ClockDisp.nTimeLen > 8)
  1789. nAMPMIndx = 8;
  1790. }
  1791. else if (ClockDisp.nTimeLen > 5)
  1792. nAMPMIndx = 5;
  1793. if (nAMPMIndx)
  1794. {
  1795. ClockDisp.nPosAMPM = ClockDisp.nPosHr + nzExts[nAMPMIndx];
  1796. ClockDisp.nSizeAMPM = sizeTimeExt.cx - nzExts[nAMPMIndx];
  1797. }
  1798. else
  1799. {
  1800. ClockDisp.nPosAMPM = 0;
  1801. ClockDisp.nSizeAMPM = 0;
  1802. }
  1803. }
  1804. }
  1805. ClockDisp.nSizeY = sizeTimeExt.cy;
  1806. /* compute size of shadow offset - if the font is too small, no
  1807. * shadow (offset = 0)
  1808. */
  1809. ClockDisp.wShdwOff = (WORD) (((ClockDisp.nSizeChar + ClockDisp.nSizeY) < 90) ?
  1810. 0 : 2 * GetSystemMetrics (SM_CXBORDER));
  1811. /* allocate a bitmap for 2 digits */
  1812. if (ClockDisp.hBitmap != NULL)
  1813. DeleteObject (ClockDisp.hBitmap);
  1814. ClockDisp.hBitmap = CreateDiscardableBitmap (hDC, 2*ClockDisp.nSizeChar
  1815. + 2*ClockDisp.wShdwOff, ClockDisp.nSizeY);
  1816. /* prepare a font for the date */
  1817. if (bDisplayDate)
  1818. {
  1819. DesiredHeight = -(FontStruct.lfHeight * 3) / 4;
  1820. /* compute appropriate font for date - same algorithm as time */
  1821. FontStruct.lfHeight = -MulDiv (InitialHeight, DesiredWidth,
  1822. sizeDateExt.cx);
  1823. if (-FontStruct.lfHeight > DesiredHeight)
  1824. FontStruct.lfHeight = -DesiredHeight;
  1825. for (; ;)
  1826. {
  1827. if (hFontDate != NULL)
  1828. DeleteObject (hFontDate);
  1829. hFontDate = CreateFontIndirect (&FontStruct);
  1830. if (hFontDate)
  1831. h = SelectObject (hDC, hFontDate);
  1832. else
  1833. h = 0;
  1834. GetTextExtentPoint (hDC, ClockDisp.szDate,
  1835. ClockDisp.nDateLen, &sizeDateExt);
  1836. if (h)
  1837. SelectObject (hDC, h);
  1838. if (sizeDateExt.cx < DesiredWidth)
  1839. break;
  1840. FontStruct.lfHeight += 2;
  1841. }
  1842. /* compute date placement and extents */
  1843. ClockDisp.nPosDateX = (newWidth - sizeDateExt.cx) / 2;
  1844. ClockDisp.nSizeDateX = sizeDateExt.cx;
  1845. ClockDisp.nSizeDateY = sizeDateExt.cy;
  1846. ClockDisp.nPosY = (newHeight - (ClockDisp.nSizeY +
  1847. ClockDisp.nSizeDateY)) / 2;
  1848. ClockDisp.nPosDateY = ClockDisp.nPosY + ClockDisp.nSizeY;
  1849. }
  1850. else
  1851. {
  1852. /* no date, so center the time */
  1853. ClockDisp.nPosY = (newHeight - ClockDisp.nSizeY) / 2;
  1854. }
  1855. ReleaseDC (hWnd, hDC);
  1856. SetCursor (hOldCur);
  1857. }
  1858. }
  1859. /*
  1860. * DrawHand() - Draw the second hand using XOR mode.
  1861. */
  1862. void NEAR PASCAL DrawHand (register HDC hDC,
  1863. int pos,
  1864. HPEN hPen,
  1865. int scale,
  1866. int patMode)
  1867. {
  1868. TRIG * lppt;
  1869. int radius;
  1870. MoveTo (hDC, clockCenter.x, clockCenter.y);
  1871. radius = MulDiv (clockRadius, scale, 100);
  1872. lppt = lpcirTab + (pos % 60);
  1873. SetROP2 (hDC, patMode);
  1874. SelectObject (hDC, hPen);
  1875. LineTo (hDC, clockCenter.x + MulDiv (lppt->x, radius, 8000),
  1876. clockCenter.y + MulDiv (lppt->y, radius, 8000));
  1877. }
  1878. /*
  1879. * SetMenuBar() - places or removes the menu bar, etc.
  1880. *
  1881. * Based on the flags in ClockDisp structure (ie: do we want a menu/title
  1882. * bar or not?), adds or removes the window title and menu bar:
  1883. * Gets current style, toggles the bits, and re-sets the style.
  1884. * Must then resize the window frame and show it.
  1885. */
  1886. void NEAR PASCAL SetMenuBar (HWND hWnd)
  1887. {
  1888. static DWORD wID;
  1889. DWORD dwStyle;
  1890. dwStyle = GetWindowLong (hWnd, GWL_STYLE);
  1891. if (ClockDisp.bNoTitle)
  1892. {
  1893. /* remove caption & menu bar, etc. */
  1894. dwStyle &= ~(WS_DLGFRAME | WS_SYSMENU |
  1895. WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
  1896. wID = SetWindowLong (hWnd, GWL_ID, 0);
  1897. }
  1898. else
  1899. {
  1900. /* put menu bar & caption back in */
  1901. dwStyle = WS_TILEDWINDOW | dwStyle;
  1902. SetWindowLong (hWnd, GWL_ID, wID);
  1903. SetWindowRgn(hWnd, NULL, TRUE);
  1904. }
  1905. SetWindowLong (hWnd, GWL_STYLE, dwStyle);
  1906. SetWindowPos (hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
  1907. SWP_NOZORDER | SWP_FRAMECHANGED);
  1908. if (ClockDisp.wFormat == IDM_ANALOG && ClockDisp.bNoTitle)
  1909. {
  1910. HRGN hrgn;
  1911. RECT rc;
  1912. GetClientRect(hWnd,&rc);
  1913. if(hrgn = CreateEllipticWndRgn(hWnd,&rc))
  1914. SetWindowRgn(hWnd,hrgn,TRUE);
  1915. }
  1916. ShowWindow (hWnd, SW_SHOW);
  1917. }
  1918. /*
  1919. * FormatInit() - Retrieve current locale information.
  1920. */
  1921. void NEAR PASCAL FormatInit (VOID)
  1922. {
  1923. LCID lcid;
  1924. TCHAR szBuf[3];
  1925. lcid = GetUserDefaultLCID ();
  1926. /*
  1927. * Get time format:
  1928. * 0 = 12 hour format
  1929. * 1 = 24 hour format
  1930. */
  1931. if (!bUtc)
  1932. {
  1933. GetLocaleInfoW (lcid, LOCALE_ITIME, (LPWSTR) szBuf, 3);
  1934. ClockDisp.wTimeFormat = (WORD)MyAtoi (szBuf);
  1935. }
  1936. else
  1937. {
  1938. /*
  1939. * GMT - use 24 hour clock format.
  1940. */
  1941. ClockDisp.wTimeFormat = 1;
  1942. }
  1943. /*
  1944. * Get time leading zero:
  1945. * 0 = no leading zero
  1946. * 1 = leading zero
  1947. */
  1948. GetLocaleInfoW (lcid, LOCALE_ITLZERO, (LPWSTR) szBuf, 3);
  1949. ClockDisp.wTimeLZero = (WORD)MyAtoi (szBuf);
  1950. /*
  1951. * Get time marker position:
  1952. * 0 = suffix
  1953. * 1 = prefix
  1954. */
  1955. GetLocaleInfoW (lcid, LOCALE_ITIMEMARKPOSN, (LPWSTR) szBuf, 3);
  1956. ClockDisp.wAMPMPosition = (WORD)MyAtoi (szBuf);
  1957. /*
  1958. * Get AM/PM designators.
  1959. */
  1960. if (!bUtc)
  1961. {
  1962. GetLocaleInfoW (lcid, LOCALE_S1159, (LPWSTR) ClockDisp.szAMPM[0], MAX_AMPM_LEN);
  1963. GetLocaleInfoW (lcid, LOCALE_S2359, (LPWSTR) ClockDisp.szAMPM[1], MAX_AMPM_LEN);
  1964. ClockDisp.nMaxAMPMLen = max( lstrlen(ClockDisp.szAMPM[0]),
  1965. lstrlen(ClockDisp.szAMPM[1]) );
  1966. if ((ClockDisp.wAMPMPosition) && (ClockDisp.nMaxAMPMLen))
  1967. {
  1968. /*
  1969. * AM/PM is a Prefix, so need to add one to the length
  1970. * for the space between the time marker and the time string.
  1971. */
  1972. (ClockDisp.nMaxAMPMLen)++;
  1973. }
  1974. }
  1975. else
  1976. {
  1977. *(ClockDisp.szAMPM[0]) = *(ClockDisp.szAMPM[1]) = TEXT('\0');
  1978. ClockDisp.nMaxAMPMLen = 0;
  1979. }
  1980. /*
  1981. * Get time separator string.
  1982. */
  1983. GetLocaleInfoW (lcid, LOCALE_STIME, (LPWSTR) ClockDisp.szTimeSep, MAX_TIME_SEP);
  1984. /*
  1985. * Get short date format.
  1986. */
  1987. GetLocaleInfoW (lcid, LOCALE_SSHORTDATE, (LPWSTR) ClockDisp.szDateFmt, MAX_DATE_LEN);
  1988. }
  1989. /*
  1990. * ClockSize()
  1991. */
  1992. void NEAR PASCAL ClockSize (register HWND hWnd,
  1993. int newWidth,
  1994. int newHeight,
  1995. WORD SizeWord)
  1996. {
  1997. BOOL bChanged = FALSE;
  1998. SetRect (&clockRect, 0, 0, newWidth, newHeight);
  1999. CompClockDim ();
  2000. if (SizeWord == SIZEICONIC)
  2001. {
  2002. ClockDisp.bIconic = TRUE;
  2003. bChanged = TRUE;
  2004. }
  2005. else if (ClockDisp.bIconic)
  2006. {
  2007. ClockDisp.bIconic = FALSE;
  2008. bChanged = TRUE;
  2009. }
  2010. if (bChanged)
  2011. {
  2012. ClockTimerInterval (hWnd);
  2013. FormatTimeStr ();
  2014. if (!ClockDisp.bNoDate)
  2015. {
  2016. FormatDateStr (&oDate, ClockDisp.bIconic);
  2017. ResetWinTitle (hWnd); /* date has changed */
  2018. }
  2019. }
  2020. if (ClockDisp.wFormat == IDM_ANALOG && ClockDisp.bNoTitle)
  2021. {
  2022. HRGN hrgn;
  2023. RECT rc;
  2024. GetClientRect(hWnd,&rc);
  2025. if(hrgn = CreateEllipticWndRgn(hWnd,&rc))
  2026. SetWindowRgn(hWnd,hrgn,TRUE);
  2027. }
  2028. }
  2029. /*
  2030. * CompClockDim() - Recompute the clock's dimensions.
  2031. */
  2032. void NEAR PASCAL CompClockDim (void)
  2033. {
  2034. int i;
  2035. register int tWidth;
  2036. register int tHeight;
  2037. tWidth = clockRect.right - clockRect.left;
  2038. tHeight = clockRect.bottom - clockRect.top;
  2039. if (tWidth > MulDiv (tHeight,aspectD,aspectN))
  2040. {
  2041. i = MulDiv (tHeight, aspectD, aspectN);
  2042. clockRect.left += (tWidth - i) >> 1;
  2043. clockRect.right = clockRect.left + i;
  2044. }
  2045. else
  2046. {
  2047. i = MulDiv (tWidth, aspectN, aspectD);
  2048. clockRect.top += (tHeight - i) >> 1;
  2049. clockRect.bottom = clockRect.top + i;
  2050. }
  2051. }
  2052. /*
  2053. * DeleteTools()
  2054. */
  2055. void NEAR PASCAL DeleteTools (void)
  2056. {
  2057. DeleteObject (hbrForeground);
  2058. DeleteObject (hbrColorWindow);
  2059. DeleteObject (hbrBtnHighlight);
  2060. DeleteObject (hbrBlobColor);
  2061. DeleteObject (hpenForeground);
  2062. DeleteObject (hpenShadow);
  2063. DeleteObject (hpenBackground);
  2064. DeleteObject (hpenBlobHlt);
  2065. DeleteObject (hpenRed);
  2066. }
  2067. void ParseSavedWindow (LPTSTR szBuf, PRECT pRect)
  2068. {
  2069. PINT pint;
  2070. int count;
  2071. short cxFrame = (short) GetSystemMetrics (SM_CXFRAME);
  2072. short cxSize = (short) GetSystemMetrics (SM_CXSIZE);
  2073. short cyFrame = (short) GetSystemMetrics (SM_CYFRAME);
  2074. short cySize = (short) GetSystemMetrics (SM_CYSIZE);
  2075. count = 0;
  2076. pint = (PINT) pRect;
  2077. while (*szBuf && count < 4)
  2078. {
  2079. *pint = (int) MyAtoi (szBuf);
  2080. pint++; // advance to next field
  2081. while (*szBuf && *szBuf != TEXT(','))
  2082. szBuf++;
  2083. while (*szBuf && *szBuf == TEXT(','))
  2084. szBuf++;
  2085. count++;
  2086. }
  2087. if ((count < 4) ||
  2088. (pRect->left >= pRect->right) || (pRect->top >= pRect->bottom))
  2089. {
  2090. HDC hDC = GetDC(NULL);
  2091. int nPixMMX = GetDeviceCaps (hDC, HORZRES) / GetDeviceCaps (hDC, HORZSIZE);
  2092. int nPixMMY = GetDeviceCaps (hDC, VERTRES) / GetDeviceCaps (hDC, VERTSIZE);
  2093. ReleaseDC (NULL, hDC);
  2094. /* Bug #14014: These sizes chosen for showing date in title bar as well as
  2095. * instruction speed. 24 September 1991 Clark Cyr
  2096. */
  2097. pRect->left = (LONG)CW_USEDEFAULT;
  2098. pRect->top = SW_SHOWNORMAL;
  2099. pRect->right = 64 * nPixMMX + 4 * cxFrame;
  2100. pRect->bottom = 64 * nPixMMY + 4 * cyFrame + cySize;
  2101. }
  2102. else
  2103. {
  2104. short cxScreen = (short) GetSystemMetrics (SM_CXSCREEN);
  2105. short cyScreen = (short) GetSystemMetrics (SM_CYSCREEN);
  2106. pRect->right -= pRect->left; /* right is now width */
  2107. pRect->bottom -= pRect->top; /* bottom is now height */
  2108. if (pRect->left > cxScreen - cxFrame - cxSize)
  2109. pRect->left = cxScreen - cxFrame - cxSize;
  2110. else if (pRect->left < cxFrame + cxSize - pRect->right)
  2111. pRect->left = cxFrame + cxSize - pRect->right;
  2112. if (pRect->top > cyScreen - cyFrame - cySize)
  2113. pRect->top = cyScreen - cyFrame - cySize;
  2114. else if (pRect->top < cxFrame + cxSize - pRect->bottom)
  2115. pRect->top = cxFrame + cxSize - pRect->bottom;
  2116. }
  2117. }
  2118. #define ADVANCE(sz) while (*sz && *sz != TEXT(',')) sz++; \
  2119. while (*sz && *sz == TEXT(',')) sz++; \
  2120. if (!*sz) return;
  2121. void NEAR PASCAL ParseSavedFlags (LPTSTR szBuf, PCLOCKDISPSTRUCT pClck)
  2122. {
  2123. pClck->wFormat = IDM_ANALOG;
  2124. pClck->bIconic = FALSE;
  2125. pClck->bNoSeconds = FALSE;
  2126. pClck->bNoTitle = FALSE;
  2127. pClck->bTopMost = FALSE;
  2128. pClck->bNoDate = FALSE;
  2129. if (!szBuf)
  2130. return;
  2131. pClck->wFormat = (WORD)(MyAtoi(szBuf) ? IDM_ANALOG : IDM_DIGITAL);
  2132. ADVANCE (szBuf);
  2133. pClck->bIconic = (MyAtoi(szBuf) ? TRUE : FALSE);
  2134. ADVANCE (szBuf);
  2135. pClck->bNoSeconds = (MyAtoi(szBuf) ? TRUE : FALSE);
  2136. ADVANCE (szBuf);
  2137. pClck->bNoTitle = (MyAtoi(szBuf) ? TRUE : FALSE);
  2138. ADVANCE (szBuf);
  2139. pClck->bTopMost = (MyAtoi(szBuf) ? TRUE : FALSE);
  2140. ADVANCE (szBuf);
  2141. pClck->bNoDate = (MyAtoi(szBuf) ? TRUE : FALSE);
  2142. }
  2143. VOID NEAR PASCAL PrepareSavedWindow (LPTSTR szBuf, PRECT pRect)
  2144. {
  2145. wsprintf (szBuf, TEXT("%i,%i,%i,%i"), pRect->left, pRect->top,
  2146. pRect->right, pRect->bottom);
  2147. }
  2148. TRIG CirTab[] = { // circle sin, cos, table
  2149. { 0, -7999 },
  2150. { 836, -7956 },
  2151. { 1663, -7825 },
  2152. { 2472, -7608 },
  2153. { 3253, -7308 },
  2154. { 3999, -6928 },
  2155. { 4702, -6472 },
  2156. { 5353, -5945 },
  2157. { 5945, -5353 },
  2158. { 6472, -4702 },
  2159. { 6928, -4000 },
  2160. { 7308, -3253 },
  2161. { 7608, -2472 },
  2162. { 7825, -1663 },
  2163. { 7956, -836 },
  2164. { 8000, 0 },
  2165. { 7956, 836 },
  2166. { 7825, 1663 },
  2167. { 7608, 2472 },
  2168. { 7308, 3253 },
  2169. { 6928, 4000 },
  2170. { 6472, 4702 },
  2171. { 5945, 5353 },
  2172. { 5353, 5945 },
  2173. { 4702, 6472 },
  2174. { 3999, 6928 },
  2175. { 3253, 7308 },
  2176. { 2472, 7608 },
  2177. { 1663, 7825 },
  2178. { 836, 7956 },
  2179. { 0, 7999 },
  2180. { -836, 7956 },
  2181. { -1663, 7825 },
  2182. { -2472, 7608 },
  2183. { -3253, 7308 },
  2184. { -4000, 6928 },
  2185. { -4702, 6472 },
  2186. { -5353, 5945 },
  2187. { -5945, 5353 },
  2188. { -6472, 4702 },
  2189. { -6928, 3999 },
  2190. { -7308, 3253 },
  2191. { -7608, 2472 },
  2192. { -7825, 1663 },
  2193. { -7956, 836 },
  2194. { -7999, -0 },
  2195. { -7956, -836 },
  2196. { -7825, -1663 },
  2197. { -7608, -2472 },
  2198. { -7308, -3253 },
  2199. { -6928, -4000 },
  2200. { -6472, -4702 },
  2201. { -5945, -5353 },
  2202. { -5353, -5945 },
  2203. { -4702, -6472 },
  2204. { -3999, -6928 },
  2205. { -3253, -7308 },
  2206. { -2472, -7608 },
  2207. { -1663, -7825 },
  2208. { -836 , -7956 }
  2209. };
  2210. VOID NEAR PASCAL PrepareSavedFlags (LPTSTR szBuf, PCLOCKDISPSTRUCT pClck)
  2211. {
  2212. wsprintf (szBuf, TEXT("%i,%i,%i,%i,%i,%i"),
  2213. (pClck->wFormat == IDM_ANALOG ? 1 : 0),
  2214. (pClck->bIconic ? 1 : 0), (pClck->bNoSeconds ? 1 : 0),
  2215. (pClck->bNoTitle ? 1 : 0), (pClck->bTopMost ? 1 : 0),
  2216. (pClck->bNoDate ? 1 : 0));
  2217. }
  2218. /*
  2219. * SaveClockOptions()
  2220. */
  2221. VOID NEAR PASCAL SaveClockOptions (HWND hWnd)
  2222. {
  2223. TCHAR szInt[80];
  2224. INT i = (INT) IsZoomed (hWnd);
  2225. /* Bug 15058: Don't save the rectangle if we're maximized, assume it
  2226. * has already been saved for restoration when maximization took place.
  2227. * 18 October 1991 Clark Cyr
  2228. */
  2229. if (!ClockDisp.bIconic && !i)
  2230. GetWindowRect (hWnd, &rCoordRect);
  2231. wsprintf (szInt, TEXT("%i"), i);
  2232. WritePrivateProfileString(szSection, szMaximized, szInt, szIniFile);
  2233. /* write current clock options */
  2234. PrepareSavedFlags (szInt, &ClockDisp);
  2235. WritePrivateProfileString (szSection, szOptions, szInt, szIniFile);
  2236. /* write window position and size */
  2237. PrepareSavedWindow (szInt, &rCoordRect);
  2238. WritePrivateProfileString (szSection, szPosition, szInt, szIniFile);
  2239. #ifdef JAPAN
  2240. WritePrivateProfileString(
  2241. szSection, szFontFileKey, FontStruct.lfFaceName, szIniFile );
  2242. wsprintf (szInt, TEXT("%i"), (INT)FontStruct.lfCharSet);
  2243. WritePrivateProfileString(szSection, szCharSet, szInt, szIniFile);
  2244. #endif
  2245. }
  2246. #if defined(JAPAN) || defined(KOREA)
  2247. /*
  2248. * ExceptVerticalFont()
  2249. */
  2250. UINT FAR PASCAL ExceptVerticalFont(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  2251. {
  2252. LOGFONT lf;
  2253. TCHAR szFaceName[LF_FACESIZE];
  2254. UINT nId, count;
  2255. switch (message)
  2256. {
  2257. case WM_INITDIALOG:
  2258. count = SendDlgItemMessage(hwnd, cmb1, CB_GETCOUNT, 0, 0L);
  2259. /* except vertical font */
  2260. for (nId = 0; nId < count; nId++)
  2261. {
  2262. SendDlgItemMessage(hwnd, cmb1, CB_GETLBTEXT,
  2263. nId, (LONG) szFaceName);
  2264. if (szFaceName[0] == TEXT('@'))
  2265. {
  2266. SendDlgItemMessage(hwnd, cmb1, CB_DELETESTRING, nId, 0L);
  2267. nId--;
  2268. count--;
  2269. }
  2270. }
  2271. /* set selection current selected facename */
  2272. SendMessage(hwnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LONG) (LPTSTR) &lf);
  2273. nId = SendDlgItemMessage(hwnd, cmb1, CB_FINDSTRING,
  2274. 0, (LONG) lf.lfFaceName);
  2275. SendDlgItemMessage(hwnd, cmb1, CB_SETCURSEL, nId, 0L);
  2276. // KKBUGFIX #1364: 12/10/92: Set focus on face name
  2277. return(TRUE);
  2278. default:
  2279. return(FALSE);
  2280. }
  2281. }
  2282. #endif
  2283. HRGN CreateEllipticWndRgn(HWND hWnd, LPRECT lprc)
  2284. {
  2285. int cSide;
  2286. int xOffset;
  2287. int yOffset;
  2288. HRGN hRgn = NULL;
  2289. if(lprc)
  2290. {
  2291. cSide = min(lprc->right, lprc->bottom);
  2292. xOffset = GetSystemMetrics(SM_CXFRAME) + ((lprc->right - cSide) >> 1);
  2293. yOffset = GetSystemMetrics(SM_CYFRAME) + ((lprc->bottom - cSide) >> 1);
  2294. hRgn = CreateEllipticRgn(xOffset, yOffset, xOffset+cSide, yOffset+cSide);
  2295. }
  2296. return(hRgn);
  2297. }
  2298.