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