home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / xmail / part03 / utils.c < prev   
C/C++ Source or Header  |  1991-06-15  |  14KB  |  464 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 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 TORTUOUS 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, 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.  XtSetArg(args[0], XtNlabel, (XtArgVal) buf);    /* show this message text */
  110.  XtSetValues(XtNameToWidget(toplevel, "topBox.statusWindow"), args, ONE);
  111.  
  112.  if (worthy && XMail.bellRing)        /* ring bell if not silenced by user */
  113.     XBell(XtDisplay (toplevel), 33);
  114.  
  115.  SetCursor(0);                /* restore default cursors */
  116. } /* Bell */
  117.  
  118.  
  119. /*
  120. ** @(#)figureWidth() - determine the figure width of the specified font
  121. */
  122. int
  123. figureWidth(font)
  124. XFontStruct *font;
  125. {
  126.  Atom        _XA_FIGURE_WIDTH;
  127.  unsigned long    width = 0;
  128.  
  129.  
  130.  _XA_FIGURE_WIDTH = XInternAtom(XtDisplay(toplevel), "FIGURE_WIDTH", FALSE);
  131.  if ((_XA_FIGURE_WIDTH != NULL) &&
  132.     ((! XGetFontProperty(font, _XA_FIGURE_WIDTH, &width)) || (width == 0)))
  133.     if (font->per_char && font->min_char_or_byte2 <= '$' &&
  134.                           font->max_char_or_byte2 >= '$')
  135.        width = font->per_char['$' - font->min_char_or_byte2].width;
  136.     else
  137.        width = font->max_bounds.width;
  138.  
  139.  return(width);
  140. } /* end - figureWidth */
  141.  
  142.  
  143. /*
  144. ** @(#)markIndex() - add or remove a tag from the start of a mail header line
  145. */
  146. void
  147. markIndex(s)
  148. char    *s;
  149. {
  150.  char            buf[3];
  151.  Arg            args[1];
  152.  Cardinal        size;
  153.  String            c, p;
  154.  Widget            iw;
  155.  XawTextBlock        text;
  156.  XawTextPosition    pos, old;
  157.  
  158.  
  159.  iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  160.  pos = XawTextGetInsertionPoint(iw);    /* save the current insertion point */
  161.  strcpy(buf, s);            /* make a copy of our marking string */
  162.  if (pos != 0) {            /* if not already at front of buffer */
  163.     text.firstPos = 0;            /* find the start of this index line */
  164.     text.length   = 1;
  165.     text.ptr      = "\n";
  166.     text.format   = FMT8BIT;
  167.     if ((old = XawTextSearch(iw, XawsdLeft, &text)) != XawTextSearchError)
  168.        pos = old + 1;
  169.     else pos = 0;
  170.    }
  171.  
  172.  if (buf[0] == '>') {            /* if mark is for 'current' pointer */
  173.     XtSetArg(args[0], XtNstring, &p);    /* retrieve the current index buffer */
  174.     XtGetValues(iw, args, ONE);
  175.     XawAsciiSourceFreeString(iw);    /* release the memory from GetValues */
  176.  
  177.     if (strlen(p) > pos + 1)
  178.        if (p[pos + 1] == 'S')        /* keep the Save marker if it exists */
  179.           if (strlen(buf) > 1)
  180.              buf[1] = '\0';
  181.  
  182.     for (c = p; *c; c++)
  183.         if (*c == '>' && (c == p || *(c - 1) == '\n')) {
  184.            old = c - p;            /* if found, remove the old '>' mark */
  185.            text.firstPos = 0;
  186.            text.length   = 1;
  187.            text.ptr      = " ";
  188.            text.format   = FMT8BIT;
  189.            XawTextReplace(iw, old, old + 1, &text);
  190.            break;
  191.           }
  192.    }
  193.  
  194.  size = strlen(buf);            /* now write the specified marker */
  195.  old = (buf[0] == '>') ? pos : pos + 1;
  196.  text.firstPos = 0;
  197.  text.length   = size;
  198.  text.ptr      = buf;
  199.  text.format   = FMT8BIT;
  200.  XawTextReplace(iw, old, old + size, &text);
  201.  
  202.  XawTextSetInsertionPoint(iw, pos);    /* reset our actual insertion point */
  203. } /* markIndex */
  204.  
  205.  
  206. /*
  207. ** @(#)SelectionNumber() - Get mail index number from line position
  208. */
  209. int
  210. SelectionNumber(undeleting)
  211. int    undeleting;
  212. {
  213.  Arg            args[1];
  214.  Widget            iw = XtNameToWidget(toplevel, "topBox.indexWindow");
  215.  String            c, str = NULL;
  216.  int            selection_number = 0;
  217.  
  218.  
  219.  XtSetArg(args[0], XtNstring, &str);
  220.  XtGetValues(iw, args, ONE);
  221.  
  222.  for (c = str; *c; c++)
  223.      if (*c == '>' && (c == str || *(c - 1) == '\n'))
  224.         break;
  225.  
  226.  if (*c && (! undeleting || *(c + 1) == 'D')) {
  227.     for (; *c && !isdigit(*c); c++);
  228.     sscanf(c, "%d", &selection_number);
  229.    }
  230.  
  231.  XawAsciiSourceFreeString(iw);        /* release GetValues memory */
  232.  
  233.  return(selection_number);
  234. } /* SelectionNumber */
  235.  
  236.  
  237. /* ARGSUSED */
  238. /*
  239. ** @(#)SetCursor() - sets the wait cursor or restores the default
  240. */
  241. void
  242. SetCursor(waiting)
  243. int    waiting;        /* a non-zero value sets the wait cursor(s) */
  244. {
  245.  Widget        tb, iw, tw, fw;
  246.  
  247.  
  248.  tb = XtNameToWidget(toplevel, "topBox");
  249.  iw = XtNameToWidget(tb, "indexWindow");
  250.  tw = XtNameToWidget(tb, "textWindow.text");
  251.  fw = XtNameToWidget(tb, "commandPanel.fileWindow");
  252.  
  253.  if (waiting) {
  254.     XDefineCursor(XtDisplay(tb), XtWindow(tb), waitC);
  255.     XDefineCursor(XtDisplay(iw), XtWindow(iw), waitC);
  256.     XDefineCursor(XtDisplay(tw), XtWindow(tw), waitC);
  257.     XDefineCursor(XtDisplay(fw), XtWindow(fw), waitC);
  258.    } else {
  259.     XDefineCursor(XtDisplay(tb), XtWindow(tb), None);
  260.     XDefineCursor(XtDisplay(iw), XtWindow(iw), xtermC);
  261.     XDefineCursor(XtDisplay(tw), XtWindow(tw), xtermC);
  262.     XDefineCursor(XtDisplay(fw), XtWindow(fw), xtermC);
  263.    }
  264.  XFlush(XtDisplay(toplevel));
  265. } /* SetCursor */
  266.  
  267.  
  268. /*
  269. ** @(#)SetXY() - Set relative window coordinates including specified offset
  270. */
  271. void
  272. SetXY(target, reference, X_offset, Y_offset)
  273. Widget    target, reference;
  274. int    X_offset, Y_offset;
  275. {
  276.  Arg        args[2];
  277.  Display    *dpy = XtDisplay(reference);
  278.  
  279.  Window        dumy;
  280.  int        x, y;
  281.  
  282.  
  283.  XTranslateCoordinates(dpy, XtWindow(reference),
  284.                        RootWindow(dpy, DefaultScreen(dpy)),
  285.                        X_offset, Y_offset, &x, &y, &dumy);
  286.  /*
  287.  ** Keep window within root window borders (don't place it off-screen)
  288.  */
  289.  if (! XtIsRealized(target))
  290.     XtRealizeWidget(target);        /* to get width and height values */
  291.  
  292.  if (x + target->core.width > RootWidth)
  293.     x = RootWidth - target->core.width - 2;
  294.  
  295.  if (y + target->core.height > RootHeight)
  296.     y = RootHeight - target->core.height - 2;
  297.  
  298.  XtSetArg(args[0], XtNx, x);
  299.  XtSetArg(args[1], XtNy, y);
  300.  XtSetValues(target, args, TWO);
  301. } /* end - SetXY */
  302.  
  303.  
  304. /*
  305. ** @(#)TextGetLastPos() - return value of text insert position
  306. */
  307. XawTextPosition
  308. TextGetLastPos(w)
  309. Widget w;
  310. {
  311.  TextWidget ctx = (TextWidget) w;
  312.  return (ctx->text.lastPos);
  313. }
  314.  
  315.  
  316. /*
  317. ** @(#)UpdateTitleBar() - replace information in the title bar title
  318. */
  319. void
  320. UpdateTitleBar(msg)
  321. char *msg;
  322. {
  323.  char        message[BUFSIZ];
  324.  Arg        args[1];
  325.  Widget        w;
  326.  
  327.  
  328.  sprintf(message, "%s%d - %s", TITLE, PATCHLEVEL, msg);
  329.  
  330.  w = XtNameToWidget(toplevel, "topBox.titleBar.title");
  331.  
  332.  XtSetArg(args[0], XtNlabel, (XtArgVal) message);
  333.  XtSetValues(w, args, ONE);
  334.  
  335.  w = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail.Newmail_menu.menu.inc");
  336.  if (w)
  337.     XtSetSensitive(w, In_System_Folder());
  338. } /* UpdateTitleBar */
  339.  
  340.  
  341. /*
  342. ** @(#)writeText() - write text to the current string source
  343. */
  344. void
  345. writeText(w, s, do_append)
  346. Widget    w;
  347. char   *s;
  348. int    do_append;
  349. {
  350.  XawTextBlock        text;
  351.  XawTextPosition    startPos, endPos;
  352.  
  353.  
  354.  text.firstPos = 0;
  355.  text.length   = strlen(s);
  356.  text.ptr      = s;
  357.  text.format   = FMT8BIT;
  358.  
  359.  endPos = TextGetLastPos(w) + (do_append ? 0 : 1);
  360.  startPos = (do_append ? endPos : 0);
  361.  
  362.  XawTextReplace(w, startPos, endPos, &text);
  363.  
  364.  XawTextSetInsertionPoint(w, TextGetLastPos(w));
  365. } /* writeText */
  366.  
  367.  
  368. /*
  369. ** @(#)writeTo() - replace the current text in the specified widget
  370. **                 Also look for an X-Face: header, and if found, display.
  371. */
  372. void
  373. writeTo(w, buf)
  374. Widget    w;
  375. char    *buf;
  376. {
  377.  Arg        args[2];
  378.  Display    *dpy = XtDisplay(w);
  379.  Widget        fw;
  380.  Window        rw;
  381.  char        cb[1024], fb[2048], *ptr;
  382.  int        i, n, x, y;
  383.  
  384.  if (buf && *buf) {
  385.     XtSetArg(args[0], XtNstring, buf);
  386.     XtSetValues(w, args, ONE);
  387.  
  388. #ifdef X_FACE
  389.     if (! (fw = XtNameToWidget(XtParent(w), "face")))
  390.        return;
  391.  
  392.     /*
  393.     ** First, unmap any current picture.
  394.     **
  395.     ** Look for a line containing an 'X-Face:' header, followed by 72
  396.     ** characters of compressed data.  The second and any subsequent lines
  397.     ** will contain an initial space (which is ignored), followed by 79
  398.     ** characters of compressed data.  The last line may contain fewer than 79
  399.     ** characters.
  400.     **
  401.     ** The X-Face: header and any immediate whitespace (tabs or spaces) will be
  402.     ** removed, and the remaining line placed in the internal buffer (minus
  403.     ** any trailing newline).  On subsequent lines, initial whitespace will be
  404.     ** removed, and the remainder of the data appended to the buffer (minus any
  405.     ** trailing newline).
  406.     **
  407.     ** A blank line, a line without an initial whitespace character, or the
  408.     ** end of the input buffer will signify the end of the X-Face data.  That
  409.     ** buffer will then be uncompressed, and if the data was valid, displayed.
  410.     */
  411.  
  412.     if (XtIsManaged(fw))
  413.        XtUnmanageChild(fw);
  414.  
  415.     for (ptr = buf; *ptr; ptr++) {
  416.         if (*ptr == '\n' || strncmp(ptr, "Status:", 7) == 0)
  417.            return;
  418.  
  419.         if (strncmp(ptr, "X-Face:", 7) == 0 ) break;
  420.  
  421.         for (; *ptr && *ptr != '\n'; ptr++);
  422.        }
  423.  
  424.     if (! *ptr || strncmp(ptr, "X-Face:", 7) != 0) return;
  425.  
  426.     bzero(fb, 2048);
  427.     for (i = 0, ptr += 7; *ptr; ptr++) {
  428.         if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n')
  429.            fb[i++] = *ptr;
  430.         if (*ptr == '\n' && *(ptr+1) && *(ptr+1) != ' ' && *(ptr+1) != '\t')
  431.            break;
  432.        }
  433.  
  434.     if (uncompface(fb) >= 0) {
  435.        bzero(cb, 1024);
  436.        for (i = n = 0;i < 1024;) {
  437.            if (! sscanf(&fb[n], "%i%n", &x, &y)) break;
  438.            cb[i++] = revtable[(x >> 8) & 0xFF];
  439.            cb[i++] = revtable[x & 0xFF];
  440.            n += y;
  441.            while (fb[n] && (fb[n]==',' || fb[n]=='\n')) n++;
  442.           }
  443.  
  444.        XtSetArg(args[0], XtNwidth, NULL);
  445.        XtGetValues(w, args, 1);
  446.        n = args[0].value - 48;
  447.        if (n < 0) n = 0;
  448.  
  449.        XtSetArg(args[0], XtNbitmap, NULL);
  450.        XtGetValues(fw, args, 1);
  451.        if (args[0].value != None)
  452.           XFreePixmap(dpy, args[0].value);
  453.  
  454.        rw = RootWindow(dpy, DefaultScreen(dpy));
  455.        XtSetArg(args[0], XtNbitmap, XCreateBitmapFromData(dpy, rw, cb, 48, 48));
  456.        XtSetArg(args[1], XtNhorizDistance, n);
  457.        XtSetValues(fw, args, TWO);
  458.  
  459.        XtManageChild(fw);
  460.       }
  461. #endif
  462.    }
  463. } /* writeTo */
  464.