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

1.1       root        1: /* $Header: Clock.c,v 1.3 87/09/12 12:42:42 swick Exp $ */
                      2: #ifndef lint
                      3: static char *sccsid = "@(#)Clock.c     1.0     2/25/87";
                      4: #endif lint
                      5:  
                      6: /*
                      7:  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
                      8:  * 
                      9:  *                         All Rights Reserved
                     10:  * 
                     11:  * Permission to use, copy, modify, and distribute this software and its 
                     12:  * documentation for any purpose and without fee is hereby granted, 
                     13:  * provided that the above copyright notice appear in all copies and that
                     14:  * both that copyright notice and this permission notice appear in 
                     15:  * supporting documentation, and that the name of Digital Equipment
                     16:  * Corporation not be used in advertising or publicity pertaining to
                     17:  * distribution of the software without specific, written prior permission.  
                     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: 
                     28: 
                     29: #include <stdio.h>
                     30: #include <strings.h>
                     31: #include "Xlib.h"
                     32: #include "Xutil.h"
                     33: #include "Intrinsic.h"
                     34: #include "Clock.h"
                     35: #include "Atoms.h"
                     36: #include <sys/time.h>
                     37: #include <sys/file.h>
                     38: #include <sys/param.h>
                     39: #include <math.h>
                     40: 
                     41: extern long time();
                     42:        
                     43: /* Private Definitions */
                     44: 
                     45: 
                     46: #define VERTICES_IN_HANDS      6       /* to draw triangle */
                     47: #define PHI                    (PI / 16.)      /* half angle of hand tip */
                     48: #define PI                     3.14159265358979
                     49: #define PI4                    (PI / 4.)
                     50: #define        SINPHI                  0.19509032201613
                     51: #define TWOPI                  (2. * PI)
                     52: 
                     53: #define SEG_BUFF_SIZE          128
                     54: 
                     55: #define SECOND_HAND_FRACT      90
                     56: #define MINUTE_HAND_FRACT      70
                     57: #define HOUR_HAND_FRACT                40
                     58: #define HAND_WIDTH_FRACT       7
                     59: #define SECOND_WIDTH_FRACT     5
                     60: #define SECOND_HAND_TIME       30
                     61: 
                     62: #define DEF_UPDATE             60
                     63: 
                     64: #define DEF_BORDER             2
                     65: #define DEF_VECTOR_HEIGHT      1
                     66: #define DEF_VECTOR_WIDTH       1
                     67: 
                     68: #define DEF_DIGITAL_PADDING    10
                     69: #define DEF_DIGITAL_FONT       "6x10"
                     70: #define DEF_ANALOG_PADDING     8
                     71: #define DEF_ANALOG_WIDTH       164
                     72: #define DEF_ANALOG_HEIGHT      164
                     73: 
                     74: #define UNINIT                 -1
                     75: #define FAILURE                        0
                     76: 
                     77: #define max(a, b) ((a) > (b) ? (a) : (b))
                     78: #define min(a, b) ((a) < (b) ? (a) : (b))
                     79: #define abs(a) ((a) < 0 ? -(a) : (a))
                     80: 
                     81: 
                     82: typedef struct WidgetDataRec {
                     83:        Display *dpy;           /* widget display connection */
                     84:         Window mywin;          /* widget window */
                     85:         Dimension      brwidth;        /* border width in pixels */
                     86:         Dimension      width, height;  /* width/height in pixels */
                     87:         Position       x, y;
                     88:         Pixel  fgpixel;        /* color index for text */
                     89:         Pixel  bgpixel;        /* color index for background */
                     90:         Pixel  Hipixel;        /* color index for Highlighting */
                     91:         Pixel  Hdpixel;        /* color index for hands */
                     92:         Pixel  brpixel;        /* pixel for border */
                     93:         XFontStruct    *fontstruct;    /* font for text */
                     94:         GC     myGC;           /* pointer to GraphicsContext */
                     95:         GC     EraseGC;        /* eraser GC */
                     96:         GC     HandGC;         /* Hand GC */
                     97:         GC     HighGC;         /* Highlighting GC */
                     98: /* start of graph stuff */
                     99:         int    update;         /* update frequence */
                    100:         Dimension radius;              /* radius factor */
                    101:         int    chime;  
                    102:         int    beeped;
                    103:         int    analog;
                    104:         int    show_second_hand;
                    105:         Dimension second_hand_length;
                    106:         Dimension minute_hand_length;
                    107:         Dimension hour_hand_length;
                    108:         Dimension hand_width;
                    109:         Dimension second_hand_width;
                    110:         Position centerX;
                    111:         Position centerY;
                    112:         int    numseg;
                    113:         int    mapped;         /* is exposed */
                    114:         int    padding;
                    115:         XPoint segbuff[SEG_BUFF_SIZE];
                    116:         XPoint *segbuffptr;
                    117:         XPoint *hour, *sec;
                    118:         struct tm  otm ;
                    119:         caddr_t cookie;
                    120:    } WidgetDataRec, *WidgetData;
                    121: 
                    122: 
                    123: /* Private Data */
                    124: 
                    125: static WidgetDataRec globaldata;
                    126: 
                    127: /* !!! STATIC !!! */
                    128: static int  initDone = 0;       /* initialization flag */
                    129: 
                    130: static XContext widgetContext;
                    131: 
                    132: /* bogus static's */
                    133: static int def_brwidth = DEF_BORDER;
                    134: static int def_width = 164;
                    135: static int def_height = 164;
                    136: static int def_x = 0;
                    137: static int def_y = 0;
                    138: static int def_update = DEF_UPDATE;
                    139: static int def_analog = 1;
                    140: static int def_chime = 0;
                    141: static int def_padding = DEF_ANALOG_PADDING;
                    142: 
                    143: static Resource resourcelist[] = {
                    144:     {XtNwindow, XtCWindow, XrmRWindow,
                    145:        sizeof(Window), (caddr_t)&globaldata.mywin, (caddr_t)NULL},
                    146:     {XtNborderWidth, XtCBorderWidth, XrmRInt,
                    147:        sizeof(int), (caddr_t)&globaldata.brwidth, (caddr_t) &def_brwidth},
                    148:     {XtNwidth, XtCWidth, XrmRInt,
                    149:        sizeof(int), (caddr_t)&globaldata.width, (caddr_t) &def_width},
                    150:     {XtNheight, XtCHeight, XrmRInt,
                    151:        sizeof(int), (caddr_t)&globaldata.height, (caddr_t) &def_height },
                    152:     {XtNx, XtCX, XrmRInt,
                    153:        sizeof(int), (caddr_t)&globaldata.x, (caddr_t) &def_x },
                    154:     {XtNy, XtCY, XrmRInt,
                    155:        sizeof(int), (caddr_t)&globaldata.y, (caddr_t) &def_y },
                    156:     {XtNupdate, XtCInterval, XrmRInt,
                    157:        sizeof(int), (caddr_t)&globaldata.update, (caddr_t) &def_update },
                    158:     {XtNchime, XtCChime, XrmRInt,
                    159:        sizeof(int), (caddr_t)&globaldata.chime, (caddr_t) &def_chime },
                    160:     {XtNhand, XtCColor, XrmRPixel,
                    161:        sizeof(int), (caddr_t)&globaldata.Hdpixel, (caddr_t)&XtDefaultFGPixel},
                    162:     {XtNhigh, XtCColor, XrmRPixel,
                    163:        sizeof(int), (caddr_t)&globaldata.Hipixel, (caddr_t)&XtDefaultFGPixel},
                    164:     {XtNforeground, XtCColor, XrmRPixel,
                    165:        sizeof(int), (caddr_t)&globaldata.fgpixel, (caddr_t)&XtDefaultFGPixel},
                    166:     {XtNbackground, XtCColor, XrmRPixel,
                    167:        sizeof(int), (caddr_t)&globaldata.bgpixel, (caddr_t)&XtDefaultBGPixel},
                    168:     {XtNpadding, XtCPadding, XrmRInt,
                    169:        sizeof(int), (caddr_t)&globaldata.padding, (caddr_t) &def_padding },
                    170:     {XtNborder, XtCColor, XrmRPixel,
                    171:        sizeof(int),(caddr_t)&globaldata.brpixel, (caddr_t)&XtDefaultFGPixel}
                    172: };
                    173: 
                    174: static Resource resourcelist1[] = {
                    175:     {XtNfont, XtCFont, XrmRFontStruct,
                    176:        sizeof(XFontStruct *), (caddr_t)&globaldata.fontstruct, (caddr_t)NULL},
                    177:     {XtNanalog, XtCAnalog, XrmRInt,
                    178:         sizeof(int), (caddr_t) &globaldata.analog, (caddr_t) &def_analog }
                    179: };
                    180: 
                    181: /****************************************************************
                    182:  *
                    183:  * Private Procedures
                    184:  *
                    185:  ****************************************************************/
                    186: 
                    187: static void ClockInitialize (dpy)
                    188:     Display    *dpy;
                    189: {
                    190:     if (initDone) return;
                    191: 
                    192:     widgetContext = XUniqueContext();
                    193:     globaldata.fontstruct = XLoadQueryFont(dpy,"fixed");
                    194: 
                    195:     initDone = 1;
                    196: }
                    197: 
                    198: /*
                    199:  * Given a display and window, get the widget data.
                    200:  */
                    201: 
                    202: static WidgetData DataFromWindow(dpy, window)
                    203: Display *dpy;
                    204: Window window;
                    205: {
                    206:     WidgetData result;
                    207:     if (XFindContext(dpy, window, widgetContext, (caddr_t *)&result))
                    208:        return NULL;
                    209:     return result;
                    210: }
                    211: 
                    212: static void Destroy();
                    213: 
                    214: /*
                    215:  *
                    216:  * Generic widget event handler
                    217:  *
                    218:  */
                    219: 
                    220: static XtEventReturnCode EventHandler(event, eventdata)
                    221: XEvent *event;
                    222: caddr_t eventdata;
                    223: {
                    224:     WidgetData         data = (WidgetData ) eventdata;
                    225:     void clock_tic();
                    226: 
                    227:     switch (event->type) {
                    228:        case ConfigureNotify:
                    229:            data->height = event->xconfigure.height;
                    230:            data->width = event->xconfigure.width;
                    231:            break;
                    232: 
                    233:        case DestroyNotify:
                    234:                Destroy(data);
                    235:            break;
                    236:        
                    237:        case ClientMessage:
                    238:            if (((XClientMessageEvent *)event)->message_type == 
                    239:                  (unsigned long) XtTimerExpired)
                    240:                  clock_tic(data);
                    241:            break;
                    242:        
                    243:         case Expose:
                    244:            data->mapped = 1;
                    245:            if( ((XExposeEvent *)event)->count == 0)
                    246:              redisplay_clock(data);
                    247:            break;
                    248: 
                    249:        case NoExpose:
                    250:            data->mapped = 0;
                    251:            break;
                    252:     }
                    253: 
                    254:     return (XteventHandled);
                    255: }
                    256: 
                    257: static redisplay_clock(data) 
                    258: WidgetData     data;
                    259: {
                    260:     if(data->analog) {
                    261:       data->radius = (min(data->width, data->height)-(2 * data->padding)) / 2;
                    262:       data->second_hand_length = ((SECOND_HAND_FRACT * data->radius) / 100);
                    263:       data->minute_hand_length = ((MINUTE_HAND_FRACT * data->radius) / 100);
                    264:       data->hour_hand_length = ((HOUR_HAND_FRACT * data->radius) / 100);
                    265:       data->hand_width = ((HAND_WIDTH_FRACT * data->radius) / 100);
                    266:       data->second_hand_width = ((SECOND_WIDTH_FRACT * data->radius) / 100);
                    267:       data->centerX = data->width / 2;
                    268:       data->centerY = data->height / 2;
                    269:       DrawClockFace(data, data->second_hand_length, data->radius);
                    270:     }
                    271:     clock_tic(data);
                    272: }
                    273: 
                    274: /*
                    275:  *
                    276:  * Destroy the widget
                    277:  *
                    278:  */
                    279: 
                    280: static void Destroy(data)
                    281: WidgetData data;
                    282: {
                    283: 
                    284:     XtClearEventHandlers(data->dpy, data->mywin);
                    285:     (void) XtClearTimeOut(data->mywin, data->cookie);
                    286:     XtFree ((char *) data);
                    287: }
                    288: 
                    289: /****************************************************************
                    290:  *
                    291:  * Public Procedures
                    292:  *
                    293:  ****************************************************************/
                    294: 
                    295: Window XtCreateClock(dpy, pw, arglist, argCount)
                    296: Display *dpy;
                    297: Window pw;                      /* parent window */
                    298: ArgList arglist;
                    299: int argCount;
                    300: {
                    301:     WidgetData data;
                    302:     unsigned long eventmask;
                    303:     GCMask             valuemask;
                    304:     XrmNameList   names;
                    305:     XrmClassList        classes;
                    306:     XGCValues  myXGCV;
                    307:     char *str;
                    308:     struct tm tm, *localtime();
                    309:     long time_value;
                    310: 
                    311:     if (!initDone)ClockInitialize (dpy);
                    312: 
                    313:     data = (WidgetData ) XtMalloc (sizeof (WidgetDataRec));
                    314:     globaldata.dpy = dpy;
                    315:  
                    316:     /* Set Some Default Values */
                    317:     XtGetResources(dpy, resourcelist1, XtNumber(resourcelist1), arglist,
                    318:                   argCount, pw, "clock", "Clock", &names, &classes);
                    319:     if(!globaldata.analog) {
                    320:       (void) time(&time_value);
                    321:       tm = *localtime(&time_value);
                    322:       str = asctime(&tm);
                    323:       def_width = XTextWidth( globaldata.fontstruct, str, strlen(str)) +
                    324:        2 * 10;
                    325:       def_height = globaldata.fontstruct->ascent +
                    326:        globaldata.fontstruct->descent + 2 * 10;
                    327:       def_padding = 10;
                    328:     }
                    329:     /* Set Default Values */
                    330:     XtGetResources(dpy, resourcelist, XtNumber(resourcelist), arglist,
                    331:                   argCount, pw, "clock", "Clock", &names, &classes);
                    332:     if(!globaldata.analog && globaldata.padding != def_padding) {
                    333:       def_width = XTextWidth( globaldata.fontstruct, str, strlen(str)) +
                    334:        2 * globaldata.padding;
                    335:       def_height = globaldata.fontstruct->ascent +
                    336:        globaldata.fontstruct->descent + 2 * globaldata.padding;
                    337:       XtGetResources(dpy, resourcelist, XtNumber(resourcelist), arglist,
                    338:                     argCount, pw, "clock", "Clock", &names, &classes);
                    339:     }
                    340:     *data = globaldata;
                    341:     valuemask = GCForeground | GCFont | GCBackground | GCLineWidth;
                    342:     myXGCV.foreground = (*data).fgpixel;
                    343:     myXGCV.font = (*data).fontstruct->fid;
                    344:     myXGCV.background = data->bgpixel;
                    345:     myXGCV.line_width = 0;
                    346:     (*data).myGC = XtGetGC(dpy, (XContext) XtNclock, pw, valuemask, &myXGCV);
                    347:     valuemask = GCForeground | GCLineWidth ;
                    348:     myXGCV.foreground = (*data).bgpixel;
                    349:     (*data).EraseGC = XtGetGC(dpy, (XContext) XtNclock, pw, valuemask, &myXGCV);
                    350:     myXGCV.foreground = (*data).Hdpixel;
                    351:     (*data).HandGC = XtGetGC(dpy, (XContext) XtNclock, pw, valuemask, &myXGCV);
                    352:     valuemask = GCForeground | GCLineWidth ;
                    353:     myXGCV.foreground = (*data).Hipixel;
                    354:     (*data).HighGC = XtGetGC(dpy, (XContext) XtNclock, pw, valuemask, &myXGCV);
                    355: 
                    356:     if (data->mywin != NULL) {
                    357:        XWindowAttributes wi;
                    358:        /* set global data from window parameters */
                    359:        if (! XGetWindowAttributes(data->dpy,data->mywin, &wi)) {
                    360:            data->mywin = NULL;
                    361:        } else {
                    362:            data->brwidth = wi.border_width;
                    363:            data->width = wi.width;
                    364:            data->height = wi.height;
                    365:        }
                    366:     }
                    367:     if (data->mywin == NULL) {
                    368:        /* create the Clock window */
                    369:          data->mywin = XCreateSimpleWindow(data->dpy, pw, data->x, data->y,
                    370:                              data->width, data->height,
                    371:                              data->brwidth, data->brpixel, data->bgpixel);
                    372:     }
                    373: 
                    374:     XtSetNameAndClass(data->dpy, data->mywin, names, classes);
                    375:     XrmFreeNameList(names);
                    376:     XrmFreeClassList(classes);
                    377: 
                    378:     /* set handler for expose, resize, and message events */
                    379: 
                    380:     eventmask = ExposureMask+StructureNotifyMask;
                    381:     XtSetEventHandler (
                    382:        data->dpy, data->mywin,
                    383:        (XtEventHandler)EventHandler, eventmask, (caddr_t)data);
                    384: 
                    385:     XtSetTimeOut(data->mywin, XtNclock, data->update*1000);
                    386:     if (data->update <= SECOND_HAND_TIME)
                    387:       data->show_second_hand = TRUE;
                    388:     return (data->mywin);
                    389: }
                    390: 
                    391: 
                    392: static void clock_tic(data)
                    393: WidgetData data;
                    394: {
                    395:     
                    396:        struct tm *localtime();
                    397:        struct tm tm; 
                    398:        long    time_value;
                    399:        char    time_string[28];
                    400:        char    *time_ptr = time_string;
                    401: 
                    402:        (void) time(&time_value);
                    403:        tm = *localtime(&time_value);
                    404:        /*
                    405:         * Beep on the half hour; double-beep on the hour.
                    406:         */
                    407:        if (data->chime == TRUE) {
                    408:            if (data->beeped && (tm.tm_min != 30) &&
                    409:                (tm.tm_min != 0))
                    410:              data->beeped = 0;
                    411:            if (((tm.tm_min == 30) || (tm.tm_min == 0)) 
                    412:                && (!data->beeped)) {
                    413:                data->beeped = 1;
                    414:                XBell(data->dpy, 50);   
                    415:                if (tm.tm_min == 0)
                    416:                  XBell(data->dpy, 50);
                    417:            }
                    418:        }
                    419:        if( data->analog == FALSE ) {
                    420:            time_ptr = asctime(&tm);
                    421:            time_ptr[strlen(time_ptr) - 1] = 0;
                    422:            XDrawImageString(data->dpy, data->mywin, data->myGC,
                    423:                             2+data->padding
                    424:                             , 2+data->fontstruct->ascent+data->padding,
                    425:                             time_ptr, strlen(time_ptr));
                    426:        } else {
                    427:                        /*
                    428:                         * The second (or minute) hand is sec (or min) 
                    429:                         * sixtieths around the clock face. The hour hand is
                    430:                         * (hour + min/60) twelfths of the way around the
                    431:                         * clock-face.  The derivation is left as an excercise
                    432:                         * for the reader.
                    433:                         */
                    434: 
                    435:                        /*
                    436:                         * 12 hour clock.
                    437:                         */
                    438:                        if(tm.tm_hour > 12)
                    439:                                tm.tm_hour -= 12;
                    440: 
                    441:                        /*
                    442:                         * Erase old hands.
                    443:                         */
                    444:                        if(data->numseg > 0) {
                    445:                            if (data->show_second_hand == TRUE) {
                    446:                                XDrawLines(data->dpy, data->mywin,
                    447:                                        data->EraseGC,
                    448:                                        data->sec,
                    449:                                        VERTICES_IN_HANDS-1,
                    450:                                        CoordModeOrigin);
                    451:                                if(data->Hdpixel != data->bgpixel) {
                    452:                                    XFillPolygon(data->dpy,
                    453:                                        data->mywin, data->EraseGC,
                    454:                                        data->sec,
                    455:                                        VERTICES_IN_HANDS-2,
                    456:                                        Convex, CoordModeOrigin
                    457:                                    );
                    458:                                }
                    459:                            }
                    460:                            if( tm.tm_min != data->otm.tm_min ||
                    461:                                tm.tm_hour != data->otm.tm_hour ) {
                    462:                                XDrawLines( data->dpy,
                    463:                                           data->mywin,
                    464:                                           data->EraseGC,
                    465:                                           data->segbuff,
                    466:                                           VERTICES_IN_HANDS,
                    467:                                           CoordModeOrigin);
                    468:                                XDrawLines( data->dpy,
                    469:                                           data->mywin,
                    470:                                           data->EraseGC,
                    471:                                           data->hour,
                    472:                                           VERTICES_IN_HANDS,
                    473:                                           CoordModeOrigin);
                    474:                                if(data->Hdpixel != data->bgpixel) {
                    475:                                    XFillPolygon( data->dpy,
                    476:                                        data->mywin, data->EraseGC,
                    477:                                        data->segbuff, VERTICES_IN_HANDS,
                    478:                                        Convex, CoordModeOrigin
                    479:                                    );
                    480:                                    XFillPolygon(data->dpy,
                    481:                                        data->mywin, data->EraseGC,
                    482:                                        data->hour,
                    483:                                        VERTICES_IN_HANDS,
                    484:                                        Convex, CoordModeOrigin
                    485:                                    );
                    486:                                }
                    487:                            }
                    488:                    }
                    489: 
                    490:                    if (data->numseg == 0 ||
                    491:                        tm.tm_min != data->otm.tm_min ||
                    492:                        tm.tm_hour != data->otm.tm_hour) {
                    493:                            data->segbuffptr = data->segbuff;
                    494:                            data->numseg = 0;
                    495:                            /*
                    496:                             * Calculate the hour hand, fill it in with its
                    497:                             * color and then outline it.  Next, do the same
                    498:                             * with the minute hand.  This is a cheap hidden
                    499:                             * line algorithm.
                    500:                             */
                    501:                            DrawHand(data,
                    502:                                data->minute_hand_length, data->hand_width,
                    503:                                ((double) tm.tm_min)/60.0
                    504:                            );
                    505:                            if(data->Hdpixel != data->bgpixel)
                    506:                                XFillPolygon( data->dpy,
                    507:                                    data->mywin, data->HandGC,
                    508:                                    data->segbuff, VERTICES_IN_HANDS,
                    509:                                    Convex, CoordModeOrigin
                    510:                                );
                    511:                            XDrawLines( data->dpy,
                    512:                                data->mywin, data->HighGC,
                    513:                                data->segbuff, VERTICES_IN_HANDS,
                    514:                                       CoordModeOrigin);
                    515:                            data->hour = data->segbuffptr;
                    516:                            DrawHand(data, 
                    517:                                data->hour_hand_length, data->hand_width,
                    518:                                ((((double)tm.tm_hour) + 
                    519:                                    (((double)tm.tm_min)/60.0)) / 12.0)
                    520:                            );
                    521:                            if(data->Hdpixel != data->bgpixel) {
                    522:                              XFillPolygon( data->dpy,
                    523:                                           data->mywin, data->HandGC,
                    524:                                           data->hour,
                    525:                                           VERTICES_IN_HANDS,
                    526:                                           Convex, CoordModeOrigin
                    527:                                           );
                    528:                            }
                    529:                            XDrawLines( data->dpy,
                    530:                                       data->mywin, data->HighGC,
                    531:                                       data->hour, VERTICES_IN_HANDS,
                    532:                                       CoordModeOrigin );
                    533: 
                    534:                            data->sec = data->segbuffptr;
                    535:                    }
                    536:                    if (data->show_second_hand == TRUE) {
                    537:                            data->segbuffptr = data->sec;
                    538:                            DrawSecond(data,
                    539:                                data->second_hand_length - 2, 
                    540:                                data->second_hand_width,
                    541:                                data->minute_hand_length + 2,
                    542:                                ((double) tm.tm_sec)/60.0
                    543:                            );
                    544:                            if(data->Hdpixel != data->bgpixel)
                    545:                                XFillPolygon( data->dpy,
                    546:                                    data->mywin, data->HandGC,
                    547:                                    data->sec,
                    548:                                    VERTICES_IN_HANDS -2,
                    549:                                    Convex, CoordModeOrigin
                    550:                            );
                    551:                            XDrawLines( data->dpy,
                    552:                                       data->mywin, data->HighGC,
                    553:                                       data->sec,
                    554:                                       VERTICES_IN_HANDS-1,
                    555:                                       CoordModeOrigin
                    556:                                        );
                    557:                            /*
                    558:                             * keep the pointer from walking too far.
                    559:                             */
                    560:                            data->segbuffptr = data->sec;
                    561:                            data->numseg = data->segbuffptr-data->segbuff;
                    562:                        }
                    563:                        data->otm = tm;
                    564:                        
                    565:                }
                    566: }
                    567:        
                    568: /*
                    569:  * DrawLine - Draws a line.
                    570:  *
                    571:  * blank_length is the distance from the center which the line begins.
                    572:  * length is the maximum length of the hand.
                    573:  * Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
                    574:  * how far around the circle (clockwise) from high noon.
                    575:  *
                    576:  * The blank_length feature is because I wanted to draw tick-marks around the
                    577:  * circle (for seconds).  The obvious means of drawing lines from the center
                    578:  * to the perimeter, then erasing all but the outside most pixels doesn't
                    579:  * work because of round-off error (sigh).
                    580:  */
                    581: static DrawLine(data, blank_length, length, fraction_of_a_circle)
                    582: WidgetData     data;
                    583: Dimension blank_length;
                    584: Dimension length;
                    585: double fraction_of_a_circle;
                    586: {
                    587:        register double angle, cosangle, sinangle;
                    588:        double cos();
                    589:        double sin();
                    590: 
                    591:        /*
                    592:         *  A full circle is 2 PI radians.
                    593:         *  Angles are measured from 12 o'clock, clockwise increasing.
                    594:         *  Since in X, +x is to the right and +y is downward:
                    595:         *
                    596:         *      x = x0 + r * sin(theta)
                    597:         *      y = y0 - r * cos(theta)
                    598:         *
                    599:         */
                    600:        angle = TWOPI * fraction_of_a_circle;
                    601:        cosangle = cos(angle);
                    602:        sinangle = sin(angle);
                    603: 
                    604:        SetSeg( data, 
                    605:               data->centerX + (int)(blank_length * sinangle),
                    606:               data->centerY - (int)(blank_length * cosangle),
                    607:               data->centerX + (int)(length * sinangle),
                    608:               data->centerY - (int)(length * cosangle));
                    609: }
                    610: 
                    611: /*
                    612:  * DrawHand - Draws a hand.
                    613:  *
                    614:  * length is the maximum length of the hand.
                    615:  * width is the half-width of the hand.
                    616:  * Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
                    617:  * how far around the circle (clockwise) from high noon.
                    618:  *
                    619:  */
                    620: static DrawHand(data, length, width, fraction_of_a_circle)
                    621: WidgetData     data;
                    622: Dimension length, width;
                    623: double fraction_of_a_circle;
                    624: {
                    625: 
                    626:        register double angle, cosangle, sinangle;
                    627:        register double ws, wc;
                    628:        Position x, y, x1, y1, x2, y2;
                    629:        double cos();
                    630:        double sin();
                    631: 
                    632:        /*
                    633:         *  A full circle is 2 PI radians.
                    634:         *  Angles are measured from 12 o'clock, clockwise increasing.
                    635:         *  Since in X, +x is to the right and +y is downward:
                    636:         *
                    637:         *      x = x0 + r * sin(theta)
                    638:         *      y = y0 - r * cos(theta)
                    639:         *
                    640:         */
                    641:        angle = TWOPI * fraction_of_a_circle;
                    642:        cosangle = cos(angle);
                    643:        sinangle = sin(angle);
                    644:        /*
                    645:         * Order of points when drawing the hand.
                    646:         *
                    647:         *              1,4
                    648:         *              / \
                    649:         *             /   \
                    650:         *            /     \
                    651:         *          2 ------- 3
                    652:         */
                    653:        wc = width * cosangle;
                    654:        ws = width * sinangle;
                    655:        SetSeg( data,
                    656:               x = data->centerX + round(length * sinangle),
                    657:               y = data->centerY - round(length * cosangle),
                    658:               x1 = data->centerX - round(ws + wc), 
                    659:               y1 = data->centerY + round(wc - ws));  /* 1 ---- 2 */
                    660:        /* 2 */
                    661:        SetSeg( data, x1, y1, 
                    662:               x2 = data->centerX - round(ws - wc), 
                    663:               y2 = data->centerY + round(wc + ws));  /* 2 ----- 3 */
                    664: 
                    665:        SetSeg( data, x2, y2, x, y);    /* 3 ----- 1(4) */
                    666: }
                    667: 
                    668: /*
                    669:  * DrawSecond - Draws the second hand (diamond).
                    670:  *
                    671:  * length is the maximum length of the hand.
                    672:  * width is the half-width of the hand.
                    673:  * offset is direct distance from center to tail end.
                    674:  * Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
                    675:  * how far around the circle (clockwise) from high noon.
                    676:  *
                    677:  */
                    678: static DrawSecond(data, length, width, offset, fraction_of_a_circle)
                    679: WidgetData data;
                    680: Dimension length, width, offset;
                    681: double fraction_of_a_circle;
                    682: {
                    683: 
                    684:        register double angle, cosangle, sinangle;
                    685:        register double ms, mc, ws, wc;
                    686:        register int mid;
                    687:        Position x, y;
                    688:        double cos();
                    689:        double sin();
                    690: 
                    691:        /*
                    692:         *  A full circle is 2 PI radians.
                    693:         *  Angles are measured from 12 o'clock, clockwise increasing.
                    694:         *  Since in X, +x is to the right and +y is downward:
                    695:         *
                    696:         *      x = x0 + r * sin(theta)
                    697:         *      y = y0 - r * cos(theta)
                    698:         *
                    699:         */
                    700:        angle = TWOPI * fraction_of_a_circle;
                    701:        cosangle = cos(angle);
                    702:        sinangle = sin(angle);
                    703:        /*
                    704:         * Order of points when drawing the hand.
                    705:         *
                    706:         *              1,5
                    707:         *              / \
                    708:         *             /   \
                    709:         *            /     \
                    710:         *          2<       >4
                    711:         *            \     /
                    712:         *             \   /
                    713:         *              \ /
                    714:         *      -        3
                    715:         *      |
                    716:         *      |
                    717:         *   offset
                    718:         *      |
                    719:         *      |
                    720:         *      -        + center
                    721:         */
                    722: 
                    723:        mid = (length + offset) / 2;
                    724:        mc = mid * cosangle;
                    725:        ms = mid * sinangle;
                    726:        wc = width * cosangle;
                    727:        ws = width * sinangle;
                    728:        /*1 ---- 2 */
                    729:        SetSeg( data,
                    730:               x = data->centerX + round(length * sinangle),
                    731:               y = data->centerY - round(length * cosangle),
                    732:               data->centerX + round(ms - wc),
                    733:               data->centerY - round(mc + ws) );
                    734:        SetSeg( data, data->centerX + round(offset *sinangle),
                    735:               data->centerY - round(offset * cosangle), /* 2-----3 */
                    736:               data->centerX + round(ms + wc), 
                    737:               data->centerY - round(mc - ws));
                    738:        data->segbuffptr->x = x;
                    739:        data->segbuffptr++->y = y;
                    740:        data->numseg ++;
                    741: }
                    742: 
                    743: static SetSeg( data, x1, y1, x2, y2)
                    744: WidgetData     data;
                    745: int x1, y1, x2, y2;
                    746: {
                    747:        data->segbuffptr->x = x1;
                    748:        data->segbuffptr++->y = y1;
                    749:        data->segbuffptr->x = x2;
                    750:        data->segbuffptr++->y = y2;
                    751:        data->numseg += 2;
                    752: }
                    753: 
                    754: /*
                    755:  *  Draw the clock face (every fifth tick-mark is longer
                    756:  *  than the others).
                    757:  */
                    758: static DrawClockFace(data, second_hand, radius)
                    759: WidgetData data;
                    760: Dimension second_hand;
                    761: Dimension radius;
                    762: {
                    763:        register int i;
                    764:        register int delta = (radius - second_hand) / 3;
                    765:        
                    766:        XClearWindow(data->dpy, data->mywin);
                    767:        data->segbuffptr = data->segbuff;
                    768:        data->numseg = 0;
                    769:        for (i = 0; i < 60; i++)
                    770:                DrawLine(data, (i % 5) == 0 ? second_hand : (radius - delta), radius,
                    771:                 ((double) i)/60.);
                    772:        /*
                    773:         * Go ahead and draw it.
                    774:         */
                    775:        XDrawSegments(data->dpy, data->mywin, 
                    776:                      data->myGC, (XSegment *) &(data->segbuff[0]),
                    777:                      data->numseg/2);
                    778:        
                    779:        data->segbuffptr = data->segbuff;
                    780:        data->numseg = 0;
                    781: }
                    782: 
                    783: static round(x)
                    784: double x;
                    785: {
                    786:        return(x >= 0 ? (int)(x + .5) : (int)(x - .5));
                    787: }
                    788: 
                    789: 
                    790: /*
                    791:  *
                    792:  * Get Attributes
                    793:  *
                    794:  */
                    795: 
                    796: void XtClockGetValues (dpy, window, arglist, argCount)
                    797: Display *dpy;
                    798: Window window;
                    799: ArgList arglist;
                    800: int argCount;
                    801: {
                    802:     WidgetData data;
                    803:     data = DataFromWindow(dpy, window);
                    804:     if (data == NULL) return;
                    805:     globaldata = *data;
                    806:     XtGetValues(resourcelist, XtNumber(resourcelist), arglist, argCount);
                    807: }
                    808: 
                    809: /*
                    810:  *
                    811:  * Set Attributes
                    812:  *
                    813:  */
                    814: 
                    815: void XtClockSetValues (dpy, window, arglist, argCount)
                    816: Display *dpy;
                    817: Window window;
                    818: ArgList arglist;
                    819: int argCount;
                    820: {
                    821:       WidgetData data;
                    822:       int redisplay = FALSE;
                    823:       GCMask valuemask;
                    824:       XGCValues        myXGCV;
                    825:       
                    826:       
                    827:       data = DataFromWindow(dpy, window);
                    828:       if (data == NULL) return;
                    829:       globaldata = *data;
                    830:       XtSetValues(resourcelist, XtNumber(resourcelist), arglist, argCount);
                    831: 
                    832:       if(globaldata.update != data->update) {
                    833:            (void) XtClearTimeOut(data->mywin, data->cookie);
                    834:            XtSetTimeOut(data->mywin, data->cookie, globaldata.update*1000);
                    835:            data->update = globaldata.update;
                    836:            if (data->update <= SECOND_HAND_TIME)
                    837:                 data->show_second_hand = TRUE;
                    838: 
                    839:       }
                    840:       if (globaldata.brpixel != data->brpixel) {
                    841:        data->brpixel = globaldata.brpixel;
                    842:        if (data->brwidth != 0)
                    843:          XSetWindowBorder(data->dpy, data->mywin, data->brpixel);
                    844:        redisplay = TRUE;
                    845:       }
                    846:       if ((globaldata.bgpixel != data->bgpixel) || 
                    847:          (globaldata.fgpixel != data->fgpixel) ||
                    848:          (globaldata.Hdpixel != data->Hdpixel) ||
                    849:          (globaldata.Hipixel != data->Hipixel)) {
                    850:          redisplay = TRUE;
                    851:          if((globaldata.bgpixel != data->bgpixel) || 
                    852:             (globaldata.fgpixel != data->fgpixel)) {
                    853:                valuemask = GCForeground | GCFont | GCBackground | GCLineWidth;
                    854:                myXGCV.foreground = (*data).fgpixel;
                    855:                myXGCV.font = (*data).fontstruct->fid;
                    856:                myXGCV.background = data->bgpixel;
                    857:                data->myGC = XtGetGC(
                    858:                        data->dpy, (XContext) XtNclock, data->mywin, valuemask, &myXGCV);
                    859:          }
                    860:          if (globaldata.bgpixel != data->bgpixel) {
                    861:                valuemask = GCForeground | GCLineWidth;
                    862:                myXGCV.foreground = (*data).bgpixel;
                    863:                data->EraseGC = XtGetGC(
                    864:                        data->dpy, (XContext) XtNclock, data->mywin, valuemask, &myXGCV);
                    865:          }
                    866:          if (globaldata.Hdpixel != data->Hdpixel) {
                    867:                valuemask = GCForeground | GCLineWidth;
                    868:                myXGCV.foreground = (*data).Hdpixel;
                    869:                data->HandGC = XtGetGC(
                    870:                        data->dpy, (XContext) XtNclock, data->mywin, valuemask, &myXGCV);
                    871:          }
                    872:          if (globaldata.Hipixel != data->Hipixel) {
                    873:                 valuemask = GCForeground | GCLineWidth;
                    874:                 myXGCV.foreground = (*data).Hipixel;
                    875:                 data->HighGC = XtGetGC(
                    876:                        data->dpy, (XContext) XtNclock, data->mywin, valuemask, &myXGCV);
                    877:          }
                    878:      }
                    879:       *data = globaldata;
                    880:       if(redisplay == TRUE) {
                    881:        XClearWindow(data->dpy, data->mywin);
                    882:        redisplay_clock(data);
                    883:       }
                    884: }
                    885: 
                    886: 

unix.superglobalmegacorp.com

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