home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xmh / tocfuncs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-17  |  25.8 KB  |  1,067 lines

  1. /*
  2.  * $XConsortium: tocfuncs.c,v 2.38 91/07/17 21:28:33 converse Exp $
  3.  *
  4.  *
  5.  *            COPYRIGHT 1987, 1989
  6.  *           DIGITAL EQUIPMENT CORPORATION
  7.  *               MAYNARD, MASSACHUSETTS
  8.  *            ALL RIGHTS RESERVED.
  9.  *
  10.  * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
  11.  * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
  12.  * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
  13.  * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
  14.  *
  15.  * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
  16.  * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
  17.  * ADDITION TO THAT SET FORTH ABOVE.
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software and its
  20.  * documentation for any purpose and without fee is hereby granted, provided
  21.  * that the above copyright notice appear in all copies and that both that
  22.  * copyright notice and this permission notice appear in supporting
  23.  * documentation, and that the name of Digital Equipment Corporation not be
  24.  * used in advertising or publicity pertaining to distribution of the software
  25.  * without specific, written prior permission.
  26.  */
  27.  
  28. /* tocfuncs.c -- action procedures concerning things in the toc widget. */
  29.  
  30. #include "xmh.h"
  31. #include "tocutil.h"
  32.  
  33. #define MAX_SYSTEM_LEN 510
  34.  
  35. Boolean UserWantsAction(w, scrn) /* general action procedure "filter" */
  36.     Widget    w;
  37.     Scrn    scrn;
  38. {
  39.     /* Commands in the command menus invoke callbacks directly. 
  40.      * Keyboard accelerators use the command menus as source widgets.
  41.      * Actions can also be specified in the translations for menu buttons.
  42.      * Actions can also be specified in the translations for menus.
  43.      * In fact, the user can attach actions to any (reasonable) widget.
  44.      *
  45.      * The purpose of this check is to prevent actions specified as
  46.      * translations for folder menus and for folder buttons from executing
  47.      * after the mouse pointer has left the folder button or the when the
  48.      * mouse button is released outside of the folder menu.
  49.      *
  50.      * The side effect of this routine is that it restricts keyboard 
  51.      * accelerators from originating from folder buttons or folder menus.
  52.      */
  53.        
  54.     if (XtIsSubclass(w, menuButtonWidgetClass) && /* w is a menu button */
  55.     w != LastMenuButtonPressed)          /* pointer left the window */
  56.     return False;
  57.  
  58.     if (XtIsSubclass(w, simpleMenuWidgetClass) &&    /* w is a menu */
  59.     (! XawSimpleMenuGetActiveEntry(w)) &&    /* no entry was selected */
  60.     (BBoxIsGrandparent(scrn->folderbuttons, w)))  /* w is a folder menu */
  61.     return False;
  62.  
  63.     return True;
  64. }
  65.  
  66.  
  67. /*ARGSUSED*/
  68. static void NextAndPreviousView(scrn, next)
  69.     Scrn    scrn;
  70.     Boolean    next;    /* if true, next or forward; if false, previous */
  71. {
  72.     Toc        toc = scrn->toc;
  73.     MsgList    mlist;
  74.     FateType    fate;
  75.     Msg        msg;
  76.  
  77.     if (toc == NULL) return;
  78.     mlist = TocCurMsgList(toc);
  79.     if (mlist->nummsgs) 
  80.     msg = (next ? mlist->msglist[0] : mlist->msglist[mlist->nummsgs - 1]);
  81.     else {
  82.     msg = TocGetCurMsg(toc);
  83.     if (msg && msg == scrn->msg) 
  84.         msg = (next ? TocMsgAfter(toc, msg) : TocMsgBefore(toc, msg));
  85.     if (msg) fate = MsgGetFate(msg, (Toc *)NULL);
  86.     while (msg && ((app_resources.skip_deleted && fate == Fdelete)
  87.         || (app_resources.skip_moved && fate == Fmove)
  88.         || (app_resources.skip_copied && fate == Fcopy))) {
  89.         msg = (next ? TocMsgAfter(toc, msg) : TocMsgBefore(toc, msg));
  90.         if (msg) fate = MsgGetFate(msg, (Toc *)NULL);
  91.     }
  92.     }
  93.  
  94.     if (msg) {
  95.     XtCallbackRec    confirms[2];
  96.     if (next)
  97.         confirms[0].callback = (XtCallbackProc) DoNextView;
  98.     else
  99.         confirms[0].callback = (XtCallbackProc) DoPrevView;
  100.     confirms[0].closure = (XtPointer) scrn;
  101.     confirms[1].callback = (XtCallbackProc) NULL;
  102.     confirms[1].closure = (XtPointer) NULL;
  103.     if (MsgSetScrn(msg, scrn, confirms, (XtCallbackList) NULL) !=
  104.         NEEDS_CONFIRMATION) {
  105.         TocUnsetSelection(toc);
  106.         TocSetCurMsg(toc, msg);
  107.     }
  108.     }
  109.     FreeMsgList(mlist);
  110. }
  111.  
  112.  
  113. /*ARGSUSED*/
  114. void DoReverseReadOrder(widget, client_data, call_data)
  115.     Widget    widget;        /* the menu entry widget */
  116.     XtPointer    client_data;
  117.     XtPointer    call_data;
  118. {
  119.     app_resources.reverse_read_order =
  120.     (app_resources.reverse_read_order ? False : True);
  121.     ToggleMenuItem(widget, app_resources.reverse_read_order);
  122. }
  123.  
  124.  
  125. /*ARGSUSED*/
  126. void DoNextView(widget, client_data, call_data)
  127.     Widget    widget;        /* unused */
  128.     XtPointer    client_data;
  129.     XtPointer    call_data;    /* unused */
  130. {
  131.     NextAndPreviousView((Scrn) client_data,
  132.             (app_resources.reverse_read_order ? False : True));
  133. }
  134.  
  135. /*ARGSUSED*/
  136. void XmhViewNextMessage(w, event, params, num_params)
  137.     Widget    w;
  138.     XEvent    *event;
  139.     String    *params;
  140.     Cardinal    *num_params;
  141. {
  142.     Scrn scrn = ScrnFromWidget(w);
  143.     if (UserWantsAction(w, scrn))
  144.     DoNextView(w, (XtPointer) scrn, (XtPointer) NULL);
  145. }
  146.  
  147. /*ARGSUSED*/
  148. void DoPrevView(widget, client_data, call_data)
  149.     Widget    widget;        /* unused */
  150.     XtPointer    client_data;    
  151.     XtPointer    call_data;    /* unused */
  152. {
  153.     NextAndPreviousView((Scrn) client_data, 
  154.             (app_resources.reverse_read_order ? True : False));
  155. }
  156.  
  157. /*ARGSUSED*/
  158. void XmhViewPreviousMessage(w, event, params, num_params)
  159.     Widget    w;
  160.     XEvent    *event;
  161.     String    *params;
  162.     Cardinal    *num_params;
  163. {
  164.     Scrn scrn = ScrnFromWidget(w);
  165.     if (UserWantsAction(w, scrn))
  166.     DoPrevView(w, (XtPointer) scrn, (XtPointer) NULL);
  167. }
  168.  
  169.  
  170. /*ARGSUSED*/
  171. void DoViewNew(w, client_data, call_data)
  172.     Widget    w;
  173.     XtPointer    client_data;
  174.     XtPointer    call_data;
  175. {
  176.     Scrn    scrn = (Scrn) client_data;
  177.     Toc        toc = scrn->toc;
  178.     Scrn    vscrn;
  179.     MsgList    mlist;
  180.  
  181.     if (toc == NULL) return;
  182.     mlist = CurMsgListOrCurMsg(toc);
  183.     if (mlist->nummsgs) {
  184.     vscrn = NewViewScrn();
  185.     (void) MsgSetScrn(mlist->msglist[0], vscrn, (XtCallbackList) NULL,
  186.               (XtCallbackList) NULL);
  187.     MapScrn(vscrn);
  188.     }
  189.     FreeMsgList(mlist);
  190. }
  191.  
  192.  
  193. /*ARGSUSED*/
  194. void XmhViewInNewWindow(w, event, params, num_params)
  195.     Widget    w;
  196.     XEvent    *event;
  197.     String    *params;
  198.     Cardinal    *num_params;
  199. {
  200.     Scrn scrn = ScrnFromWidget(w);
  201.     if (UserWantsAction(w, scrn))
  202.     DoViewNew(w, (XtPointer) scrn, (XtPointer) NULL);
  203. }
  204.  
  205.  
  206. /*ARGSUSED*/
  207. void DoForward(w, client_data, call_data)
  208.     Widget    w;
  209.     XtPointer    client_data;
  210.     XtPointer    call_data;
  211. {
  212.     Scrn    scrn = (Scrn) client_data;
  213.     Toc        toc = scrn->toc;
  214.     MsgList    mlist;
  215.  
  216.     if (toc == NULL) return;
  217.     mlist = CurMsgListOrCurMsg(toc);
  218.     if (mlist->nummsgs)
  219.     CreateForward(mlist);
  220.     FreeMsgList(mlist);
  221. }
  222.  
  223.  
  224. /*ARGSUSED*/
  225. void XmhForward(w, event, params, num_params)
  226.     Widget    w;
  227.     XEvent    *event;
  228.     String    *params;
  229.     Cardinal    *num_params;
  230. {
  231.     Scrn scrn = ScrnFromWidget(w);
  232.     if (UserWantsAction(w, scrn))
  233.     DoForward(w, (XtPointer) scrn, (XtPointer) NULL);
  234. }
  235.  
  236.  
  237. /*ARGSUSED*/
  238. void DoTocUseAsComp(w, client_data, call_data)
  239.     Widget    w;
  240.     XtPointer    client_data;
  241.     XtPointer    call_data;
  242. {
  243.     Scrn    scrn = (Scrn) client_data;
  244.     Toc        toc = scrn->toc;
  245.     Scrn    vscrn;
  246.     MsgList    mlist;
  247.     Msg        msg;
  248.  
  249.     if (toc == NULL) return;
  250.     mlist = CurMsgListOrCurMsg(toc);
  251.     if (mlist->nummsgs) {
  252.     vscrn = NewCompScrn();
  253.     if (DraftsFolder == toc) {
  254.         msg = mlist->msglist[0];
  255.     } else {
  256.         msg = TocMakeNewMsg(DraftsFolder);
  257.         MsgLoadCopy(msg, mlist->msglist[0]);
  258.         MsgSetTemporary(msg);
  259.     }
  260.     MsgSetScrnForComp(msg, vscrn);
  261.     MapScrn(vscrn);
  262.     }
  263.     FreeMsgList(mlist);
  264. }
  265.  
  266.  
  267. /*ARGSUSED*/
  268. void XmhUseAsComposition(w, event, params, num_params)
  269.     Widget    w;
  270.     XEvent    *event;
  271.     String    *params;
  272.     Cardinal    *num_params;
  273. {
  274.     Scrn scrn = ScrnFromWidget(w);
  275.     if (UserWantsAction(w, scrn))
  276.     DoTocUseAsComp(w, (XtPointer) scrn, (XtPointer) NULL);
  277. }
  278.  
  279.  
  280. /* Utility: change the fate of a set of messages. */
  281.  
  282. static MarkMessages(scrn, fate, skip)
  283. Scrn scrn;
  284. FateType fate;
  285. int skip;
  286. {
  287.     Toc toc = scrn->toc;
  288.     Toc desttoc;
  289.     int i;
  290.     MsgList mlist;
  291.     Msg msg;
  292.     if (toc == NULL) return;
  293.     if (fate == Fcopy || fate == Fmove)
  294.     desttoc = SelectedToc(scrn);
  295.     else
  296.     desttoc = NULL;
  297.     if (desttoc == toc)
  298.     Feep();
  299.     else {
  300.     mlist = TocCurMsgList(toc);
  301.     if (mlist->nummsgs == 0) {
  302.         msg = TocGetCurMsg(toc);
  303.         if (msg) {
  304.         MsgSetFate(msg, fate, desttoc);
  305.         if (skip)
  306.             DoNextView(scrn->widget, (XtPointer) scrn,
  307.                    (XtPointer) NULL);
  308.         }
  309.     } else {
  310.         for (i = 0; i < mlist->nummsgs; i++)
  311.         MsgSetFate(mlist->msglist[i], fate, desttoc);
  312.     }
  313.     FreeMsgList(mlist);
  314.     }
  315. }
  316.  
  317.  
  318. /*ARGSUSED*/
  319. void XmhMarkDelete(w, event, params, num_params)
  320.     Widget    w;
  321.     XEvent    *event;
  322.     String    *params;
  323.     Cardinal    *num_params;
  324. {
  325.     Scrn scrn = ScrnFromWidget(w);
  326.     if (UserWantsAction(w, scrn))
  327.     DoDelete(w, (XtPointer) scrn, (XtPointer) NULL);
  328. }
  329.  
  330.  
  331. /*ARGSUSED*/
  332. void DoDelete(w, client_data, call_data)
  333.     Widget    w;
  334.     XtPointer    client_data;
  335.     XtPointer    call_data;
  336. {
  337.     Scrn scrn = (Scrn) client_data;
  338.     MarkMessages(scrn, Fdelete, app_resources.skip_deleted);
  339. }
  340.  
  341.  
  342. /*ARGSUSED*/
  343. void DoCopy(w, client_data, call_data)
  344.     Widget    w;
  345.     XtPointer    client_data;
  346.     XtPointer    call_data;
  347. {
  348.     Scrn scrn = (Scrn) client_data;
  349.     MarkMessages(scrn, Fcopy, app_resources.skip_copied);
  350. }
  351.  
  352.  
  353. /*ARGSUSED*/
  354. void XmhMarkCopy(w, event, params, num_params)
  355.     Widget    w;
  356.     XEvent    *event;
  357.     String    *params;
  358.     Cardinal    *num_params;
  359. {
  360.     Scrn scrn = ScrnFromWidget(w);
  361.     if (UserWantsAction(w, scrn))
  362.     DoCopy(w, (XtPointer) scrn, (XtPointer) NULL);
  363. }
  364.  
  365.  
  366. /*ARGSUSED*/
  367. void DoMove(w, client_data, call_data)
  368.     Widget    w;
  369.     XtPointer    client_data;
  370.     XtPointer    call_data;
  371. {
  372.     Scrn scrn = (Scrn) client_data;
  373.     MarkMessages(scrn, Fmove, app_resources.skip_moved);
  374. }
  375.  
  376.  
  377. /*ARGSUSED*/
  378. void XmhMarkMove(w, event, params, num_params)
  379.     Widget    w;
  380.     XEvent    *event;
  381.     String    *params;
  382.     Cardinal    *num_params;
  383. {
  384.     Scrn scrn = ScrnFromWidget(w);
  385.     if (UserWantsAction(w, scrn))
  386.     DoMove(w, (XtPointer) scrn, (XtPointer) NULL);
  387. }
  388.  
  389.  
  390. /*ARGSUSED*/
  391. void DoUnmark(w, client_data, call_data)
  392.     Widget    w;
  393.     XtPointer    client_data;
  394.     XtPointer    call_data;
  395. {
  396.     Scrn scrn = (Scrn) client_data;
  397.     MarkMessages(scrn, Fignore, FALSE);
  398. }
  399.  
  400.  
  401. /*ARGSUSED*/
  402. void XmhUnmark(w, event, params, num_params)
  403.     Widget    w;
  404.     XEvent    *event;
  405.     String    *params;
  406.     Cardinal    *num_params;
  407. {
  408.     Scrn scrn = ScrnFromWidget(w);
  409.     if (UserWantsAction(w, scrn))
  410.     DoUnmark(w, (XtPointer) scrn, (XtPointer) NULL);
  411. }
  412.  
  413.  
  414. /*ARGSUSED*/
  415. void DoCommit(w, client_data, call_data)
  416.     Widget    w;
  417.     XtPointer    client_data;
  418.     XtPointer     call_data;
  419. {
  420.     Scrn    scrn = (Scrn) client_data;
  421.     TocCommitChanges(w, (XtPointer) scrn->toc, (XtPointer) NULL);
  422. }
  423.  
  424.  
  425. /*ARGSUSED*/
  426. void XmhCommitChanges(w, event, params, num_params)
  427.     Widget    w;
  428.     XEvent    *event;
  429.     String    *params;
  430.     Cardinal    *num_params;
  431. {
  432.     Scrn scrn = ScrnFromWidget(w);
  433.     if (UserWantsAction(w, scrn))
  434.     TocCommitChanges(w, (XtPointer) scrn->toc, (XtPointer) NULL);
  435. }
  436.  
  437.  
  438. /*ARGSUSED*/
  439. void XmhShellCommand(w, event, params, num_params)
  440.     Widget    w;     /* any widget on same scrn as the messages */
  441.     XEvent    *event;     /* unused */
  442.     String    *params; /* shell command to execute with msgs appended */
  443.     Cardinal    *num_params;
  444. {
  445.     int        i, len, used;
  446.     MsgList    mlist;
  447.     String    *p;
  448.     Scrn     scrn = ScrnFromWidget(w);
  449.     char    str[MAX_SYSTEM_LEN];
  450.  
  451.     if (! UserWantsAction(w, scrn) || ! scrn->toc)
  452.     return;
  453.     if (! *num_params) {
  454.     PopupError(scrn->parent, "XmhShellCommand: no command given.");
  455.     return;
  456.     }
  457.     used = 0;
  458.     p = params;
  459.     for (i = *num_params; --i >= 0; p++) {
  460.     len = strlen(*p);
  461.     if ((used + len + 1) >= MAX_SYSTEM_LEN) {
  462.         PopupError(scrn->parent, "XmhShellCommand: command too long.");
  463.         return;
  464.     }
  465.     strncpy(&str[used], *p, len);
  466.     str[(used += len)] = ' ';
  467.     used++;
  468.     }
  469.     str[used] = '\0';
  470.  
  471.     mlist = CurMsgListOrCurMsg(scrn->toc);
  472.     if (mlist->nummsgs) {
  473.     char *msg;
  474.     int prefix = used;
  475.     i = 0;
  476.     while (i < mlist->nummsgs) {
  477.         used = prefix;
  478.         while (i < mlist->nummsgs &&
  479.            (msg = MsgFileName(mlist->msglist[i])) &&
  480.            (used + (len = strlen(msg)) + 1) < MAX_SYSTEM_LEN) {
  481.         strncpy(&str[used], msg, len);
  482.         str[(used += len)] = ' ';
  483.         used++;
  484.         i++;
  485.         }
  486.         if (used != prefix) {
  487.         char **argv;
  488.         str[used] = '\0';
  489.         DEBUG( str );
  490.         argv = MakeArgv(3);
  491.         argv[0] = "/bin/sh";
  492.         argv[1] = "-c";    /* commands are read from the next argument */
  493.         argv[2] = str;
  494.         (void) DoCommand(argv, (char*)NULL, (char*)NULL);
  495.         /* a "notice" popup should appear with stderr output */
  496.         XtFree((char*)argv);
  497.         }
  498.     }
  499.     } else
  500.     PopupError(scrn->parent, "XmhShellCommand: no messages selected.");
  501.  
  502.     FreeMsgList(mlist);
  503. }
  504.  
  505.  
  506. void XmhPrint(w, event, params, num_params)
  507.     Widget    w;
  508.     XEvent    *event;
  509.     String    *params;
  510.     Cardinal    *num_params;
  511. {
  512.     if (! num_params || ! *num_params) {
  513.     /* use the print command specified in application resources */
  514.     Cardinal argc = 1;
  515.     String *argv = MakeArgv(argc);
  516.     argv[0] = app_resources.print_command;
  517.     XmhShellCommand(w, event, argv, &argc);
  518.     XtFree((char *) argv);
  519.     } else {
  520.     /* do whatever the user has specified as action parameters */
  521.     XmhShellCommand(w, event, params, num_params);
  522.     }
  523. }
  524.  
  525.  
  526. /*ARGSUSED*/
  527. void DoPrint(w, client_data, call_data)
  528.     Widget    w;
  529.     XtPointer    client_data;
  530.     XtPointer    call_data;    /* unused */
  531. {
  532.     Scrn    scrn = (Scrn) client_data;
  533.     Cardinal    num_params = 0;
  534.     /* The callback interface will not be entered unless the user requested
  535.      * the action, so pass a widget which will succeed the test in 
  536.      * UserWantsAction.
  537.      */
  538.     XmhPrint(scrn->parent, (XEvent*)NULL, (String*)NULL, &num_params);
  539. }
  540.  
  541.  
  542. /*ARGSUSED*/
  543. void DoPack(widget, client_data, call_data)
  544.     Widget    widget;
  545.     XtPointer    client_data;
  546.     XtPointer    call_data;    /* unused */
  547. {
  548.     Scrn    scrn = (Scrn) client_data;
  549.     Toc        toc = scrn->toc;
  550.     XtCallbackRec confirms[2];
  551.     char    **argv;
  552.     
  553.     if (toc == NULL) return;
  554.     confirms[0].callback = (XtCallbackProc) DoPack;
  555.     confirms[0].closure = (XtPointer) scrn;
  556.     confirms[1].callback = (XtCallbackProc) NULL;
  557.     confirms[1].closure = (XtPointer) NULL;
  558.     if (TocConfirmCataclysm(toc, confirms, (XtCallbackRec *) NULL))
  559.     return;
  560.     argv = MakeArgv(4);
  561.     argv[0] = "folder";
  562.     argv[1] = TocMakeFolderName(toc);
  563.     argv[2] = "-pack";
  564.     argv[3] = "-fast";
  565.     if (app_resources.block_events_on_busy) ShowBusyCursor();
  566.  
  567.     DoCommand(argv, (char *) NULL, (char *) NULL);
  568.     XtFree(argv[1]);
  569.     XtFree((char *) argv);
  570.     TocForceRescan(toc);
  571.  
  572.     if (app_resources.block_events_on_busy) UnshowBusyCursor();
  573.  
  574. }
  575.  
  576.  
  577. /*ARGSUSED*/
  578. void XmhPackFolder(w, event, params, num_params)
  579.     Widget    w;
  580.     XEvent    *event;
  581.     String    *params;
  582.     Cardinal    *num_params;
  583. {
  584.     Scrn scrn = ScrnFromWidget(w);
  585.     if (UserWantsAction(w, scrn))
  586.     DoPack(w, (XtPointer) scrn, (XtPointer) NULL);
  587. }
  588.  
  589.  
  590. /*ARGSUSED*/
  591. void DoSort(widget, client_data, call_data)
  592.     Widget    widget;
  593.     XtPointer    client_data;
  594.     XtPointer    call_data;    /* unused */
  595. {
  596.     Scrn    scrn = (Scrn) client_data;
  597.     Toc        toc = scrn->toc;
  598.     char **    argv;
  599.     XtCallbackRec confirms[2];
  600.  
  601.     if (toc == NULL) return;
  602.     confirms[0].callback = (XtCallbackProc) DoSort;
  603.     confirms[0].closure = (XtPointer) scrn;
  604.     confirms[1].callback = (XtCallbackProc) NULL;
  605.     confirms[1].closure = (XtPointer) NULL;
  606.     if (TocConfirmCataclysm(toc, confirms, (XtCallbackRec *) NULL))
  607.     return;
  608.     argv = MakeArgv(3);
  609.     argv[0] = "sortm";
  610.     argv[1] = TocMakeFolderName(toc);
  611.     argv[2] = "-noverbose";
  612.     if (app_resources.block_events_on_busy) ShowBusyCursor();
  613.  
  614.     DoCommand(argv, (char *) NULL, (char *) NULL);
  615.     XtFree(argv[1]);
  616.     XtFree((char *) argv);
  617.     TocForceRescan(toc);
  618.  
  619.     if (app_resources.block_events_on_busy) UnshowBusyCursor();
  620. }
  621.  
  622.  
  623. /*ARGSUSED*/
  624. void XmhSortFolder(w, event, params, num_params)
  625.     Widget    w;
  626.     XEvent    *event;
  627.     String    *params;
  628.     Cardinal    *num_params;
  629. {
  630.     Scrn scrn = ScrnFromWidget(w);
  631.     if (UserWantsAction(w, scrn))
  632.     DoSort(w, (XtPointer) scrn, (XtPointer) NULL);
  633. }
  634.  
  635.  
  636. /*ARGSUSED*/
  637. void XmhForceRescan(w, event, params, num_params)
  638.     Widget    w;
  639.     XEvent    *event;
  640.     String    *params;
  641.     Cardinal    *num_params;
  642. {
  643.     Scrn scrn = ScrnFromWidget(w);
  644.     if (UserWantsAction(w, scrn))
  645.     DoForceRescan(w, (XtPointer) scrn, (XtPointer) NULL);
  646. }
  647.  
  648. /*ARGSUSED*/
  649. void DoForceRescan(w, client_data, call_data)
  650.     Widget    w;
  651.     XtPointer    client_data;
  652.     XtPointer    call_data;
  653. {
  654.     Scrn    scrn = (Scrn) client_data;
  655.     Toc        toc = scrn->toc;
  656.     if (toc == NULL) return;
  657.     if (app_resources.block_events_on_busy) ShowBusyCursor();
  658.  
  659.     TocForceRescan(toc);
  660.     
  661.     if (app_resources.block_events_on_busy) UnshowBusyCursor();
  662. }
  663.  
  664. /*ARGSUSED*/
  665. void XmhCheckForNewMail(w, e, p, n)
  666.     Widget w;
  667.     XEvent *e;
  668.     String *p;
  669.     Cardinal *n;
  670. {
  671.     TocCheckForNewMail(True);
  672. }
  673.  
  674. /* Incorporate new mail. */
  675.  
  676. /*ARGSUSED*/
  677. void XmhIncorporateNewMail(w, event, params, num_params)
  678.     Widget    w;
  679.     XEvent    *event;
  680.     String    *params;
  681.     Cardinal    *num_params;
  682. {
  683.     Scrn scrn = ScrnFromWidget(w);
  684.     if (UserWantsAction(w, scrn)) {
  685.     if (TocCanIncorporate(scrn->toc))
  686.         DoIncorporateNewMail(w, (XtPointer) scrn, (XtPointer) NULL);
  687.     }
  688. }
  689.  
  690.  
  691. void DoIncorporateNewMail(w, client_data, call_data)
  692.     Widget    w;        /* unused */
  693.     XtPointer    client_data;    /* screen */
  694.     XtPointer    call_data;    /* unused */
  695. {
  696.     Scrn scrn = (Scrn) client_data;
  697.     Toc toc = scrn->toc;
  698.     int i;
  699.     int newmail;
  700.  
  701.     if (! toc) return;
  702.     newmail = TocIncorporate(toc);
  703.  
  704.     if (app_resources.show_on_inc && newmail)
  705.     DoNextView(w, client_data, call_data);
  706.  
  707.     if (app_resources.new_mail_check)
  708.     /* update the folder button */
  709.     for (i=0; i < numScrns; i++) {
  710.         scrn = scrnList[i];
  711.         if (scrn->kind == STtocAndView)
  712.         /* give visual indication of no mail waiting */
  713.         BBoxMailFlag(scrn->folderbuttons, TocName(toc), False);
  714.     }
  715.  
  716.     if (app_resources.mail_waiting_flag)
  717.     /* update the icon */
  718.     TocCheckForNewMail(False);
  719. }
  720.  
  721.  
  722. /*ARGSUSED*/
  723. void DoReply(w, client_data, call_data)
  724.     Widget    w;
  725.     XtPointer    client_data;
  726.     XtPointer    call_data;
  727. {
  728.     Scrn    scrn = (Scrn) client_data;
  729.     Toc        toc = scrn->toc;
  730.     Scrn    nscrn;
  731.     MsgList    mlist;
  732.     Msg        msg;
  733.  
  734.     if (toc == NULL) return;
  735.     mlist = CurMsgListOrCurMsg(toc);
  736.     if (mlist->nummsgs) {
  737.     nscrn = NewCompScrn();
  738.     ScreenSetAssocMsg(nscrn, mlist->msglist[0]);
  739.     msg = TocMakeNewMsg(DraftsFolder);
  740.     MsgSetTemporary(msg);
  741.     MsgLoadReply(msg, mlist->msglist[0]);
  742.     MsgSetScrnForComp(msg, nscrn);
  743.     MapScrn(nscrn);
  744.     }
  745.     FreeMsgList(mlist);
  746. }
  747.     
  748.  
  749. /*ARGSUSED*/
  750. void XmhReply(w, event, params, num_params)
  751.     Widget    w;
  752.     XEvent    *event;
  753.     String    *params;
  754.     Cardinal    *num_params;
  755. {
  756.     Scrn scrn = ScrnFromWidget(w);
  757.     if (UserWantsAction(w, scrn))
  758.     DoReply(w, (XtPointer) scrn, (XtPointer) NULL);
  759. }
  760.  
  761.  
  762. /*ARGSUSED*/
  763. void DoPickMessages(w, client_data, call_data)
  764.     Widget    w;
  765.     XtPointer    client_data;
  766.     XtPointer    call_data;
  767. {
  768.     Scrn    scrn = (Scrn) client_data;
  769.     Toc        toc = scrn->toc;
  770.     Scrn    nscrn;
  771.     char *    toseq;
  772.     Sequence    selectedseq;
  773.     Boolean    recycled;
  774.  
  775.     if (toc == NULL) return;
  776.     if ((selectedseq = TocSelectedSequence(toc)) == NULL)
  777.     toseq = "temp";
  778.     else {
  779.     toseq = selectedseq->name;
  780.     if (strcmp(toseq, "all") == 0)
  781.         toseq = "temp";
  782.     }
  783.     nscrn = CreateNewScrn(STpick);
  784.     recycled = (nscrn->pick) ? True : False;
  785.     AddPick(nscrn, toc, (TocViewedSequence(toc))->name, toseq);
  786.     DEBUG("Realizing Pick...")
  787.     XtRealizeWidget(nscrn->parent);
  788.     DEBUG(" done.\n")
  789.     if (! recycled) {
  790.     InitBusyCursor(nscrn);
  791.     XDefineCursor(XtDisplay(nscrn->parent), XtWindow(nscrn->parent),
  792.               app_resources.cursor);
  793.     (void) XSetWMProtocols(XtDisplay(toplevel), XtWindow(nscrn->parent),
  794.                    protocolList, XtNumber(protocolList));
  795.     }
  796.     MapScrn(nscrn);
  797. }
  798.  
  799.  
  800. /*ARGSUSED*/
  801. void XmhPickMessages(w, event, params, num_params)
  802.     Widget    w;
  803.     XEvent    *event;
  804.     String    *params;
  805.     Cardinal    *num_params;
  806. {
  807.     Scrn scrn = ScrnFromWidget(w);
  808.     if (UserWantsAction(w, scrn))
  809.     DoPickMessages(w, (XtPointer) scrn, (XtPointer) NULL);
  810. }
  811.  
  812.  
  813. /*ARGSUSED*/
  814. void DoSelectSequence(widget, client_data, call_data)
  815.     Widget    widget;        /* sequence menu entry object */
  816.     XtPointer    client_data;    /* the screen */
  817.     XtPointer    call_data;
  818. {
  819.     Scrn    scrn = (Scrn) client_data;
  820.     Toc        toc  = (Toc) scrn->toc;
  821.     Sequence    seq;
  822.  
  823.     if ((seq = TocSelectedSequence(toc)) != NULL) {
  824.     Widget    item, menu;
  825.     Button    button;
  826.  
  827.     button = BBoxFindButtonNamed
  828.         (scrn->mainbuttons, MenuBoxButtons[XMH_SEQUENCE].button_name);
  829.     menu = BBoxMenuOfButton(button);
  830.     if ((item = XtNameToWidget(menu, seq->name)) != NULL)
  831.         ToggleMenuItem(item, False);
  832.     }
  833.  
  834.     ToggleMenuItem(widget, True);
  835.     TocSetSelectedSequence(toc, TocGetSeqNamed(toc, XtName(widget)));
  836. }
  837.  
  838.  
  839. /*ARGSUSED*/
  840. void DoOpenSeq(w, client_data, call_data)
  841.     Widget    w;
  842.     XtPointer    client_data;
  843.     XtPointer    call_data;
  844. {
  845.     Scrn    scrn = (Scrn) client_data;
  846.     Toc        toc = scrn->toc;
  847.     if (toc == NULL) return;
  848.     TocChangeViewedSeq(toc, TocSelectedSequence(toc));
  849. }
  850.  
  851.  
  852. /*ARGSUSED*/
  853. void XmhOpenSequence(w, event, params, num_params)
  854.     Widget    w;
  855.     XEvent    *event;
  856.     String    *params;
  857.     Cardinal    *num_params;
  858. {
  859.     Widget    entry_object;
  860.     Scrn    scrn = ScrnFromWidget(w);
  861.     Sequence    selected_sequence;
  862.  
  863.     /* In case this action is called from translations defined by the
  864.      * user on folder menu buttons or on folder menu widgets.
  865.      */
  866.     if (! UserWantsAction(w, scrn))
  867.     return;
  868.  
  869.     /* In case there is nothing to do anyway. */
  870.     if (! TocHasSequences(scrn->toc))
  871.     return;
  872.  
  873.     /* In case the action was given the name of a sequence to open. */
  874.     if (*num_params) {
  875.     Toc    toc = scrn->toc;
  876.     if (selected_sequence = TocGetSeqNamed(toc, params[0])) {
  877.         TocSetSelectedSequence(toc, selected_sequence);
  878.         TocChangeViewedSeq(toc, selected_sequence);
  879.     }
  880.     return;
  881.     }
  882.  
  883.     /* In case this action is a translation on the sequence menu.  */
  884.  
  885.     if ((strcmp(XtName(w), "sequenceMenu") == 0) &&
  886.     (event->type == ButtonRelease)) {
  887.  
  888.     /* The user released the mouse button.  We must distinguish between
  889.      * a button release on a selectable menu entry, and a button release
  890.      * occuring elsewhere.  The button releases occuring elsewhere are 
  891.      * either outside of the menu, or on unselectable menu entries.
  892.      */
  893.  
  894.     if ((entry_object = XawSimpleMenuGetActiveEntry(w)) == NULL)
  895.         return;
  896.  
  897.     /* Some entry in the menu was selected.  The menu entry's callback
  898.      * procedure has already executed.  If a sequence name was selected,
  899.      * the callback procedure has caused that sequence to become the
  900.      * currently selected sequence.  If selected menu entry object's 
  901.      * name matches the currently selected sequence, we should open
  902.      * that sequence.  Otherwise, the user must have selected a sequence
  903.      * manipulation command, such as Pick.  The assumptions here are that
  904.      * the name of a menu entry object which represents a sequence is
  905.      * identical to the name of the sequence, and in the translations,
  906.      * that the notify() action was specified before this action.
  907.      */
  908.  
  909.     if ((selected_sequence = TocSelectedSequence(scrn->toc)) &&
  910.         (strcmp(XtName(entry_object), selected_sequence->name) == 0))
  911.         DoOpenSeq(w, (XtPointer) scrn, (XtPointer) NULL);
  912.     return;
  913.     }
  914.     
  915.     /* An accelerator open sequence function */
  916.  
  917.     DoOpenSeq(w, (XtPointer) scrn, (XtPointer) NULL);
  918. }
  919.  
  920.  
  921. typedef enum {ADD, REMOVE, DELETE} TwiddleOperation;
  922.  
  923. static TwiddleSequence(scrn, op)
  924. Scrn scrn;
  925. TwiddleOperation op;
  926. {
  927.     Toc toc = scrn->toc;
  928.     char **argv, str[100];
  929.     int i;
  930.     MsgList mlist;
  931.     Sequence    selectedseq;
  932.  
  933.     if (toc == NULL || ((selectedseq = TocSelectedSequence(toc)) == NULL))
  934.     return;
  935.     if (strcmp(selectedseq->name, "all") == 0) {
  936.     Feep();
  937.     return;
  938.     }
  939.     if (op == DELETE)
  940.     mlist = MakeNullMsgList();
  941.     else {
  942.     mlist = CurMsgListOrCurMsg(toc);
  943.     if (mlist->nummsgs == 0) {
  944.         FreeMsgList(mlist);
  945.         Feep();
  946.         return;
  947.     }
  948.     }
  949.     argv = MakeArgv(6 + mlist->nummsgs);
  950.     argv[0] = "mark";
  951.     argv[1] = TocMakeFolderName(toc);
  952.     argv[2] = "-sequence";
  953.     argv[3] = selectedseq->name;
  954.     switch (op) {
  955.       case ADD:
  956.     argv[4] = "-add";
  957.     argv[5] = "-nozero";
  958.     break;
  959.       case REMOVE:
  960.     argv[4] = "-delete";
  961.     argv[5] = "-nozero";
  962.     break;
  963.       case DELETE:
  964.     argv[4] = "-delete";
  965.     argv[5] = "all";
  966.     break;
  967.     }
  968.     for (i = 0; i < mlist->nummsgs; i++) {
  969.     (void) sprintf(str, "%d", MsgGetId(mlist->msglist[i]));
  970.     argv[6 + i] = XtNewString(str);
  971.     }
  972.     DoCommand(argv, (char *) NULL, (char *) NULL);
  973.     for (i = 0; i < mlist->nummsgs; i++)
  974.         XtFree((char *) argv[6 + i]);
  975.     XtFree(argv[1]);
  976.     XtFree((char *) argv);
  977.     FreeMsgList(mlist);
  978.     TocReloadSeqLists(toc);
  979. }
  980.  
  981.  
  982. /*ARGSUSED*/
  983. void DoAddToSeq(w, client_data, call_data)
  984.     Widget    w;
  985.     XtPointer    client_data;
  986.     XtPointer    call_data;
  987. {
  988.     Scrn    scrn = (Scrn) client_data;
  989.     TwiddleSequence(scrn, ADD);
  990. }
  991.  
  992.  
  993. /*ARGSUSED*/
  994. void XmhAddToSequence(w, event, params, num_params)
  995.     Widget    w;
  996.     XEvent    *event;
  997.     String    *params;
  998.     Cardinal    *num_params;
  999. {
  1000.     Scrn scrn = ScrnFromWidget(w);
  1001.     if (! UserWantsAction(w, scrn))
  1002.     return;
  1003.     if ((strcmp(XtName(w), "sequenceMenu") == 0) &&
  1004.     (event->type == ButtonRelease) &&
  1005.     (XawSimpleMenuGetActiveEntry(w) == NULL))
  1006.     return;
  1007.     if (TocHasSequences(scrn->toc))
  1008.     TwiddleSequence(scrn, ADD);
  1009. }
  1010.  
  1011.  
  1012. /*ARGSUSED*/
  1013. void DoRemoveFromSeq(w, client_data, call_data)
  1014.     Widget    w;
  1015.     XtPointer    client_data;
  1016.     XtPointer    call_data;
  1017. {
  1018.     Scrn    scrn = (Scrn) client_data;
  1019.     TwiddleSequence(scrn, REMOVE);
  1020. }
  1021.  
  1022.  
  1023. /*ARGSUSED*/
  1024. void XmhRemoveFromSequence(w, event, params, num_params)
  1025.     Widget    w;
  1026.     XEvent    *event;
  1027.     String    *params;
  1028.     Cardinal    *num_params;
  1029. {
  1030.     Scrn scrn = ScrnFromWidget(w);
  1031.     if (UserWantsAction(w, scrn))
  1032.     if (TocHasSequences(scrn->toc))
  1033.         TwiddleSequence(scrn, REMOVE);
  1034. }
  1035.  
  1036.  
  1037. /*ARGSUSED*/
  1038. void DoDeleteSeq(w, client_data, call_data)
  1039.     Widget    w;
  1040.     XtPointer    client_data;
  1041.     XtPointer    call_data;
  1042. {
  1043.     Scrn    scrn = (Scrn) client_data;
  1044.     TwiddleSequence(scrn, DELETE);
  1045.     TUCheckSequenceMenu(scrn->toc);
  1046. }
  1047.  
  1048.  
  1049. /*ARGSUSED*/
  1050. void XmhDeleteSequence(w, event, params, num_params)
  1051.     Widget    w;
  1052.     XEvent    *event;
  1053.     String    *params;
  1054.     Cardinal    *num_params;
  1055. {
  1056.     Scrn scrn = ScrnFromWidget(w);
  1057.     if (! UserWantsAction(w, scrn))
  1058.     return;
  1059.     if ((strcmp(XtName(w), "sequenceMenu") == 0) &&
  1060.     (event->type == ButtonRelease) &&
  1061.     (XawSimpleMenuGetActiveEntry(w) == NULL))
  1062.     return;
  1063.     if (TocHasSequences(scrn->toc))
  1064.     DoDeleteSeq(w, (XtPointer) scrn, (XtPointer) NULL);
  1065. }
  1066.  
  1067.