rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / x11 / libXaw4 / src / Xaw3_1Mailbox.c
blob462f94bb88e23d0693d6ffa266500d59d2085385
1 /*
2 * $XConsortium: Mailbox.c,v 1.35 89/10/09 16:51:44 jim Exp $
4 * Copyright 1988 Massachusetts Institute of Technology
6 * Permission to use, copy, modify, and distribute this software and its
7 * documentation for any purpose and without fee is hereby granted, provided
8 * that the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of M.I.T. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. M.I.T. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * Author: Jim Fulton, MIT X Consortium
18 * I recommend that you use the new mailfull and mailempty bitmaps instead of
19 * the ugly mailboxes:
21 * XBiff*fullPixmap: mailfull
22 * XBiff*emptyPixmap: mailempty
25 #include <stdio.h> /* for printing error messages */
26 #include <pwd.h> /* for getting username */
28 #include <X11/cursorfont.h> /* for cursor constants */
29 #include <X11/StringDefs.h> /* for useful atom names */
30 #include <X11/Intrinsic.h> /* for XtTimerCallbackProc */
31 #include <X11/IntrinsicP.h> /* for toolkit stuff */
32 #include <sys/stat.h> /* for stat() ** needs types.h ***/
34 #include <X11/bitmaps/mailfull> /* for flag up (mail present) bits */
35 #include <X11/bitmaps/mailempty> /* for flag down (mail not here) */
37 #include <./Xaw3_1XawInit.h>
38 #include <./Xaw3_1MailboxP.h> /* for implementation mailbox stuff */
40 #include <X11/Xmu/Converters.h> /* for XmuCvtStringToBitmap */
42 #ifdef SHAPE
43 #include <X11/extensions/shape.h>
44 #endif
47 * The default user interface is to have the mailbox turn itself off whenever
48 * the user presses a button in it. Expert users might want to make this
49 * happen on EnterWindow. It might be nice to provide support for some sort of
50 * exit callback so that you can do things like press q to quit.
53 static char defaultTranslations[] =
54 "<ButtonPress>: unset()";
56 static void Check(), Set(), Unset();
58 static XtActionsRec actionsList[] = {
59 { "check", Check },
60 { "unset", Unset },
61 { "set", Set },
65 /* Initialization of defaults */
67 #define offset(field) XtOffset(MailboxWidget,mailbox.field)
68 #define goffset(field) XtOffset(Widget,core.field)
70 static Dimension defDim = 48;
71 static Pixmap nopix = None;
73 static XtResource resources[] = {
74 { XtNwidth, XtCWidth, XtRDimension, sizeof (Dimension),
75 goffset (width), XtRDimension, (caddr_t)&defDim },
76 { XtNheight, XtCHeight, XtRDimension, sizeof (Dimension),
77 goffset (height), XtRDimension, (caddr_t)&defDim },
78 { XtNupdate, XtCInterval, XtRInt, sizeof (int),
79 offset (update), XtRString, "30" },
80 { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
81 offset (foreground_pixel), XtRString, "black" },
82 { XtNbackground, XtCBackground, XtRPixel, sizeof (Pixel),
83 goffset (background_pixel), XtRString, "white" },
84 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
85 offset (reverseVideo), XtRString, "FALSE" },
86 { XtNfile, XtCFile, XtRString, sizeof (String),
87 offset (filename), XtRString, NULL },
88 { XtNcheckCommand, XtCCheckCommand, XtRString, sizeof(char*),
89 offset (check_command), XtRString, NULL},
90 { XtNvolume, XtCVolume, XtRInt, sizeof(int),
91 offset (volume), XtRString, "33"},
92 { XtNonceOnly, XtCBoolean, XtRBoolean, sizeof(Boolean),
93 offset (once_only), XtRImmediate, (caddr_t)False },
94 { XtNfullPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
95 offset (full.bitmap), XtRString, "flagup" },
96 { XtNfullPixmapMask, XtCPixmapMask, XtRBitmap, sizeof(Pixmap),
97 offset (full.mask), XtRBitmap, (caddr_t) &nopix },
98 { XtNemptyPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
99 offset (empty.bitmap), XtRString, "flagdown" },
100 { XtNemptyPixmapMask, XtCPixmapMask, XtRBitmap, sizeof(Pixmap),
101 offset (empty.mask), XtRBitmap, (caddr_t) &nopix },
102 { XtNflip, XtCFlip, XtRBoolean, sizeof(Boolean),
103 offset (flipit), XtRString, "true" },
104 #ifdef SHAPE
105 { XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof(Boolean),
106 offset (shapeit), XtRString, "false" },
107 #endif
110 #undef offset
111 #undef goffset
113 static void GetMailFile(), CloseDown();
114 static void check_mailbox(), redraw_mailbox(), beep();
115 static void ClassInitialize(), Initialize(), Realize(), Destroy(), Redisplay();
116 static Boolean SetValues();
118 MailboxClassRec mailboxClassRec = {
119 { /* core fields */
120 /* superclass */ &widgetClassRec,
121 /* class_name */ "Mailbox",
122 /* widget_size */ sizeof(MailboxRec),
123 /* class_initialize */ ClassInitialize,
124 /* class_part_initialize */ NULL,
125 /* class_inited */ FALSE,
126 /* initialize */ Initialize,
127 /* initialize_hook */ NULL,
128 /* realize */ Realize,
129 /* actions */ actionsList,
130 /* num_actions */ XtNumber(actionsList),
131 /* resources */ resources,
132 /* resource_count */ XtNumber(resources),
133 /* xrm_class */ NULL,
134 /* compress_motion */ TRUE,
135 /* compress_exposure */ TRUE,
136 /* compress_enterleave */ TRUE,
137 /* visible_interest */ FALSE,
138 /* destroy */ Destroy,
139 /* resize */ NULL,
140 /* expose */ Redisplay,
141 /* set_values */ SetValues,
142 /* set_values_hook */ NULL,
143 /* set_values_almost */ XtInheritSetValuesAlmost,
144 /* get_values_hook */ NULL,
145 /* accept_focus */ NULL,
146 /* version */ XtVersion,
147 /* callback_private */ NULL,
148 /* tm_table */ defaultTranslations,
149 /* query_geometry */ XtInheritQueryGeometry,
150 /* display_accelerator */ XtInheritDisplayAccelerator,
151 /* extension */ NULL
155 WidgetClass mailboxWidgetClass = (WidgetClass) &mailboxClassRec;
159 * widget initialization
162 static void ClassInitialize ()
164 static XtConvertArgRec screenConvertArg[] = {
165 { XtWidgetBaseOffset, (caddr_t) XtOffset(Widget, core.screen), sizeof(Screen *) }
168 XawInitializeWidgetSet();
169 XtAddConverter (XtRString, XtRBitmap, XmuCvtStringToBitmap,
170 screenConvertArg, XtNumber(screenConvertArg));
171 return;
174 static GC get_mailbox_gc (w)
175 MailboxWidget w;
177 XtGCMask valuemask;
178 XGCValues xgcv;
180 valuemask = GCForeground | GCBackground | GCFunction | GCGraphicsExposures;
181 xgcv.foreground = w->mailbox.foreground_pixel;
182 xgcv.background = w->core.background_pixel;
183 xgcv.function = GXcopy;
184 xgcv.graphics_exposures = False; /* this is Bool, not Boolean */
185 return (XtGetGC ((Widget) w, valuemask, &xgcv));
189 /* ARGSUSED */
190 static void Initialize (request, new)
191 Widget request, new;
193 MailboxWidget w = (MailboxWidget) new;
194 #ifdef SHAPE
195 int shape_event_base, shape_error_base;
196 #endif
198 if (!w->mailbox.filename) GetMailFile (w);
200 if (w->core.width <= 0) w->core.width = 1;
201 if (w->core.height <= 0) w->core.height = 1;
203 if (w->mailbox.reverseVideo) {
204 Pixel tmp;
206 tmp = w->mailbox.foreground_pixel;
207 w->mailbox.foreground_pixel = w->core.background_pixel;
208 w->core.background_pixel = tmp;
211 #ifdef SHAPE
212 if (w->mailbox.shapeit && !XShapeQueryExtension (XtDisplay (w),
213 &shape_event_base,
214 &shape_error_base))
215 w->mailbox.shapeit = False;
216 w->mailbox.shape_cache.mask = None;
217 #endif
219 w->mailbox.gc = get_mailbox_gc (w);
220 w->mailbox.interval_id = (XtIntervalId) 0;
221 w->mailbox.full.pixmap = None;
222 w->mailbox.empty.pixmap = None;
224 return;
229 * action procedures
233 * pretend there is new mail; put widget in flagup state
236 /* ARGSUSED */
237 static void Set (gw, event, params, nparams)
238 Widget gw;
239 XEvent *event;
240 String *params;
241 Cardinal *nparams;
243 MailboxWidget w = (MailboxWidget) gw;
245 w->mailbox.last_size = -1;
247 check_mailbox (w, TRUE, FALSE); /* redraw, no reset */
249 return;
254 * ack the existing mail; put widget in flagdown state
257 /* ARGSUSED */
258 static void Unset (gw, event, params, nparams)
259 Widget gw;
260 XEvent *event;
261 String *params;
262 Cardinal *nparams;
264 MailboxWidget w = (MailboxWidget) gw;
266 check_mailbox (w, TRUE, TRUE); /* redraw, reset */
268 return;
273 * look to see if there is new mail; if so, Set, else Unset
276 /* ARGSUSED */
277 static void Check (gw, event, params, nparams)
278 Widget gw;
279 XEvent *event;
280 String *params;
281 Cardinal *nparams;
283 MailboxWidget w = (MailboxWidget) gw;
285 check_mailbox (w, TRUE, FALSE); /* redraw, no reset */
287 return;
291 /* ARGSUSED */
292 static XtTimerCallbackProc clock_tic (client_data, id)
293 caddr_t client_data;
294 XtIntervalId *id;
296 MailboxWidget w = (MailboxWidget) client_data;
298 check_mailbox (w, FALSE, FALSE); /* no redraw, no reset */
301 * and reset the timer
304 w->mailbox.interval_id = XtAddTimeOut (w->mailbox.update * 1000,
305 (XtTimerCallbackProc)clock_tic,
306 (caddr_t) w);
308 return;
311 static Pixmap make_pixmap (dpy, w, bitmap, depth, flip, widthp, heightp)
312 Display *dpy;
313 MailboxWidget w;
314 Pixmap bitmap;
315 Boolean flip;
316 int depth;
317 int *widthp, *heightp;
319 Window root;
320 int x, y;
321 unsigned int width, height, bw, dep;
322 unsigned long fore, back;
324 if (!XGetGeometry (dpy, bitmap, &root, &x, &y, &width, &height, &bw, &dep))
325 return None;
327 *widthp = (int) width;
328 *heightp = (int) height;
329 if (flip) {
330 fore = w->core.background_pixel;
331 back = w->mailbox.foreground_pixel;
332 } else {
333 fore = w->mailbox.foreground_pixel;
334 back = w->core.background_pixel;
336 return XmuCreatePixmapFromBitmap (dpy, w->core.window, bitmap,
337 width, height, depth, fore, back);
340 static void Realize (gw, valuemaskp, attr)
341 Widget gw;
342 XtValueMask *valuemaskp;
343 XSetWindowAttributes *attr;
345 MailboxWidget w = (MailboxWidget) gw;
346 register Display *dpy = XtDisplay (w);
347 int depth = w->core.depth;
349 *valuemaskp |= (CWBitGravity | CWCursor);
350 attr->bit_gravity = ForgetGravity;
351 attr->cursor = XCreateFontCursor (dpy, XC_top_left_arrow);
353 XtCreateWindow (gw, InputOutput, (Visual *) CopyFromParent,
354 *valuemaskp, attr);
357 * build up the pixmaps that we'll put into the image
359 if (w->mailbox.full.bitmap == None) {
360 w->mailbox.full.bitmap =
361 XCreateBitmapFromData (dpy, w->core.window,
362 (const char *)mailfull_bits,
363 mailfull_width, mailfull_height);
365 if (w->mailbox.empty.bitmap == None) {
366 w->mailbox.empty.bitmap =
367 XCreateBitmapFromData (dpy, w->core.window,
368 (const char *)mailempty_bits,
369 mailempty_width, mailempty_height);
372 w->mailbox.empty.pixmap = make_pixmap (dpy, w, w->mailbox.empty.bitmap,
373 depth, False,
374 &w->mailbox.empty.width,
375 &w->mailbox.empty.height);
376 w->mailbox.full.pixmap = make_pixmap (dpy, w, w->mailbox.full.bitmap,
377 depth, w->mailbox.flipit,
378 &w->mailbox.full.width,
379 &w->mailbox.full.height);
381 #ifdef SHAPE
382 if (w->mailbox.empty.mask == None && w->mailbox.full.mask == None)
383 w->mailbox.shapeit = False;
384 #endif
386 w->mailbox.interval_id = XtAddTimeOut (w->mailbox.update * 1000,
387 (XtTimerCallbackProc)clock_tic,
388 (caddr_t) w);
390 #ifdef SHAPE
391 w->mailbox.shape_cache.mask = None;
392 #endif
394 return;
398 static void Destroy (gw)
399 Widget gw;
401 MailboxWidget w = (MailboxWidget) gw;
402 Display *dpy = XtDisplay (gw);
404 XtFree (w->mailbox.filename);
405 if (w->mailbox.interval_id) XtRemoveTimeOut (w->mailbox.interval_id);
406 XtDestroyGC (w->mailbox.gc);
407 #define freepix(p) if (p) XFreePixmap (dpy, p)
408 freepix (w->mailbox.full.bitmap); /* until cvter does ref cnt */
409 freepix (w->mailbox.full.mask); /* until cvter does ref cnt */
410 freepix (w->mailbox.full.pixmap);
411 freepix (w->mailbox.empty.bitmap); /* until cvter does ref cnt */
412 freepix (w->mailbox.empty.mask); /* until cvter does ref cnt */
413 freepix (w->mailbox.empty.pixmap);
414 #ifdef SHAPE
415 freepix (w->mailbox.shape_cache.mask);
416 #endif
417 #undef freepix
418 return;
422 static void Redisplay (gw)
423 Widget gw;
425 MailboxWidget w = (MailboxWidget) gw;
427 check_mailbox (w, TRUE, FALSE);
431 static void check_mailbox (w, force_redraw, reset)
432 MailboxWidget w;
433 Boolean force_redraw, reset;
435 long mailboxsize = 0;
437 if (w->mailbox.check_command != NULL) {
438 switch (system(w->mailbox.check_command)) {
439 case 0:
440 mailboxsize = w->mailbox.last_size + 1;
441 break;
442 /* case 1 is no change */
443 case 2:
444 mailboxsize = 0;
445 /* treat everything else as no change */
448 else {
449 struct stat st;
451 if (stat (w->mailbox.filename, &st) == 0) {
452 mailboxsize = st.st_size;
457 * Now check for changes. If reset is set then we want to pretent that
458 * there is no mail. If the mailbox is empty then we want to turn off
459 * the flag. Otherwise if the mailbox has changed size then we want to
460 * put the flag up.
462 * The cases are:
463 * o forced reset by user DOWN
464 * o no mailbox or empty (zero-sized) mailbox DOWN
465 * o same size as last time no change
466 * o bigger than last time UP
467 * o smaller than last time but non-zero UP
469 * The last two cases can be expressed as different from last
470 * time and non-zero.
473 if (reset) { /* forced reset */
474 w->mailbox.flag_up = FALSE;
475 force_redraw = TRUE;
476 } else if (mailboxsize == 0) { /* no mailbox or empty */
477 w->mailbox.flag_up = FALSE;
478 if (w->mailbox.last_size > 0) force_redraw = TRUE; /* if change */
479 } else if (mailboxsize != w->mailbox.last_size) { /* different size */
480 if (!w->mailbox.once_only || !w->mailbox.flag_up)
481 beep(w);
482 w->mailbox.flag_up = TRUE;
483 force_redraw = TRUE;
486 w->mailbox.last_size = mailboxsize;
487 if (force_redraw) redraw_mailbox (w);
488 return;
492 * get user name for building mailbox
495 static void GetMailFile (w)
496 MailboxWidget w;
498 char *getlogin();
499 char *username;
501 username = getlogin ();
502 if (!username) {
503 struct passwd *pw = getpwuid (getuid ());
505 if (!pw) {
506 fprintf (stderr, "%s: unable to find a username for you.\n",
507 "Mailbox widget");
508 CloseDown (w, 1);
510 username = pw->pw_name;
512 w->mailbox.filename = (String) XtMalloc (strlen (MAILBOX_DIRECTORY) + 1 +
513 strlen (username) + 1);
514 strcpy (w->mailbox.filename, MAILBOX_DIRECTORY);
515 strcat (w->mailbox.filename, "/");
516 strcat (w->mailbox.filename, username);
517 return;
520 static void CloseDown (w, status)
521 MailboxWidget w;
522 int status;
524 Display *dpy = XtDisplay (w);
526 XtDestroyWidget ((Widget)w);
527 XCloseDisplay (dpy);
528 exit (status);
532 /* ARGSUSED */
533 static Boolean SetValues (gcurrent, grequest, gnew)
534 Widget gcurrent, grequest, gnew;
536 MailboxWidget current = (MailboxWidget) gcurrent;
537 MailboxWidget new = (MailboxWidget) gnew;
538 Boolean redisplay = FALSE;
540 if (current->mailbox.update != new->mailbox.update) {
541 if (current->mailbox.interval_id)
542 XtRemoveTimeOut (current->mailbox.interval_id);
543 new->mailbox.interval_id = XtAddTimeOut (new->mailbox.update * 1000,
544 (XtTimerCallbackProc)clock_tic,
545 (caddr_t) gnew);
548 if (current->mailbox.foreground_pixel != new->mailbox.foreground_pixel ||
549 current->core.background_pixel != new->core.background_pixel) {
550 XtDestroyGC (current->mailbox.gc);
551 new->mailbox.gc = get_mailbox_gc (new);
552 redisplay = TRUE;
555 return (redisplay);
560 * drawing code
563 static void redraw_mailbox (w)
564 MailboxWidget w;
566 register Display *dpy = XtDisplay (w);
567 register Window win = XtWindow (w);
568 register int x, y;
569 GC gc = w->mailbox.gc;
570 Pixel back = w->core.background_pixel;
571 struct _mbimage *im;
573 /* center the picture in the window */
575 if (w->mailbox.flag_up) { /* paint the "up" position */
576 im = &w->mailbox.full;
577 if (w->mailbox.flipit) back = w->mailbox.foreground_pixel;
578 } else { /* paint the "down" position */
579 im = &w->mailbox.empty;
581 x = (((int)w->core.width) - im->width) / 2;
582 y = (((int)w->core.height) - im->height) / 2;
584 XSetWindowBackground (dpy, win, back);
585 XClearWindow (dpy, win);
586 XCopyArea (dpy, im->pixmap, win, gc, 0, 0, im->width, im->height, x, y);
588 #ifdef SHAPE
590 * XXX - temporary hack; walk up widget tree to find top most parent (which
591 * will be a shell) and mash it to have our shape. This will be replaced
592 * by a special shell widget.
594 if (w->mailbox.shapeit) {
595 Widget parent;
597 for (parent = (Widget) w; XtParent(parent);
598 parent = XtParent(parent)) {
599 x += parent->core.x + parent->core.border_width;
600 y += parent->core.y + parent->core.border_width;
603 if (im->mask != w->mailbox.shape_cache.mask ||
604 x != w->mailbox.shape_cache.x || y != w->mailbox.shape_cache.y) {
605 XShapeCombineMask (XtDisplay(parent), XtWindow(parent),
606 ShapeBounding, x, y, im->mask, ShapeSet);
607 w->mailbox.shape_cache.mask = im->mask;
608 w->mailbox.shape_cache.x = x;
609 w->mailbox.shape_cache.y = y;
612 #endif
614 return;
618 static void beep (w)
619 MailboxWidget w;
621 XBell (XtDisplay (w), w->mailbox.volume);
622 return;