screen.c revision d859ff80
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 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 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 = (Scrn *) 298 XtRealloc((char *) scrnList, (unsigned) numScrns*sizeof(Scrn)); 299 scrn = scrnList[numScrns - 1] = XtNew(ScrnRec); 300 bzero((char *)scrn, sizeof(ScrnRec)); 301 scrn->kind = kind; 302 if (numScrns == 1) scrn->parent = toplevel; 303 else scrn->parent = XtCreatePopupShell( 304 progName, topLevelShellWidgetClass, 305 toplevel, arglist, XtNumber(arglist)); 306 XtAugmentTranslations(scrn->parent, 307 app_resources.wm_protocols_translations); 308 scrn->widget = 309 XtCreateManagedWidget(progName, panedWidgetClass, scrn->parent, 310 (ArgList) NULL, (Cardinal) 0); 311 312 switch (kind) { 313 case STtocAndView: MakeTocAndView(scrn); break; 314 case STview: MakeView(scrn); break; 315 case STcomp: MakeComp(scrn); break; 316 default: break; 317 } 318 319 if (kind != STpick) { 320 int theight, min, max; 321 Arg args[1]; 322 323 DEBUG("Realizing...") 324 XtRealizeWidget(scrn->parent); 325 DEBUG(" done.\n") 326 327 switch (kind) { 328 case STtocAndView: 329 BBoxLockSize(scrn->mainbuttons); 330 BBoxLockSize(scrn->folderbuttons); 331 theight = GetHeight(scrn->tocwidget) + GetHeight(scrn->viewwidget); 332 theight = app_resources.toc_percentage * theight / 100; 333 XawPanedGetMinMax((Widget) scrn->tocwidget, &min, &max); 334 XawPanedSetMinMax((Widget) scrn->tocwidget, theight, theight); 335 XawPanedSetMinMax((Widget) scrn->tocwidget, min, max); 336 if (scrn->miscbuttons) 337 BBoxLockSize(scrn->miscbuttons); 338 339 /* fall through */ 340 341 case STview: 342 343 /* Install accelerators; not active while editing in the view */ 344 345 XtSetArg(args[0], XtNtranslations, &(scrn->edit_translations)); 346 XtGetValues(scrn->viewwidget, args, (Cardinal) 1); 347 XtInstallAllAccelerators(scrn->widget, scrn->widget); 348 if (kind == STtocAndView) 349 XtInstallAllAccelerators(scrn->tocwidget, scrn->widget); 350 XtInstallAllAccelerators(scrn->viewwidget, scrn->widget); 351 XtSetArg(args[0], XtNtranslations, &(scrn->read_translations)); 352 XtGetValues(scrn->viewwidget, args, (Cardinal) 1); 353 354 if (kind == STview) 355 BBoxLockSize(scrn->viewbuttons); 356 break; 357 358 case STcomp: 359 BBoxLockSize(scrn->viewbuttons); 360 XtInstallAllAccelerators(scrn->viewwidget, scrn->widget); 361 XtSetKeyboardFocus(scrn->parent, scrn->viewwidget); 362 break; 363 364 default: 365 break; 366 } 367 368 InitBusyCursor(scrn); 369 XDefineCursor(XtDisplay(scrn->parent), XtWindow(scrn->parent), 370 app_resources.cursor); 371 (void) XSetWMProtocols(XtDisplay(scrn->parent), XtWindow(scrn->parent), 372 protocolList, XtNumber(protocolList)); 373 } 374 scrn->mapped = False; 375 return scrn; 376} 377 378 379Scrn NewViewScrn(void) 380{ 381 return CreateNewScrn(STview); 382} 383 384Scrn NewCompScrn(void) 385{ 386 Scrn scrn; 387 scrn = CreateNewScrn(STcomp); 388 scrn->assocmsg = (Msg)NULL; 389 return scrn; 390} 391 392void ScreenSetAssocMsg(Scrn scrn, Msg msg) 393{ 394 scrn->assocmsg = msg; 395} 396 397/* Destroy the screen. If unsaved changes are in a msg, too bad. */ 398 399void DestroyScrn(Scrn scrn) 400{ 401 if (scrn->mapped) { 402 scrn->mapped = False; 403 XtPopdown(scrn->parent); 404 TocSetScrn((Toc) NULL, scrn); 405 MsgSetScrnForce((Msg) NULL, scrn); 406 lastInput.win = -1; 407 } 408} 409 410 411void MapScrn(Scrn scrn) 412{ 413 if (!scrn->mapped) { 414 XtPopup(scrn->parent, XtGrabNone); 415 scrn->mapped = True; 416 } 417} 418 419 420Scrn ScrnFromWidget(Widget w) /* heavily used, should be efficient */ 421{ 422 register int i; 423 while (w && ! XtIsTopLevelShell(w)) 424 w = XtParent(w); 425 if (w) { 426 for (i=0 ; i<numScrns ; i++) { 427 if (w == (Widget) scrnList[i]->parent) 428 return scrnList[i]; 429 } 430 } 431 Punt("ScrnFromWidget failed!"); 432 return NULL; 433} 434 435 436/* Figure out which buttons should and shouldn't be enabled in the given 437 * screen. This should be called whenever something major happens to the 438 * screen. 439 */ 440 441 442/*ARGSUSED*/ 443static void EnableCallback(Widget w, XtPointer data, XtPointer junk) 444{ 445 EnableProperButtons( (Scrn) data); 446} 447 448#define SetButton(buttonbox, name, value) \ 449 if (value) BBoxEnable(BBoxFindButtonNamed(buttonbox, name)); \ 450 else BBoxDisable(BBoxFindButtonNamed(buttonbox, name)); 451 452 453void EnableProperButtons(Scrn scrn) 454{ 455 int value, changed, reapable; 456 Button button; 457 458 if (scrn) { 459 switch (scrn->kind) { 460 case STtocAndView: 461 button = BBoxFindButtonNamed 462 (scrn->mainbuttons, MenuBoxButtons[XMH_TOC].button_name); 463 value = TocCanIncorporate(scrn->toc); 464 SendMenuEntryEnableMsg(button, "inc", value); 465 466 button = BBoxFindButtonNamed 467 (scrn->mainbuttons, MenuBoxButtons[XMH_SEQUENCE].button_name); 468 value = TocHasSequences(scrn->toc); 469 SendMenuEntryEnableMsg(button, "openSeq", value); 470 SendMenuEntryEnableMsg(button, "addToSeq", value); 471 SendMenuEntryEnableMsg(button, "removeFromSeq", value); 472 SendMenuEntryEnableMsg(button, "deleteSeq", value); 473 474 button = BBoxFindButtonNamed 475 (scrn->mainbuttons, MenuBoxButtons[XMH_VIEW].button_name); 476 value = (scrn->msg != NULL && !MsgGetEditable(scrn->msg)); 477 SendMenuEntryEnableMsg(button, "edit", value); 478 SendMenuEntryEnableMsg(button, "save", 479 scrn->msg != NULL && !value); 480 break; 481 case STview: 482 value = (scrn->msg != NULL && !MsgGetEditable(scrn->msg)); 483 SetButton(scrn->viewbuttons, "edit", value); 484 SetButton(scrn->viewbuttons, "save", scrn->msg != NULL && !value); 485 break; 486 case STcomp: 487 if (scrn->msg != NULL) { 488 changed = MsgChanged(scrn->msg); 489 reapable = MsgGetReapable(scrn->msg); 490 SetButton(scrn->viewbuttons, "send", changed || !reapable); 491 SetButton(scrn->viewbuttons, "save", changed || reapable); 492 SetButton(scrn->viewbuttons, "insert", 493 scrn->assocmsg != NULL ? True : False); 494 495 if (!changed) 496 MsgSetCallOnChange(scrn->msg, EnableCallback, 497 (XtPointer) scrn); 498 else 499 MsgSetCallOnChange(scrn->msg, (XtCallbackProc) NULL, 500 (XtPointer) NULL); 501 502 } else { 503 BBoxDisable( BBoxFindButtonNamed(scrn->viewbuttons, "send")); 504 BBoxDisable( BBoxFindButtonNamed(scrn->viewbuttons, "save")); 505 BBoxDisable( BBoxFindButtonNamed(scrn->viewbuttons, "insert")); 506 } 507 break; 508 default: 509 break; 510 } 511 } 512} 513