[comp.sources.x] v06i042: xmail -- Mail front end for X11, Part02/06

michael@parns.nsc.com (Michael C. Wagnitz) (03/22/90)

Submitted-by: michael@parns.nsc.com (Michael C. Wagnitz)
Posting-number: Volume 6, Issue 42
Archive-name: xmail/part02

#! /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 2 (of 6)."
# Contents:  actions.c callMail.c callbacks.c icon.mail
# Wrapped by michael@harley on Tue Mar 20 15:28:04 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'actions.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'actions.c'\"
else
echo shar: Extracting \"'actions.c'\" \(26216 characters\)
sed "s/^X//" >'actions.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 TORTIOUS 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. DoAutograph:
X *  2. DoCmd:
X *  3. DoDone:
X *  4. DoNothing:
X *  5. DoReply:
X *  6. DoSave:
X *  7. DoSelected:
X *  8. Folder:
X *  9. Iconify:
X * 10. MyNotify:
X * 11. NextField:
X * 12. PrintMsg:
X * 13. SetAliases:
X * 14. SetCursor:
X * 15. SetDirectory:
X * 16. SetFolders:
X * 17. SetHelp:
X * 18. SetPopup: and
X * 19. SetSelect.
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X
X#include "global.h"
X#include <math.h>
X#include <ctype.h>
X#ifdef SUNOS_4
X#include <dirent.h>
X#else
X#include <sys/dir.h>
X#endif
X
X
X/*
X** @(#)DeleteLine() - Deletes the entire current line from the fileWindow.
X**                    Simulates the action of the KILL character (ctrl-U).
X*/
X/* ARGSUSED */
XXtActionProc
XDeleteLine(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextBlock    	textblock;
X XtTextPosition 	lastPos;
X Cardinal	 	i;
X
X lastPos = TextGetLastPos(w);
X textblock.firstPos = 0;
X textblock.length   = 0;
X textblock.ptr      = "";
X
X for (i = lastPos; i > StartPos && FileBuf[i - 1] != '\n'; i--);
X XtTextReplace(w, i, lastPos, &textblock);
X Normalize(w);
X} /* DeleteLine */
X
X
X/*
X** @(#)DeleteWord() - Erases the preceding word in the fileWindow buffer.
X** Simulates the action of the WERASE character (ctrl-W).
X*/
X/* ARGSUSED */
XXtActionProc
XDeleteWord(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextBlock    	textblock;
X XtTextPosition	lastPos;
X Cardinal	 	i, j;
X
X textblock.firstPos = 0;
X textblock.length   = 0;
X textblock.ptr      = "";
X
X lastPos = TextGetLastPos(w); 
X for (i = lastPos; i > StartPos && FileBuf[i - 1] == ' '; i--);
X for (j = i; i > StartPos && FileBuf[i - 1] != ' '; i--);
X XtTextReplace(w, i, lastPos, &textblock);
X Normalize(w);
X} /* DeleteWord */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoAutograph() - invoke the Autograph() callback from an action routine
X*/
XXtActionProc
XDoAutograph(w, event, params, num_params)
XWidget		w;	/* unused */
XXEvent		*event;	/* unused */
XString		*params;
XCardinal	*num_params;
X{
X Autograph(w, *params, *params);
X} /* DoAutograph */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoCmd() - send (multi-word) command to mail
X*/
XXtActionProc
XDoCmd(w, event, params, num_params)
XWidget		w;	/* unused */
XXEvent		*event;	/* unused */
XString		*params;
XCardinal	*num_params;
X{
X int	i, n;
X
X    strcpy(Command, "");
X    for (i = 0; i < *num_params; i++) {
X        strcat(Command, params[i]);
X        strcat(Command, " ");
X       }
X    if (i)
X    Command[strlen(Command)-1] = '\0';	/* Drop the last trailing blank */
X    strcat(Command, "\n");
X
X if (mailpid)				/* If connections are okay,... */
X    writeMail(Command);
X else if (strcmp(Command, "file %\n") != 0)
X         Bell("No mail\n");		/* If not 'new mail', complain */
X      else {
X         for (n = 0; n < mailargc; n++) {
X             if (strcmp(mailargv[n], "-f") == 0) {
X                for (i = n + 2; i <= mailargc;) mailargv[n++] = mailargv[i++];
X                mailargc -= 2;		/* throw away an folder argument */
X                n -= 2;			/* re-examine new mailargv value */
X               }
X            }
X         callMail(mailargc, mailargv);	/* restart the mail connections */
X         strcpy(Command, "Start");	/* Let em know we've re-started */
X         UnsetNewmail(w, NULL, NULL);
X   }
X} /* DoCmd */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoDone() - invoke the Done() callback from an action routine
X*/
XXtActionProc
XDoDone(w, event, params, num_params)
XWidget		w;	/* unused */
XXEvent		*event;	/* unused */
XString		*params;
XCardinal	*num_params;
X{
X Done(w, *params, *params);
X} /* DoDone */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoNothing() - dummy action for unwanted button(s)
X*/
XXtActionProc
XDoNothing(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X return;
X} /* DoNothing */
X
X
X/*
X** @(#)DoReply() - call Reply() CallbackProc from an ActionProc
X*/
X/* ARGSUSED */
XXtActionProc
XDoReply(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X caddr_t	client_data;
X caddr_t	call_data;
X
X client_data = params[0];
X Reply(w, client_data, call_data);
X} /* DoReply */
X
X
X/*
X** @(#)DoSave() - call Save() CallbackProc from an ActionProc
X*/
X/* ARGSUSED */
XXtActionProc
XDoSave(w, event, params, num_params)
XWidget		w;
XXEvent		*event;
XString		*params;
XCardinal	*num_params;
X{
X caddr_t	client_data;
X caddr_t	call_data;
X
X client_data = params[0];
X Save(w, client_data, call_data);
X} /* DoSave */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoSelected() - execute specified command using selected message number
X*/
XXtActionProc
XDoSelected(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextPosition	pos;
X int		num;
X
X
X if (! mailpid)
X    Bell("No mail\n");
X else {
X    if (num_params) {
X       pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X       num = PositionToMsgNumber(pos);	/* no current message returns zero */
X       if (num &&
X           *params[0] != 'n' && *params[0] != '-' && *params[0] != 'u')
X          sprintf(Command, "%s %d\n", params[0], num);
X       else sprintf(Command, "%s\n", params[0]);
X       writeMail(Command);
X      }
X   }
X} /* DoSelected */
X
X
X/*
X** @(#)Folder() - change folders - must have specified folder name or error
X*/
X/* ARGSUSED */
XXtActionProc
XFolder(w, event, params, num_params)
XWidget		w;
XXEvent		*event;
XString		*params;
XCardinal	*num_params;
X{
X XtTextPosition pos;
X char		*p;
X Cardinal	n;
X
X pos = TextGetLastPos(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow"));
X if ((n = pos - StartPos) <= 0)
X    Bell("Specify a folder name (in the [File: ] box) first\n");
X else {
X    FileBuf[StartPos + n] = '\0';
X    p = FileBuf + StartPos;
X    if (mailpid) {
X       sprintf(Command, "file %s\n", p);
X       writeMail(Command);
X      } else {
X/*
X** We must first re-establish contact with the mail utility.
X** This time, we indicate a specific mail folder to process.
X*/
X       XMail.MFileName = XtNewString(p);
X       for (n = 0; n < mailargc; n++)
X           if (strcmp(mailargv[n], "-f") == 0) {
X              mailargv[++n] = XMail.MFileName;
X              break;
X             }
X       if (n == mailargc) {		/* if not previously specified */
X          mailargv[mailargc++] = "-f";
X          mailargv[mailargc++] = XMail.MFileName;
X         }
X       callMail(mailargc, mailargv);
X       strcpy(Command, "Start");	/* Let em know we've re-started */
X      }
X   }
X} /* Folder */
X
X
X/*
X** @(#)InsertSpace() - prevents user from deleting past the File: prompt.
X** It checks the last position of text, and if it matches StartPos, inserts
X** a space so that delete-previous-character() can only delete the space.
X*/
X/* ARGSUSED */
XXtActionProc
XInsertSpace(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextBlock    textblock;
X XtTextPosition lastPos;
X
X lastPos = TextGetLastPos(w);
X XtTextSetInsertionPoint(w, lastPos);
X if (lastPos == StartPos) {
X    textblock.firstPos = 0;
X    textblock.length   = 1;
X    textblock.ptr      = " ";
X    XtTextReplace(w, lastPos, lastPos, &textblock);
X   }
X} /* InsertSpace */
X
X
X/* ARGSUSED */
X/*
X** @(#)Iconify() - request window iconification
X*/
XXtActionProc
XIconify(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X#ifndef X11R3
X Display		*disp;
X
X disp = XtDisplay(toplevel);
X
X if (! XIconifyWindow(disp, XtWindow(toplevel), DefaultScreen(disp)))
X#endif
X    XBell(XtDisplay(toplevel), 33);
X}
X
X
X/* ARGSUSED */
X/*
X** @(#)MyNotify() - call widget callbacks with passed parameter
X*/
XXtActionProc
XMyNotify(w, event, params, num_params)
XWidget		w;
XXEvent		*event;
XString		*params;
XCardinal	*num_params;
X{
X XtCallCallbacks(w, XtNcallback, *params);
X} /* MyNotify */
X
X
X/*
X** @(#)NextField() - warps pointer to next field in the Send command window.
X** This allows carriage return to focus attention on the next data requirement.
X*/
X/* ARGSUSED */
XXtActionProc
XNextField(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X String	name;
X Widget	shell;
X
X
X if (strcmp(w->core.name, "Cc") == 0)
X    name = "To"; else
X if (strcmp(w->core.name, "To") == 0)
X    name = "Subject"; else
X    name = "Cc";
X
X if ((shell = XtNameToWidget(XtParent(w), name)) != NULL)
X    XWarpPointer(XtDisplay(toplevel), None, XtWindow(shell), 0,0,0,0, 10, 5);
X
X} /* NextField */
X
X
X/*
X** @(#)PrintMsg() - sends the selected mail message to the system printer
X*/
X/* ARGSUSED */
XXtActionProc
XPrintMsg(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextPosition	pos;
X int		num;
X
X if (! mailpid)
X    Bell("No mail\n");
X else {
X    pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X    num = PositionToMsgNumber(pos);	/* no current message returns zero */
X    if (! num) Bell("No messages to print.\n");
X    else {
X       sprintf(Command, "| %d \"lpr -p\"\n", num);
X    writeMail(Command);
X   }
X   }
X} /* PrintMsg */
X
X
X/*
X** @(#)SetAliases() - create a menu list of alias names
X*/
X/* ARGSUSED */
XXtActionProc
XSetAliases(w, event, params, num_params)
XWidget		w;
XXEvent		*event;
XString		*params;
XCardinal	*num_params;
X{
X Arg		args[MAXARGS];
X Cardinal	i, j, k, n, x, y;
X Display        *ad;
X Widget		bw, lw, popup, hold, left;
X Window         aw, dumy, root;
X
X static String l_Trans = "<Btn3Up>:	MenuPopdown(aliasList)";
X
X static String fl_trans = "<EnterWindow>: set() \n\
X			   <LeaveWindow>: unset() \n\
X			   <Btn3Up>:      notify() MenuPopdown(aliasList)";
X
X static XtCallbackRec fl_callbacks[] = {
X        { (XtCallbackProc) GetAliasName, NULL },
X        { NULL,          NULL }
X       };
X
X
X popup = XtNameToWidget(w, "aliasList");
X
X if (! popup || popup->core.being_destroyed) {
X    XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(l_Trans));
X    popup = XtCreatePopupShell("aliasList",overrideShellWidgetClass,w,args,1);
X
X    (void) alias(NULL);			/* ensure our aliases list is set */
X/*
X** determine proper label width by finding longest name length
X*/
X    i = j = k = 0;
X    for (n = 0; aliases[n]; n++)
X        if ((k = strlen(aliases[n]->name)) > j) {
X           j = k;
X           i = n;
X          }
X
X    if (j == 0) { 				/* If no alias names exist */
X       XtSetArg(args[0], XtNwidth, 1);		/* set these so MenuPopup */
X       XtSetArg(args[1], XtNheight, 1);		/* won't complain about a */
X       XtSetValues(popup, (ArgList) args, 2);	/* zero width or height  */
X       XtDestroyWidget(popup);	/* it would be nice if MenuPopup() cared */
X      } else {
X/*
X** Make equal width command buttons which contain the alias names
X*/
X       XtSetArg(args[0], XtNdefaultDistance, 1);
X       lw = XtCreateManagedWidget("list", formWidgetClass, popup, args, ONE);
X
X       bw = left = NULL;
X       XtSetArg(args[0], XtNwidth, XTextWidth(TextFontStr, aliases[i]->name, j) + 14);
X       XtSetArg(args[1], XtNfont, TextFontStr);
X       XtSetArg(args[2], XtNtranslations, XtParseTranslationTable(fl_trans));
X       XtSetArg(args[3], XtNcallback, fl_callbacks);
X
X       i = j = 0;
X       if (n > 10) {			/* If more than ten aliases try to */
X          j = (int) sqrt((double)n);	/* make list approximately square. */
X          i = (int) n / j;
X          if (i * j < n) i++;
X          if (j > 3) i++;
X          if (j > 4) i++;
X          if (j > 5) i = 21;		/* try to keep box inside main shell */
X         }
X
X       for (n = 0; aliases[n]; n++) {
X           XtSetArg(args[4], XtNlabel, aliases[n]->name);
X           XtSetArg(args[5], XtNfromHoriz, left);
X           XtSetArg(args[6], XtNfromVert, bw);
X           bw = XtCreateManagedWidget("button",commandWidgetClass,lw,args,7);
X
X           if (i) {			/* post names in a rectangular list */
X              if (n % i == 0) hold = bw;
X              if ((n+1) % i == 0) {
X                 left = hold;
X                 bw = NULL;
X                }
X             }
X          }
X      }	/* end - if some alias names exist */
X   }	/* end - if popup does not exist or was being destroyed */
X/*
X** If the menu exists, pop it up, after setting the x,y coordinates
X*/
X if (popup->core.being_destroyed)
X    XBell(XtDisplay(toplevel), 33);
X else {
X    if (! XtIsRealized(popup))
X       XtRealizeWidget(popup);
X    aw = XtWindow(w);
X    ad = XtDisplay(w);
X    n = XMail.buttonHeight / 2;
X    root = RootWindow(ad, DefaultScreen(ad));
X    XTranslateCoordinates(ad, aw, root, XMail.menuX, n, &x, &y, &dumy);
X    XtSetArg(args[0], XtNx, x);
X    XtSetArg(args[1], XtNy, y);
X    XtSetValues(popup, (ArgList) args, 2);
X   }
X} /* SetAliases */
X
X
X/* ARGSUSED */
X/*
X** @(#)SetCursor() - sets wait cursor or restores default
X*/
XXtActionProc
XSetCursor(w, event, params, num_params)
XWidget		w;
XXEvent		*event;			/* unused */
XString		*params;		/* unused */
XCardinal	*num_params;		/* any param sets wait cursor */
X{
X Cursor		tmpC = None;		/* no parameter restores default */
X
X
X if (*num_params)
X    tmpC = waitC;
X
X XDefineCursor(XtDisplay(w), XtWindow(w), tmpC);
X
X if (*num_params == 1)			/* flush output if only one parameter */
X    XFlush(XtDisplay(toplevel));
X} /* SetCursor */
X
X
X/*
X** @(#)SetFolders() - create a menu list of folder names
X*/
X/* ARGSUSED */
XXtActionProc
XSetFolders(w, event, params, num_params)
XWidget		w;
XXEvent		*event;
XString		*params;
XCardinal	*num_params;
X{
X Arg		args[MAXARGS];
X Display        *ad;
X Window         aw, dumy, root;
X Widget		lw, above, this_one, to_left, popup;
X Cardinal	x, y, n;
X char		trans[BUFSIZ], tmp[BUFSIZ], *p, *List = NULL;
X char		foldir[BUFSIZ], *GetMailEnv(), *getenv();
X int		foldlen, List_size, newline = 0;
X DIR		*dirp;
X
X#ifdef SUNOS_4
X struct dirent	*dp;
X#else
X struct direct	*dp;
X#endif
X
X
X static String dir_Trans = "\
X	<Btn1Down>: SetCursor(True) SetDirectory(%s,%s,%s) SetCursor()";
X
X static String l_Trans = "<Btn3Up>:	MenuPopdown(popupList)";
X
X static String fl_trans = "<EnterWindow>: set() \n\
X        <LeaveWindow>:  unset() \n\
X        <Btn3Up>:       notify() MenuPopdown(popupList)";
X
X static XtCallbackRec fl_callbacks[] = {
X        { (XtCallbackProc) GetFolderName, NULL },
X        { NULL,          NULL }
X       };
X
X
X popup = XtNameToWidget(w, "popupList");
X
X if (! popup || popup->core.being_destroyed) {
X    p = GetMailEnv("folder");
X    if (p && strlen(p)) {
X       sprintf(foldir, "%s/%s/", getenv("HOME"), p);
X       XtFree(p);
X      } else sprintf(foldir, "%s/", getenv("HOME"));
X    foldlen = strlen(foldir);
X
X    XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(l_Trans));
X    popup = XtCreatePopupShell("popupList",overrideShellWidgetClass,w,args,1);
X
X    if (mailpid)
X       List = QueryMail("folders");
X    else {
X       if ((dirp = opendir(foldir)) == NULL)
X          XtError("SetFolder: Can't access mail folder directory");
X/*
X** allocate one block to 'List' to begin with
X*/
X       List_size = BUFSIZ;
X       List = XtMalloc(List_size);
X       strcpy(List, "");
X       x = 0;
X       for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
X           if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
X              if (strlen(List) + strlen(dp->d_name) + 2 > List_size) {
X                 List_size += BUFSIZ;
X                 List = XtRealloc(List, List_size);
X                }
X              strcat(List, " ");
X              strcat(List, dp->d_name);
X              if (++x % 6 == 0) {
X                 x = 0;
X                 strcat(List, "\n");
X                }
X             }
X       List = XtRealloc(List, strlen(List) + 1);
X       closedir(dirp);
X      }
X/*
X** determine proper label width by finding longest word length
X*/
X    strcpy(trans, "");
X    for (x = 0, p = List; *p; p++) {
X        if (*p == ' ' || *p == '\n' || *p == '\t') {
X           if (x) {
X              tmp[x] = '\0';
X              x = 0;
X              if (strlen(trans) < strlen(tmp))
X                 strcpy(trans, tmp);
X             }
X          } else tmp[x++] = *p;
X       }
X
X    if (x) {
X       tmp[x] = '\0';
X       if (strlen(trans) < strlen(tmp))
X          strcpy(trans, tmp);
X      }
X
X    if ((n = strlen(trans)) == 0) {	/* if there are no mail folders */
X       n = 0;					/* set a dummy width and */
X       XtSetArg(args[n], XtNwidth, 1); n++;	/* height so MenuPopup() */
X       XtSetArg(args[n], XtNheight, 1); n++;	/* won't complain about */
X       XtSetValues(popup, (ArgList) args, n);	/* zero width or height */
X
X       XtDestroyWidget(popup);	/* it would be nice if MenuPopup() cared */
X      } else {
X       XtSetArg(args[0], XtNdefaultDistance, 1);
X       lw = XtCreateManagedWidget("list", formWidgetClass, popup, args, ONE);
X/*
X** Now, make equal width command buttons which contain the folder names
X*/
X       XtSetArg(args[0], XtNwidth, XTextWidth(TextFontStr, trans, n) + 14);
X       XtSetArg(args[1], XtNfont, TextFontStr);
X       XtSetArg(args[2], XtNtranslations, XtParseTranslationTable(fl_trans));
X       XtSetArg(args[3], XtNcallback, fl_callbacks);
X
X       above = this_one = to_left = NULL;
X       for (x = 0, p = List; *p; p++) {
X           if (*p == '\n') {
X              newline = 1;
X             }
X           if (*p == ' ' || *p == '\n' || *p == '\t') {
X              if (x) {
X                 tmp[x] = '\0';
X/*
X** If this 'folder' is really a directory, mark it with a trailing slash '/'
X*/
X                 foldir[foldlen] = '\0';
X                 strcat(foldir, &tmp[1]);
X                 if ((dirp = opendir(foldir)) != NULL) {
X                    tmp[x++] = '/';
X                    tmp[x] = '\0';
X                   }
X                 n = 4;
X                 XtSetArg(args[n], XtNlabel, tmp);			n++;
X                 XtSetArg(args[n], XtNfromHoriz, to_left);		n++;
X                 if (! to_left) XtSetArg(args[n], XtNfromVert, above);	n++;
X   
X                 this_one = XtCreateManagedWidget("listbutton", commandWidgetClass,
X                                                lw, args, n);
X                 if (to_left == NULL) above = this_one;
X                 to_left = this_one;
X                 if (newline) {
X                    newline = 0;
X                    to_left = NULL;
X                   }
X                 x = 0;
X/*
X** If this 'folder' is a directory, add a button to popup a menu of filenames.
X*/
X                 if (dirp != NULL) {
X                    closedir(dirp);
X                    sprintf(trans, dir_Trans, &tmp[1], foldir, "0");
X                    XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
X                   }
X                }
X             } else {
X               if (x == 0) tmp[x++] = '+';	/* start folder names with a 'plus' */
X               tmp[x++] = *p;
X          }
X       }
X
X    if (x) {
X       tmp[x] = '\0';
X       foldir[foldlen] = '\0';
X       strcat(foldir, &tmp[1]);
X       if ((dirp = opendir(foldir)) != NULL) {
X          tmp[x++] = '/';
X          tmp[x] = '\0';
X         }
X       n = 4;
X       XtSetArg(args[n], XtNlabel, tmp);				n++;
X       XtSetArg(args[n], XtNfromHoriz, to_left);			n++;
X       if (! to_left) XtSetArg(args[n], XtNfromVert, above);		n++;
X
X       this_one = XtCreateManagedWidget("listbutton", commandWidgetClass,
X                                                lw, args, n);
X       if (dirp != NULL) {
X          closedir(dirp);
X          sprintf(trans, dir_Trans, &tmp[1], foldir, "0");
X          XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
X         }
X      }
X   }
X   }	/* end - if some trans strlen */
X/*
X** If folders menu exists, pop it up, after setting x,y coordinates
X*/
X if (popup->core.being_destroyed) {
X    Bell("No mail folders exist\n");
X   } else {
X    if (! XtIsRealized(popup))		/* see if folder list is small */
X       XtRealizeWidget(popup);		/* enough to fit if anchored at */
X
X    n = 3 * (XMail.buttonWidth + 12);	/* folder button instead of cmdWin */
X    if (popup->core.width + n <= XMail.shellWidth) {
X       aw = XtWindow(w);
X       ad = XtDisplay(w);
X       n = XMail.buttonHeight / 2;
X      } else {
X       aw = XtWindow(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"));
X       ad = XtDisplay(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"));
X n = XMail.commandMinHeight / 2;
X      }
X    root = RootWindow(ad, DefaultScreen(ad));
X
X XTranslateCoordinates(ad, aw, root, XMail.menuX, n, &x, &y, &dumy);
X
X n = 0;
X XtSetArg(args[n], XtNx, x);			n++;
X XtSetArg(args[n], XtNy, y);			n++;
X    XtSetValues(popup, (ArgList) args, n);
X   }
X
X XtFree(List);
X
X} /* SetFolders */
X
X
X/*
X** @(#)SetHelp() - set named string source as text for and popup help window.
X*/
X/* ARGSUSED */
XXtActionProc
XSetHelp(w, event, params, num_params)
XWidget w;				/* unused */
XXEvent *event;				/* unused */
XString *params;
XCardinal *num_params;
X{
X Arg		args[3];
X Widget		tw;
X Window		aw, dumy;
X Display	*ad;
X int		indx, status, x, y, scn;
X
X
X if (*num_params != 1)
X    XtError("Wrong parameter count passed to SetHelp()");
X
X for (indx = 0; HelpNames[indx]; indx++)
X     if (strcmp(params[0], HelpNames[indx]) == 0) break;
X
X if (HelpNames[indx]) {
X    XtTextSetSource(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), "helpWindow"), HelpStrings[indx], (XtTextPosition) 0);
X/*
X** Position help relative to textWindow
X*/
X    tw  = WidgetOf(WidgetOf(toplevel, "vpane"), "textWindow");
X    aw  = XtWindow(tw);
X    ad  = XtDisplay(tw);
X    scn = DefaultScreen(ad);
X
X    XTranslateCoordinates(ad, aw, RootWindow(ad, scn), XMail.helpX, XMail.helpY,
X                          &x, &y, &dumy);
X
X    XtSetArg(args[0], XtNx, x);
X    XtSetArg(args[1], XtNy, y);
X    XtSetValues(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), args, 2);
X
X    XtPopup(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), XtGrabNone);
X   }
X} /* SetHelp */
X
X
X/*
X** @(#)SetPopup() - place named popup at menuX, menuY relative to Widget w.
X*/
X/* ARGSUSED */
XXtActionProc
XSetPopup(w, event, params, num_params)
XWidget w;
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X Widget		shell;
X Window		aw, dumy;
X Display	*ad;
X String		p;
X int		x, y, scn;
X Arg		args[2];
X
X
X if (*num_params == 0)
X    XtError("No name parameter passed to SetPopup().");
X
X p = params[0];
X
X if ((shell = XtNameToWidget(w, p)) == NULL)
X    XtError("Shell name passed to SetPopup() not found in popup list.");
X
X if (! XtIsRealized(shell))
X    XtRealizeWidget(shell);		/* to get width and height values */
X/*
X** Position menus relative to current window
X*/
X aw  = XtWindow(w);
X ad  = XtDisplay(w);
X scn = DefaultScreen(ad);
X
X XTranslateCoordinates(ad, aw, RootWindow(ad, scn), XMail.menuX, XMail.menuY,
X                       &x, &y, &dumy);
X/*
X** Keep popup menu within root window borders (don't place it off-screen)
X*/
X if (x + shell->core.width > RootWidth)
X    x = RootWidth - shell->core.width;
X
X if (y + shell->core.height > RootHeight)
X    y = RootHeight - shell->core.height;
X
X XtSetArg(args[0], XtNx, x);
X XtSetArg(args[1], XtNy, y);
X XtSetValues(shell, (ArgList)args, 2);
X} /* SetPopup */
X
X
X/* ARGSUSED */
X/*
X** @(#)SetSelect() - highlight the index number of the selected message
X*/
XXtActionProc
XSetSelect(w, event, params, num_params)
XWidget w;
XXEvent *event;		/* unused */
XString *params;		/* unused */
XCardinal *num_params;	/* unused */
X{
X XClientMessageEvent	cm;
X XtTextPosition pos, left, right;
X String	s;
X
X
X pos = XtTextGetInsertionPoint(w);
X
X for (s = IndexBuf + pos; s > IndexBuf && *(s - 1) != '\n'; s--);
X
X pos = s - IndexBuf;
X/*
X** use XSendEvent to remove any prior selection highlight
X*/
X cm.type = ClientMessage;
X cm.display = XtDisplay(w);
X cm.message_type = XInternAtom(XtDisplay(w), "KILL_SELECTION", FALSE);
X cm.window = XtWindow(w);
X cm.format = 32;
X cm.data.l[0] = XA_PRIMARY;
X
X XSendEvent(XtDisplay(w), cm.window, TRUE, NoEventMask, &cm);
X
X for (; *s && !isdigit(*s); s++);
X left = s - IndexBuf;
X for (; *s && isdigit(*s); s++);
X right = s - IndexBuf;
X
X XtTextSetSelection(w, left, right);
X
X XtTextSetInsertionPoint(w, pos);
X} /* SetSelect */
X
X
X/*
X** @(#)Quit() - call DoQuit() CallbackProc from the Quit ActionProc
X*/
X/* ARGSUSED */
XXtActionProc
XQuit(w, event, params, num_params)
XWidget		w;	/* unused */
XXEvent		*event;	/* unused */
XString		*params;
XCardinal	*num_params;
X{
X caddr_t	client_data;
X caddr_t	call_data;
X
X client_data = params[0];
X DoQuit(w, client_data, call_data);
X} /* Quit */
END_OF_FILE
if test 26216 -ne `wc -c <'actions.c'`; then
    echo shar: \"'actions.c'\" unpacked with wrong size!
fi
# end of 'actions.c'
fi
if test -f 'callMail.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'callMail.c'\"
else
echo shar: Extracting \"'callMail.c'\" \(5706 characters\)
sed "s/^X//" >'callMail.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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X * PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X
X#include	<sgtty.h>
X#include	"global.h"
X
XFILE   	    	*mailfp = NULL;		/* file pointer to mail */
Xint    	    	mail_fd;		/* mail process master tty id */
Xint    	    	mailpid;		/* mail process id */
Xint    	    	mailInputId;		/* mail input id */
X
Xstatic char 	*pty = "/dev/pty??";	/* master side of pseudo-terminal */
Xstatic char 	*tty = "/dev/tty??";	/* slave side of pseudo-terminal */
X
X/*
X *  Xmail talks to mail through a pseudo terminal which is a pair of master
X *  and slave devices: /dev/pty?? and /dev/tty??, where ?? goes from p0 to
X *  qf (system dependent).  The pty is opened for both read and write.
X */
X/*
X** @(#)openMaster() - open master side of pipe
X*/
Xstatic int
XopenMaster()
X{
X int  i, master; 
X char c;
X
X for (c='p'; c<='s'; c++) {
X     pty[8] = c;
X     for (i=0; i<16; i++) {
X         pty[9] = "0123456789abcdef"[i];
X         if ((master = open(pty, O_RDWR)) != -1) 
X            return (master); 
X        }
X    }
X fprintf(stderr, "xmail: all ptys in use\n");
X exit(1);
X} /* openMaster */
X
X
X/*
X** @(#)openSlave() - open slave side of pipe
X*/
Xstatic int
XopenSlave()
X{
X int slave;
X
X tty[8] = pty[8];
X tty[9] = pty[9];
X if ((slave = open(tty, O_RDWR)) != -1) {
X    return (slave);
X   } else {
X    fprintf(stderr, "open: cannot open slave pty %s", tty);
X    exit(1);
X   }
X} /* openSlave */
X
X
X/*
X** @(#)callMail() - fork child to execute mail and attach to xmail input
X*/
X/* ARGSUSED */
Xvoid
XcallMail(argc, argv)
Xint argc;
Xchar *argv[];
X{
X struct sgttyb Sgtty;
X int           master;			/* file descriptor of master pty */
X int           slave;			/* file descriptor to slave pty */
X char          *Mailpgm,		/* name of executable Mailpgm */
X               errmsg[BUFSIZ];
X
X Mailpgm = (char *) getenv("XMAILER");	/* first looks up env var */
X if (Mailpgm == NULL)
X    Mailpgm = XtNewString(XMAILER);
X  
X master = openMaster();
X slave = openSlave();
X
X ioctl(slave, TIOCGETP, &Sgtty);
X Sgtty.sg_flags &= ~(ECHO|CRMOD);	/* no echo, no NL to CR */
X ioctl(slave, TIOCSETP, &Sgtty);
X
X mailpid = fork();
X if (mailpid == -1) {
X    perror("Cannot fork mail process");
X    exit(1);
X   } else if (mailpid) { 
X             /* 
X              * Parent : close the slave side of pty
X              *          close stdin and stdout
X              *          set the mail file descriptor to nonblocking mode
X              *          open file pointer with read/write access to mail
X              *          set unbuffered mode
X              *          register mail input with X
X              */
X             close(slave);
X             if (master != 0)		/* if we're restarting, master IS 0 */
X                close(0);
X             close(1);
X             fcntl(master, F_SETFL, FNDELAY);
X             mail_fd = master;			/* use descriptor for reads */
X             mailfp = fdopen(master, "r+");	/* need mailfp for fputs */
X             setbuf(mailfp, NULL);
X             mailInputId = XtAddInput(master, XtInputReadMask, readMail, NULL);
X            } else { 
X             /* 
X              * Child : close master side of pty
X              *         redirect stdin, stdout, stderr of mail to pty
X              *         unbuffer output data from mail
X              *         exec mail with arguments
X              */
X             close(master);
X             dup2(slave, 0);
X             dup2(slave, 1);
X             dup2(slave, 2);
X             if (slave > 2)
X                 close(slave);
X             fcntl(1, F_SETFL, FAPPEND);
X             setbuf(stdout, NULL);
X             argv[0] = Mailpgm;
X             execvp(Mailpgm, argv);
X             sprintf(errmsg, "callMail: Cannot call %s", Mailpgm);
X             perror(errmsg);
X             exit(1);
X            }
X} /* callMail */
END_OF_FILE
if test 5706 -ne `wc -c <'callMail.c'`; then
    echo shar: \"'callMail.c'\" unpacked with wrong size!
fi
# end of 'callMail.c'
fi
if test -f 'callbacks.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'callbacks.c'\"
else
echo shar: Extracting \"'callbacks.c'\" \(17314 characters\)
sed "s/^X//" >'callbacks.c' <<'END_OF_FILE'
X/*
X * xmail - X window system interface to the mail program
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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X * PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X
X#include "global.h"
X#include <sys/wait.h>
X#include <sys/stat.h>
X
X
X/*
X** @(#)Autograph() - Add user's Sign or sign autograph to outgoing mail
X**                   Then make button insensitive, to prevent multiple calls.
X*/
X/* ARGSUSED */
XXtCallbackProc
XAutograph(w, C, call_data)
XWidget w;
Xcaddr_t C;
Xcaddr_t call_data;
X{
X FILE	*fp;
X String	autograph;
X char	tmp[BUFSIZ];
X int	n;
X
X
X if (strcmp("Autograph", w->core.name) == 0)
X    XtSetSensitive(w, False);	/* Don't let us be pressed more than once */
X else XtSetSensitive(XtParent(XtParent(XtParent(w))), False);  /* (of popup) */
X
X strcpy(tmp, "Sign");		/* Default will be to use Sign autograph, */
X if (C && *C == 'a')		/* but if asked use their sign autograph. */
X    strcpy(tmp, "sign");
X autograph = GetMailEnv(tmp);
X if (autograph) {
X    for (n = 0; n < BUFSIZ - 2 && *autograph; autograph++)
X        if (*autograph == '\\' && *(autograph + 1) == 'n') {
X           tmp[n++] = '\n';	/* Replace newline strings with a character */
X           autograph++;
X          } else tmp[n++] = *autograph;
X
X    if (tmp[n - 1] != '\n')	/* make sure msg ends with a newline */
X       tmp[n++] = '\n';
X    tmp[n] = '\0';
X
X    if ((fp = fopen(tmpName, "a")) != NULL) {
X       fwrite(tmp, sizeof(* tmp), strlen(tmp), fp);
X       fclose(fp);
X      }
X    XtFree(autograph);
X   }
X} /* Autograph */
X
X
X/*
X** @(#)Done() - Send composed message - if closure data says "Deliver"
X*/
X/* ARGSUSED */
XXtCallbackProc
XDone(w, closure, call_data)
XWidget w;
Xcaddr_t closure;
Xcaddr_t call_data;
X{
X Widget		shell;
X FILE		*fp;
X char		*p, *record, *folder, *getenv();
X char		From[BUFSIZ], Copy[BUFSIZ], s[BUFSIZ];
X struct stat	st_buf;
X
X
X for (shell = w;
X      strcmp(shell->core.name, "popup");
X      shell = XtParent(shell));
X XtDestroyWidget(shell);		/* remove our popup prompt box */
X/*
X** first, prepare the header information (in a second temporary file)
X*/
X strcat(tmpName, "_");
X if ((fp = fopen(tmpName, "w")) != NULL) {
X    if (*Recipient)
X       fprintf(fp, "To: %s\n", alias(Recipient));
X
X    if (*SubjBuf)
X       fprintf(fp, "Subject: %s\n", SubjBuf);
X
X    if (*InReply)
X       fprintf(fp, "%s\n", InReply);
X
X    if (*CcBuf)
X       fprintf(fp, "Cc: %s\n", alias(CcBuf));
X
X    fprintf(fp, "\n");			/* separate header from text */
X    fclose(fp);
X   }
X tmpName[strlen(tmpName) - 1] = '\0';	/* Drop our marker for now */
X
X if (strcmp(closure, "Deliver") == 0) {
X    /*
X    ** mail header information and text in temporary file using sendmail
X    */
X    if (*Recipient && (*SubjBuf ||
X       (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X       sprintf(s, "cat %s_ %s | /usr/lib/sendmail -toi -om 2> /dev/null", tmpName, tmpName);
X       system(s);
X/*
X** If user has set 'record' in their .mailrc, add a message copy to that file
X*/
X       if (record = GetMailEnv("record")) {
X          p = folder = NULL;
X          if (*record == '/' || (p = GetMailEnv("outfolder")) == NULL ||
X                              (folder = GetMailEnv("folder")) == NULL) {
X             strcpy(Copy, record);
X             if (p) XtFree(p);
X            } else {
X             if (*folder == '/') {
X                if (*record != '+')
X                   sprintf(Copy, "%s/%s", folder, record);
X                else
X                   sprintf(Copy, "%s/%s", folder, &record[1]);
X               } else {
X                if (*record != '+')
X                   sprintf(Copy, "%s/%s/%s", getenv("HOME"), folder, record);
X                else
X                   sprintf(Copy,"%s/%s/%s",getenv("HOME"),folder,&record[1]);
X               }
X             XtFree(folder);
X             XtFree(p);
X            }
X          sprintf(From, "From %s `date`", getenv("USER"));
X          sprintf(s, "echo \"%s\" >> %s;cat %s_ %s >> %s 2> /dev/null; echo \"\" >> %s",
X                              From, Copy, tmpName, tmpName, Copy, Copy);
X          system(s);
X          XtFree(record);
X         }
X      } else {
X       if (! *Recipient)
X          Bell("No recipient specified\n");
X       else
X          Bell("No subject and no message\n");
X      }
X   } else {
X    if (*closure == 'c') {	/* save any partial message in our dead file */
X       if ((record = GetMailEnv("DEAD")) == NULL)
X          sprintf(Copy, "%s/dead.letter", getenv("HOME"));
X       else {
X          if (*record == '/')
X             strcpy(Copy, record);
X          else if (*record != '+')	/* default path is home directory */
X                  sprintf(Copy, "%s/%s", getenv("HOME"), record);
X               else	/* dead letters will never be legal mail messages */
X                  sprintf(Copy, "%s/%s", getenv("HOME"), &record[1]);
X          XtFree(record);
X         }
X       if (*Recipient && (*SubjBuf ||
X          (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X          sprintf(s, "cat %s_ %s >> %s 2> /dev/null", tmpName, tmpName, Copy);
X          system(s);
X          sprintf(s, "Canceled letter appended to %s\n", Copy);
X          Bell(s);
X         } else Bell("Nothing to save in your dead letter box\n");
X      }
X   }
X/*
X** remove any message text that may have been created
X*/
X sprintf(s, "rm -f %s_ %s", tmpName, tmpName);
X system(s);
X} /* Done */
X
X
X/*
X** @(#)DoIt() - send command - passed via client_data argument - to mail
X*/
X/* ARGSUSED */
XXtCallbackProc
XDoIt(w, closure, call_data)
XWidget w;
Xcaddr_t closure;
Xcaddr_t call_data;
X{
X int	i, n;
X
X
X    sprintf(Command, "%s\n", closure);
X if (mailpid)				/* If connections are okay,... */
X    writeMail(Command);
X else if (strcmp(Command, "file %\n") != 0 && strcmp(Command, "inc\n") != 0)
X         Bell("No mail\n");		/* But if no new mail, complain */
X      else {
X         for (n = 0; n < mailargc; n++) {
X             if (strcmp(mailargv[n], "-f") == 0) {
X                for (i = n + 2; i <= mailargc;) mailargv[n++] = mailargv[i++];
X                mailargc -= 2;		/* throw away any folder argument */
X                n -= 2;			/* re-examine new mailargv value */
X               }
X            }
X         callMail(mailargc, mailargv);	/* restart the mail connections */
X         strcpy(Command, "Start");	/* Let em know we've re-started */
X         UnsetNewmail(w, closure, call_data);
X   }
X} /* DoIt */
X
X
X/*
X** @(#)DoPrint() - Call the PrintMsg action routine from a callback
X*/
X/* ARGSUSED */
XXtCallbackProc
XDoPrint(w, closure, call_data)
XWidget	w;
Xcaddr_t closure;
Xcaddr_t	call_data;
X{
X PrintMsg(w, NULL, NULL, NULL);
X} /* DoPrint */
X
X
X/*
X** @(#)DoQuit() - Terminate xmail after first closing mail connection
X*/
X/* ARGSUSED */
XXtCallbackProc
XDoQuit(w, closure, call_data)
XWidget w;
Xcaddr_t closure;
Xcaddr_t call_data;
X{
X union wait	status;
X Display	*dpy = XtDisplay(toplevel);
X
X if (mailpid) {
X    sprintf(Command, "%s\n", closure);
X    writeMail(Command);
X    wait3(&status, WNOHANG, NULL);
X   }
X XtDestroyWidget(toplevel);
X XCloseDisplay(dpy);
X exit(0);
X} /* DoQuit */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoWith() - send client_data command to mail with selected msg number
X*/
XXtCallbackProc
XDoWith(w, client_data, call_data)
XWidget w;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
X XtTextPosition pos;
X int		num;
X
X if (! mailpid)
X    Bell("No mail\n");
X else {
X    pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X    num = PositionToMsgNumber(pos);	/* no current message returns zero */
X    if (num) sprintf(Command, "%s %d\n", client_data, num);
X    else sprintf(Command, "%s \n", client_data);
X    writeMail(Command);
X   }
X} /* DoWith */
X
X
X/*
X** @(#)GetAliasName() - retrieve alias name from button label
X*/
X/* ARGSUSED */
XXtCallbackProc
XGetAliasName(w, client_data, call_data)
XWidget	w;
Xcaddr_t	client_data, call_data;
X{
X Arg		args[1];
X String		alias_name;
X Widget		shell;
X
X
X XtSetArg(args[0], XtNlabel, &alias_name);
X XtGetValues(w, (ArgList) args, 1);
X
X shell = XtParent(XtParent(XtParent(w)));
X
X if (TextGetLastPos(shell))
X    writeText(shell, ", ", 1);
X
X writeText(shell, alias_name, 1);
X} /* GetAliasName */
X
X
X/*
X** @(#)GetFolderName() - retrieve full folder name from button labels
X*/
X/* ARGSUSED */
XXtCallbackProc
XGetFolderName(w, client_data, call_data)
XWidget	w;
Xcaddr_t	client_data, call_data;
X{
X Arg		args[1];
X Cardinal	k, n, x, indx;
X String		folder_name;
X Widget		shell;
X char		tmp[BUFSIZ], buf[BUFSIZ];
X
X
X XtSetArg(args[0], XtNlabel, &folder_name);
X XtGetValues(w, (ArgList) args, 1);
X
X if (! call_data)				/* just a simple label name */
X    sprintf(buf, "File: %s", folder_name);
X else {						/* multiple stack of names */
X    strcpy(tmp, "");
X    shell = w;
X    sscanf(call_data, "%d", &n);		/* using the nesting depth */
X
X    for (x = 1, k = (n * 2) + n - 1; k; k--) {
X        shell = shell->core.parent;		/* travel up the widget tree */
X        if (++x == 3) {				/* when we get to a label... */
X           x = 0;
X           strcpy(buf, shell->core.name);	/* stuff each label name in */
X           strcat(buf, tmp);			/* front of previous labels */
X           strcpy(tmp, buf);			/* to build a complete path */
X          }
X       }
X    sprintf(buf, "File: +%s%s", tmp, folder_name);
X   }
X writeText(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow"), buf, 0);
X} /* GetFolderName */
X
X
X/*
X** @(#)Reply() - send a reply to the author of the selected message
X**               include its text and/or copy the other recipients, if asked.
X*/
X/* ARGSUSED */
XXtCallbackProc
XReply(w, client_data, call_data)
XWidget w;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
X Cardinal	*num_params;
X FILE		*fp;
X Position	pos;
X String		*params, p, q, r, txt, author, subject, others, date, reference;
X XEvent		*event;
X int		erasable = 0;
X 
X
X txt = author = subject = others = date = reference = "";
X if (*client_data != 's') {
X    if ((fp = fopen(tmpName, "w")) == NULL)
X       Bell("xmail: Cannot open temp file for writing\n");
X
X    pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X    sprintf(Command, "P %d", PositionToMsgNumber(pos));
X    txt = QueryMail(Command);
X    if (fp) {
X       switch (*client_data) {
X          case 'S':
X               fputs("---------- Begin Forwarded Message ----------\n", fp);
X               if (! fwrite(txt, sizeof(*txt), strlen(txt), fp))
X                      Bell("xmail: Could not write to temp file\n");
X               fputs("----------- End Forwarded Message -----------\n", fp);
X               break;
X          case 'R':
X          case 'A':
X#ifdef SUNOS_4
X               if ((p = GetMailEnv("indentprefix")) != NULL)
X                  erasable = 1;
X               else
X#endif
X                  p = "\t";
X               for (q = r = txt; *r;) {
X                   for (; *r && *r != '\n'; r++);
X                       if (*r == '\n') {	/* For each line of insert */
X                          *r = '\0';		/* temporarily mark off eos, */
X                          fputs(p, fp);		/* write our indent prefix, */
X                          fputs(q, fp);		/* this line of insert text, */
X                          fputs("\n", fp);	/* and our missing newline, */
X                          *r = '\n';		/* and replace for later use */
X                          q = ++r;
X                         }
X                  }
X               if (erasable)
X                  XtFree(p);
X               break;
X         } /* end - switch on client_data */
X      } /* end - if file is open */
X/*
X** strip author, subject, and Carbon copy information from the selected message
X*/
X    for (p = txt; *p; p++) {
X        if (strcmp(p, "") == 0 || strncmp(p, "Status:", 7) == 0) break;
X
X        if (strncmp(p, "Return-Path:", 12) == 0) {
X           author = p + 14;
X           for (p = author; *p && *p != '>'; p++);
X           if (*p) *p++ = '\0';
X           for (; *p && *p != '\n'; p++);
X          }
X
X        else if (strncmp(p, "Date:", 5) == 0) {
X           date = p + 6;
X           for (p = date; *p && *p != '\n'; p++);
X           if (*p) *p = '\0';
X          }
X
X        else if (strncmp(p, "From:", 5) == 0) {
X           reference = p + 6;
X           for (p = reference; *p && *p != '\n'; p++);
X           if (*p) *p = '\0';
X          }
X
X        else if (strncmp(p, "Subject:", 8) == 0) {
X           subject = p + 9;
X           for (p = subject; *p && *p != '\n'; p++);
X           if (*p) *p = '\0';
X          }
X
X        else if (strncmp(p, "Cc:", 3) == 0) {
X           others = p + 4;
X           for (p = others; *p && *p != '\n'; p++);
X           if (*p) *p = '\0';
X          }
X        else for (; *p && *p != '\n'; p++);
X       } /* end - for all of message body */
X
X    if (*client_data != 'a' && *client_data != 'A')
X       others = "";	/* If not [rR]eplyall, make sender enter any Cc: */
X
X    if (fp) fclose(fp);
X
X    XtFree(txt);
X   } /* end - if client_data does not equal 's' */
X
X if (*client_data != 'S' && *client_data != 's')
X    strcpy(Recipient, author);
X
X strcpy(InReply, "");
X if (*client_data != 's' && *reference && *date) {
X    r = (*client_data == 'S') ? "Forwarding" : "In-Reply-To";
X    sprintf(InReply, "%s: Mail from '%s' dated %s", r, reference, date);
X   }
X
X if (*subject) {
X    strcpy(SubjBuf, "");
X    if (strncmp(subject, "Re: ", 4) != 0)
X       strcat(SubjBuf, "Re: ");
X    strcat(SubjBuf, subject);
X   }
X
X strcpy(CcBuf, others);
X
X sendMail(w);
X} /* Reply */
X
X
X/*
X** @(#)Save() - (or copy) a message to specified folder or mbox
X*/
X/* ARGSUSED */
XXtCallbackProc
XSave(w, cmd, call_data)
XWidget w;
Xcaddr_t cmd;
Xcaddr_t call_data;
X{
X char		*p, *q, *getenv();
X Cardinal	num, n;
X Position	pos;
X
X
X if (! mailpid)
X    Bell("No mail\n");
X else {
X pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X num = PositionToMsgNumber(pos);	/* no current message returns zero */
X
X if (*cmd == 'C' || *cmd == 'S' || *cmd == 'W' || num == 0) {
X    if (num) {
X       sprintf(Command, "%s %d\n", cmd, num);
X      } else {
X       sprintf(Command, "%s \n", cmd);
X      }
X   } else {
X    if ((n = TextGetLastPos(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow")) - StartPos) > 0) {
X       FileBuf[StartPos + n] = '\0';
X       p = FileBuf + StartPos;
X       sprintf(Command, "%s %d %s\n", cmd, num, p);
X      } else {
X/*
X** If no specified filename, use the mbox pointer.  We MUST include it here,
X** because specifying the message number for the action would be interpreted
X** as a filename, if we don't append one.
X*/
X       if ((p = GetMailEnv("MBOX"))) {
X          if (*p == '+') {		/* add folder full path to name */
X             if ((q = GetMailEnv("folder")) == NULL)
X                sprintf(Command,"%s %d %s/%s\n", cmd, num, getenv("HOME"), ++p);
X             else {
X                sprintf(Command,"%s %d %s/%s/%s\n", cmd, num, getenv("HOME"), q, ++p);
X                XtFree(q);
X               }
X            } else sprintf(Command,"%s %d %s\n",cmd, num, p);
X          XtFree(p);
X         } else sprintf(Command, "%s %d %s/mbox\n", cmd, num, getenv("HOME"));
X            }
X         }
X    writeMail(Command);
X   }
X} /* Save */
X
X
X/*
X** @(#)SetNewmail - Highlight Newmail button to attract user attention
X*/
X/* ARGSUSED */
XXtCallbackProc
XSetNewmail(w, client_data, call_data)
XWidget	w;			/* unused */
Xcaddr_t	client_data;		/* unused */
Xcaddr_t	call_data;		/* unused */
X{
X Widget	cw;
X
X if (! Highlighted) {
X    cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "Newmail");
X    XSetWindowBackgroundPixmap(XtDisplay(toplevel), XtWindow(cw), hatch);
X    XtUnmapWidget(cw);
X    XtMapWidget(cw);
X    Highlighted = 1;
X   }
X} /* SetNewmail */
X
X
X/*
X** @(#)UnsetNewmail - Remove Newmail button highlighting
X*/
X/* ARGSUSED */
XXtCallbackProc
XUnsetNewmail(w, client_data, call_data)
XWidget	w;			/* unused */
Xcaddr_t	client_data;		/* unused */
Xcaddr_t	call_data;		/* unused */
X{
X Widget	cw;
X
X if (Highlighted) {
X    cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "Newmail");
X    XSetWindowBackground(XtDisplay(toplevel), XtWindow(cw), cw->core.background_pixel);
X    XtUnmapWidget(cw);
X    XtMapWidget(cw);
X    Highlighted = 0;
X   }
X} /* UnsetNewmail */
END_OF_FILE
if test 17314 -ne `wc -c <'callbacks.c'`; then
    echo shar: \"'callbacks.c'\" unpacked with wrong size!
fi
# end of 'callbacks.c'
fi
if test -f 'icon.mail' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'icon.mail'\"
else
echo shar: Extracting \"'icon.mail'\" \(3855 characters\)
sed "s/^X//" >'icon.mail' <<'END_OF_FILE'
X/*
X * xmail - X window system interface to the mail program
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.  National Semiconductor
X * Corporation makes no representations about the suitability of this software
X * for any purpose.  It is provided "as is" without express or implied warranty.
X *
X * NATIONAL SEMICONDUCTOR CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X#define mail_width 56
X#define mail_height 56
X
Xstatic char mail_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
X 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
X 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf0, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x30, 0x03, 0x00,
X 0x00, 0x00, 0x00, 0x07, 0x30, 0x06, 0x00, 0x00, 0x00, 0x80, 0x01, 0x30,
X 0x06, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0xe0,
X 0x1f, 0xb0, 0x07, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xf0, 0x06, 0x00, 0x00,
X 0x00, 0xb8, 0xee, 0x70, 0x06, 0x00, 0x00, 0x00, 0x5c, 0xd7, 0x31, 0x06,
X 0x00, 0x00, 0x00, 0xae, 0xae, 0x39, 0x06, 0x00, 0x00, 0x00, 0x56, 0x5d,
X 0x3f, 0x06, 0x00, 0x00, 0x00, 0x8a, 0xb4, 0x37, 0x06, 0x00, 0x00, 0x00,
X 0x46, 0x64, 0x33, 0x06, 0x00, 0x00, 0x00, 0x22, 0xc4, 0x33, 0x06, 0x00,
X 0x00, 0x00, 0x12, 0x84, 0x33, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x04, 0x33,
X 0x06, 0x00, 0xff, 0xff, 0xfa, 0x07, 0x33, 0xf6, 0xff, 0x00, 0x00, 0x0a,
X 0x00, 0x33, 0x06, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x03, 0x03, 0x00, 0x00,
X 0x00, 0x3a, 0x80, 0x83, 0x01, 0x00, 0x00, 0x00, 0x7a, 0x40, 0xc3, 0x00,
X 0x00, 0x00, 0x00, 0xfa, 0xa0, 0x63, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x51,
X 0x33, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x0b, 0x3b, 0x00, 0x00, 0x00, 0x00,
X 0x3a, 0x06, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x37, 0x00, 0x00,
X 0x00, 0x00, 0x0a, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x31,
X 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02,
X 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x6a, 0x31, 0x00, 0x00, 0x00,
X 0x00, 0xaa, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x00, 0xba, 0x2a, 0x31, 0x00,
X 0x00, 0x00, 0x00, 0x2a, 0x29, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
X 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00,
X 0x52, 0x15, 0x31, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x2a, 0x31, 0x00, 0x00,
X 0xee, 0x28, 0x82, 0x02, 0x31, 0x20, 0x11, 0x88, 0x22, 0x12, 0x11, 0x2d,
X 0x29, 0x00, 0x29, 0xc8, 0xa2, 0x0b, 0xad, 0x40, 0x9a, 0xc4, 0x4a, 0xc6,
X 0x86, 0x87, 0x4e, 0x1a, 0xcb, 0x67, 0x07, 0xc2, 0x7e, 0xee, 0x3f, 0xbf,
X 0xdc, 0x8e, 0xc7, 0xd2, 0x33, 0xa5, 0x2a, 0x8f, 0x1d, 0x63, 0x72, 0xb9,
X 0x7b, 0xfd, 0x72, 0xf9, 0x7f, 0x4e, 0xe7, 0xd4 };
END_OF_FILE
if test 3855 -ne `wc -c <'icon.mail'`; then
    echo shar: \"'icon.mail'\" unpacked with wrong size!
fi
# end of 'icon.mail'
fi
echo shar: End of archive 2 \(of 6\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dan
-----------------------------------------------------------
		    O'Reilly && Associates
		argv@sun.com / argv@ora.com
	   632 Petaluma Ave, Sebastopol, CA 95472 
     800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
    Opinions expressed reflect those of the author only.