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