home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume15 / xmail / part07 / utils.c < prev   
C/C++ Source or Header  |  1991-10-29  |  14KB  |  471 lines

  1. /*
  2.  * xmail - X window system interface to the mail program
  3.  *
  4.  * Copyright 1989 The University of Texas at Austin
  5.  *
  6.  * Author:    Po Cheung
  7.  * Date:    March 10, 1989
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and
  10.  * its documentation for any purpose and without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and that
  12.  * both that copyright notice and this permission notice appear in
  13.  * supporting documentation.  The University of Texas at Austin makes no 
  14.  * representations about the suitability of this software for any purpose.  
  15.  * It is provided "as is" without express or implied warranty.
  16.  *
  17.  * Copyright 1990,1991 by National Semiconductor Corporation
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software and its
  20.  * documentation for any purpose is hereby granted without fee, provided that
  21.  * the above copyright notice appear in all copies and that both that
  22.  * copyright notice and this permission notice appear in supporting
  23.  * documentation, and that the name of National Semiconductor Corporation not
  24.  * be used in advertising or publicity pertaining to distribution of the
  25.  * software without specific, written prior permission.
  26.  *
  27.  * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  28.  * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  29.  * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  30.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  31.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  32.  * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  33.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  34.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  35.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  36.  * PERFORMANCE OF THIS SOFTWARE.
  37.  *
  38.  * The following software modules were created and are Copyrighted by
  39.  * National Semiconductor Corporation:
  40.  *
  41.  * 1. markIndex:
  42.  * 2. SelectionNumber:
  43.  * 3. SetCursor: and
  44.  * 4. SetXY.
  45.  *
  46.  * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  47.  *
  48.  */
  49.  
  50.  
  51. #include <ctype.h>
  52. #include "global.h"
  53. #include "patchlevel.h"
  54. #include "revtable.h"
  55.  
  56.  
  57. /*
  58. ** @(#)Bell() - write a status message and (optionally) ring the terminal bell
  59. */
  60. void
  61. Bell(msg)
  62. String        msg;
  63. {
  64.  Arg        args[1];
  65.  char        *p;
  66.  char        buf[BUFSIZ];
  67.  int        size;
  68.  static int    worthy = 0;        /* only msgs with ending newline are */
  69.  
  70.  
  71.  bzero(buf, (int) BUFSIZ);
  72.  size = strlen(msg);
  73.  if (size >= BUFSIZ) size = BUFSIZ - 1;
  74.  
  75.  (void) strncpy(buf, msg, size);
  76.  
  77.  p = strchr(buf, '\n');            /* messages with newline get a bell */
  78. /*
  79. ** Because we have now added enter/leave window event information messages,
  80. ** we must play a slight game with incoming messages, to prevent any error
  81. ** messages from a menu selection failure or status messages from a command
  82. ** button being overwritten by the subsequent event info messages produced
  83. ** when the menu popup is dismissed or the command completes.  To do this,
  84. ** we make the bell worthy-ness flag static, and only replace a message after
  85. ** first seeing a non-default status message, which will reset the worthy-ness
  86. ** flag, but otherwise be ignored.  When the first non-default, non-error
  87. ** message comes in, simply reset our bell worthy-ness flag and return, leaving
  88. ** the previous error message still intact.  This means, to ensure seeing the
  89. ** default message, first send a blank line to reset the worthy-ness flag.
  90. */
  91.  if (! XMail.Show_Info)            /* if NOT showing info flags always */
  92.     worthy = 0;                /* reset the bell worthy-ness flag */
  93.  else {
  94.     if (worthy && p == NULL) {        /* if last was but this ain't urgent */
  95.        if (strcmp(buf, Default_Status_Info))    /* and not the default info */
  96.           worthy = 0;            /* reset the bell worthy-ness flag */
  97.        return;                /* ignore event info if menu errored */
  98.       }                    /* by leaving previous error message */
  99.    }
  100.  
  101.  if (size == 0)                /* if intent was just to reset flag */
  102.     return;
  103.  
  104.  if (p != NULL) {            /* Only display first line of output */
  105.     *p = '\0';                /* (no new line at end of label) */
  106.     worthy = 1;                /* this message is worthy of a bell */
  107.    }
  108.  
  109.  if (worthy && XMail.bellRing)        /* ring bell if not silenced by user */
  110.     XBell(XtDisplay (toplevel), 33);
  111.  
  112.  XtSetArg(args[0], XtNlabel, (XtArgVal) buf);    /* show this message text */
  113.  XtSetValues(XtNameToWidget(toplevel, "topBox.statusWindow"), args, 1);
  114.  XFlush(XtDisplay(toplevel));
  115. } /* Bell */
  116.  
  117.  
  118. /*
  119. ** @(#)figureWidth() - determine the figure width of the specified font
  120. */
  121. int
  122. figureWidth(font)
  123. XFontStruct *font;
  124. {
  125.  Atom        _XA_FIGURE_WIDTH;
  126.  unsigned long    width = 0;
  127.  
  128.  
  129.  _XA_FIGURE_WIDTH = XInternAtom(XtDisplay(toplevel), "FIGURE_WIDTH", FALSE);
  130.  if ((_XA_FIGURE_WIDTH != NULL) &&
  131.     ((! XGetFontProperty(font, _XA_FIGURE_WIDTH, &width)) || (width == 0)))
  132.     if (font->per_char && font->min_char_or_byte2 <= '$' &&
  133.                           font->max_char_or_byte2 >= '$')
  134.        width = font->per_char['$' - font->min_char_or_byte2].width;
  135.     else
  136.        width = font->max_bounds.width;
  137.  
  138.  return(width);
  139. } /* end - figureWidth */
  140.  
  141.  
  142. /*
  143. ** @(#)markIndex() - add or remove a tag from the start of a mail header line
  144. */
  145. void
  146. markIndex(s)
  147. char    *s;
  148. {
  149.  int            size;
  150.  char            buf[3];
  151.  Arg            args[1];
  152.  String            c, p;
  153.  Widget            iw;
  154.  XawTextBlock        text;
  155.  XawTextPosition    pos, old;
  156.  
  157.  
  158.  iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  159.  pos = XawTextGetInsertionPoint(iw);    /* save the current insertion point */
  160.  (void) strcpy(buf, s);            /* make a copy of our marking string */
  161.  if (pos != 0) {            /* if not already at front of buffer */
  162.     text.firstPos = 0;            /* find the start of this index line */
  163.     text.length   = 1;
  164.     text.ptr      = "\n";
  165.     text.format   = FMT8BIT;
  166.     if ((old = XawTextSearch(iw, XawsdLeft, &text)) != XawTextSearchError)
  167.        pos = old + 1;
  168.     else pos = 0;
  169.    }
  170.  
  171.  if (buf[0] == '>') {            /* if mark is for 'current' pointer */
  172.     XtSetArg(args[0], XtNstring, &p);    /* retrieve the current index buffer */
  173.     XtGetValues(iw, args, 1);
  174.  
  175.     if (strlen(p) > pos + 1)
  176.        if (p[pos + 1] == 'S')        /* keep the Save marker if it exists */
  177.           if (strlen(buf) > 1)
  178.              buf[1] = '\0';
  179.  
  180.     for (c = p; *c; c++)
  181.         if (*c == '>' && (c == p || *(c - 1) == '\n')) {
  182.            old = c - p;            /* if found, remove the old '>' mark */
  183.            text.firstPos = 0;
  184.            text.length   = 1;
  185.            text.ptr      = " ";
  186.            text.format   = FMT8BIT;
  187.            XawTextReplace(iw, (XawTextPosition) old, (XawTextPosition) old + 1, &text);
  188.            break;
  189.           }
  190.    }
  191.  
  192.  size = strlen(buf);            /* now write the specified marker */
  193.  old = (buf[0] == '>') ? pos : pos + 1;
  194.  text.firstPos = 0;
  195.  text.length   = size;
  196.  text.ptr      = buf;
  197.  text.format   = FMT8BIT;
  198.  XawTextReplace(iw, (XawTextPosition) old, (XawTextPosition) old + size, &text);
  199.  
  200.  XawTextSetInsertionPoint(iw, pos);    /* reset our actual insertion point */
  201. } /* markIndex */
  202.  
  203.  
  204. /*
  205. ** @(#)SelectionNumber() - Get mail index number from line position
  206. */
  207. int
  208. SelectionNumber(undeleting)
  209. int    undeleting;
  210. {
  211.  Arg            args[1];
  212.  Widget            iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  213.  String            c, str = NULL;
  214.  int            selection_number = 0;
  215.  
  216.  
  217.  XtSetArg(args[0], XtNstring, &str);
  218.  XtGetValues(iw, args, 1);
  219.  
  220.  for (c = str; *c; c++)
  221.      if (*c == '>' && (c == str || *(c - 1) == '\n'))
  222.         break;
  223.  
  224.  if (*c && (! undeleting || *(c + 1) == 'D')) {
  225.     for (; *c && !isdigit(*c); c++);
  226.     (void) sscanf(c, "%d", &selection_number);
  227.    }
  228.  
  229.  return(selection_number);
  230. } /* SelectionNumber */
  231.  
  232. extern Window    WaitCursorWindow;
  233. Boolean        Waiting;
  234.  
  235. /* ARGSUSED */
  236. /*
  237. ** @(#)SetCursor() - sets the wait cursor or restores the default
  238. */
  239. void
  240. SetCursor(waiting)
  241. int    waiting;        /* a non-zero value sets the busy cursor */
  242. {
  243.  if (! waiting)
  244.     XUnmapWindow(XtDisplay(toplevel), WaitCursorWindow);
  245.  else {
  246.       XMapWindow(XtDisplay(toplevel), WaitCursorWindow);
  247.     Waiting = TRUE;        /* to prevent overwrite of important info */
  248.    }
  249.  
  250.  XFlush(XtDisplay(toplevel));
  251. } /* SetCursor */
  252.  
  253.  
  254. /*
  255. ** @(#)SetXY() - Set relative window coordinates including specified offset
  256. */
  257. void
  258. SetXY(target, reference, X_offset, Y_offset)
  259. Widget    target, reference;
  260. int    X_offset, Y_offset;
  261. {
  262.  Arg        args[2];
  263.  Display    *dpy = XtDisplay(reference);
  264.  
  265.  Window        dumy;
  266.  int        x, y;
  267.  
  268.  
  269.  XTranslateCoordinates(dpy, XtWindow(reference),
  270.                        RootWindow(dpy, DefaultScreen(dpy)),
  271.                        X_offset, Y_offset, &x, &y, &dumy);
  272.  /*
  273.  ** Keep window within root window borders (don't place it off-screen)
  274.  */
  275.  if (! XtIsRealized(target))
  276.     XtRealizeWidget(target);        /* to get width and height values */
  277.  
  278.  if (x + target->core.width > RootWidth)
  279.     x = RootWidth - target->core.width - 2;
  280.  
  281.  if (y + target->core.height > RootHeight)
  282.     y = RootHeight - target->core.height - 2;
  283.  
  284.  XtSetArg(args[0], XtNx, x);
  285.  XtSetArg(args[1], XtNy, y);
  286.  XtSetValues(target, args, 2);
  287. } /* end - SetXY */
  288.  
  289.  
  290. /*
  291. ** @(#)TextGetLastPos() - return position of last text character
  292. */
  293. XawTextPosition
  294. TextGetLastPos(w)
  295. Widget w;
  296. {
  297.  TextWidget ctx = (TextWidget) w;
  298.  return (XawTextSourceScan(ctx->text.source,0,XawstAll,XawsdRight,1,TRUE));
  299. }
  300.  
  301.  
  302. /*
  303. ** @(#)UpdateTitleBar() - replace information in the title bar title
  304. */
  305. void
  306. UpdateTitleBar(msg)
  307. char *msg;
  308. {
  309.  char        message[BUFSIZ];
  310.  Arg        args[1];
  311.  Widget        w;
  312.  
  313.  
  314.  (void) sprintf(message, "%s%d - %s", TITLE, PATCHLEVEL, msg);
  315.  
  316.  w = XtNameToWidget(toplevel, "topBox.titleBar.title");
  317.  
  318.  XtSetArg(args[0], XtNlabel, (XtArgVal) message);
  319.  XtSetValues(w, args, 1);
  320.  
  321.  w = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail.Newmail_menu.menu.inc");
  322.  if (w)
  323.     XtSetSensitive(w, In_System_Folder());
  324. } /* UpdateTitleBar */
  325.  
  326.  
  327. /*
  328. ** @(#)writeTo() - write text to the specified text widget
  329. */
  330. void
  331. writeTo(w, s, do_append)
  332. Widget    w;
  333. char   *s;
  334. int    do_append;
  335. {
  336.  XawTextBlock        text;
  337.  XawTextPosition    startPos, endPos;
  338.  
  339.  
  340.  text.firstPos = 0;
  341.  text.length   = strlen(s);
  342.  text.ptr      = s;
  343.  text.format   = FMT8BIT;
  344.  
  345.  endPos = TextGetLastPos(w) + (do_append ? 0 : 1);
  346.  startPos = (do_append ? endPos : 0);
  347.  
  348.  XawTextReplace(w, startPos, endPos, &text);
  349.  
  350.  endPos = TextGetLastPos(w);
  351.  
  352.  XawTextSetInsertionPoint(w, endPos);
  353.  
  354.  XawTextInvalidate(w, 0, endPos);
  355. } /* writeTo */
  356.  
  357.  
  358. /*
  359. ** @(#)writeText() - replace the current text string in the text window.
  360. **                 Also look for an X-Face: header and if found, display.
  361. */
  362. void
  363. writeText(buf)
  364. char    *buf;
  365. {
  366.  Arg            args[2];
  367.  Widget        w = XtNameToWidget(toplevel, "topBox.textWindow.text");
  368. #ifdef X_FACE
  369.  Display        *dpy = XtDisplay(w);
  370.  Widget         fw;
  371.  Window         rw;
  372.  char           cb[1024], fb[2048], *ptr, *xface;
  373.  int            i, n, x, y;
  374. #endif
  375.  
  376.  if (buf && *buf) {
  377. #ifndef X_FACE
  378.     XtSetArg(args[0], XtNstring, buf);
  379.     XtSetValues(w, args, 1);
  380. #else
  381.     if (! (fw = XtNameToWidget(XtParent(w), "face"))) {
  382.        XtSetArg(args[0], XtNstring, buf);
  383.        XtSetValues(w, args, 1);
  384.        return;
  385.       }
  386.     /*
  387.     ** First, unmap any current picture.
  388.     **
  389.     ** Look for a line containing an 'X-Face:' header, followed by 72
  390.     ** characters of compressed data.  The second and any subsequentlines
  391.     ** will contain an initial space (which is ignored), followed by79
  392.     ** characters of compressed data.  The last line may contain fewer than 79
  393.     ** characters.
  394.     **
  395.     ** The X-Face: header and any immediate whitespace (tabs or spaces) will be
  396.     ** removed, and the remaining line placed in the internal buffer(minus
  397.     ** any trailing newline).  On subsequent lines, initial whitespace will be
  398.     ** removed, and the remainder of the data appended to the buffer(minus any
  399.     ** trailing newline).
  400.     **
  401.     ** A blank line, a line without an initial whitespace character,or the
  402.     ** end of the input buffer will signify the end of the X-Face data.  That
  403.     ** buffer will then be uncompressed, and if the data was valid, displayed.
  404.     */
  405.  
  406.     if (XtIsManaged(fw))
  407.        XtUnmanageChild(fw);
  408.  
  409.     for (ptr = buf; *ptr; ptr++) {
  410.         if (*ptr == '\n'                    ||
  411.            strncmp(ptr, "Status:", 7) == 0  ||
  412.            strncmp(ptr, "X-Face:", 7) == 0) break;
  413.  
  414.         for (; *ptr && *ptr != '\n'; ptr++);
  415.        }
  416.  
  417.     if (! *ptr || strncmp(ptr, "X-Face:", 7) != 0) {
  418.        XtSetArg(args[0], XtNstring, buf);
  419.        XtSetValues(w, args, 1);
  420.        return;
  421.       }
  422.  
  423.     xface = ptr;    /* keep track of the start position of X-Face header */
  424.  
  425.     bzero(fb, 2048);
  426.     for (i = 0, ptr += 7; *ptr; ptr++) {
  427.         if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n')
  428.            fb[i++] = *ptr;
  429.         if (*ptr == '\n' && *(ptr+1) && *(ptr+1) != ' ' && *(ptr+1) != '\t')
  430.            break;
  431.        }
  432.  
  433.     if (XMail.No_X_Hdr) {
  434.        if (*ptr) ptr++;
  435.        bcopy(ptr, xface, strlen(ptr) + 1);    /* suppress the X-Face header */
  436.       }
  437.  
  438.     XtSetArg(args[0], XtNstring, buf);
  439.     XtSetValues(w, args, 1);
  440.  
  441.     if (uncompface(fb) >= 0) {
  442.        bzero(cb, 1024);
  443.        for (i = n = 0;i < 1024;) {
  444.            if (! sscanf(&fb[n], "%i%n", &x, &y)) break;
  445.            cb[i++] = revtable[(x >> 8) & 0xFF];
  446.            cb[i++] = revtable[x & 0xFF];
  447.            n += y;
  448.            while (fb[n] && (fb[n]==',' || fb[n]=='\n')) n++;
  449.           }
  450.  
  451.        XtSetArg(args[0], XtNwidth, NULL);
  452.        XtGetValues(XtParent(w), args, 1);
  453.        n = args[0].value - 48;
  454.        if (n < 0) n = 0;
  455.  
  456.        XtSetArg(args[0], XtNbitmap, NULL);
  457.        XtGetValues(fw, args, 1);
  458.        if (args[0].value != None)
  459.           XFreePixmap(dpy, args[0].value);
  460.  
  461.        rw = RootWindow(dpy, DefaultScreen(dpy));
  462.        XtSetArg(args[0], XtNbitmap, XCreateBitmapFromData(dpy, rw, cb, 48, 48));
  463.        XtSetArg(args[1], XtNhorizDistance, n);
  464.        XtSetValues(fw, args, 2);
  465.  
  466.        XtManageChild(fw);
  467.       }
  468. #endif
  469.    }
  470. } /* writeText */
  471.