home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / oclock / Clock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  15.6 KB  |  580 lines

  1. /*
  2.  * $XConsortium: Clock.c,v 1.24 91/05/22 17:20:31 converse Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. /*
  25.  * Clock.c
  26.  *
  27.  * a NeWS clone clock
  28.  */
  29.  
  30. #include <X11/IntrinsicP.h>
  31. #include <X11/StringDefs.h>
  32. #include <X11/Xmu/Converters.h>
  33. #include "ClockP.h"
  34. #include <X11/Xos.h>
  35. #include <stdio.h>
  36. #include <math.h>
  37. #include <X11/extensions/shape.h>
  38.  
  39. #ifdef X_NOT_STDC_ENV
  40. extern struct tm *localtime();
  41. #endif
  42.  
  43. #define offset(field) XtOffsetOf(ClockRec, clock.field)
  44. #define goffset(field) XtOffsetOf(WidgetRec, core.field)
  45.  
  46. static XtResource resources[] = {
  47.     {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  48.         goffset(width), XtRImmediate, (XtPointer) 120},
  49.     {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  50.     goffset(height), XtRImmediate, (XtPointer) 120},
  51.     {XtNminute, XtCForeground, XtRPixel, sizeof (Pixel),
  52.     offset(minute), XtRString, XtDefaultForeground},
  53.     {XtNhour, XtCForeground, XtRPixel, sizeof (Pixel),
  54.     offset(hour), XtRString, XtDefaultForeground},
  55.     {XtNjewel, XtCForeground, XtRPixel, sizeof (Pixel),
  56.     offset(jewel), XtRString, XtDefaultForeground},
  57.     {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
  58.         offset (backing_store), XtRString, "default"},
  59.     {XtNborderSize, XtCBorderSize, XtRFloat, sizeof (float),
  60.     offset (border_size), XtRString, "0.1"},
  61.     {XtNjewelSize, XtCBorderSize, XtRFloat, sizeof (float),
  62.     offset (jewel_size), XtRString, "0.075"},
  63.     {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean),
  64.     offset (shape_window), XtRImmediate, (XtPointer) True},
  65.     {XtNtransparent, XtCTransparent, XtRBoolean, sizeof (Boolean),
  66.     offset (transparent), XtRImmediate, (XtPointer) False},
  67. };
  68.  
  69. #undef offset
  70. #undef goffset
  71.  
  72. static void     new_time();
  73.  
  74. static void Initialize(), Realize(), Destroy(), Redisplay(), Resize();
  75.  
  76. # define BORDER_SIZE(w)    ((w)->clock.border_size)
  77. # define WINDOW_WIDTH(w)    (2.0 - BORDER_SIZE(w)*2)
  78. # define WINDOW_HEIGHT(w)   (2.0 - BORDER_SIZE(w)*2)
  79. # define MINUTE_WIDTH(w)    (0.05)
  80. # define HOUR_WIDTH(w)        (0.05)
  81. # define JEWEL_SIZE(w)        ((w)->clock.jewel_size)
  82. # define MINUTE_LENGTH(w)   (JEWEL_Y(w) - JEWEL_SIZE(w) / 2.0)
  83. # define HOUR_LENGTH(w)        (MINUTE_LENGTH(w) * 0.6)
  84. # define JEWEL_X(w)        (0.0)
  85. # define JEWEL_Y(w)        (1.0 - (BORDER_SIZE(w) + JEWEL_SIZE(w)))
  86.  
  87. static void ClassInitialize();
  88.  
  89. ClockClassRec clockClassRec = {
  90.     { /* core fields */
  91.     /* superclass        */    &widgetClassRec,
  92.     /* class_name        */    "Clock",
  93.     /* size            */    sizeof(ClockRec),
  94.     /* class_initialize        */    ClassInitialize,
  95.     /* class_part_initialize    */    NULL,
  96.     /* class_inited        */    FALSE,
  97.     /* initialize        */    Initialize,
  98.     /* initialize_hook        */    NULL,
  99.     /* realize            */    Realize,
  100.     /* actions            */    NULL,
  101.     /* num_actions        */    0,
  102.     /* resources        */    resources,
  103.     /* num_resources        */    XtNumber(resources),
  104.     /* xrm_class        */    NULLQUARK,
  105.     /* compress_motion        */    TRUE,
  106.     /* compress_exposure    */    TRUE,
  107.     /* compress_enterleave    */    TRUE,
  108.     /* visible_interest        */    FALSE,
  109.     /* destroy            */    Destroy,
  110.     /* resize            */    Resize,
  111.     /* expose            */    Redisplay,
  112.     /* set_values        */    NULL,
  113.     /* set_values_hook        */    NULL,
  114.     /* set_values_almost    */    NULL,
  115.     /* get_values_hook        */    NULL,
  116.     /* accept_focus        */    NULL,
  117.     /* version            */    XtVersion,
  118.     /* callback_private        */    NULL,
  119.     /* tm_table            */    NULL,
  120.     /* query_geometry        */    XtInheritQueryGeometry,
  121.     }
  122. };
  123.  
  124. static void ClassInitialize()
  125. {
  126.     XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
  127.             NULL, 0 );
  128. }
  129.  
  130. WidgetClass clockWidgetClass = (WidgetClass) &clockClassRec;
  131.  
  132. /* ARGSUSED */
  133. static void Initialize (greq, gnew)
  134.     Widget greq, gnew;
  135. {
  136.     ClockWidget w = (ClockWidget)gnew;
  137.     XtGCMask    valuemask;
  138.     XGCValues    myXGCV;
  139.     int shape_event_base, shape_error_base;
  140.  
  141.     valuemask = GCForeground;
  142.  
  143.     if (w->clock.transparent)
  144.     {
  145.     ;
  146.     }
  147.     else
  148.     {
  149.         myXGCV.foreground = w->clock.minute;
  150.         w->clock.minuteGC = XtGetGC(gnew, valuemask, &myXGCV);
  151.  
  152.         myXGCV.foreground = w->clock.hour;
  153.         w->clock.hourGC = XtGetGC(gnew, valuemask, &myXGCV);
  154.  
  155.         myXGCV.foreground = w->clock.jewel;
  156.         w->clock.jewelGC = XtGetGC(gnew, valuemask, &myXGCV);
  157.     
  158.         myXGCV.foreground = w->core.background_pixel;
  159.         w->clock.eraseGC = XtGetGC(gnew, valuemask, &myXGCV);
  160.     }
  161.  
  162.     /* wait for Realize to add the timeout */
  163.     w->clock.interval_id = 0;
  164.  
  165.     if (w->clock.shape_window && !XShapeQueryExtension (XtDisplay (w), 
  166.                             &shape_event_base, 
  167.                             &shape_error_base))
  168.     w->clock.shape_window = False;
  169.     w->clock.shape_mask = 0;
  170.     w->clock.shapeGC = 0;
  171.     w->clock.shape_width = 0;
  172.     w->clock.shape_height = 0;
  173.     w->clock.polys_valid = 0;
  174. }
  175.  
  176. static void Resize (w)
  177.     ClockWidget    w;
  178. {
  179.     XGCValues    xgcv;
  180.     Widget    parent;
  181.     XWindowChanges    xwc;
  182.     int        face_width, face_height;
  183.     int        x, y;
  184.     Pixmap    shape_mask;
  185.  
  186.     if (!XtIsRealized((Widget) w))
  187.     return;
  188.  
  189.     /*
  190.      * compute desired border size
  191.      */
  192.  
  193.     SetTransform (&w->clock.maskt,
  194.           0, w->core.width,
  195.           w->core.height, 0,
  196.           -1.0, 1.0,
  197.            -1.0, 1.0);
  198.  
  199.     face_width = abs (Xwidth (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt));
  200.     face_height = abs (Xheight (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt));
  201.  
  202.     /*
  203.      *  shape the windows and borders
  204.      */
  205.  
  206.     if (w->clock.shape_window) {
  207.  
  208.     SetTransform (&w->clock.t,
  209.             face_width, w->core.width - face_width,
  210.             w->core.height - face_height, face_height,
  211.             -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2,
  212.             -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2);
  213.     
  214.     /*
  215.      * allocate a pixmap to draw shapes in
  216.      */
  217.  
  218.     if (w->clock.shape_mask &&
  219.         (w->clock.shape_width != w->core.width ||
  220.          w->clock.shape_height != w->core.height))
  221.     {
  222.         XFreePixmap (XtDisplay (w), w->clock.shape_mask);
  223.         w->clock.shape_mask = None;
  224.     }
  225.     
  226.     if (!w->clock.shape_mask)
  227.     {
  228.         w->clock.shape_mask = XCreatePixmap (XtDisplay (w), XtWindow (w),
  229.                     w->core.width, w->core.height, 1);
  230.     }
  231.     shape_mask = w->clock.shape_mask;
  232.         if (!w->clock.shapeGC)
  233.             w->clock.shapeGC = XCreateGC (XtDisplay (w), shape_mask, 0, &xgcv);
  234.  
  235.     /* erase the pixmap */
  236.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 0);
  237.         XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC,
  238.             0, 0, w->core.width, w->core.height);
  239.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 1);
  240.  
  241.     /*
  242.      * draw the bounding shape.  Doing this first
  243.      * eliminates extra exposure events.
  244.      */
  245.  
  246.     if (w->clock.border_size > 0.0 || !w->clock.transparent)
  247.     {
  248.         TFillArc (XtDisplay (w), shape_mask,
  249.                 w->clock.shapeGC, &w->clock.maskt,
  250.                 -1.0, -1.0,
  251.                 2.0, 2.0,
  252.                 0, 360 * 64);
  253.     }
  254.  
  255.     if (w->clock.transparent)
  256.     {
  257.         if (w->clock.border_size > 0.0)
  258.         {
  259.             XSetForeground (XtDisplay (w), w->clock.shapeGC, 0);
  260.             TFillArc (XtDisplay (w), shape_mask,
  261.                     w->clock.shapeGC, &w->clock.t,
  262.                     -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2,
  263.                     WINDOW_WIDTH(w), WINDOW_HEIGHT(w),
  264.                     0, 360 * 64);
  265.             XSetForeground (XtDisplay (w), w->clock.shapeGC, 1);
  266.         }
  267.         paint_jewel (w, shape_mask, w->clock.shapeGC);
  268.         paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC);
  269.     }
  270.     /*
  271.      * Find the highest enclosing widget and shape it
  272.      */
  273.  
  274.     x = 0;
  275.     y = 0;
  276.     for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) {
  277.         x = x + parent->core.x + parent->core.border_width;
  278.         y = y + parent->core.y + parent->core.border_width;
  279.     }
  280.  
  281.     XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding,
  282.                 x, y, shape_mask, ShapeSet);
  283.  
  284.     /* erase the pixmap */
  285.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 0);
  286.         XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC,
  287.             0, 0, w->core.width, w->core.height);
  288.         XSetForeground (XtDisplay (w), w->clock.shapeGC, 1);
  289.  
  290.     /*
  291.      * draw the clip shape
  292.      */
  293.  
  294.     if (w->clock.transparent)
  295.     {
  296.         paint_jewel (w, shape_mask, w->clock.shapeGC);
  297.         paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC);
  298.     }
  299.     else
  300.     {
  301.         TFillArc (XtDisplay (w), shape_mask,
  302.                 w->clock.shapeGC, &w->clock.t,
  303.                 -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2,
  304.                 WINDOW_WIDTH(w), WINDOW_HEIGHT(w),
  305.                 0, 360 * 64);
  306.     }
  307.  
  308.     XShapeCombineMask (XtDisplay (w), XtWindow (w), ShapeClip, 
  309.             0, 0, shape_mask, ShapeSet);
  310.  
  311.     } else
  312.     {
  313.         /*
  314.           * reconfigure the widget to split the availible
  315.           * space between the window and the border
  316.           */
  317.  
  318.          if (face_width > face_height)
  319.         xwc.border_width = face_height;
  320.         else
  321.         xwc.border_width = face_width;
  322.         xwc.width = w->core.width - xwc.border_width * 2;
  323.         xwc.height = w->core.height - xwc.border_width * 2;
  324.         XConfigureWindow (XtDisplay (w), XtWindow (w),
  325.                 CWWidth|CWHeight|CWBorderWidth,
  326.                 &xwc);
  327.     
  328.         SetTransform (&w->clock.t,
  329.         0, xwc.width,
  330.         xwc.height, 0,
  331.         -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2,
  332.         -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2);
  333.     }
  334. }
  335.  
  336. static void Realize (gw, valueMask, attrs)
  337.      Widget gw;
  338.      XtValueMask *valueMask;
  339.      XSetWindowAttributes *attrs;
  340. {
  341.      ClockWidget    w = (ClockWidget)gw;
  342.  
  343.     if (w->clock.backing_store != Always + WhenMapped + NotUseful) {
  344.          attrs->backing_store = w->clock.backing_store;
  345.     *valueMask |= CWBackingStore;
  346.     }
  347.     if (w->clock.transparent)
  348.     {
  349.     attrs->background_pixel = w->clock.minute;
  350.     *valueMask |= CWBackPixel;
  351.     *valueMask &= ~CWBackPixmap;
  352.     }
  353.     XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
  354.              *valueMask, attrs );
  355.     if (!w->clock.transparent)
  356.     Resize (w);
  357.     new_time ((XtPointer) gw, 0);
  358. }
  359.  
  360. static void Destroy (gw)
  361.      Widget gw;
  362. {
  363.      ClockWidget w = (ClockWidget)gw;
  364.      if (w->clock.interval_id) XtRemoveTimeOut (w->clock.interval_id);
  365.      if (! w->clock.transparent) {
  366.      XtReleaseGC(gw, w->clock.minuteGC);
  367.      XtReleaseGC(gw, w->clock.hourGC);
  368.      XtReleaseGC(gw, w->clock.jewelGC);
  369.      XtReleaseGC(gw, w->clock.eraseGC);
  370.      }
  371.      if (w->clock.shapeGC)
  372.     XFreeGC(XtDisplay(gw), w->clock.shapeGC);
  373.     if (w->clock.shape_mask)
  374.     XFreePixmap (XtDisplay (w), w->clock.shape_mask);
  375. }
  376.  
  377. /* ARGSUSED */
  378. static void Redisplay(gw, event, region)
  379.      Widget gw;
  380.      XEvent *event;
  381.      Region region;
  382. {
  383.     ClockWidget    w;
  384.  
  385.     w = (ClockWidget) gw;
  386.     if (!w->clock.transparent)
  387.     {
  388.         paint_jewel (w, XtWindow (w), w->clock.jewelGC);
  389.         paint_hands (w, XtWindow (w), w->clock.minuteGC, w->clock.hourGC);
  390.     }
  391. }
  392.  
  393. /*
  394.  * routines to draw the hands and jewel
  395.  */
  396.  
  397. #ifndef PI    /* may be found in <math.h> */
  398. # define PI (3.14159265358979323846)
  399. #endif
  400.  
  401. /*
  402.  * converts a number from 0..1 representing a clockwise radial distance
  403.  * from the 12 oclock position to a radian measure of the counter-clockwise
  404.  * distance from the 3 oclock position
  405.  */
  406.  
  407. static double
  408. clock_to_angle (clock)
  409. double    clock;
  410. {
  411.     if (clock >= .75)
  412.         clock -= 1.0;
  413.     return -2.0 * PI * clock + PI / 2.0;
  414. }
  415.  
  416. /* ARGSUSED */
  417. static void new_time (client_data, id)
  418.      XtPointer client_data;
  419.      XtIntervalId *id;        /* unused */
  420. {
  421.         ClockWidget    w = (ClockWidget)client_data;
  422.     long        now;
  423.     struct tm    *tm;
  424.     
  425.     if (!w->clock.transparent)
  426.     if (w->clock.polys_valid) {
  427.         paint_hands (w, XtWindow (w), w->clock.eraseGC, w->clock.eraseGC);
  428.         check_jewel (w, XtWindow (w), w->clock.jewelGC);
  429.     }
  430.     (void) time (&now);
  431.     tm = localtime (&now);
  432.     if (tm->tm_hour >= 12)
  433.         tm->tm_hour -= 12;
  434.     w->clock.hour_angle = clock_to_angle ((((double) tm->tm_hour) +
  435.                 ((double) tm->tm_min) / 60.0) / 12.0);
  436.     w->clock.minute_angle =
  437.         clock_to_angle (((double) tm->tm_min) / 60.0);
  438.     /*
  439.      * add the timeout before painting the hands, that may
  440.      * take a while and we'd like the clock to keep up
  441.      * with time changes.
  442.      */
  443.     w->clock.interval_id = 
  444.         XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w),
  445.                  (60 - tm->tm_sec) * 1000, new_time, client_data);
  446.     compute_hands (w);
  447.     if (w->clock.transparent)
  448.         Resize (w);
  449.     else
  450.         paint_hands (w, XtWindow (w), w->clock.minuteGC, w->clock.hourGC);
  451. } /* new_time */
  452.  
  453. paint_jewel (w, d, gc)
  454. ClockWidget w;
  455. Drawable    d;
  456. GC        gc;
  457. {
  458.     if (JEWEL_SIZE(w) > 0.0)
  459.     {
  460.     TFillArc (XtDisplay (w), d, gc, &w->clock.t,
  461.             JEWEL_X(w) - JEWEL_SIZE(w) / 2.0,
  462.              JEWEL_Y(w) - JEWEL_SIZE(w) / 2.0,
  463.              JEWEL_SIZE(w), JEWEL_SIZE(w), 0, 360 * 64);
  464.     }
  465. }
  466.  
  467. #define sqr(x)    ((x)*(x))
  468.  
  469. /*
  470.  * check to see if the polygon intersects the circular jewel
  471.  */
  472.  
  473. check_jewel_poly (w, poly)
  474. ClockWidget    w;
  475. TPoint        poly[POLY_SIZE];
  476. {
  477.     double    a2, b2, c2, d2;
  478.     double    x, y, size;
  479.     int    i;
  480.  
  481.     if (JEWEL_SIZE(w) > 0.0)
  482.     {
  483.     x = JEWEL_X(w);
  484.     y = JEWEL_Y(w);
  485.     size = JEWEL_SIZE(w);
  486.     /*
  487.      * check each side of the polygon to see if the
  488.      * distance from the line to the center of the
  489.      * circular jewel is less than the radius.
  490.      */
  491.     for (i = 0; i < POLY_SIZE-1; i++) {
  492.         a2 = sqr (poly[i].x - x) + sqr (poly[i].y - y);
  493.         b2 = sqr (poly[i+1].x - x) + sqr (poly[i+1].y - y);
  494.         c2 = sqr (poly[i].x - poly[i+1].x) + sqr (poly[i].y - poly[i+1].y);
  495.         d2 = a2 + b2 - c2;
  496.         if (d2 <= sqr (size) &&
  497.             a2 <= 2 * c2 && b2 <= 2 * c2 ||
  498.              a2 <= sqr (size) ||
  499.             b2 <= sqr (size))
  500.             return 1;
  501.     }
  502.     }
  503.     return 0;
  504. }
  505.  
  506. check_jewel (w, d, gc)
  507. ClockWidget    w;
  508. Drawable    d;
  509. GC        gc;
  510. {
  511.     if (!w->clock.polys_valid || JEWEL_SIZE(w) <= 0.0)
  512.         return;
  513.     if ((MINUTE_LENGTH(w) >= (JEWEL_Y(w) - JEWEL_SIZE(w)/2.0) &&
  514.          check_jewel_poly (w, w->clock.minute_poly)) ||
  515.         (HOUR_LENGTH(w) >= (JEWEL_Y(w) - JEWEL_SIZE(w)/2.0) &&
  516.          check_jewel_poly (w, w->clock.minute_poly)))
  517.     {
  518.         paint_jewel (w, d, gc);
  519.     }
  520. }
  521.  
  522. /*
  523.  * A hand is a rectangle with a triangular cap at the far end.
  524.  * This is represented with a five sided polygon.
  525.  */
  526.  
  527. compute_hand (w, a, l, width, poly)
  528. ClockWidget    w;
  529. double        a, l, width;
  530. TPoint        poly[POLY_SIZE];
  531. {
  532.     double    c, s;
  533.  
  534.     c = cos(a);
  535.     s = sin(a);
  536.     poly[0].x = c * l;    
  537.     poly[0].y = s * l;
  538.     poly[1].x = (l - width) * c - s * width;
  539.     poly[1].y = (l - width) * s + c * width;
  540.     poly[2].x = (-width) * c - s * width;
  541.     poly[2].y = (-width) * s + c * width;
  542.     poly[3].x = (-width) * c + s * width;
  543.     poly[3].y = (-width) * s - c * width;
  544.     poly[4].x = (l - width) * c + s * width;
  545.     poly[4].y = (l - width) * s - c * width;
  546.     poly[5].x = poly[0].x;
  547.     poly[5].y = poly[0].y;
  548. }
  549.  
  550. compute_hands (w)
  551. ClockWidget    w;
  552. {
  553.     compute_hand (w, w->clock.minute_angle,
  554.         MINUTE_LENGTH(w), MINUTE_WIDTH(w), w->clock.minute_poly);
  555.     compute_hand (w, w->clock.hour_angle,
  556.         HOUR_LENGTH(w), HOUR_WIDTH(w), w->clock.hour_poly);
  557.     w->clock.polys_valid = 1;
  558. }
  559.  
  560. paint_hand (w, d, gc, poly)
  561. ClockWidget    w;
  562. Drawable    d;
  563. GC        gc;
  564. TPoint        poly[POLY_SIZE];
  565. {
  566.     TFillPolygon (XtDisplay (w), d, gc, &w->clock.t, poly, POLY_SIZE,
  567.             Convex, CoordModeOrigin);
  568. }
  569.  
  570. paint_hands (w, d, minute_gc, hour_gc)
  571. ClockWidget    w;
  572. Drawable    d;
  573. GC        minute_gc, hour_gc;
  574. {
  575.     if (w->clock.polys_valid) {
  576.     paint_hand (w, d, hour_gc, w->clock.hour_poly);
  577.     paint_hand (w, d, minute_gc, w->clock.minute_poly);
  578.     }
  579. }
  580.