1c19de146Smrg/* $XConsortium: Mailbox.c,v 1.64 94/04/17 20:43:26 rws Exp $ */ 2c19de146Smrg/* 3c19de146Smrg 4c19de146SmrgCopyright (c) 1988 X Consortium 5c19de146Smrg 6c19de146SmrgPermission is hereby granted, free of charge, to any person obtaining 7c19de146Smrga copy of this software and associated documentation files (the 8c19de146Smrg"Software"), to deal in the Software without restriction, including 9c19de146Smrgwithout limitation the rights to use, copy, modify, merge, publish, 10c19de146Smrgdistribute, sublicense, and/or sell copies of the Software, and to 11c19de146Smrgpermit persons to whom the Software is furnished to do so, subject to 12c19de146Smrgthe following conditions: 13c19de146Smrg 14c19de146SmrgThe above copyright notice and this permission notice shall be included 15c19de146Smrgin all copies or substantial portions of the Software. 16c19de146Smrg 17c19de146SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18c19de146SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19c19de146SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20c19de146SmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 21c19de146SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22c19de146SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23c19de146SmrgOTHER DEALINGS IN THE SOFTWARE. 24c19de146Smrg 25c19de146SmrgExcept as contained in this notice, the name of the X Consortium shall 26c19de146Smrgnot be used in advertising or otherwise to promote the sale, use or 27c19de146Smrgother dealings in this Software without prior written authorization 28c19de146Smrgfrom the X Consortium. 29c19de146Smrg 30c19de146Smrg*/ 31c19de146Smrg/* $XFree86: xc/programs/xbiff/Mailbox.c,v 1.4 2001/08/01 00:45:02 tsi Exp $ */ 32c19de146Smrg 33c19de146Smrg/* 34c19de146Smrg * Author: Jim Fulton, MIT X Consortium 35c19de146Smrg * 36c19de146Smrg * I recommend that you use the new mailfull and mailempty bitmaps instead of 37c19de146Smrg * the ugly mailboxes: 38c19de146Smrg * 39c19de146Smrg * XBiff*fullPixmap: mailfull 40c19de146Smrg * XBiff*emptyPixmap: mailempty 41c19de146Smrg */ 42c19de146Smrg 433b83913fSmrg#ifdef HAVE_CONFIG_H 443b83913fSmrg#include "config.h" 453b83913fSmrg#endif 463b83913fSmrg 47c19de146Smrg#include <X11/IntrinsicP.h> /* for toolkit stuff */ 48c19de146Smrg#include <X11/StringDefs.h> /* for useful atom names */ 49c19de146Smrg#include <X11/cursorfont.h> /* for cursor constants */ 50c19de146Smrg#include <X11/Xosdefs.h> /* for X_NOT_POSIX def */ 51c19de146Smrg#include <stdlib.h> 52c19de146Smrg#ifdef WIN32 53c19de146Smrg#include <X11/Xw32defs.h> 54c19de146Smrg#else 55c19de146Smrg#include <pwd.h> /* for getting username */ 56c19de146Smrg#endif 57c19de146Smrg#include <sys/stat.h> /* for stat() ** needs types.h ***/ 58c19de146Smrg#include <stdio.h> /* for printing error messages */ 59c19de146Smrg#include <unistd.h> 60c19de146Smrg 61c19de146Smrg#ifndef X_NOT_POSIX 62c19de146Smrg#ifdef _POSIX_SOURCE 63c19de146Smrg# include <sys/wait.h> 64c19de146Smrg#else 65c19de146Smrg#define _POSIX_SOURCE 66c19de146Smrg# include <sys/wait.h> 67c19de146Smrg#undef _POSIX_SOURCE 68c19de146Smrg#endif 69c19de146Smrg# define waitCode(w) WEXITSTATUS(w) 70c19de146Smrg# define waitSig(w) WIFSIGNALED(w) 71c19de146Smrgtypedef int waitType; 72c19de146Smrg# define INTWAITTYPE 73c19de146Smrg#else /* ! X_NOT_POSIX */ 74c19de146Smrg#ifdef SYSV 75c19de146Smrg# define waitCode(w) (((w) >> 8) & 0x7f) 76c19de146Smrg# define waitSig(w) ((w) & 0xff) 77c19de146Smrgtypedef int waitType; 78c19de146Smrg# define INTWAITTYPE 79c19de146Smrg#else 80c19de146Smrg#ifdef WIN32 81c19de146Smrg#include <process.h> 82c19de146Smrg# define INTWAITTYPE 83c19de146Smrgtypedef int waitType; 84c19de146Smrg# define waitCode(w) (w) 85c19de146Smrg# define waitSig(w) (0) 86c19de146Smrg#else 87c19de146Smrg# include <sys/wait.h> 88c19de146Smrg# define waitCode(w) ((w).w_T.w_Retcode) 89c19de146Smrg# define waitSig(w) ((w).w_T.w_Termsig) 90c19de146Smrgtypedef union wait waitType; 91c19de146Smrg#endif /* WIN32 else */ 92c19de146Smrg#endif /* SYSV else */ 93c19de146Smrg#endif /* ! X_NOT_POSIX else */ 94c19de146Smrg 95c19de146Smrg#include <X11/bitmaps/mailfull> /* for flag up (mail present) bits */ 96c19de146Smrg#include <X11/bitmaps/mailempty> /* for flag down (mail not here) */ 97c19de146Smrg 98c19de146Smrg#include <X11/Xaw/XawInit.h> 99c19de146Smrg#include "MailboxP.h" /* for implementation mailbox stuff */ 100c19de146Smrg#include <X11/Xmu/Drawing.h> 101c19de146Smrg#include <X11/extensions/shape.h> 102c19de146Smrg 103c19de146Smrg/* 104c19de146Smrg * The default user interface is to have the mailbox turn itself off whenever 105c19de146Smrg * the user presses a button in it. Expert users might want to make this 106c19de146Smrg * happen on EnterWindow. It might be nice to provide support for some sort of 107c19de146Smrg * exit callback so that you can do things like press q to quit. 108c19de146Smrg */ 109c19de146Smrg 110c19de146Smrgstatic char defaultTranslations[] = 111c19de146Smrg "<ButtonPress>: unset()"; 112c19de146Smrg 1139ef7378bSmrgstatic void Set (Widget gw, XEvent *event, String *params, Cardinal *nparams); 1149ef7378bSmrgstatic void Check(Widget gw, XEvent *event, String *params, Cardinal *nparams); 1159ef7378bSmrgstatic void Unset(Widget gw, XEvent *event, String *params, Cardinal *nparams); 116c19de146Smrg 117c19de146Smrgstatic XtActionsRec actionsList[] = { 118c19de146Smrg { "check", Check }, 119c19de146Smrg { "unset", Unset }, 120c19de146Smrg { "set", Set }, 121c19de146Smrg}; 122c19de146Smrg 123c19de146Smrg 124c19de146Smrg/* Initialization of defaults */ 125c19de146Smrg 126c19de146Smrg#define offset(field) XtOffsetOf(MailboxRec, mailbox.field) 127c19de146Smrg#define goffset(field) XtOffsetOf(WidgetRec, core.field) 128c19de146Smrg 129c19de146Smrgstatic Dimension defDim = 48; 130c19de146Smrgstatic Pixmap nopix = None; 131c19de146Smrg 132c19de146Smrgstatic XtResource resources[] = { 133c19de146Smrg { XtNwidth, XtCWidth, XtRDimension, sizeof (Dimension), 134c19de146Smrg goffset (width), XtRDimension, (XtPointer)&defDim }, 135c19de146Smrg { XtNheight, XtCHeight, XtRDimension, sizeof (Dimension), 136c19de146Smrg goffset (height), XtRDimension, (XtPointer)&defDim }, 137c19de146Smrg { XtNupdate, XtCInterval, XtRInt, sizeof (int), 138c19de146Smrg offset (update), XtRString, "30" }, 139c19de146Smrg { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), 140c19de146Smrg offset (foreground_pixel), XtRString, XtDefaultForeground }, 141c19de146Smrg { XtNfile, XtCFile, XtRString, sizeof (String), 142c19de146Smrg offset (filename), XtRString, NULL }, 143c19de146Smrg { XtNcheckCommand, XtCCheckCommand, XtRString, sizeof(char*), 144c19de146Smrg offset (check_command), XtRString, NULL}, 145c19de146Smrg { XtNvolume, XtCVolume, XtRInt, sizeof(int), 146c19de146Smrg offset (volume), XtRString, "33"}, 147c19de146Smrg { XtNonceOnly, XtCBoolean, XtRBoolean, sizeof(Boolean), 148c19de146Smrg offset (once_only), XtRImmediate, (XtPointer)False }, 149c19de146Smrg { XtNfullPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap), 150c19de146Smrg offset (full.bitmap), XtRString, "flagup" }, 151c19de146Smrg { XtNfullPixmapMask, XtCPixmapMask, XtRBitmap, sizeof(Pixmap), 152c19de146Smrg offset (full.mask), XtRBitmap, (XtPointer) &nopix }, 153c19de146Smrg { XtNemptyPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap), 154c19de146Smrg offset (empty.bitmap), XtRString, "flagdown" }, 155c19de146Smrg { XtNemptyPixmapMask, XtCPixmapMask, XtRBitmap, sizeof(Pixmap), 156c19de146Smrg offset (empty.mask), XtRBitmap, (XtPointer) &nopix }, 157c19de146Smrg { XtNflip, XtCFlip, XtRBoolean, sizeof(Boolean), 158c19de146Smrg offset (flipit), XtRString, "true" }, 159c19de146Smrg { XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof(Boolean), 160c19de146Smrg offset (shapeit), XtRString, "false" }, 161c19de146Smrg}; 162c19de146Smrg 163c19de146Smrg#undef offset 164c19de146Smrg#undef goffset 165c19de146Smrg 1669ef7378bSmrgstatic void GetMailFile(MailboxWidget w); 1679ef7378bSmrgstatic void CloseDown (MailboxWidget w, int status); 1689ef7378bSmrg 1699ef7378bSmrgstatic void check_mailbox(MailboxWidget w, Boolean force_redraw, Boolean reset); 1709ef7378bSmrgstatic void redraw_mailbox (MailboxWidget w); 1719ef7378bSmrgstatic void beep (MailboxWidget w); 1729ef7378bSmrgstatic void Initialize (Widget request, Widget new, 1739ef7378bSmrg ArgList args, Cardinal *num_args); 1749ef7378bSmrgstatic void Realize (Widget gw, XtValueMask *valuemaskp, 1759ef7378bSmrg XSetWindowAttributes *attr); 1769ef7378bSmrgstatic void Destroy (Widget gw); 1779ef7378bSmrgstatic void Redisplay (Widget gw, XEvent *event, Region region); 1789ef7378bSmrgstatic Boolean SetValues (Widget gcurrent, Widget grequest, Widget gnew, 1799ef7378bSmrg ArgList args, Cardinal *num_args); 180c19de146Smrg 181c19de146SmrgMailboxClassRec mailboxClassRec = { 182c19de146Smrg { /* core fields */ 183c19de146Smrg /* superclass */ (WidgetClass) &simpleClassRec, 184c19de146Smrg /* class_name */ "Mailbox", 185c19de146Smrg /* widget_size */ sizeof(MailboxRec), 186c19de146Smrg /* class_initialize */ XawInitializeWidgetSet, 187c19de146Smrg /* class_part_initialize */ NULL, 188c19de146Smrg /* class_inited */ FALSE, 189c19de146Smrg /* initialize */ Initialize, 190c19de146Smrg /* initialize_hook */ NULL, 191c19de146Smrg /* realize */ Realize, 192c19de146Smrg /* actions */ actionsList, 193c19de146Smrg /* num_actions */ XtNumber(actionsList), 194c19de146Smrg /* resources */ resources, 195c19de146Smrg /* resource_count */ XtNumber(resources), 196c19de146Smrg /* xrm_class */ NULLQUARK, 197c19de146Smrg /* compress_motion */ TRUE, 198c19de146Smrg /* compress_exposure */ TRUE, 199c19de146Smrg /* compress_enterleave */ TRUE, 200c19de146Smrg /* visible_interest */ FALSE, 201c19de146Smrg /* destroy */ Destroy, 202c19de146Smrg /* resize */ NULL, 203c19de146Smrg /* expose */ Redisplay, 204c19de146Smrg /* set_values */ SetValues, 205c19de146Smrg /* set_values_hook */ NULL, 206c19de146Smrg /* set_values_almost */ XtInheritSetValuesAlmost, 207c19de146Smrg /* get_values_hook */ NULL, 208c19de146Smrg /* accept_focus */ NULL, 209c19de146Smrg /* version */ XtVersion, 210c19de146Smrg /* callback_private */ NULL, 211c19de146Smrg /* tm_table */ defaultTranslations, 212c19de146Smrg /* query_geometry */ XtInheritQueryGeometry, 213c19de146Smrg /* display_accelerator */ XtInheritDisplayAccelerator, 214c19de146Smrg /* extension */ NULL 215c19de146Smrg }, 216c19de146Smrg { /* simple fields */ 217c19de146Smrg /* change_sensitive */ XtInheritChangeSensitive 218c19de146Smrg }, 219c19de146Smrg { /* mailbox fields */ 220c19de146Smrg /* ignore */ 0 221c19de146Smrg } 222c19de146Smrg}; 223c19de146Smrg 224c19de146SmrgWidgetClass mailboxWidgetClass = (WidgetClass) &mailboxClassRec; 225c19de146Smrg 226c19de146Smrg 227c19de146Smrg/* 228c19de146Smrg * widget initialization 229c19de146Smrg */ 230c19de146Smrg 2319ef7378bSmrgstatic GC get_mailbox_gc (MailboxWidget w) 232c19de146Smrg{ 2333b83913fSmrg XtGCMask valuemask 2343b83913fSmrg = GCForeground | GCBackground | GCFunction | GCGraphicsExposures; 2353b83913fSmrg XGCValues xgcv = { 2363b83913fSmrg .foreground = w->mailbox.foreground_pixel, 2373b83913fSmrg .background = w->core.background_pixel, 2383b83913fSmrg .function = GXcopy, 2393b83913fSmrg .graphics_exposures = False /* this is Bool, not Boolean */ 2403b83913fSmrg }; 241c19de146Smrg return (XtGetGC ((Widget) w, valuemask, &xgcv)); 242c19de146Smrg} 243c19de146Smrg 244c19de146Smrg 245c19de146Smrg/* ARGSUSED */ 2469ef7378bSmrgstatic void Initialize (Widget request, Widget new, 2479ef7378bSmrg ArgList args, Cardinal *num_args) 248c19de146Smrg{ 249c19de146Smrg MailboxWidget w = (MailboxWidget) new; 250c19de146Smrg int shape_event_base, shape_error_base; 251c19de146Smrg 252c19de146Smrg if (w->core.width <= 0) w->core.width = 1; 253c19de146Smrg if (w->core.height <= 0) w->core.height = 1; 254c19de146Smrg 255c19de146Smrg if (w->mailbox.shapeit && !XShapeQueryExtension (XtDisplay (w), 256c19de146Smrg &shape_event_base, 257c19de146Smrg &shape_error_base)) 258c19de146Smrg w->mailbox.shapeit = False; 259c19de146Smrg w->mailbox.shape_cache.mask = None; 260c19de146Smrg w->mailbox.gc = get_mailbox_gc (w); 261c19de146Smrg w->mailbox.interval_id = (XtIntervalId) 0; 262c19de146Smrg w->mailbox.full.pixmap = None; 263c19de146Smrg w->mailbox.empty.pixmap = None; 264c19de146Smrg w->mailbox.flag_up = FALSE; 265c19de146Smrg w->mailbox.last_size = 0; 266c19de146Smrg if (!w->mailbox.filename) GetMailFile (w); 267c19de146Smrg return; 268c19de146Smrg} 269c19de146Smrg 270c19de146Smrg 271c19de146Smrg/* 272c19de146Smrg * action procedures 273c19de146Smrg */ 274c19de146Smrg 275c19de146Smrg/* 276c19de146Smrg * pretend there is new mail; put widget in flagup state 277c19de146Smrg */ 278c19de146Smrg 279c19de146Smrg/* ARGSUSED */ 2809ef7378bSmrgstatic void Set (Widget gw, XEvent *event, String *params, Cardinal *nparams) 281c19de146Smrg{ 282c19de146Smrg MailboxWidget w = (MailboxWidget) gw; 283c19de146Smrg 284c19de146Smrg w->mailbox.last_size = -1; 285c19de146Smrg 286c19de146Smrg check_mailbox (w, TRUE, FALSE); /* redraw, no reset */ 287c19de146Smrg} 288c19de146Smrg 289c19de146Smrg 290c19de146Smrg/* 291c19de146Smrg * ack the existing mail; put widget in flagdown state 292c19de146Smrg */ 293c19de146Smrg 294c19de146Smrg/* ARGSUSED */ 2959ef7378bSmrgstatic void Unset (Widget gw, XEvent *event, String *params, Cardinal *nparams) 296c19de146Smrg{ 297c19de146Smrg MailboxWidget w = (MailboxWidget) gw; 298c19de146Smrg 299c19de146Smrg check_mailbox (w, TRUE, TRUE); /* redraw, reset */ 300c19de146Smrg} 301c19de146Smrg 302c19de146Smrg 303c19de146Smrg/* 304c19de146Smrg * look to see if there is new mail; if so, Set, else Unset 305c19de146Smrg */ 306c19de146Smrg 307c19de146Smrg/* ARGSUSED */ 3089ef7378bSmrgstatic void Check (Widget gw, XEvent *event, String *params, Cardinal *nparams) 309c19de146Smrg{ 310c19de146Smrg MailboxWidget w = (MailboxWidget) gw; 311c19de146Smrg 312c19de146Smrg check_mailbox (w, TRUE, FALSE); /* redraw, no reset */ 313c19de146Smrg} 314c19de146Smrg 315c19de146Smrg 316c19de146Smrg/* ARGSUSED */ 3179ef7378bSmrgstatic void clock_tic (XtPointer client_data, XtIntervalId *id) 318c19de146Smrg{ 319c19de146Smrg MailboxWidget w = (MailboxWidget) client_data; 320c19de146Smrg 321c19de146Smrg check_mailbox (w, FALSE, FALSE); /* no redraw, no reset */ 322c19de146Smrg 323c19de146Smrg /* 324c19de146Smrg * and reset the timer 325c19de146Smrg */ 326c19de146Smrg 327c19de146Smrg w->mailbox.interval_id = 328c19de146Smrg XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w), 329c19de146Smrg w->mailbox.update * 1000, clock_tic, client_data); 330c19de146Smrg 331c19de146Smrg return; 332c19de146Smrg} 333c19de146Smrg 3349ef7378bSmrgstatic Pixmap make_pixmap (Display *dpy, MailboxWidget w, Pixmap bitmap, 3359ef7378bSmrg int depth, Boolean flip, int *widthp, int *heightp) 336c19de146Smrg{ 337c19de146Smrg Window root; 338c19de146Smrg int x, y; 339c19de146Smrg unsigned int width, height, bw, dep; 340c19de146Smrg unsigned long fore, back; 341c19de146Smrg 342c19de146Smrg if (!XGetGeometry (dpy, bitmap, &root, &x, &y, &width, &height, &bw, &dep)) 343c19de146Smrg return None; 344c19de146Smrg 345c19de146Smrg *widthp = (int) width; 346c19de146Smrg *heightp = (int) height; 347c19de146Smrg if (flip) { 348c19de146Smrg fore = w->core.background_pixel; 349c19de146Smrg back = w->mailbox.foreground_pixel; 350c19de146Smrg } else { 351c19de146Smrg fore = w->mailbox.foreground_pixel; 352c19de146Smrg back = w->core.background_pixel; 353c19de146Smrg } 354c19de146Smrg return XmuCreatePixmapFromBitmap (dpy, w->core.window, bitmap, 355c19de146Smrg width, height, depth, fore, back); 356c19de146Smrg} 357c19de146Smrg 3589ef7378bSmrgstatic void Realize (Widget gw, XtValueMask *valuemaskp, 3599ef7378bSmrg XSetWindowAttributes *attr) 360c19de146Smrg{ 361c19de146Smrg MailboxWidget w = (MailboxWidget) gw; 362c19de146Smrg register Display *dpy = XtDisplay (w); 363c19de146Smrg int depth = w->core.depth; 364c19de146Smrg 365c19de146Smrg *valuemaskp |= (CWBitGravity | CWCursor); 366c19de146Smrg attr->bit_gravity = ForgetGravity; 367c19de146Smrg attr->cursor = XCreateFontCursor (dpy, XC_top_left_arrow); 368c19de146Smrg 369c19de146Smrg (*mailboxWidgetClass->core_class.superclass->core_class.realize) 370c19de146Smrg (gw, valuemaskp, attr); 371c19de146Smrg 372c19de146Smrg /* 373c19de146Smrg * build up the pixmaps that we'll put into the image 374c19de146Smrg */ 375c19de146Smrg if (w->mailbox.full.bitmap == None) { 376c19de146Smrg w->mailbox.full.bitmap = 377c19de146Smrg XCreateBitmapFromData (dpy, w->core.window, (char *) mailfull_bits, 378c19de146Smrg mailfull_width, mailfull_height); 379c19de146Smrg } 380c19de146Smrg if (w->mailbox.empty.bitmap == None) { 381c19de146Smrg w->mailbox.empty.bitmap = 382c19de146Smrg XCreateBitmapFromData (dpy, w->core.window, (char *) mailempty_bits, 383c19de146Smrg mailempty_width, mailempty_height); 384c19de146Smrg } 385c19de146Smrg 386c19de146Smrg w->mailbox.empty.pixmap = make_pixmap (dpy, w, w->mailbox.empty.bitmap, 387c19de146Smrg depth, False, 388c19de146Smrg &w->mailbox.empty.width, 389c19de146Smrg &w->mailbox.empty.height); 390c19de146Smrg w->mailbox.full.pixmap = make_pixmap (dpy, w, w->mailbox.full.bitmap, 391c19de146Smrg depth, w->mailbox.flipit, 392c19de146Smrg &w->mailbox.full.width, 393c19de146Smrg &w->mailbox.full.height); 394c19de146Smrg 395c19de146Smrg if (w->mailbox.empty.mask == None && w->mailbox.full.mask == None) 396c19de146Smrg w->mailbox.shapeit = False; 397c19de146Smrg 398c19de146Smrg w->mailbox.interval_id = 399c19de146Smrg XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w), 400c19de146Smrg w->mailbox.update * 1000, clock_tic, (XtPointer) w); 401c19de146Smrg 402c19de146Smrg w->mailbox.shape_cache.mask = None; 403c19de146Smrg 404c19de146Smrg check_mailbox (w, TRUE, FALSE); 405c19de146Smrg 406c19de146Smrg return; 407c19de146Smrg} 408c19de146Smrg 409c19de146Smrg 4109ef7378bSmrgstatic void Destroy (Widget gw) 411c19de146Smrg{ 412c19de146Smrg MailboxWidget w = (MailboxWidget) gw; 413c19de146Smrg Display *dpy = XtDisplay (gw); 414c19de146Smrg 415c19de146Smrg XtFree (w->mailbox.filename); 416c19de146Smrg if (w->mailbox.interval_id) XtRemoveTimeOut (w->mailbox.interval_id); 417c19de146Smrg XtReleaseGC(gw, w->mailbox.gc); 418c19de146Smrg#define freepix(p) if (p) XFreePixmap (dpy, p) 419c19de146Smrg freepix (w->mailbox.full.bitmap); /* until cvter does ref cnt */ 420c19de146Smrg freepix (w->mailbox.full.mask); /* until cvter does ref cnt */ 421c19de146Smrg freepix (w->mailbox.full.pixmap); 422c19de146Smrg freepix (w->mailbox.empty.bitmap); /* until cvter does ref cnt */ 423c19de146Smrg freepix (w->mailbox.empty.mask); /* until cvter does ref cnt */ 424c19de146Smrg freepix (w->mailbox.empty.pixmap); 425c19de146Smrg freepix (w->mailbox.shape_cache.mask); 426c19de146Smrg#undef freepix 427c19de146Smrg} 428c19de146Smrg 429c19de146Smrg 4309ef7378bSmrgstatic void Redisplay (Widget gw, XEvent *event, Region region) 431c19de146Smrg{ 432c19de146Smrg MailboxWidget w = (MailboxWidget) gw; 433c19de146Smrg 434c19de146Smrg check_mailbox (w, TRUE, FALSE); 435c19de146Smrg} 436c19de146Smrg 437c19de146Smrg 4389ef7378bSmrgstatic void check_mailbox (MailboxWidget w, Boolean force_redraw, Boolean reset) 439c19de146Smrg{ 440c19de146Smrg long mailboxsize = 0; 441c19de146Smrg Boolean readSinceLastWrite = FALSE; 442c19de146Smrg 443c19de146Smrg if (w->mailbox.check_command != NULL) { 444c19de146Smrg waitType wait_status; 445c19de146Smrg int check_status; 446c19de146Smrg#ifdef INTWAITTYPE 447c19de146Smrg wait_status = system(w->mailbox.check_command); 448c19de146Smrg#else 449c19de146Smrg wait_status.w_status = system(w->mailbox.check_command); 450c19de146Smrg#endif 451c19de146Smrg check_status = waitCode(wait_status); 452c19de146Smrg 453c19de146Smrg /* error in sh checkCommand execution */ 454c19de146Smrg if (waitSig(wait_status)) 455c19de146Smrg check_status = 2; /* act as if there is no mail */ 456c19de146Smrg 457c19de146Smrg switch (check_status) { 458c19de146Smrg case 0: 459c19de146Smrg mailboxsize = w->mailbox.last_size + 1; 460c19de146Smrg break; 461c19de146Smrg case 2: 462c19de146Smrg mailboxsize = 0; 463c19de146Smrg break; 464c19de146Smrg default: /* treat everything else as no change */ 465c19de146Smrg /* case 1 is no change */ 466c19de146Smrg mailboxsize = w->mailbox.last_size; 467c19de146Smrg } 468c19de146Smrg } else { 469c19de146Smrg struct stat st; 470c19de146Smrg if (stat (w->mailbox.filename, &st) == 0) { 471c19de146Smrg mailboxsize = st.st_size; 472c19de146Smrg readSinceLastWrite = (st.st_atime > st.st_mtime); 473c19de146Smrg } 474c19de146Smrg } 475c19de146Smrg 476c19de146Smrg /* 477c19de146Smrg * Now check for changes. If reset is set then we want to pretent that 478c19de146Smrg * there is no mail. If the mailbox is empty then we want to turn off 479c19de146Smrg * the flag. Otherwise if the mailbox has changed size then we want to 480c19de146Smrg * put the flag up, unless the mailbox has been read since the last 481c19de146Smrg * write. 482c19de146Smrg * 483c19de146Smrg * The cases are: 484c19de146Smrg * o forced reset by user DOWN 485c19de146Smrg * o no mailbox or empty (zero-sized) mailbox DOWN 486c19de146Smrg * o if read after most recent write DOWN 487c19de146Smrg * o same size as last time no change 488c19de146Smrg * o bigger than last time UP 489c19de146Smrg * o smaller than last time but non-zero UP 490c19de146Smrg * 491c19de146Smrg * The last two cases can be expressed as different from last 492c19de146Smrg * time and non-zero. 493c19de146Smrg */ 494c19de146Smrg 495c19de146Smrg if (reset) { /* forced reset */ 496c19de146Smrg w->mailbox.flag_up = FALSE; 497c19de146Smrg force_redraw = TRUE; 498c19de146Smrg } else if (mailboxsize == 0) { /* no mailbox or empty */ 499c19de146Smrg w->mailbox.flag_up = FALSE; 500c19de146Smrg if (w->mailbox.last_size > 0) force_redraw = TRUE; /* if change */ 501c19de146Smrg } else if (readSinceLastWrite) { /* only when checkCommand is NULL */ 502c19de146Smrg /* mailbox has been read after most recent write */ 503c19de146Smrg if (w->mailbox.flag_up) { 504c19de146Smrg w->mailbox.flag_up = FALSE; 505c19de146Smrg force_redraw = TRUE; 506c19de146Smrg } 507c19de146Smrg } else if (mailboxsize != w->mailbox.last_size) { /* different size */ 508c19de146Smrg if (!w->mailbox.once_only || !w->mailbox.flag_up) 509c19de146Smrg beep(w); 510c19de146Smrg if (!w->mailbox.flag_up) 511c19de146Smrg force_redraw = w->mailbox.flag_up = TRUE; 512c19de146Smrg } 513c19de146Smrg 514c19de146Smrg w->mailbox.last_size = mailboxsize; 515c19de146Smrg if (force_redraw) redraw_mailbox (w); 516c19de146Smrg return; 517c19de146Smrg} 518c19de146Smrg 519c19de146Smrg/* 520c19de146Smrg * get user name for building mailbox 521c19de146Smrg */ 522c19de146Smrg 5239ef7378bSmrgstatic void GetMailFile (MailboxWidget w) 524c19de146Smrg{ 525c19de146Smrg char *username; 526c19de146Smrg char *mailpath; 527c19de146Smrg#ifdef WIN32 528c19de146Smrg if (!(username = getenv("USERNAME"))) { 529c19de146Smrg fprintf (stderr, "%s: unable to find a username for you.\n", 530c19de146Smrg "Mailbox widget"); 531c19de146Smrg CloseDown (w, 1); 532c19de146Smrg } 533c19de146Smrg#else 534c19de146Smrg 535c19de146Smrg username = getlogin (); 536c19de146Smrg if (!username) { 537c19de146Smrg struct passwd *pw = getpwuid (getuid ()); 538c19de146Smrg 539c19de146Smrg if (!pw) { 540c19de146Smrg fprintf (stderr, "%s: unable to find a username for you.\n", 541c19de146Smrg "Mailbox widget"); 542c19de146Smrg CloseDown (w, 1); 543c19de146Smrg } 544c19de146Smrg username = pw->pw_name; 545c19de146Smrg } 546c19de146Smrg#endif 547c19de146Smrg if ((mailpath = getenv("MAIL"))) { 5483b83913fSmrg XtAsprintf(&w->mailbox.filename, "%s", mailpath); 549c19de146Smrg } else { 5503b83913fSmrg XtAsprintf(&w->mailbox.filename, "%s/%s", 5513b83913fSmrg MAILBOX_DIRECTORY, username); 552c19de146Smrg } 553c19de146Smrg return; 554c19de146Smrg} 555c19de146Smrg 5569ef7378bSmrgstatic void CloseDown (MailboxWidget w, int status) 557c19de146Smrg{ 558c19de146Smrg Display *dpy = XtDisplay (w); 559c19de146Smrg 560c19de146Smrg XtDestroyWidget ((Widget)w); 561c19de146Smrg XCloseDisplay (dpy); 562c19de146Smrg exit (status); 563c19de146Smrg} 564c19de146Smrg 565c19de146Smrg 566c19de146Smrg/* ARGSUSED */ 5679ef7378bSmrgstatic Boolean SetValues (Widget gcurrent, Widget grequest, Widget gnew, 5689ef7378bSmrg ArgList args, Cardinal *num_args) 569c19de146Smrg{ 570c19de146Smrg MailboxWidget current = (MailboxWidget) gcurrent; 571c19de146Smrg MailboxWidget new = (MailboxWidget) gnew; 572c19de146Smrg Boolean redisplay = FALSE; 573c19de146Smrg 574c19de146Smrg if (current->mailbox.update != new->mailbox.update) { 575c19de146Smrg if (current->mailbox.interval_id) 576c19de146Smrg XtRemoveTimeOut (current->mailbox.interval_id); 577c19de146Smrg new->mailbox.interval_id = 578c19de146Smrg XtAppAddTimeOut (XtWidgetToApplicationContext(gnew), 579c19de146Smrg new->mailbox.update * 1000, clock_tic, 580c19de146Smrg (XtPointer) gnew); 581c19de146Smrg } 582c19de146Smrg 583c19de146Smrg if (current->mailbox.foreground_pixel != new->mailbox.foreground_pixel || 584c19de146Smrg current->core.background_pixel != new->core.background_pixel) { 585c19de146Smrg XtReleaseGC (gcurrent, current->mailbox.gc); 586c19de146Smrg new->mailbox.gc = get_mailbox_gc (new); 587c19de146Smrg redisplay = TRUE; 588c19de146Smrg } 589c19de146Smrg 590c19de146Smrg return (redisplay); 591c19de146Smrg} 592c19de146Smrg 593c19de146Smrg 594c19de146Smrg/* 595c19de146Smrg * drawing code 596c19de146Smrg */ 597c19de146Smrg 5989ef7378bSmrgstatic void redraw_mailbox (MailboxWidget w) 599c19de146Smrg{ 600c19de146Smrg register Display *dpy = XtDisplay (w); 601c19de146Smrg register Window win = XtWindow (w); 602c19de146Smrg register int x, y; 603c19de146Smrg GC gc = w->mailbox.gc; 604c19de146Smrg Pixel back = w->core.background_pixel; 605c19de146Smrg struct _mbimage *im; 606c19de146Smrg 607c19de146Smrg /* center the picture in the window */ 608c19de146Smrg 609c19de146Smrg if (w->mailbox.flag_up) { /* paint the "up" position */ 610c19de146Smrg im = &w->mailbox.full; 611c19de146Smrg if (w->mailbox.flipit) back = w->mailbox.foreground_pixel; 612c19de146Smrg } else { /* paint the "down" position */ 613c19de146Smrg im = &w->mailbox.empty; 614c19de146Smrg } 615c19de146Smrg x = (((int)w->core.width) - im->width) / 2; 616c19de146Smrg y = (((int)w->core.height) - im->height) / 2; 617c19de146Smrg 618c19de146Smrg XSetWindowBackground (dpy, win, back); 619c19de146Smrg XClearWindow (dpy, win); 620c19de146Smrg XCopyArea (dpy, im->pixmap, win, gc, 0, 0, im->width, im->height, x, y); 621c19de146Smrg 622c19de146Smrg /* 623c19de146Smrg * XXX - temporary hack; walk up widget tree to find top most parent (which 624c19de146Smrg * will be a shell) and mash it to have our shape. This will be replaced 625c19de146Smrg * by a special shell widget. 626c19de146Smrg */ 627c19de146Smrg if (w->mailbox.shapeit) { 628c19de146Smrg Widget parent; 629c19de146Smrg 630c19de146Smrg for (parent = (Widget) w; XtParent(parent); 631c19de146Smrg parent = XtParent(parent)) { 632c19de146Smrg x += parent->core.x + parent->core.border_width; 633c19de146Smrg y += parent->core.y + parent->core.border_width; 634c19de146Smrg } 635c19de146Smrg 636c19de146Smrg if (im->mask != w->mailbox.shape_cache.mask || 637c19de146Smrg x != w->mailbox.shape_cache.x || y != w->mailbox.shape_cache.y) { 638c19de146Smrg XShapeCombineMask (XtDisplay(parent), XtWindow(parent), 639c19de146Smrg ShapeBounding, x, y, im->mask, ShapeSet); 640c19de146Smrg w->mailbox.shape_cache.mask = im->mask; 641c19de146Smrg w->mailbox.shape_cache.x = x; 642c19de146Smrg w->mailbox.shape_cache.y = y; 643c19de146Smrg } 644c19de146Smrg } 645c19de146Smrg 646c19de146Smrg return; 647c19de146Smrg} 648c19de146Smrg 649c19de146Smrg 6509ef7378bSmrgstatic void beep (MailboxWidget w) 651c19de146Smrg{ 652c19de146Smrg XBell (XtDisplay (w), w->mailbox.volume); 653c19de146Smrg return; 654c19de146Smrg} 655