Annotation of researchv9/X11/src/X.V11R1/lib/Xtk/Clock.c, revision 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.