home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume1 / dclock / part01 / Dclock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-15  |  18.5 KB  |  634 lines

  1. /*
  2.  * Dclock.c -- a digital clock widget.
  3.  * Author: Dan Heller <island!argv@sun.com>
  4.  */
  5. #include <stdio.h>
  6. #include <X11/IntrinsicP.h>
  7. #include <X11/Xos.h>
  8. #include <X11/StringDefs.h>
  9. #include "DclockP.h"
  10.  
  11. static void
  12.     Initialize(), Resize(), Realize(), Destroy(), Redisplay(),
  13.     timeout(), toggle_bell(), toggle_reverse_video(), toggle_scroll(),
  14.     toggle_seconds(), show_dialog_box(), GetGC(), make_number(), show_time(),
  15.     show_date(), scroll_time();
  16.  
  17. #define BORDER        5
  18. #define CLOCK_WIDTH    256
  19. #define CLOCK_HEIGHT    80
  20. #define when        break;case
  21. #define otherwise    break;default
  22.  
  23. static Boolean SetValues();
  24. static int winwidth = CLOCK_WIDTH;
  25. static int winheight = CLOCK_HEIGHT;
  26. static Boolean false = False;
  27. static Boolean true = True;
  28. static double x_ratio, y_ratio;
  29. static Pixmap old_pix[4];
  30. static struct tm before;
  31.  
  32. extern int exit();
  33.  
  34. static char defaultTranslations[] =
  35.     "<Key>b:        toggle-bell()        \n\
  36.      <Key>j:        toggle-scroll()        \n\
  37.      <Key>r:        toggle-reverse-video()    \n\
  38.      <Key>s:        toggle-seconds()    \n\
  39.      <Btn3Down>:    dialog-box()";
  40.  
  41. static XtActionsRec actionsList[] = {
  42.     { "toggle-bell",        toggle_bell        },
  43.     { "toggle-scroll",        toggle_scroll        },
  44.     { "toggle-reverse-video",    toggle_reverse_video    },
  45.     { "toggle-seconds",        toggle_seconds        },
  46.     { "dialog-box",        show_dialog_box        },
  47. };
  48.  
  49. static XtResource resources[] = {
  50.     { XtNwidth, XtCWidth, XtRInt, sizeof(int),
  51.     XtOffset(Widget,core.width), XtRInt, (caddr_t)&winwidth },
  52.     { XtNheight, XtCHeight, XtRInt, sizeof(int),
  53.     XtOffset(Widget,core.height), XtRInt, (caddr_t)&winheight },
  54.     { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  55.         XtOffset(DclockWidget,dclock.foreground), XtRString, "Black"},
  56.     { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
  57.     XtOffset(DclockWidget,dclock.reverse), XtRBoolean, (caddr_t)&false},
  58.     { XtNscroll, XtCBoolean, XtRBoolean, sizeof (Boolean),
  59.     XtOffset(DclockWidget,dclock.scroll), XtRBoolean, (caddr_t)&true},
  60.     { XtNbell, XtCBoolean, XtRBoolean, sizeof (Boolean),
  61.     XtOffset(DclockWidget,dclock.bell), XtRBoolean, (caddr_t)&false},
  62.     { XtNseconds, XtCBoolean, XtRBoolean, sizeof (Boolean),
  63.     XtOffset(DclockWidget,dclock.seconds), XtRBoolean, (caddr_t)&false},
  64.     { XtNdate, XtCString, XtRString, sizeof (String),
  65.     XtOffset(DclockWidget,dclock.date_fmt), XtRString, NULL},
  66.     { XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  67.     XtOffset(DclockWidget,dclock.font), XtRString, "Fixed"},
  68. };
  69.  
  70. DclockClassRec dclockClassRec = {
  71.     { /* core fields */
  72.     /* superclass        */    &widgetClassRec,
  73.     /* class_name        */    "Dclock",
  74.     /* widget_size        */    sizeof(DclockRec),
  75.     /* class_initialize        */    NULL,
  76.     /* class_part_initialize    */    NULL,
  77.     /* class_inited        */    FALSE,
  78.     /* initialize        */    Initialize,
  79.     /* initialize_hook        */    NULL,
  80.     /* realize            */    Realize,
  81.     /* actions            */    actionsList,
  82.     /* num_actions        */    XtNumber(actionsList),
  83.     /* resources        */    resources,
  84.     /* resource_count        */    XtNumber(resources),
  85.     /* xrm_class        */    NULL,
  86.     /* compress_motion        */    TRUE,
  87.     /* compress_exposure    */    TRUE,
  88.     /* compress_enterleave    */    TRUE,
  89.     /* visible_interest        */    FALSE,
  90.     /* destroy            */    Destroy,
  91.     /* resize            */    Resize,
  92.     /* expose            */    Redisplay,
  93.     /* set_values        */    SetValues,
  94.     /* set_values_hook        */    NULL,
  95.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  96.     /* get_values_hook        */    NULL,
  97.     /* accept_focus        */    NULL,
  98.     /* version            */    XtVersion,
  99.     /* callback_private        */    NULL,
  100.     /* tm_table            */    defaultTranslations,
  101.     /* query_geometry        */    NULL,
  102.     }
  103. };
  104.  
  105. WidgetClass dclockWidgetClass = (WidgetClass) &dclockClassRec;
  106.  
  107. /* ARGSUSED */
  108. static void
  109. Initialize (request, new)
  110. DclockWidget   request;
  111. DclockWidget   new;
  112. {
  113.     GetGC(new);
  114. }
  115.  
  116. static void
  117. GetGC(w)
  118. DclockWidget w;
  119. {
  120.     XGCValues          xgcv;
  121.     XtGCMask        gc_mask = GCFont | GCForeground | GCBackground;
  122.  
  123. #ifdef NOT_NOW
  124.     if (w->dclock.reverse) {
  125.     Pixel fg = w->dclock.foreground;
  126.     Pixel bg = w->core.background_pixel;
  127.  
  128.     if (w->core.border_pixel == fg)
  129.         w->core.border_pixel = bg;
  130.     w->dclock.foreground = bg;
  131.     w->core.background_pixel = fg;
  132.     xgcv.function = GXcopyInverted;        gc_mask |= GCFunction;
  133.     } else
  134.     xgcv.function = GXcopy;        gc_mask |= GCFunction;
  135. #endif /* NOT_NOW */
  136.  
  137.     xgcv.font = w->dclock.font->fid;
  138.     xgcv.foreground = BlackPixel(XtDisplay(w), DefaultScreen(XtDisplay(w)));
  139.     xgcv.background = WhitePixel(XtDisplay(w), DefaultScreen(XtDisplay(w)));
  140.     /*
  141.     xgcv.foreground = w->dclock.foreground;
  142.     xgcv.background = w->core.background_pixel;
  143.     */
  144.  
  145.     w->dclock.foreGC = XtGetGC ((Widget) w, gc_mask, &xgcv);
  146.     xgcv.foreground = w->core.background_pixel;
  147.     xgcv.background = w->dclock.foreground;
  148.     w->dclock.backGC = XtGetGC ((Widget) w, gc_mask, &xgcv);
  149. }
  150.  
  151. static void
  152. Realize (w, valueMask, attrs)
  153. Widget w;
  154. XtValueMask *valueMask;
  155. XSetWindowAttributes *attrs;
  156. {
  157.     *valueMask |= CWBitGravity;
  158.     attrs->bit_gravity = ForgetGravity;
  159.     XtCreateWindow (w, InputOutput, (Visual *) CopyFromParent,
  160.             *valueMask, attrs);
  161.     Resize(w);
  162. }
  163.  
  164. static void
  165. Destroy (w)
  166. DclockWidget w;
  167. {
  168.     int n;
  169.  
  170.     XtRemoveTimeOut(w->dclock.interval_id);
  171.     XtDestroyGC (w->dclock.foreGC);
  172.     XtDestroyGC (w->dclock.backGC);
  173.     for (n = 0; n < 10; n++) {
  174.     XFreePixmap(XtDisplay(w), w->dclock.digits[n]);
  175.     XFreePixmap(XtDisplay(w), w->dclock.tiny_digits[n]);
  176.     }
  177.     if (w->dclock.colon[0])
  178.     XFreePixmap(XtDisplay(w), w->dclock.colon[0]);
  179.     if (w->dclock.colon[1])
  180.     XFreePixmap(XtDisplay(w), w->dclock.colon[1]);
  181. }
  182.  
  183. /* ARGSUSED */
  184. static void
  185. Resize  (w)
  186. DclockWidget    w;
  187. {
  188.     int i, digit_w, digit_h;
  189.     Pixmap pix;
  190.     GC gc;
  191.  
  192.     if (!XtIsRealized(w))
  193.     return;
  194.  
  195.     winwidth = w->core.width;
  196.     winheight = w->core.height;
  197.  
  198.     x_ratio = (double)winwidth / CLOCK_WIDTH;
  199.     y_ratio =  (double)winheight / CLOCK_HEIGHT;
  200.  
  201.     if (w->dclock.date_fmt)
  202.     /* make win temporarily shorter so digits will fit on top of date */
  203.     winheight -= w->dclock.font->ascent + w->dclock.font->descent;
  204.  
  205.     digit_w = winwidth/(4 - !w->dclock.seconds) - (int)(x_ratio*BORDER*5);
  206.     digit_h = winheight - (int)(y_ratio * BORDER*2);
  207.     w->dclock.digit_w = digit_w;
  208.     w->dclock.digit_h = digit_h;
  209.  
  210.     gc = w->dclock.reverse? w->dclock.backGC : w->dclock.foreGC;
  211.  
  212.     for (i = 0; i < 10; i++) {
  213.     /* Make the big digit */
  214.     if (w->dclock.digits[i])
  215.         XFreePixmap(XtDisplay(w), w->dclock.digits[i]);
  216.     w->dclock.digits[i] =
  217.           XCreatePixmap(XtDisplay(w), XtWindow(w), digit_w, digit_h, 1);
  218.     make_number(w, w->dclock.digits[i], gc, i, digit_w, digit_h);
  219.  
  220.     /* make smaller version of this digit for use by "seconds" */
  221.     if (w->dclock.tiny_digits[i])
  222.         XFreePixmap(XtDisplay(w), w->dclock.tiny_digits[i]);
  223.     w->dclock.tiny_digits[i] =
  224.           XCreatePixmap(XtDisplay(w), XtWindow(w), digit_w/2,digit_h/2,1);
  225.     make_number(w, w->dclock.tiny_digits[i], gc, i, digit_w/2, digit_h/2);
  226.     }
  227.     /* The colon[0] area is blank */
  228.     if (w->dclock.colon[0])
  229.     XFreePixmap(XtDisplay(w), w->dclock.colon[0]);
  230.     w->dclock.colon[0] =
  231.     XCreatePixmap(XtDisplay(w), XtWindow(w), digit_w, digit_h, 1);
  232.     if (w->dclock.reverse)
  233.     XFillRectangle(XtDisplay(w), w->dclock.colon[0], w->dclock.foreGC,
  234.                0, 0, digit_w,digit_h);
  235.     else
  236.     XFillRectangle(XtDisplay(w), w->dclock.colon[0], w->dclock.backGC,
  237.                0, 0, digit_w,digit_h);
  238.  
  239.     /* colon[1] area has two squares */
  240.     if (w->dclock.colon[1])
  241.     XFreePixmap(XtDisplay(w), w->dclock.colon[1]);
  242.     w->dclock.colon[1] = XCreatePixmap(XtDisplay(w), XtWindow(w),
  243.                        (int)(30*x_ratio), digit_h, 1);
  244.     if (w->dclock.reverse)
  245.     /* black background with white squres */
  246.         XFillRectangle(XtDisplay(w), w->dclock.colon[1], w->dclock.foreGC,
  247.                0, 0, (int)(30*x_ratio), digit_h);
  248.     else
  249.         XFillRectangle(XtDisplay(w), w->dclock.colon[1], w->dclock.backGC,
  250.                0, 0, (int)(30*x_ratio), digit_h);
  251.     XFillArc(XtDisplay(w), w->dclock.colon[1], gc,
  252.         (int)(15*x_ratio), digit_h/3, digit_w/7, digit_w/7,
  253.         0, 360 * 64);
  254.     XFillArc(XtDisplay(w), w->dclock.colon[1], gc,
  255.         (int)(15*x_ratio), (2*digit_h)/3, digit_w/7, digit_w/7,
  256.         0, 360 * 64);
  257.  
  258.     /* to optimize scrolling information (see scroll_time()) */
  259.     old_pix[0] = w->dclock.digits[0];
  260.     old_pix[1] = old_pix[2] = old_pix[3] = 0;
  261.  
  262.     if (w->dclock.date_fmt)
  263.     /* restore size */
  264.     winheight += w->dclock.font->ascent + w->dclock.font->descent;
  265. }
  266.  
  267. /* Defines to draw the (simulated) LED bars for each light in the digit */
  268. #define TOP    (pts[0].x = 2, pts[0].y = pts[1].y = 0, pts[1].x = w-2, \
  269.                 pts[3].x = 2+6*x_ratio, pts[3].y = pts[2].y = 6*y_ratio, \
  270.         pts[2].x = w - pts[3].x, \
  271.         XFillPolygon(dpy, pix, gc, pts, 4, Convex, CoordModeOrigin));
  272.  
  273. #define MIDDLE (pts[0].x = 2, pts[0].y = h/2 - 1, \
  274.         pts[1].x = 6*x_ratio, pts[1].y = h/2 - 3*y_ratio, \
  275.                 pts[2].x = w-pts[1].x, pts[2].y = pts[1].y, \
  276.                 pts[3].x = w-2, pts[3].y = h/2 - 1, \
  277.         pts[4].x = pts[2].x, pts[4].y = h/2 + 3*y_ratio, \
  278.         pts[5].x = pts[1].x, pts[5].y = pts[4].y, \
  279.         XFillPolygon(dpy, pix, gc, pts, 6, Convex, CoordModeOrigin));
  280.  
  281. #define BOTTOM (pts[0].x = 2, pts[0].y = pts[1].y = h, pts[1].x = w-2, \
  282.                 pts[3].x = 6*x_ratio, pts[3].y = pts[2].y = h - 6*y_ratio, \
  283.         pts[2].x = w - pts[3].x, \
  284.         XFillPolygon(dpy, pix, gc, pts, 4, Convex, CoordModeOrigin));
  285.  
  286. #define T_LEFT (pts[0].x = pts[1].x = 0, pts[0].y = 2, pts[1].y = h/2-2, \
  287.                 pts[2].x = pts[3].x = 6*x_ratio, \
  288.         pts[2].y = h/2 - 5*y_ratio, pts[3].y = 8*y_ratio, \
  289.         XFillPolygon(dpy, pix, gc, pts, 4, Convex, CoordModeOrigin));
  290.  
  291. #define B_LEFT (pts[0].x = pts[1].x = 0, pts[0].y = h/2, pts[1].y = h, \
  292.                 pts[2].x = pts[3].x = 6*x_ratio, \
  293.         pts[3].y = h/2 + 5*y_ratio, pts[2].y = h - 8*y_ratio, \
  294.         XFillPolygon(dpy, pix, gc, pts, 4, Convex, CoordModeOrigin));
  295.  
  296. #define T_RIGHT (pts[0].x = pts[1].x = w, pts[0].y = 2, pts[1].y = h/2-2, \
  297.                  pts[2].x = pts[3].x = w-6*x_ratio, \
  298.          pts[2].y = h/2 - 5*y_ratio, pts[3].y = 8*y_ratio, \
  299.          XFillPolygon(dpy, pix, gc, pts, 4, Convex, CoordModeOrigin));
  300.  
  301. #define B_RIGHT (pts[0].x = pts[1].x = w, pts[0].y = h/2, pts[1].y = h, \
  302.                  pts[2].x = pts[3].x = w-6*x_ratio, \
  303.          pts[3].y = h/2 + 5*y_ratio, pts[2].y = h - 8*y_ratio, \
  304.          XFillPolygon(dpy, pix, gc, pts, 4, Convex, CoordModeOrigin));
  305.  
  306. static void
  307. make_number(dw, pix, gc, n, w, h)
  308. DclockWidget dw;
  309. Pixmap pix;
  310. GC gc;
  311. int n, w, h;
  312. {
  313.     XPoint pts[6];
  314.     Display *dpy = XtDisplay(dw);
  315.  
  316.     if (dw->dclock.reverse)
  317.     XFillRectangle(dpy, pix, dw->dclock.foreGC, 0, 0, w, h);
  318.     else
  319.     XFillRectangle(dpy, pix, dw->dclock.backGC, 0, 0, w, h);
  320.     switch(n) {
  321.     when 0: TOP  T_RIGHT  B_RIGHT  BOTTOM  B_LEFT  T_LEFT
  322.     when 1: T_RIGHT  B_RIGHT
  323.     when 2: TOP  T_RIGHT  MIDDLE  B_LEFT  BOTTOM
  324.     when 3: TOP  T_RIGHT  MIDDLE  B_RIGHT  BOTTOM
  325.     when 4: T_LEFT  MIDDLE  T_RIGHT  B_RIGHT
  326.     when 5: TOP  T_LEFT  MIDDLE  B_RIGHT  BOTTOM
  327.     when 6: T_LEFT  B_LEFT  MIDDLE BOTTOM B_RIGHT
  328.     when 7: TOP  T_RIGHT  B_RIGHT
  329.     when 8: T_LEFT B_LEFT MIDDLE TOP BOTTOM T_RIGHT B_RIGHT
  330.     when 9: TOP T_LEFT T_RIGHT MIDDLE B_RIGHT
  331.     otherwise: MIDDLE
  332.     }
  333. }
  334.  
  335. /* ARGSUSED */
  336. static void
  337. Redisplay  (w)
  338. DclockWidget    w;
  339. {
  340.     Boolean save_scroll = w->dclock.scroll;
  341.     long t;
  342.  
  343.     if (!XtIsRealized(w))
  344.     return;
  345.  
  346.     if (w->dclock.interval_id)
  347.     XtRemoveTimeOut(w->dclock.interval_id);
  348.     if (w->dclock.reverse)
  349.     XFillRectangle(XtDisplay(w), XtWindow(w), w->dclock.foreGC,
  350.         0, 0, w->core.width, w->core.height);
  351.     else
  352.     XClearWindow(XtDisplay(w), XtWindow(w));
  353.     before.tm_min = before.tm_hour = before.tm_wday = -1;
  354.     old_pix[0] = w->dclock.digits[0];
  355.     old_pix[1] = old_pix[2] = old_pix[3] = 0;
  356.     w->dclock.scroll = FALSE;
  357.     show_time(w);
  358.     w->dclock.scroll = save_scroll;
  359.     if (w->dclock.seconds)
  360.     w->dclock.interval_id = XtAddTimeOut(1000, timeout, w);
  361.     else {
  362.     t = time(0);
  363.     w->dclock.interval_id =
  364.         XtAddTimeOut((unsigned long)(60 - (t % 60)) * 1000, timeout, w);
  365.     }
  366. }
  367.  
  368. static void
  369. show_time(w)
  370. DclockWidget w;
  371. {
  372.     char buf[11];
  373.     long t = time(0);
  374.     register struct tm *l_time = localtime(&t);
  375.     int digit_w = w->dclock.digit_w;
  376.     int digit_h = w->dclock.digit_h;
  377.     Display *dpy = XtDisplay(w);
  378.     Window win = XtWindow(w);
  379.     GC gc = w->dclock.reverse ? w->dclock.backGC : w->dclock.foreGC;
  380.  
  381.     (void) sprintf(buf, "%02d%02d",
  382.          (l_time->tm_hour) ?
  383.         ((l_time->tm_hour <= 12)? l_time->tm_hour: l_time->tm_hour-12): 12,
  384.           l_time->tm_min);
  385.  
  386.     if (l_time->tm_min != before.tm_min || l_time->tm_hour != before.tm_hour)
  387.     scroll_time(w, buf);
  388.  
  389.     if (w->dclock.seconds) {
  390.     XCopyArea(dpy, w->dclock.tiny_digits[l_time->tm_sec/10], win, gc, 0, 0,
  391.           digit_w/2, digit_h/2,
  392.           winwidth - 2*(digit_w/2 + (int)(BORDER*x_ratio)),
  393.           (int)(BORDER*y_ratio));
  394.     XCopyArea(dpy, w->dclock.tiny_digits[l_time->tm_sec%10], win, gc, 0, 0,
  395.           digit_w/2, digit_h/2,
  396.           winwidth - digit_w/2 - (int)(BORDER*x_ratio),
  397.           (int)(BORDER*y_ratio));
  398.     }
  399.  
  400.     XCopyArea(dpy, w->dclock.colon[(!w->dclock.seconds || l_time->tm_sec & 1)],
  401.         win, gc, 0, 0,
  402.         (int)(30*x_ratio), digit_h,
  403.         (int)(-digit_w*.75 + 2*BORDER*x_ratio) + 2*digit_w,
  404.         (int)(BORDER*y_ratio));
  405.  
  406.     if (w->dclock.date_fmt && before.tm_wday != l_time->tm_wday)
  407.     show_date(w, l_time);
  408.  
  409.     if (w->dclock.bell && (!w->dclock.seconds || l_time->tm_sec == 0) &&
  410.     (l_time->tm_min == 0 || l_time->tm_min == 30)) {
  411.     XBell(dpy, 50);
  412.     if (l_time->tm_min == 0)
  413.         XBell(dpy, 50);
  414.     }
  415.     before = *l_time;
  416. }
  417.  
  418. static void
  419. scroll_time(w, p)
  420. DclockWidget w;
  421. register char *p;
  422. {
  423.     int scroll_me[4], J = winheight - BORDER*2*y_ratio + 1;
  424.     register int i, j, incr;
  425.     int digit_w = w->dclock.digit_w;
  426.     int digit_h = w->dclock.digit_h;
  427.     Display *dpy = XtDisplay(w);
  428.     Window win = XtWindow(w);
  429.     GC gc = w->dclock.reverse? w->dclock.backGC : w->dclock.foreGC;
  430.     Pixmap tmp[4];
  431.  
  432.     if (w->dclock.date_fmt)
  433.     J -= w->dclock.font->ascent + w->dclock.font->descent;
  434.  
  435.     if ((incr = J / 30) < 1)
  436.     incr = 1;
  437.  
  438. #define x ((int)(-digit_w*.75 + ((i+1)*BORDER + (i>1)*30)*x_ratio) + i*digit_w)
  439. #define y (int)(BORDER * y_ratio)
  440.  
  441.     for (i = 0; i < 4; i++)    /* if pixrects don't match, scroll it */
  442.     scroll_me[i] = ((tmp[i] = w->dclock.digits[*p++ - '0']) != old_pix[i]);
  443.     if (w->dclock.scroll &&
  444.     (scroll_me[0] || scroll_me[1] || scroll_me[2] || scroll_me[3]))
  445.     for (j = 0; j <= J; j += incr)
  446.         for (i = 0; i < 4; i++)
  447.         if (scroll_me[i]) {
  448.             if (old_pix[i])
  449.             XCopyArea(dpy, old_pix[i], win, gc,
  450.                 0, j, digit_w, digit_h - j, x, y);
  451.             if (i || tmp[i] == w->dclock.digits[1])
  452.             XCopyArea(dpy, tmp[i], win, gc,
  453.                 0, 0, digit_w, j, x, y + digit_h - j);
  454.             else
  455.             XCopyArea(dpy, w->dclock.colon[0], win, gc,
  456.                 0, 0, x+5, y + digit_h - j, digit_w, j);
  457.         }
  458.  
  459.     for (i = 0; i < 4; i++)
  460.     if (i || tmp[0] == w->dclock.digits[1])
  461.         XCopyArea(dpy, tmp[i], win, gc, 0,0, digit_w, digit_h, x,y);
  462.     else
  463.         XCopyArea(dpy, w->dclock.colon[0], win, gc,
  464.         0,0, digit_w,digit_h, x+5,y);
  465. #undef x
  466. #undef y
  467.     for (i = 0; i < 4; i++)
  468.     old_pix[i] = tmp[i];
  469. }
  470.  
  471. static char *months[] = {
  472.     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
  473.     "Aug", "Sep", "Oct", "Nov", "Dec"
  474. };
  475. static char *Months[] = {
  476.     "January", "February", "March", "April", "May", "June", "July",
  477.     "August", "September", "October", "November", "December"
  478. };
  479. static char *days[] = {
  480.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
  481. };
  482. static char *Days[] = {
  483.     "Sunday", "Monday", "Tuesday", "Wednesday",
  484.     "Thursday", "Friday", "Saturday", "Sunday"
  485. };
  486.  
  487. static void
  488. show_date(w, now)
  489. DclockWidget w;
  490. struct tm *now;
  491. {
  492.     char datestr[128];
  493.     register char *datep = datestr, *p;
  494.     int x;
  495.  
  496.     if (!w->dclock.date_fmt)
  497.     return;
  498.  
  499. #if 0
  500.     if (set_alarm)
  501.     sprintf(datestr, "Alarm is %s.", alarm_time.tm_sec < 0? "off" : "on");
  502.     else
  503. #endif /* 0 */
  504.     {
  505.     for (p = w->dclock.date_fmt; *p; p++) {
  506.         if (*p != '%')
  507.         *datep++ = *p;
  508.         else switch (*++p) {
  509.         when 'M':
  510.             datep += strlen(strcpy(datep, Months[now->tm_mon]));
  511.         when 'm':
  512.             datep += strlen(strcpy(datep, months[now->tm_mon]));
  513.         when 'W':
  514.             datep += strlen(strcpy(datep, Days[now->tm_wday]));
  515.         when 'w':
  516.             datep += strlen(strcpy(datep, days[now->tm_wday]));
  517.         when 'd':
  518.             if (now->tm_mday >= 10)
  519.             *datep++ = (now->tm_mday / 10 + '0');
  520.             *datep++ = now->tm_mday % 10 + '0';
  521.         when 'Y':
  522.             *datep++ = '1', *datep++ = '9';
  523.             /* fall thru */
  524.         case 'y':
  525.             *datep++ = now->tm_year / 10 + '0';
  526.             *datep++ = now->tm_year % 10 + '0';
  527.         when '%':
  528.             *datep++ = *p;
  529.         otherwise: ; /* nothing */
  530.         }
  531.     }
  532.     *datep = 0;
  533.     }
  534.     x = (w->core.width - XTextWidth(w->dclock.font, datestr, datep-datestr))/2;
  535.     if (x < 2)
  536.     x = 2;
  537.  
  538.     /* remove what was there in case the whole thing isn't overwritten */
  539.     if (w->dclock.reverse)
  540.     XFillRectangle(XtDisplay(w), XtWindow(w), w->dclock.foreGC,
  541.        0, winheight - (w->dclock.font->ascent + w->dclock.font->descent),
  542.        winwidth, w->dclock.font->ascent + w->dclock.font->descent);
  543.     else
  544.     XClearArea(XtDisplay(w), XtWindow(w),
  545.        0, winheight - (w->dclock.font->ascent + w->dclock.font->descent),
  546.        winwidth, w->dclock.font->ascent + w->dclock.font->descent, False);
  547.  
  548.     XDrawString(XtDisplay(w), XtWindow(w),
  549.     w->dclock.reverse? w->dclock.backGC : w->dclock.foreGC,
  550.     x, winheight - BORDER, datestr, (int)(datep - datestr));
  551. }
  552.  
  553.  
  554. static void
  555. timeout(w, id)
  556. DclockWidget w;
  557. XtIntervalId *id;
  558. {
  559.     show_time(w);
  560.     w->dclock.interval_id =
  561.     XtAddTimeOut(w->dclock.seconds? 1000 : 60000, timeout, w);
  562. }
  563.  
  564. /* ARGSUSED */
  565. static Boolean
  566. SetValues (current, request, new)
  567. DclockWidget current, request, new;
  568. {
  569.     Boolean do_redraw = False;
  570.  
  571.     if (new->dclock.foreground != current->dclock.foreground
  572.     ||  new->core.background_pixel != current->core.background_pixel
  573.     ||  new->dclock.reverse != current->dclock.reverse) {
  574.     XtDestroyGC (current->dclock.foreGC);
  575.     XtDestroyGC (current->dclock.backGC);
  576.     GetGC(new);
  577.     Resize(new); /* pixmaps need to be redrawn */
  578.     do_redraw = True;
  579.     }
  580.     if (new->dclock.seconds != current->dclock.seconds) {
  581.     XtRemoveTimeOut(current->dclock.interval_id);
  582.     Resize(new);
  583.     do_redraw = True;
  584.     }
  585.     if (new->dclock.date_fmt != current->dclock.date_fmt) {
  586.     do_redraw = True;
  587.     before.tm_wday = -1;
  588.     }
  589.  
  590.     return do_redraw;
  591. }
  592.  
  593. static void
  594. toggle_bell(w)
  595. DclockWidget w;
  596. {
  597.     if (w->dclock.bell = !w->dclock.bell)
  598.     XBell(XtDisplay(w), 50);
  599. }
  600.  
  601. static void
  602. toggle_scroll(w)
  603. DclockWidget w;
  604. {
  605.     w->dclock.scroll = !w->dclock.scroll;
  606. }
  607.  
  608. static void
  609. toggle_reverse_video(w)
  610. DclockWidget w;
  611. {
  612.     Arg arg;
  613.  
  614.     XtSetArg(arg, XtNreverseVideo, !w->dclock.reverse);
  615.     XtSetValues(w, &arg, 1);
  616. }
  617.  
  618. static void
  619. toggle_seconds(w)
  620. DclockWidget w;
  621. {
  622.     Arg arg;
  623.  
  624.     XtSetArg(arg, XtNseconds, !w->dclock.seconds);
  625.     XtSetValues(w, &arg, 1);
  626. }
  627.  
  628. static void
  629. show_dialog_box(w)
  630. Widget w;
  631. {
  632.     XBell(XtDisplay(w), 50);
  633. }
  634.