source: trunk/third/xmh/screen.c @ 9658

Revision 9658, 15.2 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9657, which included commits to RCS files with non-trunk default branches.
RevLine 
[9657]1/*
2 * $XConsortium: screen.c,v 2.62 91/07/22 21:23:25 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/* scrn.c -- management of scrns. */
29
30#include "xmh.h"
31
32XmhMenuEntryRec folderMenu[] = {
33    {"open",                    DoOpenFolder},
34    {"openInNew",               DoOpenFolderInNewWindow},
35    {"create",                  DoCreateFolder},
36    {"delete",                  DoDeleteFolder},
37    {"line",                    (XtCallbackProc) NULL},
38    {"close",                   DoClose},
39};
40
41XmhMenuEntryRec tocMenu[] = {
42    {"inc",                     DoIncorporateNewMail},
43    {"commit",                  DoCommit},
44    {"pack",                    DoPack},
45    {"sort",                    DoSort},
46    {"rescan",                  DoForceRescan},
47};
48
49XmhMenuEntryRec messageMenu[] = {
50    {"compose",                 DoComposeMessage},
51    {"next",                    DoNextView},
52    {"prev",                    DoPrevView},
53    {"delete",                  DoDelete},
54    {"move",                    DoMove},
55    {"copy",                    DoCopy},
56    {"unmark",                  DoUnmark},
57    {"viewNew",                 DoViewNew},
58    {"reply",                   DoReply},
59    {"forward",                 DoForward},
60    {"useAsComp",               DoTocUseAsComp},
61    {"print",                   DoPrint},
62};
63
64XmhMenuEntryRec sequenceMenu[] = {
65    {"pick",                    DoPickMessages},
66    {"openSeq",                 DoOpenSeq},
67    {"addToSeq",                DoAddToSeq},
68    {"removeFromSeq",           DoRemoveFromSeq},
69    {"deleteSeq",               DoDeleteSeq},
70    {"line",                    (XtCallbackProc) NULL},
71    {"all",                     DoSelectSequence},
72};
73
74XmhMenuEntryRec viewMenu[] = {
75    {"reply",                   DoViewReply},
76    {"forward",                 DoViewForward},
77    {"useAsComp",               DoViewUseAsComposition},
78    {"edit",                    DoEditView},
79    {"save",                    DoSaveView},
80    {"print",                   DoPrintView},
81};
82
83XmhMenuEntryRec optionMenu[] = {
84    {"reverse",                 DoReverseReadOrder},
85};
86
87XmhMenuButtonDescRec    MenuBoxButtons[] = {
88    {"folderButton",    "folderMenu",   XMH_FOLDER,     folderMenu,
89         XtNumber(folderMenu) },
90    {"tocButton",       "tocMenu",      XMH_TOC,        tocMenu,
91         XtNumber(tocMenu) },
92    {"messageButton",   "messageMenu",  XMH_MESSAGE,    messageMenu,
93         XtNumber(messageMenu) },
94    {"sequenceButton",  "sequenceMenu", XMH_SEQUENCE,   sequenceMenu,
95         XtNumber(sequenceMenu) },
96    {"viewButton",      "viewMenu",     XMH_VIEW,       viewMenu,
97         XtNumber(viewMenu) },
98    {"optionButton",    "optionMenu",   XMH_OPTION,     optionMenu,
99         XtNumber(optionMenu) },
100};
101
102
103/* Fill in the buttons for the view commands. */
104
105static void FillViewButtons(scrn)
106Scrn scrn;
107{
108    ButtonBox buttonbox = scrn->viewbuttons;
109    BBoxAddButton(buttonbox, "close", commandWidgetClass, True);
110    BBoxAddButton(buttonbox, "reply", commandWidgetClass, True);
111    BBoxAddButton(buttonbox, "forward", commandWidgetClass, True);
112    BBoxAddButton(buttonbox, "useAsComp", commandWidgetClass, True);
113    BBoxAddButton(buttonbox, "edit", commandWidgetClass, True);
114    BBoxAddButton(buttonbox, "save", commandWidgetClass, False);
115    BBoxAddButton(buttonbox, "print", commandWidgetClass, True);
116    BBoxAddButton(buttonbox, "delete", commandWidgetClass, True);
117}
118   
119
120
121static void FillCompButtons(scrn)
122Scrn scrn;
123{
124    ButtonBox buttonbox = scrn->viewbuttons;
125    BBoxAddButton(buttonbox, "close", commandWidgetClass, True);
126    BBoxAddButton(buttonbox, "send", commandWidgetClass, True);
127    BBoxAddButton(buttonbox, "reset", commandWidgetClass, True);
128    BBoxAddButton(buttonbox, "compose", commandWidgetClass, True);
129    BBoxAddButton(buttonbox, "save", commandWidgetClass, True);
130    BBoxAddButton(buttonbox, "insert", commandWidgetClass, True);
131}
132
133
134static void MakeCommandMenu(scrn, mbd)
135    Scrn                scrn;
136    XmhMenuButtonDesc   mbd;
137{
138    register int i;
139    Cardinal     n;
140    Widget      menu;
141    ButtonBox   buttonbox = scrn->mainbuttons;
142    XmhMenuEntry        e;
143    Boolean     indent;
144    WidgetClass widgetclass;
145    Arg         args[4];
146    static XtCallbackRec callbacks[] = {
147        { (XtCallbackProc) NULL, (XtPointer) NULL},
148        { (XtCallbackProc) NULL, (XtPointer) NULL},
149        { (XtCallbackProc) NULL, (XtPointer) NULL},
150    };
151
152    /* Menus are created as childen of the Paned widget of the scrn in order
153     * that they can be used both as pop-up and as pull-down menus.
154     */
155
156    n = 0;
157    if (mbd->id == XMH_SEQUENCE) {
158        XtSetArg(args[n], XtNallowShellResize, True);   n++;
159    }
160    menu = XtCreatePopupShell(mbd->menu_name, simpleMenuWidgetClass,
161                              scrn->widget, args, n);
162
163    indent = (mbd->id == XMH_SEQUENCE || mbd->id == XMH_OPTION) ? True : False;
164    e = mbd->entry;
165    for (i=0; i < mbd->num_entries; i++, e++) {
166        n = 0;
167        if (e->function) {
168            callbacks[0].callback = e->function;
169            callbacks[0].closure  = (XtPointer) scrn;
170            callbacks[1].callback = (app_resources.sticky_menu
171                                     ? (XtCallbackProc) DoRememberMenuSelection
172                                     : (XtCallbackProc) NULL);
173            XtSetArg(args[n], XtNcallback, callbacks);  n++;
174
175            if (indent) { XtSetArg(args[n], XtNleftMargin, 18); n++; }
176            widgetclass = smeBSBObjectClass;
177        } else
178            widgetclass = smeLineObjectClass;
179        XtCreateManagedWidget(e->name, widgetclass, menu, args, n);
180    }
181
182    AttachMenuToButton( BBoxFindButtonNamed( buttonbox, mbd->button_name),
183                       menu, mbd->menu_name);
184    if (mbd->id == XMH_OPTION && app_resources.reverse_read_order)
185        ToggleMenuItem(XtNameToWidget(menu, "reverse"), True);
186}
187
188
189/* Create subwidgets for a toc&view window. */
190
191static void MakeTocAndView(scrn)
192Scrn scrn;
193{
194    register int        i;
195    XmhMenuButtonDesc   mbd;
196    ButtonBox           buttonbox;
197    char                *name;
198    static XawTextSelectType sarray[] = {XawselectLine,
199                                        XawselectPosition,
200                                        XawselectAll,
201                                        XawselectNull};
202    static Arg args[] = {
203        { XtNselectTypes,       (XtArgVal) sarray},
204        { XtNdisplayCaret,      (XtArgVal) False}
205    };
206
207    scrn->mainbuttons   = BBoxCreate(scrn, "menuBox");
208    scrn->folderlabel   = CreateTitleBar(scrn, "folderTitlebar");
209    scrn->folderbuttons = BBoxCreate(scrn, "folders");
210    scrn->toclabel      = CreateTitleBar(scrn, "tocTitlebar");
211    scrn->tocwidget     = CreateTextSW(scrn, "toc", args, XtNumber(args));
212    if (app_resources.command_button_count > 0)
213        scrn->miscbuttons = BBoxCreate(scrn, "commandBox");
214    scrn->viewlabel     = CreateTitleBar(scrn, "viewTitlebar");
215    scrn->viewwidget    = CreateTextSW(scrn, "view", args, (Cardinal) 0);
216
217    /* the command buttons and menus */
218
219    buttonbox = scrn->mainbuttons;
220    mbd = MenuBoxButtons;
221    for (i=0; i < XtNumber(MenuBoxButtons); i++, mbd++) {
222        name = mbd->button_name;
223        BBoxAddButton(buttonbox, name, menuButtonWidgetClass, True);
224        MakeCommandMenu(scrn, mbd);
225    }
226
227    /* the folder buttons; folder menus are created on demand. */
228
229    buttonbox = scrn->folderbuttons;
230    for (i=0 ; i<numFolders ; i++) {
231        name = TocName(folderList[i]);
232        if (! IsSubfolder(name))
233            BBoxAddButton(buttonbox, name, menuButtonWidgetClass, True);
234        if (app_resources.new_mail_check &&
235            numScrns > 1 &&
236            TocCanIncorporate(folderList[i]))
237            BBoxMailFlag(buttonbox, name, TocHasMail(folderList[i]));
238    }
239
240    /* the optional miscellaneous command buttons */
241
242    if (app_resources.command_button_count > 0) {
243        char    name[12];
244        if (app_resources.command_button_count > 500)
245            app_resources.command_button_count = 500;
246        for (i=1; i <= app_resources.command_button_count; i++) {
247            sprintf(name, "button%d", i);
248            BBoxAddButton(scrn->miscbuttons, name, commandWidgetClass, True);
249        }
250    }
251}
252
253static void MakeView(scrn)
254Scrn scrn;
255{
256    scrn->viewlabel = CreateTitleBar(scrn, "viewTitlebar");
257    scrn->viewwidget = CreateTextSW(scrn, "view", (ArgList)NULL, (Cardinal)0);
258    scrn->viewbuttons = BBoxCreate(scrn, "viewButtons");
259    FillViewButtons(scrn);
260}
261
262
263static void MakeComp(scrn)
264Scrn scrn;
265{
266    scrn->viewlabel = CreateTitleBar(scrn, "composeTitlebar");
267    scrn->viewwidget = CreateTextSW(scrn, "comp", (ArgList)NULL, (Cardinal)0);
268    scrn->viewbuttons = BBoxCreate(scrn, "compButtons");
269    FillCompButtons(scrn);
270}
271
272
273/* Create a scrn of the given type. */
274
275Scrn CreateNewScrn(kind)
276ScrnKind kind;
277{
278    int i;
279    Scrn scrn;
280    static Arg arglist[] = {
281        { XtNgeometry,  (XtArgVal) NULL},
282        { XtNinput,     (XtArgVal) True}
283    };
284
285    for (i=0 ; i<numScrns ; i++)
286        if (scrnList[i]->kind == kind && !scrnList[i]->mapped)
287            return scrnList[i];
288    switch (kind) {
289       case STtocAndView: arglist[0].value =
290                           (XtArgVal)app_resources.toc_geometry;        break;
291       case STview:       arglist[0].value =
292                           (XtArgVal)app_resources.view_geometry;       break;
293       case STcomp:       arglist[0].value =
294                           (XtArgVal)app_resources.comp_geometry;       break;
295       case STpick:       arglist[0].value =
296                           (XtArgVal)app_resources.pick_geometry;       break;
297    }
298
299    numScrns++;
300    scrnList = (Scrn *)
301        XtRealloc((char *) scrnList, (unsigned) numScrns*sizeof(Scrn));
302    scrn = scrnList[numScrns - 1] = XtNew(ScrnRec);
303    bzero((char *)scrn, sizeof(ScrnRec));
304    scrn->kind = kind;
305    if (numScrns == 1) scrn->parent = toplevel;
306    else scrn->parent = XtCreatePopupShell(
307                                   progName, topLevelShellWidgetClass,
308                                   toplevel, arglist, XtNumber(arglist));
309    XtAugmentTranslations(scrn->parent,
310                          app_resources.wm_protocols_translations);
311    scrn->widget =
312        XtCreateManagedWidget(progName, panedWidgetClass, scrn->parent,
313                              (ArgList) NULL, (Cardinal) 0);
314
315    switch (kind) {
316        case STtocAndView:      MakeTocAndView(scrn); break;
317        case STview:            MakeView(scrn); break;
318        case STcomp:            MakeComp(scrn); break;
319    }
320
321    if (kind != STpick) {
322        int     theight, min, max;
323        Arg     args[1];
324
325        DEBUG("Realizing...")
326        XtRealizeWidget(scrn->parent);
327        DEBUG(" done.\n")
328
329        switch (kind) {
330          case STtocAndView:
331            BBoxLockSize(scrn->mainbuttons);
332            BBoxLockSize(scrn->folderbuttons);
333            theight = GetHeight(scrn->tocwidget) + GetHeight(scrn->viewwidget);
334            theight = app_resources.toc_percentage * theight / 100;
335            XawPanedGetMinMax((Widget) scrn->tocwidget, &min, &max);
336            XawPanedSetMinMax((Widget) scrn->tocwidget, theight, theight);
337            XawPanedSetMinMax((Widget) scrn->tocwidget, min, max);
338            if (scrn->miscbuttons)
339                BBoxLockSize(scrn->miscbuttons);
340
341            /* fall through */
342
343          case STview:
344
345            /* Install accelerators; not active while editing in the view */
346
347            XtSetArg(args[0], XtNtranslations, &(scrn->edit_translations));
348            XtGetValues(scrn->viewwidget, args, (Cardinal) 1);
349            XtInstallAllAccelerators(scrn->widget, scrn->widget);
350            if (kind == STtocAndView)
351                XtInstallAllAccelerators(scrn->tocwidget, scrn->widget);
352            XtInstallAllAccelerators(scrn->viewwidget, scrn->widget);
353            XtSetArg(args[0], XtNtranslations, &(scrn->read_translations));
354            XtGetValues(scrn->viewwidget, args, (Cardinal) 1);
355
356            if (kind == STview)
357                BBoxLockSize(scrn->viewbuttons);
358            break;
359
360          case STcomp:
361            BBoxLockSize(scrn->viewbuttons);
362            XtInstallAllAccelerators(scrn->viewwidget, scrn->widget);
363            XtSetKeyboardFocus(scrn->parent, scrn->viewwidget);
364            break;
365        }
366
367        InitBusyCursor(scrn);
368        XDefineCursor(XtDisplay(scrn->parent), XtWindow(scrn->parent),
369                      app_resources.cursor);
370        (void) XSetWMProtocols(XtDisplay(scrn->parent), XtWindow(scrn->parent),
371                               protocolList, XtNumber(protocolList));
372    }
373    scrn->mapped = (numScrns == 1);
374    return scrn;
375}
376
377
378Scrn NewViewScrn()
379{
380    return CreateNewScrn(STview);
381}
382
383Scrn NewCompScrn()
384{
385    Scrn scrn;
386    scrn = CreateNewScrn(STcomp);
387    scrn->assocmsg = (Msg)NULL;
388    return scrn;
389}
390
391void ScreenSetAssocMsg(scrn, msg)
392  Scrn scrn;
393  Msg msg;
394{
395    scrn->assocmsg = msg;
396}
397
398/* Destroy the screen.  If unsaved changes are in a msg, too bad. */
399
400void DestroyScrn(scrn)
401  Scrn scrn;
402{
403    if (scrn->mapped) {
404        scrn->mapped = False;
405        XtPopdown(scrn->parent);
406        TocSetScrn((Toc) NULL, scrn);
407        MsgSetScrnForce((Msg) NULL, scrn);
408        lastInput.win = -1;
409    }
410}
411
412
413void MapScrn(scrn)
414Scrn scrn;
415{
416    if (!scrn->mapped) {
417        XtPopup(scrn->parent, XtGrabNone);
418        scrn->mapped = True;
419    }
420}
421
422
423Scrn ScrnFromWidget(w)          /* heavily used, should be efficient */
424Widget w;
425{
426    register int i;
427    while (w && (XtClass(w) != applicationShellWidgetClass) &&
428           (XtClass(w) != topLevelShellWidgetClass))
429        w = XtParent(w);
430    if (w) {
431        for (i=0 ; i<numScrns ; i++) {
432            if (w == (Widget) scrnList[i]->parent)
433                return scrnList[i];
434        }
435    }
436    Punt("ScrnFromWidget failed!");
437    /*NOTREACHED*/
438}
439 
440
441/* Figure out which buttons should and shouldn't be enabled in the given
442 * screen.  This should be called whenever something major happens to the
443 * screen.
444 */
445
446
447/*ARGSUSED*/
448static void EnableCallback(w, data, junk)
449Widget w;
450XtPointer data, junk;
451{
452  EnableProperButtons( (Scrn) data);
453
454
455static void EnableCallback();
456
457#define SetButton(buttonbox, name, value) \
458    if (value) BBoxEnable(BBoxFindButtonNamed(buttonbox, name)); \
459    else BBoxDisable(BBoxFindButtonNamed(buttonbox, name));
460
461
462void EnableProperButtons(scrn)
463Scrn scrn;
464{
465    int value, changed, reapable;
466    Button      button;
467
468    if (scrn) {
469        switch (scrn->kind) {
470          case STtocAndView:
471            button = BBoxFindButtonNamed
472                (scrn->mainbuttons, MenuBoxButtons[XMH_TOC].button_name);
473            value = TocCanIncorporate(scrn->toc);
474            SendMenuEntryEnableMsg(button, "inc", value);
475
476            button = BBoxFindButtonNamed
477                (scrn->mainbuttons, MenuBoxButtons[XMH_SEQUENCE].button_name);
478            value = TocHasSequences(scrn->toc);
479            SendMenuEntryEnableMsg(button, "openSeq", value);
480            SendMenuEntryEnableMsg(button, "addToSeq", value);
481            SendMenuEntryEnableMsg(button, "removeFromSeq", value);
482            SendMenuEntryEnableMsg(button, "deleteSeq", value);
483
484            button = BBoxFindButtonNamed
485                 (scrn->mainbuttons, MenuBoxButtons[XMH_VIEW].button_name);
486            value = (scrn->msg != NULL && !MsgGetEditable(scrn->msg));
487            SendMenuEntryEnableMsg(button, "edit", value);
488            SendMenuEntryEnableMsg(button, "save",
489                                   scrn->msg != NULL && !value);
490            break;
491          case STview:
492            value = (scrn->msg != NULL && !MsgGetEditable(scrn->msg));
493            SetButton(scrn->viewbuttons, "edit", value);
494            SetButton(scrn->viewbuttons, "save", scrn->msg != NULL && !value);
495            break;
496          case STcomp:
497            if (scrn->msg != NULL) {
498                changed = MsgChanged(scrn->msg);
499                reapable = MsgGetReapable(scrn->msg);
500                SetButton(scrn->viewbuttons, "send", changed || !reapable);
501                SetButton(scrn->viewbuttons, "save", changed || reapable);
502                SetButton(scrn->viewbuttons, "insert",
503                          scrn->assocmsg != NULL ? True : False);
504
505                if (!changed)
506                    MsgSetCallOnChange(scrn->msg, EnableCallback,
507                                       (XtPointer) scrn);
508                else
509                    MsgSetCallOnChange(scrn->msg, (XtCallbackProc) NULL,
510                                       (XtPointer) NULL);
511
512            } else {
513                BBoxDisable( BBoxFindButtonNamed(scrn->viewbuttons, "send"));
514                BBoxDisable( BBoxFindButtonNamed(scrn->viewbuttons, "save"));
515                BBoxDisable( BBoxFindButtonNamed(scrn->viewbuttons, "insert"));
516            }
517            break;
518        }
519    }
520}
Note: See TracBrowser for help on using the repository browser.