home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / mark.c < prev    next >
C/C++ Source or Header  |  1992-06-25  |  23KB  |  1,059 lines

  1. /*
  2.  * Copyright 1989 Dirk Grunwald
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without fee,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of Dirk Grunwald or M.I.T.
  9.  * not be used in advertising or publicity pertaining to distribution of
  10.  * the software without specific, written prior permission.  Dirk
  11.  * Grunwald and M.I.T. makes no representations about the suitability of
  12.  * this software for any purpose.  It is provided "as is" without express
  13.  * or implied warranty.
  14.  * 
  15.  * DIRK GRUNWALD AND M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  16.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17.  * FITNESS, IN NO EVENT SHALL M.I.T.  BE LIABLE FOR ANY SPECIAL, INDIRECT
  18.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  19.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  20.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  21.  * OR PERFORMANCE OF THIS SOFTWARE.
  22.  * 
  23.  * Author:
  24.  *     Dr. Dirk Grunwald
  25.  *     Dept. of Computer Science
  26.  *     Campus Box 430
  27.  *     Univ. of Colorado, Boulder
  28.  *     Boulder, CO 80309
  29.  * 
  30.  *     grunwald@colorado.edu
  31.  *     
  32.  */ 
  33.  
  34. /*
  35.  *    Handle printing of marked pages
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include <X11/Xos.h>  
  40. #include <X11/IntrinsicP.h>
  41. #include <X11/StringDefs.h>
  42.  
  43. #include <X11/cursorfont.h>
  44.  
  45. #include <assert.h>
  46. #include <sys/wait.h>
  47.  
  48. #include "dvi-simple.h"
  49. #include "xtex.h"
  50. #include "mark.h"
  51. #include "page.h"
  52. #include "widgets.h"
  53.  
  54. typedef struct MarkStackStruct MarkStack;
  55.  
  56. struct MarkStackStruct {
  57.   Bool *mark;
  58.   short pages;
  59.   MarkStack *next;
  60. };
  61.  
  62. MarkStack *CurrentMarks = 0;
  63.  
  64.  
  65. /*
  66.  *    Widgets for menu of marked pages
  67.  */
  68. typedef struct {
  69.   Boolean valid;
  70.   int *listOffset;
  71.   String *listItems;
  72.   String listStorage;
  73.   int stringSize;
  74.   int stringLast;
  75. } MarkMenu;
  76.  
  77. MarkMenu TheMarkMenu = {0,0,0,0,0};
  78.  
  79. /* update the displayed marks & cause the menu to be refreshed */
  80.  
  81. static void
  82.   TeXMarkMenuRefresh()
  83. {
  84.   int page;
  85.   
  86.   if ( TheMarkMenu.valid ) {
  87.     
  88.     for ( page = 0; page < DviTotalPages; page ++ ) {
  89.       char *item = TheMarkMenu.listItems[ page ];
  90.       
  91.       *(item) = (CurrentMarks -> mark [ page ]) ? '*' : ' ';
  92.     }
  93.     
  94.     XawListChange( markMenuList, TheMarkMenu.listItems, -1, -1, True );
  95.   }
  96. }
  97.  
  98. void
  99.   TeXMarkMenuSelect(w, client_data, call_data)
  100. Widget w;
  101. caddr_t client_data;
  102. caddr_t call_data;
  103. {
  104.   XawListReturnStruct *item = (XawListReturnStruct *) call_data;
  105.   
  106.   if ( item != 0 ) {
  107.     int page = item -> list_index;
  108.     TeXMark( markToggle, page);
  109.   }
  110. }
  111.  
  112. void BuildMarkMenuPopUp()
  113. {
  114.   if ( markMenuList && DviTotalPages > 0 ) {
  115.     int mallocSize;
  116.     int page;
  117.     
  118.     /* Build the list - one item for each page, one null terminator
  119.      * We don't know what the various count0 fields enclose, so we
  120.      * make a guess for the string space needed and realloc it as
  121.      * needed.
  122.      */
  123.     if ( TheMarkMenu.stringSize != 0 ) {
  124.       XtFree( TheMarkMenu.listStorage );
  125.       TheMarkMenu.listStorage = 0;
  126.     }
  127.     
  128.     TheMarkMenu.stringSize = DviTotalPages * 6;
  129.     TheMarkMenu.stringLast = TheMarkMenu.stringSize;
  130.     TheMarkMenu.listStorage = XtMalloc( TheMarkMenu.stringSize );
  131.     
  132.     mallocSize = ( sizeof(String) * (DviTotalPages + 2) );
  133.     TheMarkMenu.listItems = (String *) XtMalloc( mallocSize );
  134.     bzero(TheMarkMenu.listItems, mallocSize);
  135.     
  136.     mallocSize = ( sizeof(int) * (DviTotalPages + 2) );
  137.     TheMarkMenu.listOffset = (int *) XtMalloc( mallocSize );
  138.     bzero(TheMarkMenu.listItems, mallocSize);
  139.     
  140.     for (page = 0; page < DviTotalPages; page++) {
  141.       char thisPage[128];
  142.       int len;
  143.       
  144.       sprintf(thisPage," %d", DviCount[0][page]);
  145.       
  146.       len = strlen(thisPage) + 1;
  147.       if ( (TheMarkMenu.stringSize - TheMarkMenu.stringLast) <= len ) {
  148.     TheMarkMenu.listStorage
  149.       = XtRealloc( TheMarkMenu.listStorage, TheMarkMenu.stringSize * 2 );
  150.       }
  151.       
  152.       TheMarkMenu.listOffset[page] = TheMarkMenu.stringLast;
  153.       bcopy(thisPage,
  154.         TheMarkMenu.listStorage + TheMarkMenu.listOffset[page], len);
  155.       TheMarkMenu.stringLast += len;
  156.     }
  157.     
  158.     /*
  159.      * Convert offsets to actual addresses
  160.      */
  161.     for (page = 0; page < DviTotalPages; page++) {
  162.       TheMarkMenu.listItems[ page ] =
  163.     TheMarkMenu.listStorage + TheMarkMenu.listOffset[ page ];
  164.     }
  165.     
  166.     TheMarkMenu.valid = True;
  167.     
  168.     TeXMarkMenuRefresh();
  169.     XtMapWidget(markMenuViewPort);
  170.     TeXMarkMenuRefresh();
  171.   }
  172. }
  173.  
  174.  
  175. void
  176.   TeXMarkPush()
  177. {
  178.   MarkStack *stk = (MarkStack *) malloc( sizeof(MarkStack) );
  179.   int len = DviTotalPages * sizeof(Bool);
  180.   stk -> mark = (Bool *) malloc( len );
  181.   
  182.   assert(stk && stk -> mark);
  183.   
  184.   if ( (int) False == 0 ) {
  185.     bzero(stk -> mark, len);
  186.   }
  187.   else {
  188.     int page;
  189.     for ( page = 0; page< DviTotalPages; page++ ) {
  190.       CurrentMarks -> mark [ page ] = False;
  191.     }
  192.   }
  193.   stk -> next = CurrentMarks;
  194.   CurrentMarks = stk;
  195.   
  196.   TeXMarkMenuRefresh();
  197. }
  198.  
  199. void
  200.   TeXMarkPop()
  201. {
  202.   if ( CurrentMarks != 0 ) {
  203.     MarkStack *stk = CurrentMarks;
  204.     CurrentMarks = stk -> next;
  205.     free( stk -> mark );
  206.     free( stk );
  207.     
  208.     TeXMarkMenuRefresh();
  209.     
  210.   }
  211. }
  212.  
  213. static void
  214.   insureMarks()
  215. {
  216.   if ( CurrentMarks == 0 ) TeXMarkPush();
  217. }
  218.  
  219. void
  220.   TeXMarkNewFile()
  221. {
  222.   int page;
  223.   
  224.   TheMarkMenu.valid = False;
  225.   
  226.   while (CurrentMarks != 0) {
  227.     TeXMarkPop();
  228.   }
  229.   
  230.   if ( DviFile != 0 ) {
  231.     TeXMarkPush();
  232.     BuildMarkMenuPopUp();
  233.   }
  234. }
  235.  
  236. /*
  237.  *    Simply return the state
  238.  */
  239. Bool
  240.   TeXMarkState(page)
  241. int page;
  242. {
  243.   if ( page >=0 && page < DviTotalPages ) {
  244.     insureMarks();
  245.     return( CurrentMarks -> mark[  page  ] );
  246.   }
  247.   else {
  248.     return( 0 );
  249.   }
  250. }
  251.  
  252. Bool
  253.   TeXMark( md, page )
  254. MarkDirective md;
  255. int page;
  256. {
  257.   if ( page >=0 && page < DviTotalPages ) {
  258.     insureMarks();
  259.     
  260.     switch ( md ) {
  261.     case markSet:
  262.       CurrentMarks -> mark[  page  ]  = True;
  263.       break;
  264.     case markClear:
  265.       CurrentMarks -> mark[  page  ]  = False;
  266.       break;
  267.     case markToggle:
  268.       CurrentMarks -> mark[  page  ]  = ~ CurrentMarks -> mark[ page ];
  269.       break;
  270.     default:
  271.       error(0,0,"Unknown mark directive in TeXMark: %d\n", (int) md);
  272.     }
  273.     TeXMarkMenuRefresh();
  274.     return( CurrentMarks -> mark[  page  ] );
  275.   }
  276.   else {
  277.     return( False );
  278.   }
  279. }
  280.  
  281. void
  282.   TeXMarkAll( md )
  283. MarkDirective md;
  284. {
  285.   int page;
  286.   
  287.   insureMarks();
  288.   
  289.   switch ( md ) {
  290.     
  291.   case markSet:
  292.     for (page = 0; page < DviTotalPages; page++) {
  293.       CurrentMarks -> mark[  page  ] = True;
  294.     }
  295.     break;
  296.     
  297.   case markClear:
  298.     for (page = 0; page < DviTotalPages; page++) {
  299.       CurrentMarks -> mark[  page  ] = False;
  300.     }
  301.     break;
  302.     
  303.   case markToggle:
  304.     for (page = 0; page < DviTotalPages; page++) {
  305.       CurrentMarks -> mark[  page  ] = ~CurrentMarks -> mark[ page ];
  306.     }
  307.     break;
  308.     
  309.   default:
  310.     error(0,0,"Unknown mark directive in TeXMark: %d\n", (int) md);
  311.   }
  312.   
  313.   TeXMarkMenuRefresh();
  314. }
  315.  
  316. /*
  317.  *    Do a system call, while handling X events. This is used to print
  318.  *    marked pages while still doing other X things.
  319.  */
  320.  
  321.  
  322.  
  323. /* 
  324.  * create the normal and busy cursors
  325.  */
  326.  
  327. /* number of busy calls outstanding, change the cursor back when this is zero */
  328. static int nbusy=0;
  329.  
  330. void
  331. busyCursor()
  332. {
  333.  
  334.     Widget w;
  335.     int i;
  336.  
  337.     static Cursor busyCursor = (Cursor) 0;
  338.  
  339.     nbusy++;
  340.  
  341.     if( nbusy > 1 ) return;
  342.  
  343.     w = TopLevelWidget;
  344.  
  345.     /* define the busy cursor */
  346.     if (busyCursor == (Cursor) 0) {
  347.     busyCursor = XCreateFontCursor(XtDisplay(w), XC_watch);
  348.     }
  349.  
  350.     for( i = 0; i <TeXPages; i++ ){
  351.       if ( IS_VALID_PAGE(TheTeXPages[i])) {
  352.     Widget x = TheTeXPages[i]->dviPageBox;
  353.     if ( XtIsRealized(x) ) {
  354.       XDefineCursor(XtDisplay(x), XtWindow(x), busyCursor);
  355.     }
  356.       }
  357.     }
  358.  
  359.     XDefineCursor(XtDisplay(w), XtWindow(w), busyCursor);
  360.     XFlush(XtDisplay(w));
  361.     
  362.     return;
  363. }
  364.  
  365.  
  366. void
  367. unbusyCursor()
  368. {
  369.     Widget w;
  370.     int i;
  371.  
  372.     static Cursor unBusyCursor = (Cursor) 0;
  373.  
  374.     nbusy--;
  375.  
  376.     if( nbusy >0 ) return;
  377.  
  378.     w = TopLevelWidget;
  379.  
  380.     if (unBusyCursor == (Cursor) 0) {
  381.     unBusyCursor = XCreateFontCursor(XtDisplay(w), XC_left_ptr);
  382.     }
  383.  
  384.     for( i = 0; i <TeXPages; i++ ){
  385.       if ( IS_VALID_PAGE(TheTeXPages[i])) {
  386.     Widget x = TheTeXPages[i]->dviPageBox;
  387.     if ( XtIsRealized(x) ) {
  388.       XDefineCursor(XtDisplay(x), XtWindow(x), unBusyCursor);
  389.     }
  390.      }
  391.     }
  392.  
  393.     XDefineCursor(XtDisplay(w), XtWindow(w), unBusyCursor);
  394.     XFlush(XtDisplay(w));
  395.     
  396.     return;
  397. }
  398.  
  399. static Boolean TeXSystemChildDied;
  400. static int TeXSystemChild;
  401.  
  402. static void
  403.   TeXSystemCallRead( f )
  404. caddr_t f;
  405. {
  406.   int fd = (int) f;
  407.   char buffer[1024];
  408.   int bytes;
  409.   int pid;
  410.   union wait status;
  411.   
  412.   /* call ye not upon the dead */
  413.   
  414.   int rfds = 1 << fd;
  415.   static struct timeval tv = {0, 0};
  416.   
  417.   do {
  418.       if ( select(fd+1, &rfds, NULL, NULL, &tv) > 0 ) {
  419.         bytes = read(fd, buffer, sizeof(buffer)-1);
  420.         if ( bytes > 0 ) {
  421.           buffer[bytes] = 0;
  422.           DialogMessage(buffer,0);
  423.         }
  424.       }
  425.       else
  426.     bytes = 0;
  427.   } while (bytes > 0);
  428. }
  429.  
  430. void
  431.   TeXSystemCall(str)
  432. char *str;
  433. {
  434.   int fildes[2];
  435.   
  436.   if ( pipe(fildes) < 0 ) {
  437.     perror("pipe");
  438.     exit(1);
  439.   }
  440.  
  441.   busyCursor();
  442.  
  443.   if (TeXSystemChild = fork()) {
  444.     /* ye olde parent, who will read from fildes[0] */
  445.     
  446.     int filemask = (1 << fildes[0]);
  447.     
  448.     XtAppContext context = 
  449.       XtWidgetToApplicationContext( TopLevelWidget );
  450.     
  451.     XtInputId inputId;
  452.     
  453.     TeXSystemChildDied = False;
  454.     inputId = XtAppAddInput(context, fildes[0],
  455.                 (XtPointer) XtInputReadMask,
  456.                 TeXSystemCallRead,
  457.                 (caddr_t) fildes[0]);
  458.     
  459.     while ( ! TeXSystemChildDied ) {
  460.       
  461.       int pid;
  462.       union wait status;
  463.       
  464.       /*
  465.        * This is not desirable, since it causes the X application to
  466.        * spin while the child does its stuff, but the X application
  467.        * appears to be stuck on some event if I do the more normal
  468.        * AppNextEvent/DispatchEvent loop - as if we're blocked waiting
  469.        * for something to happen.
  470.        *
  471.        *
  472.        * The XtAppNextEvent appears to work for X11R5 intrinsics and later
  473.        * and the previous method gives lots of "copy buffer" errors in text
  474.        * widget.
  475.        */
  476.       
  477.       XEvent event;
  478. #if XtSpecificationRelease < 5
  479.       if ( XtAppPeekEvent(context, &event) ) {
  480.     XtDispatchEvent(&event);
  481.       }
  482. #else
  483.       XtAppNextEvent(context, &event);
  484.       XtDispatchEvent(&event);
  485. #endif
  486.       pid = wait3(&status, WNOHANG, 0);
  487.       if ( pid == TeXSystemChild ) {
  488.     TeXSystemChildDied = True;
  489.       }
  490.  
  491.       TeXSystemCallRead(fildes[0]);    /* catch any pending output */
  492.     }
  493.     
  494.     close(fildes[0]);
  495.     XtRemoveInput( inputId );
  496.   }
  497.   else {
  498.     /* ye newe child, who will write to fildes[1] */
  499.     dup2(fildes[1],1);
  500.     dup2(fildes[1],2);
  501.     fprintf(stderr,"[ exec ] %s\n", str);
  502.     system( str );
  503.     
  504.     /* terminate the line */
  505.     fclose(stderr);
  506.     fclose(stdout);
  507.     close(fildes[1]);
  508.     close(1);
  509.     close(2);
  510.     exit(0);
  511.   }
  512.   unbusyCursor();
  513. }
  514.  
  515. /* Print some pages. The mark selection dictates what pages get printed */
  516. void
  517.   TeXMarkPrintUsing(inWidget, pd, dvips)
  518. Widget inWidget;
  519. char *dvips;
  520. PrintDirective pd;
  521. {
  522.   int cnt;
  523.   int i;
  524.   char buf[20];
  525.   
  526.   char printCommand[1024];
  527.   char *pc;
  528.   char *dv;
  529.   char tmpFileName[1024];
  530.   
  531.   char *fileToPrint;
  532.   int deletePrintedFile;
  533.   
  534.   int sawFile;
  535.   
  536.   if ( pd == printAll ) {
  537.     fileToPrint = DVIFileName;
  538.     deletePrintedFile = 0;
  539.   }
  540.   else {
  541.     
  542.     int dviSelectBufferLength = 2048;
  543.     char dviSelectBuffer[ 2048 ];
  544.     
  545.     /* create a temporary file name in a more portable way */
  546.     sprintf(tmpFileName,"/tmp/xtex%u.dvi", getpid());
  547.     
  548.     fileToPrint = tmpFileName;
  549.     deletePrintedFile = 1;
  550.     
  551.     /* Now run dviselect to extract the pages */
  552.     
  553.     sprintf(dviSelectBuffer, "dviselect -i \"%s\" -o \"%s\" ",
  554.         DVIFileName, fileToPrint);
  555.     
  556.     cnt = 0;
  557.     for (i = 0; i < DviTotalPages; i++) {
  558.       if (   (CurrentMarks -> mark[  i  ] && pd == printMarked )
  559.       || (!CurrentMarks -> mark[  i  ] && pd == printUnmarked )) {
  560.     sprintf(buf, " =%d", i + 1);
  561.     strcat(dviSelectBuffer, buf);
  562.     cnt++;
  563.       }
  564.     }
  565.     
  566.     if (cnt != 0) {
  567.       TeXSystemCall(dviSelectBuffer);
  568.     }
  569.     else {
  570.       unlink( fileToPrint );
  571.       return;
  572.     }
  573.   }
  574.   
  575.   /* Now print pages */
  576.   
  577.   sawFile = 0;
  578.   pc = printCommand;
  579.   dv = dvips;
  580.  
  581.   while (dv && *dv) { 
  582.     switch ( *dv ) {
  583.       /*
  584.        * Look for special %f marker
  585.        */
  586.  
  587.     case '%':
  588.       dv++;
  589.       if ( *dv == 'f' ) {
  590.     char *fn = fileToPrint;
  591.  
  592.     dv++; /* skip over 'f' */
  593.  
  594.     while (fn && *fn) {
  595.       *pc = *fn;
  596.       pc++; fn++;
  597.     }
  598.     sawFile = 1;
  599.       } else {
  600.     *pc = '%'; pc++;
  601.     *pc = *dv; pc++; dv++;
  602.       }
  603.       break;
  604.  
  605.     default:
  606.       *pc = *dv; pc++; dv++;
  607.       break;
  608.     }
  609.   }
  610.  
  611.   *pc = 0;
  612.  
  613.   if (! sawFile ) {
  614.     strcat(printCommand, " ");
  615.     strcat(printCommand, fileToPrint);
  616.   }
  617.   
  618.   pc = TeXConfirmString(inWidget, "Print using command:", printCommand);
  619.   
  620.   if ( pc ) { 
  621.     TeXSystemCall(pc);
  622.   }
  623.   
  624.   if ( deletePrintedFile ) {
  625.     unlink( fileToPrint );
  626.   }
  627. }
  628.  
  629. void
  630.   TeXMarkPrint(inWidget, pd)
  631. Widget inWidget;
  632. PrintDirective pd;
  633. {
  634.   char *dvips = xtexResources.printProgram;
  635.   
  636.   if ( dvips == 0 ) {
  637.     extern char *getenv();
  638.     dvips = getenv("DVIPRINT");
  639.     if (dvips == NULL) {
  640.       dvips = "lpr -d ";    /* a good guess on BSD systems */
  641.     }
  642.     error(0,0, "Using default ``%s'' to print\n", dvips);
  643.   }
  644.   
  645.   TeXMarkPrintUsing( inWidget, pd, dvips );
  646. }
  647.  
  648. /**********************************************************************/
  649. /**    Confirm String **/
  650.  
  651. #define MAX_STRING 1024
  652. static char TeXString[MAX_STRING];
  653.  
  654. static Widget PopUpWidget;
  655. static Widget StringWidget;
  656. static Boolean ConfirmOrCancel;
  657. static Boolean ConfirmP;
  658.  
  659. static void
  660.   confirmString()
  661. {
  662.   ConfirmOrCancel = True;
  663.   ConfirmP = True;
  664.   if ( PopUpWidget && XtIsRealized(PopUpWidget)) {
  665.     XtPopdown( PopUpWidget );
  666.   }
  667. }
  668.  
  669. static void
  670.   cancelString()
  671. {
  672.   ConfirmOrCancel = True;
  673.   ConfirmP = False;
  674.   if ( PopUpWidget && XtIsRealized(PopUpWidget)) {
  675.     XtPopdown( PopUpWidget );
  676.   }
  677. }
  678.  
  679. char *
  680.   TeXConfirmString(inWidget, title, defaultString)
  681. Widget inWidget;
  682. char *title;
  683. char *defaultString;
  684. {
  685.   XawTextBlock tblk;
  686.   int len = (defaultString == 0) ? 0 : strlen(defaultString);
  687.   char *string;
  688.   Arg argList[20];
  689.   int args = 0;
  690.   Window root, child;
  691.   static Boolean inited = False;
  692.   int root_x, root_y, child_x, child_y;
  693.   unsigned int buttons;
  694.   static Widget titleWidget, formWidget, cancelWidget, confirmWidget;
  695.   
  696.   Dimension width;
  697.   Dimension height;
  698.   Dimension confirmHeight;
  699.   Dimension confirmWidth;
  700.   Dimension titleHeight;
  701.   
  702.   static XtCallbackRec confirmCB[] = {
  703.     {(XtCallbackProc) confirmString, NULL},
  704.     {(XtCallbackProc) NULL, NULL}};
  705.   
  706.   static XtCallbackRec cancelCB[] = {
  707.     {(XtCallbackProc) cancelString, NULL},
  708.     {(XtCallbackProc) NULL, NULL}};
  709.   
  710.   XtAppContext context = 
  711.     XtWidgetToApplicationContext( inWidget );
  712.   
  713.   if ( ! inited ) {
  714.     /*
  715.      * The confirmation box will be a pop-up widget.
  716.      */
  717.     PopUpWidget =
  718.       XtCreatePopupShell("stringQuery",
  719.              POPUP_WINDOW_TYPE, TopLevelWidget,
  720.              NULL, 0);
  721.     
  722.     /*
  723.      * Make a form to put the buttons in.
  724.      */
  725.     formWidget = XtCreateWidget("form", formWidgetClass,
  726.                 PopUpWidget, NULL, 0);
  727.     
  728.     args = 0;
  729.     XtSetArg(argList[args], XtNlabel, title); args++;
  730.     titleWidget = XtCreateManagedWidget("title",labelWidgetClass,
  731.                     formWidget, argList, args);
  732.     
  733.     /*
  734.      * Confirmation & cancellation buttons.
  735.      */
  736.     args = 0;
  737.     XtSetArg(argList[args], XtNcallback, confirmCB); args++;
  738.     confirmWidget = XtCreateManagedWidget("confirm", commandWidgetClass,
  739.                       formWidget, argList, args);
  740.     
  741.     args = 0;
  742.     XtSetArg(argList[args], XtNcallback, cancelCB); args++;
  743.     cancelWidget = XtCreateManagedWidget("cancel", commandWidgetClass,
  744.                      formWidget, argList, args);
  745.     
  746.     args = 0;
  747.     XtSetArg(argList[args], XtNeditType,XawtextEdit); args++;
  748.     XtSetArg(argList[args], XtRAsciiType, XawAsciiString); args++;
  749.     XtSetArg(argList[args], XtNstring, TeXString); args++;
  750.     XtSetArg(argList[args], XtNlength, MAX_STRING); args++;
  751.     StringWidget = XtCreateManagedWidget("string",
  752.                      asciiTextWidgetClass,
  753.                      formWidget, argList, args);
  754.     /*
  755.      * Let the shell widget know we're here.
  756.      */
  757.     XtManageChild(formWidget);
  758.     XtRealizeWidget(PopUpWidget);
  759.     inited = True;
  760.   }
  761.   
  762.   /*
  763.    * Find out where the mouse is, so we can put the confirmation
  764.    * box right there.
  765.    */
  766.   XQueryPointer(XtDisplay(inWidget),
  767.         XtWindow(inWidget), &root, &child,
  768.         &root_x, &root_y, &child_x, &child_y, &buttons);
  769.   
  770.   /* get the box size */
  771.   
  772.   args = 0;
  773.   XtSetArg(argList[args], XtNwidth, &width); args++;
  774.   XtSetArg(argList[args], XtNheight, &height); args++;
  775.   XtGetValues(PopUpWidget,argList,args);
  776.   
  777.   args = 0;
  778.   XtSetArg(argList[args], XtNwidth, &confirmWidth); args++;
  779.   XtSetArg(argList[args], XtNheight, &confirmHeight); args++;
  780.   XtGetValues(confirmWidget,argList,args);
  781.   
  782.   args = 0;
  783.   XtSetArg(argList[args], XtNheight, &titleHeight); args++;
  784.   XtGetValues(titleWidget,argList,args);
  785.   
  786.   /* reset the confirmation box position -- try to get it lined
  787.      up on the confirm widget */
  788.   
  789.   root_x -= (confirmWidth/2);
  790.   root_y -= (titleHeight + confirmHeight);
  791.   
  792.   args = 0;
  793.   XtSetArg(argList[args], XtNx, root_x); args++;
  794.   XtSetArg(argList[args], XtNy, root_y); args++;
  795.   XtSetValues(PopUpWidget,argList,args);
  796.   
  797.   /* set the default string */
  798.   
  799.   if ( len > 0 ) {
  800.     Arg argList[20];
  801.     Cardinal args;
  802.     char *currentString;
  803.     XawTextPosition start;
  804.     XawTextPosition end;
  805.     
  806.     args = 0;
  807.     XtSetArg(argList[args], XtNstring, ¤tString); args++;
  808.     XtGetValues(StringWidget, argList, args);
  809.     start = 0; end = strlen(currentString);
  810.     
  811.     tblk.firstPos = 0;
  812.     tblk.length = len;
  813.     tblk.ptr = defaultString;
  814.     tblk.format = FMT8BIT;
  815.     
  816.     XawTextDisableRedisplay(StringWidget);
  817.     XawTextReplace( StringWidget, start, end, &tblk );
  818.     XawTextEnableRedisplay(StringWidget);
  819.   }
  820.   
  821.   /* pop it up */
  822.   ConfirmP = False;
  823.   ConfirmOrCancel = False;
  824.   XtPopup(PopUpWidget, XtGrabExclusive);
  825.   
  826.   while ( ! ConfirmOrCancel ) {
  827.     XEvent event;
  828.     XtAppNextEvent(context, &event);
  829.     XtDispatchEvent(&event);
  830.   }
  831.   
  832.   if ( ConfirmP ) {
  833.     args = 0;
  834.     XtSetArg(argList[args], XtNstring, &string); args++;
  835.     XtGetValues(StringWidget, argList, args);
  836.   }
  837.   else {
  838.     string = 0;
  839.   }
  840.   return(string);
  841. }
  842.  
  843.  
  844. /*********************************************************/
  845. /*    Action Interface                 */
  846. /*********************************************************/
  847.  
  848.  
  849. static void actionPrintUsing(w, event, params, num_params)
  850.      Widget w;
  851.      XEvent *event;
  852.      String *params;
  853.      Cardinal *num_params;
  854. {
  855.   char *directive = (char *) params[0];
  856.   PrintDirective pd;
  857.   
  858.   if (*num_params < 1 ) {
  859.     return;
  860.   }
  861.   
  862.   if ( strcmp(directive,"all") == 0 ) {
  863.     pd = printAll;
  864.   }
  865.   else if (strcmp(directive,"set") == 0) {
  866.     pd = printMarked;
  867.   }
  868.   else if (strcmp(directive,"clear") == 0) {
  869.     pd = printUnmarked;
  870.   }
  871.   else {
  872.     return;
  873.   }
  874.   
  875.   if (*num_params == 1) {
  876.     TeXMarkPrint(w, pd);
  877.   }
  878.   else if (*num_params >= 2) {
  879.     int totalLen;
  880.     int i;
  881.     char *printCommand;
  882.     
  883.     totalLen = 0;
  884.     for ( i = 1; i < *num_params; i++ ) {
  885.       if ( params[i] ) {
  886.     totalLen += strlen( params[i] );
  887.       }
  888.       else {
  889.     break;
  890.       }
  891.     }
  892.     
  893.     totalLen += (*num_params = 10);
  894.     
  895.     printCommand = (char *) malloc( sizeof(char) * totalLen + 1);
  896.     bzero(printCommand, totalLen + 1);
  897.     
  898.     for ( i = 1; i < *num_params; i++ ) {
  899.       if ( params[i] ) {
  900.     strncat(printCommand, params[i], totalLen);
  901.     strncat(printCommand, " ", totalLen);
  902.       }
  903.       else {
  904.     break;
  905.       }
  906.     }
  907.     TeXMarkPrintUsing(w, pd, printCommand);
  908.     
  909.     free( printCommand );
  910.   }
  911. }
  912.  
  913. static void actionMarkPage(w, event, params, num_params)
  914.      Widget w;
  915.      XEvent *event;
  916.      String *params;
  917.      Cardinal *num_params;
  918. {
  919.   MarkDirective d;
  920.   
  921.   d = markNone;
  922.   
  923.   if (*num_params < 1) {
  924.     error(0,0,"Must specify set/clear/toggle to texx-mark-all");
  925.   }
  926.   else if ( strcmp(params[0],"set") == 0 ) {
  927.     d = markSet;
  928.   }
  929.   else if ( strcmp(params[0],"clear") == 0 ) {
  930.     d = markClear;
  931.   }
  932.   else if ( strcmp(params[0],"toggle") == 0 ) {
  933.     d = markToggle;
  934.   }
  935.   else {
  936.     error(0,0,"Must specify set/clear/toggle to texx-mark-all");
  937.   }
  938.   
  939.   if (markNone) {
  940.     return;
  941.   }
  942.   else {
  943.     TeXPage *tp = TeXPageLocate(w);
  944.     int num = tp -> pageNumber;
  945.     TeXMark( d, num );
  946.   }
  947.  
  948. static void actionMarkAll(w, event, params, num_params)
  949.      Widget w;
  950.      XEvent *event;
  951.      String *params;
  952.      Cardinal *num_params;
  953. {
  954.   MarkDirective d;
  955.   
  956.   d = markNone;
  957.   
  958.   if (*num_params < 1) {
  959.     error(0,0,"Must specify set/clear/toggle to texx-mark-all");
  960.   }
  961.   else if ( strcmp(params[0],"set") == 0 ) {
  962.     d = markSet;
  963.   }
  964.   else if ( strcmp(params[0],"clear") == 0 ) {
  965.     d = markClear;
  966.   }
  967.   else if ( strcmp(params[0],"toggle") == 0 ) {
  968.     d = markToggle;
  969.   }
  970.   else {
  971.     error(0,0,"Must specify set/clear/toggle to texx-mark-all");
  972.   }
  973.   
  974.   if  ( d != markNone ) {
  975.     TeXMarkAll( d );
  976.   }
  977. }
  978.  
  979. static void actionMarkPush(w, event, params, num_params)
  980.      Widget w;
  981.      XEvent *event;
  982.      String *params;
  983.      Cardinal *num_params;
  984. {
  985.   TeXMarkPush();
  986.  
  987. static void actionMarkPop(w, event, params, num_params)
  988.      Widget w;
  989.      XEvent *event;
  990.      String *params;
  991.      Cardinal *num_params;
  992. {
  993.   TeXMarkPop();
  994.  
  995. static void actionSystem(w, event, params, num_params)
  996.      Widget w;
  997.      XEvent *event;
  998.      String *params;
  999.      Cardinal *num_params;
  1000. {
  1001.   if ( num_params ) {
  1002.     int p;
  1003.     char buffer[1024];
  1004.     char *buf = buffer;
  1005.     int buflen = 0;
  1006.     char *b = buf;
  1007.     int space = 1024;
  1008.     Bool malloced = False;
  1009.  
  1010.     for (p = 0; p < *num_params ; p++) {
  1011.       int len = strlen( params[p] );
  1012.       if (space < (len+1)) {
  1013.     char *new = (char *) XtMalloc( buflen * 2);
  1014.     space = buflen * 2;
  1015.     strcpy(new,buf);
  1016.     if ( malloced ) XtFree(buf);
  1017.     malloced = True;
  1018.     buf = new;
  1019.     b = buf + buflen;
  1020.       }
  1021.  
  1022.       strcpy(b,params[p]);
  1023.  
  1024.       b += len;
  1025.       *(b++) = ' ';
  1026.  
  1027.       buflen += (len + 1);
  1028.       space -= (len + 1);
  1029.     }
  1030.  
  1031.     *b = 0;
  1032.  
  1033.     TeXSystemCall(buf);
  1034.  
  1035.     if ( malloced ) XtFree(buf);
  1036.   }
  1037.  
  1038. static XtActionsRec texxMarkActionsTable[] = {
  1039.   {"xtex-mark-all",  actionMarkAll },
  1040.   {"xtex-mark-page",  actionMarkPage },
  1041.   {"xtex-mark-push",  actionMarkPush },
  1042.   {"xtex-mark-pop",  actionMarkPop },
  1043.   {"xtex-system",  actionSystem},
  1044.   {"xtex-string-confirm",  confirmString},
  1045.   {"xtex-string-cancel",  cancelString},
  1046.   {"xtex-print-using",  actionPrintUsing }
  1047. };
  1048.  
  1049. void
  1050.   TeXMarkInstallActions()
  1051. {
  1052.   XtAddActions(texxMarkActionsTable, XtNumber(texxMarkActionsTable));
  1053. }
  1054.  
  1055.