1 /*---------------------------------------------------------------------------- 2 -- 3 -- Module: xitInfoToc 4 -- 5 -- Project: xit - X Internal Toolkit 6 -- System: <> 7 -- Subsystem: <> 8 -- Function block: <> 9 -- 10 -- Description: 11 -- Table of contents for the information database. 12 -- 13 -- Filename: xitInfoToc.c 14 -- 15 -- Authors: Roger Larsson, Ulrika Bornetun 16 -- Creation date: 1992-10-17 17 -- 18 -- 19 -- (C) Copyright Ulrika Bornetun, Roger Larsson (1995) 20 -- All rights reserved 21 -- 22 -- Permission to use, copy, modify, and distribute this software and its 23 -- documentation for any purpose and without fee is hereby granted, 24 -- provided that the above copyright notice appear in all copies. Ulrika 25 -- Bornetun and Roger Larsson make no representations about the usability 26 -- of this software for any purpose. It is provided "as is" without express 27 -- or implied warranty. 28 ----------------------------------------------------------------------------*/ 29 30 /* SCCS module identifier. */ 31 static char SCCSID[] = "@(#) Module: xitInfoToc.c, Version: 1.1, Date: 95/02/18 15:10:39"; 32 33 34 /*---------------------------------------------------------------------------- 35 -- Include files 36 ----------------------------------------------------------------------------*/ 37 38 #include <limits.h> 39 #include <stdio.h> 40 #include <ctype.h> 41 42 #include <X11/Intrinsic.h> 43 #include <X11/Shell.h> 44 #include <X11/cursorfont.h> 45 46 #include <Xm/Xm.h> 47 #include <Xm/List.h> 48 #include <Xm/RowColumn.h> 49 #include <Xm/SeparatoG.h> 50 #include <Xm/Text.h> 51 52 #include "System.h" 53 #include "Message.h" 54 55 #include "msgTopic.h" 56 #include "xitInfoFile.h" 57 #include "xitTools.h" 58 #include "xitInfoToc.h" 59 60 61 /*---------------------------------------------------------------------------- 62 -- Macro definitions 63 ----------------------------------------------------------------------------*/ 64 65 /* Local widgets in the print window. */ 66 #define gotoRc dataLocalW[ 0 ] 67 #define sep1 dataLocalW[ 1 ] 68 #define tocLa dataLocalW[ 2 ] 69 #define tocLi dataLocalW[ 3 ] 70 71 /* Max number of matches we can handle. */ 72 #define MAX_MATCHES 500 73 74 75 /*---------------------------------------------------------------------------- 76 -- Type declarations 77 ----------------------------------------------------------------------------*/ 78 79 /* Record while searching entries. */ 80 typedef struct { 81 82 /* The selected section. */ 83 int selected_item; 84 85 /* File where the book is. */ 86 char *book_file; 87 88 /* The toc window. */ 89 Widget tocW; 90 91 /* Callback to inform our creator of specific actions. */ 92 void *user_data; 93 XIT_IT_ACTION_CB actionCB; 94 95 } TOC_REC, *TOC_REC_REF; 96 97 98 /*---------------------------------------------------------------------------- 99 -- Global definitions 100 ----------------------------------------------------------------------------*/ 101 102 /* Name of module. */ 103 static char *module_name = "xitInfoToc"; 104 105 /* Name of text domain. */ 106 static char *td = "Topic"; 107 108 109 /*---------------------------------------------------------------------------- 110 -- Function prototypes 111 ----------------------------------------------------------------------------*/ 112 113 static void 114 cancelCB( Widget widget, 115 TOC_REC_REF toc_ref, 116 XtPointer call_data ); 117 118 static Widget 119 createTocWindow( TOC_REC_REF toc_ref, 120 Widget parent ); 121 122 static void 123 destroyCB( Widget widget, 124 TOC_REC_REF toc_ref, 125 XtPointer call_data ); 126 127 static void 128 displaySelectedSection( TOC_REC_REF toc_ref ); 129 130 static void 131 displayToc( TOC_REC_REF toc_ref ); 132 133 static void 134 gotoCB( Widget widget, 135 TOC_REC_REF toc_ref, 136 XmRowColumnCallbackStruct *call_data ); 137 138 static void 139 setGotoButtons( TOC_REC_REF toc_ref, 140 Boolean sensitive ); 141 142 static void 143 tocLiCB( Widget widget, 144 TOC_REC_REF toc_ref, 145 XmListCallbackStruct *call_data ); 146 147 148 /*---------------------------------------------------------------------------- 149 -- Functions 150 ----------------------------------------------------------------------------*/ 151 152 XIT_IT_HANDLE xitItInitialize(Widget parent,XIT_IT_ACTION_CB actionCB,void * user_data)153 xitItInitialize( Widget parent, 154 XIT_IT_ACTION_CB actionCB, 155 void *user_data ) 156 { 157 158 /* Variables. */ 159 TOC_REC_REF toc_ref; 160 161 162 /* Code. */ 163 164 /* Create and initialize our private data. */ 165 toc_ref = SysNew( TOC_REC ); 166 if( toc_ref == NULL ) 167 return( NULL ); 168 169 toc_ref -> book_file = NULL; 170 toc_ref -> actionCB = actionCB; 171 toc_ref -> user_data = user_data; 172 173 174 /* Create the toc window. */ 175 toc_ref -> tocW = createTocWindow( toc_ref, parent ); 176 177 if( toc_ref -> tocW == NULL ) { 178 SysFree( toc_ref ); 179 180 return( NULL ); 181 } 182 183 184 return( (XIT_IT_HANDLE) toc_ref ); 185 186 } /* xitItInitialize */ 187 188 189 /*----------------------------------------------------------------------*/ 190 191 void xitItDestroy(XIT_IT_HANDLE toc_handle)192 xitItDestroy( XIT_IT_HANDLE toc_handle ) 193 { 194 195 /* Variables. */ 196 TOC_REC_REF toc_ref; 197 198 199 /* Code. */ 200 201 if( toc_handle == NULL ) 202 return; 203 204 /* Our private data. */ 205 toc_ref = (TOC_REC_REF) toc_handle; 206 207 208 /* Destroy the window. */ 209 XtDestroyWidget( toc_ref -> tocW ); 210 211 212 return; 213 214 } /* xitItDestroy */ 215 216 217 /*----------------------------------------------------------------------*/ 218 219 void xitItDisplayToc(XIT_IT_HANDLE toc_handle,char * book_file)220 xitItDisplayToc( XIT_IT_HANDLE toc_handle, 221 char *book_file ) 222 { 223 224 /* Variables. */ 225 Arg args[ 10 ]; 226 Cardinal n; 227 Widget mainW; 228 TOC_REC_REF toc_ref; 229 230 231 /* Code. */ 232 233 toc_ref = (TOC_REC_REF) toc_handle; 234 if( toc_ref == NULL ) 235 return; 236 237 mainW = XtNameToWidget( toc_ref -> tocW, "TocFdFo" ); 238 239 if( toc_ref -> book_file != NULL ) 240 SysFree( toc_ref -> book_file ); 241 toc_ref -> book_file = SysNewString( book_file ); 242 243 244 /* The Goto buttons are not valid. */ 245 setGotoButtons( toc_ref, False ); 246 247 248 /* Make sure the window is visible. */ 249 XtManageChild( toc_ref -> tocW ); 250 251 252 /* Don't let our children spoil our size. */ 253 n = 0; 254 XtSetArg( args[ n ], XmNallowShellResize, False ); n++; 255 XtSetValues( toc_ref -> tocW, args, n ); 256 257 258 /* Display the TOC. */ 259 displayToc( toc_ref ); 260 261 262 return; 263 264 } /* xitItDisplayToc */ 265 266 267 /*----------------------------------------------------------------------*/ 268 269 static Widget createTocWindow(TOC_REC_REF toc_ref,Widget parent)270 createTocWindow( TOC_REC_REF toc_ref, 271 Widget parent ) 272 { 273 274 /* Variables. */ 275 int index; 276 Arg args[ 10 ]; 277 Cardinal n; 278 Widget dataLocalW[ 4 ]; 279 Widget gotoBu[ 2 ]; 280 Widget tocFd; 281 Widget workFo; 282 283 static XIT_PUSH_STRUCT goto_def[] = { 284 { "GotoNextBu", "", "", True, NULL }, 285 { "GotoPrevBu", "", "", True, NULL }, 286 }; 287 288 static XIT_ACTION_AREA_ITEM action_buttons[] = { 289 { "", cancelCB, NULL }, 290 { NULL, NULL, NULL }, 291 { NULL, NULL, NULL }, 292 { NULL, NULL, NULL }, 293 }; 294 295 296 /* Code. */ 297 298 action_buttons[ 0 ].label = msgDGetText( td, MINF_CLOSE_BUTTON ); 299 action_buttons[ 0 ].data = toc_ref; 300 301 goto_def[ 0 ].title = msgDGetText( td, MINF_GOTO_NEXT_BUTTON ); 302 goto_def[ 1 ].title = msgDGetText( td, MINF_GOTO_PREV_BUTTON ); 303 304 305 /* Create a form dialog with buttons. */ 306 tocFd = xitCreateFormDialog( parent, "TocFd", 307 1, 0, 308 action_buttons, 309 XtNumber( action_buttons ) ); 310 311 XtAddCallback( tocFd, XmNdestroyCallback, 312 (XtCallbackProc) destroyCB, (XtPointer) toc_ref ); 313 314 n = 0; 315 XtSetArg( args[ n ], XmNtitle, msgDGetText( td, MINF_TOC_TITLE ) ); n++; 316 XtSetValues( XtParent( tocFd ), args, n ); 317 318 n = 0; 319 XtSetArg( args[ n ], XmNdeleteResponse, XmUNMAP ); n++; 320 XtSetValues( tocFd, args, n ); 321 322 /* Container for the contents of the window. */ 323 workFo = XtNameToWidget( tocFd, "TocFdFo" ); 324 325 326 /* Create result list. */ 327 tocLa = xitCreateLabel( workFo, "TocLa", 328 msgDGetText( td, MINF_TOC_LIST_LABEL ), -1 ); 329 330 n = 0; 331 XtSetArg( args[ n ], XmNlistSizePolicy, XmCONSTANT ); n++; 332 XtSetArg( args[ n ], XmNscrollBarDisplayPolicy, XmSTATIC ); n++; 333 XtSetArg( args[ n ], XmNselectionPolicy, XmSINGLE_SELECT ); n++; 334 XtSetArg( args[ n ], XmNlistMarginHeight, 5 ); n++; 335 XtSetArg( args[ n ], XmNlistMarginWidth, 5 ); n++; 336 tocLi = XmCreateScrolledList( workFo, "TocLi", args, n ); 337 338 XtAddCallback( tocLi, XmNsingleSelectionCallback, 339 (XtCallbackProc) tocLiCB, (XtPointer) toc_ref ); 340 XtAddCallback( tocLi, XmNdefaultActionCallback, 341 (XtCallbackProc) tocLiCB, (XtPointer) toc_ref ); 342 343 344 /* Create the action form. */ 345 n = 0; 346 XtSetArg( args[ n ], XmNspacing, 10 ); n++; 347 XtSetArg( args[ n ], XmNmarginHeight, 10 ); n++; 348 XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++; 349 gotoRc = XmCreateRowColumn( workFo, "GotoRc", args, n ); 350 351 XtAddCallback( gotoRc, XmNentryCallback, 352 (XtCallbackProc) gotoCB, (XtPointer) toc_ref ); 353 354 for( index = 0; index < XtNumber( gotoBu ); index++ ) { 355 gotoBu[ index ] = xitCreatePushButton( gotoRc, &goto_def[ index ] ); 356 357 XtAddCallback( gotoBu[ index ], XmNactivateCallback, 358 (XtCallbackProc) gotoCB, (XtPointer)(intptr_t)index ); 359 } 360 361 362 /* Create separators. */ 363 n = 0; 364 XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++; 365 sep1 = XmCreateSeparatorGadget( workFo, "Sep1", args, n ); 366 367 368 /* Place the various elements together. */ 369 xitAttachWidget( tocLa, 370 XmATTACH_FORM, NULL, XmATTACH_FORM, NULL, 371 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 372 xitAttachWidget( XtParent( tocLi ), 373 XmATTACH_WIDGET, tocLa, XmATTACH_FORM, NULL, 374 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 375 xitAttachWidget( sep1, 376 XmATTACH_WIDGET, XtParent( tocLi ), XmATTACH_FORM, NULL, 377 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 378 xitAttachWidget( gotoRc, 379 XmATTACH_WIDGET, sep1, XmATTACH_FORM, NULL, 380 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 381 382 383 /* Make sure there is enough space between the children. */ 384 n = 0; 385 XtSetArg( args[ n ], XmNleftOffset, 5 ); n++; 386 XtSetArg( args[ n ], XmNrightOffset, 5 ); n++; 387 XtSetValues( gotoRc, args, n ); 388 389 n = 0; 390 XtSetArg( args[ n ], XmNleftOffset, 5 ); n++; 391 XtSetArg( args[ n ], XmNrightOffset, 5 ); n++; 392 XtSetArg( args[ n ], XmNtopOffset, 5 ); n++; 393 XtSetArg( args[ n ], XmNbottomOffset, 5 ); n++; 394 XtSetValues( tocLa, args, n ); 395 XtSetValues( XtParent( tocLi ), args, n ); 396 XtSetValues( gotoRc, args, n ); 397 398 n = 0; 399 XtSetArg( args[ n ], XmNtopOffset, 5 ); n++; 400 XtSetArg( args[ n ], XmNbottomOffset, 5 ); n++; 401 XtSetValues( sep1, args, n ); 402 403 404 /* Manage all the children except the search form. */ 405 xitManageChildren( gotoBu, XtNumber( gotoBu ) ); 406 407 xitManageChildren( dataLocalW, XtNumber( dataLocalW ) ); 408 409 410 /* Set the size of the window. */ 411 xitSetSizeFormDialog( tocFd, True ); 412 413 414 /* Make the final attachments. */ 415 xitAttachWidget( gotoRc, 416 XmATTACH_NONE, NULL, XmATTACH_FORM, NULL, 417 XmATTACH_NONE, NULL, XmATTACH_FORM, NULL ); 418 xitAttachWidget( sep1, 419 XmATTACH_NONE, NULL, XmATTACH_FORM, NULL, 420 XmATTACH_FORM, NULL, XmATTACH_WIDGET, gotoRc ); 421 xitAttachWidget( XtParent( tocLi ), 422 XmATTACH_WIDGET, tocLa, XmATTACH_FORM, NULL, 423 XmATTACH_FORM, NULL, XmATTACH_WIDGET, sep1 ); 424 425 426 return( tocFd ); 427 428 } /* createTocWindow */ 429 430 431 /*----------------------------------------------------------------------*/ 432 433 static void displaySelectedSection(TOC_REC_REF toc_ref)434 displaySelectedSection( TOC_REC_REF toc_ref ) 435 { 436 437 /* Variables. */ 438 int item_count; 439 char chapter_id[ 50 ]; 440 char title[ 100 ]; 441 char *char_ref; 442 Arg args[ 10 ]; 443 Cardinal n; 444 Widget mainW; 445 Widget tocLiW; 446 XmString *items; 447 448 449 /* Code. */ 450 451 mainW = XtNameToWidget( toc_ref -> tocW, "TocFdFo" ); 452 tocLiW = XtNameToWidget( mainW, "TocLiSW.TocLi" ); 453 454 455 /* Fetch the selected item. */ 456 n = 0; 457 XtSetArg( args[ n ], XmNselectedItemCount, &item_count ); n++; 458 XtGetValues( tocLiW, args, n ); 459 460 461 /* There can only be ONE selection. */ 462 if( item_count != 1 ) 463 return; 464 465 466 /* Get the selected string. */ 467 n = 0; 468 XtSetArg( args[ n ], XmNselectedItems, &items ); n++; 469 XtGetValues( tocLiW, args, n ); 470 471 char_ref = xitStringGetString( *items, CS ); 472 473 474 /* Extract header and chapter id. */ 475 sscanf( char_ref, "%[^#]#%[^#]", title, chapter_id ); 476 477 SysFree( char_ref ); 478 479 480 /* Tell our parent what we have found. */ 481 if( toc_ref -> actionCB != NULL ) 482 (* toc_ref -> actionCB)( XIT_IT_REASON_NEW_SECTION, 483 toc_ref -> user_data, chapter_id, title ); 484 485 return; 486 487 } /* displaySelectedSection */ 488 489 490 /*----------------------------------------------------------------------*/ 491 492 static void displayToc(TOC_REC_REF toc_ref)493 displayToc( TOC_REC_REF toc_ref ) 494 { 495 496 /* Variables. */ 497 int index; 498 int matches_no; 499 char buffer[ 200 ]; 500 char format[ 20 ]; 501 char indent[ 200 ]; 502 char *char_ref; 503 Arg args[ 10 ]; 504 Cardinal n; 505 Widget mainW; 506 Widget tempW; 507 XmString list_items[ MAX_MATCHES ]; 508 XIT_IF_HANDLE info_handle; 509 XIT_IF_SECTION_REF matches[ MAX_MATCHES ]; 510 XIT_IF_STATUS status; 511 512 513 /* Code. */ 514 515 mainW = XtNameToWidget( toc_ref -> tocW, "TocFdFo" ); 516 517 518 /* The Goto buttons are not valid. */ 519 setGotoButtons( toc_ref, False ); 520 521 522 /* Initalize the info file. */ 523 info_handle = xitIfInitialize( toc_ref -> book_file ); 524 if( info_handle == NULL ) 525 return; 526 527 528 /* Do the toc. */ 529 { 530 531 Cursor wait_cursor; 532 Display *display = XtDisplay( toc_ref -> tocW ); 533 Window window = XtWindow( toc_ref -> tocW ); 534 535 /* This might take time. */ 536 wait_cursor = XCreateFontCursor( display, XC_watch ); 537 XDefineCursor( display, window, wait_cursor ); 538 539 XFlush( display ); 540 541 /* Toc. */ 542 status = xitIfGetToc( info_handle, 543 XtNumber( matches ), &matches[ 0 ], 544 &matches_no ); 545 546 /* Clean up. */ 547 xitIfDestroy( info_handle ); 548 549 XUndefineCursor( display, window ); 550 551 } /* block */ 552 553 554 /* Assign the found sections to the result list. */ 555 for( index = 0; index < matches_no; index++ ) { 556 557 /* Create the indent string. */ 558 sprintf( format, "%%-%d.%ds", 559 (matches[ index ] -> toc_level - 1) * 2, 560 (matches[ index ] -> toc_level - 1) * 2 ); 561 562 sprintf( indent, format, "" ); 563 564 /* Strip blanks. */ 565 char_ref = matches[ index ] -> title; 566 while( isspace( *char_ref ) ) 567 char_ref++; 568 569 sprintf( buffer, "%s%-80.80s#%s#%d#", 570 indent, 571 char_ref, 572 matches[ index ] -> chapter_id, 573 matches[ index ] -> toc_level ); 574 575 list_items[ index ] = XmStringCreate( buffer, CS ); 576 577 } /* loop */ 578 579 580 tempW = XtNameToWidget( mainW, "TocLiSW.TocLi" ); 581 582 n = 0; 583 XtSetArg( args[ n ], XmNitems, list_items ); n++; 584 XtSetArg( args[ n ], XmNitemCount, matches_no ); n++; 585 XtSetArg( args[ n ], XmNselectedItemCount, 0 ); n++; 586 XtSetValues( tempW, args, n ); 587 588 /* Free the match records. */ 589 for( index = 0; index < matches_no; index++ ) 590 XmStringFree( list_items[ index ] ); 591 592 xitIfFreeMatchInfo( &matches[ 0 ], matches_no ); 593 594 595 return; 596 597 } /* displayToc */ 598 599 600 /*----------------------------------------------------------------------*/ 601 602 static void setGotoButtons(TOC_REC_REF toc_ref,Boolean sensitive)603 setGotoButtons( TOC_REC_REF toc_ref, 604 Boolean sensitive ) 605 { 606 607 /* Variables. */ 608 Widget mainW; 609 Widget tempW; 610 611 612 /* Code. */ 613 614 mainW = XtNameToWidget( toc_ref -> tocW, "TocFdFo" ); 615 tempW = XtNameToWidget( mainW, "GotoRc" ); 616 617 XtSetSensitive( tempW, sensitive ); 618 619 620 return; 621 622 } /* setGotoButtons */ 623 624 625 /*----------------------------------------------------------------------*/ 626 627 static void cancelCB(Widget widget,TOC_REC_REF toc_ref,XtPointer call_data)628 cancelCB( Widget widget, 629 TOC_REC_REF toc_ref, 630 XtPointer call_data ) 631 { 632 633 /* Code. */ 634 635 /* Do we have a user action callback registered? */ 636 if( toc_ref -> actionCB != NULL ) 637 (* toc_ref -> actionCB)( XIT_IT_REASON_POPDOWN, 638 toc_ref -> user_data, NULL, NULL ); 639 640 641 XtUnmanageChild( toc_ref -> tocW ); 642 643 644 return; 645 646 } /* cancelCB */ 647 648 649 /*----------------------------------------------------------------------*/ 650 651 static void destroyCB(Widget widget,TOC_REC_REF toc_ref,XtPointer call_data)652 destroyCB( Widget widget, 653 TOC_REC_REF toc_ref, 654 XtPointer call_data ) 655 { 656 657 /* Code. */ 658 659 /* Do we have a user action callback registered? */ 660 if( toc_ref -> actionCB != NULL ) 661 (* toc_ref -> actionCB)( XIT_IT_REASON_DESTROY, 662 toc_ref -> user_data, NULL, NULL ); 663 664 /* Free allocated data. */ 665 if( toc_ref -> book_file != NULL ) 666 SysFree( toc_ref -> book_file ); 667 668 SysFree( toc_ref ); 669 670 671 return; 672 673 } /* destroyCB */ 674 675 676 /*----------------------------------------------------------------------*/ 677 678 static void gotoCB(Widget widget,TOC_REC_REF toc_ref,XmRowColumnCallbackStruct * call_data)679 gotoCB( Widget widget, 680 TOC_REC_REF toc_ref, 681 XmRowColumnCallbackStruct *call_data ) 682 { 683 684 /* Variables. */ 685 int item_count; 686 Arg args[ 3 ]; 687 Cardinal n; 688 Widget mainW; 689 Widget tocLiW; 690 691 692 /* Code. */ 693 694 mainW = XtNameToWidget( toc_ref -> tocW, "TocFdFo" ); 695 696 /* Elements in the list. */ 697 tocLiW = XtNameToWidget( mainW, "TocLiSW.TocLi" ); 698 699 n = 0; 700 XtSetArg( args[ n ], XmNitemCount, &item_count ); n++; 701 XtGetValues( tocLiW, args, n ); 702 703 704 /* Select what to do. */ 705 switch( (intptr_t) call_data -> data ) { 706 707 /* Next? */ 708 case 0: 709 if( toc_ref -> selected_item >= item_count ) 710 return; 711 712 /* Make the selected position the top position. */ 713 XmListSetPos( tocLiW, toc_ref -> selected_item + 1 ); 714 715 /* Select the next position in the list. */ 716 XmListSelectPos( tocLiW, toc_ref -> selected_item + 1, True ); 717 break; 718 719 720 /* Previous? */ 721 case 1: 722 if( toc_ref -> selected_item <= 1 ) 723 return; 724 725 /* Make the selected position the top position. */ 726 XmListSetPos( tocLiW, toc_ref -> selected_item - 1 ); 727 728 /* Select the next position in the list. */ 729 XmListSelectPos( tocLiW, toc_ref -> selected_item - 1, True ); 730 break; 731 732 } /* switch */ 733 734 735 return; 736 737 } /* gotoCB */ 738 739 740 /*----------------------------------------------------------------------*/ 741 742 static void tocLiCB(Widget widget,TOC_REC_REF toc_ref,XmListCallbackStruct * call_data)743 tocLiCB( Widget widget, 744 TOC_REC_REF toc_ref, 745 XmListCallbackStruct *call_data ) 746 { 747 748 /* Code. */ 749 750 /* Save the select section. */ 751 toc_ref -> selected_item = call_data -> item_position; 752 753 /* We can use the goto buttons. */ 754 setGotoButtons( toc_ref, True ); 755 756 757 /* Display the info text for this section. */ 758 displaySelectedSection( toc_ref ); 759 760 761 return; 762 763 } /* tocLiCB */ 764