home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xmail / part04 < prev    next >
Encoding:
Text File  |  1993-04-27  |  57.5 KB  |  1,769 lines

  1. Newsgroups: comp.sources.x
  2. From: markham@cadence.com (Jeff Markham)
  3. Subject: v19i029:  xmail - X Window System interface to the mail program, Part04/10
  4. Message-ID: <1993Mar10.202831.10887@sparky.imd.sterling.com>
  5. X-Md4-Signature: 66309127f61e3679b5542cc6152d4520
  6. Date: Wed, 10 Mar 1993 20:28:31 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: markham@cadence.com (Jeff Markham)
  10. Posting-number: Volume 19, Issue 29
  11. Archive-name: xmail/part04
  12. Environment: X11
  13. Supersedes: xmail: Volume 15, Issue 18-26
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  Mailwatch.h actions.c xmail.c
  20. # Wrapped by chris@sparky on Wed Mar 10 14:17:46 1993
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 4 (of 10)."'
  24. if test -f 'Mailwatch.h' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'Mailwatch.h'\"
  26. else
  27.   echo shar: Extracting \"'Mailwatch.h'\" \(1082 characters\)
  28.   sed "s/^X//" >'Mailwatch.h' <<'END_OF_FILE'
  29. X/*
  30. X * Author:  Dan heller
  31. X */
  32. X
  33. X#ifndef _XtMailwatch_h
  34. X#define _XtMailwatch_h
  35. X
  36. X/*
  37. X * Mailwatch widget; looks a lot like the Mailbox widget, don't it...
  38. X */
  39. X
  40. X#ifndef XtNupdate
  41. X#define XtNupdate    "update"    /* Int: how often to check mail */
  42. X#endif /* XtNupdate */
  43. X
  44. X#ifndef XtNfile
  45. X#define XtNfile        "file"        /* String:  file name to check */
  46. X#endif /* Xtfile */
  47. X
  48. X#define XtNbell        "bell"        /* boolean to ring bell on new mail */
  49. X#define XtNmailFlag    "mailFlag"    /* path to icon file for mail */
  50. X#define XtNnoMailFlag    "noMailFlag"    /* path to icon file for no mail */
  51. X#define XtNmail        "mail"        /* For XtGetValues to get mail info */
  52. X
  53. X#define XtCPixmapMask    "PixmapMask"
  54. X#define XtCMailFlag    "MailFlag"    /* Class name of icon file for mail */
  55. X#define XtCNoMailFlag    "NoMailFlag"    /* Class name of icon file for nomail */
  56. X
  57. X/* structures */
  58. Xtypedef struct _MailwatchRec *MailwatchWidget;  /* see MailwatchP.h */
  59. Xtypedef struct _MailwatchClassRec *MailwatchWidgetClass;  /* see MailwatchP.h */
  60. X
  61. Xextern WidgetClass mailwatchWidgetClass;
  62. X
  63. X#endif /* _XtMailwatch_h */
  64. X/* DON'T ADD STUFF AFTER THIS #endif */
  65. END_OF_FILE
  66.   if test 1082 -ne `wc -c <'Mailwatch.h'`; then
  67.     echo shar: \"'Mailwatch.h'\" unpacked with wrong size!
  68.   fi
  69.   # end of 'Mailwatch.h'
  70. fi
  71. if test -f 'actions.c' -a "${1}" != "-c" ; then 
  72.   echo shar: Will not clobber existing file \"'actions.c'\"
  73. else
  74.   echo shar: Extracting \"'actions.c'\" \(33275 characters\)
  75.   sed "s/^X//" >'actions.c' <<'END_OF_FILE'
  76. X/*
  77. X * xmail - X window system interface to the mail program
  78. X *
  79. X * Copyright 1990,1991,1992 by National Semiconductor Corporation
  80. X *
  81. X * Permission to use, copy, modify, and distribute this software and its
  82. X * documentation for any purpose is hereby granted without fee, provided that
  83. X * the above copyright notice appear in all copies and that both that
  84. X * copyright notice and this permission notice appear in supporting
  85. X * documentation, and that the name of National Semiconductor Corporation not
  86. X * be used in advertising or publicity pertaining to distribution of the
  87. X * software without specific, written prior permission.
  88. X *
  89. X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  90. X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  91. X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  92. X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  93. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  94. X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  95. X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  96. X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  97. X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  98. X * PERFORMANCE OF THIS SOFTWARE.
  99. X *
  100. X * The following software modules were created and are Copyrighted by
  101. X * National Semiconductor Corporation:
  102. X *
  103. X *  1. initfoldir:
  104. X *  2. str_compare:
  105. X *  3. CheckInsert:
  106. X *  4. EraseIt:
  107. X *  5. DeleteChar:
  108. X *  6. DeleteLine:
  109. X *  7. DeleteWord:
  110. X *  8. DoCmd:
  111. X *  9. DoDone:
  112. X * 10. DoNothing:
  113. X * 11. DoReply:
  114. X * 12. DoSave:
  115. X * 13. DoSelected:
  116. X * 14. Folder:
  117. X * 15. Iconify:
  118. X * 16. MyNotify:
  119. X * 17. NextField:
  120. X * 18. PrintMsg:
  121. X * 19. Quit:
  122. X * 20. SetAliases:
  123. X * 21. SetNewness:
  124. X * 22. SetFolders:
  125. X * 23. SetMenu:
  126. X * 24. SetPopup:
  127. X * 25. SetSelect: and
  128. X * 26. ShowHelp.
  129. X *
  130. X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  131. X *
  132. X */
  133. X
  134. X
  135. X#include "global.h"
  136. X#include <unistd.h>
  137. X#include <ctype.h>
  138. X#include <sys/stat.h>
  139. X#include <pwd.h>
  140. X#include "xmailregexp.h"
  141. X
  142. X#ifdef    AIXV3
  143. X#include <sys/mode.h>
  144. X#endif
  145. X
  146. X#ifndef    S_ISDIR
  147. X#define    S_ISDIR(m)    (((m)&S_IFMT) == S_IFDIR)
  148. X#endif
  149. X
  150. X#ifdef USE_DIRENT
  151. X#include <dirent.h>
  152. X#else
  153. X#include <sys/dir.h>
  154. X#endif
  155. X
  156. X
  157. Xvoid
  158. Xinitfoldir()
  159. X{
  160. X String    cp;
  161. X
  162. X
  163. X if (! foldir[0])
  164. X    if (cp = GetMailEnv("folder")) {
  165. X       if (strchr("/.", *cp))
  166. X          (void) strcpy(foldir, cp);
  167. X       else
  168. X          (void) sprintf(foldir, "%s/%s", HOME, cp);
  169. X
  170. X       XtFree((String) cp);
  171. X       if (LASTCH(foldir) != '/')
  172. X          (void) strcat(foldir, "/");
  173. X      }
  174. X}
  175. X
  176. X
  177. X/*
  178. X** @(#)str_compare() - compare function for the qsort of folder names
  179. X*/
  180. Xstr_compare(s1, s2)
  181. Xchar **s1, **s2;
  182. X{
  183. X return(strcmp(*s1, *s2));
  184. X}
  185. X
  186. X
  187. X/*
  188. X** @(#)CheckInsert() - prevents the user from munging up the File: prompt.
  189. X** If the current insertion point is less than the minimum StartPos, move
  190. X** the insertion point to the StartPos.
  191. X*/
  192. X/* ARGSUSED */
  193. XXtActionProc
  194. XCheckInsert(w, event, params, num_params)
  195. XWidget w;
  196. XXEvent *event;
  197. XString *params;
  198. XCardinal *num_params;
  199. X{
  200. X if (XawTextGetInsertionPoint(w) < StartPos)
  201. X     XawTextSetInsertionPoint(w, (XawTextPosition) StartPos);
  202. X} /* CheckInsert */
  203. X
  204. X
  205. X/*
  206. X** @(#)EraseIt() - Delete the specified portion of text.
  207. X*/
  208. Xvoid
  209. XEraseIt(w, i, pos)
  210. XWidget    w;
  211. XXawTextPosition    i, pos;
  212. X{
  213. X XawTextBlock    textblock;
  214. X
  215. X textblock.firstPos = 0;
  216. X textblock.length   = 0;
  217. X textblock.ptr      = "";
  218. X
  219. X XawTextReplace(w, i, pos, &textblock);
  220. X
  221. X XawTextSetInsertionPoint(w, (XawTextPosition) i);
  222. X} /* EraseIt */
  223. X
  224. X
  225. X/*
  226. X** @(#)DeleteChar() - prevents the user from deleting past the File: prompt.
  227. X** If the current insertion point is greater than the minimum StartPos, then
  228. X** delete the previous character.
  229. X*/
  230. X/* ARGSUSED */
  231. XXtActionProc
  232. XDeleteChar(w, event, params, num_params)
  233. XWidget w;
  234. XXEvent *event;
  235. XString *params;
  236. XCardinal *num_params;
  237. X{
  238. X XawTextPosition pos, i;
  239. X
  240. X pos = XawTextGetInsertionPoint(w);
  241. X if (pos > StartPos) {
  242. X    i = pos - 1;
  243. X    EraseIt(w, i, pos);
  244. X   }
  245. X} /* DeleteChar */
  246. X
  247. X
  248. X/*
  249. X** @(#)DeleteLine() - Deletes the entire current line from the file window.
  250. X**                    Simulates the action of the KILL character (ctrl-U).
  251. X*/
  252. X/* ARGSUSED */
  253. XXtActionProc
  254. XDeleteLine(w, event, params, num_params)
  255. XWidget            w;
  256. XXEvent            *event;
  257. XString            *params;
  258. XCardinal        *num_params;
  259. X{
  260. X XawTextPosition    pos, i;
  261. X String            FBuf;
  262. X Arg            args[1];
  263. X
  264. X
  265. X pos = XawTextGetInsertionPoint(w);
  266. X if (pos > StartPos) {
  267. X    XtSetArg(args[0], XtNstring, &FBuf);
  268. X    XtGetValues(w, args, ONE);
  269. X
  270. X    for (i = pos; i > StartPos && FBuf[i - 1] != '\n'; i--);
  271. X
  272. X    EraseIt(w, i, pos);
  273. X   }
  274. X} /* DeleteLine */
  275. X
  276. X
  277. X/*
  278. X** @(#)DeleteWord() - Erases the preceding word in the fileWindow buffer.
  279. X** Simulates the action of the WERASE character (ctrl-W).
  280. X*/
  281. X/* ARGSUSED */
  282. XXtActionProc
  283. XDeleteWord(w, event, params, num_params)
  284. XWidget            w;
  285. XXEvent            *event;
  286. XString            *params;
  287. XCardinal        *num_params;
  288. X{
  289. X XawTextPosition    pos, i;
  290. X String            FBuf;
  291. X Arg            args[1];
  292. X
  293. X pos = XawTextGetInsertionPoint(w);
  294. X if (pos > StartPos) {
  295. X    XtSetArg(args[0], XtNstring, &FBuf);
  296. X    XtGetValues(w, args, ONE);
  297. X
  298. X    for (i = pos; i > StartPos && FBuf[i - 1] == ' '; i--);
  299. X    for (; i > StartPos && FBuf[i - 1] != ' '; i--);
  300. X
  301. X    EraseIt(w, i, pos);
  302. X   }
  303. X} /* DeleteWord */
  304. X
  305. X
  306. X/* ARGSUSED */
  307. X/*
  308. X** @(#)DoCmd() - send (multi-word) command to mail
  309. X*/
  310. XXtActionProc
  311. XDoCmd(w, event, params, num_params)
  312. XWidget        w;            /* unused */
  313. XXEvent        *event;            /* unused */
  314. XString        *params;
  315. XCardinal    *num_params;
  316. X{
  317. X int        i;
  318. X char        buf[BUFSIZ];
  319. X
  320. X
  321. X if (strcmp(params[0], "drop") == 0) {
  322. X    SetCursor(NORMAL);
  323. X    DropIt(w, *params, NULL);
  324. X   } else {
  325. X    buf[0] = '\0';
  326. X    for (i = 0; i < *num_params; i++) {
  327. X        if (i > 0)
  328. X           (void) strcat(buf, " ");
  329. X        (void) strcat(buf, params[i]);
  330. X       }
  331. X    DoIt(w, buf, NULL);            /* Let DoIt (CallbackProc) do work */
  332. X   }
  333. X} /* DoCmd */
  334. X
  335. X
  336. X/* ARGSUSED */
  337. X/*
  338. X** @(#)DoDone() - execute one of the selected message composition callbacks
  339. X*/
  340. XXtActionProc
  341. XDoDone(w, event, params, num_params)
  342. XWidget        w;            /* unused */
  343. XXEvent        *event;            /* unused */
  344. XString        *params;
  345. XCardinal    *num_params;        /* unused */
  346. X{
  347. X char        buf[11];
  348. X Widget        button;
  349. X
  350. X if (strcmp(*params, "ReEdit") == 0)
  351. X    ReEdit(w, *params, NULL);
  352. X else if (strcmp(¶ms[0][1], "utograph") == 0) {
  353. X    (void) sprintf(buf, "*%s", *params);
  354. X    button = XtNameToWidget(XtParent(w), buf);
  355. X    Autograph(button, *params, NULL);
  356. X   } else {
  357. X    button = XtNameToWidget(XtParent(w), "*Deliver");
  358. X    Done(button, *params, NULL);
  359. X   }
  360. X} /* DoDone */
  361. X
  362. X
  363. X/* ARGSUSED */
  364. X/*
  365. X** @(#)DoNothing() - dummy action for unwanted button(s)
  366. X*/
  367. XXtActionProc
  368. XDoNothing(w, event, params, num_params)
  369. XWidget w;
  370. XXEvent *event;
  371. XString *params;
  372. XCardinal *num_params;
  373. X{
  374. X return;
  375. X} /* DoNothing */
  376. X
  377. X
  378. X/*
  379. X** @(#)DoReply() - call Reply() CallbackProc from an ActionProc
  380. X*/
  381. X/* ARGSUSED */
  382. XXtActionProc
  383. XDoReply(w, event, params, num_params)
  384. XWidget w;
  385. XXEvent *event;
  386. XString *params;
  387. XCardinal *num_params;
  388. X{
  389. X Reply(w, *params, NULL);
  390. X} /* DoReply */
  391. X
  392. X
  393. X/*
  394. X** @(#)DoSave() - call Save() CallbackProc from an ActionProc
  395. X*/
  396. X/* ARGSUSED */
  397. XXtActionProc
  398. XDoSave(w, event, params, num_params)
  399. XWidget        w;
  400. XXEvent        *event;
  401. XString        *params;
  402. XCardinal    *num_params;
  403. X{
  404. X Save(w, *params, NULL);
  405. X} /* DoSave */
  406. X
  407. X
  408. X/* ARGSUSED */
  409. X/*
  410. X** @(#)DoSelected() - execute specified command using selected message number
  411. X*/
  412. XXtActionProc
  413. XDoSelected(w, event, params, num_params)
  414. XWidget        w;
  415. XXEvent        *event;
  416. XString        *params;
  417. XCardinal    *num_params;
  418. X{
  419. X int        LastNumber(), num = 0;
  420. X char        cmd[2];
  421. X
  422. X
  423. X Waiting = TRUE;              /* so popup's EnterNotify won't erase the msg */
  424. X if (! mailpid) Bell("No current mail connection\n");
  425. X else if (num_params) {
  426. X         (void) strcpy(cmd, params[0]);
  427. X         num = SelectionNumber(cmd[0] == 'u');
  428. X         /*
  429. X         ** For 'next' and 'previous' commands, remember that
  430. X         ** mail's idea of the current message number may not
  431. X         ** match what the user has selected (without reading).
  432. X         */
  433. X         if (cmd[0] == 'n') {
  434. X            if (++num <= LastNumber(/* of the index */)) cmd[0] = 'p';
  435. X            else {            /* just say what would be said */
  436. X               Bell("At EOF\n");    /* if last msg num was current */
  437. X               return;
  438. X              }
  439. X           }
  440. X         if (cmd[0] == '-') {
  441. X            if (--num) cmd[0] = 'p';
  442. X            else {            /* just say what would be said if */
  443. X               Bell("Referencing before first message\n"); /* first was current */
  444. X               return;
  445. X              }
  446. X           }
  447. X
  448. X         SetCursor(WATCH);
  449. X         if (num) (void) sprintf(Command, "%s %d\n", cmd, num);
  450. X         else (void) sprintf(Command, "%s\n", cmd);
  451. X
  452. X         writeMail(Command);
  453. X        }
  454. X} /* DoSelected */
  455. X
  456. X
  457. X/*
  458. X** @(#)Folder() - change folders - must have specified folder name or error
  459. X*/
  460. X/* ARGSUSED */
  461. XXtActionProc
  462. XFolder(w, event, params, num_params)
  463. XWidget        w;
  464. XXEvent        *event;
  465. XString        *params;
  466. XCardinal    *num_params;
  467. X{
  468. X XawTextPosition pos;
  469. X String        c, p, buf;
  470. X Widget        fw = XtNameToWidget(toplevel, "topBox.commandPanel.fileWindow");
  471. X Arg        args[1];
  472. X
  473. X#ifndef    NO_FOLDER_NAME
  474. X#define    NO_FOLDER_NAME    "Specify a folder name (in the [File: ] box) first\n"
  475. X#endif
  476. X
  477. X pos = TextGetLastPos(fw);
  478. X if (pos - StartPos <= 0) {
  479. X    Bell(NO_FOLDER_NAME);
  480. X   } else {
  481. X    buf = NULL;
  482. X    XtSetArg(args[0], XtNstring, &buf);
  483. X    XtGetValues(fw, args, ONE);
  484. X
  485. X    if (buf[pos] != '\0') buf[pos] = '\0';
  486. X    for (pos = StartPos; buf[pos] && strchr(" \t", buf[pos]);) pos++;
  487. X
  488. X    if (! buf[pos]) {
  489. X       EraseIt(fw, (XawTextPosition) StartPos, pos);
  490. X       Bell(NO_FOLDER_NAME);
  491. X      } else {
  492. X       p = XtNewString(&buf[pos]);
  493. X
  494. X       if (mailpid) {            /* check for commit of any changes */
  495. X          buf = NULL;
  496. X          XtSetArg(args[0], XtNlabel, &buf);
  497. X          XtGetValues(XtNameToWidget(toplevel,"topBox.titleBar.title"),args,1);
  498. X
  499. X          c = strrchr(buf, 'l');  if (c) c -= 2;
  500. X
  501. X          if (! c || strncmp(c, "deleted", 7) != 0 ||
  502. X              Confirm("COMMIT all changes to this folder")) {
  503. X             (void) sprintf(Command, "file %s\n", p);
  504. X             writeMail(Command);
  505. X             SetCursor(WATCH);        /* will be reset by parser routine */
  506. X             (void) strcpy(lastFolder, buf);    /* save titlebar for utimes */
  507. X            }
  508. X          XtFree((String) p);
  509. X         } else {
  510. X          /*
  511. X          ** We must first re-establish contact with the mail utility.
  512. X          ** This time, we indicate a specific mail folder to process.
  513. X          */
  514. X          XtFree((String) XMail.MFileName);
  515. X          XMail.MFileName = p;
  516. X          if (mailargc > 2 && strcmp(mailargv[mailargc - 2], "-f") == 0) {
  517. X             mailargv[mailargc - 1] = XMail.MFileName;
  518. X            } else {
  519. X             mailargv[mailargc++] = "-f";
  520. X             mailargv[mailargc++] = XMail.MFileName;
  521. X             mailargv[mailargc] = NULL;    /* list MUST be NULL terminated */
  522. X            }
  523. X          callMail(mailargv);
  524. X          (void) strcpy(Command, "Start");    /* Let em know we've re-started */
  525. X          In_Bogus_Mail_File = FALSE;    /* reset this so titleBar will chg */
  526. X          SetCursor(WATCH);        /* will be reset by parser routine */
  527. X         }
  528. X      } /* end - if a folder name was specified */
  529. X   }
  530. X} /* Folder */
  531. X
  532. X
  533. X/* ARGSUSED */
  534. X/*
  535. X** @(#)Iconify() - request window iconification
  536. X*/
  537. XXtActionProc
  538. XIconify(w, event, params, num_params)
  539. XWidget w;
  540. XXEvent *event;
  541. XString *params;
  542. XCardinal *num_params;
  543. X{
  544. X Display        *disp = XtDisplay(toplevel);
  545. X
  546. X
  547. X if (! XIconifyWindow(disp, XtWindow(toplevel), DefaultScreen(disp)))
  548. X    XBell(disp, 33);
  549. X}
  550. X
  551. X
  552. X/* ARGSUSED */
  553. X/*
  554. X** @(#)MyNotify() - call widget callbacks with passed parameter
  555. X*/
  556. XXtActionProc
  557. XMyNotify(w, event, params, num_params)
  558. XWidget        w;
  559. XXEvent        *event;
  560. XString        *params;
  561. XCardinal    *num_params;
  562. X{
  563. X XtCallCallbacks(w, XtNcallback, *params);
  564. X} /* MyNotify */
  565. X
  566. X
  567. X/*
  568. X** @(#)NextField() - warps pointer to next field in the Send command window.
  569. X** This allows carriage return to focus attention on the next data requirement.
  570. X*/
  571. X/* ARGSUSED */
  572. XXtActionProc
  573. XNextField(w, event, params, num_params)
  574. XWidget w;
  575. XXEvent *event;
  576. XString *params;
  577. XCardinal *num_params;
  578. X{
  579. X String    name;
  580. X Widget    shell;
  581. X
  582. X
  583. X if (strcmp(w->core.name, "Cc") == 0)
  584. X    name = "Bcc"; else
  585. X if (strcmp(w->core.name, "Bcc") == 0)
  586. X    name = "To"; else
  587. X if (strcmp(w->core.name, "To") == 0)
  588. X    name = "Subject"; else
  589. X    name = "Cc";
  590. X
  591. X if ((shell = XtNameToWidget(XtParent(w), name)) != NULL)
  592. X    XWarpPointer(XtDisplay(toplevel), None, XtWindow(shell), 0,0,0,0, 15, 10);
  593. X
  594. X} /* NextField */
  595. X
  596. X
  597. X/*
  598. X** @(#)PrintMsg() - sends the selected mail message to the system printer
  599. X*/
  600. X/* ARGSUSED */
  601. XXtActionProc
  602. XPrintMsg(w, event, params, num_params)
  603. XWidget        w;
  604. XXEvent        *event;
  605. XString        *params;
  606. XCardinal    *num_params;
  607. X{
  608. X int        k, num;
  609. X String        cp, sp;
  610. X char        buf[BUFSIZ];
  611. X
  612. X
  613. X if (! mailpid) Bell("No current mail connection\n");
  614. X else {
  615. X    num = SelectionNumber(FALSE);    /* no current message returns zero */
  616. X    if (! num) Bell("No messages to print.\n");
  617. X    else {
  618. X       SetCursor(WATCH);        /* will be reset by parser routine */
  619. X       cp = QueryMail("|");
  620. X       if (strncmp(cp, "Unknown", 7) == 0) {    /* Then this is NOT Sun mail */
  621. X          (void) sprintf(buf, "copy %d %s", num, tmpName);
  622. X          cp = QueryMail(buf);            /* write message to a file */
  623. X          sp = strrchr(cp, '/');        /* get the size of the file */
  624. X          if (sp)
  625. X             (void) sscanf(sp, "/%d", &k);
  626. X          else {
  627. X             struct stat    sb;
  628. X
  629. X             if (stat(tmpName, &sb) == 0)
  630. X                k = sb.st_size;
  631. X             else k = 0;
  632. X            }
  633. X          if (! (cp = GetMailEnv("printmail")))
  634. X             (void) sprintf(buf, "lpr -p %s && rm -f %s &", tmpName, tmpName);
  635. X          else {
  636. X             (void) sprintf(buf, "%s %s && rm -f %s &", cp, tmpName, tmpName);
  637. X             XtFree((String) cp);
  638. X            }
  639. X
  640. X          (void) system(buf);
  641. X          (void) sprintf(buf, "Message %d sent to printer -- %d bytes\n",num,k);
  642. X          Bell(buf);                /* Notify user of action */
  643. X          Command[0] = '\0';            /* Toss any previous value */
  644. X          SetCursor(NORMAL);
  645. X         } else {
  646. X          if (! (cp = GetMailEnv("printmail")))
  647. X             (void) sprintf(Command, "| %d \"lpr -p\"\n", num);
  648. X          else {
  649. X             (void) sprintf(Command, "| %d \"%s\"\n", num, cp);
  650. X             XtFree((String) cp);
  651. X            }
  652. X
  653. X          writeMail(Command);
  654. X         }
  655. X      }
  656. X   }
  657. X} /* PrintMsg */
  658. X
  659. X
  660. X/*
  661. X** @(#)Quit() - call DoQuit() CallbackProc from the Quit ActionProc
  662. X*/
  663. X/* ARGSUSED */
  664. XXtActionProc
  665. XQuit(w, event, params, num_params)
  666. XWidget        w;
  667. XXEvent        *event;
  668. XString        *params;
  669. XCardinal    *num_params;    /* unused */
  670. X{
  671. X if (event->type == ClientMessage &&
  672. X    event->xclient.data.l[0] != wmDeleteWindow) {
  673. X    XBell (XtDisplay(w), 0);
  674. X    return;
  675. X   }
  676. X
  677. X DoQuit(w, *params, NULL);
  678. X} /* Quit */
  679. X
  680. X
  681. X/*
  682. X** @(#)SetAliases() - create a menu list of alias names
  683. X*/
  684. X/* ARGSUSED */
  685. XXtActionProc
  686. XSetAliases(w, event, params, num_params)
  687. XWidget        w;
  688. XXEvent        *event;
  689. XString        *params;
  690. XCardinal    *num_params;
  691. X{
  692. X int        columns, j, k, n;
  693. X Cardinal    numChildren = 0;
  694. X Widget        bw, lw, popup, above, left, parent = XtParent(w);
  695. X Display    *dpy = XtDisplay(parent);
  696. X Window        rootW, parentW, *cL, *childList = 0;
  697. X Arg        args[6];
  698. X
  699. X static String l_Trans = "<Btn3Up>:    MenuPopdown(aliasList)";
  700. X static String fl_trans = "<Enter>: set()\n<Leave>: unset()\n<Btn3Up>: notify()";
  701. X
  702. X
  703. X popup = XtNameToWidget(parent, "aliasList");
  704. X
  705. X if (! popup) {
  706. X    (void) alias(NULL);            /* ensure our aliases list is set */
  707. X/*
  708. X** determine proper label width by finding longest name length
  709. X*/
  710. X    j = k = columns = 0;
  711. X    for (n = 0; aliases[n]; n++)
  712. X        if ((columns = strlen(aliases[n]->name)) > k) {
  713. X           k = columns;
  714. X           j = n;
  715. X          }
  716. X
  717. X    if (k > 0) {                /* some alias names exist */
  718. X       /*
  719. X       ** Make equal width command buttons which contain the alias names
  720. X       */
  721. X       XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(l_Trans));
  722. X       popup = XtCreatePopupShell("aliasList", overrideShellWidgetClass, parent, args, 1);
  723. X
  724. X       XtSetArg(args[0], XtNdefaultDistance, (XtArgVal) 1);
  725. X       lw = XtCreateManagedWidget("table", formWidgetClass, popup, args, 1);
  726. X
  727. X       XtSetArg(args[0], XtNwidth, XTextWidth(XMail.buttonFont, aliases[j]->name, k) + 14);
  728. X       XtSetArg(args[1], XtNfont, XMail.buttonFont);
  729. X       XtSetArg(args[2], XtNtranslations, XtParseTranslationTable(fl_trans));
  730. X
  731. X       columns = XMail.shellWidth / args[0].value;    /* no wider than this */
  732. X       while (columns * columns > n) columns--;    /* try to shape into a square */
  733. X
  734. X       k = 0;
  735. X       above = left = NULL;
  736. X       for (n = 0; aliases[n]; n++) {
  737. X           XtSetArg(args[3], XtNlabel, aliases[n]->name);
  738. X           XtSetArg(args[4], XtNfromHoriz, left);            j = 5;
  739. X           if (! left)            /* also anchor to the button above */
  740. X              XtSetArg(args[j], XtNfromVert, above);            j++;
  741. X
  742. X           bw = XtCreateManagedWidget("entry", commandWidgetClass, lw, args, j);
  743. X           AddInfoHandler(bw, "Copy this alias to the current header field");
  744. X
  745. X           if (! left) above = bw;
  746. X           left = bw;
  747. X
  748. X           if (++k % columns == 0) {    /* make a box # columns wide */
  749. X              k = 0;
  750. X              left = NULL;        /* start next row at left edge of box */
  751. X             }
  752. X          } /* end - for all the aliases in the list */
  753. X      }    /* end - if some alias names exist */
  754. X   } /* end - if popup did not previously exist */
  755. X/*
  756. X** If the popup menu of aliases does exist, add a window-specific callback,
  757. X** set the menu's x,y coordinates and then pop it up
  758. X*/
  759. X if (! popup)
  760. X    XBell(XtDisplay(toplevel), 33);
  761. X else {
  762. X    if (! XtIsRealized(popup))
  763. X       XtRealizeWidget(popup);
  764. X
  765. X    lw = XtNameToWidget(popup, "*table");
  766. X    if (XQueryTree(dpy, XtWindow(lw), &rootW, &parentW, &childList, &numChildren)) {
  767. X       for (cL = childList; numChildren--;) {
  768. X            bw = XtWindowToWidget(dpy, *cL++);
  769. X
  770. X           if (XtHasCallbacks(bw, XtNcallback) == XtCallbackHasSome)
  771. X              XtRemoveAllCallbacks(bw, XtNcallback);
  772. X
  773. X           XtAddCallback(bw, XtNcallback, (XtCallbackProc) GetAliasName, w);
  774. X          }
  775. X
  776. X       XFree((Window *) childList);
  777. X      }
  778. X
  779. X    SetXY(popup, w, XMail.menuX, XMail.buttonHeight / 2);
  780. X
  781. X    XtPopupSpringLoaded(popup);
  782. X   }
  783. X} /* SetAliases */
  784. X
  785. X
  786. X/*
  787. X** @(#)SetNewness() - hatch label background of folder if recently modified
  788. X*/
  789. Xvoid
  790. XSetNewness(parent, path)
  791. XWidget    parent;
  792. Xchar    *path;
  793. X{
  794. X Cardinal    numChildren = 0;
  795. X char        *folder_name, buf[BUFSIZ];
  796. X Display    *dpy = XtDisplay(parent);
  797. X Window        rootW, parentW, *cL, *childList = 0;
  798. X Widget        w;
  799. X Arg        args[1];
  800. X struct    stat    stb;
  801. X
  802. X
  803. X if (XQueryTree(dpy, XtWindow(parent), &rootW, &parentW, &childList, &numChildren)) {
  804. X    for (cL = childList; numChildren--;) {
  805. X        w = XtWindowToWidget(dpy, *cL++);
  806. X
  807. X        XtSetArg(args[0], XtNlabel, &folder_name);
  808. X        XtGetValues(w, args, 1);
  809. X
  810. X        if (LASTCH(folder_name) != '/') {    /* If its not a directory... */
  811. X           (void) strcpy(buf, path);        /* build complete foldername */
  812. X           if (folder_name[0] == '+')        /* must be a toplevel folder */
  813. X              (void) strcat(buf, folder_name + 1);    /* (no plus sign) */
  814. X           else {
  815. X              (void) strcat(buf, "/");
  816. X              (void) strcat(buf, folder_name);
  817. X             }
  818. X           /*
  819. X           ** Using access versus modified timestamps is inherently unreliable
  820. X           ** in determining the newness of messages in a folder, but the
  821. X           ** alternative of examining the file for the last Status or From is
  822. X           ** horribly slow. 
  823. X           */
  824. X           if (stat(buf, &stb) == 0) {
  825. X              if (stb.st_size && stb.st_atime < stb.st_mtime)
  826. X                 XtSetArg(args[0], XtNbackgroundPixmap, hatch);
  827. X              else
  828. X                 XtSetArg(args[0], XtNbackgroundPixmap, XtUnspecifiedPixmap);
  829. X              XtSetValues(w, args, 1);
  830. X             } /* end - if readable */
  831. X          } /* end - if not a directory */
  832. X       } /* end - for each child in the list */
  833. X
  834. X    XFree((Window *) childList);
  835. X   } /* end - if some children exist */
  836. X} /* end - SetNewness */
  837. X
  838. X
  839. X/*
  840. X** @(#)SetFolders() - create a menu list of folder names
  841. X*/
  842. X/* ARGSUSED */
  843. XXtActionProc
  844. XSetFolders(w, event, params, num_params)
  845. XWidget        w;
  846. XXEvent        *event;
  847. XString        *params;
  848. XCardinal    *num_params;
  849. X{
  850. X int        m, n, total, no_List = TRUE;
  851. X int        isAdir, freeable = FALSE;    /* If we built list then true */
  852. X String        *ftbl = NULL;
  853. X String        cp, List = NULL;
  854. X char        trans[BUFSIZ], tmp[BUFSIZ], buf[BUFSIZ];
  855. X Widget        lw, above, this_one, to_left, popup;
  856. X Arg        args[8];
  857. X DIR        *dirp = NULL;
  858. X struct    stat    st_buf;
  859. X
  860. X
  861. X#ifdef USE_DIRENT
  862. X struct dirent    *dp;
  863. X#else
  864. X struct direct    *dp;
  865. X#endif
  866. X
  867. X static String dir_Trans = "<Btn1Down>: SetDirectory(%s,%s,%s)";
  868. X static String  l_Trans = "<Btn3Up>: MenuPopdown(popupList)";
  869. X static String fl_trans = "<Enter>: set()\n<Leave>: unset()\n\
  870. X                   <Btn3Up>: notify() MenuPopdown(popupList)";
  871. X
  872. X static XtCallbackRec fl_callbacks[] = {
  873. X        { (XtCallbackProc) GetFolderName, NULL },
  874. X        { NULL,          NULL }
  875. X       };
  876. X
  877. X
  878. X popup = XtNameToWidget(w, "popupList");
  879. X
  880. X if (! popup) {
  881. X    XtSetSensitive(w, FALSE);
  882. X    XFlush(XtDisplay(toplevel));
  883. X    initfoldir();
  884. X
  885. X    if (foldir[0]) {                /* if folder variable exists */
  886. X       if (mailpid) {                /* try to get list from mail */
  887. X          List = QueryMail("folders");        /* returns a string of names */
  888. X         } else {
  889. X          if (dirp = opendir((char *)foldir)) {    /* and folder is readable... */
  890. X             n = BUFSIZ;            /* start with a BUFSIZ block */
  891. X             List = (String) XtMalloc((unsigned) n);
  892. X             List[0] = '\0';
  893. X             freeable = TRUE;
  894. X             for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
  895. X                 if (dp->d_name[0] != '.') {    /* skip parent and dot files */
  896. X                    if (strlen(List) + strlen(dp->d_name) + 2 > n) {
  897. X                       n += BUFSIZ;
  898. X                       List = (String) XtRealloc(List, n);
  899. X                      }
  900. X                    if (List[0]) (void) strcat(List, " ");
  901. X                    (void) strcat(List, dp->d_name);
  902. X                   }
  903. X             (void) closedir(dirp);
  904. X             List = (String) XtRealloc(List, strlen(List) + 1);
  905. X            } /* end - if folder directory is readable */
  906. X         } /* end - if mail process is running */
  907. X      } /* end - if a folder value exists */
  908. X
  909. X    if (List) {                /* could be null if no current mail */
  910. X       no_List = FALSE;
  911. X       if (XM_O_BELL == match(output_pattern, List)) {
  912. X          if (strlen(List) + 1 < BUFSIZ)
  913. X             (void) sprintf(tmp, "%s\n", List);
  914. X          else
  915. X             (void) sprintf(tmp, "Cannot access folders\n");
  916. X          Bell(tmp);
  917. X          if (freeable) {
  918. X             freeable = FALSE;
  919. X             XtFree((String)List);
  920. X             List = NULL;
  921. X            } else List[0] = '\0';
  922. X          no_List = TRUE;
  923. X         }
  924. X      }
  925. X
  926. X    if (List && List[0]) {            /* if some folder names exist */
  927. X       no_List = FALSE;
  928. X       for (total = 1, cp = List; *cp; cp++)    /* count number of names */
  929. X           if (strchr(" \t\n", *cp)) {
  930. X              total++;            /* (increase the folder name count) */
  931. X              while (*(cp+1) && strchr(" \t\n", *(cp+1))) cp++;
  932. X             }
  933. X       ftbl = (String *) XtMalloc((unsigned) (total + 1) * sizeof(String));
  934. X       m = n = 0;
  935. X       for (cp = List; *cp; cp++) {    /* stuff word pointers into a table */
  936. X           while (*(cp+n) && ! strchr(" \t\n", *(cp+n))) n++;
  937. X           if (*(cp+n)) *(cp+n) = '\0';    /* mark off the end of this name */
  938. X           ftbl[m++] = cp;        /* save this pointer in our table */
  939. X           cp += n;            /* find start of next folder name */
  940. X           n = 0;
  941. X           while (*(cp+1) && strchr(" \t\n", *(cp+1))) cp++;
  942. X          }
  943. X       ftbl[m] = NULL;            /* NULL terminate our table */
  944. X       /*
  945. X       ** (quick) sort our table into ascending alphabetical order
  946. X       */
  947. X       if (total > 1)
  948. X          qsort((String) ftbl, total, sizeof(String), str_compare);
  949. X       /*
  950. X       ** Next, determine label width of longest word in our table
  951. X       */
  952. X       for (m = n = 0; n < total && ftbl[n]; n++) {
  953. X           if (strlen(ftbl[n]) > strlen(ftbl[m])) m = n;
  954. X          }
  955. X       /*
  956. X       ** Now, make equal width command buttons which contain the folder names
  957. X       */
  958. X       XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(l_Trans));
  959. X       popup = XtCreatePopupShell("popupList",overrideShellWidgetClass,w,args,1);
  960. X
  961. X       XtSetArg(args[0], XtNdefaultDistance, 1);
  962. X       lw = XtCreateManagedWidget("list", formWidgetClass, popup, args, 1);
  963. X
  964. X       n = XTextWidth(XMail.buttonFont, ftbl[m], strlen(ftbl[m]));
  965. X
  966. X       XtSetArg(args[0], XtNwidth, n + 20);
  967. X       XtSetArg(args[1], XtNfont, XMail.buttonFont);
  968. X       XtSetArg(args[2], XtNtranslations, XtParseTranslationTable(fl_trans));
  969. X       XtSetArg(args[3], XtNcallback, fl_callbacks);
  970. X
  971. X       above = this_one = to_left = NULL;
  972. X       tmp[0] = '\0';
  973. X       (void) strcpy(buf, foldir);
  974. X       n = strlen(buf) - 1;
  975. X       for (m = 0; m < total; m++) {
  976. X           buf[n] = '\0';        /* restore name only value for tests */
  977. X           /*
  978. X           ** Watch out for special case of only one folder which isn't
  979. X           ** really a directory... (i.e. foldir and folder are same name)
  980. X           */
  981. X           if (0 != strcmp(ftbl[m], buf))
  982. X              (void) strcpy(tmp, "+");    /* true folders start with a 'plus' */
  983. X           (void) strcat(tmp, ftbl[m]);
  984. X           /*
  985. X           ** mark any directory 'folders' with a trailing slash '/'.
  986. X           */
  987. X           isAdir = FALSE;            /* assume its a regular file */
  988. X           (void) strcat(buf, "/");
  989. X           (void) strcat(buf, ftbl[m]);
  990. X           if (access(buf, R_OK) == 0 &&    /* IF exists and is readable */
  991. X               access(buf, X_OK) == 0 &&    /* and we can execute/search */
  992. X               stat(buf, &st_buf) == 0)
  993. X          if (S_ISDIR(st_buf.st_mode)) {     /* and has directory bit set */
  994. X                 isAdir = TRUE;
  995. X             if (LASTCH(tmp) != '/')
  996. X                 (void) strcat(tmp, "/");    /* If a directory mark it so */
  997. X                } else isAdir = FALSE;
  998. X
  999. X           XtSetArg(args[4], XtNlabel, tmp);
  1000. X           XtSetArg(args[5], XtNfromHoriz, to_left);
  1001. X           if (! to_left) XtSetArg(args[6], XtNfromVert, above);
  1002. X
  1003. X           this_one = XtCreateManagedWidget("menubutton", commandWidgetClass, lw, args, 7);
  1004. X
  1005. X           if (to_left == NULL) above = this_one;
  1006. X           to_left = this_one;
  1007. X
  1008. X           if ((m+1) % 5 == 0)
  1009. X              to_left = NULL;
  1010. X/*
  1011. X** If this 'folder' is a directory, add a button to popup a menu of filenames.
  1012. X*/
  1013. X           if (isAdir) {
  1014. X              (void) sprintf(trans, dir_Trans, &tmp[1], buf, "0");
  1015. X              XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
  1016. X              AddInfoHandler(this_one, Folder_Info[2]);
  1017. X             } else
  1018. X              AddInfoHandler(this_one, Folder_Info[1]);
  1019. X          } /* end - for each folder name in the table of folders */
  1020. X       XtFree((String) ftbl);
  1021. X      }    /* end - if some folder names exist */
  1022. X    XtSetSensitive(w, TRUE);
  1023. X
  1024. X    if (freeable)
  1025. X       XtFree((String) List);
  1026. X   } /* end - if no popup previously existed */
  1027. X/*
  1028. X** If no folders to display, tell the user why
  1029. X*/
  1030. X if (! popup) {
  1031. X    if (! foldir[0])
  1032. X       Bell("No value set for \"folder\"\n");
  1033. X    else if (dirp || no_List == FALSE) {
  1034. X            if (! mailpid || no_List == FALSE)
  1035. X               Bell("No mail folders exist\n");
  1036. X              }
  1037. X   } else {
  1038. X    /*
  1039. X    ** If folders menu exists, pop it up, after setting x,y coordinates
  1040. X    */
  1041. X    if (! XtIsRealized(popup))
  1042. X       XtRealizeWidget(popup);
  1043. X    /*
  1044. X    ** Mark folders with new messages by changing the background Pixmap
  1045. X    */
  1046. X    SetNewness(XtNameToWidget(popup, "*list"), foldir);
  1047. X    /*
  1048. X    ** If folder list is small enough, anchor it to
  1049. X    ** the folder button instead of the commandPanel
  1050. X    */
  1051. X    if (popup->core.width + (3 * (XMail.buttonWidth + 12)) <= XMail.shellWidth)
  1052. X       SetXY(popup, w, XMail.menuX, XMail.buttonHeight / 2);
  1053. X    else
  1054. X       SetXY(popup, XtNameToWidget(toplevel, "topBox.commandPanel"),
  1055. X             XMail.menuX, XMail.commandHeight / 2);
  1056. X
  1057. X    XtPopupSpringLoaded(popup);
  1058. X   }
  1059. X} /* SetFolders */
  1060. X
  1061. X
  1062. X
  1063. X/* 
  1064. X** @(#)SetMenu() - create a menu for toggling selected mail options
  1065. X*/
  1066. X/* ARGSUSED */
  1067. XXtActionProc
  1068. XSetMenu(parent, event, params, num_params)
  1069. XWidget        parent;
  1070. XXEvent        *event;        /* unused */
  1071. XString        *params;    /* unused */
  1072. XCardinal    *num_params;    /* unused */
  1073. X{
  1074. X int        indx;
  1075. X String        c, info;
  1076. X char        label[BUFSIZ], name[BUFSIZ];        
  1077. X Widget        menu, layout, previous, next;
  1078. X Arg         args[6];
  1079. X
  1080. X static String m_Trans = "<Btn3Up>: MenuPopdown(set_menu)";
  1081. X static String b_Trans = "<Enter>: set()\n<Leave>: reset()\n<Btn3Up>: notify() unset()";
  1082. X
  1083. X static String list[] = { "alwaysignore",
  1084. X                           "editheaders",
  1085. X                             "autoprint",
  1086. X                                  "hold",
  1087. X                                "expert",
  1088. X                           NULL };
  1089. X
  1090. X static String set_info[] = {
  1091. X "Skip 'ignore'd header fields everywhere, not just during a print or read",
  1092. X "Enable editing of selected headers within the message body when sending",
  1093. X "Enable automatic printing of messages after delete and undelete commands",
  1094. X "Preserve messages in the system mailbox after they have been read",
  1095. X "Don't ask for confirmation when commiting changes or aborting a new letter",
  1096. X NULL
  1097. X };
  1098. X
  1099. X static String unset_info[] = {
  1100. X "Skip 'ignore'd header fields only when doing a print or read command",
  1101. X "Disallow editing of selected headers within the message body when sending",
  1102. X "Disable automatic printing of messages after delete and undelete commands",
  1103. X "Move system mailbox messages to the mbox save file after you read them",
  1104. X "Ask for confirmation before commiting any changes or aborting a new letter",
  1105. X NULL
  1106. X };
  1107. X
  1108. X
  1109. X menu = XtNameToWidget(parent, "set_menu");
  1110. X
  1111. X if (! menu || menu->core.being_destroyed) {
  1112. X    XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(m_Trans));
  1113. X    menu = XtCreatePopupShell("set_menu",overrideShellWidgetClass,parent,args,1);
  1114. X
  1115. X    XtSetArg(args[0], XtNdefaultDistance, (XtArgVal) 1);
  1116. X    layout = XtCreateManagedWidget("menu", formWidgetClass, menu, args, 1);
  1117. X/*
  1118. X** create the menu buttons
  1119. X*/
  1120. X    previous = NULL;
  1121. X    XtSetArg(args[0], XtNwidth, figureWidth(XMail.buttonFont) * 18 + 12);
  1122. X    XtSetArg(args[1], XtNfont, XMail.buttonFont);
  1123. X    XtSetArg(args[2], XtNjustify, XtJustifyLeft);
  1124. X    XtSetArg(args[3], XtNtranslations, XtParseTranslationTable(b_Trans));
  1125. X    for (indx = 0; list[indx] != NULL; indx++) {
  1126. X        info = set_info[indx];
  1127. X        (void) strcpy(label, "set ");
  1128. X        if (strcmp(list[indx], "expert") == 0) {
  1129. X           if (XMail.expert) {
  1130. X              info = unset_info[indx];
  1131. X              (void) strcat(label, "no");
  1132. X             }
  1133. X          } else if ((c = GetMailEnv(list[indx])) != NULL) {
  1134. X              info = unset_info[indx];
  1135. X              (void) strcat(label, "no");
  1136. X              XtFree((String) c);
  1137. X          }
  1138. X        (void) strcat(label, list[indx]);    /* set window name by label */
  1139. X        (void) strcpy(name, &label[4]);
  1140. X        XtSetArg(args[4], XtNlabel, label);
  1141. X        XtSetArg(args[5], XtNfromVert, previous);
  1142. X        next = XtCreateManagedWidget(name, commandWidgetClass, layout, args, 6);
  1143. X        XtAddCallback(next, XtNcallback, (XtCallbackProc) DoSet, NULL);
  1144. X        AddInfoHandler(next, info);
  1145. X        previous = next;
  1146. X       }
  1147. X   } /* end - menu creation */
  1148. X SetXY(menu, parent, XMail.menuX, XMail.buttonHeight / 2);
  1149. X} /* SetMenu */
  1150. X
  1151. X
  1152. X/*
  1153. X** @(#)SetPopup() - place named popup at menuX, menuY relative to Widget w.
  1154. X*/
  1155. X/* ARGSUSED */
  1156. XXtActionProc
  1157. XSetPopup(w, event, params, num_params)
  1158. XWidget w;
  1159. XXEvent *event; /* unused */
  1160. XString *params;
  1161. XCardinal *num_params;
  1162. X{
  1163. X String        p;
  1164. X Widget        shell;
  1165. X
  1166. X
  1167. X if (*num_params == 0)
  1168. X    XtError("xmail had no name parameter passed to SetPopup()");
  1169. X
  1170. X p = params[0];
  1171. X
  1172. X if ((shell = XtNameToWidget(w, p)) == NULL)
  1173. X    XtError("xmail shell name passed to SetPopup() not found in list");
  1174. X
  1175. X SetXY(shell, w, XMail.menuX, XMail.menuY);
  1176. X} /* SetPopup */
  1177. X
  1178. X
  1179. X/* ARGSUSED */
  1180. X/*
  1181. X** @(#)SetSelect() - flag the index number of the selected message
  1182. X*/
  1183. XXtActionProc
  1184. XSetSelect(w, event, params, num_params)
  1185. XWidget w;        /* unused */
  1186. XXEvent *event;        /* unused */
  1187. XString *params;        /* unused */
  1188. XCardinal *num_params;    /* unused */
  1189. X{
  1190. X markIndex(">");
  1191. X} /* SetSelect */
  1192. X
  1193. X
  1194. X/*
  1195. X** @(#)ShowHelp() - set named string source as text for and popup help window.
  1196. X*/
  1197. X/* ARGSUSED */
  1198. XXtActionProc
  1199. XShowHelp(w, event, params, num_params)
  1200. XWidget        w;
  1201. XXEvent        *event;
  1202. XString        *params;            /* unused */
  1203. XCardinal    *num_params;            /* unused */
  1204. X{
  1205. X Widget        tbox = XtNameToWidget(toplevel, "topBox");
  1206. X Widget        help = XtNameToWidget(tbox, "help");
  1207. X String        name;
  1208. X helpText    *help_text;
  1209. X
  1210. X
  1211. X name = w->core.name;
  1212. X if (strcmp(name, "text") == 0 && event->type == KeyPress)
  1213. X    name = "text2";
  1214. X
  1215. X for (help_text = HelpList; help_text; help_text = help_text->next)
  1216. X     if (strcmp(name, help_text->name) == 0) {
  1217. X        XawTextSetSource(XtNameToWidget(help, "helpWindow"),
  1218. X                        (AsciiSrcObject) help_text->data, (XawTextPosition) 0);
  1219. X
  1220. X        SetXY(help, XtNameToWidget(tbox, "textWindow.text"), XMail.helpX, XMail.helpY);
  1221. X
  1222. X        XtPopup(help, XtGrabNone);
  1223. X        break;
  1224. X       }
  1225. X} /* ShowHelp */
  1226. END_OF_FILE
  1227.   if test 33275 -ne `wc -c <'actions.c'`; then
  1228.     echo shar: \"'actions.c'\" unpacked with wrong size!
  1229.   fi
  1230.   # end of 'actions.c'
  1231. fi
  1232. if test -f 'xmail.c' -a "${1}" != "-c" ; then 
  1233.   echo shar: Will not clobber existing file \"'xmail.c'\"
  1234. else
  1235.   echo shar: Extracting \"'xmail.c'\" \(20058 characters\)
  1236.   sed "s/^X//" >'xmail.c' <<'END_OF_FILE'
  1237. X/*
  1238. X * xmail - X window system interface to the mail program
  1239. X *
  1240. X * Copyright 1990,1991,1992 by National Semiconductor Corporation
  1241. X *
  1242. X * Permission to use, copy, modify, and distribute this software and its
  1243. X * documentation for any purpose is hereby granted without fee, provided that
  1244. X * the above copyright notice appear in all copies and that both that
  1245. X * copyright notice and this permission notice appear in supporting
  1246. X * documentation, and that the name of National Semiconductor Corporation not
  1247. X * be used in advertising or publicity pertaining to distribution of the
  1248. X * software without specific, written prior permission.
  1249. X *
  1250. X * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  1251. X * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  1252. X * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  1253. X * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  1254. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  1255. X * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  1256. X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  1257. X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1258. X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  1259. X * PERFORMANCE OF THIS SOFTWARE.
  1260. X *
  1261. X * The following software modules were created and are Copyrighted by National
  1262. X * Semiconductor Corporation:
  1263. X *
  1264. X * 1. initialize: and
  1265. X * 2. SetHints.
  1266. X *
  1267. X * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  1268. X *
  1269. X */
  1270. X
  1271. X#include "global.h"
  1272. X#include "Mailwatch.h"            /* use as icon and watch for newmail */
  1273. X#include <X11/Xaw/CommandP.h>
  1274. X#include <X11/Xaw/TextP.h>
  1275. X#include <X11/cursorfont.h>        /* use watch cursor for busy notify */
  1276. X#include <X11/bitmaps/cross_weave>    /* background use in Newmail notify */
  1277. X#include <pwd.h>            /* for getting user's home directory */
  1278. X
  1279. X#ifndef    lint
  1280. Xstatic char what[] =
  1281. X "@(#)xmail.c 1.5 92/01/31 Copyright 1989,1990,1991,1992 National Semiconductor Corp.";
  1282. X#endif
  1283. X
  1284. X#define Offset(field) (XtOffset(XmailResources *, field))
  1285. X
  1286. Xstatic XtResource resrcs[] = {
  1287. X    {"textFont", XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  1288. X    Offset(textFont), XtRString, XtDefaultFont},
  1289. X    {"helpFont", XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  1290. X    Offset(helpFont), XtRString, XtDefaultFont},
  1291. X    {"buttonFont", XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  1292. X    Offset(buttonFont), XtRString, XtDefaultFont},
  1293. X    {"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
  1294. X        Offset(iconGeometry), XtRString, (caddr_t) NULL},
  1295. X    {"mFileName", "MFileName", XtRString, sizeof(char *), 
  1296. X    Offset(MFileName), XtRString, (caddr_t) NULL},
  1297. X    {"editorCommand", "EditorCommand", XtRString, sizeof(char *), 
  1298. X    Offset(editorCommand), XtRString, (caddr_t) NULL},
  1299. X    {"bellRing", "BellRing", XtRBoolean, sizeof(Boolean), 
  1300. X    Offset(bellRing), XtRImmediate, (caddr_t) True},
  1301. X    {"expert", "Expert", XtRBoolean, sizeof(Boolean), 
  1302. X    Offset(expert), XtRImmediate, (caddr_t) False},
  1303. X    {"iconic", "Iconic", XtRBoolean, sizeof(Boolean), 
  1304. X    Offset(iconic), XtRImmediate, (caddr_t) False},
  1305. X    {"mailopt_n", "Mailopt_n", XtRBoolean, sizeof(Boolean), 
  1306. X    Offset(mailopt_n), XtRImmediate, (caddr_t) False},
  1307. X    {"mailopt_U", "Mailopt_U", XtRBoolean, sizeof(Boolean), 
  1308. X    Offset(mailopt_U), XtRImmediate, (caddr_t) False},
  1309. X    {"show_Last", "Show_Last", XtRBoolean, sizeof(Boolean), 
  1310. X    Offset(Show_Last), XtRImmediate, (caddr_t) True},
  1311. X    {"show_Info", "Show_Info", XtRBoolean, sizeof(Boolean), 
  1312. X    Offset(Show_Info), XtRImmediate, (caddr_t) True},
  1313. X    {"no_X_Hdr", "No_X_Hdr", XtRBoolean, sizeof(Boolean), 
  1314. X    Offset(No_X_Hdr), XtRImmediate, (caddr_t) False},
  1315. X    { XtNborderWidth, XtCBorderWidth, XtRInt, sizeof (int),
  1316. X    Offset(borderWidth), XtRString, "1"},
  1317. X};
  1318. X
  1319. X#undef Offset
  1320. X
  1321. Xstatic XrmOptionDescRec Opts[] = {
  1322. X    {"-borderwidth",    ".TopLevelShell.borderWidth",    XrmoptionSepArg,    (caddr_t) NULL},
  1323. X    {"-buttonfont",    "*buttonFont",            XrmoptionSepArg,    (caddr_t) NULL},
  1324. X    {"-buttonFont",    "*buttonFont",            XrmoptionSepArg,    (caddr_t) NULL},
  1325. X    {"-bw",        ".TopLevelShell.borderWidth",    XrmoptionSepArg,    (caddr_t) NULL},
  1326. X    {"-editorcommand",    "*editorCommand",        XrmoptionSepArg,    (caddr_t) NULL},
  1327. X    {"-editorCommand",    "*editorCommand",        XrmoptionSepArg,    (caddr_t) NULL},
  1328. X    {"-e",        "*expert",            XrmoptionNoArg,        (caddr_t) "True"},
  1329. X    {"-f",        "*MFileName",            XrmoptionSepArg,    (caddr_t) NULL},
  1330. X    {"-fn",        "*Font",            XrmoptionSepArg,    (caddr_t) NULL},
  1331. X    {"-font",        "*Font",            XrmoptionSepArg,    (caddr_t) NULL},
  1332. X    {"-geometry",    ".geometry",            XrmoptionSepArg,    (caddr_t) NULL},
  1333. X    {"-h",        "*icon*useHost",        XrmoptionNoArg,        (caddr_t) "True"},
  1334. X    {"-helpfont",    "*helpFont",            XrmoptionSepArg,    (caddr_t) NULL},
  1335. X    {"-helpFont",    "*helpFont",            XrmoptionSepArg,    (caddr_t) NULL},
  1336. X    {"-iconGeometry",    "*iconGeometry",        XrmoptionSepArg,    (caddr_t) NULL},
  1337. X    {"-iconic",        "*iconic",            XrmoptionNoArg,        (caddr_t) "True"},
  1338. X    {"-ls",        "*show_Last",            XrmoptionNoArg,        (caddr_t) "False"},
  1339. X    {"-n",        "*mailopt_n",            XrmoptionNoArg,        (caddr_t) "True"},
  1340. X    {"-nb",        "*bellRing",            XrmoptionNoArg,        (caddr_t) "False"},
  1341. X    {"-noinfo",        "*show_Info",            XrmoptionNoArg,        (caddr_t) "False"},
  1342. X    {"-nx",        "*no_X_Hdr",            XrmoptionNoArg,        (caddr_t) "True"},
  1343. X    {"-rv",        "*icon*reverseVideo",        XrmoptionNoArg,        (caddr_t) "True"},
  1344. X    {"-textfont",    "*textFont",            XrmoptionSepArg,    (caddr_t) NULL},
  1345. X    {"-textFont",    "*textFont",            XrmoptionSepArg,    (caddr_t) NULL},
  1346. X    {"-U",        "*mailopt_U",            XrmoptionNoArg,        (caddr_t) "True"},
  1347. X    {"-u",        "*icon*useName",        XrmoptionNoArg,        (caddr_t) "True"},
  1348. X    {"-xrm",        NULL,                XrmoptionResArg,    (caddr_t) NULL},
  1349. X};
  1350. X
  1351. X
  1352. XAtom        wmDeleteWindow;        /* for WM_DELETE_WINDOW property */
  1353. XBoolean        In_Bogus_Mail_File;    /* in bogus folder when we're iconic */
  1354. XBoolean        Waiting;        /* TRUE when we set the busy cursor */
  1355. XPixmap        hatch;            /* cross_weave, to indicate new mail */
  1356. XWidget        toplevel;         /* top level shell widget */
  1357. XWindow        WaitCursorWindow;
  1358. X
  1359. XAliasRecPtr    *aliases = NULL;    /* array of mail alias strings */
  1360. XhelpText    *HelpList = NULL;    /* list of help text objects */
  1361. XXmailResources     XMail;            /* application resources of xmail */
  1362. X
  1363. Xint        mailargc;        /* counter passed to mail child    */
  1364. Xint        RootWidth, RootHeight;
  1365. Xint        Highlighted;        /* state of 'Newmail' highlighting */
  1366. X
  1367. Xchar        HOME[BUFSIZ];        /* home directory of user */
  1368. Xchar        Command[BUFSIZ];    /* xmail command string */
  1369. Xchar         InReply[BUFSIZ];    /* reply reference string */
  1370. Xchar         tmpName[BUFSIZ];    /* message temporary filename */
  1371. Xchar        otherBuf[BUFSIZ];    /* bucket for non-addressee names */
  1372. Xchar        foldir[BUFSIZ];        /* name of the folder directory */
  1373. Xchar        lastFolder[BUFSIZ];    /* previous folder's title-bar    */
  1374. Xchar        *mailargv[8];        /* array passed to mail child */
  1375. X
  1376. X/*
  1377. X** @(#)mailoptions() - construct command line arguments for calling mail.
  1378. X**                     Return the argument list for mail and new value of argc.
  1379. X*/
  1380. Xint
  1381. Xmailoptions()
  1382. X{
  1383. X XWMHints    *wm_hints;
  1384. X int        i;
  1385. X char        *cp;
  1386. X
  1387. X
  1388. X if ((cp = (char *)getenv("XMAILER")) == NULL)    /* first looks up env var */
  1389. X      cp = DEFAULT_MAILER;
  1390. X
  1391. X wm_hints = XGetWMHints(XtDisplay(toplevel), XtWindow(toplevel));
  1392. X
  1393. X i = 0;
  1394. X mailargv[i++] = cp;        /* Argv[0] is the name of the program */
  1395. X mailargv[i++] = "-N";        /* no version or header info at start */
  1396. X if (XMail.mailopt_n)
  1397. X    mailargv[i++] = "-n";    /* don't initialize from Mail.rc file */
  1398. X if (XMail.mailopt_U)
  1399. X    mailargv[i++] = "-U";    /* Change uucp to Internet addresses */
  1400. X
  1401. X if (wm_hints->initial_state == IconicState) {    /* start iconic in bogus */
  1402. X    FILE    *fp;
  1403. X
  1404. X    (void) sprintf(InReply, "%s+", tmpName);
  1405. X    if (fp = fopen(InReply, "w")) {    /* create our bogus mail file */
  1406. X       (void) fprintf(fp, "\n");
  1407. X       (void) fclose(fp);
  1408. X       mailargv[i++] = "-f";        /* start in our bogus mail folder */
  1409. X       mailargv[i++] = InReply;
  1410. X       In_Bogus_Mail_File = True;
  1411. X      }
  1412. X   } else if (XMail.MFileName) {
  1413. X         mailargv[i++] = "-f";    /* start from mail folder MFileName */
  1414. X         mailargv[i++] = XMail.MFileName;
  1415. X            }
  1416. X mailargv[i] = NULL;
  1417. X XFree((XWMHints *)wm_hints);
  1418. X return (i);
  1419. X} /* mailoptions */
  1420. X
  1421. X
  1422. X/*
  1423. X** @(#)initialize() - establish xmail program defaults and setups
  1424. X*/
  1425. Xvoid
  1426. Xinitialize()
  1427. X{
  1428. X long        buttonSpace, i;
  1429. X String        disp, file, str_type[20];
  1430. X Display    *dpy = XtDisplay(toplevel);
  1431. X XrmValue    value;
  1432. X struct passwd    *pw;
  1433. X
  1434. X
  1435. X if (XrmGetResource(dpy->db, "command.borderWidth", "Command.BorderWidth",
  1436. X    str_type, &value)) {
  1437. X    if ((i = atoi(value.addr)) > XMail.borderWidth)
  1438. X       XMail.borderWidth = i;
  1439. X   }
  1440. X
  1441. X if (XrmGetResource(dpy->db, "send.borderWidth", "Send.BorderWidth",
  1442. X    str_type, &value)) {
  1443. X    if ((i = atoi(value.addr)) > XMail.borderWidth)
  1444. X       XMail.borderWidth = i;
  1445. X   }
  1446. X
  1447. X lastFolder[0] = foldir[0] = '\0';
  1448. X
  1449. X (void) strcpy(Command, "Start");    /* let parser know we've started */
  1450. X
  1451. X (void) sprintf(tmpName, "/tmp/xmail%d", getpid());
  1452. X
  1453. X pw = getpwuid((uid_t) getuid());    /* get the user's home directory */
  1454. X (void) strcpy(HOME, pw->pw_dir);
  1455. X/*
  1456. X** TRAP any stupid attempt to set the border width of this application to less
  1457. X** than the allowed minimum (0) or greater than an acceptable maximum.  This
  1458. X** to prevent a really wierd reaction to a negative number for border width.
  1459. X*/
  1460. X if (XMail.borderWidth < 0)
  1461. X     XMail.borderWidth = 1;
  1462. X if (XMail.borderWidth > 6)
  1463. X     XMail.borderWidth = 6;
  1464. X/*
  1465. X** Compute all window dimensions based on extents of the specified fonts.
  1466. X** Make shell wide enough to hold eight buttons on a row.  Total button width
  1467. X** includes width of text area plus width of separation plus width of border.
  1468. X*/
  1469. X XMail.commandHSpace    = 10;
  1470. X XMail.commandVSpace    = 10;
  1471. X XMail.buttonHeight    = CHARHEIGHT(XMail.buttonFont) + (XMail.buttonFont->ascent / 2);
  1472. X XMail.buttonWidth    = figureWidth(XMail.buttonFont) * 9; /* ' NewMail ' */
  1473. X       buttonSpace    = XMail.borderWidth * 2;
  1474. X       buttonSpace    += XMail.buttonWidth + XMail.commandHSpace;
  1475. X XMail.shellWidth    = (8 * buttonSpace) + 26;    /*  8 buttons per row */
  1476. X XMail.fileBoxWidth    = (4 * buttonSpace) + XMail.buttonWidth;
  1477. X XMail.helpHeight    = CHARHEIGHT(XMail.helpFont) * 15 + 5;
  1478. X XMail.helpWidth    = figureWidth(XMail.helpFont) * 62 + 5;
  1479. X XMail.helpX        = (XMail.shellWidth - XMail.helpWidth) / 2;
  1480. X XMail.helpY        = 70;
  1481. X       buttonSpace    = CHARHEIGHT(XMail.textFont) + (XMail.textFont->ascent / 2);
  1482. X XMail.indexHeight    = 12 * buttonSpace;
  1483. X XMail.textHeight    = 23 * buttonSpace;
  1484. X XMail.commandHeight    = (XMail.buttonHeight*2) + (XMail.commandVSpace*3) +
  1485. X              (4 * XMail.borderWidth);
  1486. X XMail.menuX        = 15;
  1487. X XMail.menuY        = 7;
  1488. X       RootWidth    = XDisplayWidth(XtDisplay(toplevel),
  1489. X              DefaultScreen(XtDisplay(toplevel))) - 1;
  1490. X       RootHeight    = XDisplayHeight(XtDisplay(toplevel),
  1491. X               DefaultScreen(XtDisplay(toplevel))) - 1;
  1492. X/*
  1493. X** Ensure xmail shell height does not exceed the height of the root window.
  1494. X*/
  1495. X      buttonSpace    = (2 * XMail.buttonHeight) + XMail.indexHeight +
  1496. X              XMail.commandHeight + XMail.textHeight + 
  1497. X              (6 * XMail.borderWidth);
  1498. X
  1499. X for (i = 0, buttonSpace -= RootHeight; buttonSpace > 0; i++) {
  1500. X     buttonSpace -= CHARHEIGHT(XMail.textFont);
  1501. X     if (i % 2)
  1502. X        XMail.indexHeight -= CHARHEIGHT(XMail.textFont);
  1503. X     else
  1504. X        XMail.textHeight -= CHARHEIGHT(XMail.textFont);
  1505. X    }
  1506. X/*
  1507. X** If editorCommand resource exists, warn if it doesn't have two %s entries.
  1508. X*/
  1509. X if (XMail.editorCommand)
  1510. X    if (! (disp =  strchr(XMail.editorCommand, '%')) || *(disp + 1) != 's' ||
  1511. X        ! (file = strrchr(XMail.editorCommand, '%')) || *(file + 1) != 's' ||
  1512. X           disp == file) {
  1513. X    XtWarning("xmail editorCommand resource improperly defined... ignoring");
  1514. X    XtFree((String) XMail.editorCommand);
  1515. X    XMail.editorCommand = NULL;
  1516. X   }
  1517. X
  1518. X parser_init();
  1519. X} /* initialize */
  1520. X
  1521. X
  1522. X/*
  1523. X** @(#)SetHints() - Sets hatching, cursor, icon and size hints, and wm protocol
  1524. X*/
  1525. XSetHints()
  1526. X{
  1527. X Cardinal        x, y;
  1528. X unsigned long        valuemask;
  1529. X Window            win = XtWindow(toplevel);
  1530. X CommandWidget        nm = (CommandWidget)XtNameToWidget(toplevel, "topBox.commandPanel.Newmail");
  1531. X Display        *dpy = XtDisplay(toplevel);
  1532. X Screen            *scn = XtScreen(toplevel);
  1533. X XSetWindowAttributes    attributes;
  1534. X XSizeHints        size_hints;
  1535. X XWMHints        wm_hints;
  1536. X/*
  1537. X** Hatch will be used to indicate new mail arrival on command & folder buttons
  1538. X*/
  1539. X hatch    = XCreatePixmapFromBitmapData(dpy, XtScreen(toplevel)->root,
  1540. X            cross_weave_bits, cross_weave_width, cross_weave_height,
  1541. X            nm->label.foreground, nm->core.background_pixel,
  1542. X            DefaultDepth(dpy, DefaultScreen(dpy)));
  1543. X/*
  1544. X** Notify the window manager about our icon window
  1545. X*/
  1546. X wm_hints.input        = True;
  1547. X wm_hints.initial_state    = (XMail.iconic) ? IconicState : NormalState;
  1548. X wm_hints.flags        = InputHint | StateHint;
  1549. X
  1550. X if (XMail.iconGeometry) {
  1551. X    ParseIconGeometry(XMail.iconGeometry, &x, &y);
  1552. X    wm_hints.icon_x    = x;
  1553. X    wm_hints.icon_y    = y;
  1554. X    wm_hints.flags    |= IconPositionHint;
  1555. X   }
  1556. X wm_hints.flags        |= IconWindowHint;
  1557. X wm_hints.icon_window    = XtWindow(XtNameToWidget(toplevel, "icon"));
  1558. X
  1559. X XSetWMHints(dpy, win, &wm_hints);
  1560. X/*
  1561. X** Set starting position and default geometry
  1562. X*/
  1563. X if (! XGetNormalHints(dpy, win, &size_hints)) {
  1564. X    size_hints.x = 56;
  1565. X    size_hints.y = 56;            /* slightly off from top left corner */
  1566. X   }
  1567. X
  1568. X size_hints.width    = XMail.shellWidth;
  1569. X size_hints.height    = (2 * XMail.buttonHeight) + XMail.indexHeight +
  1570. X              XMail.commandHeight + XMail.textHeight +
  1571. X              (6 * XMail.borderWidth);
  1572. X
  1573. X size_hints.min_width = size_hints.max_width = size_hints.width;
  1574. X size_hints.min_height = size_hints.max_height = size_hints.height;
  1575. X size_hints.flags = USPosition | USSize | PMinSize;
  1576. X
  1577. X XSetNormalHints(dpy, win, &size_hints);
  1578. X/*
  1579. X** Add a protocol flag indicating we wish to handle WM_DELETE_WINDOW requests
  1580. X*/
  1581. X wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  1582. X XSetWMProtocols(dpy, win, &wmDeleteWindow, 1);
  1583. X/*
  1584. X** Create a WaitCursor window, ala FAQ to Ignore device events while
  1585. X** the busy cursor is displayed.  The window will be as big as the
  1586. X** display screen, and clipped by its own parent window, so we never
  1587. X** have to worry about resizing.
  1588. X*/
  1589. X valuemask = CWDontPropagate | CWCursor;
  1590. X
  1591. X attributes.do_not_propagate_mask =  (KeyPressMask | KeyReleaseMask |
  1592. X                                   ButtonPressMask | ButtonReleaseMask |
  1593. X                                   PointerMotionMask);
  1594. X
  1595. X attributes.cursor = XCreateFontCursor(dpy, XC_watch);
  1596. X
  1597. X WaitCursorWindow = XCreateWindow(dpy, win, 0, 0, WidthOfScreen(scn),
  1598. X                          HeightOfScreen(scn), (unsigned int) 0, CopyFromParent,
  1599. X                          InputOnly, CopyFromParent, valuemask, &attributes);
  1600. X} /* SetHints */
  1601. X
  1602. X
  1603. X/*
  1604. X** @(#)main() - main routine for the x11 interface to the mail utility
  1605. X*/
  1606. Xmain(argc, argv)
  1607. Xint    argc;
  1608. XString    *argv;
  1609. X{
  1610. X int    indx, value, aC;
  1611. X String    cp, *aV;
  1612. X
  1613. X static XtActionsRec actionTable[] = {
  1614. X    {"CheckInsert",        (XtActionProc) CheckInsert},
  1615. X    {"DeleteChar",        (XtActionProc) DeleteChar},
  1616. X    {"DeleteLine",        (XtActionProc) DeleteLine},
  1617. X    {"DeleteWord",        (XtActionProc) DeleteWord},
  1618. X    {"DoCmd",        (XtActionProc) DoCmd},
  1619. X    {"DoDone",        (XtActionProc) DoDone},
  1620. X    {"DoNothing",        (XtActionProc) DoNothing},
  1621. X    {"DoReply",        (XtActionProc) DoReply},
  1622. X    {"DoSave",        (XtActionProc) DoSave},
  1623. X    {"DoSelected",        (XtActionProc) DoSelected},
  1624. X    {"Iconify",        (XtActionProc) Iconify},
  1625. X    {"Folder",        (XtActionProc) Folder},
  1626. X    {"MyNotify",        (XtActionProc) MyNotify},
  1627. X    {"NextField",        (XtActionProc) NextField},
  1628. X    {"PrintMsg",        (XtActionProc) PrintMsg},
  1629. X    {"Quit",        (XtActionProc) Quit},
  1630. X    {"SetAliases",        (XtActionProc) SetAliases},
  1631. X    {"SetDirectory",    (XtActionProc) SetDirectory},
  1632. X    {"SetFolders",        (XtActionProc) SetFolders},
  1633. X    {"SetMenu",        (XtActionProc) SetMenu},
  1634. X    {"SetPopup",        (XtActionProc) SetPopup},
  1635. X    {"SetSelect",        (XtActionProc) SetSelect},
  1636. X    {"ShowHelp",        (XtActionProc) ShowHelp},
  1637. X        {NULL, NULL}
  1638. X      };
  1639. X/*
  1640. X** First, examine our command line arguments and Class resources for bogus
  1641. X** values which would cause the application to operate incorrectly.  Drop
  1642. X** command lines arguments and/or change the resource values before we
  1643. X** initialize our widgets.
  1644. X*/
  1645. X aV = (String *) XtMalloc((unsigned) (argc + 1) * sizeof(String *));
  1646. X aC = 0;
  1647. X
  1648. X for (value = indx = 0; indx < argc; indx++)
  1649. X      value += strlen(argv[indx]) + 1;
  1650. X aV[aC] = (String) XtMalloc((unsigned) value);
  1651. X
  1652. X (void) strcpy(aV[aC++], *argv);
  1653. X aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1654. X for (indx = 1; indx < argc; indx++)
  1655. X     switch (argv[indx][0]) {        /* look for, -xrm *[Bb]orderWidth or */
  1656. X         case '-':            /* -bw, w/ negative valued arguments */
  1657. X              if ((argv[indx][1] != 'b'  || argv[indx][2] != 'w') &&
  1658. X                  (argv[indx][1] != 'x'  || argv[indx][2] != 'r'  ||
  1659. X                   argv[indx][3] != 'm') || (indx + 1) >= argc) {
  1660. X                 (void) strcpy(aV[aC++], argv[indx]);
  1661. X                 aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1662. X                }
  1663. X              else if (sscanf(argv[indx+1], "%d", &value) == 1) {
  1664. X                   if (value < 0)
  1665. X                      indx++;        /* skip the value argument too */
  1666. X                   else if (value < 7) {
  1667. X                           (void) strcpy(aV[aC++], argv[indx]);
  1668. X                           aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1669. X                          } else {
  1670. X                           (void) strcpy(aV[aC++], argv[indx++]);
  1671. X                           aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1672. X                           (void) strcpy(aV[aC++], "6");
  1673. X                           aV[aC] = aV[aC - 1] + 2;
  1674. X                          }
  1675. X                }
  1676. X              else if ((cp = strchr(argv[indx + 1], 'o')) == NULL ||
  1677. X                       strncmp(cp, "orderWidth:", 11)     != 0    ||
  1678. X                       sscanf(cp + 11, "%d", &value)      != 1) {
  1679. X                      (void) strcpy(aV[aC++], argv[indx]);
  1680. X                      aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1681. X                     }
  1682. X              else if (value >= 0) {
  1683. X                      if (value < 7) {
  1684. X                         (void) strcpy(aV[aC++], argv[indx]);
  1685. X                         aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1686. X                        } else {
  1687. X                         (void) strcpy(aV[aC++], argv[indx++]);
  1688. X                         aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1689. X                         (void) strcpy(aV[aC], argv[indx]);
  1690. X                         cp = strchr(aV[aC], ':');
  1691. X                         *++cp = '\0';
  1692. X                         (void) strcat(aV[aC], " 6");    /* max allowed value */
  1693. X                         aV[aC + 1] = aV[aC] + strlen(aV[aC]) + 1;
  1694. X                         aC++;
  1695. X                        }
  1696. X                }
  1697. X              else indx++;        /* skip the value argument too */
  1698. X              break;            /* if negative, it is not included */
  1699. X         default :
  1700. X              (void) strcpy(aV[aC++], argv[indx]);
  1701. X              aV[aC] = aV[aC - 1] + strlen(aV[aC - 1]) + 1;
  1702. X              break;
  1703. X        }
  1704. X aV[aC] = NULL;                /* array MUST end with a null */
  1705. X/*
  1706. X** Now, initialize our toplevel widget and parse the command line
  1707. X*/
  1708. X toplevel = XtInitialize(*aV, "XMail", Opts, XtNumber(Opts), &aC, aV);
  1709. X if (aC > 1) {
  1710. X    (void) fprintf(stderr,"Usage: %s [-toolkitoptions] [-xmailoptions]\n",*aV);
  1711. X    exit(-1);
  1712. X    /*NOTREACHED*/
  1713. X   }
  1714. X
  1715. X/*
  1716. X** Next, add xmail specific as well as Athena text widget actions
  1717. X*/
  1718. X XtAddActions(actionTable, XtNumber(actionTable));
  1719. X XtAddActions(_XawTextActionsTable, _XawTextActionsTableCount);
  1720. X
  1721. X XtGetApplicationResources(toplevel, &XMail, resrcs, XtNumber(resrcs), NULL, 0);
  1722. X
  1723. X XtOverrideTranslations(toplevel,
  1724. X                     XtParseTranslationTable("<Message>WM_PROTOCOLS: Quit(q)"));
  1725. X
  1726. X initialize();                /* set window sizes based on font */
  1727. X CreateSubWindows(toplevel);        /* and build our widget hierarchy */
  1728. X XSync(XtDisplay(toplevel), False);    /* ensure everyone's on the same page */
  1729. X XtRealizeWidget(toplevel);        /* initialize widgets for our hints */
  1730. X SetHints();                /* tell WM about our icon and size */
  1731. X
  1732. X mailargc = mailoptions();        /* set up the mail pgm argv and argc */
  1733. X
  1734. X callMail(mailargv);            /* attempt to start Mail connection */
  1735. X
  1736. X SetCursor(WATCH);
  1737. X
  1738. X XtMainLoop();
  1739. X /* NOTREACHED */
  1740. X} /* main */
  1741. END_OF_FILE
  1742.   if test 20058 -ne `wc -c <'xmail.c'`; then
  1743.     echo shar: \"'xmail.c'\" unpacked with wrong size!
  1744.   fi
  1745.   # end of 'xmail.c'
  1746. fi
  1747. echo shar: End of archive 4 \(of 10\).
  1748. cp /dev/null ark4isdone
  1749. MISSING=""
  1750. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1751.     if test ! -f ark${I}isdone ; then
  1752.     MISSING="${MISSING} ${I}"
  1753.     fi
  1754. done
  1755. if test "${MISSING}" = "" ; then
  1756.     echo You have unpacked all 10 archives.
  1757.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1758. else
  1759.     echo You still must unpack the following archives:
  1760.     echo "        " ${MISSING}
  1761. fi
  1762. exit 0
  1763. exit 0 # Just in case...
  1764. -- 
  1765.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  1766. \X/  Amiga - The only way to fly!      |
  1767.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  1768.   casual observer..."                  |
  1769.