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