home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / sysba021.zip / SRC.ZIP / sysbar2 / Clock / sb2_clock.cpp < prev    next >
C/C++ Source or Header  |  2003-01-03  |  27KB  |  797 lines

  1. /*
  2.  
  3.   SysBar/2 Utility Set  version 0.21
  4.  
  5.   Clock module
  6.  
  7.   ..................................................................
  8.  
  9.   Copyright (c) 1995-1999  Dmitry I. Platonoff
  10.                            All rights reserved
  11.  
  12.                          dplatonoff@canada.com
  13.  
  14.   ..................................................................
  15.  
  16.   LICENSE
  17.   ~~~~~~~
  18.   Redistribution and use in source and binary forms, with or without
  19.   modification, are permitted provided that the following conditions
  20.   are met:
  21.  
  22.   1. Redistributions of source code must retain the above copyright
  23.      notice, this list of conditions and the following disclaimer.
  24.  
  25.   2. Redistributions in binary form must reproduce the above
  26.      copyright notice, this list of conditions and the following
  27.      disclaimer in the documentation and/or other materials provided
  28.      with the distribution.
  29.  
  30.   3. Redistributions of any form whatsoever, as well as all
  31.      advertising materials mentioning features or use of this
  32.      software (if any), must include the following acknowledgment:
  33.      "This product includes software developed by Dmitry I. Platonoff".
  34.  
  35.   4. The names "SysBar/2" and "Dmitry I. Platonoff" must not be
  36.      used to endorse or promote products derived from this software
  37.      without prior written permission. For such permission, please
  38.      contact dplatonoff@canada.com.
  39.  
  40.   5. Products derived from this software may not be called
  41.      "SysBar/2" nor may "Dmitry I. Platonoff" appear in their
  42.      contributor lists without prior written permission.
  43.  
  44.   ..................................................................
  45.  
  46.   DISCLAIMER
  47.   ~~~~~~~~~~
  48.   THIS SOFTWARE IS PROVIDED BY THE AUTHOR OR CONTRIBUTORS "AS IS"
  49.   AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50.   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  51.   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  52.   AUTHOR OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  53.   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  54.   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  55.   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  56.   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  57.   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  58.   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59.   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60.  
  61. */
  62.  
  63. #define __IBMCPP__
  64.  
  65. #define INCL_DOSDATETIME
  66. #define INCL_GPI
  67. #define INCL_WIN
  68.  
  69. #include <os2.h>
  70. #include <stdio.h>
  71. #include <stdlib.h>
  72. #include <string.h>
  73.  
  74. #include "..\SysBar2.h"
  75. #include "SB2_Clock_res.h"
  76.  
  77.  
  78. // Clock dimensions
  79. int iClockWidth[2] = { 94, 134 };
  80. int iClockHeight[2] = { 26, 33 };
  81. int iClockMonthX[2] = { 21, 27 };
  82. int iClockMonthW[2] = { 14, 20 };
  83. int iClockMonthH[2] = { 6, 9 };
  84. int iDigitW[2] = { 8, 12 };
  85. int iDigitH[2] = { 14, 21 };
  86.  
  87. // Clock handles
  88. HAB hab;
  89. HWND hwClockClient = NULLHANDLE;
  90. HWND hwClockFrame = NULLHANDLE;
  91. HWND hmPopupMenu = NULLHANDLE;
  92. HMODULE hmSysBar2Dll = NULLHANDLE;
  93. HBITMAP hbMonths[2][2];
  94.  
  95. // Clock settings
  96. short int iTopmost = 1;
  97. short int bMonochrome = 0;
  98. short int bLarge = 0;
  99. short int bLockPosition = 0;
  100. short int b12h = 0;
  101. short int bSeconds = 1;
  102. short int iBindToCorner = 0;
  103. static short int bLastVisible = 0;
  104.  
  105. inline int CurrentWidth( void )
  106. {
  107.   return iClockWidth[bLarge] - ( bSeconds ? 0 : ( iDigitW[bLarge] * 3 ) );
  108. }
  109.  
  110.  
  111.  
  112. // Config file stuff
  113. char *pszIniFile = NULL;
  114. char szSysBar2Clock[] = "SysBar2_Clock";
  115. char *pszYesNo[2] = { "no", "yes" };
  116.  
  117. // Just a dummy data structure
  118. typedef struct
  119. {
  120.   short int iSize;
  121. } DummyData;
  122. DummyData DummyInit = { sizeof ( DummyData ) };
  123.  
  124.  
  125. // Config string conversion routines -----------------------------------------
  126. inline int strcmp2( char *s1, char *s2 )
  127. {
  128.   if ( ! s1 || ! s2 ) return -1;
  129.   else return strcmp( s1, s2 );
  130. }
  131.  
  132. inline int atoi2( char *s )
  133. {
  134.   if ( s ) return atoi( s );
  135.   else return 0;
  136. }
  137.  
  138.  
  139. // Startup canceller ---------------------------------------------------------
  140. void AbortStartup( void )
  141. {
  142.   PERRINFO pErrInfoBlk;
  143.   PSZ pszOffSet;
  144.   PSZ pszErrMsg;
  145.  
  146.   if ( ( pErrInfoBlk = WinGetErrorInfo( hab ) ) != ( PERRINFO ) NULL )
  147.   {
  148.     pszOffSet = ( ( PSZ ) pErrInfoBlk ) + pErrInfoBlk->offaoffszMsg;
  149.     pszErrMsg = ( ( PSZ ) pErrInfoBlk ) + *( ( PSHORT ) pszOffSet );
  150.     if ( ( int ) hwClockFrame && ( int ) hwClockClient )
  151.       WinMessageBox( HWND_DESKTOP, hwClockFrame, ( PSZ ) pszErrMsg,
  152.         "SysBar/2 Clock startup error :(", 8999, 
  153.         MB_MOVEABLE | MB_ERROR | MB_CANCEL );
  154.     WinFreeErrorInfo( pErrInfoBlk );
  155.   }
  156.   WinPostMsg( hwClockClient, WM_QUIT, ( MPARAM ) NULL, ( MPARAM ) NULL );
  157. }
  158.  
  159.  
  160. // Configuration saver -------------------------------------------------------
  161. void SaveOptions( void )
  162. {
  163.   SWP Swp;
  164.   if ( WinQueryWindowPos( hwClockFrame, &Swp ) )
  165.   {
  166.     FILE *f = fopen( pszIniFile, "wt" );
  167.     if ( f )
  168.     {
  169.       fprintf( f, 
  170.         "[%s]\n"
  171.         "x=%i\n"
  172.         "y=%i\n"
  173.         "topmost=%i\n"
  174.         "monochrome=%s\n"
  175.         "largesize=%s\n"
  176.         "12hmode=%s\n"
  177.         "seconds=%s\n"
  178.         "lockposition=%s\n"
  179.         "cornerbind=%i\n",
  180.         szSysBar2Clock, Swp.x, Swp.y, iTopmost,
  181.         pszYesNo[bMonochrome], pszYesNo[bLarge], pszYesNo[b12h],
  182.         pszYesNo[bSeconds], pszYesNo[bLockPosition], iBindToCorner );
  183.       fclose( f );
  184.     }
  185.   }
  186. }
  187.  
  188.  
  189. // Month names
  190. char *pszMonths[12] =
  191. {
  192.   "January", "February", "March", "April", "May", "June", "July", "August",
  193.   "September", "October", "November", "December"
  194. };
  195.  
  196. // Settings dialog window procedure ------------------------------------------
  197. MRESULT EXPENTRY SettingsDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  198. {
  199.   switch ( msg )
  200.   {
  201.     case WM_INITDLG:
  202.       {
  203.         DATETIME dtIn;
  204.         DosGetDateTime( &dtIn );
  205.         WinSendDlgItemMsg( hwnd, D_Time_Hours, SPBM_SETLIMITS,
  206.           ( MPARAM ) 23, ( MPARAM ) 0 );
  207.         WinSendDlgItemMsg( hwnd, D_Time_Hours, SPBM_SETCURRENTVALUE,
  208.           ( MPARAM ) dtIn.hours, 0 );
  209.         WinSendDlgItemMsg( hwnd, D_Time_Minutes, SPBM_SETLIMITS,
  210.           ( MPARAM ) 59, ( MPARAM ) 0 );
  211.         WinSendDlgItemMsg( hwnd, D_Time_Minutes, SPBM_SETCURRENTVALUE,
  212.           ( MPARAM ) dtIn.minutes, 0 );
  213.         WinSendDlgItemMsg( hwnd, D_Time_Seconds, SPBM_SETLIMITS,
  214.           ( MPARAM ) 59, ( MPARAM ) 0 );
  215.         WinSendDlgItemMsg( hwnd, D_Time_Seconds, SPBM_SETCURRENTVALUE,
  216.           ( MPARAM ) dtIn.seconds, 0 );
  217.         WinSendDlgItemMsg( hwnd, D_Date_Day, SPBM_SETLIMITS,
  218.           ( MPARAM ) 31, ( MPARAM ) 1 );
  219.         WinSendDlgItemMsg( hwnd, D_Date_Day, SPBM_SETCURRENTVALUE,
  220.           ( MPARAM ) dtIn.day, 0 );
  221.         WinSendDlgItemMsg( hwnd, D_Date_Month, SPBM_SETARRAY,
  222.           ( MPARAM ) pszMonths, ( MPARAM ) 12 );
  223.         WinSendDlgItemMsg( hwnd, D_Date_Month, SPBM_SETCURRENTVALUE,
  224.           ( MPARAM ) ( dtIn.month - 1 ), 0 );
  225.         WinSendDlgItemMsg( hwnd, D_Display_None + iTopmost, BM_SETCHECK,
  226.          ( MPARAM ) 1, 0 );
  227.         WinSendDlgItemMsg( hwnd, D_Size_Small + bLarge, BM_SETCHECK,
  228.           ( MPARAM ) 1, 0 );
  229.         WinSendDlgItemMsg( hwnd, D_Bind_Off + iBindToCorner, BM_SETCHECK,
  230.           ( MPARAM ) 1, 0 );
  231.         WinSendDlgItemMsg( hwnd, D_Display_Mono, BM_SETCHECK,
  232.           ( MPARAM ) bMonochrome, 0 );
  233.         WinSendDlgItemMsg( hwnd, D_Display_12h, BM_SETCHECK,
  234.           ( MPARAM ) b12h, 0 );
  235.         WinSendDlgItemMsg( hwnd, D_Display_Seconds, BM_SETCHECK,
  236.           ( MPARAM ) bSeconds, 0 );
  237.         WinSendDlgItemMsg( hwnd, D_Lock_Position, BM_SETCHECK,
  238.           ( MPARAM ) bLockPosition, 0 );
  239.       }
  240.       break;
  241.  
  242.     case WM_COMMAND:
  243.       switch ( SHORT1FROMMP( mp1 ) )
  244.       {
  245.         case D_Time_Set:
  246.           {
  247.             DATETIME dtOut;
  248.             DosGetDateTime( &dtOut );
  249.             long lValue;
  250.             WinSendDlgItemMsg( hwnd, D_Time_Hours, SPBM_QUERYVALUE, 
  251.               &lValue, 0 );
  252.             dtOut.hours = ( UCHAR ) lValue;
  253.             WinSendDlgItemMsg( hwnd, D_Time_Minutes, SPBM_QUERYVALUE,
  254.               &lValue, 0 );
  255.             dtOut.minutes = ( UCHAR ) lValue;
  256.             WinSendDlgItemMsg( hwnd, D_Time_Seconds, SPBM_QUERYVALUE,
  257.               &lValue, 0 );
  258.             dtOut.seconds = ( UCHAR ) lValue;
  259.             DosSetDateTime( &dtOut );
  260.           }
  261.           break;
  262.           
  263.         case D_Date_Set:
  264.           {
  265.             DATETIME dtOut;
  266.             DosGetDateTime( &dtOut );
  267.             long lValue;
  268.             WinSendDlgItemMsg( hwnd, D_Date_Day, SPBM_QUERYVALUE,
  269.               &lValue, 0 );
  270.             dtOut.day = ( UCHAR ) lValue;
  271.             WinSendDlgItemMsg( hwnd, D_Date_Month, SPBM_QUERYVALUE,
  272.               &lValue, 0 );
  273.             dtOut.month = ( UCHAR ) ( lValue + 1 );
  274.             DosSetDateTime( &dtOut );
  275.           }
  276.           break;
  277.  
  278.         default:
  279.           return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  280.       }
  281.       break;
  282.  
  283.     case WM_CONTROL:
  284.       switch ( SHORT1FROMMP( mp1 ) )
  285.       {
  286.         case D_Lock_Position:
  287.           if ( bLockPosition != ( int ) WinSendDlgItemMsg( hwnd,
  288.             D_Lock_Position, BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwClockClient,
  289.             WM_COMMAND, ( MPARAM ) ( MNU_CLOCK_LOCKPOSITION ), 0 );
  290.           break;
  291.         case D_Display_None:
  292.         case D_Display_OnTop:
  293.         case D_Display_Popup:
  294.         case D_Display_Popup2:
  295.           {
  296.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Display_None,
  297.               BM_QUERYCHECKINDEX, 0, 0 );
  298.             if ( ( s & 3 ) == s ) WinPostMsg( hwClockClient, WM_COMMAND,
  299.               ( MPARAM ) ( MNU_CLOCK_NOTOP + s ), 0 );
  300.           }
  301.           break;
  302.         case D_Bind_Off:
  303.         case D_Bind_NW:
  304.         case D_Bind_NE:
  305.         case D_Bind_SW:
  306.         case D_Bind_SE:
  307.           {
  308.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Bind_Off,
  309.               BM_QUERYCHECKINDEX, 0, 0 );
  310.             if ( s >= 0 && s <= 4 ) WinPostMsg( hwClockClient, WM_COMMAND,
  311.               ( MPARAM ) ( MNU_CLOCK_BIND_OFF + s ), 0 );
  312.           }
  313.         case D_Size_Small:
  314.         case D_Size_Large:
  315.           {
  316.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Size_Small,
  317.               BM_QUERYCHECKINDEX, 0, 0 );
  318.             if ( s == 0 || s == 1 ) WinPostMsg( hwClockClient, WM_COMMAND,
  319.               ( MPARAM ) ( MNU_CLOCK_SMALL + s ), 0 );
  320.           }
  321.           break;
  322.         case D_Display_Mono:
  323.           if ( bMonochrome != ( int ) WinSendDlgItemMsg( hwnd, D_Display_Mono,
  324.             BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwClockClient, WM_COMMAND,
  325.             ( MPARAM ) ( MNU_CLOCK_MONO ), 0 );
  326.           break;
  327.         case D_Display_12h:
  328.           if ( b12h != ( int ) WinSendDlgItemMsg( hwnd, D_Display_12h,
  329.             BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwClockClient, WM_COMMAND,
  330.             ( MPARAM ) ( MNU_CLOCK_12H ), 0 );
  331.           break;
  332.         case D_Display_Seconds:
  333.           if ( bSeconds != ( int ) WinSendDlgItemMsg( hwnd, D_Display_Seconds,
  334.             BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwClockClient, WM_COMMAND,
  335.             ( MPARAM ) ( MNU_CLOCK_SECONDS ), 0 );
  336.           break;
  337.       }
  338.       break;
  339.  
  340.     default:
  341.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  342.   }
  343.   return ( MRESULT ) FALSE;
  344. }
  345.  
  346.  
  347. // About dialog window procedure ---------------------------------------------
  348. MRESULT EXPENTRY AboutDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  349. {
  350.   if ( msg == WM_INITDLG )
  351.   {
  352.     WinSetDlgItemText( hwnd, D_Version, SB2_Strings( iSB2S_Version ) );
  353.     WinSetDlgItemText( hwnd, D_Copyright, SB2_Strings( iSB2S_Copyright ) );
  354.     WinSetDlgItemText( hwnd, D_Email, SB2_Strings( iSB2S_Email ) );
  355.   }
  356.   return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  357. }
  358.  
  359.  
  360. // Main properties dialog window procedure -----------------------------------
  361. MRESULT EXPENTRY PropertiesDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  362. {
  363.   static short int bInit = 1;
  364.   static ULONG ulAboutPage;
  365.   static ULONG ulSettingsPage;
  366.   static HWND hwSettingsDlg = NULL;
  367.   static HWND hwAboutDlg = NULL;
  368.  
  369.   switch ( msg )
  370.   {
  371.     case WM_INITDLG:
  372.       if ( mp2 )
  373.       {
  374.         WinSetWindowText( hwnd, "SysBar/2 Clock - Properties" );
  375.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETNOTEBOOKCOLORS,
  376.           MPFROMLONG( SYSCLR_DIALOGBACKGROUND ),
  377.           MPFROMLONG( BKA_BACKGROUNDPAGECOLORINDEX ) );
  378.         HWND hwNotebook = WinWindowFromID( hwnd, D_Prop_Notebook );
  379.  
  380.         ulSettingsPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "General",
  381.           "General settings" );
  382.         hwSettingsDlg = WinLoadDlg( hwNotebook, hwNotebook, SettingsDlgProc,
  383.           ( HMODULE ) 0, DLG_SETTINGS, NULL );
  384.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  385.           ( MPARAM ) ulSettingsPage, ( MPARAM ) hwSettingsDlg );
  386.  
  387.         ulAboutPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "About",
  388.           "About SysBar/2 Clock" );
  389.         hwAboutDlg = WinLoadDlg( hwNotebook, hwNotebook, AboutDlgProc,
  390.           ( HMODULE ) 0, DLG_ABOUT, NULL );
  391.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  392.           ( MPARAM ) ulAboutPage, ( MPARAM ) hwAboutDlg );
  393.  
  394.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  395.           MPFROM2SHORT ( 21, 21 ), MPFROMSHORT ( BKA_PAGEBUTTON ) );
  396.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  397.           MPFROM2SHORT ( 80, 20 ), MPFROMSHORT ( BKA_MAJORTAB ) );
  398.       }
  399.       break;
  400.  
  401.     case WM_CLOSE:
  402.       WinDestroyWindow( hwSettingsDlg );
  403.       WinDestroyWindow( hwAboutDlg );
  404.       WinPostMsg( hwClockClient, WM_COMMAND, ( MPARAM ) MNU_CLOCK_SAVE, 0 );
  405.     default:
  406.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  407.   }
  408.   return ( MRESULT ) FALSE;
  409. }
  410.  
  411.  
  412. HWND hwPrevWindow = HWND_DESKTOP;
  413.  
  414. void PopUpMainWindow( void )
  415. {
  416.   if ( iTopmost >= 2 ) hwPrevWindow = WinQueryWindow( hwClockFrame, QW_PREV );
  417.   WinSetWindowPos( hwClockFrame, HWND_TOP, 0L, 0L, 0L, 0L,
  418.     SWP_ZORDER | SWP_SHOW );
  419.   bLastVisible = 1;
  420. }
  421.  
  422.  
  423. // Clear flag
  424. short int bClearIt = 0;
  425.  
  426. void InvalidateInside( HWND hwnd )
  427. {
  428.   RECTL re = { 6, 5, 0, 0 };
  429.   re.xRight = CurrentWidth() - 6;
  430.   re.yTop = iClockHeight[bLarge] - 5;
  431.   WinInvalidateRect( hwnd, &re, FALSE );
  432. }
  433.  
  434. // Main window procedure -----------------------------------------------------
  435. MRESULT EXPENTRY ClockWinProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  436. {
  437.   switch ( msg )
  438.   {
  439.     case WM_CREATE:
  440.       {
  441.         HPS hps = WinGetPS( hwnd );
  442.         hbMonths[0][0] = GpiLoadBitmap( hps, NULLHANDLE, BMP_MONTHS,
  443.           iClockMonthW[0] * 12, iClockMonthH[0] );
  444.         hbMonths[0][1] = GpiLoadBitmap( hps, NULLHANDLE, BMP_MONTHSBW,
  445.           iClockMonthW[0] * 12, iClockMonthH[0] );
  446.         hbMonths[1][0] = GpiLoadBitmap( hps, NULLHANDLE, BMP_MONTHS2,
  447.           iClockMonthW[1] * 12, iClockMonthH[1] );
  448.         hbMonths[1][1] = GpiLoadBitmap( hps, NULLHANDLE, BMP_MONTHS2BW,
  449.           iClockMonthW[1] * 12, iClockMonthH[1] );
  450.         WinReleasePS( hps );
  451.         hmPopupMenu = WinLoadMenu( hwnd, NULLHANDLE, MNU_CLOCK );
  452.         WinStartTimer( hab, hwnd, TID_USERMAX + 7, 1000 );
  453.       }
  454.       break;
  455.       
  456.     case WM_COMMAND:
  457.       {
  458.         USHORT uCommand = SHORT1FROMMP( mp1 );
  459.         switch ( uCommand )
  460.         {
  461.           case MNU_CLOCK_NOTOP:
  462.           case MNU_CLOCK_TOPMOST:
  463.           case MNU_CLOCK_POPUP:
  464.           case MNU_CLOCK_POPUP2:
  465.             iTopmost = uCommand - MNU_CLOCK_NOTOP;
  466.             break;
  467.             
  468.           case MNU_CLOCK_BIND_OFF:
  469.           case MNU_CLOCK_BIND_NW:
  470.           case MNU_CLOCK_BIND_NE:
  471.           case MNU_CLOCK_BIND_SW:
  472.           case MNU_CLOCK_BIND_SE:
  473.             if ( ( iBindToCorner = uCommand - MNU_CLOCK_BIND_OFF ) > 0 )
  474.             {
  475.               int x = -1;
  476.               int y = -1;
  477.               if ( iBindToCorner == 1 || iBindToCorner == 2 )
  478.                 y = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) -
  479.                   iClockHeight[bLarge] + 1;
  480.               if ( iBindToCorner == 2 || iBindToCorner == 4 )
  481.                 x = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ) -
  482.                   CurrentWidth() + 1;
  483.               WinSetWindowPos( hwClockFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE );
  484.             }
  485.             break;
  486.  
  487.           case MNU_CLOCK_LOCKPOSITION:
  488.             bLockPosition ^= 1;
  489.             break;
  490.  
  491.           case MNU_CLOCK_MONO:
  492.             bMonochrome ^= 1;
  493.             InvalidateInside( hwnd );
  494.             break;
  495.  
  496.           case MNU_CLOCK_SECONDS:
  497.             bSeconds ^= 1;
  498.             InvalidateInside( hwnd );
  499.             WinPostMsg( hwnd, WM_COMMAND,
  500.               ( MPARAM ) ( MNU_CLOCK_SMALL + bLarge ), 0 );
  501.             break;
  502.  
  503.           case MNU_CLOCK_12H:
  504.             b12h ^= 1;
  505.             bClearIt = 1;
  506.             InvalidateInside( hwnd );
  507.             break;
  508.  
  509.           case MNU_CLOCK_PROPERTIES:
  510.             hwPrevWindow = HWND_TOP;
  511.             WinDlgBox( HWND_DESKTOP, hwClockFrame, PropertiesDlgProc,
  512.               hmSysBar2Dll, DLG_PROPERTIES, ( PVOID ) &DummyInit );
  513.             break;
  514.  
  515.           case MNU_CLOCK_SMALL:
  516.           case MNU_CLOCK_LARGE:
  517.             bLarge = uCommand - MNU_CLOCK_SMALL;
  518.             {
  519.               SWP Swp;
  520.               WinQueryWindowPos( hwClockFrame, &Swp );
  521.               WinInvalidateRect( hwClockFrame, NULL, TRUE );
  522.               WinSetWindowPos( hwClockFrame, HWND_TOP, 0, 0,
  523.                 CurrentWidth(), iClockHeight[bLarge],
  524.                 SWP_SIZE | SWP_SHOW );
  525.               if ( iBindToCorner ) WinPostMsg( hwnd, WM_COMMAND,
  526.                 ( MPARAM ) ( MNU_CLOCK_BIND_OFF + iBindToCorner ), 0 );
  527.             }
  528.             break;
  529.  
  530.           case MNU_CLOCK_SAVE:
  531.             SaveOptions();
  532.             break;
  533.             
  534.           case MNU_CLOCK_CLOSE:
  535.             WinPostMsg( hwClockFrame, WM_CLOSE, 0, 0 );
  536.             break;
  537.         }
  538.       }
  539.       break;
  540.  
  541.     case WM_BUTTON1DOWN:
  542.       bLastVisible = 0;
  543.       if ( ! bLockPosition )
  544.         WinPostMsg( hwClockFrame, WM_TRACKFRAME, ( MPARAM ) TF_MOVE, 0L );
  545.       break;
  546.       
  547.     case WM_BUTTON2CLICK:
  548.       bLastVisible = 0;
  549.       WinPopupMenu( hwnd, hwnd, hmPopupMenu, SHORT1FROMMP( mp1 ), 
  550.         SHORT2FROMMP( mp1 ), 0, PU_HCONSTRAIN | PU_VCONSTRAIN |
  551.         PU_NONE | PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 );
  552.       break;
  553.       
  554.     case WM_TIMER:
  555.       if ( ( USHORT ) ( mp1 ) == TID_USERMAX + 7 )
  556.       {
  557.         InvalidateInside( hwnd );
  558.  
  559.         short int bOnTop = iTopmost;
  560.  
  561.         if ( iTopmost >= 2 )
  562.         {
  563.           SWP swp;
  564.           WinQueryWindowPos( hwClockFrame, &swp );
  565.           POINTL ptl = { 0, 0 };
  566.           WinQueryPointerPos( HWND_DESKTOP, &ptl );
  567.           ptl.x -= swp.x;
  568.           ptl.y -= swp.y;
  569.           if ( ptl.x >= 0 && ptl.y >= 0 &&
  570.             ptl.x < CurrentWidth() && ptl.y < iClockHeight[bLarge] )
  571.           {
  572.             if ( ! bLastVisible ) bLastVisible = bOnTop = 1;
  573.           }
  574.           else if ( bLastVisible )
  575.           {
  576.             if ( iTopmost == 3 ) WinSetWindowPos( hwClockFrame, hwPrevWindow,
  577.               0L, 0L, 0L, 0L, SWP_ZORDER );
  578.             bLastVisible = 0;
  579.           }
  580.         }
  581.  
  582.         if ( bOnTop == 1 ) PopUpMainWindow();
  583.       }
  584.       break;
  585.  
  586.     case WM_ERASEBACKGROUND:
  587.       {
  588.         bClearIt = 1;
  589. /*        
  590.         HPS hps = ( HPS ) mp1;
  591.         SB2_Border( hps, 0, 0, iClockWidth[bLarge] - 1,
  592.           iClockHeight[bLarge] - 1, 1, SB2c_Filler, 1 );
  593.         SB2_Border( hps, 4, 3, iClockWidth[bLarge] - 5,
  594.           iClockHeight[bLarge] - 4, 0, CLR_BLACK );
  595. */          
  596.       }
  597.       break;
  598.  
  599.     case WM_PAINT:
  600.       {
  601.         HPS hps;
  602.         RECTL rc;
  603.         hps = WinBeginPaint( hwnd, 0L, &rc );
  604. /*  
  605.         // DC
  606.         DEVOPENSTRUC dop = { 0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L };
  607.         HDC hdcMem = DevOpenDC( hab, OD_MEMORY, "*", 5L,
  608.           ( PDEVOPENDATA ) & dop, NULLHANDLE );
  609.           
  610.         // PS  
  611.         SIZEL sizl = { 0, 0 };
  612.         HPS hpsMem = GpiCreatePS( hab, hdcMem, &sizl, GPIT_MICRO |
  613.           GPIA_ASSOC | PU_PELS );
  614.           
  615.         // bitmap  
  616.         BITMAPINFOHEADER2 bmih;  
  617.         memset( &bmih, 0, sizeof ( BITMAPINFOHEADER2 ) );
  618.         bmih.cbFix = sizeof ( BITMAPINFOHEADER2 );
  619.         bmih.cx = iClockWidth[bLarge];
  620.         bmih.cy = iClockHeight[bLarge];
  621.         bmih.cPlanes = 1;
  622.         bmih.cBitCount = 4;
  623.         HBITMAP hbMem = GpiCreateBitmap( hpsMem, &bmih, 0L, NULL, NULL );
  624.         GpiSetBitmap( hpsMem, hbMem );
  625. */
  626.         if ( bClearIt )
  627.         {
  628.           bClearIt = 0;
  629.           SB2_Border( hps, 0, 0, CurrentWidth() - 1,
  630.             iClockHeight[bLarge] - 1, 1, SB2c_Filler, 1 );
  631.           SB2_Border( hps, 4, 3, CurrentWidth() - 5,
  632.             iClockHeight[bLarge] - 4, 0, CLR_BLACK );
  633.         }
  634.  
  635.         DATETIME dtIn;
  636.         DosGetDateTime( &dtIn );
  637.         char szTimeBuf[11];
  638.         int iAMPM = 0;
  639.         if ( b12h )
  640.         {
  641.           if ( dtIn.hours >= 12 )
  642.           {
  643.             dtIn.hours -= 12;
  644.             iAMPM = 1;
  645.           }
  646.           if ( dtIn.hours == 0 ) dtIn.hours = 12;
  647.         }
  648.         short int bLess12 = ( dtIn.hours <= 9 );
  649.         sprintf( szTimeBuf, "%02i:%02i:%02i%02i", short ( dtIn.hours ),
  650.           short ( dtIn.minutes ), short ( dtIn.seconds ), short ( dtIn.day ) );
  651.         POINTL pt4[4];
  652.         if ( b12h )
  653.         {
  654.           SB2_LargeDigits( hps, 8, 6, szTimeBuf, bMonochrome, bLarge, 2 );
  655.           pt4[0].x = iDigitW[bLarge] * 2 + 10;
  656.           pt4[0].y = ( iClockHeight[bLarge] >> 1 ) + 1 + bLarge;
  657.           pt4[1].x = pt4[0].x - 1 + ( iClockMonthW[bLarge] / 3 );
  658.           pt4[1].y = pt4[0].y + iClockMonthH[bLarge] - 1;
  659.           pt4[2].x = iClockMonthW[bLarge] * 3 +
  660.             ( iAMPM ? ( iClockMonthW[bLarge] / 3 ) + 1 : 0 );
  661.           pt4[2].y = 0;
  662.           pt4[3].x = pt4[2].x + ( iClockMonthW[bLarge] / 3 );
  663.           pt4[3].y = iClockMonthH[bLarge];
  664.           GpiWCBitBlt( hps, hbMonths[bLarge][bMonochrome], 4L, pt4,
  665.             ROP_SRCCOPY, BBO_IGNORE );
  666.           SB2_LargeDigits( hps, iDigitW[bLarge] * 3 + 8, 6, szTimeBuf + 3,
  667.             bMonochrome, bLarge, bSeconds ? 5 : 2 );
  668.         }
  669.         else SB2_LargeDigits( hps, 8, 6, szTimeBuf, bMonochrome, bLarge,
  670.           bSeconds ? 8 : 5 );
  671.         SB2_SmallDigits( hps, CurrentWidth() - iClockMonthX[bLarge] + 1,
  672.           6, szTimeBuf + 8, bMonochrome, bLarge );
  673.         pt4[0].x = CurrentWidth() - iClockMonthX[bLarge];
  674.         pt4[0].y = ( iClockHeight[bLarge] >> 1 ) + 1 + bLarge;
  675.         pt4[1].x = pt4[0].x + iClockMonthW[bLarge] - 1;
  676.         pt4[1].y = pt4[0].y + iClockMonthH[bLarge] - 1;
  677.         pt4[2].x = ( dtIn.month - 1 ) * iClockMonthW[bLarge];
  678.         pt4[2].y = 0;
  679.         pt4[3].x = pt4[2].x + iClockMonthW[bLarge];
  680.         pt4[3].y = iClockMonthH[bLarge];
  681.         GpiWCBitBlt( hps, hbMonths[bLarge][bMonochrome], 4L, pt4,
  682.           ROP_SRCCOPY, BBO_IGNORE );
  683. /*        
  684.         pt4[0].x = 0;
  685.         pt4[0].y = 0;
  686.         pt4[1].x = iClockWidth[bLarge];
  687.         pt4[1].y = iClockHeight[bLarge];
  688.         pt4[2].x = 0;
  689.         pt4[2].y = 0;
  690.         pt4[3].x = iClockWidth[bLarge];
  691.         pt4[3].y = iClockHeight[bLarge];
  692.         GpiBitBlt( hps, hpsMem, 4L, pt4, ROP_SRCCOPY, BBO_IGNORE );
  693.         
  694.         GpiDeleteBitmap( hbMem );
  695.         GpiDestroyPS( hpsMem );
  696.         DevCloseDC( hdcMem );
  697. */          
  698.         WinEndPaint( hps );
  699.       }
  700.       break;
  701.       
  702.     case WM_CLOSE:
  703.       SaveOptions();
  704.       WinPostMsg( hwnd, WM_QUIT, 0, 0 );
  705.       break;
  706.       
  707.     case WM_DESTROY:
  708.       WinStopTimer( hab, hwnd, TID_USERMAX + 7 );
  709.       GpiDeleteBitmap( hbMonths[0][0] );
  710.       GpiDeleteBitmap( hbMonths[0][1] );
  711.       GpiDeleteBitmap( hbMonths[1][0] );
  712.       GpiDeleteBitmap( hbMonths[1][1] );
  713.       break;
  714.       
  715.     case WM_MOUSEMOVE:
  716.       if ( iTopmost >= 2 && ! bLastVisible ) PopUpMainWindow();
  717.  
  718.     default:
  719.       return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  720.   }
  721.   return ( MRESULT ) FALSE;
  722. }
  723.  
  724.  
  725. // Main procedure ------------------------------------------------------------
  726. int main( int argc, char *argv[] )
  727. {
  728.   HMQ hmq;
  729.   QMSG qmsg;
  730.   char szClassName[] = "SysBar2ClockClass";
  731.  
  732.   if ( ( hab = WinInitialize( 0 ) ) == 0L ) AbortStartup();
  733.   if ( ( hmq = WinCreateMsgQueue( hab, 0 ) ) == 0L ) AbortStartup();
  734.  
  735.   hmSysBar2Dll = SB2_Init();
  736.  
  737.   if ( ! WinRegisterClass( hab, ( PSZ ) szClassName, 
  738.     ( PFNWP ) ClockWinProc, 0L, 0 ) ) AbortStartup();
  739.  
  740.   pszIniFile = new char[strlen( argv[0] ) + 1];
  741.   SB2_CfgFilename( pszIniFile,  argv[0] );
  742.   
  743.   ULONG ulWinStyle = FCF_AUTOICON | FCF_ICON | FCF_NOBYTEALIGN | FCF_TASKLIST;
  744.     
  745.   if ( ( hwClockFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWinStyle,
  746.     szClassName, 0, 0, NULLHANDLE, ICO_MAIN, &hwClockClient ) ) == 0L )
  747.     AbortStartup();
  748.  
  749.   WinSetWindowText( hwClockFrame, "SysBar/2 Clock" );
  750.  
  751.   {
  752.     IniFile *pCfg = new IniFile( pszIniFile );
  753.     int x = 0, y = 0;
  754.     if ( pCfg && ( *pCfg )() )
  755.     {
  756.       x = atoi2( pCfg->Get( szSysBar2Clock, "x" ) );
  757.       y = atoi2( pCfg->Get( szSysBar2Clock, "y" ) );
  758.       iTopmost = atoi2( pCfg->Get( szSysBar2Clock, "topmost" ) ) & 3;
  759.       bMonochrome = ( strcmp2(
  760.         pCfg->Get( szSysBar2Clock, "monochrome" ), pszYesNo[1] ) == 0 );
  761.       bLarge = ( strcmp2(
  762.         pCfg->Get( szSysBar2Clock, "largesize" ), pszYesNo[1] ) == 0 );
  763.       b12h = ( strcmp2(
  764.         pCfg->Get( szSysBar2Clock, "12hmode" ), pszYesNo[1] ) == 0 );
  765.       bSeconds = ( strcmp2(
  766.         pCfg->Get( szSysBar2Clock, "seconds" ), pszYesNo[1] ) == 0 );
  767.       bLockPosition = ( strcmp2(
  768.         pCfg->Get( szSysBar2Clock, "lockposition" ), pszYesNo[1] ) == 0 );
  769.       iBindToCorner = atoi2( pCfg->Get( szSysBar2Clock, "cornerbind" ) );
  770.       if ( iBindToCorner > 4 || iBindToCorner < 0 ) iBindToCorner = 0;
  771.     }
  772.     delete pCfg;
  773.     if ( ! WinSetWindowPos( hwClockFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE ) ) 
  774.       AbortStartup();
  775.     else
  776.     {
  777.       WinPostMsg( hwClockFrame, WM_COMMAND,
  778.         ( MPARAM ) ( MNU_CLOCK_BIND_OFF + iBindToCorner ), 0L );
  779.       WinPostMsg( hwClockFrame, WM_COMMAND,
  780.         ( MPARAM ) ( MNU_CLOCK_SMALL + bLarge ), 0L );
  781.     }
  782.   }
  783.  
  784.   while( WinGetMsg( hab, &qmsg, 0L, 0, 0 ) ) WinDispatchMsg( hab, &qmsg );
  785.   
  786.   SB2_Over();
  787.  
  788.   WinDestroyWindow( hwClockFrame );
  789.   WinDestroyMsgQueue( hmq );
  790.   WinTerminate( hab );
  791.  
  792.   delete pszIniFile;
  793.   
  794.   return 0;
  795. }
  796.  
  797.