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