michael@parns.nsc.com (Michael C. Wagnitz) (03/22/90)
Submitted-by: michael@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@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@sun.com / argv@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.