Annotation of researchv9/X11/src/X.V11R1/lib/Xtk/Clock.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char rcsid[] = "$Header: Clock.c,v 1.18 87/09/13 22:45:21 newman Exp $";
                      3: #endif lint
                      4: 
                      5: /*
                      6:  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
                      7:  * 
                      8:  *                         All Rights Reserved
                      9:  * 
                     10:  * Permission to use, copy, modify, and distribute this software and its 
                     11:  * documentation for any purpose and without fee is hereby granted, 
                     12:  * provided that the above copyright notice appear in all copies and that
                     13:  * both that copyright notice and this permission notice appear in 
                     14:  * supporting documentation, and that the name of Digital Equipment
                     15:  * Corporation not be used in advertising or publicity pertaining to
                     16:  * distribution of the software without specific, written prior permission.  
                     17:  * 
                     18:  * 
                     19:  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     20:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     21:  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     22:  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     23:  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     24:  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     25:  * SOFTWARE.
                     26:  */
                     27: #include <sys/time.h>
                     28: 
                     29: #include "Xlib.h"
                     30: #include "Xutil.h"
                     31: #include "Intrinsic.h"
                     32: #include "Clock.h"
                     33: #include "ClockP.h"
                     34: #include "Atoms.h"
                     35: 
                     36: extern long time();
                     37: static void clock_tic(), DrawHand(), DrawSecond(), SetSeg(), DrawClockFace();
                     38:        
                     39: /* Private Definitions */
                     40: 
                     41: #define VERTICES_IN_HANDS      6       /* to draw triangle */
                     42: #define PI                     3.14159265358979
                     43: #define TWOPI                  (2. * PI)
                     44: 
                     45: #define SECOND_HAND_FRACT      90
                     46: #define MINUTE_HAND_FRACT      70
                     47: #define HOUR_HAND_FRACT                40
                     48: #define HAND_WIDTH_FRACT       7
                     49: #define SECOND_WIDTH_FRACT     5
                     50: #define SECOND_HAND_TIME       30
                     51: 
                     52: #define max(a, b) ((a) > (b) ? (a) : (b))
                     53: #define min(a, b) ((a) < (b) ? (a) : (b))
                     54: #define abs(a) ((a) < 0 ? -(a) : (a))
                     55: 
                     56: 
                     57: /* Initialization of defaults */
                     58: 
                     59: #define offset(field) XtOffset(ClockWidget,clock.field)
                     60: #define goffset(field) XtOffset(Widget,core.field)
                     61: 
                     62: static XtResource resources[] = {
                     63:     {XtNwidth, XtCWidth, XrmRInt, sizeof(int),
                     64:        goffset(width), XrmRString, "164"},
                     65:     {XtNheight, XtCHeight, XrmRInt, sizeof(int),
                     66:        goffset(height), XrmRString, "164"},
                     67:     {XtNupdate, XtCInterval, XrmRInt, sizeof(int), 
                     68:         offset(update), XrmRString, "60" },
                     69:     {XtNforeground, XtCForeground, XrmRPixel, sizeof(Pixel),
                     70:         offset(fgpixel), XrmRString, "Black"},
                     71:     {XtNhand, XtCForeground, XrmRPixel, sizeof(Pixel),
                     72:         offset(Hdpixel), XrmRString, "Black"},
                     73:     {XtNhigh, XtCForeground, XrmRPixel, sizeof(Pixel),
                     74:         offset(Hipixel), XrmRString, "Black"},
                     75:     {XtNanalog, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                     76:         offset(analog), XrmRString, "TRUE"},
                     77:     {XtNchime, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                     78:        offset(chime), XrmRString, "FALSE" },
                     79:     {XtNpadding, XtCMargin, XrmRInt, sizeof(int),
                     80:         offset(padding), XrmRString, "8"},
                     81:     {XtNfont, XtCFont, XrmRFontStruct, sizeof(XFontStruct *),
                     82:         offset(font), XrmRString, "6x10"},
                     83: };
                     84: 
                     85: #undef offset
                     86: #undef goffset
                     87: 
                     88: static void Initialize(), Realize(), Destroy(), Resize(), Redisplay();
                     89: static Boolean SetValues();
                     90: 
                     91: ClockClassRec clockClassRec = {
                     92:     { /* core fields */
                     93:     /* superclass */     &widgetClassRec,
                     94:     /* class_name */      "Clock",
                     95:     /* size */            sizeof(ClockRec),
                     96:     /* class_initialize */ NULL,
                     97:     /* class_inited */     FALSE,
                     98:     /* initialize */      Initialize,
                     99:     /* realize */         Realize,
                    100:     /* actions */         NULL,
                    101:     /* num_actions */      0,
                    102:     /* resources */       resources,
                    103:     /* resource_count*/    XtNumber(resources),
                    104:     /* xrm_class */        NULL,
                    105:     /* compress_motion */  TRUE,
                    106:     /* compress_exposure */TRUE,
                    107:     /* visible_interest */ FALSE,
                    108:     /* destroy */          Destroy,
                    109:     /* resize */           Resize,
                    110:     /* expose */          Redisplay,
                    111:     /* set_values */       SetValues,
                    112:     /* accept_focus */     NULL,
                    113:     }
                    114: };
                    115: 
                    116: WidgetClass clockWidgetClass = (WidgetClass) &clockClassRec;
                    117: 
                    118: /****************************************************************
                    119:  *
                    120:  * Private Procedures
                    121:  *
                    122:  ****************************************************************/
                    123: 
                    124: 
                    125: static void EventHandler(gw, closure, event)
                    126:     Widget gw;
                    127:     char *closure;
                    128:     XEvent *event;
                    129: {
                    130:     if (event->type == ClientMessage && event->xclient.message_type == XtTimerExpired)
                    131:         clock_tic((ClockWidget)gw);
                    132: }
                    133: 
                    134: static void Initialize (request, new)
                    135:     Widget request, new;
                    136: {
                    137:     ClockWidget w = (ClockWidget)new;
                    138:     XtGCMask           valuemask;
                    139:     XGCValues  myXGCV;
                    140: 
                    141:     if(!w->clock.analog) {
                    142:        char *str;
                    143:        struct tm tm, *localtime();
                    144:        long time_value;
                    145:        int min_height, min_width;
                    146:        (void) time(&time_value);
                    147:        tm = *localtime(&time_value);
                    148:        str = asctime(&tm);
                    149:        min_width = XTextWidth(w->clock.font, str, strlen(str)) +
                    150:          2 * w->clock.padding;
                    151:        min_height = w->clock.font->ascent +
                    152:          w->clock.font->descent + 2 * w->clock.padding;
                    153:        if (w->core.width < min_width) w->core.width = min_width;
                    154:        if (w->core.height < min_height) w->core.width = min_height;
                    155:     }
                    156:     valuemask = GCForeground | GCBackground | GCFont | GCLineWidth;
                    157:     myXGCV.foreground = w->clock.fgpixel;
                    158:     myXGCV.background = w->core.background_pixel;
                    159:     myXGCV.font = w->clock.font->fid;
                    160:     myXGCV.line_width = 0;
                    161:     w->clock.myGC = XtGetGC(w, valuemask, &myXGCV);
                    162: 
                    163:     valuemask = GCForeground | GCLineWidth ;
                    164:     myXGCV.foreground = w->core.background_pixel;
                    165:     w->clock.EraseGC = XtGetGC(w, valuemask, &myXGCV);
                    166: 
                    167:     myXGCV.foreground = w->clock.Hipixel;
                    168:     w->clock.HighGC = XtGetGC(w, valuemask, &myXGCV);
                    169: 
                    170:     valuemask = GCForeground;
                    171:     myXGCV.foreground = w->clock.Hdpixel;
                    172:     w->clock.HandGC = XtGetGC(w, valuemask, &myXGCV);
                    173: 
                    174:     XtAddEventHandler (w, 0, TRUE, EventHandler, NULL);
                    175: 
                    176:     w->clock.interval_id = XtAddTimeOut(w, w->clock.update*1000);
                    177:     w->clock.show_second_hand = (w->clock.update <= SECOND_HAND_TIME);
                    178: }
                    179: 
                    180: static void Realize (gw, valueMask, attrs)
                    181:      Widget gw;
                    182:      XtValueMask valueMask;
                    183:      XSetWindowAttributes *attrs;
                    184: {
                    185:      valueMask |= CWBitGravity;
                    186:      attrs->bit_gravity = ForgetGravity;
                    187:      gw->core.window = XCreateWindow (XtDisplay(gw),
                    188:                                      gw->core.parent->core.window,
                    189:                                      gw->core.x, gw->core.y,
                    190:                                      gw->core.width, gw->core.height,
                    191:                                      gw->core.border_width,
                    192:                                      gw->core.depth, InputOutput,
                    193:                                      /* visualID */ CopyFromParent,
                    194:                                      valueMask, attrs);
                    195:      Resize(gw);
                    196: }
                    197: 
                    198: static void Destroy (gw)
                    199:      Widget gw;
                    200: {
                    201:      ClockWidget w = (ClockWidget) gw;
                    202:      XtRemoveTimeOut (w->clock.interval_id);
                    203:      XtDestroyGC (w->clock.myGC);
                    204:      XtDestroyGC (w->clock.HighGC);
                    205:      XtDestroyGC (w->clock.HandGC);
                    206:      XtDestroyGC (w->clock.EraseGC);
                    207: }
                    208: 
                    209: static void Resize (gw) 
                    210:     Widget gw;
                    211: {
                    212:     ClockWidget w = (ClockWidget) gw;
                    213:     /* don't do this computation if window hasn't been realized yet. */
                    214:     if (XtIsRealized(gw) && w->clock.analog) {
                    215:         w->clock.radius = (min(w->core.width, w->core.height)-(2 * w->clock.padding)) / 2;
                    216:         w->clock.second_hand_length = ((SECOND_HAND_FRACT * w->clock.radius) / 100);
                    217:         w->clock.minute_hand_length = ((MINUTE_HAND_FRACT * w->clock.radius) / 100);
                    218:         w->clock.hour_hand_length = ((HOUR_HAND_FRACT * w->clock.radius) / 100);
                    219:         w->clock.hand_width = ((HAND_WIDTH_FRACT * w->clock.radius) / 100);
                    220:         w->clock.second_hand_width = ((SECOND_WIDTH_FRACT * w->clock.radius) / 100);
                    221:         w->clock.centerX = w->core.width / 2;
                    222:         w->clock.centerY = w->core.height / 2;
                    223:     }
                    224: }
                    225: 
                    226: static void Redisplay (gw)
                    227:     Widget gw;
                    228: {
                    229:     ClockWidget w = (ClockWidget) gw;
                    230:     if (w->clock.analog)
                    231:         DrawClockFace(w);
                    232:     clock_tic(w);
                    233: }
                    234: 
                    235: 
                    236: static void clock_tic(w)
                    237:         ClockWidget w;
                    238: {
                    239:     
                    240:        struct tm *localtime();
                    241:        struct tm tm; 
                    242:        long    time_value;
                    243:        char    time_string[28];
                    244:        char    *time_ptr = time_string;
                    245:         register Display *dpy = XtDisplay(w);
                    246:         register Window win = XtWindow(w);
                    247: 
                    248:        (void) time(&time_value);
                    249:        tm = *localtime(&time_value);
                    250:        /*
                    251:         * Beep on the half hour; double-beep on the hour.
                    252:         */
                    253:        if (w->clock.chime == TRUE) {
                    254:            if (w->clock.beeped && (tm.tm_min != 30) &&
                    255:                (tm.tm_min != 0))
                    256:              w->clock.beeped = FALSE;
                    257:            if (((tm.tm_min == 30) || (tm.tm_min == 0)) 
                    258:                && (!w->clock.beeped)) {
                    259:                w->clock.beeped = TRUE;
                    260:                XBell(dpy, 50); 
                    261:                if (tm.tm_min == 0)
                    262:                  XBell(dpy, 50);
                    263:            }
                    264:        }
                    265:        if( w->clock.analog == FALSE ) {
                    266:            time_ptr = asctime(&tm);
                    267:            time_ptr[strlen(time_ptr) - 1] = 0;
                    268:            XDrawImageString (dpy, win, w->clock.myGC,
                    269:                             2+w->clock.padding, 2+w->clock.font->ascent+w->clock.padding,
                    270:                             time_ptr, strlen(time_ptr));
                    271:        } else {
                    272:                        /*
                    273:                         * The second (or minute) hand is sec (or min) 
                    274:                         * sixtieths around the clock face. The hour hand is
                    275:                         * (hour + min/60) twelfths of the way around the
                    276:                         * clock-face.  The derivation is left as an excercise
                    277:                         * for the reader.
                    278:                         */
                    279: 
                    280:                        /*
                    281:                         * 12 hour clock.
                    282:                         */
                    283:                        if(tm.tm_hour > 12)
                    284:                                tm.tm_hour -= 12;
                    285: 
                    286:                        /*
                    287:                         * Erase old hands.
                    288:                         */
                    289:                        if(w->clock.numseg > 0) {
                    290:                            if (w->clock.show_second_hand == TRUE) {
                    291:                                XDrawLines(dpy, win,
                    292:                                        w->clock.EraseGC,
                    293:                                        w->clock.sec,
                    294:                                        VERTICES_IN_HANDS-1,
                    295:                                        CoordModeOrigin);
                    296:                                if(w->clock.Hdpixel != w->core.background_pixel) {
                    297:                                    XFillPolygon(dpy,
                    298:                                        win, w->clock.EraseGC,
                    299:                                        w->clock.sec,
                    300:                                        VERTICES_IN_HANDS-2,
                    301:                                        Convex, CoordModeOrigin
                    302:                                    );
                    303:                                }
                    304:                            }
                    305:                            if( tm.tm_min != w->clock.otm.tm_min ||
                    306:                                tm.tm_hour != w->clock.otm.tm_hour ) {
                    307:                                XDrawLines( dpy,
                    308:                                           win,
                    309:                                           w->clock.EraseGC,
                    310:                                           w->clock.segbuff,
                    311:                                           VERTICES_IN_HANDS,
                    312:                                           CoordModeOrigin);
                    313:                                XDrawLines( dpy,
                    314:                                           win,
                    315:                                           w->clock.EraseGC,
                    316:                                           w->clock.hour,
                    317:                                           VERTICES_IN_HANDS,
                    318:                                           CoordModeOrigin);
                    319:                                if(w->clock.Hdpixel != w->core.background_pixel) {
                    320:                                    XFillPolygon( dpy,
                    321:                                        win, w->clock.EraseGC,
                    322:                                        w->clock.segbuff, VERTICES_IN_HANDS,
                    323:                                        Convex, CoordModeOrigin
                    324:                                    );
                    325:                                    XFillPolygon(dpy,
                    326:                                        win, w->clock.EraseGC,
                    327:                                        w->clock.hour,
                    328:                                        VERTICES_IN_HANDS,
                    329:                                        Convex, CoordModeOrigin
                    330:                                    );
                    331:                                }
                    332:                            }
                    333:                    }
                    334: 
                    335:                    if (w->clock.numseg == 0 ||
                    336:                        tm.tm_min != w->clock.otm.tm_min ||
                    337:                        tm.tm_hour != w->clock.otm.tm_hour) {
                    338:                            w->clock.segbuffptr = w->clock.segbuff;
                    339:                            w->clock.numseg = 0;
                    340:                            /*
                    341:                             * Calculate the hour hand, fill it in with its
                    342:                             * color and then outline it.  Next, do the same
                    343:                             * with the minute hand.  This is a cheap hidden
                    344:                             * line algorithm.
                    345:                             */
                    346:                            DrawHand(w,
                    347:                                w->clock.minute_hand_length, w->clock.hand_width,
                    348:                                ((double) tm.tm_min)/60.0
                    349:                            );
                    350:                            if(w->clock.Hdpixel != w->core.background_pixel)
                    351:                                XFillPolygon( dpy,
                    352:                                    win, w->clock.HandGC,
                    353:                                    w->clock.segbuff, VERTICES_IN_HANDS,
                    354:                                    Convex, CoordModeOrigin
                    355:                                );
                    356:                            XDrawLines( dpy,
                    357:                                win, w->clock.HighGC,
                    358:                                w->clock.segbuff, VERTICES_IN_HANDS,
                    359:                                       CoordModeOrigin);
                    360:                            w->clock.hour = w->clock.segbuffptr;
                    361:                            DrawHand(w, 
                    362:                                w->clock.hour_hand_length, w->clock.hand_width,
                    363:                                ((((double)tm.tm_hour) + 
                    364:                                    (((double)tm.tm_min)/60.0)) / 12.0)
                    365:                            );
                    366:                            if(w->clock.Hdpixel != w->core.background_pixel) {
                    367:                              XFillPolygon(dpy,
                    368:                                           win, w->clock.HandGC,
                    369:                                           w->clock.hour,
                    370:                                           VERTICES_IN_HANDS,
                    371:                                           Convex, CoordModeOrigin
                    372:                                           );
                    373:                            }
                    374:                            XDrawLines( dpy,
                    375:                                       win, w->clock.HighGC,
                    376:                                       w->clock.hour, VERTICES_IN_HANDS,
                    377:                                       CoordModeOrigin );
                    378: 
                    379:                            w->clock.sec = w->clock.segbuffptr;
                    380:                    }
                    381:                    if (w->clock.show_second_hand == TRUE) {
                    382:                            w->clock.segbuffptr = w->clock.sec;
                    383:                            DrawSecond(w,
                    384:                                w->clock.second_hand_length - 2, 
                    385:                                w->clock.second_hand_width,
                    386:                                w->clock.minute_hand_length + 2,
                    387:                                ((double) tm.tm_sec)/60.0
                    388:                            );
                    389:                            if(w->clock.Hdpixel != w->core.background_pixel)
                    390:                                XFillPolygon( dpy,
                    391:                                    win, w->clock.HandGC,
                    392:                                    w->clock.sec,
                    393:                                    VERTICES_IN_HANDS -2,
                    394:                                    Convex, CoordModeOrigin
                    395:                            );
                    396:                            XDrawLines( dpy,
                    397:                                       win, w->clock.HighGC,
                    398:                                       w->clock.sec,
                    399:                                       VERTICES_IN_HANDS-1,
                    400:                                       CoordModeOrigin
                    401:                                        );
                    402: 
                    403:                        }
                    404:                        w->clock.otm = tm;
                    405:                        
                    406:                }
                    407: }
                    408:        
                    409: /*
                    410:  * DrawLine - Draws a line.
                    411:  *
                    412:  * blank_length is the distance from the center which the line begins.
                    413:  * length is the maximum length of the hand.
                    414:  * Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
                    415:  * how far around the circle (clockwise) from high noon.
                    416:  *
                    417:  * The blank_length feature is because I wanted to draw tick-marks around the
                    418:  * circle (for seconds).  The obvious means of drawing lines from the center
                    419:  * to the perimeter, then erasing all but the outside most pixels doesn't
                    420:  * work because of round-off error (sigh).
                    421:  */
                    422: static void DrawLine(w, blank_length, length, fraction_of_a_circle)
                    423: ClockWidget w;
                    424: Dimension blank_length;
                    425: Dimension length;
                    426: double fraction_of_a_circle;
                    427: {
                    428:        register double angle, cosangle, sinangle;
                    429:        double cos();
                    430:        double sin();
                    431: 
                    432:        /*
                    433:         *  A full circle is 2 PI radians.
                    434:         *  Angles are measured from 12 o'clock, clockwise increasing.
                    435:         *  Since in X, +x is to the right and +y is downward:
                    436:         *
                    437:         *      x = x0 + r * sin(theta)
                    438:         *      y = y0 - r * cos(theta)
                    439:         *
                    440:         */
                    441:        angle = TWOPI * fraction_of_a_circle;
                    442:        cosangle = cos(angle);
                    443:        sinangle = sin(angle);
                    444: 
                    445:        SetSeg(w, 
                    446:               w->clock.centerX + (int)(blank_length * sinangle),
                    447:               w->clock.centerY - (int)(blank_length * cosangle),
                    448:               w->clock.centerX + (int)(length * sinangle),
                    449:               w->clock.centerY - (int)(length * cosangle));
                    450: }
                    451: 
                    452: /*
                    453:  * DrawHand - Draws a hand.
                    454:  *
                    455:  * length is the maximum length of the hand.
                    456:  * width is the half-width of the hand.
                    457:  * Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
                    458:  * how far around the circle (clockwise) from high noon.
                    459:  *
                    460:  */
                    461: static void DrawHand(w, length, width, fraction_of_a_circle)
                    462: ClockWidget w;
                    463: Dimension length, width;
                    464: double fraction_of_a_circle;
                    465: {
                    466: 
                    467:        register double angle, cosangle, sinangle;
                    468:        register double ws, wc;
                    469:        Position x, y, x1, y1, x2, y2;
                    470:        double cos();
                    471:        double sin();
                    472: 
                    473:        /*
                    474:         *  A full circle is 2 PI radians.
                    475:         *  Angles are measured from 12 o'clock, clockwise increasing.
                    476:         *  Since in X, +x is to the right and +y is downward:
                    477:         *
                    478:         *      x = x0 + r * sin(theta)
                    479:         *      y = y0 - r * cos(theta)
                    480:         *
                    481:         */
                    482:        angle = TWOPI * fraction_of_a_circle;
                    483:        cosangle = cos(angle);
                    484:        sinangle = sin(angle);
                    485:        /*
                    486:         * Order of points when drawing the hand.
                    487:         *
                    488:         *              1,4
                    489:         *              / \
                    490:         *             /   \
                    491:         *            /     \
                    492:         *          2 ------- 3
                    493:         */
                    494:        wc = width * cosangle;
                    495:        ws = width * sinangle;
                    496:        SetSeg(w,
                    497:               x = w->clock.centerX + round(length * sinangle),
                    498:               y = w->clock.centerY - round(length * cosangle),
                    499:               x1 = w->clock.centerX - round(ws + wc), 
                    500:               y1 = w->clock.centerY + round(wc - ws));  /* 1 ---- 2 */
                    501:        /* 2 */
                    502:        SetSeg(w, x1, y1, 
                    503:               x2 = w->clock.centerX - round(ws - wc), 
                    504:               y2 = w->clock.centerY + round(wc + ws));  /* 2 ----- 3 */
                    505: 
                    506:        SetSeg(w, x2, y2, x, y);        /* 3 ----- 1(4) */
                    507: }
                    508: 
                    509: /*
                    510:  * DrawSecond - Draws the second hand (diamond).
                    511:  *
                    512:  * length is the maximum length of the hand.
                    513:  * width is the half-width of the hand.
                    514:  * offset is direct distance from center to tail end.
                    515:  * Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
                    516:  * how far around the circle (clockwise) from high noon.
                    517:  *
                    518:  */
                    519: static void DrawSecond(w, length, width, offset, fraction_of_a_circle)
                    520: ClockWidget w;
                    521: Dimension length, width, offset;
                    522: double fraction_of_a_circle;
                    523: {
                    524: 
                    525:        register double angle, cosangle, sinangle;
                    526:        register double ms, mc, ws, wc;
                    527:        register int mid;
                    528:        Position x, y;
                    529:        double cos();
                    530:        double sin();
                    531: 
                    532:        /*
                    533:         *  A full circle is 2 PI radians.
                    534:         *  Angles are measured from 12 o'clock, clockwise increasing.
                    535:         *  Since in X, +x is to the right and +y is downward:
                    536:         *
                    537:         *      x = x0 + r * sin(theta)
                    538:         *      y = y0 - r * cos(theta)
                    539:         *
                    540:         */
                    541:        angle = TWOPI * fraction_of_a_circle;
                    542:        cosangle = cos(angle);
                    543:        sinangle = sin(angle);
                    544:        /*
                    545:         * Order of points when drawing the hand.
                    546:         *
                    547:         *              1,5
                    548:         *              / \
                    549:         *             /   \
                    550:         *            /     \
                    551:         *          2<       >4
                    552:         *            \     /
                    553:         *             \   /
                    554:         *              \ /
                    555:         *      -        3
                    556:         *      |
                    557:         *      |
                    558:         *   offset
                    559:         *      |
                    560:         *      |
                    561:         *      -        + center
                    562:         */
                    563: 
                    564:        mid = (length + offset) / 2;
                    565:        mc = mid * cosangle;
                    566:        ms = mid * sinangle;
                    567:        wc = width * cosangle;
                    568:        ws = width * sinangle;
                    569:        /*1 ---- 2 */
                    570:        SetSeg(w,
                    571:               x = w->clock.centerX + round(length * sinangle),
                    572:               y = w->clock.centerY - round(length * cosangle),
                    573:               w->clock.centerX + round(ms - wc),
                    574:               w->clock.centerY - round(mc + ws) );
                    575:        SetSeg(w, w->clock.centerX + round(offset *sinangle),
                    576:               w->clock.centerY - round(offset * cosangle), /* 2-----3 */
                    577:               w->clock.centerX + round(ms + wc), 
                    578:               w->clock.centerY - round(mc - ws));
                    579:        w->clock.segbuffptr->x = x;
                    580:        w->clock.segbuffptr++->y = y;
                    581:        w->clock.numseg ++;
                    582: }
                    583: 
                    584: static void SetSeg(w, x1, y1, x2, y2)
                    585: ClockWidget w;
                    586: int x1, y1, x2, y2;
                    587: {
                    588:        w->clock.segbuffptr->x = x1;
                    589:        w->clock.segbuffptr++->y = y1;
                    590:        w->clock.segbuffptr->x = x2;
                    591:        w->clock.segbuffptr++->y = y2;
                    592:        w->clock.numseg += 2;
                    593: }
                    594: 
                    595: /*
                    596:  *  Draw the clock face (every fifth tick-mark is longer
                    597:  *  than the others).
                    598:  */
                    599: static void DrawClockFace(w)
                    600: ClockWidget w;
                    601: {
                    602:        register int i;
                    603:        register int delta = (w->clock.radius - w->clock.second_hand_length) / 3;
                    604:        
                    605:        w->clock.segbuffptr = w->clock.segbuff;
                    606:        w->clock.numseg = 0;
                    607:        for (i = 0; i < 60; i++)
                    608:                DrawLine(w, (i % 5) == 0 ? w->clock.second_hand_length : (w->clock.radius - delta),
                    609:                    w->clock.radius, ((double) i)/60.);
                    610:        /*
                    611:         * Go ahead and draw it.
                    612:         */
                    613:        XDrawSegments(XtDisplay(w), XtWindow(w),
                    614:                      w->clock.myGC, (XSegment *) &(w->clock.segbuff[0]),
                    615:                      w->clock.numseg/2);
                    616:        
                    617:        w->clock.segbuffptr = w->clock.segbuff;
                    618:        w->clock.numseg = 0;
                    619: }
                    620: 
                    621: static int round(x)
                    622: double x;
                    623: {
                    624:        return(x >= 0.0 ? (int)(x + .5) : (int)(x - .5));
                    625: }
                    626: 
                    627: static Boolean SetValues (gcurrent, grequest, gnew, last)
                    628:     Widget gcurrent, grequest, gnew;
                    629:     Boolean last;
                    630: {
                    631:       ClockWidget current = (ClockWidget) gcurrent;
                    632:       ClockWidget new = (ClockWidget) gnew;
                    633:       Boolean redisplay = FALSE;
                    634:       XtGCMask valuemask;
                    635:       XGCValues        myXGCV;
                    636: 
                    637:       /* first check for changes to clock-specific resources.  We'll accept all
                    638:          the changes, but may need to do some computations first. */
                    639: 
                    640:       if (new->clock.update != current->clock.update) {
                    641:            XtRemoveTimeOut (current->clock.interval_id);
                    642:            new->clock.interval_id = XtAddTimeOut(gcurrent, new->clock.update*1000);
                    643:            new->clock.show_second_hand = (new->clock.update <= SECOND_HAND_TIME);
                    644:       }
                    645: 
                    646:       if (new->clock.analog != current->clock.analog)
                    647:           redisplay = TRUE;
                    648: 
                    649:       if (new->clock.padding != current->clock.padding) {
                    650:           Resize(gnew);
                    651:           redisplay = TRUE;
                    652:           }
                    653: 
                    654:       if (new->clock.font != current->clock.font)
                    655:           redisplay = TRUE;
                    656: 
                    657:       if ((new->clock.fgpixel != current->clock.fgpixel)
                    658:           || (new->core.background_pixel != current->core.background_pixel)) {
                    659:           valuemask = GCForeground | GCBackground | GCFont | GCLineWidth;
                    660:          myXGCV.foreground = new->clock.fgpixel;
                    661:          myXGCV.background = new->core.background_pixel;
                    662:           myXGCV.font = new->clock.font->fid;
                    663:          myXGCV.line_width = 0;
                    664:          XtDestroyGC (current->clock.myGC);
                    665:          new->clock.myGC = XtGetGC(gcurrent, valuemask, &myXGCV);
                    666:          redisplay = TRUE;
                    667:           }
                    668: 
                    669:       if (new->clock.Hipixel != current->clock.Hipixel) {
                    670:           valuemask = GCForeground | GCLineWidth;
                    671:          myXGCV.foreground = new->clock.fgpixel;
                    672:           myXGCV.font = new->clock.font->fid;
                    673:          myXGCV.line_width = 0;
                    674:          XtDestroyGC (current->clock.HighGC);
                    675:          new->clock.HighGC = XtGetGC(gcurrent, valuemask, &myXGCV);
                    676:          redisplay = TRUE;
                    677:           }
                    678: 
                    679:       if (new->clock.Hdpixel != current->clock.Hdpixel) {
                    680:           valuemask = GCForeground;
                    681:          myXGCV.foreground = new->clock.fgpixel;
                    682:          XtDestroyGC (current->clock.HandGC);
                    683:          new->clock.HandGC = XtGetGC(gcurrent, valuemask, &myXGCV);
                    684:          redisplay = TRUE;
                    685:           }
                    686: 
                    687:       if (new->core.background_pixel != current->core.background_pixel) {
                    688:           valuemask = GCForeground | GCLineWidth;
                    689:          myXGCV.foreground = new->core.background_pixel;
                    690:          myXGCV.line_width = 0;
                    691:          XtDestroyGC (current->clock.EraseGC);
                    692:          new->clock.EraseGC = XtGetGC(gcurrent, valuemask, &myXGCV);
                    693:          redisplay = TRUE;
                    694:          }
                    695: 
                    696:      if ((new->core.x != current->core.x)
                    697:        || (new->core.y != current->core.y)
                    698:        || (new->core.width != current->core.width)
                    699:        || (new->core.height != current->core.height)
                    700:        || (new->core.border_width != current->core.border_width))
                    701:          /* need to make geometry request */;
                    702:      
                    703:      return (redisplay);
                    704: 
                    705: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.