v13i045: xmail, Part03/11
Michael Wagnitz
stratus!voder!nsc!berlioz.nsc.com!michael at uunet.UU.NET
Sun Jun 16 05:44:27 AEST 1991
Submitted-by: stratus!voder!nsc!berlioz.nsc.com!michael at 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 at 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 at uunet.uu.net
argv at ora.com argv at zipcode.com
More information about the Comp.sources.x
mailing list