/*
* xmail - X window system interface to the mail program
*
* Copyright 1990,1991,1992 by National Semiconductor Corporation
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of National Semiconductor Corporation not
* be used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
* SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
* WITHOUT EXPRESS OR IMPLIED WARRANTY. NATIONAL SEMICONDUCTOR CORPORATION
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
* EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* The following software modules were created and are Copyrighted by National
* Semiconductor Corporation:
*
* 1. warp_handler:
* 2. extract_of:
* 3. endEdits:
* 4. editMail:
* 5. makeHeading:
* 6. makeButton:
* 7. sendMail:
*
* Author: Michael C. Wagnitz - National Semiconductor Corporation
*
*/
#include "global.h"
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#ifdef vms
extern int noshare errno;
#else
extern int errno;
#endif
#if ! defined(SIGCHLD) && defined(SIGCLD)
#define SIGCHLD SIGCLD
#endif
#ifndef DEFAULT_VISUAL
#ifndef linux
#define DEFAULT_VISUAL "/usr/ucb/vi"
#else
#define DEFAULT_VISUAL "/usr/bin/vi"
#endif
#endif
static int editMail_pid;
/* ARGSUSED */
void
warp_handler(Widget w, XtPointer client_data, XEvent *event, Boolean *continueToDispatch)
{
Widget Popup = XtNameToWidget(toplevel,"topBox.commandPanel.Send.popup");
Widget To = XtNameToWidget(Popup, "SubjCc.To");
if (event->type == MapNotify) {
XWarpPointer(XtDisplay(toplevel), None, XtWindow(To), 0,0,0,0, 15, 10);
XtRemoveEventHandler(Popup, StructureNotifyMask, False, warp_handler, NULL);
}
}
/*
** @(#)extract_of - strip off header information from a buffer and return
** the extracted information and the incremented pointer
*/
char *
extract_of(char **p)
{
int n;
static char tmp[BUFSIZ];
for (n = 0; *(*p); (*p)++) {
if (*(*p) == '\n' && *((*p) + 1) != ' ' && *((*p) + 1) != '\t') break;
if (*(*p) == '\n') {
if (tmp[n - 1] != ' ' && tmp[n - 1] != '\t') tmp[n++] = ' ';
for ((*p)++; *(*p) && (*(*p) == ' ' || *(*p) == '\t');) (*p)++;
}
if (*(*p) != '\n') tmp[n++] = *(*p);
}
tmp[n] = '\0';
return((char *)tmp);
}
/*
** @(#)endEdits() - catch the signal when the edit child finishes
** (The idea for this was ``borrowed'' from xrn.)
** If editheaders is set, extract selected header
** information from the message text file and
** install it in the appropriate header windows.
** Then, popup the completion window with header
** edit windows and completion control buttons.
*/
#if defined(sun) || defined(SVR4)
void
#else
int
#endif
endEdits(int signum)
{
int fd, status;
String p, q;
char buf[BUFSIZ];
Widget sb, Popup;
if (signum != SIGCHLD)
#if defined(sun) || defined(SVR4)
return ;
#else
return 1;
#endif
if (editMail_pid != wait(&status))
#if defined(sun) || defined(SVR4)
return ; /* the mail child could die too */
#else
return 1;
#endif
(void) signal(SIGCHLD, SIG_DFL); /* turn off the endEdits hook */
sb = XtNameToWidget(toplevel, "topBox.commandPanel.Send");
if (p = GetMailEnv("editheaders")) {
XtFree((String) p);
if ((fd = open(tmpName, O_RDONLY)) >= 0) {
while (1) {
bzero(Command, BUFSIZ);
status = read(fd, Command, BUFSIZ);
for (p = Command; *p; p++) {
if (*p == '\n' && *(p - 1) == '\n') {
status = 0;
break;
}
if (strncmp(p, "To: ", 4) == 0) {
p += 4;
writeTo(XtNameToWidget(sb, "*To"), extract_of(&p), REPLACE);
} else
if (strncmp(p, "Subject: ", 9) == 0) {
p += 9;
writeTo(XtNameToWidget(sb,"*Subject"),extract_of(&p),REPLACE);
} else
if (strncmp(p, "In-Reply-To: ", 13) == 0) {
p += 13;
(void) strcpy(buf, extract_of(&p));
if (! (q = strchr(buf, ':')))
(void) sprintf(InReply, "In-Reply-To: %s", buf);
else {
q -= 5;
if (strncmp(q, "dated: ", 7) != 0)
(void) sprintf(InReply, "In-Reply-To: %s", buf);
else {
*(q - 1) = '\0';
(void) sprintf(InReply, "In-Reply-To: %s\n ", buf);
(void) strcat(InReply, q);
}
}
} else
if (strncmp(p, "Forwarding: ", 12) == 0) {
p += 12;
(void) strcpy(buf, extract_of(&p));
if (! (q = strchr(buf, ':')))
(void) sprintf(InReply, "Forwarding: %s", buf);
else {
q -= 5;
if (strncmp(q, "dated: ", 7) != 0)
(void) sprintf(InReply, "Forwarding: %s", buf);
else {
*(q - 1) = '\0';
(void) sprintf(InReply, "Forwarding: %s\n ", buf);
(void) strcat(InReply, q);
}
}
} else
if (strncmp(p, "Cc: ", 4) == 0) {
p += 4;
writeTo(XtNameToWidget(sb, "*Cc"), extract_of(&p), REPLACE);
} else
if (strncmp(p, "Bcc: ", 5) == 0) {
p += 5;
writeTo(XtNameToWidget(sb, "*Bcc"), extract_of(&p), REPLACE);
} else {
for (;*p && *p != '\n';) p++;
}
}
if (status < BUFSIZ) break;
}
(void) close(fd);
}
}
Popup = XtNameToWidget(sb, ".popup");
SetXY(Popup, XtNameToWidget(toplevel, "topBox.commandPanel"), 0, 0);
XtPopup(Popup, XtGrabNone);
XSync(XtDisplay(toplevel), False);
XtAddEventHandler(Popup, StructureNotifyMask, False, warp_handler, NULL);
#if defined(sun) || defined(SVR4)
return ;
#else
return 1;
#endif
}
/*
** @(#)editMail() - edit a mail message using the preferred editor
**
** Support is now provided for declaring the editor command as an xmail
** resource, ala xrn. If the resource ``xmail.editorCommand'' is defined,
** it must contain an `sprintf'-able format string that provides for the
** inclusion of both a display name and the name of the file to be edited.
** If the resource declaration is not included, or does not contain the two
** required percent-s (%s) formatting strings, xmail will use the VISUAL
** resource. If VISUAL is used, try to accommodate those editors (emacs,
** xedit...) which start their own window in X11. We know for a fact that
** vi and ed variants do not invoke windows. We assume any other editor
** specification does.
*/
void
editMail(void)
{
String edit, cp;
char cmd[BUFSIZ];
Display *ad;
bzero(cmd, BUFSIZ);
ad = XtDisplay(XtNameToWidget(toplevel, "topBox.statusWindow"));
/*
** If editorCommand resource exists, use it (format validated during initialize)
*/
if (XMail.editorCommand)
(void) sprintf(cmd, XMail.editorCommand, DisplayString(ad), tmpName);
else {
/*
** Otherwise, default to the VISUAL method of starting things
*/
if (! (edit = GetMailEnv("VISUAL")))
edit = XtNewString(DEFAULT_VISUAL);
if ((cp = strrchr(edit, '/')) == NULL) cp = edit;
else cp++;
if (strcmp(cp, "ed") == 0 ||
strcmp(cp,"red") == 0 ||
strcmp(cp, "ex") == 0 ||
strcmp(cp, "vi") == 0) {
(void) sprintf(cmd, "exec xterm -display %s -name XMail -title 'Message entry' -e %s %s",
DisplayString(ad), edit, tmpName);
} else (void) sprintf(cmd, "exec %s -display %s %s", edit, DisplayString(ad), tmpName);
XtFree((String) edit);
}
editMail_pid = fork();
switch (editMail_pid) {
case -1: /* fork failed ... */
if (errno == ENOMEM)
Bell("Not enough core for edits\n");
else
Bell("No more processes - no edits\n");
break;
case 0: /* child starts the message entry session */
(void) close(ConnectionNumber(XtDisplay(toplevel)));
(void) execl("/bin/sh", "sh", "-c", cmd, 0);
perror("editMail: Failed to start the text editor");
(void) _exit(127);
break;
default: /* parent waits for editing to conclude */
(void) signal(SIGCHLD, endEdits);
break;
}
} /* editMail */
/*
** @(#)readMail() - callback invoked every time input is pending on mail fd
**
** Calls QueryMail() to read all available data from mail file descriptor,
** and passes output to parse() for analysis and appropriate action.
*/
/* ARGSUSED */
void
readMail(XtPointer client_data, int *source, XtInputId *id)
/* unused */
/* unused */
/* unused */
{
SetCursor(WATCH);
parse(QueryMail(""));
} /* readMail */
/*
** @(#)makeHeading() - Create the specified message header windows
*/
void
makeHeading(Widget parent, String label_string, Widget *left, Widget *above, String info, String help_text)
{
Arg args[11];
char resource_name[10];
Widget input_window;
XtSetArg(args[0], XtNfromVert, *left);
XtSetArg(args[1], XtNfromHoriz, NULL);
XtSetArg(args[2], XtNlabel, label_string);
XtSetArg(args[3], XtNborderWidth, 0);
XtSetArg(args[4], XtNfont, XMail.buttonFont);
XtSetArg(args[5], XtNheight, XMail.buttonHeight + XMail.borderWidth + 7);
XtSetArg(args[6], XtNwidth, XMail.buttonWidth);
XtSetArg(args[7], XtNjustify, XtJustifyLeft);
XtSetArg(args[8], XtNinternalHeight, 0);
XtSetArg(args[9], XtNinternalWidth, 1);
*left = XtCreateManagedWidget("SubjCc", labelWidgetClass, parent, args, 10);
bzero(resource_name, 9);
(void) strncpy(resource_name, label_string, strlen(label_string) - 1);
input_window = CreateInputWindow(parent, resource_name);
XtSetArg(args[0], XtNfromVert, *above);
XtSetArg(args[1], XtNfromHoriz, *left);
XtSetValues(input_window, args, 2);
AddInfoHandler(input_window, info);
AddHelpText(input_window, help_text);
*above = input_window;
} /* makeHeading */
/*
** @(#)makeButton() - Create the specified command button with callback
*/
void
makeButton(Widget parent, String label, XtCallbackProc CBProc, String CBData, String info, String help_text)
{
Arg args[3];
Widget button;
int width = ((((int)XMail.shellWidth-2)/6) - (int)XMail.borderWidth*2) - 4;
XtSetArg(args[0], XtNfont, XMail.buttonFont);
XtSetArg(args[1], XtNheight, XMail.buttonHeight);
XtSetArg(args[2], XtNwidth, width);
button = XtCreateManagedWidget(label, commandWidgetClass, parent, args, 3);
XtAddCallback(button, XtNcallback, CBProc, CBData);
AddInfoHandler(button, info);
AddHelpText(button, help_text);
} /* makeButton */
/*
** @(#)sendMail() - Create the send window popup for message headers
*/
void
sendMail(Widget parent)
{
Arg args[11];
Widget Popup, Layout, Box, left, above;
Popup = XtNameToWidget(parent, "popup");
if (! Popup) {
XtSetArg(args[0], XtNinput, True);
XtSetArg(args[1], XtNwidth, XMail.shellWidth - 2);
XtSetArg(args[2], XtNheight,
XMail.borderWidth*3 + XMail.buttonHeight*5 + 44);
Popup = XtCreatePopupShell("popup",transientShellWidgetClass,parent,args,3);
XtSetArg(args[0], XtNdefaultDistance, 2);
Layout = XtCreateManagedWidget("SubjCc", formWidgetClass, Popup, args, 1);
left = above = NULL;
makeHeading(Layout, "To:",&left,&above,SendMail_Info[0],To_Help);
makeHeading(Layout, "Subject:",&left,&above,SendMail_Info[1],Subject_Help);
makeHeading(Layout, "Cc:",&left,&above,SendMail_Info[2],Cc_Help);
makeHeading(Layout, "Bcc:",&left,&above,SendMail_Info[3],Bcc_Help);
XtRegisterGrabAction(SetAliases, True, ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync);
XtSetArg(args[0], XtNfont, XMail.buttonFont);
XtSetArg(args[1], XtNheight, XMail.buttonHeight + XMail.borderWidth*2 + 4);
XtSetArg(args[2], XtNwidth, XMail.shellWidth - 2);
XtSetArg(args[3], XtNfromVert, left);
XtSetArg(args[4], XtNfromHoriz, NULL);
XtSetArg(args[5], XtNborderWidth, 0);
XtSetArg(args[6], XtNresize, False);
XtSetArg(args[7], XtNmin, args[1].value);
XtSetArg(args[8], XtNmax, args[1].value);
XtSetArg(args[9], XtNhSpace, 2);
XtSetArg(args[10],XtNvSpace, 2);
Box = XtCreateManagedWidget("Box", boxWidgetClass, Layout, args, 11);
makeButton(Box, "Autograph", (XtCallbackProc) Autograph, "A",
Autograph_Info[0], Sign_Help);
makeButton(Box, "autograph", (XtCallbackProc) Autograph, "a",
Autograph_Info[1], sign_Help);
makeButton(Box, "ReEdit", (XtCallbackProc) ReEdit, "ReEdit",
Deliver_Info[1], ReEdit_Help);
makeButton(Box, "Cancel", (XtCallbackProc) Done, "cancel",
Deliver_Info[2], Cancel_Help);
makeButton(Box, "Abort", (XtCallbackProc) Done, "Cancel",
Deliver_Info[3], Abort_Help);
makeButton(Box, "Deliver", (XtCallbackProc) Done, "Deliver",
Deliver_Info[0], Deliver_Help);
}
} /* sendMail */
/*
** @(#)writeMail() - Write command s to the mail process.
*/
void
writeMail(char *s)
{
(void) write(mail_fd, s, strlen(s));
} /* writeMail */
syntax highlighted by Code2HTML, v. 0.9.1