|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.