home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 December / VPR9712B.ISO / Nsos2 / OS2PLUG.EXE / SAMPLE / NPCLOCK / clock.cpp next >
Text File  |  1996-12-04  |  49KB  |  1,580 lines

  1. /***************************************************************************
  2.  *
  3.  * File name   :  clock.cpp
  4.  *
  5.  *  Copyright (C) 1996 IBM Corporation
  6.  *
  7.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  8.  *      sample code created by IBM Corporation. This sample code is not
  9.  *      part of any standard or IBM product and is provided to you solely
  10.  *      for  the purpose of assisting you in the development of your
  11.  *      applications.  The code is provided "AS IS", without
  12.  *      warranty of any kind.  IBM shall not be liable for any damages
  13.  *      arising out of your use of the sample code, even if they have been
  14.  *      advised of the possibility of such damages.
  15.  *
  16.  *
  17.  *  Contains:  Source code for the sample "Clock" part
  18.  *
  19.  *  Original PM App. Written by:  Steve Smith
  20.  *  Original OpenDoc App Written by: Chuck Dumont
  21.  *  Updated for Plugins by Michael Perks
  22.  *
  23.  ***************************************************************************/
  24.  
  25. #define INCL_WIN
  26. #define INCL_GPI
  27. #define INCL_DOSDATETIME
  28. #define INCL_DOSPROCESS
  29. #include <os2.h>
  30.  
  31. #include <time.h>
  32. #include <string.h>
  33.  
  34. #include "Clock.hpp"
  35.  
  36. POINTL aptlFillet1[]= {{53L ,63L },{ 70L ,50L },{68L,47L}} ;
  37. POINTL aptlFillet2[]= {{68L,47L},{ 70L, 50L },{56L ,67L }} ;
  38. POINTL aptlFillet3[]= {{53L ,64L },{ 56L ,62L },{60L,58L}} ;
  39. POINTL aptlFillet4[]= {{60L,58L},{ 60L, 63L },{56L ,67L }} ;
  40. POINTL ptlLight= { -1L , 1L } ;
  41. POINTL ptlShade= {  2L, -2L } ;
  42. POINTL ptlFace = { 0L, 0L};
  43.  
  44. static FIXED fxSin [60] =
  45. {
  46.     0x00000000, 0x00001ac2, 0x00003539, 0x00004f1b, 0x0000681f, 0x00007fff,
  47.     0x00009679, 0x0000ab4c, 0x0000be3e, 0x0000cf1b, 0x0000ddb3, 0x0000e9de,
  48.     0x0000f378, 0x0000fa67, 0x0000fe98, 0x0000ffff, 0x0000fe98, 0x0000fa67,
  49.     0x0000f378, 0x0000e9de, 0x0000ddb3, 0x0000cf1b, 0x0000be3e, 0x0000ab4c,
  50.     0x00009679, 0x00008000, 0x00006820, 0x00004f1b, 0x00003539, 0x00001ac2,
  51.     0x00000000, 0xffffe53e, 0xffffcac7, 0xffffb0e5, 0xffff97e1, 0xffff8001,
  52.     0xffff6988, 0xffff54b5, 0xffff41c2, 0xffff30e5, 0xffff224d, 0xffff1622,
  53.     0xffff0c88, 0xffff0599, 0xffff0168, 0xffff0001, 0xffff0167, 0xffff0599,
  54.     0xffff0c88, 0xffff1622, 0xffff224d, 0xffff30e5, 0xffff41c2, 0xffff54b4,
  55.     0xffff6987, 0xffff8000, 0xffff97e0, 0xffffb0e4, 0xffffcac6, 0xffffe53e
  56. } ;
  57.  
  58.  
  59. MATRIXLF vmatlfDateTrans = {
  60.      MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  61.      MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  62.      0L ,                      0L ,                      1L } ;
  63. MATRIXLF vmatlfDateScale  = {
  64.      MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  65.      MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  66.      0L ,                      0L ,                      1L } ;
  67.  
  68. /****************************************************************\
  69.  *
  70.  *--------------------------------------------------------------
  71.  *
  72.  *  Name:Clock()
  73.  *
  74.  *  Purpose:Intialize a newly created client window
  75.  *
  76.  *
  77.  *
  78.  *  Usage:
  79.  *
  80.  *  Method:
  81.  *
  82.  *  Returns:
  83.  *          1 - if sucessful execution completed
  84.  *          0 - if error
  85. \****************************************************************/
  86. Clock:: Clock()
  87. {
  88.     SIZEL sizl = { 200 , 200 };
  89.  
  90.     /* init the Data structure */
  91.  
  92.     /*
  93.      * Create our off-screen 'buffer'.
  94.      */
  95.  
  96.     data.hdcBuffer = DevOpenDC ( HAB(0), OD_MEMORY, (PSZ) "*", 0L, 0, 0);
  97.  
  98.     data.hpsBuffer = GpiCreatePS (HAB(0), data.hdcBuffer, &sizl, PU_ARBITRARY |
  99.                                GPIT_MICRO | GPIA_ASSOC);
  100.  
  101.     // Set the PS into RGB mode!
  102.     GpiCreateLogColorTable (data.hpsBuffer, 0, LCOLF_RGB, 0, 0, (PLONG)NULL);
  103.  
  104.     // if we don't read this in from storage unit.
  105.     {
  106.         data.cp.usMajorTickPref = CLKTM_ALWAYS;
  107.         data.cp.usMinorTickPref = CLKTM_NOTICONIC;
  108.         data.cp.clrBackground = 0x00008080;
  109.         data.cp.clrFace = 0x00008080;
  110.         data.cp.clrHourHand = RGB_RED;
  111.         data.cp.clrMinuteHand = RGB_RED;
  112.         data.cp.fControlsHidden = FALSE;
  113.         data.cp.usDispMode = DM_TIME | DM_ANALOG | DM_SECONDHAND;
  114.         // data.cp.usDispMode = DM_TIME | DM_DIGITAL | DM_SECONDHAND;
  115.         data.cp.alarm.uchHour = 0;
  116.         data.cp.alarm.uchMinutes = 0;
  117.         data.cp.alarm.usMode = 0;
  118.         SetRGBColors();
  119.         strcpy(data.szTimeSep,":");
  120.         strcpy(data.szAnteMeridian,"AM");
  121.         strcpy(data.szPostMeridian,"PM");
  122.         data.bTwelveHourFormat = TRUE;
  123.         data.fIconic = FALSE;
  124.     }
  125.  
  126.     /* get the time in a format for dislaying */
  127.     DosGetDateTime(&data.dt);
  128.     data.dt.hours = (UCHAR )(data.dt.hours * (UCHAR) 5) %
  129.                                            (UCHAR) 60 + data.dt.minutes / (UCHAR)12;
  130.  
  131.  
  132. }
  133.  
  134. /****************************************************************\
  135.  *
  136.  *--------------------------------------------------------------
  137.  *
  138.  *  Name: destructor
  139.  *
  140.  *  Purpose: Destroy clock face.
  141.  *
  142.  *
  143.  *
  144.  *  Usage:
  145.  *
  146.  *  Method:
  147.  *
  148.  *  Returns:VOID
  149.  *
  150.  *
  151. \****************************************************************/
  152. Clock:: ~Clock ()
  153. {
  154.     HBITMAP hbm;
  155.  
  156.     hbm = GpiSetBitmap (data.hpsBuffer, NULLHANDLE);
  157.  
  158.     if (hbm != NULLHANDLE)
  159.         GpiDeleteBitmap (hbm);
  160.  
  161.     GpiDestroyPS (data.hpsBuffer);
  162.     DevCloseDC (data.hdcBuffer);
  163. }
  164.  
  165. /****************************************************************\
  166.  *
  167.  *--------------------------------------------------------------
  168.  *
  169.  *  Name: CreateRegion
  170.  *
  171.  *  Purpose: Creates a region.
  172.  *
  173.  *
  174.  *
  175.  *  Usage:
  176.  *
  177.  *  Method:
  178.  *
  179.  *  Returns:VOID
  180.  *
  181.  *
  182. \****************************************************************/
  183. HRGN Clock:: CreateRegion( HPS hps )
  184. {
  185.     BOOL f ;
  186.     static POINTL ptlLight= { -2L , 2L } ;
  187.     static POINTL ptlShade= {  1L, -1L } ;
  188.     static POINTL ptlFace = { 0L, 0L};
  189.     static POINTL ptlShadeIn= { -3L , 3L } ;
  190.     static POINTL ptlLightIn= {  1L, -1L } ;
  191.     HRGN hRegion, hRegionTemp;
  192.     RECTL rclBounds;
  193.  
  194.     /*        1         0      0     *\
  195.     *         0         1      0      *
  196.     \*      100       100      1     */
  197.  
  198.     static MATRIXLF matlfModel = {
  199.     MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  200.     MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  201.     100L ,                      100L ,                      1L } ;
  202.  
  203.     /* center at (100, 100) and draw the clock face */
  204.     f = GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  205.                                      & matlfModel , TRANSFORM_REPLACE ) ;
  206.  
  207.     DrawFullCircle(hps,
  208.                    &ptlShade,
  209.                    MAKEFIXED(99 ,0));
  210.  
  211.     hRegion = GpiPathToRegion(hps, 1, FPATH_ALTERNATE);
  212.         GpiQueryRegionBox(hps, hRegion, &rclBounds);
  213.  
  214.     DrawFullCircle(hps,
  215.                    &ptlLight,
  216.                    MAKEFIXED(98 ,0));
  217.  
  218.     hRegionTemp = GpiPathToRegion(hps, 1, FPATH_ALTERNATE);
  219.     GpiCombineRegion(hps, hRegion, hRegion, hRegionTemp, CRGN_OR);
  220.     GpiDestroyRegion(hps, hRegionTemp);
  221.  
  222.     DrawFullCircle(hps,
  223.                    &ptlLightIn,
  224.                    MAKEFIXED(94,0));
  225.  
  226.     hRegionTemp = GpiPathToRegion(hps, 1, FPATH_ALTERNATE);
  227.     GpiCombineRegion(hps, hRegion, hRegion, hRegionTemp, CRGN_OR);
  228.     GpiDestroyRegion(hps, hRegionTemp);
  229.  
  230.     DrawFullCircle(hps,
  231.                    &ptlShadeIn,
  232.                    MAKEFIXED(93,0));
  233.  
  234.     hRegionTemp = GpiPathToRegion(hps, 1, FPATH_ALTERNATE);
  235.     GpiCombineRegion(hps, hRegion, hRegion, hRegionTemp, CRGN_OR);
  236.     GpiDestroyRegion(hps, hRegionTemp);
  237.  
  238.     DrawFullCircle(hps,
  239.                     &ptlFace ,
  240.                     MAKEFIXED(98 ,0));
  241.  
  242.     hRegionTemp = GpiPathToRegion(hps, 1, FPATH_ALTERNATE);
  243.     GpiCombineRegion(hps, hRegion, hRegion, hRegionTemp, CRGN_OR);
  244.     GpiDestroyRegion(hps, hRegionTemp);
  245.  
  246.     return hRegion;
  247. }
  248.  
  249. /****************************************************************\
  250.  *
  251.  *--------------------------------------------------------------
  252.  *
  253.  *  Name: Size()
  254.  *
  255.  *  Purpose:When the window has been sized, we calculate  a page
  256.  *          rectangle which: (a) fills the window rectangle in either
  257.  *          the x or y dimension, (b) appears square, and (c) is centered
  258.  *          in the window rectangle
  259.  *  Usage:
  260.  *
  261.  *  Method:
  262.  *
  263.  *  Returns:
  264.  *
  265.  *
  266. \****************************************************************/
  267. VOID Clock:: Size( RECTL& rcl, HRGN *hrgnUsed)
  268. {
  269.     SIZEF            sizef;
  270.  
  271.     LONG             cxSquare;
  272.     LONG             cySquare;
  273.  
  274.     LONG             cxEdge;
  275.     LONG             cyEdge;
  276.  
  277.     LONG             cyHeight;
  278.     LONG             cxWidth;
  279.  
  280.     HBITMAP          hbm;
  281.     BITMAPINFOHEADER bmp;
  282.  
  283.     HRGN             hOldRegion;
  284.     RECTL            rclBounds;
  285.  
  286.     LONG             cxRes;
  287.     LONG             cyRes;
  288.  
  289.     LONG             cColorPlanes;
  290.     LONG             cColorBitcount;
  291.  
  292.     BOOL             f;
  293.     SWP              swp;
  294.  
  295.     this-> rcl = rcl;
  296.  
  297.     /*
  298.      * First get rid of any buffer bitmap already there.
  299.      */
  300.     hbm = GpiSetBitmap (data.hpsBuffer, NULLHANDLE);
  301.  
  302.     if (hbm != NULLHANDLE)
  303.         GpiDeleteBitmap (hbm);
  304.  
  305.     /*
  306.      * Get the width and height of the window rectangle.
  307.      */
  308.     cxWidth = rcl.xRight - rcl.xLeft;
  309.     cyHeight = rcl.yTop - rcl.yBottom;
  310.  
  311.     /*
  312.      * Now create a bitmap the size of the window.
  313.      */
  314.  
  315.     //KLS Get device info from desktop window.
  316.     HPS hps;                /* presentation space handle            */
  317.     HDC hdc;                /* device context handle                */
  318.     LONG lWidth, lHeight;
  319.  
  320.     DevQueryCaps (data.hdcBuffer, CAPS_COLOR_PLANES, 1L, &cColorPlanes);
  321.     DevQueryCaps (data.hdcBuffer, CAPS_COLOR_BITCOUNT, 1L, &cColorBitcount);
  322.     DevQueryCaps (data.hdcBuffer, (LONG)CAPS_VERTICAL_RESOLUTION,(LONG) 1L, &cyRes);
  323.     DevQueryCaps (data.hdcBuffer, CAPS_HORIZONTAL_RESOLUTION, 1L, &cxRes);
  324.  
  325.     bmp.cbFix = sizeof(BITMAPINFOHEADER);
  326.     bmp.cx = (SHORT)cxWidth;
  327.     bmp.cy = (SHORT)cyHeight;
  328.     bmp.cPlanes = (SHORT)cColorPlanes;
  329.     bmp.cBitCount = (SHORT)cColorBitcount;
  330.     hbm = GpiCreateBitmap(data.hpsBuffer, (PBITMAPINFOHEADER2)&bmp,
  331.                           0x0000, (PBYTE)NULL, (PBITMAPINFO2)NULL);
  332.     GpiSetBitmap (data.hpsBuffer, hbm);
  333.  
  334.     /*
  335.      * Assume the size of the page rectangle is constrained in the y
  336.      * dimension,compute the x size which would make the rectangle appear
  337.      * square, then check the assumption and do the reverse calculation
  338.      * if necessary.
  339.      */
  340.     cySquare = cyHeight;
  341.     cxSquare = ( cyHeight * cxRes ) / cyRes;
  342.  
  343.     if (cxWidth < cxSquare)
  344.     {
  345.         cxSquare = cxWidth;
  346.         cySquare = (cxWidth * cyRes) / cxRes;
  347.     }
  348.  
  349.     /*
  350.      * Fill in the page rectangle and set the page viewport.
  351.      */
  352.     cxEdge = (cxWidth - cxSquare ) / 2;
  353.     cyEdge = (cyHeight - cySquare ) / 2;
  354.     rclPage.xLeft = cxEdge;
  355.     rclPage.xRight = cxWidth - cxEdge;
  356.     rclPage.yBottom = cyEdge;
  357.     rclPage.yTop = cyHeight - cyEdge;
  358.  
  359.     f = GpiSetPageViewport (data.hpsBuffer, &rclPage);
  360.  
  361.  
  362.     *hrgnUsed = CreateRegion(data.hpsBuffer);
  363.  
  364. //  if (data.hrgnFace != 0)
  365. //     GpiDestroyRegion(data.hpsBuffer, data.hrgnFace);
  366.  
  367. //  data.hrgnFace = CreateFaceRegion(data.hpsBuffer);
  368.  
  369.     GpiQueryCharBox(data.hpsBuffer, &sizef);
  370.     GpiSetCharBox(data.hpsBuffer, &sizef);
  371.     data.fBufferDirty = TRUE;
  372. }
  373.  
  374. /****************************************************************\
  375.  *
  376.  *--------------------------------------------------------------
  377.  *
  378.  *  Name: DrawAnalog()
  379.  *
  380.  *  Purpose:Draw the clock face ,hand and minute hand,
  381.  *
  382.  *
  383.  *
  384.  *  Usage:
  385.  *
  386.  *  Method:
  387.  *
  388.  *  Returns: void
  389.  *
  390.  *
  391. \****************************************************************/
  392. void Clock:: DrawAnalog(HPS hpsDraw, BOOL fTransparent)
  393. {
  394.     HPS hps;
  395.     if (hpsDraw)
  396.        hps = hpsDraw;
  397.     else
  398.        hps = data.hpsBuffer;
  399.  
  400.     /* draw the face, the hour hand, and the minute hand */
  401.  
  402.     if (!fTransparent) {
  403.       POINTL ptl = {-101, -101};
  404.       GpiSetColor ( hps , data.vclrFace[SURFACE]);
  405.       GpiMove(hps, &ptl);
  406.       ptl.x = ptl.y = 100;
  407.       GpiBox(hps, DRO_FILL, &ptl, 0, 0);
  408.  
  409.       DrawRing (hps, data.vclrRing, data.vclrFace);
  410.  
  411.       DrawFace (hps, data.vclrFace);
  412.     }
  413.  
  414.     DrawHand (hps, HT_HOUR_SHADE, data.dt.hours, data.vclrFace, data.vclrHands);
  415.  
  416.     DrawHand (hps, HT_MINUTE_SHADE, data.dt.minutes, data.vclrFace, data.vclrHands);
  417.  
  418.     DrawHand (hps, HT_HOUR, data.dt.hours, data.vclrFace, data.vclrHands);
  419.  
  420.     DrawHand (hps, HT_MINUTE, data.dt.minutes, data.vclrFace, data.vclrHands);
  421.  
  422.     /* draw the tick marks */
  423.     DrawTicks (hps, CLK_MAJORTICKS, data.vclrMajorTicks, data.vclrMinorTicks);
  424.  
  425.     DrawTicks (hps, CLK_MINORTICKS, data.vclrMajorTicks, data.vclrMinorTicks);
  426. }
  427.  
  428. /****************************************************************\
  429.  *
  430.  *--------------------------------------------------------------
  431.  *
  432.  *  Name:DrawDigitalTime()
  433.  *
  434.  *  Purpose:
  435.  *
  436.  *
  437.  *
  438.  *  Usage:
  439.  *
  440.  *  Method:
  441.  *          -
  442.  *
  443.  *  Returns: void
  444.  *
  445. \****************************************************************/
  446.  
  447. VOID Clock::DrawDigitalTime(HPS hpsDraw, RECTL & rcl, BOOL fTransparent)
  448. {
  449.     RECTL rclChar;
  450.     RECTL rclCharOld;
  451.     RECTL rclTime;
  452.     RECTL rclAmPm;
  453.     RECTL rclDate;
  454.     SIZEF sizef;
  455.     USHORT usi;
  456.     ULONG  ulCharWidth,ulCharModulu;
  457.     char achTime[9];
  458.     char achFinalDate[9];
  459.     time_t     tTime;
  460.     struct tm  *pLocalTime;
  461.  
  462.     memset(achTime,0,sizeof(achTime) );
  463.     memset(achFinalDate,0,sizeof(achFinalDate) );
  464.  
  465.     GpiCreateLogColorTable (hpsDraw, LCOL_RESET, LCOLF_RGB, 0, 0,
  466.                                  (PLONG) NULL);
  467.  
  468.     /*
  469.      *if black hands and black background
  470.      *selected force the background to
  471.      *blue
  472.      */
  473.  
  474.     if( !data.cp.clrMinuteHand && !data.cp.clrBackground )
  475.     {
  476.           data.cp.clrBackground = RGB_BLUE;
  477.     }
  478.  
  479.  
  480.  
  481.     switch (data.cp.usDispMode & (DM_TIME | DM_DATE))
  482.     {
  483.     case DM_DATE:
  484.         rclDate = rcl;
  485.         break;
  486.  
  487.     case DM_TIME | DM_DATE:
  488.         if (!data.fIconic)
  489.         {
  490.             rclTime = rclDate = rcl;
  491.             rclTime.yBottom = rclDate.yTop = rcl.yTop / 2;
  492.             break;
  493.         } /*else fall through*/
  494.  
  495.     case DM_TIME:
  496.         rclTime = rcl;
  497.         break;
  498.     }
  499.  
  500.     if (data.cp.usDispMode & DM_TIME)
  501.     {
  502.  
  503.         rclAmPm = rclTime;
  504.         time(&tTime);
  505.         pLocalTime = localtime(&tTime);
  506.         if (data.bTwelveHourFormat)
  507.         {
  508.            strftime(achTime, sizeof(achTime), "%I %M %S", pLocalTime);
  509.         }
  510.         else
  511.         {
  512.            strftime(achTime, sizeof(achTime), "%H %M %S", pLocalTime);
  513.         }
  514.  
  515.         /*insert country time separator*/
  516.         achTime[2] = achTime[5] = data.szTimeSep[0];
  517.         achTime[8] = '\000';
  518.         /*Process 12 hours mode*/
  519.         if (data.bTwelveHourFormat)
  520.         {
  521.  
  522.             if (data.fIconic)
  523.             {
  524.                 rclTime.yBottom = rclAmPm.yTop = rclTime.yTop / 2;
  525.             }
  526.             else
  527.             {
  528.                 rclTime.xRight = rcl.xRight * 8 / 11;
  529.                 rclAmPm.xLeft = rclTime.xRight;
  530.             }
  531.  
  532.             strcpy(data.achAmPm,data.szAnteMeridian);
  533.  
  534.             if (pLocalTime->tm_hour >= 12)
  535.             {
  536.                 strcpy(data.achAmPm,data.szPostMeridian);
  537.             }
  538.  
  539.         }
  540.  
  541.         GpiSetCharMode(hpsDraw, CM_MODE3);
  542.  
  543.         if (data.fIconic)
  544.         {
  545.             sizef.cx = MAKEFIXED(LOUSHORT((rclTime.xRight - rclTime.xLeft)
  546.                     / 3), 0);
  547.             sizef.cy = MAKEFIXED(LOUSHORT((rclTime.yTop - rclTime.yBottom)
  548.                     * 1400 / 1000), 0);
  549.         }
  550.         else
  551.         {
  552.             sizef.cx = MAKEFIXED(LOUSHORT((rclTime.xRight - rclTime.xLeft)
  553.                     / 6), 8000);
  554.             sizef.cy = MAKEFIXED(LOUSHORT((rclTime.yTop - rclTime.yBottom)
  555.                     * 1000 / 1500), 0);
  556.         }
  557.  
  558.         GpiSetCharBox(hpsDraw, &sizef);
  559.  
  560.         if (data.bTwelveHourFormat)
  561.         {
  562.  
  563.             if( strcmp(data.achAmPm,data.achOldAmPm) )
  564.             {
  565.                 //WinFillRect(hpsDraw, &rclAmPm, data.cp.clrBackground);
  566.                 if (!fTransparent)
  567.                   FillRect(hpsDraw, rclAmPm);
  568.                 WinDrawText(hpsDraw, sizeof(data.achAmPm) - 1, (PSZ)data.achAmPm,
  569.                         (PRECTL)&rclAmPm, data.cp.clrMinuteHand, data.cp.clrBackground,
  570.                         DT_CENTER | DT_VCENTER );
  571.             }
  572.         }
  573.  
  574.         if (!data.fIconic)
  575.         {
  576.  
  577.             WinDrawText(hpsDraw, sizeof(achTime) - 1 , (PSZ)achTime,
  578.                     (PRECTL)&rclTime, data.cp.clrMinuteHand, data.cp.clrBackground,
  579.                     DT_CENTER | DT_VCENTER | DT_QUERYEXTENT);
  580.  
  581.             ulCharWidth = (rclTime.xRight - rclTime.xLeft) / (sizeof(achTime) - 1 );
  582.             ulCharModulu = (rclTime.xRight - rclTime.xLeft) % (sizeof(achTime) - 1 );
  583.             rclCharOld.xRight = rclTime.xLeft;
  584.  
  585.             rclChar.yTop = rclTime.yTop;
  586.             rclChar.yBottom = rclTime.yBottom;
  587.  
  588.             for (usi = 0; usi < (sizeof(achTime)); usi++)
  589.             {
  590.                 rclChar.xLeft = rclCharOld.xRight + (ULONG)1;
  591.                 rclChar.xRight = rclChar.xLeft + ulCharWidth +
  592.                         ((ulCharModulu > 0L) ? 1L : 0L);
  593.  
  594.                 if (ulCharModulu)
  595.                     ulCharModulu--;
  596.  
  597.                 if (achTime[usi] == data.szTimeSep[0])
  598.                 {
  599.                     rclChar.xRight -= 3;
  600.                 }
  601.                 else
  602.                 {
  603.                     rclChar.xRight += 1;
  604.                 }
  605.  
  606.                 rclCharOld = rclChar;
  607.  
  608.                 if (achTime[usi] != data.achOldTime[usi] )
  609.                 {
  610.                     // WinFillRect (hpsDraw, &rclChar, data.cp.clrBackground);
  611.                     if (!fTransparent)
  612.                       FillRect(hpsDraw, rclChar);
  613.  
  614.                     if (!((usi == 0) && (achTime[0] == '0') &&
  615.                             (data.bTwelveHourFormat)))
  616.                         WinDrawText (hpsDraw, 1, (PSZ)&achTime[usi], &rclChar,
  617.                                 data.cp.clrMinuteHand, data.cp.clrBackground,
  618.                                 DT_CENTER | DT_VCENTER);
  619.                 }
  620.             }
  621.         }
  622.         else
  623.         {   /*Iconic. just draw if minute changed*/
  624.  
  625.             if (strncmp(achTime,data.achOldTime,5))
  626.             {
  627.                 //WinFillRect(hpsDraw,&rclTime,data.cp.clrBackground);
  628.                 if (!fTransparent)
  629.                   FillRect(hpsDraw, rclTime);
  630.  
  631.                 WinDrawText(hpsDraw, sizeof(achTime) - 4 , (PSZ)achTime,
  632.                         (PRECTL)&rclTime, data.cp.clrMinuteHand, data.cp.clrBackground,
  633.                         DT_CENTER | DT_VCENTER);
  634.             }
  635.         }
  636.     }
  637.  
  638.     if ((!(data.cp.usDispMode & DM_TIME)) || ((data.cp.usDispMode & DM_DATE) &&
  639.             (!data.fIconic)))
  640.     {
  641.         GetArrangedDate(achFinalDate);
  642.         if (strncmp(achFinalDate, data.achOldDate,
  643.                 sizeof(achFinalDate) - data.fIconic ? 4 : 1))
  644.         {
  645.  
  646.             if (!fTransparent)
  647.               WinFillRect (hpsDraw, &rclDate, data.cp.clrBackground);
  648.  
  649.             GpiSetCharMode (hpsDraw, CM_MODE3);
  650.  
  651.             sizef.cx = MAKEFIXED(LOUSHORT(
  652.                             (rclDate.xRight - rclDate.xLeft) / 5), 0);
  653.             sizef.cy = MAKEFIXED(LOUSHORT(
  654.                             (rclDate.yTop - rclDate.yBottom) * 1000 / 1500), 0);
  655.  
  656.             GpiSetCharBox(hpsDraw, &sizef);
  657.             WinDrawText(hpsDraw,
  658.                         (sizeof(achFinalDate) - (data.fIconic ? 4 : 1) ),
  659.                         (PSZ)achFinalDate,(PRECTL)&rclDate,
  660.                         (LONG)data.cp.clrMinuteHand,
  661.                         (LONG)data.cp.clrBackground,
  662.                         (ULONG )(DT_CENTER | DT_VCENTER ) );
  663.         }
  664.     }
  665.  
  666.     strncpy(data.achOldTime,achTime,sizeof(data.achOldTime));
  667.     strncpy(data.achOldAmPm,data.achAmPm,sizeof(data.achOldAmPm));
  668.     strncpy(data.achOldDate,achFinalDate,sizeof(data.achOldDate));
  669. }
  670.  
  671. /****************************************************************\
  672.  *
  673.  *--------------------------------------------------------------
  674.  *
  675.  *  Name: Draw
  676.  *
  677.  *  Purpose: Paint the clock client window.
  678.  *
  679.  *
  680.  *
  681.  *  Usage:
  682.  *
  683.  *  Method:
  684.  *
  685.  *  Returns:  void
  686.  *
  687.  *
  688. \****************************************************************/
  689. void Clock::Draw( HPS hps, PRECTL rclFrame, BOOL toScreen, BOOL fTransparent)
  690. {
  691.  
  692.    RECTL rcl = *rclFrame;
  693.    ULONG cxFrame = rclFrame->xRight - rclFrame->xLeft;
  694.    ULONG cyFrame = rclFrame->yTop - rclFrame->yBottom;
  695.    if (cxFrame > cyFrame)
  696.    {
  697.       rcl.xLeft += ((cxFrame - cyFrame) / 2);
  698.       rcl.xRight = rcl.xLeft + cyFrame;
  699.    }
  700.    else if (cxFrame < cyFrame)
  701.    {
  702.       rcl.yBottom += ((cyFrame - cxFrame) / 2);
  703.       rcl.yTop = rcl.yBottom + cxFrame;
  704.    }
  705.  
  706.    // Set the PS into RGB mode!
  707.    GpiCreateLogColorTable (hps, 0, LCOLF_RGB, 0, 0, (PLONG)NULL);
  708.  
  709.    GpiSetColor(hps, data.vclrFace[SURFACE]);
  710.  
  711.    if (!fTransparent) {
  712.      POINTL ptl = {0, 0};
  713.      GpiMove(hps, &ptl);
  714.      ptl.x = rclFrame->xRight;
  715.      ptl.y = rclFrame->yTop;
  716.      GpiBox(hps, DRO_FILL, &ptl, 0, 0);
  717.    }
  718.  
  719.    MATRIXLF mtlf, mtlfSave;
  720.    FIXED afxScale[2] = { (rcl.xRight - rcl.xLeft) * 0x10000 / 200,
  721.                          (rcl.yTop - rcl.yBottom) * 0x10000 / 200 };
  722.    POINTL ptlOffset = {rcl.xLeft, rcl.yBottom}, ptlScaleOffset = {0, 0};
  723.    GpiScale(hps, &mtlf, TRANSFORM_REPLACE, afxScale, &ptlScaleOffset);
  724.    GpiTranslate(hps, &mtlf, TRANSFORM_ADD, &ptlOffset);
  725.    GpiQueryDefaultViewMatrix(hps, 9, &mtlfSave);
  726.    GpiSetDefaultViewMatrix(hps, 9, &mtlf, TRANSFORM_PREEMPT);
  727.  
  728.    if (data.cp.usDispMode & DM_ANALOG)
  729.    {
  730.        if (toScreen && !fTransparent)
  731.        {
  732.           if ( data. fBufferDirty )
  733.           {
  734.              DrawAnalog(0,fTransparent);
  735.              data. fBufferDirty = FALSE;
  736.           }
  737.           GpiSetDefaultViewMatrix(hps, 9, &mtlfSave, TRANSFORM_REPLACE);
  738.           UpdateScreen (hps, &rcl);
  739.           GpiSetDefaultViewMatrix(hps, 9, &mtlf, TRANSFORM_PREEMPT);
  740.        }
  741.        else
  742.        {
  743.            DrawAnalog(hps,fTransparent);
  744.        }
  745.  
  746.        DrawHand( hps, HT_SECOND, data.dt.seconds, data.vclrFace, data.vclrHands );
  747.    }
  748.    else
  749.    { /*For now, if it is not Analog, it must be digital*/
  750.  
  751.  
  752.        // WinFillRect (hps, &rcl, data.cp.clrBackground);
  753.        // FillRect(hps, rcl);
  754.        memset (data.achOldTime, 0, sizeof(data.achOldTime));
  755.        memset (data.achOldAmPm, 0, sizeof(data.achOldAmPm));
  756.        memset (data.achOldDate, 0, sizeof(data.achOldDate));
  757.  
  758.        // DrawDigitalTime (hps, rcl);
  759.  
  760.    }
  761.  
  762. }
  763.  
  764. /****************************************************************\
  765.  *  Name:Timer()
  766.  *
  767.  *  Purpose: Handles window timer events
  768.  *
  769.  *  Usage:
  770.  *
  771.  *  Method:
  772.  *
  773.  *  Returns:
  774. \****************************************************************/
  775. BOOL Clock:: Timer ( HPS hps, PRECTL rclFrame)
  776. {
  777.     HRGN hrgnInvalid = 0;
  778.  
  779.    RECTL rcl = *rclFrame;
  780.    ULONG cxFrame = rclFrame->xRight - rclFrame->xLeft;
  781.    ULONG cyFrame = rclFrame->yTop - rclFrame->yBottom;
  782.    if (cxFrame > cyFrame)
  783.    {
  784.       rcl.xLeft += ((cxFrame - cyFrame) / 2);
  785.       rcl.xRight = rcl.xLeft + cyFrame;
  786.    }
  787.    else if (cxFrame < cyFrame)
  788.    {
  789.       rcl.yBottom += ((cyFrame - cxFrame) / 2);
  790.       rcl.yTop = rcl.yBottom + cxFrame;
  791.    }
  792.  
  793.     // Set the PS into RGB mode!
  794.     GpiCreateLogColorTable (hps, 0, LCOLF_RGB, 0, 0, (PLONG)NULL);
  795.  
  796.     DATETIME  dtNew;
  797.     static LONG lTimeChangeCheck = 0L;
  798.     LONG  lTime;
  799.     BOOL invalidate = FALSE;
  800.  
  801.     if (data.cp.usDispMode & DM_ANALOG)
  802.     {
  803.       /* get the new time */
  804.       DosGetDateTime (&dtNew);
  805.  
  806.       /* adjust the hour hand */
  807.       dtNew.hours = (dtNew.hours * (UCHAR) 5 ) % (UCHAR) 60
  808.                     + dtNew.minutes / (UCHAR)12;
  809.  
  810.       /* if we must move the hour and minute hands, redraw it all */
  811.       if (dtNew.minutes != data. dt.minutes)
  812.       {
  813.           DrawFace (data. hpsBuffer, data.vclrFace);
  814.           DrawHand (data. hpsBuffer, HT_HOUR_SHADE, dtNew.hours, data.vclrFace, data.vclrHands);
  815.           DrawHand (data. hpsBuffer, HT_MINUTE_SHADE, dtNew.minutes, data.vclrFace, data.vclrHands);
  816.           DrawHand (data. hpsBuffer, HT_HOUR, dtNew.hours, data.vclrFace, data.vclrHands);
  817.           DrawHand (data. hpsBuffer, HT_MINUTE, dtNew.minutes, data.vclrFace, data.vclrHands);
  818.           invalidate = TRUE;
  819.       }
  820.       else /* otherwise just undraw the old second hand and draw the new */
  821.       {
  822.           MATRIXLF mtlf;
  823.           FIXED afxScale[2] = { (rcl.xRight - rcl.xLeft) * 0x10000 / 200,
  824.                                 (rcl.yTop - rcl.yBottom) * 0x10000 / 200 };
  825.           POINTL ptlOffset = {rcl.xLeft, rcl.yBottom}, ptlScaleOffset = {0, 0};
  826.           GpiScale(hps, &mtlf, TRANSFORM_REPLACE, afxScale, &ptlScaleOffset);
  827.           GpiTranslate(hps, &mtlf, TRANSFORM_ADD, &ptlOffset);
  828.           GpiSetDefaultViewMatrix(hps, 9, &mtlf, TRANSFORM_PREEMPT);
  829.  
  830.           GpiSetMix(hps, FM_INVERT);
  831.           DrawHand( hps, HT_SECOND, data. dt.seconds, data.vclrFace, data.vclrHands);
  832.           DrawHand( hps, HT_SECOND, dtNew.seconds, data.vclrFace, data.vclrHands);
  833.           GpiSetMix(hps, FM_OVERPAINT);
  834.       }
  835.       data. dt = dtNew ;
  836.     }
  837.     else /*Must be Digital*/
  838.     {
  839.       if(data.fBufferDirty)
  840.       {
  841.         FillRect(hps, rcl);
  842.         memset (data.achOldTime, 0, sizeof(data.achOldTime));
  843.         memset (data.achOldAmPm, 0, sizeof(data.achOldAmPm));
  844.         memset (data.achOldDate, 0, sizeof(data.achOldDate));
  845.         data. fBufferDirty = FALSE;
  846.       }
  847.       DrawDigitalTime(hps, rcl, FALSE);
  848.       invalidate = TRUE;
  849.     }
  850.     return invalidate;
  851. }
  852.  
  853. /****************************************************************\
  854.  *
  855.  *--------------------------------------------------------------
  856.  *
  857.  *  Name:UpdateScreen()
  858.  *
  859.  *  Purpose: Update the screen area.
  860.  *
  861.  *
  862.  *
  863.  *  Usage:
  864.  *
  865.  *  Method:
  866.  *
  867.  *  Returns:
  868.  *
  869.  *
  870. \****************************************************************/
  871. VOID Clock:: UpdateScreen (HPS hps, PRECTL rclFrame)
  872. {
  873.     POINTL aptl[4];
  874.     HBITMAP hbm;
  875.  
  876.     aptl[0].x = rclFrame->xLeft;
  877.     aptl[0].y = rclFrame->yBottom;
  878.     aptl[1].x = rclFrame->xRight;
  879.     aptl[1].y = rclFrame->yTop;
  880.     aptl[2].x = this->rclPage.xLeft;
  881.     aptl[2].y = this->rclPage.yBottom;
  882.     aptl[3].x = this->rclPage.xRight;
  883.     aptl[3].y = this->rclPage.yTop;
  884.  
  885.     hbm = GpiSetBitmap(data.hpsBuffer, 0);      // Get the bitmap from the presentation space
  886.  
  887.     IMAGEBUNDLE ibundle;
  888.     LONG lRop;
  889.     GpiQueryDefAttrs(hps, PRIM_IMAGE, IBB_MIX_MODE, &ibundle);
  890.     lRop = (ibundle.usMixMode == FM_NOTCOPYSRC) ? ROP_NOTSRCCOPY : ROP_SRCCOPY;
  891.  
  892.     GpiWCBitBlt (hps, hbm, 4L, aptl, lRop, BBO_IGNORE);
  893.     GpiSetBitmap(data.hpsBuffer, hbm);          // Set bitmap back into pres space
  894. }
  895.  
  896. /**************************************************************************\
  897. *                                                                          *
  898. *       ROUTINE:    DrawHand                                            *
  899. *                                                                          *
  900. *       COMMENT:    Draws specified hand at specified hour in given PS     *
  901. *                                                                          *
  902. \**************************************************************************/
  903.  
  904. void Clock:: DrawHand ( HPS hps , SHORT sHandType , SHORT sAngle, LONG vclrFace[], LONG vclrHands[] )
  905. {
  906.     static POINTL aptlHour [ ] = { { 6 , 0 } , { 0 , 62 } , { -6 , 0 } ,
  907.                                    { 0 , -14 } , { 6 , 0 } } ;
  908.     static POINTL aptlHourLine1 [] = {{0L,-10L},{0L,56}};
  909.  
  910.     static POINTL aptlMinute [ ] = { { 5 , 0 } , { 0 , 77 } , { -5 , 0 } ,
  911.                                      { 0 , -14 } , { 5 , 0 } } ;
  912.     static POINTL aptlMinuteLine1 [] = {{0L,-15L},{0L,72}};
  913.  
  914.     static POINTL aptlSecond [ ] = { { 0 , -15 } , { 0 , 74 } } ;
  915.     static POINTL ptlOrigin = {0L,0L};
  916.  
  917.     static LONG cptlHour = sizeof ( aptlHour ) / sizeof ( POINTL ) ;
  918.     static LONG cptlMinute = sizeof ( aptlMinute ) / sizeof ( POINTL ) ;
  919.     static LONG cptlSecond = sizeof ( aptlSecond ) / sizeof ( POINTL ) ;
  920.     BOOL f ;
  921.  
  922.     static MATRIXLF matlfModel =
  923.     {
  924.         MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  925.         MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  926.         100L ,                      100L ,                      1L } ;
  927.  
  928.     static MATRIXLF matlfShade =
  929.     {
  930.         MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  931.         MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  932.         3L ,                     -3L ,                      1L } ;
  933.  
  934.     /* prepare a rotation transform and set it into the ps */
  935.     /*      cos x    - sin x    0     *\
  936.     |       sin x      cos x    0      |
  937.     \*      100        100      1     */
  938.  
  939.     matlfModel.fxM11 =
  940.     matlfModel.fxM22 = fxSin[(sAngle + 15) % 60];
  941.     matlfModel.fxM12 = fxSin[(sAngle + 30) % 60];
  942.     matlfModel.fxM21 = fxSin[sAngle];
  943.  
  944.     f = GpiSetModelTransformMatrix(hps, (LONG)MATLF_SIZE, &matlfModel, TRANSFORM_REPLACE);
  945.  
  946.     /* draw the specified hand */
  947.  
  948.     switch ( sHandType )
  949.     {
  950.  
  951.         case HT_HOUR:
  952.             GpiSetColor ( hps , vclrHands[SURFACE] ) ;
  953.             GpiBeginPath ( hps , 1L ) ;
  954.             GpiSetCurrentPosition ( hps , aptlHour ) ;
  955.             GpiPolyLine ( hps , cptlHour , aptlHour ) ;
  956.             GpiEndPath ( hps ) ;
  957.             GpiFillPath ( hps , 1L , FPATH_ALTERNATE ) ;
  958.             GpiSetColor ( hps , vclrHands[SHADE]   ) ;
  959.             GpiSetCurrentPosition ( hps , aptlHour ) ;
  960.             GpiPolyLine ( hps , cptlHour , aptlHour ) ;
  961.             GpiSetColor ( hps , vclrHands[SHADE]   ) ;
  962.             GpiSetCurrentPosition ( hps , aptlHourLine1 ) ;
  963.             GpiPolyLine ( hps , 1L , &(aptlHourLine1[1]) ) ;
  964.             break;
  965.         case HT_HOUR_SHADE:
  966.             GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  967.                                               & matlfShade , TRANSFORM_ADD     ) ;
  968.             GpiSetColor ( hps , vclrFace [SHADE]   ) ;
  969.             GpiBeginPath ( hps , 1L ) ;
  970.             GpiSetCurrentPosition ( hps , aptlHour ) ;
  971.             GpiPolyLine ( hps , cptlHour , aptlHour ) ;
  972.             GpiEndPath ( hps ) ;
  973.             GpiFillPath ( hps , 1L , FPATH_ALTERNATE ) ;
  974.             break;
  975.  
  976.         case HT_MINUTE:
  977.             GpiSetColor ( hps , vclrHands[SURFACE] ) ;
  978.             GpiBeginPath ( hps , 1L ) ;
  979.             GpiSetCurrentPosition ( hps , aptlMinute ) ;
  980.             GpiPolyLine ( hps , cptlMinute , aptlMinute ) ;
  981.             GpiEndPath ( hps ) ;
  982.             GpiFillPath ( hps , 1L , FPATH_ALTERNATE ) ;
  983.  
  984.             GpiSetColor ( hps , vclrHands[SHADE]   ) ;
  985.             GpiSetCurrentPosition ( hps , aptlMinute ) ;
  986.             GpiPolyLine ( hps , cptlMinute , aptlMinute ) ;
  987.             GpiSetColor ( hps , vclrHands[SHADE]   ) ;
  988.             GpiSetCurrentPosition ( hps , aptlMinuteLine1 ) ;
  989.             GpiPolyLine ( hps , 1L , &(aptlMinuteLine1[1]) ) ;
  990.             GpiSetCurrentPosition ( hps , & ptlOrigin) ;
  991.             GpiFullArc ( hps , DRO_OUTLINEFILL , MAKEFIXED ( 2 , 0 ) ) ;
  992.             break;
  993.         case HT_MINUTE_SHADE:
  994.             GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  995.                                               & matlfShade , TRANSFORM_ADD     ) ;
  996.             GpiSetColor ( hps , vclrFace [SHADE]   ) ;
  997.             GpiBeginPath ( hps , 1L ) ;
  998.             GpiSetCurrentPosition ( hps , aptlMinute ) ;
  999.             GpiPolyLine ( hps , cptlMinute , aptlMinute ) ;
  1000.             GpiEndPath ( hps ) ;
  1001.             GpiFillPath ( hps , 1L , FPATH_ALTERNATE ) ;
  1002.             break;
  1003.  
  1004.         case HT_SECOND:
  1005.             /* draw in XOR mixmode, so we can undraw later */
  1006.             GpiSetMix ( hps , FM_INVERT ) ;
  1007.             GpiSetCurrentPosition ( hps , aptlSecond ) ;
  1008.             GpiPolyLine ( hps , cptlSecond , aptlSecond ) ;
  1009.             GpiSetMix ( hps , FM_OVERPAINT ) ;
  1010.             break;
  1011.     }
  1012. }
  1013.  
  1014. /****************************************************************\
  1015.  *
  1016.  *--------------------------------------------------------------
  1017.  *
  1018.  *  Name:DrawFace()
  1019.  *
  1020.  *  Purpose:
  1021.  *
  1022.  *
  1023.  *
  1024.  *  Usage:
  1025.  *
  1026.  *  Method:
  1027.  *
  1028.  *  Returns: void
  1029.  *
  1030.  *
  1031. \****************************************************************/
  1032. void Clock:: DrawFace ( HPS hps, LONG vclrFace[] )
  1033. {
  1034.     BOOL f ;
  1035.     static POINTL ptlLight= { -2L , 2L } ;
  1036.     static POINTL ptlShade= {  2L, -2L } ;
  1037.     static POINTL ptlFace = { 0L, 0L};
  1038.     /*        1         0      0     *\
  1039.     *         0         1      0      *
  1040.     \*      100       100      1     */
  1041.  
  1042.     static MATRIXLF matlfModel = {
  1043.         MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  1044.         MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  1045.         100L ,                      100L ,                      1L } ;
  1046.  
  1047.     /* center at (100, 100) and draw the clock face */
  1048.     f = GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  1049.                                      & matlfModel , TRANSFORM_REPLACE ) ;
  1050.  
  1051.  
  1052.     GpiSetColor ( hps , vclrFace[SURFACE]);
  1053.     GpiSetCurrentPosition ( hps , & ptlFace ) ;
  1054.     GpiFullArc ( hps , DRO_OUTLINEFILL , MAKEFIXED ( 80, 0 ) ) ;
  1055.  
  1056.     FATTRS fat;
  1057.     POINTL grad = { 1, 4 };
  1058.     POINTL aptlPoints[TXTBOX_COUNT];
  1059.     LONG lcid = 244;
  1060.     memset(&fat, 0, sizeof(FATTRS));
  1061.     fat.usRecordLength = sizeof(FATTRS);
  1062.     strcpy(fat.szFacename, "Helv Bold");
  1063.     fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
  1064.     if (FONT_MATCH == GpiCreateLogFont( hps, 0, lcid, &fat))
  1065.     {
  1066.        FONTMETRICS fm;
  1067.        GpiSetCharSet(hps, lcid);
  1068.        GpiQueryFontMetrics(hps, sizeof(fm), &fm);
  1069.        GpiSetCharShear(hps, &grad);
  1070.        SIZEF sizfxBox ;
  1071.        sizfxBox.cy = MAKEFIXED(20,0);
  1072.        sizfxBox.cx = 20 * fm.lEmHeight * 0x10000 / fm.lEmInc;
  1073.        GpiSetCharBox(hps, &sizfxBox);
  1074.     }
  1075.     POINTL ptlString ;
  1076.     GpiSetColor ( hps, vclrFace[SHADE]);
  1077.     GpiSetTextAlignment(hps, TA_CENTER, TA_HALF);
  1078.     ptlString.x = 0;
  1079.     ptlString.y = 40;
  1080.     GpiCharStringAt ( hps, &ptlString, 8, (PCH) "Netscape");
  1081.     ptlString.y = -45;
  1082.     GpiCharStringAt ( hps, &ptlString, 4, (PCH) "OS/2");
  1083.  
  1084.     GpiDeleteSetId(hps, lcid);
  1085. }
  1086.  
  1087. /****************************************************************\
  1088.  *
  1089.  *--------------------------------------------------------------
  1090.  *
  1091.  *  Name:CreateFaceRegion()
  1092.  *
  1093.  *  Purpose:
  1094.  *
  1095.  *
  1096.  *
  1097.  *  Usage:
  1098.  *
  1099.  *  Method:
  1100.  *
  1101.  *  Returns: void
  1102.  *
  1103.  *
  1104. \****************************************************************/
  1105. HRGN Clock:: CreateFaceRegion ( HPS hps )
  1106. {
  1107.     BOOL f ;
  1108.     static POINTL ptlFace = { 0L, 0L};
  1109.     /*        1         0      0     *\
  1110.     *         0         1      0      *
  1111.     \*      100       100      1     */
  1112.  
  1113.     static MATRIXLF matlfModel = {
  1114.         MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  1115.         MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  1116.         100L ,                      100L ,                      1L } ;
  1117.  
  1118.     /* center at (100, 100) and draw the clock face */
  1119.     f = GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  1120.                                      & matlfModel , TRANSFORM_REPLACE ) ;
  1121.  
  1122.     GpiBeginPath(hps, 1);
  1123.     GpiSetCurrentPosition ( hps , & ptlFace ) ;
  1124.     GpiFullArc ( hps , DRO_OUTLINE , MAKEFIXED ( 80, 0 ) ) ;
  1125.     GpiEndPath (hps);
  1126.     return GpiPathToRegion(hps, 1, FPATH_ALTERNATE);
  1127. }
  1128.  
  1129. void Clock:: DrawRing ( HPS hps, LONG vclrRing[], LONG vclrFace[] )
  1130. {
  1131.     BOOL f ;
  1132.     static POINTL ptlLight= { -2L , 2L } ;
  1133.     static POINTL ptlShade= {  1L, -1L } ;
  1134.     static POINTL ptlFace = { 0L, 0L};
  1135.     static POINTL ptlShadeIn= { -3L , 3L } ;
  1136.     static POINTL ptlLightIn= {  1L, -1L } ;
  1137.     /*        1         0      0     *\
  1138.     *         0         1      0      *
  1139.     \*      100       100      1     */
  1140.  
  1141.     static MATRIXLF matlfModel = {
  1142.         MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  1143.         MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  1144.         100L ,                      100L ,                      1L } ;
  1145.  
  1146.     /* center at (100, 100) and draw the clock face */
  1147.     f = GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  1148.                                      & matlfModel , TRANSFORM_REPLACE ) ;
  1149.  
  1150.     DrawFullRing(hps,
  1151.                     &ptlShade,
  1152.                     MAKEFIXED(95,0),
  1153.                     MAKEFIXED(99 ,0),
  1154.                     vclrRing[SHADE]);
  1155.  
  1156.     DrawFullRing(hps,
  1157.                     &ptlLight,
  1158.                     MAKEFIXED(95,0),
  1159.                     MAKEFIXED(98 ,0),
  1160.                     vclrRing[LIGHT]   );
  1161.  
  1162.     DrawFullRing(hps,
  1163.                     &ptlLightIn,
  1164.                     MAKEFIXED(88,0),
  1165.                     MAKEFIXED(94,0),
  1166.                     vclrRing[LIGHT]   );
  1167.  
  1168.  
  1169.     DrawFullRing(hps,
  1170.                     &ptlShadeIn,
  1171.                     MAKEFIXED(86,0),
  1172.                     MAKEFIXED(93,0),
  1173.                     vclrRing[SHADE]);
  1174.  
  1175.     DrawFullRing(hps,
  1176.                     &ptlFace ,
  1177.                     MAKEFIXED(94,0),
  1178.                     MAKEFIXED(98 ,0),
  1179.                     vclrRing[SURFACE]);
  1180.  
  1181.     GpiSetColor ( hps , vclrFace[SURFACE]);
  1182.     GpiSetCurrentPosition ( hps , & ptlFace ) ;
  1183.     GpiFullArc ( hps , DRO_OUTLINEFILL , MAKEFIXED ( 91, 0 ) ) ;
  1184. }
  1185.  
  1186. void Clock:: DrawFullCircle(HPS hps, PPOINTL pptlCenter, FIXED fxRad)
  1187. {
  1188.     GpiSetCurrentPosition ( hps , pptlCenter );
  1189.     GpiBeginPath(hps,1L);
  1190.     GpiFullArc ( hps , DRO_OUTLINE ,  fxRad  ) ;
  1191.     GpiEndPath(hps);
  1192. }
  1193.  
  1194. /****************************************************************\
  1195.  *
  1196.  *--------------------------------------------------------------
  1197.  *
  1198.  *  Name:GetArrangedDate()
  1199.  *
  1200.  *  Purpose:
  1201.  *
  1202.  *
  1203.  *
  1204.  *  Usage:
  1205.  *
  1206.  *  Method:
  1207.  *
  1208.  *  Returns: VOID
  1209.  *
  1210. \****************************************************************/
  1211. VOID Clock:: GetArrangedDate(CHAR achFinalDate[])
  1212. {
  1213.     time_t     tTime;
  1214.     struct tm  *pLocalTime;
  1215.  
  1216.     time(&tTime);
  1217.     pLocalTime = localtime(&tTime);
  1218.     strftime(achFinalDate, sizeof(achFinalDate), "%m %d %y", pLocalTime);
  1219.  
  1220.     /*put date separators*/
  1221.     achFinalDate[2] = achFinalDate[5] = '/';
  1222.     achFinalDate[8] = '\0';
  1223. }
  1224.  
  1225. /****************************************************************\
  1226.  *
  1227.  *--------------------------------------------------------------
  1228.  *
  1229.  *  Name:DrawTicks()
  1230.  *
  1231.  *  Purpose:Draws Clock Ticks()
  1232.  *
  1233.  *
  1234.  *
  1235.  *  Usage:
  1236.  *
  1237.  *  Method:
  1238.  *
  1239.  *  Returns: void
  1240.  *
  1241.  *
  1242. \****************************************************************/
  1243. void Clock:: DrawTicks ( HPS hps , USHORT usTicks, LONG vclrMajorTicks[], LONG vclrMinorTicks[] )
  1244. {
  1245.     BOOL f ;
  1246.     USHORT usAngle,usTrapez ;
  1247.  
  1248.     /* prepare a transform to use when rotating the ticks */
  1249.     /*      cos x    - sin x    0     *\
  1250.     |       sin x      cos x    0      |
  1251.     \*      100        100      1     */
  1252.  
  1253.     static MATRIXLF matlfModel = {
  1254.         MAKEFIXED ( 1 , 0 ) ,       MAKEFIXED ( 0 , 0 ) ,       0L ,
  1255.         MAKEFIXED ( 0 , 0 ) ,       MAKEFIXED ( 1 , 0 ) ,       0L ,
  1256.         100L ,                      100L ,                      1L } ;
  1257.  
  1258.     /* define what the tick marks look like */
  1259.     static POINTL aptlMajorTick [ ] = { { -3 , 94 } , { 3 , 100 } } ;
  1260.     static BYTE   aclr [12][4] = {
  1261.             /*12*/        {SHADE,LIGHT,LIGHT,SHADE},
  1262.             /*1*/         {LIGHT,LIGHT,LIGHT,SHADE},
  1263.             /*2*/         {LIGHT,LIGHT,SHADE,SHADE},
  1264.             /*3*/         {LIGHT,LIGHT,SHADE,SHADE},
  1265.             /*4*/         {LIGHT,LIGHT,SHADE,LIGHT},
  1266.             /*5*/         {LIGHT,SHADE,SHADE,LIGHT},
  1267.             /*6*/         {LIGHT,SHADE,SHADE,LIGHT},
  1268.             /*7*/         {LIGHT,SHADE,SHADE,LIGHT},
  1269.             /*8*/         {LIGHT,SHADE,LIGHT,LIGHT},
  1270.             /*9*/         {SHADE,SHADE,LIGHT,LIGHT},
  1271.             /*9*/         {SHADE,SHADE,LIGHT,LIGHT},
  1272.             /*11*/        {SHADE,LIGHT,LIGHT,SHADE}
  1273.                                  };
  1274.     static  POINTL aptlMT  [4][4] = {
  1275.                                   { {-3,81},{-1,83},{1,83},{3,81  }} ,
  1276.                                   { {-3,81},{-1,83},{-1,87},{-3,89 }} ,
  1277.                                   { {-3,89},{-1,87},{1,87},{3,89 }} ,
  1278.                                   { {3,89},{1,87},{1,83},{3,81  }}
  1279.                                  };
  1280.     static POINTL aptlMajorTickShadow [ ] = { { -1 , 83 } , { 1 , 87  } } ;
  1281.     static POINTL aptlMinorTick [ ] = { { 0 , 83 } , { 0 , 85 } } ;
  1282.  
  1283.     /* have we been asked to draw the major ticks? */
  1284.     if ( usTicks & CLK_MAJORTICKS )
  1285.     {
  1286.         for ( usAngle = 0 ; usAngle < 60 ; usAngle += 5 )
  1287.         {
  1288.             /* set the rotation transform */
  1289.             matlfModel . fxM11 =
  1290.             matlfModel . fxM22 = fxSin [ ( usAngle + 15 ) % 60 ] ;
  1291.             matlfModel . fxM12 = fxSin [ ( usAngle + 30 ) % 60 ] ;
  1292.             matlfModel . fxM21 = fxSin [ usAngle ] ;
  1293.             f = GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  1294.                                              & matlfModel ,
  1295.                                              TRANSFORM_REPLACE ) ;
  1296.  
  1297.             /* draw a major tick mark */
  1298.             for (usTrapez = 0; usTrapez < 4; usTrapez++)
  1299.             {
  1300.                 DrawTrapez(hps,aptlMT[usTrapez],vclrMajorTicks[aclr[usAngle/5][usTrapez]]);
  1301.             }
  1302.             GpiSetColor ( hps , vclrMajorTicks[SURFACE]) ;
  1303.             GpiSetCurrentPosition ( hps , & aptlMajorTickShadow [ 0 ] ) ;
  1304.             GpiBox ( hps , DRO_FILL , & aptlMajorTickShadow [ 1 ] , 0L , 0L ) ;
  1305.         }
  1306.     }
  1307.  
  1308.     /* have we been asked to draw the minor ticks? */
  1309.     /* draw in the default color */
  1310.     GpiSetColor ( hps ,vclrMinorTicks[SHADE]  ) ;
  1311.     if ( usTicks & CLK_MINORTICKS )
  1312.     {
  1313.         for ( usAngle = 0 ; usAngle < 60 ; usAngle ++ )
  1314.         {
  1315.             if ((usAngle % 5) != 0)
  1316.             {
  1317.                 matlfModel . fxM11 =
  1318.                 matlfModel . fxM22 = fxSin [ ( usAngle + 15 ) % 60 ] ;
  1319.                 matlfModel . fxM12 = fxSin [ ( usAngle + 30 ) % 60 ] ;
  1320.                 matlfModel . fxM21 = fxSin [ usAngle ] ;
  1321.  
  1322.                 /* set the transform */
  1323.                 f = GpiSetModelTransformMatrix ( hps , ( LONG ) MATLF_SIZE ,
  1324.                                                  & matlfModel ,
  1325.                                                  TRANSFORM_REPLACE ) ;
  1326.  
  1327.                 /* draw a minor tick mark */
  1328.                 GpiSetCurrentPosition ( hps , & aptlMinorTick [ 0 ] ) ;
  1329.                 GpiBox ( hps , DRO_OUTLINEFILL , & aptlMinorTick [ 1 ] , 0L , 0L ) ;
  1330.             }
  1331.        }
  1332.     }
  1333. }
  1334. /****************************************************************\
  1335.  *
  1336.  *--------------------------------------------------------------
  1337.  *
  1338.  *  Name:DrawTrapez()
  1339.  *
  1340.  *  Purpose:
  1341.  *
  1342.  *
  1343.  *
  1344.  *  Usage:
  1345.  *
  1346.  *  Method:
  1347.  *
  1348.  *  Returns:
  1349.  *
  1350.  *
  1351. \****************************************************************/
  1352. void Clock:: DrawTrapez(HPS hps,POINTL *aptl,LONG color)
  1353. {
  1354.     GpiSetColor ( hps,color) ;
  1355.     GpiBeginPath(hps, 1L);                  /* start the path bracket */
  1356.     GpiSetCurrentPosition ( hps ,  aptl  ) ;
  1357.     GpiPolyLine(hps, 3L,&(aptl[1]) );      /* draw the three sides   */
  1358.     GpiCloseFigure(hps);                    /* close the triangle     */
  1359.     GpiEndPath(hps);                        /* end the path bracket   */
  1360.     GpiFillPath(hps, 1L, FPATH_ALTERNATE);  /* draw and fill the path */
  1361. }
  1362. /****************************************************************\
  1363.  *
  1364.  *--------------------------------------------------------------
  1365.  *
  1366.  *  Name:DrawFullRing()
  1367.  *
  1368.  *  Purpose: This routine draws the ring for the clock face.
  1369.  *
  1370.  *
  1371.  *
  1372.  *  Usage:
  1373.  *
  1374.  *  Method:
  1375.  *
  1376.  *  Returns:
  1377.  *
  1378.  *
  1379. \****************************************************************/
  1380. void Clock:: DrawFullRing(HPS hps,PPOINTL pptlCenter,FIXED fxRadIn, FIXED fxRadOut,
  1381.                      LONG lColor)
  1382. {
  1383.     GpiSetColor(hps,lColor);
  1384.     GpiSetCurrentPosition ( hps , pptlCenter );
  1385.     GpiBeginPath(hps,1L);
  1386.     GpiFullArc ( hps , DRO_OUTLINE ,  fxRadIn  ) ;
  1387.     GpiFullArc ( hps , DRO_OUTLINE ,  fxRadOut  ) ;
  1388.     GpiCloseFigure(hps);
  1389.     GpiEndPath(hps);
  1390.     GpiFillPath ( hps , 1L , FPATH_ALTERNATE ) ;
  1391. }
  1392.  
  1393. /****************************************************************\
  1394.  *
  1395.  *--------------------------------------------------------------
  1396.  *
  1397.  *  Name: SetRGBColors
  1398.  *
  1399.  *  Purpose: Set the RGB schema so that each time a user changes the
  1400.  *           color we update it here.
  1401.  *
  1402.  *
  1403.  *  Usage:
  1404.  *
  1405.  *  Method:
  1406.  *
  1407.  *  Returns:VOID
  1408.  *
  1409.  *
  1410. \****************************************************************/
  1411. VOID Clock:: SetRGBColors()
  1412. {
  1413.  
  1414.     data.vclrFace[SURFACE]       = data.cp.clrFace;
  1415.     data.vclrBG[SURFACE]         = data.cp.clrBackground;
  1416.     data.vclrHands[SURFACE]      = data.cp.clrMinuteHand;
  1417.     data.vclrMajorTicks[SURFACE] = data.cp.clrHourHand;
  1418.  
  1419.     /*Fill color tables*/
  1420.     ShadeLight(data.vclrMajorTicks);
  1421.  
  1422.     data.vclrMinorTicks[SURFACE] = data.vclrFace[SURFACE];
  1423.     ShadeLight(data.vclrMinorTicks);
  1424.  
  1425.     ShadeLight(data.vclrFace);
  1426.  
  1427.     data.vclrRing[SURFACE] = data.vclrFace[SURFACE];
  1428.     ShadeLight(data.vclrRing);
  1429.  
  1430.     ShadeLight(data.vclrHands);
  1431.     data.vclrHands[SHADE] = RGB_BLACK;
  1432.  
  1433.     ShadeLight(data.vclrBG);
  1434. }
  1435. /****************************************************************\
  1436.  *
  1437.  *--------------------------------------------------------------
  1438.  *
  1439.  *  Name:ShadeLight()
  1440.  *
  1441.  *  Purpose: Find the shade and light color index values and
  1442.  *           install them in the colors   array of the element
  1443.  *
  1444.  *
  1445.  *
  1446.  *  Usage:
  1447.  *
  1448.  *  Method:
  1449.  *
  1450.  *  Returns:
  1451.  *
  1452.  *
  1453. \****************************************************************/
  1454. VOID Clock:: ShadeLight(PLONG nplColors)
  1455. {
  1456.    typedef  union  _RGBLONG
  1457.    {
  1458.         RGB rgb;
  1459.         LONG lng;
  1460.    } RGBLONG ;
  1461.    RGBLONG  rgbSurface,rgbShade,rgbLight;
  1462.  
  1463.    rgbSurface.lng = rgbShade.lng = rgbLight.lng = 0L;
  1464.  
  1465.    rgbSurface.lng = nplColors[SURFACE];
  1466.    rgbShade.rgb.bBlue = ShadeRGBByte(rgbSurface.rgb.bBlue);
  1467.    rgbShade.rgb.bRed = ShadeRGBByte(rgbSurface.rgb.bRed);
  1468.    rgbShade.rgb.bGreen = ShadeRGBByte(rgbSurface.rgb.bGreen);
  1469.    rgbLight.rgb.bBlue = LightRGBByte(rgbSurface.rgb.bBlue);
  1470.    rgbLight.rgb.bRed = LightRGBByte(rgbSurface.rgb.bRed);
  1471.    rgbLight.rgb.bGreen = LightRGBByte(rgbSurface.rgb.bGreen);
  1472.    nplColors[SHADE] = rgbShade.lng;
  1473.    nplColors[LIGHT] = rgbLight.lng;
  1474. }
  1475.  
  1476.  
  1477. /****************************************************************\
  1478.  *
  1479.  *--------------------------------------------------------------
  1480.  *
  1481.  *  Name:ShadeRGBByte
  1482.  *
  1483.  *  Purpose:
  1484.  *
  1485.  *
  1486.  *
  1487.  *  Usage:
  1488.  *
  1489.  *  Method:
  1490.  *
  1491.  *  Returns:
  1492.  *
  1493.  *
  1494. \****************************************************************/
  1495.  
  1496. BYTE Clock:: ShadeRGBByte(BYTE brgb)
  1497. {
  1498.   #define SHADER   ( (BYTE) 0x50)
  1499.  
  1500.   if (brgb > SHADER)
  1501.   {
  1502.      return (brgb - SHADER);
  1503.   }
  1504.   else
  1505.   {
  1506.      return (0);
  1507.   }
  1508.  
  1509. }
  1510. /****************************************************************\
  1511.  *
  1512.  *--------------------------------------------------------------
  1513.  *
  1514.  *  Name:LightRGBByte
  1515.  *
  1516.  *  Purpose:
  1517.  *
  1518.  *
  1519.  *
  1520.  *  Usage:
  1521.  *
  1522.  *  Method:
  1523.  *
  1524.  *  Returns:
  1525.  *
  1526.  *
  1527. \****************************************************************/
  1528. BYTE Clock:: LightRGBByte(BYTE brgb)
  1529. {
  1530.  
  1531.   #define LIGHTER  ( (BYTE) 0x40)
  1532.  
  1533.   if (brgb < (0xff - LIGHTER) )
  1534.   {
  1535.      return (brgb + LIGHTER);
  1536.   }
  1537.  
  1538.   else return (0xff);
  1539.  
  1540. }
  1541.  
  1542. /****************************************************************\
  1543.  *
  1544.  *--------------------------------------------------------------
  1545.  *
  1546.  *  Name:  FillRect
  1547.  *
  1548.  *  Purpose: Fills background space when win calls cannot be made
  1549.  *
  1550.  *
  1551.  *
  1552.  *  Usage:
  1553.  *
  1554.  *  Method:
  1555.  *
  1556.  *  Returns:
  1557.  *
  1558.  *
  1559. \****************************************************************/
  1560. void Clock::FillRect(HPS hpsDraw, RECTL & rcl)
  1561. {
  1562.  
  1563.   long lColor = GpiQueryColor(hpsDraw);
  1564.   GpiSetColor(hpsDraw, data.cp.clrBackground);
  1565.   POINTL ptl1, ptl2;
  1566.   ptl1.x = rcl.xLeft;
  1567.   ptl1.y = rcl.yBottom;
  1568.   ptl2.x = rcl.xRight;
  1569.   ptl2.y = rcl.yTop;
  1570.   GpiMove(hpsDraw, &ptl1);
  1571.   GpiBox(hpsDraw, DRO_FILL, &ptl2, 0, 0);
  1572.   GpiSetColor(hpsDraw, lColor);
  1573. }
  1574.  
  1575. void Clock::SetMode(USHORT dispMode)
  1576. {
  1577.   data.cp.usDispMode = dispMode;
  1578.   data.fBufferDirty = TRUE;
  1579. }
  1580.