v06i042: xmail -- Mail front end for X11, Part02/06
Michael C. Wagnitz
michael at parns.nsc.com
Thu Mar 22 17:55:18 AEST 1990
Submitted-by: michael at parns.nsc.com (Michael C. Wagnitz)
Posting-number: Volume 6, Issue 42
Archive-name: xmail/part02
#! /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 2 (of 6)."
# Contents: actions.c callMail.c callbacks.c icon.mail
# Wrapped by michael at harley on Tue Mar 20 15:28:04 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'actions.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'actions.c'\"
else
echo shar: Extracting \"'actions.c'\" \(26216 characters\)
sed "s/^X//" >'actions.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 TORTIOUS 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. DoAutograph:
X * 2. DoCmd:
X * 3. DoDone:
X * 4. DoNothing:
X * 5. DoReply:
X * 6. DoSave:
X * 7. DoSelected:
X * 8. Folder:
X * 9. Iconify:
X * 10. MyNotify:
X * 11. NextField:
X * 12. PrintMsg:
X * 13. SetAliases:
X * 14. SetCursor:
X * 15. SetDirectory:
X * 16. SetFolders:
X * 17. SetHelp:
X * 18. SetPopup: and
X * 19. SetSelect.
X *
X * Author: Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X
X#include "global.h"
X#include <math.h>
X#include <ctype.h>
X#ifdef SUNOS_4
X#include <dirent.h>
X#else
X#include <sys/dir.h>
X#endif
X
X
X/*
X** @(#)DeleteLine() - Deletes the entire current line from the fileWindow.
X** Simulates the action of the KILL character (ctrl-U).
X*/
X/* ARGSUSED */
XXtActionProc
XDeleteLine(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextBlock textblock;
X XtTextPosition lastPos;
X Cardinal i;
X
X lastPos = TextGetLastPos(w);
X textblock.firstPos = 0;
X textblock.length = 0;
X textblock.ptr = "";
X
X for (i = lastPos; i > StartPos && FileBuf[i - 1] != '\n'; i--);
X XtTextReplace(w, i, lastPos, &textblock);
X Normalize(w);
X} /* DeleteLine */
X
X
X/*
X** @(#)DeleteWord() - Erases the preceding word in the fileWindow buffer.
X** Simulates the action of the WERASE character (ctrl-W).
X*/
X/* ARGSUSED */
XXtActionProc
XDeleteWord(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextBlock textblock;
X XtTextPosition lastPos;
X Cardinal i, j;
X
X textblock.firstPos = 0;
X textblock.length = 0;
X textblock.ptr = "";
X
X lastPos = TextGetLastPos(w);
X for (i = lastPos; i > StartPos && FileBuf[i - 1] == ' '; i--);
X for (j = i; i > StartPos && FileBuf[i - 1] != ' '; i--);
X XtTextReplace(w, i, lastPos, &textblock);
X Normalize(w);
X} /* DeleteWord */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoAutograph() - invoke the Autograph() callback from an action routine
X*/
XXtActionProc
XDoAutograph(w, event, params, num_params)
XWidget w; /* unused */
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X Autograph(w, *params, *params);
X} /* DoAutograph */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoCmd() - send (multi-word) command to mail
X*/
XXtActionProc
XDoCmd(w, event, params, num_params)
XWidget w; /* unused */
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X int i, n;
X
X strcpy(Command, "");
X for (i = 0; i < *num_params; i++) {
X strcat(Command, params[i]);
X strcat(Command, " ");
X }
X if (i)
X Command[strlen(Command)-1] = '\0'; /* Drop the last trailing blank */
X strcat(Command, "\n");
X
X if (mailpid) /* If connections are okay,... */
X writeMail(Command);
X else if (strcmp(Command, "file %\n") != 0)
X Bell("No mail\n"); /* If not 'new mail', complain */
X else {
X for (n = 0; n < mailargc; n++) {
X if (strcmp(mailargv[n], "-f") == 0) {
X for (i = n + 2; i <= mailargc;) mailargv[n++] = mailargv[i++];
X mailargc -= 2; /* throw away an folder argument */
X n -= 2; /* re-examine new mailargv value */
X }
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} /* DoCmd */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoDone() - invoke the Done() callback from an action routine
X*/
XXtActionProc
XDoDone(w, event, params, num_params)
XWidget w; /* unused */
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X Done(w, *params, *params);
X} /* DoDone */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoNothing() - dummy action for unwanted button(s)
X*/
XXtActionProc
XDoNothing(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X return;
X} /* DoNothing */
X
X
X/*
X** @(#)DoReply() - call Reply() CallbackProc from an ActionProc
X*/
X/* ARGSUSED */
XXtActionProc
XDoReply(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X caddr_t client_data;
X caddr_t call_data;
X
X client_data = params[0];
X Reply(w, client_data, call_data);
X} /* DoReply */
X
X
X/*
X** @(#)DoSave() - call Save() CallbackProc from an ActionProc
X*/
X/* ARGSUSED */
XXtActionProc
XDoSave(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X caddr_t client_data;
X caddr_t call_data;
X
X client_data = params[0];
X Save(w, client_data, call_data);
X} /* DoSave */
X
X
X/* ARGSUSED */
X/*
X** @(#)DoSelected() - execute specified command using selected message number
X*/
XXtActionProc
XDoSelected(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextPosition pos;
X int num;
X
X
X if (! mailpid)
X Bell("No mail\n");
X else {
X if (num_params) {
X pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X num = PositionToMsgNumber(pos); /* no current message returns zero */
X if (num &&
X *params[0] != 'n' && *params[0] != '-' && *params[0] != 'u')
X sprintf(Command, "%s %d\n", params[0], num);
X else sprintf(Command, "%s\n", params[0]);
X writeMail(Command);
X }
X }
X} /* DoSelected */
X
X
X/*
X** @(#)Folder() - change folders - must have specified folder name or error
X*/
X/* ARGSUSED */
XXtActionProc
XFolder(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextPosition pos;
X char *p;
X Cardinal n;
X
X pos = TextGetLastPos(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow"));
X if ((n = pos - StartPos) <= 0)
X Bell("Specify a folder name (in the [File: ] box) first\n");
X else {
X FileBuf[StartPos + n] = '\0';
X p = FileBuf + StartPos;
X if (mailpid) {
X sprintf(Command, "file %s\n", p);
X writeMail(Command);
X } else {
X/*
X** We must first re-establish contact with the mail utility.
X** This time, we indicate a specific mail folder to process.
X*/
X XMail.MFileName = XtNewString(p);
X for (n = 0; n < mailargc; n++)
X if (strcmp(mailargv[n], "-f") == 0) {
X mailargv[++n] = XMail.MFileName;
X break;
X }
X if (n == mailargc) { /* if not previously specified */
X mailargv[mailargc++] = "-f";
X mailargv[mailargc++] = XMail.MFileName;
X }
X callMail(mailargc, mailargv);
X strcpy(Command, "Start"); /* Let em know we've re-started */
X }
X }
X} /* Folder */
X
X
X/*
X** @(#)InsertSpace() - prevents user from deleting past the File: prompt.
X** It checks the last position of text, and if it matches StartPos, inserts
X** a space so that delete-previous-character() can only delete the space.
X*/
X/* ARGSUSED */
XXtActionProc
XInsertSpace(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextBlock textblock;
X XtTextPosition lastPos;
X
X lastPos = TextGetLastPos(w);
X XtTextSetInsertionPoint(w, lastPos);
X if (lastPos == StartPos) {
X textblock.firstPos = 0;
X textblock.length = 1;
X textblock.ptr = " ";
X XtTextReplace(w, lastPos, lastPos, &textblock);
X }
X} /* InsertSpace */
X
X
X/* ARGSUSED */
X/*
X** @(#)Iconify() - request window iconification
X*/
XXtActionProc
XIconify(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X#ifndef X11R3
X Display *disp;
X
X disp = XtDisplay(toplevel);
X
X if (! XIconifyWindow(disp, XtWindow(toplevel), DefaultScreen(disp)))
X#endif
X XBell(XtDisplay(toplevel), 33);
X}
X
X
X/* ARGSUSED */
X/*
X** @(#)MyNotify() - call widget callbacks with passed parameter
X*/
XXtActionProc
XMyNotify(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtCallCallbacks(w, XtNcallback, *params);
X} /* MyNotify */
X
X
X/*
X** @(#)NextField() - warps pointer to next field in the Send command window.
X** This allows carriage return to focus attention on the next data requirement.
X*/
X/* ARGSUSED */
XXtActionProc
XNextField(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X String name;
X Widget shell;
X
X
X if (strcmp(w->core.name, "Cc") == 0)
X name = "To"; else
X if (strcmp(w->core.name, "To") == 0)
X name = "Subject"; else
X name = "Cc";
X
X if ((shell = XtNameToWidget(XtParent(w), name)) != NULL)
X XWarpPointer(XtDisplay(toplevel), None, XtWindow(shell), 0,0,0,0, 10, 5);
X
X} /* NextField */
X
X
X/*
X** @(#)PrintMsg() - sends the selected mail message to the system printer
X*/
X/* ARGSUSED */
XXtActionProc
XPrintMsg(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X XtTextPosition pos;
X int num;
X
X if (! mailpid)
X Bell("No mail\n");
X else {
X pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X num = PositionToMsgNumber(pos); /* no current message returns zero */
X if (! num) Bell("No messages to print.\n");
X else {
X sprintf(Command, "| %d \"lpr -p\"\n", num);
X writeMail(Command);
X }
X }
X} /* PrintMsg */
X
X
X/*
X** @(#)SetAliases() - create a menu list of alias names
X*/
X/* ARGSUSED */
XXtActionProc
XSetAliases(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X Arg args[MAXARGS];
X Cardinal i, j, k, n, x, y;
X Display *ad;
X Widget bw, lw, popup, hold, left;
X Window aw, dumy, root;
X
X static String l_Trans = "<Btn3Up>: MenuPopdown(aliasList)";
X
X static String fl_trans = "<EnterWindow>: set() \n\
X <LeaveWindow>: unset() \n\
X <Btn3Up>: notify() MenuPopdown(aliasList)";
X
X static XtCallbackRec fl_callbacks[] = {
X { (XtCallbackProc) GetAliasName, NULL },
X { NULL, NULL }
X };
X
X
X popup = XtNameToWidget(w, "aliasList");
X
X if (! popup || popup->core.being_destroyed) {
X XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(l_Trans));
X popup = XtCreatePopupShell("aliasList",overrideShellWidgetClass,w,args,1);
X
X (void) alias(NULL); /* ensure our aliases list is set */
X/*
X** determine proper label width by finding longest name length
X*/
X i = j = k = 0;
X for (n = 0; aliases[n]; n++)
X if ((k = strlen(aliases[n]->name)) > j) {
X j = k;
X i = n;
X }
X
X if (j == 0) { /* If no alias names exist */
X XtSetArg(args[0], XtNwidth, 1); /* set these so MenuPopup */
X XtSetArg(args[1], XtNheight, 1); /* won't complain about a */
X XtSetValues(popup, (ArgList) args, 2); /* zero width or height */
X XtDestroyWidget(popup); /* it would be nice if MenuPopup() cared */
X } else {
X/*
X** Make equal width command buttons which contain the alias names
X*/
X XtSetArg(args[0], XtNdefaultDistance, 1);
X lw = XtCreateManagedWidget("list", formWidgetClass, popup, args, ONE);
X
X bw = left = NULL;
X XtSetArg(args[0], XtNwidth, XTextWidth(TextFontStr, aliases[i]->name, j) + 14);
X XtSetArg(args[1], XtNfont, TextFontStr);
X XtSetArg(args[2], XtNtranslations, XtParseTranslationTable(fl_trans));
X XtSetArg(args[3], XtNcallback, fl_callbacks);
X
X i = j = 0;
X if (n > 10) { /* If more than ten aliases try to */
X j = (int) sqrt((double)n); /* make list approximately square. */
X i = (int) n / j;
X if (i * j < n) i++;
X if (j > 3) i++;
X if (j > 4) i++;
X if (j > 5) i = 21; /* try to keep box inside main shell */
X }
X
X for (n = 0; aliases[n]; n++) {
X XtSetArg(args[4], XtNlabel, aliases[n]->name);
X XtSetArg(args[5], XtNfromHoriz, left);
X XtSetArg(args[6], XtNfromVert, bw);
X bw = XtCreateManagedWidget("button",commandWidgetClass,lw,args,7);
X
X if (i) { /* post names in a rectangular list */
X if (n % i == 0) hold = bw;
X if ((n+1) % i == 0) {
X left = hold;
X bw = NULL;
X }
X }
X }
X } /* end - if some alias names exist */
X } /* end - if popup does not exist or was being destroyed */
X/*
X** If the menu exists, pop it up, after setting the x,y coordinates
X*/
X if (popup->core.being_destroyed)
X XBell(XtDisplay(toplevel), 33);
X else {
X if (! XtIsRealized(popup))
X XtRealizeWidget(popup);
X aw = XtWindow(w);
X ad = XtDisplay(w);
X n = XMail.buttonHeight / 2;
X root = RootWindow(ad, DefaultScreen(ad));
X XTranslateCoordinates(ad, aw, root, XMail.menuX, n, &x, &y, &dumy);
X XtSetArg(args[0], XtNx, x);
X XtSetArg(args[1], XtNy, y);
X XtSetValues(popup, (ArgList) args, 2);
X }
X} /* SetAliases */
X
X
X/* ARGSUSED */
X/*
X** @(#)SetCursor() - sets wait cursor or restores default
X*/
XXtActionProc
XSetCursor(w, event, params, num_params)
XWidget w;
XXEvent *event; /* unused */
XString *params; /* unused */
XCardinal *num_params; /* any param sets wait cursor */
X{
X Cursor tmpC = None; /* no parameter restores default */
X
X
X if (*num_params)
X tmpC = waitC;
X
X XDefineCursor(XtDisplay(w), XtWindow(w), tmpC);
X
X if (*num_params == 1) /* flush output if only one parameter */
X XFlush(XtDisplay(toplevel));
X} /* SetCursor */
X
X
X/*
X** @(#)SetFolders() - create a menu list of folder names
X*/
X/* ARGSUSED */
XXtActionProc
XSetFolders(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X Arg args[MAXARGS];
X Display *ad;
X Window aw, dumy, root;
X Widget lw, above, this_one, to_left, popup;
X Cardinal x, y, n;
X char trans[BUFSIZ], tmp[BUFSIZ], *p, *List = NULL;
X char foldir[BUFSIZ], *GetMailEnv(), *getenv();
X int foldlen, List_size, newline = 0;
X DIR *dirp;
X
X#ifdef SUNOS_4
X struct dirent *dp;
X#else
X struct direct *dp;
X#endif
X
X
X static String dir_Trans = "\
X <Btn1Down>: SetCursor(True) SetDirectory(%s,%s,%s) SetCursor()";
X
X static String l_Trans = "<Btn3Up>: MenuPopdown(popupList)";
X
X static String fl_trans = "<EnterWindow>: set() \n\
X <LeaveWindow>: unset() \n\
X <Btn3Up>: notify() MenuPopdown(popupList)";
X
X static XtCallbackRec fl_callbacks[] = {
X { (XtCallbackProc) GetFolderName, NULL },
X { NULL, NULL }
X };
X
X
X popup = XtNameToWidget(w, "popupList");
X
X if (! popup || popup->core.being_destroyed) {
X p = GetMailEnv("folder");
X if (p && strlen(p)) {
X sprintf(foldir, "%s/%s/", getenv("HOME"), p);
X XtFree(p);
X } else sprintf(foldir, "%s/", getenv("HOME"));
X foldlen = strlen(foldir);
X
X XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(l_Trans));
X popup = XtCreatePopupShell("popupList",overrideShellWidgetClass,w,args,1);
X
X if (mailpid)
X List = QueryMail("folders");
X else {
X if ((dirp = opendir(foldir)) == NULL)
X XtError("SetFolder: Can't access mail folder directory");
X/*
X** allocate one block to 'List' to begin with
X*/
X List_size = BUFSIZ;
X List = XtMalloc(List_size);
X strcpy(List, "");
X x = 0;
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
X if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
X if (strlen(List) + strlen(dp->d_name) + 2 > List_size) {
X List_size += BUFSIZ;
X List = XtRealloc(List, List_size);
X }
X strcat(List, " ");
X strcat(List, dp->d_name);
X if (++x % 6 == 0) {
X x = 0;
X strcat(List, "\n");
X }
X }
X List = XtRealloc(List, strlen(List) + 1);
X closedir(dirp);
X }
X/*
X** determine proper label width by finding longest word length
X*/
X strcpy(trans, "");
X for (x = 0, p = List; *p; p++) {
X if (*p == ' ' || *p == '\n' || *p == '\t') {
X if (x) {
X tmp[x] = '\0';
X x = 0;
X if (strlen(trans) < strlen(tmp))
X strcpy(trans, tmp);
X }
X } else tmp[x++] = *p;
X }
X
X if (x) {
X tmp[x] = '\0';
X if (strlen(trans) < strlen(tmp))
X strcpy(trans, tmp);
X }
X
X if ((n = strlen(trans)) == 0) { /* if there are no mail folders */
X n = 0; /* set a dummy width and */
X XtSetArg(args[n], XtNwidth, 1); n++; /* height so MenuPopup() */
X XtSetArg(args[n], XtNheight, 1); n++; /* won't complain about */
X XtSetValues(popup, (ArgList) args, n); /* zero width or height */
X
X XtDestroyWidget(popup); /* it would be nice if MenuPopup() cared */
X } else {
X XtSetArg(args[0], XtNdefaultDistance, 1);
X lw = XtCreateManagedWidget("list", formWidgetClass, popup, args, ONE);
X/*
X** Now, make equal width command buttons which contain the folder names
X*/
X XtSetArg(args[0], XtNwidth, XTextWidth(TextFontStr, trans, n) + 14);
X XtSetArg(args[1], XtNfont, TextFontStr);
X XtSetArg(args[2], XtNtranslations, XtParseTranslationTable(fl_trans));
X XtSetArg(args[3], XtNcallback, fl_callbacks);
X
X above = this_one = to_left = NULL;
X for (x = 0, p = List; *p; p++) {
X if (*p == '\n') {
X newline = 1;
X }
X if (*p == ' ' || *p == '\n' || *p == '\t') {
X if (x) {
X tmp[x] = '\0';
X/*
X** If this 'folder' is really a directory, mark it with a trailing slash '/'
X*/
X foldir[foldlen] = '\0';
X strcat(foldir, &tmp[1]);
X if ((dirp = opendir(foldir)) != NULL) {
X tmp[x++] = '/';
X tmp[x] = '\0';
X }
X n = 4;
X XtSetArg(args[n], XtNlabel, tmp); n++;
X XtSetArg(args[n], XtNfromHoriz, to_left); n++;
X if (! to_left) XtSetArg(args[n], XtNfromVert, above); n++;
X
X this_one = XtCreateManagedWidget("listbutton", commandWidgetClass,
X lw, args, n);
X if (to_left == NULL) above = this_one;
X to_left = this_one;
X if (newline) {
X newline = 0;
X to_left = NULL;
X }
X x = 0;
X/*
X** If this 'folder' is a directory, add a button to popup a menu of filenames.
X*/
X if (dirp != NULL) {
X closedir(dirp);
X sprintf(trans, dir_Trans, &tmp[1], foldir, "0");
X XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
X }
X }
X } else {
X if (x == 0) tmp[x++] = '+'; /* start folder names with a 'plus' */
X tmp[x++] = *p;
X }
X }
X
X if (x) {
X tmp[x] = '\0';
X foldir[foldlen] = '\0';
X strcat(foldir, &tmp[1]);
X if ((dirp = opendir(foldir)) != NULL) {
X tmp[x++] = '/';
X tmp[x] = '\0';
X }
X n = 4;
X XtSetArg(args[n], XtNlabel, tmp); n++;
X XtSetArg(args[n], XtNfromHoriz, to_left); n++;
X if (! to_left) XtSetArg(args[n], XtNfromVert, above); n++;
X
X this_one = XtCreateManagedWidget("listbutton", commandWidgetClass,
X lw, args, n);
X if (dirp != NULL) {
X closedir(dirp);
X sprintf(trans, dir_Trans, &tmp[1], foldir, "0");
X XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
X }
X }
X }
X } /* end - if some trans strlen */
X/*
X** If folders menu exists, pop it up, after setting x,y coordinates
X*/
X if (popup->core.being_destroyed) {
X Bell("No mail folders exist\n");
X } else {
X if (! XtIsRealized(popup)) /* see if folder list is small */
X XtRealizeWidget(popup); /* enough to fit if anchored at */
X
X n = 3 * (XMail.buttonWidth + 12); /* folder button instead of cmdWin */
X if (popup->core.width + n <= XMail.shellWidth) {
X aw = XtWindow(w);
X ad = XtDisplay(w);
X n = XMail.buttonHeight / 2;
X } else {
X aw = XtWindow(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"));
X ad = XtDisplay(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"));
X n = XMail.commandMinHeight / 2;
X }
X root = RootWindow(ad, DefaultScreen(ad));
X
X XTranslateCoordinates(ad, aw, root, XMail.menuX, n, &x, &y, &dumy);
X
X n = 0;
X XtSetArg(args[n], XtNx, x); n++;
X XtSetArg(args[n], XtNy, y); n++;
X XtSetValues(popup, (ArgList) args, n);
X }
X
X XtFree(List);
X
X} /* SetFolders */
X
X
X/*
X** @(#)SetHelp() - set named string source as text for and popup help window.
X*/
X/* ARGSUSED */
XXtActionProc
XSetHelp(w, event, params, num_params)
XWidget w; /* unused */
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X Arg args[3];
X Widget tw;
X Window aw, dumy;
X Display *ad;
X int indx, status, x, y, scn;
X
X
X if (*num_params != 1)
X XtError("Wrong parameter count passed to SetHelp()");
X
X for (indx = 0; HelpNames[indx]; indx++)
X if (strcmp(params[0], HelpNames[indx]) == 0) break;
X
X if (HelpNames[indx]) {
X XtTextSetSource(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), "helpWindow"), HelpStrings[indx], (XtTextPosition) 0);
X/*
X** Position help relative to textWindow
X*/
X tw = WidgetOf(WidgetOf(toplevel, "vpane"), "textWindow");
X aw = XtWindow(tw);
X ad = XtDisplay(tw);
X scn = DefaultScreen(ad);
X
X XTranslateCoordinates(ad, aw, RootWindow(ad, scn), XMail.helpX, XMail.helpY,
X &x, &y, &dumy);
X
X XtSetArg(args[0], XtNx, x);
X XtSetArg(args[1], XtNy, y);
X XtSetValues(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), args, 2);
X
X XtPopup(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), XtGrabNone);
X }
X} /* SetHelp */
X
X
X/*
X** @(#)SetPopup() - place named popup at menuX, menuY relative to Widget w.
X*/
X/* ARGSUSED */
XXtActionProc
XSetPopup(w, event, params, num_params)
XWidget w;
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X Widget shell;
X Window aw, dumy;
X Display *ad;
X String p;
X int x, y, scn;
X Arg args[2];
X
X
X if (*num_params == 0)
X XtError("No name parameter passed to SetPopup().");
X
X p = params[0];
X
X if ((shell = XtNameToWidget(w, p)) == NULL)
X XtError("Shell name passed to SetPopup() not found in popup list.");
X
X if (! XtIsRealized(shell))
X XtRealizeWidget(shell); /* to get width and height values */
X/*
X** Position menus relative to current window
X*/
X aw = XtWindow(w);
X ad = XtDisplay(w);
X scn = DefaultScreen(ad);
X
X XTranslateCoordinates(ad, aw, RootWindow(ad, scn), XMail.menuX, XMail.menuY,
X &x, &y, &dumy);
X/*
X** Keep popup menu within root window borders (don't place it off-screen)
X*/
X if (x + shell->core.width > RootWidth)
X x = RootWidth - shell->core.width;
X
X if (y + shell->core.height > RootHeight)
X y = RootHeight - shell->core.height;
X
X XtSetArg(args[0], XtNx, x);
X XtSetArg(args[1], XtNy, y);
X XtSetValues(shell, (ArgList)args, 2);
X} /* SetPopup */
X
X
X/* ARGSUSED */
X/*
X** @(#)SetSelect() - highlight the index number of the selected message
X*/
XXtActionProc
XSetSelect(w, event, params, num_params)
XWidget w;
XXEvent *event; /* unused */
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X XClientMessageEvent cm;
X XtTextPosition pos, left, right;
X String s;
X
X
X pos = XtTextGetInsertionPoint(w);
X
X for (s = IndexBuf + pos; s > IndexBuf && *(s - 1) != '\n'; s--);
X
X pos = s - IndexBuf;
X/*
X** use XSendEvent to remove any prior selection highlight
X*/
X cm.type = ClientMessage;
X cm.display = XtDisplay(w);
X cm.message_type = XInternAtom(XtDisplay(w), "KILL_SELECTION", FALSE);
X cm.window = XtWindow(w);
X cm.format = 32;
X cm.data.l[0] = XA_PRIMARY;
X
X XSendEvent(XtDisplay(w), cm.window, TRUE, NoEventMask, &cm);
X
X for (; *s && !isdigit(*s); s++);
X left = s - IndexBuf;
X for (; *s && isdigit(*s); s++);
X right = s - IndexBuf;
X
X XtTextSetSelection(w, left, right);
X
X XtTextSetInsertionPoint(w, pos);
X} /* SetSelect */
X
X
X/*
X** @(#)Quit() - call DoQuit() CallbackProc from the Quit ActionProc
X*/
X/* ARGSUSED */
XXtActionProc
XQuit(w, event, params, num_params)
XWidget w; /* unused */
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X caddr_t client_data;
X caddr_t call_data;
X
X client_data = params[0];
X DoQuit(w, client_data, call_data);
X} /* Quit */
END_OF_FILE
if test 26216 -ne `wc -c <'actions.c'`; then
echo shar: \"'actions.c'\" unpacked with wrong size!
fi
# end of 'actions.c'
fi
if test -f 'callMail.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'callMail.c'\"
else
echo shar: Extracting \"'callMail.c'\" \(5706 characters\)
sed "s/^X//" >'callMail.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 TORTIOUS 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 <sgtty.h>
X#include "global.h"
X
XFILE *mailfp = NULL; /* file pointer to mail */
Xint mail_fd; /* mail process master tty id */
Xint mailpid; /* mail process id */
Xint mailInputId; /* mail input id */
X
Xstatic char *pty = "/dev/pty??"; /* master side of pseudo-terminal */
Xstatic char *tty = "/dev/tty??"; /* slave side of pseudo-terminal */
X
X/*
X * Xmail talks to mail through a pseudo terminal which is a pair of master
X * and slave devices: /dev/pty?? and /dev/tty??, where ?? goes from p0 to
X * qf (system dependent). The pty is opened for both read and write.
X */
X/*
X** @(#)openMaster() - open master side of pipe
X*/
Xstatic int
XopenMaster()
X{
X int i, master;
X char c;
X
X for (c='p'; c<='s'; c++) {
X pty[8] = c;
X for (i=0; i<16; i++) {
X pty[9] = "0123456789abcdef"[i];
X if ((master = open(pty, O_RDWR)) != -1)
X return (master);
X }
X }
X fprintf(stderr, "xmail: all ptys in use\n");
X exit(1);
X} /* openMaster */
X
X
X/*
X** @(#)openSlave() - open slave side of pipe
X*/
Xstatic int
XopenSlave()
X{
X int slave;
X
X tty[8] = pty[8];
X tty[9] = pty[9];
X if ((slave = open(tty, O_RDWR)) != -1) {
X return (slave);
X } else {
X fprintf(stderr, "open: cannot open slave pty %s", tty);
X exit(1);
X }
X} /* openSlave */
X
X
X/*
X** @(#)callMail() - fork child to execute mail and attach to xmail input
X*/
X/* ARGSUSED */
Xvoid
XcallMail(argc, argv)
Xint argc;
Xchar *argv[];
X{
X struct sgttyb Sgtty;
X int master; /* file descriptor of master pty */
X int slave; /* file descriptor to slave pty */
X char *Mailpgm, /* name of executable Mailpgm */
X errmsg[BUFSIZ];
X
X Mailpgm = (char *) getenv("XMAILER"); /* first looks up env var */
X if (Mailpgm == NULL)
X Mailpgm = XtNewString(XMAILER);
X
X master = openMaster();
X slave = openSlave();
X
X ioctl(slave, TIOCGETP, &Sgtty);
X Sgtty.sg_flags &= ~(ECHO|CRMOD); /* no echo, no NL to CR */
X ioctl(slave, TIOCSETP, &Sgtty);
X
X mailpid = fork();
X if (mailpid == -1) {
X perror("Cannot fork mail process");
X exit(1);
X } else if (mailpid) {
X /*
X * Parent : close the slave side of pty
X * close stdin and stdout
X * set the mail file descriptor to nonblocking mode
X * open file pointer with read/write access to mail
X * set unbuffered mode
X * register mail input with X
X */
X close(slave);
X if (master != 0) /* if we're restarting, master IS 0 */
X close(0);
X close(1);
X fcntl(master, F_SETFL, FNDELAY);
X mail_fd = master; /* use descriptor for reads */
X mailfp = fdopen(master, "r+"); /* need mailfp for fputs */
X setbuf(mailfp, NULL);
X mailInputId = XtAddInput(master, XtInputReadMask, readMail, NULL);
X } else {
X /*
X * Child : close master side of pty
X * redirect stdin, stdout, stderr of mail to pty
X * unbuffer output data from mail
X * exec mail with arguments
X */
X close(master);
X dup2(slave, 0);
X dup2(slave, 1);
X dup2(slave, 2);
X if (slave > 2)
X close(slave);
X fcntl(1, F_SETFL, FAPPEND);
X setbuf(stdout, NULL);
X argv[0] = Mailpgm;
X execvp(Mailpgm, argv);
X sprintf(errmsg, "callMail: Cannot call %s", Mailpgm);
X perror(errmsg);
X exit(1);
X }
X} /* callMail */
END_OF_FILE
if test 5706 -ne `wc -c <'callMail.c'`; then
echo shar: \"'callMail.c'\" unpacked with wrong size!
fi
# end of 'callMail.c'
fi
if test -f 'callbacks.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'callbacks.c'\"
else
echo shar: Extracting \"'callbacks.c'\" \(17314 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 TORTIOUS 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 <sys/wait.h>
X#include <sys/stat.h>
X
X
X/*
X** @(#)Autograph() - Add user's Sign or sign autograph to outgoing mail
X** Then make button insensitive, to prevent multiple calls.
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 if (strcmp("Autograph", w->core.name) == 0)
X XtSetSensitive(w, False); /* Don't let us be pressed more than once */
X else XtSetSensitive(XtParent(XtParent(XtParent(w))), False); /* (of popup) */
X
X strcpy(tmp, "Sign"); /* Default will be to use Sign autograph, */
X if (C && *C == 'a') /* but if asked use their sign autograph. */
X strcpy(tmp, "sign");
X autograph = GetMailEnv(tmp);
X if (autograph) {
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*/
X/* ARGSUSED */
XXtCallbackProc
XDone(w, closure, call_data)
XWidget w;
Xcaddr_t closure;
Xcaddr_t call_data;
X{
X Widget shell;
X FILE *fp;
X char *p, *record, *folder, *getenv();
X char From[BUFSIZ], Copy[BUFSIZ], s[BUFSIZ];
X struct stat st_buf;
X
X
X for (shell = w;
X strcmp(shell->core.name, "popup");
X shell = XtParent(shell));
X XtDestroyWidget(shell); /* remove our popup prompt box */
X/*
X** first, prepare the header information (in a second temporary file)
X*/
X strcat(tmpName, "_");
X if ((fp = fopen(tmpName, "w")) != NULL) {
X if (*Recipient)
X fprintf(fp, "To: %s\n", alias(Recipient));
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 fprintf(fp, "Cc: %s\n", alias(CcBuf));
X
X fprintf(fp, "\n"); /* separate header from text */
X fclose(fp);
X }
X tmpName[strlen(tmpName) - 1] = '\0'; /* Drop our marker for now */
X
X if (strcmp(closure, "Deliver") == 0) {
X /*
X ** mail header information and text in temporary file using sendmail
X */
X if (*Recipient && (*SubjBuf ||
X (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X sprintf(s, "cat %s_ %s | /usr/lib/sendmail -toi -om 2> /dev/null", tmpName, tmpName);
X system(s);
X/*
X** If user has set 'record' in their .mailrc, add a message copy to that file
X*/
X if (record = GetMailEnv("record")) {
X p = folder = NULL;
X if (*record == '/' || (p = GetMailEnv("outfolder")) == NULL ||
X (folder = GetMailEnv("folder")) == NULL) {
X strcpy(Copy, record);
X if (p) XtFree(p);
X } else {
X if (*folder == '/') {
X if (*record != '+')
X sprintf(Copy, "%s/%s", folder, record);
X else
X sprintf(Copy, "%s/%s", folder, &record[1]);
X } else {
X if (*record != '+')
X sprintf(Copy, "%s/%s/%s", getenv("HOME"), folder, record);
X else
X sprintf(Copy,"%s/%s/%s",getenv("HOME"),folder,&record[1]);
X }
X XtFree(folder);
X XtFree(p);
X }
X sprintf(From, "From %s `date`", getenv("USER"));
X sprintf(s, "echo \"%s\" >> %s;cat %s_ %s >> %s 2> /dev/null; echo \"\" >> %s",
X From, Copy, tmpName, tmpName, Copy, Copy);
X system(s);
X XtFree(record);
X }
X } else {
X if (! *Recipient)
X Bell("No recipient specified\n");
X else
X Bell("No subject and no message\n");
X }
X } else {
X if (*closure == 'c') { /* save any partial message in our dead file */
X if ((record = GetMailEnv("DEAD")) == NULL)
X sprintf(Copy, "%s/dead.letter", getenv("HOME"));
X else {
X if (*record == '/')
X strcpy(Copy, record);
X else if (*record != '+') /* default path is home directory */
X sprintf(Copy, "%s/%s", getenv("HOME"), record);
X else /* dead letters will never be legal mail messages */
X sprintf(Copy, "%s/%s", getenv("HOME"), &record[1]);
X XtFree(record);
X }
X if (*Recipient && (*SubjBuf ||
X (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X sprintf(s, "cat %s_ %s >> %s 2> /dev/null", tmpName, tmpName, Copy);
X system(s);
X sprintf(s, "Canceled letter appended to %s\n", Copy);
X Bell(s);
X } else Bell("Nothing to save in your dead letter box\n");
X }
X }
X/*
X** remove any message text that may have been created
X*/
X sprintf(s, "rm -f %s_ %s", tmpName, tmpName);
X system(s);
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 i, n;
X
X
X sprintf(Command, "%s\n", closure);
X if (mailpid) /* If connections are okay,... */
X writeMail(Command);
X else if (strcmp(Command, "file %\n") != 0 && strcmp(Command, "inc\n") != 0)
X Bell("No mail\n"); /* But if no new mail, complain */
X else {
X for (n = 0; n < mailargc; n++) {
X if (strcmp(mailargv[n], "-f") == 0) {
X for (i = n + 2; i <= mailargc;) mailargv[n++] = mailargv[i++];
X mailargc -= 2; /* throw away any folder argument */
X n -= 2; /* re-examine new mailargv value */
X }
X }
X callMail(mailargc, mailargv); /* restart the mail connections */
X strcpy(Command, "Start"); /* Let em know we've re-started */
X UnsetNewmail(w, closure, call_data);
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 union wait status;
X Display *dpy = XtDisplay(toplevel);
X
X if (mailpid) {
X sprintf(Command, "%s\n", closure);
X writeMail(Command);
X wait3(&status, WNOHANG, NULL);
X }
X XtDestroyWidget(toplevel);
X XCloseDisplay(dpy);
X exit(0);
X} /* DoQuit */
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 XtTextPosition pos;
X int num;
X
X if (! mailpid)
X Bell("No mail\n");
X else {
X pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X num = PositionToMsgNumber(pos); /* no current message returns zero */
X if (num) sprintf(Command, "%s %d\n", client_data, num);
X else sprintf(Command, "%s \n", client_data);
X writeMail(Command);
X }
X} /* DoWith */
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, call_data;
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);
X
X shell = XtParent(XtParent(XtParent(w)));
X
X if (TextGetLastPos(shell))
X writeText(shell, ", ", 1);
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, indx;
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 strcpy(tmp, "");
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(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow"), buf, 0);
X} /* GetFolderName */
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 Cardinal *num_params;
X FILE *fp;
X Position pos;
X String *params, p, q, r, txt, author, subject, others, date, reference;
X XEvent *event;
X int erasable = 0;
X
X
X txt = author = subject = others = date = reference = "";
X if (*client_data != 's') {
X if ((fp = fopen(tmpName, "w")) == NULL)
X Bell("xmail: Cannot open temp file for writing\n");
X
X pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X sprintf(Command, "P %d", PositionToMsgNumber(pos));
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#ifdef SUNOS_4
X if ((p = GetMailEnv("indentprefix")) != NULL)
X erasable = 1;
X else
X#endif
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 for (p = txt; *p; p++) {
X if (strcmp(p, "") == 0 || strncmp(p, "Status:", 7) == 0) break;
X
X if (strncmp(p, "Return-Path:", 12) == 0) {
X author = p + 14;
X for (p = author; *p && *p != '>'; p++);
X if (*p) *p++ = '\0';
X for (; *p && *p != '\n'; p++);
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 reference = p + 6;
X for (p = reference; *p && *p != '\n'; p++);
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 if (*p) *p = '\0';
X }
X
X else if (strncmp(p, "Cc:", 3) == 0) {
X others = p + 4;
X for (p = others; *p && *p != '\n'; p++);
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 others = ""; /* If not [rR]eplyall, make sender enter any Cc: */
X
X if (fp) fclose(fp);
X
X XtFree(txt);
X } /* end - if client_data does not equal 's' */
X
X if (*client_data != 'S' && *client_data != 's')
X strcpy(Recipient, author);
X
X strcpy(InReply, "");
X if (*client_data != 's' && *reference && *date) {
X r = (*client_data == 'S') ? "Forwarding" : "In-Reply-To";
X sprintf(InReply, "%s: Mail from '%s' dated %s", r, reference, date);
X }
X
X if (*subject) {
X strcpy(SubjBuf, "");
X if (strncmp(subject, "Re: ", 4) != 0)
X strcat(SubjBuf, "Re: ");
X strcat(SubjBuf, subject);
X }
X
X strcpy(CcBuf, others);
X
X sendMail(w);
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, *getenv();
X Cardinal num, n;
X Position pos;
X
X
X if (! mailpid)
X Bell("No mail\n");
X else {
X pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X num = PositionToMsgNumber(pos); /* no current message returns zero */
X
X if (*cmd == 'C' || *cmd == 'S' || *cmd == 'W' || 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(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "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 if (*p == '+') { /* add folder full path to name */
X if ((q = GetMailEnv("folder")) == NULL)
X sprintf(Command,"%s %d %s/%s\n", cmd, num, getenv("HOME"), ++p);
X else {
X sprintf(Command,"%s %d %s/%s/%s\n", cmd, num, getenv("HOME"), q, ++p);
X XtFree(q);
X }
X } else sprintf(Command,"%s %d %s\n",cmd, num, p);
X XtFree(p);
X } else sprintf(Command, "%s %d %s/mbox\n", cmd, num, getenv("HOME"));
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 = WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "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;
X
X if (Highlighted) {
X cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "Newmail");
X XSetWindowBackground(XtDisplay(toplevel), XtWindow(cw), cw->core.background_pixel);
X XtUnmapWidget(cw);
X XtMapWidget(cw);
X Highlighted = 0;
X }
X} /* UnsetNewmail */
END_OF_FILE
if test 17314 -ne `wc -c <'callbacks.c'`; then
echo shar: \"'callbacks.c'\" unpacked with wrong size!
fi
# end of 'callbacks.c'
fi
if test -f 'icon.mail' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'icon.mail'\"
else
echo shar: Extracting \"'icon.mail'\" \(3855 characters\)
sed "s/^X//" >'icon.mail' <<'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. National Semiconductor
X * Corporation makes no representations about the suitability of this software
X * for any purpose. It is provided "as is" without express or implied warranty.
X *
X * NATIONAL SEMICONDUCTOR CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author: Michael C. Wagnitz - National Semiconductor Corporation
X *
X */
X
X#define mail_width 56
X#define mail_height 56
X
Xstatic char mail_bits[] = {
X 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
X 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
X 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
X 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
X 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf0, 0x00, 0x00, 0x00, 0x00,
X 0x00, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x30, 0x03, 0x00,
X 0x00, 0x00, 0x00, 0x07, 0x30, 0x06, 0x00, 0x00, 0x00, 0x80, 0x01, 0x30,
X 0x06, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0xe0,
X 0x1f, 0xb0, 0x07, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xf0, 0x06, 0x00, 0x00,
X 0x00, 0xb8, 0xee, 0x70, 0x06, 0x00, 0x00, 0x00, 0x5c, 0xd7, 0x31, 0x06,
X 0x00, 0x00, 0x00, 0xae, 0xae, 0x39, 0x06, 0x00, 0x00, 0x00, 0x56, 0x5d,
X 0x3f, 0x06, 0x00, 0x00, 0x00, 0x8a, 0xb4, 0x37, 0x06, 0x00, 0x00, 0x00,
X 0x46, 0x64, 0x33, 0x06, 0x00, 0x00, 0x00, 0x22, 0xc4, 0x33, 0x06, 0x00,
X 0x00, 0x00, 0x12, 0x84, 0x33, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x04, 0x33,
X 0x06, 0x00, 0xff, 0xff, 0xfa, 0x07, 0x33, 0xf6, 0xff, 0x00, 0x00, 0x0a,
X 0x00, 0x33, 0x06, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x03, 0x03, 0x00, 0x00,
X 0x00, 0x3a, 0x80, 0x83, 0x01, 0x00, 0x00, 0x00, 0x7a, 0x40, 0xc3, 0x00,
X 0x00, 0x00, 0x00, 0xfa, 0xa0, 0x63, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x51,
X 0x33, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x0b, 0x3b, 0x00, 0x00, 0x00, 0x00,
X 0x3a, 0x06, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x37, 0x00, 0x00,
X 0x00, 0x00, 0x0a, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x31,
X 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02,
X 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x6a, 0x31, 0x00, 0x00, 0x00,
X 0x00, 0xaa, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x00, 0xba, 0x2a, 0x31, 0x00,
X 0x00, 0x00, 0x00, 0x2a, 0x29, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
X 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00,
X 0x52, 0x15, 0x31, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x2a, 0x31, 0x00, 0x00,
X 0xee, 0x28, 0x82, 0x02, 0x31, 0x20, 0x11, 0x88, 0x22, 0x12, 0x11, 0x2d,
X 0x29, 0x00, 0x29, 0xc8, 0xa2, 0x0b, 0xad, 0x40, 0x9a, 0xc4, 0x4a, 0xc6,
X 0x86, 0x87, 0x4e, 0x1a, 0xcb, 0x67, 0x07, 0xc2, 0x7e, 0xee, 0x3f, 0xbf,
X 0xdc, 0x8e, 0xc7, 0xd2, 0x33, 0xa5, 0x2a, 0x8f, 0x1d, 0x63, 0x72, 0xb9,
X 0x7b, 0xfd, 0x72, 0xf9, 0x7f, 0x4e, 0xe7, 0xd4 };
END_OF_FILE
if test 3855 -ne `wc -c <'icon.mail'`; then
echo shar: \"'icon.mail'\" unpacked with wrong size!
fi
# end of 'icon.mail'
fi
echo shar: End of archive 2 \(of 6\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 6 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
dan
-----------------------------------------------------------
O'Reilly && Associates
argv at sun.com / argv at ora.com
632 Petaluma Ave, Sebastopol, CA 95472
800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list