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