v13i045: xmail, Part03/11

Michael Wagnitz stratus!voder!nsc!berlioz.nsc.com!michael at uunet.UU.NET
Sun Jun 16 05:44:27 AEST 1991


Submitted-by: stratus!voder!nsc!berlioz.nsc.com!michael at uunet.UU.NET (Michael Wagnitz)
Posting-number: Volume 13, Issue 45
Archive-name: xmail/part03

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 11)."
# Contents:  handler.c mail.c utils.c
# Wrapped by michael at harley on Fri May  3 13:35:49 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'handler.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'handler.c'\"
else
echo shar: Extracting \"'handler.c'\" \(11898 characters\)
sed "s/^X//" >'handler.c' <<'END_OF_FILE'
X/*
X * xmail - X window system interface to the mail program
X *
X * Copyright 1989 The University of Texas at Austin
X *
X * Author:	Po Cheung
X * Date:	March 10, 1989
X *
X * Permission to use, copy, modify, and distribute this software and
X * its documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation.  The University of Texas at Austin makes no 
X * representations about the suitability of this software for any purpose.  
X * It is provided "as is" without express or implied warranty.
X *
X * Copyright 1990 by National Semiconductor Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of National Semiconductor Corporation not
X * be used in advertising or publicity pertaining to distribution of the
X * software without specific, written prior permission.
X *
X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
X * OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X * PERFORMANCE OF THIS SOFTWARE.
X *
X * The following software modules were created and are Copyrighted by National
X * Semiconductor Corporation:
X *
X * 1. In_System_Folder:
X * 2. icon_handler:
X * 3. index_handler:
X * 4. info_handler: and
X * 5. file_handler.
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X
X#include <ctype.h>
X#include "global.h"
X#include "xmailregex.h"
X#include "MailwatchP.h"
X#include <X11/Xaw/LabelP.h>
X
XBoolean	In_Bogus_Mail_File = False;	/* TRUE when we go iconic */
X
X/*
X** Examine the current value of the titleBar title and return TRUE/FALSE
X** to the question "Does it match the system mail folder name?"
X*/
Xint
XIn_System_Folder()
X{
X int		 result;
X char		 *cp, buf[BUFSIZ];
X Arg		 args[1];
X MailwatchWidget mb = (MailwatchWidget) XtNameToWidget(toplevel, "icon.mailbox");
X LabelWidget	 tb = (LabelWidget) XtNameToWidget(toplevel, "topBox.titleBar.title");
X
X XtSetArg(args[0], XtNlabel, (XtArgVal) NULL);
X XtGetValues(tb, args, ONE);
X strcpy(buf, (char *)args[0].value);
X
X if ((cp = strrchr(buf, '"')) == NULL) result = FALSE;
X else {					/* if a current folder name exists */
X    *cp = NULL;				/* chop off the rest of the label */
X    if ((cp = strchr(buf, '"')) == NULL) result = FALSE;
X    else result = (strcmp(mb->mailbox.filename, ++cp) == 0) ? TRUE : FALSE;
X   }
X return(result);
X} /* In_System_Folder */
X
X
X/*
X** Process map and unmap events for the icon widget to manage iconify and
X** deiconify events and switch to/from a bogus mail folder.  This allows users
X** to access mail from another process without colliding with an open folder.
X** Once the bogus mail folder is accessed, we unlink it, to avoid having to
X** explicitly remove it later.
X*/
XXtEventHandler
Xicon_handler(w, client_data, event)
XWidget	w;
Xcaddr_t	client_data;
XXEvent	*event;
X{
X FILE	*fp;
X char	*cp, cmd[BUFSIZ];
X static Boolean	Was_System_Folder = False;	/* TRUE if we had been in */
X
X
X if (mailpid) {
X    switch (event->type) {
X           case MapNotify :
X                if (! In_Bogus_Mail_File) {
X                   Was_System_Folder = In_System_Folder();
X                   (void) sprintf(cmd, "%s+", tmpName);
X                   if (fp = fopen(cmd, "w")) {	/* create a bogus mail file */
X                      (void) fprintf(fp, "\n");
X                      fclose(fp);
X                      (void) sprintf(cmd, "file %s+", tmpName);
X                      cp = QueryMail(cmd);	/* focus our attention there */
X                      XtFree(cp);
X                      (void) sprintf(cmd, "%s+", tmpName);
X                      (void) unlink(cmd);	/* toss it now that we're in */
X                      In_Bogus_Mail_File = True;
X                     }
X                  }
X                break;
X           case UnmapNotify :
X                if (In_Bogus_Mail_File) {
X                   if (strcmp(Command, "Start") != 0) {	/* if not starting up */
X                      if (Was_System_Folder) {		/* go to system file */
X                         (void) strcpy(Command, "file %\n");
X                        } else {			/* go to prev. file */
X                         (void) strcpy(Command, "file #\n");
X                        }
X                     } else {
X                      if (XMail.MFileName) {	/* start in specified folder */
X                         (void) sprintf(Command, "file %s\n", XMail.MFileName);
X                        } else {		/* or else use system folder */
X                         (void) strcpy(Command, "file %\n");
X                        }
X                     }
X                   writeMail(Command);		/* let parser do the updating */
X                   In_Bogus_Mail_File = False;
X                   Was_System_Folder = False;
X                  } else if (In_System_Folder())
X                            UnsetNewmail(NULL, NULL, NULL);
X                break;
X           default:
X                break;
X          } /* end - switch on event type */
X   } /* end - if mail is active */
X} /* icon_handler */
X
X
X/*
X** @(#)index_handler() - find value of specified or next appropriate message
X*/
Xint
Xindex_handler(msg_num, undeleting)
Xint	msg_num;
Xint	undeleting;
X{
X Arg			args[1];
X Cardinal		j, k;
X String			c, s, IBuf;
X Widget			iw;
X XawTextPosition	pos;
X
X
X Bell("");					/* reset bell worthyness flag */
X Bell(Default_Status_Info);
X
X k = msg_num;					/* Try to use specified msg. */
X if (k == 0) {					/* But, if not specified... */
X    c = QueryMail("=");
X    if (*c)
X       sscanf(c, "%d", &k);			/* get msg num from mail. */
X    XtFree(c);
X   }
X
X IBuf = NULL;
X XtSetArg(args[0], XtNstring, &IBuf);
X iw = XtNameToWidget(toplevel, "topBox.indexWindow");
X XtGetValues(iw, args, ONE);
X
X if (k <= 50) {					/* do short index from front */
X    s = IBuf;
X    for (j = k - 1; j > 0 && (c = strchr(s, '\n')) != NULL; j--) s = c + 1;
X   } else {					/* if index is fairly large */
X    for (s = &IBuf[strlen(IBuf) - 2]; s > IBuf && *s != '\n'; s--);
X    for (c = s + 1; *c && !isdigit(*c); c++);	/* get number of last entry */
X    j = 0;
X    if (*c)
X       sscanf(c, "%d", &j);			/* look backwards from there */
X    for (; j > k; j--) {
X        if (s > IBuf) s--;
X        for (; s > IBuf && *s != '\n'; s--);
X       }
X    if (*s == '\n') s++;
X   } 
X
X j = k;
X for (;;) {					/* allow for deleted msgs */
X     for (c = s; *c && !isdigit(*c); c++);
X     if (! *c || k == 0 ||
X	(sscanf(c, "%d", &j) && j <= k))	/* total may be less than us */
X        break;
X
X     if (s - 2 >= IBuf)
X        for (s -= 2; s > IBuf && *s != '\n'; s--);
X     if (*s == '\n') s++;
X    }
X
X if (! undeleting && *(s + 1) == 'D') {		/* If this is a deleted msg */
X    j = 0;					/* then num is inappropriate */
X    for (;*s && *(s + 1) == 'D';) {		/* try looking above deletes */
X        if (! (c = strchr(s,'\n'))) break;	/* don't go past end of buf */
X        s = c + 1;
X       }
X    for (;s > IBuf && *(s + 1) == 'D';) {
X        for (s -= 2; s > IBuf && *s != '\n'; s--);
X        if (*s == '\n') s++;
X       }
X    if (*(s + 1) != 'D') {			/* If we found a readable msg */
X       for (c = s; *c && !isdigit(*c); c++);
X       if (*c)
X          sscanf(c, "%d", &j);
X      }
X   }
X
X if (j) {					/* if we have a valid msg num */
X    pos = s - IBuf;				/* resolve our position */
X    XawTextSetInsertionPoint(iw, pos);		/* point at selected line */
X    markIndex("> ");				/* flag it as current */
X   } else XawAsciiSourceFreeString(iw);		/* release GetValues memory */
X
X return(j);					/* return msg actually found */
X} /* index_handler */
X
X
X/*
X** @(#)info_handler - use enter/leave_notify events to alter status window info
X*/
X/*ARGSUSED*/
Xvoid
Xinfo_handler(w, client_data, event)
XWidget	w;				/* unused */
Xcaddr_t	client_data;
XXEvent	*event;
X{
X if      (event->type == LeaveNotify)	Bell(Default_Status_Info);
X else if (event->type == EnterNotify)	Bell(client_data);
X} /* end - info_handler */
X
X
X/*
X** @(#)file_handler() - Handle output of Start and file commands.
X**                      If *Show_Last: resource is TRUE show last
X**                      message in list, if none are marked as new.
X*/
Xfile_handler()
X{
X Widget			iw = XtNameToWidget(toplevel, "topBox.indexWindow");
X XawTextPosition	pos;
X char			*c, *s, *p, msgnum_str[10];
X int			more_than_one, msg_num = 0;
X
X
X c = QueryMail("=");				/* Get current mail msg num. */
X while (! isdigit(*c)) {
X    XtFree(c);
X    if (! mailpid) return;
X    c = QueryMail("=");
X   }
X sprintf(msgnum_str, c);
X XtFree(c);
X
X c = QueryMail("file");				/* Forces current msg to one */
X if (! mailpid) return (0);
X
X if (! In_Bogus_Mail_File)
X    (void) UpdateTitleBar(c);
X XtFree(c);
X
X if (strcmp(Command, "Start") == 0) {		/* unless we're at Start, in */
X    c = QueryMail("=");				/* which case we get it now  */
X    sprintf(msgnum_str, c);			/* (due to -N mailargv use). */
X    XtFree(c);
X   }
X if (! mailpid) return (0);
X 
X s = QueryMail("h");
X if (strncmp(s, "No applicable messages", 22) == 0) {
X    Bell(s);
X    writeTo(iw, " ");
X    writeTo(XtNameToWidget(toplevel, "topBox.textWindow.text"), " ");
X   } else {
X/*
X** find mail's idea of this folder's current message number
X*/
X    for (c = s; *c; c++)
X        if (*c == '>' && (c == s || *(c - 1) == '\n'))
X           break;
X/*
X** If the current message is marked new or unread, ensure as many of the new
X** message headers as possible are displayed in the index window (especially
X** the current one), else if the Show_Last resource is not false, select the
X** last message in the header.
X*/
X   p = c;					/* save position of current */
X   more_than_one = FALSE;			/* set a flag for new/unread */
X   if (*(c+1) == 'N' || *(c+1) == 'U') more_than_one = TRUE;
X   else if (XMail.Show_Last) {			/* find the last message */
X           if (*p == '>') *p = ' ';		/* erase the original marker */
X           if (c == s) {			/* if would've started @ One */
X              for (p = &s[strlen(s)-2];
X                   p > s && *p != '\n'; p--);
X              if (*p == '\n') p++;		/* go to last line of buffer */
X             } else {
X              for (;*++c && *(c+1) != 'N' && *(c+1) != 'U';) {
X                  if (! (c = strchr(p,'\n')))
X                     break;			/* don't go past end of buf */
X                  p = c + 1;
X                 }
X             }
X           for (c = p; *c && !isdigit(*c); c++);
X           if (*c)
X              sscanf(c, "%d", &msg_num);
X           sprintf(msgnum_str, "%d", msg_num);
X          }
X/*
X** mark the current message's index line
X*/
X   *p = '>'; *(p+1) = ' ';
X/*
X** Return the current message number.
X*/
X    msg_num = atoi(msgnum_str);
X/*
X** Write the header info to the index window buffer, replacing existing info.
X*/
X    writeTo(iw, s);
X/*
X** Ensure if we are seeing new or unread messages that as many as possible are
X** displayed in the index window, to reduce the amount of scrolling required
X** when reading(/deleting) them.
X*/
X    pos = p - s;
X    if (more_than_one)
X       XawTextSetInsertionPoint(iw, TextGetLastPos(iw));
X    XawTextSetInsertionPoint(iw, pos);
X   }
X XtFree(s);
X return(msg_num);
X} /* file_handler */
END_OF_FILE
if test 11898 -ne `wc -c <'handler.c'`; then
    echo shar: \"'handler.c'\" unpacked with wrong size!
fi
# end of 'handler.c'
fi
if test -f 'mail.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mail.c'\"
else
echo shar: Extracting \"'mail.c'\" \(12038 characters\)
sed "s/^X//" >'mail.c' <<'END_OF_FILE'
X/*
X * xmail - X window system interface to the mail program
X *
X * Copyright 1989 The University of Texas at Austin
X *
X * Author:	Po Cheung
X * Date:	March 10, 1989
X *
X * Permission to use, copy, modify, and distribute this software and
X * its documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation.  The University of Texas at Austin makes no 
X * representations about the suitability of this software for any purpose.  
X * It is provided "as is" without express or implied warranty.
X *
X * Copyright 1990 by National Semiconductor Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of National Semiconductor Corporation not
X * be used in advertising or publicity pertaining to distribution of the
X * software without specific, written prior permission.
X *
X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
X * OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X * PERFORMANCE OF THIS SOFTWARE.
X *
X * The following software modules were created and are Copyrighted by National
X * Semiconductor Corporation:
X *
X * 1. editMail: 
X * 2. sendMail: 
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X#include "global.h"
X#include <sys/wait.h>
X#include <sys/stat.h>
X
X#ifndef	DEFAULT_VISUAL
X#define	DEFAULT_VISUAL	"/usr/ucb/vi"
X#endif
X/*
X** @(#)editMail() - edit a mail message using the preferred editor
X**
X** Support is now provided for declaring the editor command as an xmail
X** resource, ala xrn.  If the resource ``xmail.editorCommand'' is defined,
X** it must contain an `sprintf'-able format string that provides for the
X** inclusion of both a display name and the name of the file to be edited.
X** If the resource declaration is not included, or does not contain the two
X** required percent-s (%s) formatting strings, xmail will use the VISUAL
X** resource.  If VISUAL is used, try to accommodate those editors (emacs,
X** xedit...) which start their own window in X11.  We know for a fact that
X** vi and ed variants do not invoke windows.  We assume any other editor
X** specification does.
X*/
Xvoid
XeditMail()
X{
X Display	*ad;
X char		*edit, *cp;
X char		*Argv[50];
X char		cmd[BUFSIZ];
X int		i, editMail_pid;
X int		status;
X static XEvent	event;
X
X
X bzero(cmd, BUFSIZ);
X
X ad  = XtDisplay(XtNameToWidget(toplevel, "topBox.statusWindow"));
X/*
X** If editorCommand resource exists, use it (format validated during initialize)
X*/
X if (XMail.editorCommand)
X    sprintf(cmd, XMail.editorCommand, ad->display_name, tmpName);
X else {
X    /*
X    ** Otherwise, default to the VISUAL method of starting things
X    */
X    if ((edit = GetMailEnv("VISUAL")) == NULL)
X         edit = XtNewString(DEFAULT_VISUAL);
X
X    if ((cp = strrchr(edit, '/')) == NULL) cp = edit;
X    else cp++;
X
X    if (strcmp(cp, "ed") == 0 ||
X        strcmp(cp,"red") == 0 ||
X        strcmp(cp, "ex") == 0 ||
X        strcmp(cp, "vi") == 0) {
X       sprintf(cmd,
X   "/usr/bin/X11/xterm -display %s -name XMail -title 'Message entry' -e %s %s",
X                     ad->display_name, edit, tmpName);
X      } else sprintf(cmd, "%s -display %s %s", edit, ad->display_name, tmpName);
X    XtFree(edit);
X   }
X
X editMail_pid = fork();
X
X switch (editMail_pid) {
X    case -1:			/* fork failed ... revert to a system call */
X         system(cmd);
X         break;
X    case 0:			/* child starts the message entry session */
X         for (i = 0, cp = cmd; i < 49 && *cp; i++) {
X             Argv[i] = cp++;		/* pull out each separate argument */
X             if (*Argv[i] == '"') {	/* if this is a "quoted string"... */
X                Argv[i] = cp++;
X                while (*cp && *cp != '"') cp++;
X                *cp++ = '\0';
X               } else
X             if (*Argv[i] == "'"[0]) {	/* or if it's a 'quoted string'... */
X                Argv[i] = cp++;
X                while (*cp && *cp != "'"[0]) cp++;
X                *cp++ = '\0';
X               }
X             else while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n') cp++;
X             if (*cp)			/* truncate each argument as needed */
X                *cp++ = '\0';
X            }
X         Argv[i] = NULL;
X
X         SetCursor(0);			/* restore cursor just before editing */
X
X         execvp(Argv[0], Argv);
X         perror("editMail: Failed to start the text editor");
X         _exit();
X         break;
X    default:			/* wait for child to finish before continuing */
X         while (wait3(&status, WNOHANG, NULL) != editMail_pid)
X               if (XPending(XtDisplay(toplevel)) > 0) {
X                  XNextEvent(XtDisplay(toplevel), &event);
X                  XtDispatchEvent(&event);
X                 }
X         break;
X   }
X} /* editMail */
X
X
X/*
X** @(#)readMail() - callback invoked every time input is pending on mail fd
X**
X** Calls QueryMail() to read all available data from mail file descriptor,
X** and passes output to parse() for analysis and appropriate action.
X*/
XXtInputCallbackProc
XreadMail(client_data, source, id)
Xcaddr_t   client_data;
Xint 	  *source;
XXtInputId *id;
X{
X parse(QueryMail(""));
X} /* readMail */
X
X
X/*
X** @(#)sendMail() - send a mail message to the indicated recipient(s)
X*/
X/* ARGSUSED */
Xvoid
XsendMail(parent)
XWidget	parent;
X{
X Arg		args[11];
X Widget		Popup, Layout, Box;
X Widget		lab1, lab2, lab3, lab4;
X Widget		To, Subject, Cclist, Bcc, Last;
X
X
X editMail();
X
X Popup = XtNameToWidget(toplevel, "topBox.commandPanel.Send.popup");
X
X if (! Popup) {
X    XtSetArg(args[0], XtNinput, True);
X    XtSetArg(args[1], XtNwidth, XMail.shellWidth - 2);
X    XtSetArg(args[2], XtNheight,
X           XMail.borderWidth*3 + XMail.buttonHeight*5 + 44);
X    Popup = XtCreatePopupShell("popup",transientShellWidgetClass,parent,args,3);
X
X    XtSetArg(args[0], XtNdefaultDistance, 2);
X    Layout = XtCreateManagedWidget("SubjCc", formWidgetClass, Popup, args, 1);
X
X    XtSetArg(args[0], XtNfromVert, NULL);
X    XtSetArg(args[1], XtNfromHoriz, NULL);
X    XtSetArg(args[2], XtNlabel, "To:");
X    XtSetArg(args[3], XtNborderWidth, 0);
X    XtSetArg(args[4], XtNfont, XMail.buttonFont);
X    XtSetArg(args[5], XtNheight, XMail.buttonHeight + XMail.borderWidth + 7);
X    XtSetArg(args[6], XtNwidth, XMail.buttonWidth);
X    XtSetArg(args[7], XtNjustify, XtJustifyLeft);
X    XtSetArg(args[8], XtNinternalHeight, 0);
X    XtSetArg(args[9], XtNinternalWidth, 1);
X    lab1 = XtCreateManagedWidget("SubjCc", labelWidgetClass, Layout, args, 10);
X
X    To = CreateInputWindow(Layout, "To", Recipient, BUFSIZ);
X
X    AddInfoHandler(To, SendMail_Info[0]);
X
X    XtSetArg(args[0], XtNfromVert, NULL);
X    XtSetArg(args[1], XtNfromHoriz, lab1);
X    XtSetValues(To, args, 2);
X
X    AddHelpText(To, To_Help);
X
X    XtSetArg(args[0], XtNfromVert, lab1);
X    XtSetArg(args[1], XtNfromHoriz, NULL);
X    XtSetArg(args[2], XtNlabel, "Subject:");
X    lab2 = XtCreateManagedWidget("SubjCc", labelWidgetClass, Layout, args, 10);
X
X    Subject = CreateInputWindow(Layout, "Subject", SubjBuf, BUFSIZ);
X
X    AddInfoHandler(Subject, SendMail_Info[1]);
X
X    XtSetArg(args[0], XtNfromVert, To);
X    XtSetArg(args[1], XtNfromHoriz, lab2);
X    XtSetValues(Subject, args, 2);
X
X    AddHelpText(Subject, Subject_Help);
X
X    XtSetArg(args[0], XtNfromVert, lab2);
X    XtSetArg(args[1], XtNfromHoriz, NULL);
X    XtSetArg(args[2], XtNlabel, "Cc:");
X    lab3 = XtCreateManagedWidget("SubjCc", labelWidgetClass, Layout, args, 10);
X
X    Cclist = CreateInputWindow(Layout, "Cc", CcBuf, BUFSIZ);
X
X    AddInfoHandler(Cclist, SendMail_Info[2]);
X
X    XtSetArg(args[0], XtNfromVert, Subject);
X    XtSetArg(args[1], XtNfromHoriz, lab3);
X    XtSetValues(Cclist, args, 2);
X
X    AddHelpText(Cclist, Cc_Help);
X
X    XtSetArg(args[0], XtNfromVert, lab3);
X    XtSetArg(args[1], XtNfromHoriz, NULL);
X    XtSetArg(args[2], XtNlabel, "Bcc:");
X    lab4 = XtCreateManagedWidget("SubjCc", labelWidgetClass, Layout, args, 10);
X
X    Bcc = CreateInputWindow(Layout, "Bcc", BccBuf, BUFSIZ);
X
X    AddInfoHandler(Bcc, SendMail_Info[3]);
X
X    XtSetArg(args[0], XtNfromVert, Cclist);
X    XtSetArg(args[1], XtNfromHoriz, lab4);
X    XtSetValues(Bcc, args, 2);
X
X    AddHelpText(Bcc, Bcc_Help);
X
X    XtSetArg(args[0], XtNfont, XMail.buttonFont);
X    XtSetArg(args[1], XtNheight, XMail.buttonHeight + XMail.borderWidth*2 + 4);
X    XtSetArg(args[2], XtNwidth, XMail.shellWidth - 2);
X    XtSetArg(args[3], XtNfromVert, lab4);
X    XtSetArg(args[4], XtNfromHoriz, NULL);
X    XtSetArg(args[5], XtNborderWidth, 0);
X    XtSetArg(args[6], XtNresize, False);
X    XtSetArg(args[7], XtNmin, args[1].value);
X    XtSetArg(args[8], XtNmax, args[1].value);
X    XtSetArg(args[9], XtNhSpace, 2);
X    XtSetArg(args[10],XtNvSpace, 2);
X    Box = XtCreateManagedWidget("Box", boxWidgetClass, Layout, args, 11);
X
X    XtSetArg(args[1], XtNheight, XMail.buttonHeight);
X    XtSetArg(args[2], XtNwidth,
X    (((XMail.shellWidth - 2) / 6) - XMail.borderWidth * 2) - 4);
X
X    lab1 = XtCreateManagedWidget("Autograph", commandWidgetClass, Box, args, 3);
X    XtAddCallback(lab1, XtNcallback, (XtCallbackProc) Autograph, (caddr_t) "A");
X    AddInfoHandler(lab1, Autograph_Info[0]);
X    AddHelpText(lab1, Sign_Help);
X
X    lab2 = XtCreateManagedWidget("autograph", commandWidgetClass, Box, args, 3);
X    XtAddCallback(lab2, XtNcallback, (XtCallbackProc) Autograph, (caddr_t) "a");
X    AddInfoHandler(lab2, Autograph_Info[1]);
X    AddHelpText(lab2, sign_Help);
X
X    lab1 = XtCreateManagedWidget("ReEdit", commandWidgetClass, Box, args, 3);
X    XtAddCallback(lab1,XtNcallback,(XtCallbackProc) ReEdit, (caddr_t)"ReEdit");
X    AddInfoHandler(lab1, Deliver_Info[1]);
X    AddHelpText(lab1, ReEdit_Help);
X
X    lab2 = XtCreateManagedWidget("Cancel", commandWidgetClass, Box, args, 3);
X    XtAddCallback(lab2, XtNcallback, (XtCallbackProc) Done, (caddr_t) "cancel");
X    AddInfoHandler(lab2, Deliver_Info[2]);
X    AddHelpText(lab2, Cancel_Help);
X
X    lab3 = XtCreateManagedWidget("Abort", commandWidgetClass, Box, args, 3);
X    XtAddCallback(lab3, XtNcallback, (XtCallbackProc) Done, (caddr_t) "Cancel");
X    AddInfoHandler(lab3, Deliver_Info[3]);
X    AddHelpText(lab3, Abort_Help);
X
X    Last = XtCreateManagedWidget("Deliver", commandWidgetClass, Box, args, 3);
X    XtAddCallback(Last, XtNcallback, (XtCallbackProc) Done, (caddr_t)"Deliver");
X    AddInfoHandler(Last, Deliver_Info[0]);
X    AddHelpText(Last, Deliver_Help);
X   }
X
X To = XtNameToWidget(Popup, "*To");
X writeText(To, Recipient, 0);
X XawTextSetInsertionPoint(To, TextGetLastPos(To));
X
X Subject = XtNameToWidget(Popup, "*Subject");
X writeText(Subject, SubjBuf, 0);
X XawTextSetInsertionPoint(Subject, TextGetLastPos(Subject));
X
X Cclist = XtNameToWidget(Popup, "*Cc");
X writeText(Cclist, CcBuf, 0);
X XawTextSetInsertionPoint(Cclist, TextGetLastPos(Cclist));
X
X Bcc = XtNameToWidget(Popup, "*Bcc");
X writeText(Bcc, BccBuf, 0);
X XawTextSetInsertionPoint(Bcc, TextGetLastPos(Bcc));
X
X SetXY(Popup, XtNameToWidget(toplevel, "topBox.commandPanel"), 0, 0);
X
X XtPopup(Popup, XtGrabNone);
X
X XWarpPointer(XtDisplay(toplevel), None, XtWindow(To), 0, 0, 0, 0, 10, 5);
X} /* sendMail */
X
X
X/*
X** @(#)writeMail() - Write s to mail, and flush the output.
X*/
Xvoid
XwriteMail(s) 
Xchar *s;
X{
X write(mail_fd, s, strlen(s));
X} /* writeMail */
END_OF_FILE
if test 12038 -ne `wc -c <'mail.c'`; then
    echo shar: \"'mail.c'\" unpacked with wrong size!
fi
# end of 'mail.c'
fi
if test -f 'utils.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'utils.c'\"
else
echo shar: Extracting \"'utils.c'\" \(13708 characters\)
sed "s/^X//" >'utils.c' <<'END_OF_FILE'
X/*
X * xmail - X window system interface to the mail program
X *
X * Copyright 1989 The University of Texas at Austin
X *
X * Author:	Po Cheung
X * Date:	March 10, 1989
X *
X * Permission to use, copy, modify, and distribute this software and
X * its documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation.  The University of Texas at Austin makes no 
X * representations about the suitability of this software for any purpose.  
X * It is provided "as is" without express or implied warranty.
X *
X * Copyright 1990 by National Semiconductor Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of National Semiconductor Corporation not
X * be used in advertising or publicity pertaining to distribution of the
X * software without specific, written prior permission.
X *
X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
X * OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X * PERFORMANCE OF THIS SOFTWARE.
X *
X * The following software modules were created and are Copyrighted by
X * National Semiconductor Corporation:
X *
X * 1. markIndex:
X * 2. SelectionNumber:
X * 3. SetCursor: and
X * 4. SetXY.
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X
X#include <ctype.h>
X#include "global.h"
X#include "patchlevel.h"
X#include "revtable.h"
X
X
X/*
X** @(#)Bell() - write a status message and (optionally) ring the terminal bell
X*/
Xvoid
XBell(msg)
XString		msg;
X{
X Arg		args[1];
X char		*p;
X char		buf[BUFSIZ];
X int		size;
X static int	worthy = 0;		/* only msgs with ending newline are */
X
X
X bzero(buf, BUFSIZ);
X size = strlen(msg);
X if (size >= BUFSIZ) size = BUFSIZ - 1;
X
X (void) strncpy(buf, msg, size);
X
X p = strchr(buf, '\n');			/* messages with newline get a bell */
X/*
X** Because we have now added enter/leave window event information messages,
X** we must play a slight game with incoming messages, to prevent any error
X** messages from a menu selection failure or status messages from a command
X** button being overwritten by the subsequent event info messages produced
X** when the menu popup is dismissed or the command completes.  To do this,
X** we make the bell worthy-ness flag static, and only replace a message after
X** first seeing a non-default status message, which will reset the worthy-ness
X** flag, but otherwise be ignored.  When the first non-default, non-error
X** message comes in, simply reset our bell worthy-ness flag and return, leaving
X** the previous error message still intact.  This means, to ensure seeing the
X** default message, first send a blank line to reset the worthy-ness flag.
X*/
X if (! XMail.Show_Info)			/* if NOT showing info flags always */
X    worthy = 0;				/* reset the bell worthy-ness flag */
X else {
X    if (worthy && p == NULL) {		/* if last was but this ain't urgent */
X       if (strcmp(buf, Default_Status_Info))	/* and not the default info */
X          worthy = 0;			/* reset the bell worthy-ness flag */
X       return;				/* ignore event info if menu errored */
X      }					/* by leaving previous error message */
X   }
X
X if (size == 0)				/* if intent was just to reset flag */
X    return;
X
X if (p != NULL) {			/* Only display first line of output */
X    *p = '\0';				/* (no new line at end of label) */
X    worthy = 1;				/* this message is worthy of a bell */
X   }
X
X XtSetArg(args[0], XtNlabel, (XtArgVal) buf);	/* show this message text */
X XtSetValues(XtNameToWidget(toplevel, "topBox.statusWindow"), args, ONE);
X
X if (worthy && XMail.bellRing)		/* ring bell if not silenced by user */
X    XBell(XtDisplay (toplevel), 33);
X
X SetCursor(0);				/* restore default cursors */
X} /* Bell */
X
X
X/*
X** @(#)figureWidth() - determine the figure width of the specified font
X*/
Xint
XfigureWidth(font)
XXFontStruct *font;
X{
X Atom		_XA_FIGURE_WIDTH;
X unsigned long	width = 0;
X
X
X _XA_FIGURE_WIDTH = XInternAtom(XtDisplay(toplevel), "FIGURE_WIDTH", FALSE);
X if ((_XA_FIGURE_WIDTH != NULL) &&
X    ((! XGetFontProperty(font, _XA_FIGURE_WIDTH, &width)) || (width == 0)))
X    if (font->per_char && font->min_char_or_byte2 <= '$' &&
X                          font->max_char_or_byte2 >= '$')
X       width = font->per_char['$' - font->min_char_or_byte2].width;
X    else
X       width = font->max_bounds.width;
X
X return(width);
X} /* end - figureWidth */
X
X
X/*
X** @(#)markIndex() - add or remove a tag from the start of a mail header line
X*/
Xvoid
XmarkIndex(s)
Xchar	*s;
X{
X char			buf[3];
X Arg			args[1];
X Cardinal		size;
X String			c, p;
X Widget			iw;
X XawTextBlock		text;
X XawTextPosition	pos, old;
X
X
X iw = XtNameToWidget(toplevel, "topBox.indexWindow");
X pos = XawTextGetInsertionPoint(iw);	/* save the current insertion point */
X strcpy(buf, s);			/* make a copy of our marking string */
X if (pos != 0) {			/* if not already at front of buffer */
X    text.firstPos = 0;			/* find the start of this index line */
X    text.length   = 1;
X    text.ptr      = "\n";
X    text.format   = FMT8BIT;
X    if ((old = XawTextSearch(iw, XawsdLeft, &text)) != XawTextSearchError)
X       pos = old + 1;
X    else pos = 0;
X   }
X
X if (buf[0] == '>') {			/* if mark is for 'current' pointer */
X    XtSetArg(args[0], XtNstring, &p);	/* retrieve the current index buffer */
X    XtGetValues(iw, args, ONE);
X    XawAsciiSourceFreeString(iw);	/* release the memory from GetValues */
X
X    if (strlen(p) > pos + 1)
X       if (p[pos + 1] == 'S')		/* keep the Save marker if it exists */
X          if (strlen(buf) > 1)
X             buf[1] = '\0';
X
X    for (c = p; *c; c++)
X        if (*c == '>' && (c == p || *(c - 1) == '\n')) {
X           old = c - p;			/* if found, remove the old '>' mark */
X           text.firstPos = 0;
X           text.length   = 1;
X           text.ptr      = " ";
X           text.format   = FMT8BIT;
X           XawTextReplace(iw, old, old + 1, &text);
X           break;
X          }
X   }
X
X size = strlen(buf);			/* now write the specified marker */
X old = (buf[0] == '>') ? pos : pos + 1;
X text.firstPos = 0;
X text.length   = size;
X text.ptr      = buf;
X text.format   = FMT8BIT;
X XawTextReplace(iw, old, old + size, &text);
X
X XawTextSetInsertionPoint(iw, pos);	/* reset our actual insertion point */
X} /* markIndex */
X
X
X/*
X** @(#)SelectionNumber() - Get mail index number from line position
X*/
Xint
XSelectionNumber(undeleting)
Xint	undeleting;
X{
X Arg			args[1];
X Widget			iw = XtNameToWidget(toplevel, "topBox.indexWindow");
X String			c, str = NULL;
X int			selection_number = 0;
X 
X
X XtSetArg(args[0], XtNstring, &str);
X XtGetValues(iw, args, ONE);
X
X for (c = str; *c; c++)
X     if (*c == '>' && (c == str || *(c - 1) == '\n'))
X        break;
X
X if (*c && (! undeleting || *(c + 1) == 'D')) {
X    for (; *c && !isdigit(*c); c++);
X    sscanf(c, "%d", &selection_number);
X   }
X
X XawAsciiSourceFreeString(iw);		/* release GetValues memory */
X
X return(selection_number);
X} /* SelectionNumber */
X
X
X/* ARGSUSED */
X/*
X** @(#)SetCursor() - sets the wait cursor or restores the default
X*/
Xvoid
XSetCursor(waiting)
Xint	waiting;		/* a non-zero value sets the wait cursor(s) */
X{
X Widget		tb, iw, tw, fw;
X
X
X tb = XtNameToWidget(toplevel, "topBox");
X iw = XtNameToWidget(tb, "indexWindow");
X tw = XtNameToWidget(tb, "textWindow.text");
X fw = XtNameToWidget(tb, "commandPanel.fileWindow");
X
X if (waiting) {
X    XDefineCursor(XtDisplay(tb), XtWindow(tb), waitC);
X    XDefineCursor(XtDisplay(iw), XtWindow(iw), waitC);
X    XDefineCursor(XtDisplay(tw), XtWindow(tw), waitC);
X    XDefineCursor(XtDisplay(fw), XtWindow(fw), waitC);
X   } else {
X    XDefineCursor(XtDisplay(tb), XtWindow(tb), None);
X    XDefineCursor(XtDisplay(iw), XtWindow(iw), xtermC);
X    XDefineCursor(XtDisplay(tw), XtWindow(tw), xtermC);
X    XDefineCursor(XtDisplay(fw), XtWindow(fw), xtermC);
X   }
X XFlush(XtDisplay(toplevel));
X} /* SetCursor */
X
X
X/*
X** @(#)SetXY() - Set relative window coordinates including specified offset
X*/
Xvoid
XSetXY(target, reference, X_offset, Y_offset)
XWidget	target, reference;
Xint	X_offset, Y_offset;
X{
X Arg		args[2];
X Display	*dpy = XtDisplay(reference);
X 
X Window		dumy;
X int		x, y;
X
X
X XTranslateCoordinates(dpy, XtWindow(reference),
X                       RootWindow(dpy, DefaultScreen(dpy)),
X                       X_offset, Y_offset, &x, &y, &dumy);
X /*
X ** Keep window within root window borders (don't place it off-screen)
X */
X if (! XtIsRealized(target))
X    XtRealizeWidget(target);		/* to get width and height values */
X
X if (x + target->core.width > RootWidth)
X    x = RootWidth - target->core.width - 2;
X
X if (y + target->core.height > RootHeight)
X    y = RootHeight - target->core.height - 2;
X
X XtSetArg(args[0], XtNx, x);
X XtSetArg(args[1], XtNy, y);
X XtSetValues(target, args, TWO);
X} /* end - SetXY */
X
X
X/*
X** @(#)TextGetLastPos() - return value of text insert position
X*/
XXawTextPosition
XTextGetLastPos(w)
XWidget w;
X{
X TextWidget ctx = (TextWidget) w;
X return (ctx->text.lastPos);
X}
X
X
X/*
X** @(#)UpdateTitleBar() - replace information in the title bar title
X*/
Xvoid
XUpdateTitleBar(msg)
Xchar *msg;
X{
X char		message[BUFSIZ];
X Arg		args[1];
X Widget		w;
X
X
X sprintf(message, "%s%d - %s", TITLE, PATCHLEVEL, msg);
X
X w = XtNameToWidget(toplevel, "topBox.titleBar.title");
X
X XtSetArg(args[0], XtNlabel, (XtArgVal) message);
X XtSetValues(w, args, ONE);
X 
X w = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail.Newmail_menu.menu.inc");
X if (w)
X    XtSetSensitive(w, In_System_Folder());
X} /* UpdateTitleBar */
X
X
X/*
X** @(#)writeText() - write text to the current string source
X*/
Xvoid
XwriteText(w, s, do_append)
XWidget	w;
Xchar   *s;
Xint	do_append;
X{
X XawTextBlock		text;
X XawTextPosition	startPos, endPos;
X
X
X text.firstPos = 0;
X text.length   = strlen(s);
X text.ptr      = s;
X text.format   = FMT8BIT;
X
X endPos = TextGetLastPos(w) + (do_append ? 0 : 1);
X startPos = (do_append ? endPos : 0);
X
X XawTextReplace(w, startPos, endPos, &text);
X
X XawTextSetInsertionPoint(w, TextGetLastPos(w));
X} /* writeText */
X
X
X/*
X** @(#)writeTo() - replace the current text in the specified widget
X**                 Also look for an X-Face: header, and if found, display.
X*/
Xvoid
XwriteTo(w, buf)
XWidget	w;
Xchar	*buf;
X{
X Arg		args[2];
X Display	*dpy = XtDisplay(w);
X Widget		fw;
X Window		rw;
X char		cb[1024], fb[2048], *ptr;
X int		i, n, x, y;
X
X if (buf && *buf) {
X    XtSetArg(args[0], XtNstring, buf);
X    XtSetValues(w, args, ONE);
X
X#ifdef X_FACE
X    if (! (fw = XtNameToWidget(XtParent(w), "face")))
X       return;
X
X    /*
X    ** First, unmap any current picture.
X    **
X    ** Look for a line containing an 'X-Face:' header, followed by 72
X    ** characters of compressed data.  The second and any subsequent lines
X    ** will contain an initial space (which is ignored), followed by 79
X    ** characters of compressed data.  The last line may contain fewer than 79
X    ** characters.
X    **
X    ** The X-Face: header and any immediate whitespace (tabs or spaces) will be
X    ** removed, and the remaining line placed in the internal buffer (minus
X    ** any trailing newline).  On subsequent lines, initial whitespace will be
X    ** removed, and the remainder of the data appended to the buffer (minus any
X    ** trailing newline).
X    **
X    ** A blank line, a line without an initial whitespace character, or the
X    ** end of the input buffer will signify the end of the X-Face data.  That
X    ** buffer will then be uncompressed, and if the data was valid, displayed.
X    */
X
X    if (XtIsManaged(fw))
X       XtUnmanageChild(fw);
X
X    for (ptr = buf; *ptr; ptr++) {
X        if (*ptr == '\n' || strncmp(ptr, "Status:", 7) == 0)
X           return;
X
X        if (strncmp(ptr, "X-Face:", 7) == 0 ) break;
X
X        for (; *ptr && *ptr != '\n'; ptr++);
X       }
X
X    if (! *ptr || strncmp(ptr, "X-Face:", 7) != 0) return;
X
X    bzero(fb, 2048);
X    for (i = 0, ptr += 7; *ptr; ptr++) {
X        if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n')
X           fb[i++] = *ptr;
X        if (*ptr == '\n' && *(ptr+1) && *(ptr+1) != ' ' && *(ptr+1) != '\t')
X           break;
X       }
X
X    if (uncompface(fb) >= 0) {
X       bzero(cb, 1024);
X       for (i = n = 0;i < 1024;) {
X           if (! sscanf(&fb[n], "%i%n", &x, &y)) break;
X           cb[i++] = revtable[(x >> 8) & 0xFF];
X           cb[i++] = revtable[x & 0xFF];
X           n += y;
X           while (fb[n] && (fb[n]==',' || fb[n]=='\n')) n++;
X          }
X
X       XtSetArg(args[0], XtNwidth, NULL);
X       XtGetValues(w, args, 1);
X       n = args[0].value - 48;
X       if (n < 0) n = 0;
X
X       XtSetArg(args[0], XtNbitmap, NULL);
X       XtGetValues(fw, args, 1);
X       if (args[0].value != None)
X          XFreePixmap(dpy, args[0].value);
X
X       rw = RootWindow(dpy, DefaultScreen(dpy));
X       XtSetArg(args[0], XtNbitmap, XCreateBitmapFromData(dpy, rw, cb, 48, 48));
X       XtSetArg(args[1], XtNhorizDistance, n);
X       XtSetValues(fw, args, TWO);
X
X       XtManageChild(fw);
X      }
X#endif
X   }
X} /* writeTo */
END_OF_FILE
if test 13708 -ne `wc -c <'utils.c'`; then
    echo shar: \"'utils.c'\" unpacked with wrong size!
fi
# end of 'utils.c'
fi
echo shar: End of archive 3 \(of 11\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources-x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list