diff options
-rw-r--r-- | Clock-color.ad | 6 | ||||
-rw-r--r-- | Clock.c | 590 | ||||
-rw-r--r-- | Clock.h | 75 | ||||
-rw-r--r-- | ClockP.h | 87 | ||||
-rw-r--r-- | oclmask.bit | 14 | ||||
-rw-r--r-- | oclock.bit | 14 | ||||
-rw-r--r-- | oclock.c | 171 | ||||
-rw-r--r-- | oclock.man | 101 | ||||
-rw-r--r-- | transform.c | 142 | ||||
-rw-r--r-- | transform.h | 56 |
10 files changed, 1256 insertions, 0 deletions
diff --git a/Clock-color.ad b/Clock-color.ad new file mode 100644 index 0000000..00e87f4 --- /dev/null +++ b/Clock-color.ad @@ -0,0 +1,6 @@ +! $Xorg: Clock-col.ad,v 1.3 2000/08/17 19:53:59 cpqbld Exp $ +Clock*Background: grey +Clock*BorderColor: light blue +Clock*hour: yellow +Clock*jewel: yellow +Clock*minute: yellow @@ -0,0 +1,590 @@ +/* + * $Xorg: Clock.c,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +/* + * Clock.c + * + * a NeWS clone clock + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Converters.h> +#include "ClockP.h" +#include <X11/Xos.h> +#include <stdio.h> +#include <math.h> +#include <X11/extensions/shape.h> + +#ifdef X_NOT_STDC_ENV +extern struct tm *localtime(); +#define Time_t long +extern Time_t time(); +#else +#include <time.h> +#define Time_t time_t +#endif + +#define offset(field) XtOffsetOf(ClockRec, clock.field) +#define goffset(field) XtOffsetOf(WidgetRec, core.field) + +static XtResource resources[] = { + {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), + goffset(width), XtRImmediate, (XtPointer) 120}, + {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), + goffset(height), XtRImmediate, (XtPointer) 120}, + {XtNminute, XtCForeground, XtRPixel, sizeof (Pixel), + offset(minute), XtRString, XtDefaultForeground}, + {XtNhour, XtCForeground, XtRPixel, sizeof (Pixel), + offset(hour), XtRString, XtDefaultForeground}, + {XtNjewel, XtCForeground, XtRPixel, sizeof (Pixel), + offset(jewel), XtRString, XtDefaultForeground}, + {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int), + offset (backing_store), XtRString, "default"}, + {XtNborderSize, XtCBorderSize, XtRFloat, sizeof (float), + offset (border_size), XtRString, "0.1"}, + {XtNjewelSize, XtCBorderSize, XtRFloat, sizeof (float), + offset (jewel_size), XtRString, "0.075"}, + {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean), + offset (shape_window), XtRImmediate, (XtPointer) True}, + {XtNtransparent, XtCTransparent, XtRBoolean, sizeof (Boolean), + offset (transparent), XtRImmediate, (XtPointer) False}, +}; + +#undef offset +#undef goffset + +static void new_time(); + +static void Initialize(), Realize(), Destroy(), Redisplay(), Resize(); + +# define BORDER_SIZE(w) ((w)->clock.border_size) +# define WINDOW_WIDTH(w) (2.0 - BORDER_SIZE(w)*2) +# define WINDOW_HEIGHT(w) (2.0 - BORDER_SIZE(w)*2) +# define MINUTE_WIDTH(w) (0.05) +# define HOUR_WIDTH(w) (0.05) +# define JEWEL_SIZE(w) ((w)->clock.jewel_size) +# define MINUTE_LENGTH(w) (JEWEL_Y(w) - JEWEL_SIZE(w) / 2.0) +# define HOUR_LENGTH(w) (MINUTE_LENGTH(w) * 0.6) +# define JEWEL_X(w) (0.0) +# define JEWEL_Y(w) (1.0 - (BORDER_SIZE(w) + JEWEL_SIZE(w))) + +static void ClassInitialize(); + +ClockClassRec clockClassRec = { + { /* core fields */ + /* superclass */ &widgetClassRec, + /* class_name */ "Clock", + /* size */ sizeof(ClockRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ Resize, + /* expose */ Redisplay, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* set_values_almost */ NULL, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ XtInheritQueryGeometry, + } +}; + +static void ClassInitialize() +{ + XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + NULL, 0 ); +} + +WidgetClass clockWidgetClass = (WidgetClass) &clockClassRec; + +/* ARGSUSED */ +static void Initialize (greq, gnew, args, num_args) + Widget greq, gnew; + ArgList args; + Cardinal *num_args; +{ + ClockWidget w = (ClockWidget)gnew; + XtGCMask valuemask; + XGCValues myXGCV; + int shape_event_base, shape_error_base; + + valuemask = GCForeground; + + if (w->clock.transparent) + { + ; + } + else + { + myXGCV.foreground = w->clock.minute; + w->clock.minuteGC = XtGetGC(gnew, valuemask, &myXGCV); + + myXGCV.foreground = w->clock.hour; + w->clock.hourGC = XtGetGC(gnew, valuemask, &myXGCV); + + myXGCV.foreground = w->clock.jewel; + w->clock.jewelGC = XtGetGC(gnew, valuemask, &myXGCV); + + myXGCV.foreground = w->core.background_pixel; + w->clock.eraseGC = XtGetGC(gnew, valuemask, &myXGCV); + } + + /* wait for Realize to add the timeout */ + w->clock.interval_id = 0; + + if (w->clock.shape_window && !XShapeQueryExtension (XtDisplay (w), + &shape_event_base, + &shape_error_base)) + w->clock.shape_window = False; + w->clock.shape_mask = 0; + w->clock.shapeGC = 0; + w->clock.shape_width = 0; + w->clock.shape_height = 0; + w->clock.polys_valid = 0; +} + +static void Resize (widget) + Widget widget; +{ + ClockWidget w = (ClockWidget) widget; + XGCValues xgcv; + Widget parent; + XWindowChanges xwc; + int face_width, face_height; + int x, y; + Pixmap shape_mask; + + if (!XtIsRealized((Widget) w)) + return; + + /* + * compute desired border size + */ + + SetTransform (&w->clock.maskt, + 0, w->core.width, + w->core.height, 0, + -1.0, 1.0, + -1.0, 1.0); + + face_width = abs (Xwidth (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt)); + face_height = abs (Xheight (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt)); + + /* + * shape the windows and borders + */ + + if (w->clock.shape_window) { + + SetTransform (&w->clock.t, + face_width, w->core.width - face_width, + w->core.height - face_height, face_height, + -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2, + -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2); + + /* + * allocate a pixmap to draw shapes in + */ + + if (w->clock.shape_mask && + (w->clock.shape_width != w->core.width || + w->clock.shape_height != w->core.height)) + { + XFreePixmap (XtDisplay (w), w->clock.shape_mask); + w->clock.shape_mask = None; + } + + if (!w->clock.shape_mask) + { + w->clock.shape_mask = XCreatePixmap (XtDisplay (w), XtWindow (w), + w->core.width, w->core.height, 1); + } + shape_mask = w->clock.shape_mask; + if (!w->clock.shapeGC) + w->clock.shapeGC = XCreateGC (XtDisplay (w), shape_mask, 0, &xgcv); + + /* erase the pixmap */ + XSetForeground (XtDisplay (w), w->clock.shapeGC, 0); + XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC, + 0, 0, w->core.width, w->core.height); + XSetForeground (XtDisplay (w), w->clock.shapeGC, 1); + + /* + * draw the bounding shape. Doing this first + * eliminates extra exposure events. + */ + + if (w->clock.border_size > 0.0 || !w->clock.transparent) + { + TFillArc (XtDisplay (w), shape_mask, + w->clock.shapeGC, &w->clock.maskt, + -1.0, -1.0, + 2.0, 2.0, + 0, 360 * 64); + } + + if (w->clock.transparent) + { + if (w->clock.border_size > 0.0) + { + XSetForeground (XtDisplay (w), w->clock.shapeGC, 0); + TFillArc (XtDisplay (w), shape_mask, + w->clock.shapeGC, &w->clock.t, + -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2, + WINDOW_WIDTH(w), WINDOW_HEIGHT(w), + 0, 360 * 64); + XSetForeground (XtDisplay (w), w->clock.shapeGC, 1); + } + paint_jewel (w, shape_mask, w->clock.shapeGC); + paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC); + } + /* + * Find the highest enclosing widget and shape it + */ + + x = 0; + y = 0; + for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) { + x = x + parent->core.x + parent->core.border_width; + y = y + parent->core.y + parent->core.border_width; + } + + XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding, + x, y, shape_mask, ShapeSet); + + /* erase the pixmap */ + XSetForeground (XtDisplay (w), w->clock.shapeGC, 0); + XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC, + 0, 0, w->core.width, w->core.height); + XSetForeground (XtDisplay (w), w->clock.shapeGC, 1); + + /* + * draw the clip shape + */ + + if (w->clock.transparent) + { + paint_jewel (w, shape_mask, w->clock.shapeGC); + paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC); + } + else + { + TFillArc (XtDisplay (w), shape_mask, + w->clock.shapeGC, &w->clock.t, + -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2, + WINDOW_WIDTH(w), WINDOW_HEIGHT(w), + 0, 360 * 64); + } + + XShapeCombineMask (XtDisplay (w), XtWindow (w), ShapeClip, + 0, 0, shape_mask, ShapeSet); + + } else + { + /* + * reconfigure the widget to split the availible + * space between the window and the border + */ + + if (face_width > face_height) + xwc.border_width = face_height; + else + xwc.border_width = face_width; + xwc.width = w->core.width - xwc.border_width * 2; + xwc.height = w->core.height - xwc.border_width * 2; + XConfigureWindow (XtDisplay (w), XtWindow (w), + CWWidth|CWHeight|CWBorderWidth, + &xwc); + + SetTransform (&w->clock.t, + 0, xwc.width, + xwc.height, 0, + -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2, + -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2); + } +} + +static void Realize (gw, valueMask, attrs) + Widget gw; + XtValueMask *valueMask; + XSetWindowAttributes *attrs; +{ + ClockWidget w = (ClockWidget)gw; + + if (w->clock.backing_store != Always + WhenMapped + NotUseful) { + attrs->backing_store = w->clock.backing_store; + *valueMask |= CWBackingStore; + } + if (w->clock.transparent) + { + attrs->background_pixel = w->clock.minute; + *valueMask |= CWBackPixel; + *valueMask &= ~CWBackPixmap; + } + XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent, + *valueMask, attrs ); + if (!w->clock.transparent) + Resize (w); + new_time ((XtPointer) gw, 0); +} + +static void Destroy (gw) + Widget gw; +{ + ClockWidget w = (ClockWidget)gw; + if (w->clock.interval_id) XtRemoveTimeOut (w->clock.interval_id); + if (! w->clock.transparent) { + XtReleaseGC(gw, w->clock.minuteGC); + XtReleaseGC(gw, w->clock.hourGC); + XtReleaseGC(gw, w->clock.jewelGC); + XtReleaseGC(gw, w->clock.eraseGC); + } + if (w->clock.shapeGC) + XFreeGC(XtDisplay(gw), w->clock.shapeGC); + if (w->clock.shape_mask) + XFreePixmap (XtDisplay (w), w->clock.shape_mask); +} + +/* ARGSUSED */ +static void Redisplay(gw, event, region) + Widget gw; + XEvent *event; + Region region; +{ + ClockWidget w; + + w = (ClockWidget) gw; + if (!w->clock.transparent) + { + paint_jewel (w, XtWindow (w), w->clock.jewelGC); + paint_hands (w, XtWindow (w), w->clock.minuteGC, w->clock.hourGC); + } +} + +/* + * routines to draw the hands and jewel + */ + +#ifndef PI /* may be found in <math.h> */ +# define PI (3.14159265358979323846) +#endif + +/* + * converts a number from 0..1 representing a clockwise radial distance + * from the 12 oclock position to a radian measure of the counter-clockwise + * distance from the 3 oclock position + */ + +static double +clock_to_angle (clock) +double clock; +{ + if (clock >= .75) + clock -= 1.0; + return -2.0 * PI * clock + PI / 2.0; +} + +/* ARGSUSED */ +static void new_time (client_data, id) + XtPointer client_data; + XtIntervalId *id; /* unused */ +{ + ClockWidget w = (ClockWidget)client_data; + Time_t now; + struct tm *tm; + + if (!w->clock.transparent) + if (w->clock.polys_valid) { + paint_hands (w, XtWindow (w), w->clock.eraseGC, w->clock.eraseGC); + check_jewel (w, XtWindow (w), w->clock.jewelGC); + } + (void) time (&now); + tm = localtime (&now); + if (tm->tm_hour >= 12) + tm->tm_hour -= 12; + w->clock.hour_angle = clock_to_angle ((((double) tm->tm_hour) + + ((double) tm->tm_min) / 60.0) / 12.0); + w->clock.minute_angle = + clock_to_angle (((double) tm->tm_min) / 60.0); + /* + * add the timeout before painting the hands, that may + * take a while and we'd like the clock to keep up + * with time changes. + */ + w->clock.interval_id = + XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w), + (60 - tm->tm_sec) * 1000, new_time, client_data); + compute_hands (w); + if (w->clock.transparent) + Resize (w); + else + paint_hands (w, XtWindow (w), w->clock.minuteGC, w->clock.hourGC); +} /* new_time */ + +paint_jewel (w, d, gc) +ClockWidget w; +Drawable d; +GC gc; +{ + if (JEWEL_SIZE(w) > 0.0) + { + TFillArc (XtDisplay (w), d, gc, &w->clock.t, + JEWEL_X(w) - JEWEL_SIZE(w) / 2.0, + JEWEL_Y(w) - JEWEL_SIZE(w) / 2.0, + JEWEL_SIZE(w), JEWEL_SIZE(w), 0, 360 * 64); + } +} + +#define sqr(x) ((x)*(x)) + +/* + * check to see if the polygon intersects the circular jewel + */ + +check_jewel_poly (w, poly) +ClockWidget w; +TPoint poly[POLY_SIZE]; +{ + double a2, b2, c2, d2; + double x, y, size; + int i; + + if (JEWEL_SIZE(w) > 0.0) + { + x = JEWEL_X(w); + y = JEWEL_Y(w); + size = JEWEL_SIZE(w); + /* + * check each side of the polygon to see if the + * distance from the line to the center of the + * circular jewel is less than the radius. + */ + for (i = 0; i < POLY_SIZE-1; i++) { + a2 = sqr (poly[i].x - x) + sqr (poly[i].y - y); + b2 = sqr (poly[i+1].x - x) + sqr (poly[i+1].y - y); + c2 = sqr (poly[i].x - poly[i+1].x) + sqr (poly[i].y - poly[i+1].y); + d2 = a2 + b2 - c2; + if (d2 <= sqr (size) && + a2 <= 2 * c2 && b2 <= 2 * c2 || + a2 <= sqr (size) || + b2 <= sqr (size)) + return 1; + } + } + return 0; +} + +check_jewel (w, d, gc) +ClockWidget w; +Drawable d; +GC gc; +{ + if (!w->clock.polys_valid || JEWEL_SIZE(w) <= 0.0) + return; + if ((MINUTE_LENGTH(w) >= (JEWEL_Y(w) - JEWEL_SIZE(w)/2.0) && + check_jewel_poly (w, w->clock.minute_poly)) || + (HOUR_LENGTH(w) >= (JEWEL_Y(w) - JEWEL_SIZE(w)/2.0) && + check_jewel_poly (w, w->clock.minute_poly))) + { + paint_jewel (w, d, gc); + } +} + +/* + * A hand is a rectangle with a triangular cap at the far end. + * This is represented with a five sided polygon. + */ + +compute_hand (w, a, l, width, poly) +ClockWidget w; +double a, l, width; +TPoint poly[POLY_SIZE]; +{ + double c, s; + + c = cos(a); + s = sin(a); + poly[0].x = c * l; + poly[0].y = s * l; + poly[1].x = (l - width) * c - s * width; + poly[1].y = (l - width) * s + c * width; + poly[2].x = (-width) * c - s * width; + poly[2].y = (-width) * s + c * width; + poly[3].x = (-width) * c + s * width; + poly[3].y = (-width) * s - c * width; + poly[4].x = (l - width) * c + s * width; + poly[4].y = (l - width) * s - c * width; + poly[5].x = poly[0].x; + poly[5].y = poly[0].y; +} + +compute_hands (w) +ClockWidget w; +{ + compute_hand (w, w->clock.minute_angle, + MINUTE_LENGTH(w), MINUTE_WIDTH(w), w->clock.minute_poly); + compute_hand (w, w->clock.hour_angle, + HOUR_LENGTH(w), HOUR_WIDTH(w), w->clock.hour_poly); + w->clock.polys_valid = 1; +} + +paint_hand (w, d, gc, poly) +ClockWidget w; +Drawable d; +GC gc; +TPoint poly[POLY_SIZE]; +{ + TFillPolygon (XtDisplay (w), d, gc, &w->clock.t, poly, POLY_SIZE, + Convex, CoordModeOrigin); +} + +paint_hands (w, d, minute_gc, hour_gc) +ClockWidget w; +Drawable d; +GC minute_gc, hour_gc; +{ + if (w->clock.polys_valid) { + paint_hand (w, d, hour_gc, w->clock.hour_poly); + paint_hand (w, d, minute_gc, w->clock.minute_poly); + } +} @@ -0,0 +1,75 @@ +/* $Xorg: Clock.h,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef _XtClock_h +#define _XtClock_h + +/*********************************************************************** + * + * Clock Widget + * + ***********************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background pixel White + border BorderColor pixel Black + borderWidth BorderWidth int 1 + minute Foreground Pixel Black + hour Foreground Pixel Black + height Height int 120 + mappedWhenManaged MappedWhenManaged Boolean True + width Width int 120 + x Position int 0 + y Position int 0 + +*/ + +#define XtNminute "minute" +#define XtNhour "hour" +#define XtNjewel "jewel" + +#define XtNshapeWindow "shapeWindow" +#define XtCShapeWindow "ShapeWindow" +#define XtNtransparent "transparent" +#define XtCTransparent "Transparent" + +#define XtNjewelSize "jewelSize" +#define XtNborderSize "borderSize" +#define XtCBorderSize "BorderSize" + +typedef struct _ClockRec *ClockWidget; /* completely defined in ClockPrivate.h */ +typedef struct _ClockClassRec *ClockWidgetClass; /* completely defined in ClockPrivate.h */ + +extern WidgetClass clockWidgetClass; + +#endif /* _XtClock_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/ClockP.h b/ClockP.h new file mode 100644 index 0000000..408dc4d --- /dev/null +++ b/ClockP.h @@ -0,0 +1,87 @@ +/* $Xorg: ClockP.h,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#ifndef _ClockP_h +#define _ClockP_h + +#include "Clock.h" +#include <X11/CoreP.h> +#include "transform.h" + +#define POLY_SIZE 6 + +/* New fields for the clock widget instance record */ +typedef struct { + Pixel minute; + Pixel hour; + Pixel jewel; + GC minuteGC; + GC hourGC; + GC jewelGC; + GC eraseGC; + GC shapeGC; /* pointer to GraphicsContext */ +/* start of graph stuff */ + int backing_store; /* backing store variety */ + Boolean shape_window; /* use SetWindowShapeMask */ + Boolean transparent; /* make window transparent */ + float border_size; + float jewel_size; + XtIntervalId interval_id; + Transform t; + Transform maskt; + Pixmap shape_mask; /* window shape */ + int shape_width; /* window width when shape last made */ + int shape_height; /* window height when shape last made */ + double hour_angle; /* hour hand position */ + double minute_angle; /* minute hand position */ + int polys_valid; /* polygons contain good data */ + TPoint minute_poly[POLY_SIZE]; /* polygon for minute hand */ + TPoint hour_poly[POLY_SIZE]; /* polygon for hour hand */ +} ClockPart; + +/* Full instance record declaration */ +typedef struct _ClockRec { + CorePart core; + ClockPart clock; +} ClockRec; + +/* New fields for the Clock widget class record */ +typedef struct {int dummy;} ClockClassPart; + +/* Full class record declaration. */ +typedef struct _ClockClassRec { + CoreClassPart core_class; + ClockClassPart clock_class; +} ClockClassRec; + +/* Class pointer. */ +extern ClockClassRec clockClassRec; + +#endif /* _ClockP_h */ diff --git a/oclmask.bit b/oclmask.bit new file mode 100644 index 0000000..19fb3ca --- /dev/null +++ b/oclmask.bit @@ -0,0 +1,14 @@ +#define oclmask_width 32 +#define oclmask_height 32 +static unsigned char oclmask_bits[] = { + 0x00, 0xf0, 0x07, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x80, 0xff, 0xff, 0x00, + 0xc0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x07, + 0xf8, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x1f, + 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f, + 0xfe, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x03, + 0xc0, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00, 0xfe, 0x3f, 0x00, + 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/oclock.bit b/oclock.bit new file mode 100644 index 0000000..c264fe7 --- /dev/null +++ b/oclock.bit @@ -0,0 +1,14 @@ +#define oclock_width 32 +#define oclock_height 32 +static unsigned char oclock_bits[] = { + 0x00, 0xf0, 0x07, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x80, 0x8f, 0xf8, 0x00, + 0xc0, 0xc1, 0xc1, 0x01, 0xe0, 0x80, 0x80, 0x03, 0x30, 0x00, 0x00, 0x06, + 0x18, 0x00, 0x00, 0x0c, 0x1c, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x70, 0x18, + 0x06, 0x00, 0x78, 0x30, 0x06, 0x00, 0x3c, 0x30, 0x06, 0x00, 0x1e, 0x30, + 0x03, 0x00, 0x0f, 0x60, 0x03, 0x80, 0x07, 0x60, 0x03, 0xc0, 0x03, 0x60, + 0x03, 0xc0, 0x01, 0x60, 0x03, 0xc0, 0x01, 0x60, 0x03, 0xc0, 0x01, 0x60, + 0x03, 0xc0, 0x01, 0x60, 0x06, 0xc0, 0x01, 0x30, 0x06, 0xc0, 0x01, 0x30, + 0x06, 0xc0, 0x01, 0x30, 0x0c, 0xc0, 0x01, 0x18, 0x1c, 0xc0, 0x01, 0x1c, + 0x18, 0xc0, 0x01, 0x0c, 0x30, 0xc0, 0x01, 0x06, 0xe0, 0xc0, 0x81, 0x03, + 0xc0, 0x81, 0xc0, 0x01, 0x80, 0x0f, 0xf8, 0x00, 0x00, 0xfe, 0x3f, 0x00, + 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/oclock.c b/oclock.c new file mode 100644 index 0000000..32bc912 --- /dev/null +++ b/oclock.c @@ -0,0 +1,171 @@ +/* + * $Xorg: oclock.c,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +#include <X11/Intrinsic.h> +#include <X11/Xatom.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xmu/Editres.h> +#include "Clock.h" +#include <stdio.h> + +#ifdef XKB +#include <X11/extensions/XKBbells.h> +#endif + +#include "oclock.bit" +#include "oclmask.bit" + +extern void exit(); +static void quit(); + +static XtActionsRec actions[] = { + {"quit", quit} +}; + +static Atom wm_delete_window; + +static void die(w, client_data, call_data) + Widget w; + XtPointer client_data, call_data; +{ + XCloseDisplay(XtDisplay(w)); + exit(0); +} + +static void save(w, client_data, call_data) + Widget w; + XtPointer client_data, call_data; +{ + return; /* stateless */ +} + +/* Exit with message describing command line format */ + +void usage() +{ + fprintf(stderr, +"usage: oclock\n"); + fprintf (stderr, +" [-geometry [{width}][x{height}][{+-}{xoff}[{+-}{yoff}]]] [-display [{host}]:[{vs}]]\n"); + fprintf(stderr, +" [-fg {color}] [-bg {color}] [-bd {color}] [-bw {pixels}]\n"); + fprintf(stderr, +" [-minute {color}] [-hour {color}] [-jewel {color}]\n"); + fprintf(stderr, +" [-backing {backing-store}] [-shape] [-noshape] [-transparent]\n"); + exit(1); +} + +/* Command line options table. Only resources are entered here...there is a + pass over the remaining options after XtParseCommand is let loose. */ + +static XrmOptionDescRec options[] = { +{"-fg", "*Foreground", XrmoptionSepArg, NULL}, +{"-bg", "*Background", XrmoptionSepArg, NULL}, +{"-foreground", "*Foreground", XrmoptionSepArg, NULL}, +{"-background", "*Background", XrmoptionSepArg, NULL}, +{"-minute", "*clock.minute", XrmoptionSepArg, NULL}, +{"-hour", "*clock.hour", XrmoptionSepArg, NULL}, +{"-jewel", "*clock.jewel", XrmoptionSepArg, NULL}, +{"-backing", "*clock.backingStore", XrmoptionSepArg, NULL}, +{"-shape", "*clock.shapeWindow", XrmoptionNoArg, "TRUE"}, +{"-noshape", "*clock.shapeWindow", XrmoptionNoArg, "FALSE"}, +{"-transparent","*clock.transparent", XrmoptionNoArg, "TRUE"}, +}; + +void main(argc, argv) + int argc; + char **argv; +{ + XtAppContext xtcontext; + Widget toplevel; + Widget clock; + Arg arg[2]; + int i; + + toplevel = XtOpenApplication(&xtcontext, "Clock", + options, XtNumber(options), &argc, argv, NULL, + sessionShellWidgetClass, NULL, 0); + if (argc != 1) usage(); + XtAddCallback(toplevel, XtNsaveCallback, save, NULL); + XtAddCallback(toplevel, XtNdieCallback, die, NULL); + + XtAppAddActions + (xtcontext, actions, XtNumber(actions)); + XtOverrideTranslations + (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); + + i = 0; + XtSetArg (arg[i], XtNiconPixmap, + XCreateBitmapFromData (XtDisplay(toplevel), + XtScreen(toplevel)->root, + (char *)oclock_bits, + oclock_width, oclock_height)); + i++; + XtSetArg (arg[i], XtNiconMask, + XCreateBitmapFromData (XtDisplay(toplevel), + XtScreen(toplevel)->root, + (char *)oclmask_bits, + oclmask_width, oclmask_height)); + i++; + XtSetValues (toplevel, arg, i); + + clock=XtCreateManagedWidget("clock", clockWidgetClass, toplevel, NULL, 0); + XtRealizeWidget (toplevel); + + wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", + False); + (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), + &wm_delete_window, 1); + + XtAddEventHandler(toplevel, (EventMask) 0, TRUE, + _XEditResCheckMessages, NULL); + + XtAppMainLoop(xtcontext); +} + +static void quit(w, event, params, num_params) + Widget w; + XEvent *event; + String *params; + Cardinal *num_params; +{ + Arg arg; + + if (event->type == ClientMessage && + event->xclient.data.l[0] != wm_delete_window) { +#ifdef XKB + XkbStdBell(XtDisplay(w), XtWindow(w), 0, XkbBI_BadValue); +#else + XBell(XtDisplay(w), 0); +#endif + } else { + XtSetArg(arg, XtNjoinSession, False); + XtSetValues(w, &arg, (Cardinal)1); + die(w, NULL, NULL); + } +} diff --git a/oclock.man b/oclock.man new file mode 100644 index 0000000..41128e1 --- /dev/null +++ b/oclock.man @@ -0,0 +1,101 @@ +.\" $Xorg: oclock.man,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ +.\" Copyright 1989, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.TH OCLOCK 1 "Release 6.4" "X Version 11" +.SH NAME +oclock \- round X clock +.SH SYNOPSIS +.B oclock +[\-option ... ] +.SH DESCRIPTION +.I Oclock +simply displays the current time on an analog display. +.SH OPTIONS +.TP 8 +.B \-fg \fIcolor\fB +choose a different color for the both hands and the jewel of the clock +.TP 8 +.B \-bg \fIcolor\fB +choose a different color for the background. +.TP 8 +.B \-jewel \fIcolor\fB +choose a different color for the jewel on the clock. +.TP 8 +.B \-minute \fIcolor\fB +choose a different color for the minute hand of the clock. +.TP 8 +.B \-hour \fIcolor\fB +choose a different color for the hour hand of the clock. +.TP 8 +.B \-backing \fI{ WhenMapped Always NotUseful }\fB +selects an appropriate level of backing store. +.TP 8 +.B \-geometry \fIgeometry\fB +define the initial window geometry; see \fIX(1)\fP. +.TP 8 +.B \-display \fIdisplay\fB +specify the display to use; see \fIX(1)\fP. +.TP 8 +.B \-bd \fIcolor\fB +choose a different color for the window border. +.TP 8 +.B \-bw \fIwidth\fB +choose a different width for the window border. As the Clock widget changes +its border around quite a bit, this is most usefully set to zero. +.TP 8 +.B \-shape +causes the clock to use the Shape extension to create an oval window. +This is the default unless the shapeWindow resource is set to false. +.TP 8 +.B \-noshape +causes the clock to not reshape itself and ancestors to exactly +fit the outline of the clock. +.TP 8 +.B \-transparent +causes the clock to consist only of the jewel, the hands, and the border. +.SH COLORS +If you would like your clock to be viewable in color, include the following +in the #ifdef COLOR section you read with xrdb: +.sp 1 +*customization: -color +.sp 1 +.br +This will cause oclock to pick up the colors in the app-defaults color +customization file: +<XRoot>/lib/X11/app-defaults/Clock-color. +Below are the default colors: +.sp 1 +Clock*Background: grey +.br +Clock*BorderColor: light blue +.br +Clock*hour: yellow +.br +Clock*jewel: yellow +.br +Clock*minute: yellow +.SH "SEE ALSO" +X(1), X Toolkit documentation +.SH AUTHOR +Keith Packard, MIT X Consortium diff --git a/transform.c b/transform.c new file mode 100644 index 0000000..60a717a --- /dev/null +++ b/transform.c @@ -0,0 +1,142 @@ +/* $Xorg: transform.c,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +/* + * transformed coordinate system objects for X + */ + +# include <X11/Xlib.h> +# include "transform.h" + +static XPoint * +TranslatePoints (points, n_points, t, mode) +TPoint *points; +int n_points; +Transform *t; +int mode; +{ + XPoint *xpoints; + int i; + double xoff = 0.0, yoff = 0.0; + + xpoints = (XPoint *) malloc ((unsigned)n_points * sizeof (*xpoints)); + if (!xpoints) + return 0; + for (i = 0; i < n_points; i++) { + xpoints[i].x = Xx(points[i].x + xoff, points[i].y + yoff, t); + xpoints[i].y = Xy(points[i].x + xoff, points[i].y + yoff, t); + if (mode == CoordModePrevious) { + xoff += points[i].x; + yoff += points[i].y; + } + } + return xpoints; +} + +TFillPolygon (dpy, d, gc, t, points, n_points, shape, mode) +register Display *dpy; +Drawable d; +GC gc; +Transform *t; +TPoint *points; +int n_points; +int shape; +int mode; +{ + XPoint *xpoints; + + xpoints = TranslatePoints (points, n_points, t, mode); + if (xpoints) { + XFillPolygon (dpy, d, gc, xpoints, n_points, shape, + CoordModeOrigin); + free (xpoints); + } +} + +TDrawArc (dpy, d, gc, t, x, y, width, height, angle1, angle2) + register Display *dpy; + Drawable d; + GC gc; + Transform *t; + double x, y, width, height; + int angle1, angle2; +{ + int xx, xy, xw, xh; + + xx = Xx(x,y,t); + xy = Xy(x,y,t); + xw = Xwidth (width, height, t); + xh = Xheight (width, height, t); + if (xw < 0) { + xx += xw; + xw = -xw; + } + if (xh < 0) { + xy += xh; + xh = -xh; + } + XDrawArc (dpy, d, gc, xx, xy, xw, xh, angle1, angle2); +} + +TFillArc (dpy, d, gc, t, x, y, width, height, angle1, angle2) + register Display *dpy; + Drawable d; + GC gc; + Transform *t; + double x, y, width, height; + int angle1, angle2; +{ + int xx, xy, xw, xh; + + xx = Xx(x,y,t); + xy = Xy(x,y,t); + xw = Xwidth (width, height, t); + xh = Xheight (width, height, t); + if (xw < 0) { + xx += xw; + xw = -xw; + } + if (xh < 0) { + xy += xh; + xh = -xh; + } + XFillArc (dpy, d, gc, xx, xy, xw, xh, angle1, angle2); +} + +SetTransform (t, xx1, xx2, xy1, xy2, tx1, tx2, ty1, ty2) +Transform *t; +int xx1, xx2, xy1, xy2; +double tx1, tx2, ty1, ty2; +{ + t->mx = ((double) xx2 - xx1) / (tx2 - tx1); + t->bx = ((double) xx1) - t->mx * tx1; + t->my = ((double) xy2 - xy1) / (ty2 - ty1); + t->by = ((double) xy1) - t->my * ty1; +} diff --git a/transform.h b/transform.h new file mode 100644 index 0000000..6377979 --- /dev/null +++ b/transform.h @@ -0,0 +1,56 @@ +/* $Xorg: transform.h,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +/* + * header file for transformed coordinate system. No rotations + * supported, as elipses cannot be rotated in X. + */ + +typedef struct _transform { + double mx, bx; + double my, by; +} Transform; + +typedef struct _TPoint { + double x, y; +} TPoint; + +typedef struct _TRectangle { + double x, y, width, height; +} TRectangle; + +# define Xx(x,y,t) ((int)((t)->mx * (x) + (t)->bx + 0.5)) +# define Xy(x,y,t) ((int)((t)->my * (y) + (t)->by + 0.5)) +# define Xwidth(w,h,t) ((int)((t)->mx * (w) + 0.5)) +# define Xheight(w,h,t) ((int)((t)->my * (h) + 0.5)) +# define Tx(x,y,t) ((((double) (x)) - (t)->bx) / (t)->mx) +# define Ty(x,y,t) ((((double) (y)) - (t)->by) / (t)->my) +# define Twidth(w,h,t) (((double) (w)) / (t)->mx) +# define Theight(w,h,t) (((double) (h)) / (t)->my) |