v13i051: xmail, Part09/11

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


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

#! /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 9 (of 11)."
# Contents:  callbacks.c
# Wrapped by michael at harley on Fri May  3 13:35:53 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'callbacks.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'callbacks.c'\"
else
echo shar: Extracting \"'callbacks.c'\" \(32817 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 TORTUOUS 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 "xmailregex.h"
X#include <sys/wait.h>
X#include <sys/stat.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <pwd.h>
X
Xextern	char	otherBuf[BUFSIZ];
X
X/*
X** @(#)Autograph() - Add user's Sign or sign autograph to outgoing mail
X**                   Then make button insensitive, to prevent multiple calls.
X**                   If requested autograph signature does not exist, tell user.
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 strcpy(tmp, "Sign");		/* Default action is to use Sign autograph */
X if (*C == 'a') tmp[0] = 's';
X autograph = GetMailEnv(tmp);	/* First, see if an autograph exists */
X
X if (! autograph) {
X    strcpy(tmp, "Cannot find a 'Sign'ature in your .mailrc file\n");
X    if (*C == 'a') tmp[15] = 's';
X    Bell(tmp);
X   } else {
X    XtSetSensitive(w, False);	/* Don't let us be pressed more than once */
X    if (*C == 'A')		/* also make other sign button inoperative */
X       XtSetSensitive(XtNameToWidget(XtParent(w), "autograph"), False);
X    else			/* if this was a request for lowercase sign */
X       XtSetSensitive(XtNameToWidget(XtParent(w), "Autograph"), False);
X
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**		Attempt to do the task as a forked child.  Failing that,
X**		deliver the message by system call(s).
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, *xf;
X char		*ARGV[3];
X char		*p, *q, *record, *folder, *getenv();
X char		From[BUFSIZ], Copy[BUFSIZ], s[BUFSIZ], addressees[BUFSIZ];
X int		n;
X struct stat	st_buf;
X
X
X Bell(Default_Status_Info);
X
X shell = XtNameToWidget(toplevel, "topBox.commandPanel.Send.popup");
X if (! shell) return;			/* SOMEthing would be VERY wrong here */
X
X SetCursor(1);
X XtPopdown(shell);			/* remove from use but don't destroy */
X/*
X** Restore the sensitivity of the Autograph buttons
X*/
X XtSetSensitive(XtNameToWidget(XtParent(w), "Autograph"), True);
X XtSetSensitive(XtNameToWidget(XtParent(w), "autograph"), True);
X
X st_buf.st_size = 0;			/* (in case msg file does not exist) */
X stat(tmpName, &st_buf);
X
X if (strcmp(closure, "Deliver") == 0) {
X    otherBuf[0] = '\0';			/* remove names from any previous act */
X/*
X** Prepare header information (in a second temporary file).  Call the alias()
X** routine recursively, to de-alias the user's To:, Cc:, and Bcc: fields.
X*/
X    if ((fp = fopen(tmpName, "a+")) != NULL) {	/* (give cat something to do) */
X       fprintf(fp, "\n");		/* ensure the last line is a blank */
X       fclose(fp);
X       if (st_buf.st_size)		/* don't count unless text was there */
X          st_buf.st_size += 1;		/* but try to be accurate for cancel */
X      }
X
X    sprintf(s, "%s_", tmpName);
X    if ((fp = fopen(s, "w")) != NULL) {
X       if (*Recipient) {
X          strcpy(addressees, Recipient); /* alias() adds file names to a list */
X          for (p = alias(addressees);
X               strcmp(p, addressees);
X               p = alias(addressees))
X              strcpy(addressees, p);	/* and returns just user addresses, */
X
X          if (*addressees)		/* for case if user has mix of both */
X             fprintf(fp, "To: %s\n", addressees);
X         }
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          strcpy(s, CcBuf);
X          for (p = alias(s); strcmp(p, s); p = alias(s))
X              strcpy(s, p);
X
X          if (*p) {
X             fprintf(fp, "Cc: %s\n", p);
X             strcat(addressees, " ");
X             strcat(addressees, p);
X            }
X         }
X
X       if (*BccBuf) {
X          strcpy(s, BccBuf);
X          for (p = alias(s); strcmp(p, s); p = alias(s))
X              strcpy(s, p);
X
X          if (*p) {
X             fprintf(fp, "Bcc: %s\n", p);
X             strcat(addressees, " ");
X             strcat(addressees, p);
X            }
X         }
X
X#ifdef X_FACE
X/*
X** Look in user's home directory for, and add contents of, their .face file
X*/
X       sprintf(s, "%s/.face", getenv("HOME"));
X       if (xf = fopen(s, "r")) {
X          while (fgets(s, BUFSIZ, xf) != NULL)
X                fprintf(fp, "%s", s);
X          fclose(xf);
X         }
X#endif X_FACE
X
X       if ((*Recipient || *SubjBuf) && st_buf.st_size)
X          fprintf(fp, "\n");		/* separate the header from any text */
X       fclose(fp);
X      }
X
X    sprintf(s, "%s=", tmpName);
X    fp = fopen(s, "w");
X    if (fp) {			/* try to keep user from overwriting these */
X       fprintf(fp,"mv %s_ %s#_ 2> /dev/null\n", tmpName, tmpName);
X       fprintf(fp,"mv %s  %s#  2> /dev/null\n", tmpName, tmpName);
X      }
X/*
X** mail the header information and text in temporary files using sendmail
X*/
X    if (*addressees && (*SubjBuf || st_buf.st_size)) {
X       if ((p = GetMailEnv("sendmail")) == NULL)
X            p = XtNewString("/usr/lib/sendmail");
X/*
X** To avoid a bug in Sun's sendmail (for occasionally not being able to find
X** the name of the real author of the message), strip commas from the address
X** list and pass the recipient names to sendmail on the command line, ala Mail.
X*/
X       for (q = addressees; *q; q++) if (*q == ',') *q = ' ';
X       q = addressees;
X/*
X** The following arguments are passed to the sendmail command:
X**
X**	-oi	don't accept a dot on a line by itself as message termination
X**
X**	-om	send to "me" too, if I am a member of an alias expansion
X*/
X       if (fp)
X          fprintf(fp, "cat %s#_ %s# | %s -oi -om %s\n", tmpName, tmpName, p, q);
X       else {
X          sprintf(s, "cat %s_ %s | %s -oi -om %s", tmpName, tmpName, p, q);
X          system(s);
X         }
X
X       XtFree(p);
X/*
X** If user has set "record" in their .mailrc, add a message copy to that file.
X** Try to faithfully follow the description of the "outfolder" variable, even
X** if Berkeley Mail doesn't appear to do so.  To whit, if "outfolder" is set,
X** ``locate files used to record outgoing messages (the "record" variable,
X** for one) in the directory specified by the "folder" variable, unless the
X** pathname is absolute.'' (Quoted from Mail man page outfolder description.)
X** Consider both absolute and relative addressing (i.e. /* and ./*)
X*/
X       if (record = GetMailEnv("record")) {
X          long	*clock;
X
X          p = GetMailEnv("outfolder");
X          folder = GetMailEnv("folder");
X          if (*record != '+' &&
X             (*record == '/' || (*record == '.' && *(record+1) == '/') ||
X             p == NULL || folder == NULL)) {
X             strcpy(Copy, record);
X            } else {
X             if (*folder == '/')
X                sprintf(Copy, "%s/%s", folder,
X                        (*record == '+') ? &record[1] : record);
X             else
X                sprintf(Copy, "%s/%s/%s", getenv("HOME"), folder,
X                        (*record == '+') ? &record[1] : record);
X            }
X          if (folder) XtFree(folder);
X          if (p) XtFree(p);
X          XtFree(record);
X
X          (void) time(&clock);
X          sprintf(From, "From %s %24.24s", getenv("USER"), ctime(&clock));
X          if (fp)
X             fprintf(fp,"echo \"%s\" >> %s\ncat %s#_ %s# >> %s 2> /dev/null\n",
X                              From, Copy, tmpName, tmpName, Copy);
X          else {
X             sprintf(s, "echo \"%s\" >> %s;cat %s_ %s >> %s 2> /dev/null",
X                              From, Copy, tmpName, tmpName, Copy);
X             system(s);
X            }
X         }			/* end - if record variable is set */
X/*
X** If there are other addresses, add copies to those files and or folders
X*/
X       if (*otherBuf) {
X          FILE	*fp1;
X          long	*clock;
X          /*
X          ** Prepare (aliased) header information (in a third temporary file)
X          */
X           sprintf(s, "%s$", tmpName);
X           if ((fp1 = fopen(s, "w"))) {
X              (void) time(&clock);
X              sprintf(fp1, "From %s %s", getenv("USER"), ctime(&clock));
X              fprintf(fp1, "To: %s\n", Recipient);
X
X              if (*SubjBuf)
X                 fprintf(fp1, "Subject: %s\n", SubjBuf);
X
X              if (*InReply)
X                 fprintf(fp1, "%s\n", InReply);
X
X              if (*CcBuf)
X                 fprintf(fp1, "Cc: %s\n", CcBuf);
X
X              fprintf(fp1, "\n");		/* separate header from text */
X              fclose(fp1);
X             }
X          p      = GetMailEnv("outfolder");
X          folder = GetMailEnv("folder");
X          for (record = otherBuf; *record;) {
X              for (q = record; *q && *q != ','; q++);
X              n = 0;
X              if (*q == ',') {
X                 *q = '\0';
X                 n = 1;
X                }
X              if (*record != '+' && 
X                 (*record == '/' || (*record == '.' && *(record+1) == '/') ||
X                 p == NULL || folder == NULL)) {
X                 strcpy(Copy, record);		/* same rules as for 'record' */
X                } else {
X                 if (*folder == '/')
X                    sprintf(Copy, "%s/%s", folder,
X                        (*record == '+') ? &record[1] : record);
X                 else
X                    sprintf(Copy, "%s/%s/%s", getenv("HOME"), folder,
X                                       (*record == '+') ? &record[1] : record);
X                }
X
X              if (fp)
X                 fprintf(fp, "cat %s$ %s# >>%s 2>/dev/null\n", tmpName, tmpName, Copy);
X              else {
X                 sprintf(s, "cat %s$ %s >> %s 2> /dev/null", tmpName, tmpName, Copy);
X                 system(s);
X                }
X              if (n) *q++ = ',';
X              record = q;
X             }	/* end - for each record in otherBuf */
X          if (p) XtFree(p);
X          if (folder) XtFree(folder);
X         }	/* end - if records in otherBuf */
X      } else {			/* end - if something is there to deliver */
X       if (! *Recipient)
X          Bell("No recipient specified\n");
X       else
X          Bell("No subject and no message\n");
X      }
X   } else {     	/* do we want to save the message text in dead file */
X    sprintf(s, "%s=", tmpName);		/* name of the command script file */
X    fp = fopen(s, "w");			/* try to run commands in a child */
X    n = st_buf.st_size;			/* remember num bytes in msg text */
X    if (n == 0 && *closure == 'c')
X       Bell("No text to save in your dead letter box\n");
X    else {
X       if (n && (*closure == 'c' || ! Confirm("REALLY discard this text"))) {
X          if ((record = GetMailEnv("DEAD")) == NULL)
X             sprintf(Copy, "%s/dead.letter", getenv("HOME"));
X          else {
X             strcpy(Copy, record);		/* take whatever is given */
X             XtFree(record);
X            }
X          st_buf.st_size = -1;			/* see if our target exists */
X          stat(Copy, &st_buf);
X          sprintf(s, "\"%s\" [%s] (%d bytes)\n", Copy,
X                 (st_buf.st_size >= 0) ? "Appended" : "New file", n);
X          Bell(s);
X          if (fp)
X             fprintf(fp,"cat %s# >> %s 2> /dev/null\n", tmpName, Copy);
X          else {
X             sprintf(s, "cat %s >> %s 2> /dev/null", tmpName, Copy);
X             system(s);
X            }
X         }
X      }
X   }
X/*
X** remove any message text that may have been created
X*/
X SetCursor(0);
X if (! fp) {				/* if we failed to make temp file */
X    sprintf(s, "rm -f %s_ %s %s$ &", tmpName, tmpName, tmpName);
X    system(s);
X   } else {			/* try to fork this off to a child process */
X    fprintf(fp, "rm -f %s#_ %s# %s= %s$\n", tmpName,tmpName,tmpName,tmpName);
X    fclose(fp);
X    switch (fork()) {
X         case -1:			/* failed, so use old fashioned way */
X                 sprintf(s, "/bin/sh %s= &", tmpName);
X                 system(s);
X                 break;
X         case 0:			/* fork succeeded - we are the child */
X                 sprintf(s, "%s=", tmpName);
X                 ARGV[0] = "/bin/sh";
X                 ARGV[1] = s;
X                 ARGV[2] = NULL;
X                 execv("/bin/sh", ARGV);
X                 break;
X        }
X    }
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		n;
X char		buf[BUFSIZ];
X Arg		args[1];
X LabelWidget	lw = (LabelWidget) XtNameToWidget(toplevel, "topBox.titleBar.title");
X
X
X SetCursor(1);
X sprintf(Command, "%s\n", closure);
X if (mailpid) {				/* If connections are okay,... */
X    if ((n = match(&command_pattern, Command)) != C_FILE && n != C_NEWMAIL)
X       writeMail(Command);
X    else {				/* check for commit of any changes */
X       XtSetArg(args[0], XtNlabel, (XtArgVal) NULL);
X       XtGetValues(lw, args, ONE);
X       strcpy(buf, (char *)args[0].value);
X
X       if (strcmp(&buf[strlen(buf) - 7], "deleted") ||
X           strcmp(closure, "inc") == 0 ||
X           Confirm("COMMIT all changes to this folder"))
X          writeMail(Command);
X      }
X   } else if (C_NEWMAIL != match(&command_pattern, Command))
X         Bell("No current mail connection\n");		/* if not 'Newmail' */
X     else {
X         if (strcmp(mailargv[mailargc - 2], "-f") == 0) {
X            mailargc -= 2;		/* throw away any folder argument */
X            mailargv[mailargc] = NULL;	/* and NULL end of argument list */
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} /* 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 Arg		args[1];
X Display	*dpy = XtDisplay(toplevel);
X LabelWidget	lw = (LabelWidget) XtNameToWidget(toplevel, "topBox.titleBar.title");
X char		buf[BUFSIZ];
X int		status;
X
X if (mailpid) {				/* check for commit of any changes */
X    XtSetArg(args[0], XtNlabel, (XtArgVal) NULL);
X    XtGetValues(lw, args, ONE);
X    strcpy(buf, (char *)args[0].value);
X
X    if (*closure != 'q' || strcmp(&buf[strlen(buf) - 7], "deleted") ||
X        Confirm("Changes in folder.  REALLY quit")) {
X       sprintf(Command, "%s\n", closure);
X       writeMail(Command);
X       wait3(&status, WNOHANG, NULL);
X      } else return;
X   }
X
X XtDestroyWidget(toplevel);
X XCloseDisplay(dpy);
X _exit(0);
X} /* DoQuit */
X
X
X/*
X** @(#)DoSet() - send specified set request to mail and destroy current menu.
X**		 To accommodate those systems (Sony?) whose mail cannot handle
X**		 'set no' commands, convert 'set no's to unsets.
X*/
X/* ARGSUSED */
XXtCallbackProc
XDoSet(w, closure, call_data)
XWidget	w;
Xcaddr_t	closure;
Xcaddr_t	call_data;
X{
X char	*c, buf[32];
X
X
X SetCursor(1);
X if (! mailpid)
X    Bell("No current mail connection\n");
X else {
X    c = w->core.name;
X    if (strcmp(&c[strlen(c) - 6], "expert") == 0)
X       if (*c == 'n')
X            XMail.expert = (Boolean) 0;
X       else XMail.expert = (Boolean) 1;
X    else {
X       if (*c == 'n')
X          sprintf(buf, "unset %s", &c[2]);
X       else
X          sprintf(buf, "set %s", c);
X
X       c = QueryMail(buf);
X       XtFree(c);
X      }
X
X    XtDestroyWidget(XtParent(XtParent(w)));
X    SetCursor(0);
X   }
X} /* DoSet */
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 int	num = 0;
X
X
X SetCursor(1);
X if (! mailpid) Bell("No current mail connection\n");
X else {
X    num = SelectionNumber(*client_data == 'u');
X
X    if (num) sprintf(Command, "%s %d\n", client_data, num);
X    else sprintf(Command, "%s \n", client_data);
X
X    writeMail(Command);
X   }
X} /* DoWith */
X
X
X/* ARGSUSED */
X/*
X** @(#)DropIt() - callback to destroy the current folder popup list(s)
X*/
XXtCallbackProc
XDropIt(w, client_data, call_data)
XWidget w;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
X Widget	popup = XtNameToWidget(toplevel,"topBox.commandPanel.Folder.popupList");
X if (popup)
X    XtDestroyWidget(popup);
X} /* DropIt */
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;			/* unused */
Xcaddr_t	call_data;			/* unused */
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);	/* get this entry's label value */
X
X shell = XtParent(XtParent(w));		/* aliasList<-table<-entry */
X XtPopdown(shell);
X
X shell = XtParent(shell);		/* (To|Cc|Bcc)<-aliasList */
X
X if (TextGetLastPos(shell))		/* if some alias is already in there */
X    writeText(shell, ", ", 1);		/* add comma separator between names */
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;
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    tmp[0] = '\0';
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(XtNameToWidget(toplevel, "topBox.commandPanel.fileWindow"), buf, 0);
X} /* GetFolderName */
X
X
X/*
X** @(#)ReEdit() - Call the editMail routine to re-edit a message
X*/
X/* ARGSUSED */
XXtCallbackProc
XReEdit(w, closure, call_data)
XWidget	w;
Xcaddr_t closure;
Xcaddr_t	call_data;
X{
X Widget	Popup, To;
X
X
X Popup = XtNameToWidget(toplevel, "topBox.commandPanel.Send.popup");
X
X if (! Popup) {
X    XBell(XtDisplay(toplevel), 33);
X    return;				/* SOMEthing must be VERY wrong here */
X   }
X
X To = XtNameToWidget(Popup, "SubjCc.To");
X
X XtPopdown(Popup);			/* pop down the send popup */
X
X editMail();				/* re-edit the message file */
X
X XtPopup(Popup, XtGrabNone);		/* pop back the send popup */
X XWarpPointer(XtDisplay(toplevel), None, XtWindow(To), 0, 0, 0, 0, 10, 5);
X} /* ReEdit */
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 FILE		*fp;
X String		p, q, r, old_From;
X String		txt, ccList, author, subject, others, date, reference, empty;
X Widget		sb = XtNameToWidget(toplevel, "topBox.commandPanel.Send");
X char		*us, *getlogin();
X int		erasable = 0;
X int		alwaysIgnore;
X 
X
X SetCursor(1);
X txt = ccList = author = subject = others = date = reference = empty = old_From = "";
X if (*client_data != 's') {
X    if ((fp = fopen(tmpName, "w")) == NULL)
X       Bell("xmail: Cannot open temp file for writing\n");
X
X    if (p = GetMailEnv("alwaysignore")) {
X       XtFree(p);
X       alwaysIgnore = (strchr("SRA", *client_data)) ? 1 : 0;
X      } else alwaysIgnore = 0;
X
X    if (alwaysIgnore)		/* do we need to include a limited copy? */
X       sprintf(Command, "p %d", SelectionNumber(False));
X    else
X       sprintf(Command, "P %d", SelectionNumber(False));
X
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               if ((p = GetMailEnv("indentprefix")) != NULL)
X                  erasable = 1;
X               else
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    if (alwaysIgnore) {		/* get full headers for data (top 100 lines) */
X       XtFree(txt);
X       txt = QueryMail("unset alwaysignore");
X       XtFree(txt);
X       sprintf(Command, "top %d", SelectionNumber(False));
X       txt = QueryMail(Command);
X       p = QueryMail("set alwaysignore");
X       XtFree(p);
X      }
X    for (p = txt; *p; p++) {
X        if (strcmp(p, empty) == 0 || strncmp(p, "Status:", 7) == 0) break;
X
X        if (strncmp(p, "From ", 5) == 0 ) {
X           old_From = p + 5;
X           for (p = old_From; *p && *p != ' ' && *p != '\n'; p++);
X           if (*p) *p++ = '\0';			/* drop the date portion now */
X           for (; *p && *p != '\n'; p++);	/* skip to end of this line */
X          }
X
X        else if (strncmp(p, "Return-Path:", 12) == 0) {
X           reference = p + 14;		/* step over the opening '<' chevron */
X           for (p = reference; *p && *p != '>'; p++);
X           if (*p) *p++ = '\0';			/* drop the trailing chevron */
X           for (; *p && *p != '\n'; p++);	/* skip to end of this line */
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           author = p + 6;
X           for (p = author; *p && *p != '\n'; p++);
X           while (*(p+1) && strchr(" \t", *(p+1))) {
X                 *p = ' ';		/* change this newline to a space */
X                 *(p+1) = ' ';		/* change possible tab to a space */
X                 for (p++; *p && *p != '\n'; p++);
X                }
X           if (*p) *p = '\0';
X          }
X
X        else if (strncmp(p, "To:", 3) == 0) {
X           others = p + 4;
X           for (p = others; *p && *p != '\n'; p++);
X           while (*(p+1) && strchr(" \t", *(p+1))) {
X                 *p = ' ';		/* change this newline to a space */
X                 *(p+1) = ' ';		/* change possible tab to a space */
X                 for (p++; *p && *p != '\n'; p++);
X                }
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           while (*(p+1) && strchr(" \t", *(p+1))) {
X                 *p = ' ';		/* change this newline to a space */
X                 *(p+1) = ' ';		/* change possible tab to a space */
X                 for (p++; *p && *p != '\n'; p++);
X                }
X           if (*p) *p = '\0';
X          }
X
X        else if (strncmp(p, "Cc:", 3) == 0) {
X           ccList = p + 4;
X           for (p = ccList; *p && *p != '\n'; p++);
X           while (*(p+1) && strchr(" \t", *(p+1))) {
X                 *p = ' ';		/* change this newline to a space */
X                 *(p+1) = ' ';		/* change possible tab to a space */
X                 for (p++; *p && *p != '\n'; p++);
X                }
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       ccList = empty;	/* If not [rR]eplyall, make sender enter any Cc: */
X       others = empty;
X      } else {		/* otherwise, remove ourself from the others list */
X       us = getlogin();
X       if (! us) {
X          struct passwd *pw = getpwuid(getuid());
X
X          if (pw)
X             us = pw->pw_name;
X         }
X       for (p = others; *us && *p; p++) {
X           if (strncmp(p, us, strlen(us)) == 0) {
X              for (us = p + strlen(us); *us && *us != ',' && *us != ' ';) us++;
X              for (; *us && (*us == ',' || *us == ' ');) us++;
X              for (; *us;) *p++ = *us++;
X              *p = '\0';
X              break;
X             }
X           while (*p && *p != ',' && *p != ' ') p++;
X           while (*p && (*p == ',' || *p == ' ')) p++;
X           p--;
X          }
X      }
X
X    if (fp) fclose(fp);
X
X   } /* end - if client_data does not equal 's' */
X
X Recipient[0] = InReply[0] = SubjBuf[0] = CcBuf[0] = BccBuf[0] = '\0';
X/*
X** If message did not have a 'From:', use 'Return-Path:' for reply recipient.
X** If message also did not have a 'Return-Path', use the older style 'From '.
X*/
X if (*client_data != 'S' && *client_data != 's') {
X    if (! *author && *reference) 
X       author = reference;
X    if (! *author && *old_From)
X       author = old_From;
X    strcpy(Recipient, author);
X/*
X** If author's name consists of a compound address (i.e. name <address>,
X** (Name) address, or equivalents...) strip off the real address portion
X** (i.e. that portion not in parens, but possibly between chevrons).
X*/
X    if ((p = strchr(Recipient, '(')) || (p = strchr(Recipient, '<')))
X       switch (*p) {
X          case '(': q = strchr(p, ')');		/* skipping past the parens */
X                    if (p == Recipient) {	/* '(Name) address' format */
X                       for (q++; *q && (*q == ' ' || *q == '\t'); q++);
X                       bcopy(p, Recipient, strlen(p) + 1);
X                      } else {			/* 'address (Name)' format */
X                       for (; (p-1) > Recipient &&
X                            (*(p-1) == ' ' || *(p-1) == '\t'); p--);
X                       *++p = '\0';
X                      }
X                    break;
X
X          case '<': q = strchr(p++, '>');
X                    *q = '\0';	/* '<address> Name' or 'Name <address>' */
X                    bcopy(p, Recipient, strlen(p) + 1);
X                    break;
X         }
X/*
X** If the user wishes to include all recipients of the original
X** message in this message, include those others in the address.
X*/
X    if (*others && (*client_data == 'a' || *client_data == 'A')) {
X       if (LASTCH(Recipient) && LASTCH(Recipient) != ',')
X          strcat(Recipient, ", ");
X       strcat(Recipient, others);
X       for (p = Recipient + strlen(Recipient) - 1; *p == ' ' || *p == ','; p--);
X       *++p = '\0';			/* drop any trailing ", " garbage */
X      }
X   }
X
X if (*client_data != 's' && *reference && *date) {
X    r = (*client_data == 'S') ? "Forwarding" : "In-Reply-To";
X    sprintf(InReply, "%s: Mail from '%s'\n      dated: %s", r, reference, date);
X   }
X
X if (*subject) {
X    if (strncmp(subject, "Re:", 3) != 0 &&
X        strncmp(subject, "Re;", 3) != 0 &&
X        strncmp(subject, "RE:", 3) != 0 &&
X        strncmp(subject, "RE;", 3) != 0 &&
X        strncmp(subject, "re:", 3) != 0 &&
X        strncmp(subject, "re;", 3) != 0)
X       strcpy(SubjBuf, "Re: ");
X    strcat(SubjBuf, subject);
X   }
X
X strcpy(CcBuf, ccList);
X
X XtFree(txt);
X
X SetCursor(0);
X
X sendMail(sb);
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, *r, *getenv();
X Cardinal	num, n;
X
X
X SetCursor(1);
X if (! mailpid) Bell("No current mail connection\n");
X else {
X    num = SelectionNumber(False);	/* no current message returns zero */
X    if (*cmd == 'C' || *cmd == 'S' || 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(XtNameToWidget(toplevel, "topBox.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               q = GetMailEnv("outfolder");
X               r = GetMailEnv("folder");
X             if (*p != '+' && (*p == '/' || (*p == '.' && *(p+1) == '/') ||
X                  q == NULL || r == NULL)) {
X                sprintf(Command, "%s %d %s\n", cmd, num, p);
X               } else {
X                if (*r == '/')
X                   sprintf(Command, "%s %d %s/%s\n", cmd, num, r, (*p == '+') ? &p[1] : p);
X                else
X                   sprintf(Command, "%s %d %s/%s/%s\n", cmd, num,
X                           getenv("HOME"), r, (*p == '+') ? &p[1] : p);
X               }
X             if (r) XtFree(r);
X             if (q) XtFree(q);
X             XtFree(p);
X            }
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 = XtNameToWidget(toplevel, "topBox.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 = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail");
X
X if (Highlighted) {
X    XSetWindowBackground(XtDisplay(toplevel), XtWindow(cw), cw->core.background_pixel);
X    XtUnmapWidget(cw);
X    XtMapWidget(cw);
X    Highlighted = 0;
X    reset_mailbox(XtNameToWidget(toplevel, "icon.mailbox"));
X   }
X} /* UnsetNewmail */
END_OF_FILE
if test 32817 -ne `wc -c <'callbacks.c'`; then
    echo shar: \"'callbacks.c'\" unpacked with wrong size!
fi
# end of 'callbacks.c'
fi
echo shar: End of archive 9 \(of 11\).
cp /dev/null ark9isdone
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