home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / xdvi / part01 / xdvi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-07  |  42.3 KB  |  1,542 lines

  1. /*
  2.  * DVI previewer for X.
  3.  *
  4.  * Eric Cooper, CMU, September 1985.
  5.  *
  6.  * Code derived from dvi-imagen.c.
  7.  *
  8.  * Modification history:
  9.  * 1/1986    Modified for X.10 by Bob Scheifler, MIT LCS.
  10.  * 7/1988    Modified for X.11 by Mark Eichin, MIT
  11.  * 12/1988    Added 'R' option, toolkit, magnifying glass
  12.  *            --Paul Vojta, UC Berkeley.
  13.  * 2/1989    Added tpic support    --Jeffrey Lee, U of Toronto
  14.  *
  15.  *    Compilation options:
  16.  *    X10    compile for X10
  17.  *    MSBITFIRST    store bitmaps internally in with significant bit first
  18.  *    BMSHORT    store bitmaps in shorts instead of bytes
  19.  *    BMLONG    store bitmaps in longs instead of bytes
  20.  */
  21. #ifndef lint
  22. #include "patchlevel.h"
  23. static    struct {char    a[36], b, c;}
  24. #ifndef X10
  25.     dv_c = {"$Header: xdvi.c (X11), patchlevel = ", '0' + PATCHLEVEL, 0};
  26. #else X10
  27.     dv_c = {"$Header: xdvi.c (X10), patchlevel = ", '0' + PATCHLEVEL, 0};
  28. #endif X10
  29. #endif    lint
  30.  
  31. #ifndef X10
  32.  
  33. #undef Boolean
  34. #include <X11/Xlib.h>
  35. #include <X11/Xutil.h>
  36. #include <X11/Intrinsic.h>
  37. #ifdef OLD_X11_TOOLKIT
  38. #include <X11/Atoms.h>
  39. #else not OLD_X11_TOOLKIT
  40. #include <X11/Xatom.h>
  41. #include <X11/StringDefs.h>
  42. #endif not OLD_X11_TOOLKIT
  43. #include <X11/Shell.h>    /* needed for def. of XtNiconX */
  44. #include <X11/Viewport.h>
  45. #include <X11/Simple.h>
  46. #include <X11/cursorfont.h>
  47. #include "xdvi.icon"
  48.  
  49. #else X10
  50.  
  51. #include <X/Xlib.h>
  52.  
  53. #endif X10
  54.  
  55. #include <stdio.h>
  56. #include <ctype.h>
  57. #include <fcntl.h>
  58. #include <signal.h>
  59. #include "xdvi.h"
  60.  
  61. #ifndef X10
  62. static    Display    *DISP;
  63. #define    DPY    DISP,
  64. static    Screen    *SCRN;
  65. static    Cursor    redraw_cursor, ready_cursor;
  66. #define    SetCursor(x)    XDefineCursor(DISP, mane.win, x)
  67. #define    ClearPage()    XClearWindow(DISP, mane.win);
  68. #define    Flush()        XFlush(DISP)
  69. static    Boolean    unmapped = True;
  70. #ifndef X11HEIGHT
  71. #define    X11HEIGHT    8    /* Height of server default font */
  72. #endif X11HEIGHT
  73. #else X10
  74. #define    DPY
  75. #define    GC        int
  76. #define    XtNumber(arr)    (sizeof(arr)/sizeof(arr[0]))
  77. #define    XtPending    XPending
  78. typedef    int        Position;
  79. typedef    int        Dimension;
  80. #define    SetCursor(x)
  81. #define    ClearPage()    XClear(mane.win);
  82. #define    XBell(a,b)    XFeep(b/10-1)
  83. #define    Flush()        XFlush()
  84. #define    ConnectionNumber(DISP)    (_XlibCurrentDisplay->fd)
  85. #ifndef X10FONT
  86. #define    X10FONT    "helv10b"    /* Font for X10 error messages */
  87. #define    X10HEIGHT    10
  88. #endif X10FONT
  89. #endif X10
  90.  
  91. #define    MAGBORD    1    /* border size for magnifier */
  92. char    *font_path;
  93. char    default_font_path[]    = DEFAULT_FONT_PATH;
  94.  
  95. /*
  96.  * Command line flags.
  97.  */
  98. int    debug = 0;
  99. Boolean    list_fonts = False;
  100.  
  101. int    density = 40;
  102. int    pixels_per_inch = 300;
  103. static    char    *margins, *sidemargin, *topmargin;
  104. static    Boolean    reverse;
  105. static    Dimension    bwidth    = 2;
  106. static    int    bak_shrink;
  107. static    char    *debug_arg;
  108. static    int    mg_size[5] = {200, 350, 600, 900, 1200};
  109.  
  110. char    *dvi_name = NULL;
  111. FILE    *dvi_file;                /* user's file */
  112. char    *prog;
  113. char    *curr_page = NULL;
  114.  
  115. #ifndef X10
  116. static    double    specialConv;
  117.         /* fg and bg colors */
  118. static    Arg    fore_args = {XtNforeground,    (XtArgVal) 0};
  119. static    Arg    back_args = {XtNbackground,    (XtArgVal) 0};
  120. static    XColor    hl_Color, cr_Color;
  121. #endif X10
  122.  
  123. static    char    *fore_color;
  124. static    char    *back_color;
  125. static    char    *high_color;
  126. static    char    *curs_color;
  127. static    GC    foreGC, highGC;
  128. #ifndef X10
  129. static    GC    ruleGC;
  130. static    GC    foreGC2;
  131. #else X10
  132. #define    ruleGC    foreGC
  133. #endif X10
  134.  
  135. int    page_w, page_h;
  136. static    int    screen_w, screen_h;
  137. static    Dimension    window_w, window_h;
  138. static    int    home_x, home_y;
  139. static    int    min_x, max_x, min_y, max_y;
  140.  
  141. struct WindowRec mane    = {NULL, 4, 0, 0, MAXINT, 0, MAXINT, 0};
  142. struct WindowRec alt    = {NULL, 1, 0, 0, MAXINT, 0, MAXINT, 0};
  143. /*    curr is temporary storage except for within redraw() */
  144. struct WindowRec curr    = {NULL, 4, 0, 0, MAXINT, 0, MAXINT, 0};
  145.  
  146. /*
  147.  *    Mechanism to keep track of the magnifier window.  The problems are,
  148.  *    (a) if the button is released while the window is being drawn, this
  149.  *    could cause an X error if we continue drawing in it after it is
  150.  *    destroyed, and
  151.  *    (b) creating and destroying the window too quickly confuses the window
  152.  *    manager, which is avoided by waiting for an expose event before
  153.  *    destroying it.
  154.  */
  155. static    short    alt_stat;    /* 1 = wait for expose, */
  156.                 /* -1 = destroy upon expose */
  157. static    Boolean    alt_canit;    /* stop drawing this window */
  158.  
  159. int    pageno_correct    = 1;
  160.  
  161. /*
  162.  *    Data for buffered events.
  163.  */
  164.  
  165. static    Boolean    canit        = False,
  166.         arg        = False;
  167. static    short    event_counter    = 0,
  168.         event_freq    = 70;
  169. static    int    number        = 0,
  170.         sign        = 1;
  171. static    jmp_buf    canit_env;
  172.  
  173. static    void    can_exposures(), read_events();
  174.  
  175. char    *malloc(), *index(), *rindex(), *sprintf(), *getenv(),
  176.     *strcpy(), *strcat();
  177.  
  178. double    atof();
  179.  
  180. #ifndef X10
  181. /* Things we need from spec_draw, unfortunately */
  182.  
  183. /* (ignored for now)
  184. extern int pen_size, blacken, whiten, shade;
  185. */
  186.  
  187. #define    toint(x)    ((int) ((x) + 0.5))
  188. #define    xconv(x)    (toint(specialConv*(x))/shrink_factor + PXL_H)
  189. #define    yconv(y)    (toint(specialConv*(y))/shrink_factor + PXL_V)
  190.  
  191. /*
  192.  *    Draw a line from (fx,fy) to (tx,ty).
  193.  *    Right now, we ignore pen_size.
  194.  */
  195. void
  196. line_btw(fx, fy, tx, ty)
  197. int fx, fy, tx, ty;
  198. {
  199.     register int    fcx = xconv(fx),
  200.             tcx = xconv(tx),
  201.             fcy = yconv(fy),
  202.             tcy = yconv(ty);
  203.  
  204.     if ((fcx < max_x || tcx < max_x) && (fcx >= min_x || tcx >= min_x) &&
  205.         (fcy < max_y || tcy < max_y) && (fcy >= min_y || tcy >= min_y))
  206.         XDrawLine(DISP, curr.win, ruleGC,
  207.             fcx - curr.base_x, fcy - curr.base_y,
  208.             tcx - curr.base_x, tcy - curr.base_y);
  209. }
  210.  
  211. /*
  212.  *    Draw a dot at (x,y)
  213.  */
  214. void
  215. dot_at(x, y)
  216. {
  217.     register int    cx = xconv(x),
  218.             cy = yconv(y);
  219.  
  220.     if (cx < max_x && cx >= min_x && cy < max_y && cy >= min_y)
  221.         XDrawPoint(DISP, curr.win, ruleGC,
  222.         cx - curr.base_x, cy - curr.base_y);
  223. }
  224.  
  225. /*
  226.  *    Apply the requested attributes to the last path (box) drawn.
  227.  *    Attributes are reset.
  228.  *    (Not currently implemented.)
  229.  */
  230.     /* ARGSUSED */
  231. void
  232. do_attribute_path(last_min_x, last_max_x, last_min_y, last_max_y)
  233. int last_min_x, last_max_x, last_min_y, last_max_y;
  234. {
  235. }
  236. #else X10
  237. /*
  238.  *    Specials are not implemented in X10.
  239.  */
  240.  
  241. void
  242. applicationDoSpecial(cmd)
  243. char    *cmd;
  244. {
  245.     if (spec_warn) Fprintf(stderr, "special ``%s'' not implemented\n", cmd);
  246. }
  247. #endif X10
  248.  
  249. #ifndef X10
  250. static    Widget    top_level, vport_widget, draw_widget, clip_widget;
  251. static    XImage    *image;
  252.  
  253. static    Arg    vport_args[] = {
  254.     {XtNallowHoriz,    (XtArgVal) True},
  255.     {XtNallowVert,    (XtArgVal) True},
  256. };
  257.  
  258. /*    Note:  Argument order in the following is important! */
  259.  
  260. static    Arg    draw_args[] = {
  261.     {XtNwidth,    (XtArgVal) 0},
  262.     {XtNheight,    (XtArgVal) 0},
  263.     {XtNx,        (XtArgVal) 0},
  264.     {XtNy,        (XtArgVal) 0},
  265.     {XtNlabel,    (XtArgVal) ""},
  266. };
  267.  
  268. static    void    set_draw_args();
  269. #else X10
  270. static    int    GXfunc;
  271. static    int    backpix, backmap, bdrmap;
  272. /*
  273.  * Cursor and mask for valid cursor
  274.  */
  275. #include "xdvi_curs.h"
  276. #include "xdvi_mask.h"
  277. #endif X10
  278.  
  279. #ifdef lint
  280. #ifndef X10
  281. WidgetClass    viewportWidgetClass, simpleWidgetClass;
  282. char    xdvi_bits[288];
  283. #else X10
  284. short    xdvi_bits[15], xdvi_mask_bits[15];
  285. Display    *_XlibCurrentDisplay;
  286. #endif X10
  287. #endif lint
  288.  
  289. /**
  290.  **    Put a rectangle on the screen.  hl determines the GC.
  291.  **/
  292.  
  293. put_rectangle(x, y, w, h, hl)
  294.     int x, y, w, h;
  295.     Boolean hl;
  296. {
  297.     if (x < max_x && x + w >= min_x && y < max_y && y + h >= min_y) {
  298.         if (--event_counter == 0) read_events(False);
  299. #ifndef X10
  300.         XFillRectangle(DISP, curr.win, hl ? highGC : ruleGC,
  301.                    x - curr.base_x, y - curr.base_y, w?w:1, h?h:1);
  302. #else X10
  303.         XPixSet(curr.win, x - curr.base_x, y - curr.base_y,
  304.             w?w:1, h?h:1, hl ? highGC : ruleGC);
  305. #endif X10
  306.     }
  307. }
  308.  
  309. put_bitmap(bitmap, x, y)
  310.     register struct bitmap *bitmap;
  311.     register int x, y;
  312. {
  313.  
  314.     if (debug & DBG_BITMAP)
  315.         Printf("X(%d,%d)\n", x-curr.base_x, y-curr.base_y);
  316.     if (x < max_x && x + bitmap->w >= min_x &&
  317.         y < max_y && y + bitmap->h >= min_y) {
  318.         if (--event_counter == 0) read_events(False);
  319. #ifndef X10
  320.         image->width = bitmap->w;
  321.         image->height = bitmap->h;
  322.         image->data = (char *)bitmap->bits;
  323.         image->bytes_per_line = bitmap->bytes_wide;
  324.         XPutImage(DISP, curr.win, foreGC, image,
  325.             0, 0,
  326.             x - curr.base_x, y - curr.base_y,
  327.             bitmap->w, bitmap->h);
  328.         if (foreGC2)
  329.             XPutImage(DISP, curr.win, foreGC2, image,
  330.             0, 0,
  331.             x - curr.base_x, y - curr.base_y,
  332.             bitmap->w, bitmap->h);
  333. #else X10
  334.         XBitmapBitsPut(curr.win, x - curr.base_x, y - curr.base_y,
  335.             bitmap->w, bitmap->h, (char *) bitmap->bits,
  336.             foreGC, backpix, NULL, GXfunc, AllPlanes);
  337. #endif X10
  338.     }
  339. }
  340.  
  341. put_border(x, y, w, h, t)
  342.     int x, y, w, h, t;
  343. {
  344.     put_rectangle(x, y, w, t, True);
  345.     put_rectangle(x, y, t, h, True);
  346.     put_rectangle(x, y + h - t, w, t, True);
  347.     put_rectangle(x + w - t, y, t, h, True);
  348. }
  349.  
  350. #ifndef X10
  351. /*
  352.  *    routines for X11 toolkit
  353.  */
  354.  
  355. static    Arg    arg_wh[] = {
  356.     {XtNwidth,    (XtArgVal) &window_w},
  357.     {XtNheight,    (XtArgVal) &window_h},
  358. };
  359.  
  360. #define    get_wh(widget)    XtGetValues(widget, arg_wh, 2)
  361.  
  362. static    Position    window_x, window_y;
  363. static    Arg        arg_xy[] = {
  364.     {XtNx,        (XtArgVal) &window_x},
  365.     {XtNy,        (XtArgVal) &window_y},
  366. };
  367.  
  368. #define    get_xy()    XtGetValues(draw_widget, arg_xy, 2)
  369.  
  370. #define    mane_base_x    0
  371. #define    mane_base_y    0
  372.  
  373. static    Boolean
  374. scroll(horizontal, percent)
  375.     Boolean    horizontal;
  376.     float    percent;
  377. {
  378.     register Widget    widget;
  379.  
  380.     widget = XtNameToWidget(vport_widget,
  381.         horizontal ? "horizontal" : "vertical");
  382.     if (!widget) return False;
  383.     XtGetValues(clip_widget, horizontal ? &arg_wh[0] : &arg_wh[1], 1);
  384.     XtCallCallbacks(widget, XtNscrollProc,
  385.         (int) (percent*(horizontal ? window_w : window_h)));
  386.     return True;
  387. }
  388.  
  389. /*
  390.  *    We unmap the window so that it does not generate expose events when
  391.  *    moving things around.  I have found that compress_exposure does not do
  392.  *    this.
  393.  */
  394.  
  395. static
  396. unmap()
  397. {
  398.     if (unmapped) return;
  399.     XUnmapWindow(DISP, mane.win);
  400.     unmapped = True;
  401. }
  402.  
  403. static
  404. home()
  405. {
  406.     register Widget    widget;
  407.     register int coord;
  408.  
  409.     unmap();
  410.     get_xy();
  411.     get_wh(clip_widget);
  412.     widget = XtNameToWidget(vport_widget, "horizontal");
  413.     if (widget) {
  414.         coord = 0;
  415.         if (page_w > window_w) {
  416.         coord = (page_w - window_w) / 2;
  417.         if (coord > home_x / mane.shrinkfactor)
  418.             coord = home_x / mane.shrinkfactor;
  419.         }
  420.         XtCallCallbacks(widget, XtNscrollProc, window_x + coord);
  421.     }
  422.     widget = XtNameToWidget(vport_widget, "vertical");
  423.     if (widget) {
  424.         coord = 0;
  425.         if (page_h > window_h) {
  426.         coord = (page_h - window_h) / 2;
  427.         if (coord > home_y / mane.shrinkfactor)
  428.             coord = home_y / mane.shrinkfactor;
  429.         }
  430.         XtCallCallbacks(widget, XtNscrollProc, window_y + coord);
  431.     }
  432. }
  433.  
  434. static    void
  435. center(x, y)
  436.     int x, y;
  437. {
  438.     register Widget widget;
  439.  
  440. /*    We use the clip widget here because it gives a more exact value. */
  441.     get_wh(clip_widget);
  442.     x -= window_w/2;
  443.     y -= window_h/2;
  444.     widget = XtNameToWidget(vport_widget, "horizontal");
  445.     if (widget) XtCallCallbacks(widget, XtNscrollProc, x);
  446.     widget = XtNameToWidget(vport_widget, "vertical");
  447.     if (widget) XtCallCallbacks(widget, XtNscrollProc, y);
  448.     XWarpPointer(DISP, None, None, 0, 0, 0, 0, -x, -y);
  449. }
  450.  
  451. /*
  452.  *    callback routines
  453.  */
  454.  
  455. /* The following callback routine should never be called. */
  456.     /*ARGSUSED*/
  457. static    void
  458. handle_key(widget, junk, event)
  459.     Widget    widget;
  460.     caddr_t    junk;
  461.     XEvent    *event;
  462. {
  463.     XBell(DISP, 20);
  464. }
  465. #else X10
  466. static
  467. home()
  468. {
  469.     mane.base_x = 0;
  470.     if (page_w > window_w) {
  471.         mane.base_x = (page_w - window_w) / 2;
  472.         if (mane.base_x > home_x / mane.shrinkfactor)
  473.         mane.base_x = home_x / mane.shrinkfactor;
  474.     }
  475.     mane.base_y = 0;
  476.     if (page_h > window_h) {
  477.         mane.base_y = (page_h - window_h) / 2;
  478.         if (mane.base_y > home_y / mane.shrinkfactor)
  479.         mane.base_y = home_y / mane.shrinkfactor;
  480.     }
  481. }
  482.  
  483. #define    unmap()
  484. #define    get_wh(widget)
  485. #define    get_xy()
  486. #define    window_x 0
  487. #define    window_y 0
  488. #define    mane_base_x    mane.base_x
  489. #define    mane_base_y    mane.base_y
  490. #endif X10
  491.  
  492. #ifndef X10
  493.     /*ARGSUSED*/
  494. static    void
  495. handle_button(widget, junk, event)
  496.     Widget    widget;
  497.     caddr_t    junk;
  498.     XButtonEvent *event;
  499. #else X10
  500. static    void
  501. handle_button(event, mag_size)
  502.     XButtonPressedEvent *event;
  503.     int mag_size;
  504. #endif X10
  505. {
  506.     int x, y;
  507. #ifndef X10
  508.     int mag_size = mg_size[event->button - 1];
  509.     XSetWindowAttributes attr;
  510. #endif X10
  511.  
  512.     if (alt.win != NULL || mane.shrinkfactor == 1 || mag_size <= 0)
  513.         XBell(DISP, 20);
  514.     else {
  515. #ifndef X10
  516.         x = event->x_root - mag_size/2;
  517.         if (x > WidthOfScreen(SCRN) - mag_size - 2*MAGBORD)
  518.         x = WidthOfScreen(SCRN) - mag_size - 2*MAGBORD;
  519.         if (x < 0) x = 0;
  520.         y = event->y_root - mag_size/2;
  521.         if (y > HeightOfScreen(SCRN) - mag_size - 2*MAGBORD)
  522.         y = HeightOfScreen(SCRN) - mag_size - 2*MAGBORD;
  523.         if (y < 0) y = 0;
  524. #else X10
  525.         x = event->x - mag_size/2;
  526.         if (x > window_w - mag_size - 2*MAGBORD)
  527.         x = window_w - mag_size - 2*MAGBORD;
  528.         if (x < 0) x = 0;
  529.         y = event->y - mag_size/2;
  530.         if (y > window_h - mag_size - 2*MAGBORD)
  531.         y = window_h - mag_size - 2*MAGBORD;
  532.         if (y < 0) y = 0;
  533. #endif X10
  534.         alt.base_x = (event->x + mane_base_x) * mane.shrinkfactor -
  535.         mag_size/2;
  536.         alt.base_y = (event->y + mane_base_y) * mane.shrinkfactor -
  537.         mag_size/2;
  538. #ifndef X10
  539.         attr.save_under = True;
  540.         attr.border_pixel = fore_args.value;
  541.         attr.background_pixel = back_args.value;
  542.         alt.win = XCreateWindow(DISP, RootWindowOfScreen(SCRN),
  543.             x, y, mag_size, mag_size, MAGBORD,
  544.             0,    /* depth from parent */
  545.             InputOutput, CopyFromParent,
  546.             CWSaveUnder|CWBorderPixel|CWBackPixel, &attr);
  547.         XSetTransientForHint(DISP, alt.win, XtWindow(top_level));
  548.         XSelectInput(DISP, alt.win, ExposureMask);
  549. #else X10
  550.         alt.win = XCreateWindow(mane.win,
  551.             x, y, mag_size, mag_size, MAGBORD,
  552.             bdrmap, backmap);
  553.         XSelectInput(alt.win, ExposeRegion);
  554. #endif X10
  555.         XMapWindow(DPY alt.win);
  556.         alt_stat = 1;    /* waiting for exposure */
  557.     }
  558. }
  559.  
  560. #ifndef X10
  561.     /*ARGSUSED*/
  562. static    void
  563. handle_release(widget, junk, event)
  564.     Widget    widget;
  565.     caddr_t    junk;
  566.     XButtonEvent *event;
  567. #else X10
  568. static    void
  569. handle_release()
  570. #endif X10
  571. {
  572.     if (alt.win)
  573.         if (alt_stat) alt_stat = -1;    /* destroy upon expose */
  574.         else {
  575.         XDestroyWindow(DPY alt.win);
  576.         if (curr.win == alt.win) alt_canit = True;
  577.         alt.win = NULL;
  578.         can_exposures(&alt);
  579.         }
  580. }
  581.  
  582. #ifndef X10
  583.     /*ARGSUSED*/
  584. static    void
  585. handle_exp(widget, windowrec, event)
  586.     Widget    widget;
  587.     struct WindowRec *windowrec;
  588.     register XExposeEvent *event;
  589. {
  590.     if (windowrec == &alt)
  591.         if (alt_stat < 0) {    /* destroy upon exposure */
  592.         alt_stat = 0;
  593.         handle_release(widget, (caddr_t) NULL, (XButtonEvent *) event);
  594.         return;
  595.         }
  596.         else
  597.         alt_stat = 0;
  598.     if (windowrec->min_x > event->x) windowrec->min_x = event->x;
  599.     if (windowrec->max_x < event->x + event->width)
  600.         windowrec->max_x = event->x + event->width;
  601.     if (windowrec->min_y > event->y) windowrec->min_y = event->y;
  602.     if (windowrec->max_y < event->y + event->height)
  603.         windowrec->max_y = event->y + event->height;
  604. }
  605. #endif X10
  606.  
  607. #ifndef X10
  608. #define    TRSIZE    100
  609. #endif X10
  610. static    void
  611. read_events(wait)
  612.     Boolean    wait;
  613. {
  614.     char    ch;
  615.     Boolean    arg0;
  616.     int    number0;
  617.     XEvent    event;
  618. #ifndef X10
  619.     char    trbuf[TRSIZE];
  620. #endif X10
  621.     char    *string;
  622.     int    nbytes;
  623.     int    next_page;
  624.  
  625.     alt_canit = False;
  626.     for (;;) {
  627.         ch = '\0';
  628.         event_counter = event_freq;
  629.         /*
  630.          * If we get a hit at this point, then we'll just end up making
  631.          * an extra call.
  632.          * Also, watch out, if we destroy the magnifying glass while
  633.          * writing it.
  634.          */
  635.         if (!XtPending() && (!wait || canit || mane.min_x < MAXINT ||
  636.             alt.min_x < MAXINT))
  637.         if (alt_canit) longjmp(canit_env, 1);
  638.         else return;
  639. #ifndef X10
  640.         XtNextEvent(&event);
  641.         if (event.xany.window == alt.win &&
  642.             event.type == Expose) {
  643.         handle_exp((Widget) NULL, &alt, &event.xexpose);
  644.         continue;
  645.         }
  646.         if (event.type != KeyPress) {
  647.         XtDispatchEvent(&event);
  648.         continue;
  649.         }
  650.         string = trbuf;
  651.         nbytes = XLookupString(&event, string, TRSIZE, NULL, NULL);
  652.         if (nbytes > 1) goto bad;
  653.         if (nbytes != 0) ch = *string;
  654. #else X10
  655.         XNextEvent(&event);
  656.         switch (event.type) {
  657.         case ExposeWindow:
  658.         if (event.window == mane.win) {
  659.             window_h = ((XExposeEvent *)(&event))->height;
  660.             window_w = ((XExposeEvent *)(&event))->width;
  661.             home();
  662.             ch = '\f';
  663.             break;
  664.         }
  665.         /* otherwise control passes through */
  666.  
  667.         case ExposeRegion:
  668.             /* check in case we already destroyed the window */
  669.         if (event.window == mane.win || alt.win != NULL) {
  670.             struct WindowRec *wr =
  671.             (event.window == mane.win ? &mane : &alt);
  672.             if (wr == &alt)
  673.             if (alt_stat < 0) { /* destroy upon exposure */
  674.                 alt_stat = 0;
  675.                 handle_release();
  676.                 break;
  677.             }
  678.             else
  679.                 alt_stat = 0;
  680. #define    ev        ((XExposeEvent *)(&event))
  681.             if (wr->min_x > ev->x) wr->min_x = ev->x;
  682.             if (wr->max_x < ev->x + ev->width)
  683.             wr->max_x = ev->x + ev->width;
  684.             if (wr->min_y > ev->y) wr->min_y = ev->y;
  685.             if (wr->max_y < ev->y + ev->height)
  686.             wr->max_y = ev->y + ev->height;
  687. #undef    ev
  688.         }
  689.         break;
  690.  
  691.         case ButtonPressed: {
  692.             int n = 0;
  693.             switch (((XButtonPressedEvent *) (&event))->detail &
  694.                 ValueMask) {
  695.             case LeftButton:  n=0; break;
  696.             case MiddleButton:  n=1; break;
  697.             case RightButton:  n=2; break;
  698.             }
  699.             handle_button((XButtonPressedEvent *) (&event), mg_size[n]);
  700.         }
  701.         break;
  702.         case ButtonReleased:
  703.         handle_release();
  704.         break;
  705.         case KeyPressed:
  706.         string = XLookupMapping (&event, &nbytes);
  707.         if (nbytes > 1) goto bad;
  708.         if (nbytes != 0) ch = *string;
  709.         break;
  710.         }
  711. #endif X10
  712.         if (ch == '\0') continue;
  713.         if (ch >= '0' && ch <= '9') {
  714.         arg = True;
  715.         number = number * 10 + sign * (ch - '0');
  716.         continue;
  717.         }
  718.         else if (ch == '-') {
  719.         arg = True;
  720.         sign = -1;
  721.         number = 0;
  722.         continue;
  723.         }
  724.         arg0 = arg;
  725.         arg = False;
  726.         number0 = number;
  727.         number = 0;
  728.         sign = 1;
  729.         next_page = current_page;
  730.  
  731.         switch (ch) {
  732.         case 'q':
  733.         case '\003':    /* control-C */
  734.         case '\004':    /* control-D */
  735.             exit(0);
  736.         case 'n':
  737.         case 'f':
  738.         case ' ':
  739.         case '\r':
  740.         case '\n':
  741.             /* scroll forward; i.e. go to relative page */
  742.             next_page = current_page + (arg0 ? number0 : 1);
  743.             break;
  744.         case 'p':
  745.         case 'b':
  746.         case '\b':
  747.         case '\177':    /* Del */
  748.             /* scroll backward */
  749.             next_page = current_page - 1;
  750.             break;
  751.         case 'g':
  752.             /* go to absolute page */
  753.             next_page = (arg0 ? number0 - pageno_correct :
  754.             total_pages - 1);
  755.             break;
  756.         case 'P':        /* declare current page */
  757.             pageno_correct = arg0 * number0 - current_page;
  758.             continue;
  759.         case '\f':
  760.             /* redisplay current page */
  761.             break;
  762.         case '^':
  763.             home();
  764.             break;
  765. #ifndef X10
  766.         case 'u':
  767.             if (!scroll(False, -0.67)) goto bad;
  768.             continue;
  769.         case 'd':
  770.             if (!scroll(False, 0.67)) goto bad;
  771.             continue;
  772.         case 'l':
  773.             if (!scroll(True, -0.67)) goto bad;
  774.             continue;
  775.         case 'r':
  776.             if (!scroll(True, 0.67)) goto bad;
  777.             continue;
  778.         case 'c':
  779.             center(event.xkey.x, event.xkey.y);
  780.             continue;
  781.         case 'M':
  782.             XTranslateCoordinates(DISP, event.xkey.window, mane.win,
  783.                 event.xkey.x, event.xkey.y, &home_x, &home_y,
  784.                 &number0);    /* throw away last argument */
  785.             home_x *= mane.shrinkfactor;
  786.             home_y *= mane.shrinkfactor;
  787.             continue;
  788.         case '\020':    /* Control P */
  789.             Printf("Unit = %d, bitord = %d, byteord = %d\n",
  790.             BitmapUnit(DISP), BitmapBitOrder(DISP),
  791.             ImageByteOrder(DISP));
  792.             continue;
  793. #else X10
  794.         case 'u':
  795.             if (mane.base_y == 0) goto bad;
  796.             mane.base_y -= window_h;
  797.             if (mane.base_y < 0)
  798.             mane.base_y = 0;
  799.             break;
  800.         case 'd':
  801.             if (mane.base_y >= page_h - window_h) goto bad;
  802.             mane.base_y += window_h;
  803.             if (mane.base_y > page_h - window_h)
  804.             mane.base_y = page_h - window_h;
  805.             break;
  806.         case 'l':
  807.             if (mane.base_x == 0) goto bad;
  808.             mane.base_x -= window_w;
  809.             if (mane.base_x < 0)
  810.             mane.base_x = 0;
  811.             break;
  812.         case 'r':
  813.             if (mane.base_x >= page_w - window_w) goto bad;
  814.             mane.base_x += window_w;
  815.             if (mane.base_x > page_w - window_w)
  816.             mane.base_x = page_w - window_w;
  817.             break;
  818.         case 'c':
  819. #define    ev        ((XKeyPressedEvent *) (&event))
  820.             mane.base_x += ev->x - window_w/2;
  821.             mane.base_y += ev->y - window_h/2;
  822.             XWarpMouse(mane.win, window_w/2, window_h/2, 3);
  823.             break;
  824.         case 'M':
  825.             home_x = (ev->x + mane.base_x) * mane.shrinkfactor;
  826.             home_y = (ev->y + mane.base_y) * mane.shrinkfactor;
  827.             continue;
  828. #undef    ev
  829. #endif X10
  830.         case 's':
  831.             if (!arg0) {
  832.             long fac1, fac2;
  833.             shrink_factor = 1;
  834.             get_wh(vport_widget);
  835.             fac1 = ROUNDUP(PAPER_WIDTH, window_w);
  836.             fac2 = ROUNDUP(PAPER_HEIGHT, window_h);
  837.             if (fac1 < fac2)
  838.                 number0 = fac2;
  839.             else
  840.                 number0 = fac1;
  841.             }
  842.             if (number0 <= 0) goto bad;
  843.             if (number0 == mane.shrinkfactor) continue;
  844.             shrink_factor = mane.shrinkfactor = number0;
  845.             unmap();
  846.             init_page();
  847.             if (number0 != 1 && number0 != bak_shrink) {
  848.             bak_shrink = number0;
  849.             reset_fonts();
  850.             }
  851. #ifndef X10
  852.             set_draw_args();
  853.             XtSetValues(draw_widget, draw_args, 2);
  854. #endif X10
  855.             home();
  856.             break;
  857.         case 'S':
  858.             if (!arg0) goto bad;
  859.             if (number0 < 0) goto bad;
  860.             if (number0 == density) continue;
  861.             density = number0;
  862.             reset_fonts();
  863.             if (mane.shrinkfactor == 1) continue;
  864.             unmap();
  865.             break;
  866.         case 'R':
  867.             /* reread DVI file */
  868.             --dvi_time;    /* then it will notice a change */
  869.             break;
  870.         default:
  871.             goto bad;
  872.         }
  873.         if (0 <= next_page && next_page < total_pages) {
  874.         if (current_page != next_page) {
  875.             current_page = next_page;
  876.             spec_warn = True;
  877.             home();
  878.         }
  879.         canit = True;
  880.         Flush();
  881.         longjmp(canit_env, 1);
  882.         }
  883.         bad:  XBell(DISP, 10);
  884.     }
  885. }
  886.  
  887. static
  888. redraw(windowrec)
  889.     struct WindowRec *windowrec;
  890. {
  891.     char    *errtext;
  892. #ifdef X10
  893.     static FontInfo *font = 0;
  894. #endif X10
  895.  
  896.     curr = *windowrec;
  897.     min_x = curr.min_x + curr.base_x;
  898.     min_y = curr.min_y + curr.base_y;
  899.     max_x = curr.max_x + curr.base_x;
  900.     max_y = curr.max_y + curr.base_y;
  901.     can_exposures(windowrec);
  902.  
  903.     if (debug & DBG_EVENT)
  904.         Printf("Redraw %d x %d at (%d, %d) (base=%d,%d)\n", max_x - min_x,
  905.         max_y - min_y, min_x, min_y, curr.base_x, curr.base_y);
  906.     SetCursor(redraw_cursor);
  907.     if (errtext = (char *) setjmp(dvi_env)) {
  908.         ClearPage();
  909. #ifndef X10
  910.         get_xy();
  911.         XDrawString(DISP, mane.win, foreGC,
  912.         5 - window_x, 5 + X11HEIGHT - window_y,
  913.         errtext, strlen(errtext));
  914. #else X10
  915.         if (!font) font = XOpenFont(X10FONT);
  916.         XTextMask(mane.win, 5, 5 + X10HEIGHT, errtext, strlen(errtext),
  917.         font->id, foreGC);
  918. #endif X10
  919.         if (dvi_file) {
  920.         Fclose(dvi_file);
  921.         dvi_file = NULL;
  922.         }
  923.     }
  924.     else {
  925.         draw_page();
  926.         spec_warn = False;
  927.     }
  928. }
  929.  
  930. redraw_page()
  931. {
  932.     if (debug & DBG_EVENT) fputs("Redraw page:  ", stdout);
  933.     get_wh(clip_widget);
  934.     get_xy();
  935.     ClearPage();
  936.     mane.min_x = -window_x;
  937.     mane.max_x = -window_x + window_w;
  938.     mane.min_y = -window_y;
  939.     mane.max_y = -window_y + window_h;
  940.     redraw(&mane);
  941. }
  942.  
  943. /*
  944.  *    Interrupt system for receiving events.  The program sets a flag
  945.  *    whenever an event comes in, so that at the proper time (i.e., when
  946.  *    reading a new dvi item), we can check incoming events to see if we
  947.  *    still want to go on printing this page.  This way, one can stop
  948.  *    displaying a page if it is about to be erased anyway.  We try to read
  949.  *    as many events as possible before doing anything and base the next
  950.  *    action on all events read.
  951.  *    Note that the Xlib and Xt routines are not reentrant, so the most we
  952.  *    can do is set a flag in the interrupt routine and check it later.
  953.  *    Also, sometimes the interrupts are not generated (some systems only
  954.  *    guarantee that SIGIO is generated for terminal files, and on the system
  955.  *    I use, the interrupts are not generated if I use "(xdvi foo &)" instead
  956.  *    of "xdvi foo").  Therefore, there is also a mechanism to check the
  957.  *    event queue every 70 drawing operations or so.  This mechanism is
  958.  *    disabled if it turns out that the interrupts do work.
  959.  *    For a fuller discussion of some of the above, see xlife in
  960.  *    comp.sources.x.
  961.  */
  962.  
  963. static    void
  964. can_exposures(windowrec)
  965.     struct WindowRec *windowrec;
  966. {
  967.     windowrec->min_x = windowrec->min_y = MAXINT;
  968.     windowrec->max_x = windowrec->max_y = 0;
  969. }
  970.  
  971. static    int
  972. handle_intr() {
  973.     event_counter = 1;
  974.     event_freq = -1;    /* forget Plan B */
  975. }
  976.  
  977. static    void
  978. enable_intr() {
  979.     int    socket    = ConnectionNumber(DISP);
  980.     if (!isatty(0)) {
  981.         puts("trying...");
  982.         if (dup2(socket, 0) == -1) perror(prog);
  983.         socket = 0;
  984.     }
  985.     (void) signal(SIGIO, handle_intr);
  986.     (void) fcntl(socket, F_SETOWN, getpid());
  987.     (void) fcntl(socket, F_SETFL, fcntl(socket, F_GETFL, 0) | FASYNC);
  988. }
  989.  
  990. static
  991. do_pages()
  992. {
  993.     if (debug & DBG_BATCH) {
  994.         while (mane.min_x == MAXINT) read_events(True);
  995.         for (current_page = 0; current_page < total_pages; ++current_page)
  996.         redraw_page();
  997.         exit(0);
  998.     }
  999.     else {
  1000.         enable_intr();
  1001.         (void) setjmp(canit_env);
  1002.         for (;;) {
  1003.         SetCursor(ready_cursor);
  1004.         read_events(True);
  1005.         if (canit) {
  1006.             canit = False;
  1007.             can_exposures(&mane);
  1008.             can_exposures(&alt);
  1009. #ifndef X10
  1010.             if (unmapped) {
  1011.                 /* this creates a redraw event */
  1012.             XMapWindow(DISP, mane.win);
  1013.             unmapped = False;
  1014.             }
  1015.             else
  1016. #endif
  1017.             redraw_page();
  1018.         }
  1019.         else if (alt.min_x < MAXINT) redraw(&alt);
  1020.         else if (mane.min_x < MAXINT) redraw(&mane);
  1021.         Flush();
  1022.         }
  1023.     }
  1024. }
  1025.  
  1026. static
  1027. usage() {
  1028. #ifndef X10
  1029.     fputs("\
  1030. Usage: xdvi [+[<page>]] [-s <shrink>] [-S <density>] [-p <pixels>] [-l] [-rv]\n\
  1031.     [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] \
  1032. [-cr <color>]\n\
  1033.     [-margins <inches>] [-sidemargin <inches>] [-topmargin <inches>]\n\
  1034.     [-mgs[n] <size>] [-geometry <geometry>]  [#<geometry>]\n\
  1035.     [-display <host:display>] dvi_file\n", stderr);
  1036. #else X10
  1037.     fputs("\
  1038. Usage: xdvi [+[<page>]] [-s <shrink>] [-S <density>] [-p <pixels>] [-l] [-rv]\n\
  1039.     [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] \
  1040. [-cr <color>]\n\
  1041.     [-margins <inches>] [-sidemargin <inches>] [-topmargin <inches>]\n\
  1042.     [-mgs[n] <size>] [-geometry <geometry> | =<geometry>]\n\
  1043.     [-display <host:display> | host:display] dvi_file\n", stderr);
  1044. #endif X10
  1045.     exit(1);
  1046. }
  1047.  
  1048. /**
  1049.  **    Main programs start here.
  1050.  **/
  1051.  
  1052. #ifndef X10
  1053. static    char    *icon_geometry;
  1054. static    Boolean    thorough;
  1055.  
  1056. static    XrmOptionDescRec    options[] = {
  1057. {"-d",        ".debugLevel",    XrmoptionSepArg,    (caddr_t) NULL},
  1058. {"+",        ".gotoPage",    XrmoptionStickyArg,    (caddr_t) NULL},
  1059. {"-s",        ".shrinkFactor", XrmoptionSepArg,    (caddr_t) NULL},
  1060. {"-S",        ".densityPercent", XrmoptionSepArg,    (caddr_t) NULL},
  1061. {"-p",        ".pixelsPerInch", XrmoptionSepArg,    (caddr_t) NULL},
  1062. {"-margins",    ".margins",    XrmoptionSepArg,    (caddr_t) NULL},
  1063. {"-sidemargin",    ".sideMargin",    XrmoptionSepArg,    (caddr_t) NULL},
  1064. {"-topmargin",    ".topMargin",    XrmoptionSepArg,    (caddr_t) NULL},
  1065. {"-l",        ".listFonts",    XrmoptionNoArg,        (caddr_t) "on"},
  1066. {"+l",        ".listFonts",    XrmoptionNoArg,        (caddr_t) "off"},
  1067. {"-fg",        ".foreground",    XrmoptionSepArg,    (caddr_t) NULL},
  1068. {"-foreground",    ".foreground",    XrmoptionSepArg,    (caddr_t) NULL},
  1069. {"-bg",        ".background",    XrmoptionSepArg,    (caddr_t) NULL},
  1070. {"-background",    ".background",    XrmoptionSepArg,    (caddr_t) NULL},
  1071. {"-hl",        ".highlight",    XrmoptionSepArg,    (caddr_t) NULL},
  1072. {"-cr",        ".cursorColor",    XrmoptionSepArg,    (caddr_t) NULL},
  1073. {"#",        ".iconGeometry",XrmoptionStickyArg,     (caddr_t) NULL},
  1074. {"-thorough",    ".thorough",    XrmoptionNoArg,        (caddr_t) "on"},
  1075. {"+thorough",    ".thorough",    XrmoptionNoArg,        (caddr_t) "off"},
  1076. {"-mgs",    ".magnifierSize1",XrmoptionSepArg,    (caddr_t) NULL},
  1077. {"-mgs1",    ".magnifierSize1",XrmoptionSepArg,    (caddr_t) NULL},
  1078. {"-mgs2",    ".magnifierSize2",XrmoptionSepArg,    (caddr_t) NULL},
  1079. {"-mgs3",    ".magnifierSize3",XrmoptionSepArg,    (caddr_t) NULL},
  1080. {"-mgs4",    ".magnifierSize4",XrmoptionSepArg,    (caddr_t) NULL},
  1081. {"-mgs5",    ".magnifierSize5",XrmoptionSepArg,    (caddr_t) NULL},
  1082. };
  1083.  
  1084. static    XtResource    resources[] = {
  1085. {"debugLevel", "DebugLevel", XtRString, sizeof(char *),
  1086.   (Cardinal) &debug_arg, XtRString, NULL},
  1087. {"gotoPage", "GotoPage", XtRString, sizeof(char *),
  1088.   (Cardinal) &curr_page, XtRString, NULL},
  1089. {"shrinkFactor", "ShrinkFactor", XtRInt, sizeof(int),
  1090.   (Cardinal) &shrink_factor, XtRInt, (caddr_t) &shrink_factor},
  1091. {"densityPercent", "DensityPercent", XtRInt, sizeof(int),
  1092.   (Cardinal) &density, XtRInt, (caddr_t) &density},
  1093. {"pixelsPerInch", "PixelsPerInch", XtRInt, sizeof(int),
  1094.   (Cardinal) &pixels_per_inch, XtRInt, (caddr_t) &pixels_per_inch},
  1095. {"margins", "Margin", XtRString, sizeof(char *),
  1096.   (Cardinal) &margins, XtRString, NULL},
  1097. {"sideMargin", "Margin", XtRString, sizeof(char *),
  1098.   (Cardinal) &sidemargin, XtRString, NULL},
  1099. {"topMargin", "Margin", XtRString, sizeof(char *),
  1100.   (Cardinal) &topmargin, XtRString, NULL},
  1101. {"listFonts", "ListFonts", XtRBoolean, sizeof(Boolean),
  1102.   (Cardinal) &list_fonts, XtRBoolean, (caddr_t) &list_fonts},
  1103. {"reverseVideo", "ReverseVideo", XtRBoolean, sizeof(Boolean),
  1104.   (Cardinal) &reverse, XtRBoolean, (caddr_t) &reverse},
  1105. {"foreground", "Foreground", XtRPixel, sizeof(Pixel),
  1106.   (Cardinal)&fore_args.value, XtRPixel, (caddr_t) &fore_args.value},
  1107. {"foreground", "Foreground", XtRString, sizeof(char *),
  1108.   (Cardinal)&fore_color, XtRString, NULL},
  1109. {"background", "Background", XtRPixel, sizeof(Pixel),
  1110.   (Cardinal)&back_args.value, XtRPixel, (caddr_t) &back_args.value},
  1111. {"background", "Background", XtRString, sizeof(char *),
  1112.   (Cardinal)&back_color, XtRString, NULL},
  1113. {"highlight", "Highlight", XtRColor, sizeof(XColor),
  1114.   (Cardinal)&hl_Color, XtRColor, (caddr_t) &hl_Color},
  1115. {"highlight", "Highlight", XtRString, sizeof(char *),
  1116.   (Cardinal)&high_color, XtRString, NULL},
  1117. {"cursorColor", "CursorColor", XtRColor, sizeof(XColor),
  1118.   (Cardinal)&cr_Color, XtRColor, (caddr_t) &cr_Color},
  1119. {"cursorColor", "CursorColor", XtRString, sizeof(char *),
  1120.   (Cardinal)&curs_color, XtRString, NULL},
  1121. {"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
  1122.   (Cardinal)&icon_geometry, XtRString, (caddr_t) NULL},
  1123. {"thorough", "Thorough", XtRBoolean, sizeof(Boolean),
  1124.   (Cardinal)&thorough, XtRBoolean, (caddr_t) &thorough},
  1125. {"magnifierSize1", "MagnifierSize", XtRInt, sizeof(int),
  1126.   (Cardinal) &mg_size[0], XtRInt, (caddr_t) &mg_size[0]},
  1127. {"magnifierSize2", "MagnifierSize", XtRInt, sizeof(int),
  1128.   (Cardinal) &mg_size[1], XtRInt, (caddr_t) &mg_size[1]},
  1129. {"magnifierSize3", "MagnifierSize", XtRInt, sizeof(int),
  1130.   (Cardinal) &mg_size[2], XtRInt, (caddr_t) &mg_size[2]},
  1131. {"magnifierSize4", "MagnifierSize", XtRInt, sizeof(int),
  1132.   (Cardinal) &mg_size[3], XtRInt, (caddr_t) &mg_size[3]},
  1133. {"magnifierSize5", "MagnifierSize", XtRInt, sizeof(int),
  1134.   (Cardinal) &mg_size[4], XtRInt, (caddr_t) &mg_size[4]},
  1135. };
  1136.  
  1137. static    void
  1138. set_draw_args() {
  1139.     draw_args[0].value = (XtArgVal) page_w;
  1140.     draw_args[1].value = (XtArgVal) page_h;
  1141. }
  1142.  
  1143. static    Arg    temp_args1[] = {
  1144.     {XtNiconX,    (XtArgVal) 0},
  1145.     {XtNiconY,    (XtArgVal) 0},
  1146. };
  1147.  
  1148. static    Arg    temp_args2 = {XtNborderWidth,    (XtArgVal) &bwidth};
  1149.  
  1150. static    Arg    temp_args3[] = {
  1151.     {XtNwidth,    (XtArgVal) 0},
  1152.     {XtNheight,    (XtArgVal) 0},
  1153.     {XtNiconPixmap,    (XtArgVal) 0},
  1154. };
  1155.  
  1156. /*
  1157.  *    X11 main program
  1158.  */
  1159.  
  1160. main(argc, argv)
  1161.     int argc;
  1162.     char **argv;
  1163. {
  1164.     prog = *argv;
  1165.     if (*prog == '/') prog = rindex(prog, '/') + 1;
  1166.  
  1167.     top_level = XtInitialize(prog, "XDvi", options, XtNumber(options),
  1168.         &argc, argv);
  1169.     if (argc != 2) usage();
  1170.     dvi_name = argv[1];
  1171.  
  1172.     XtGetApplicationResources(top_level, (caddr_t) NULL, resources,
  1173.         XtNumber(resources), NULL, 0);
  1174.     if (shrink_factor <= 0 || density <= 0 || pixels_per_inch <= 0) usage();
  1175.     if (shrink_factor != 1) bak_shrink = shrink_factor;
  1176.     mane.shrinkfactor = shrink_factor;
  1177.     specialConv = pixels_per_inch / 1000.0;
  1178.     if (debug_arg != NULL)
  1179.         debug = isdigit(*debug_arg) ? atoi(debug_arg) : DBG_ALL;
  1180.     if (margins) home_x = home_y = atof(margins) * pixels_per_inch;
  1181.     if (sidemargin) home_x = atof(sidemargin) * pixels_per_inch;
  1182.     if (topmargin) home_y = atof(topmargin) * pixels_per_inch;
  1183.         /* The following code is lifted from Xterm */
  1184.     DISP = XtDisplay(top_level);
  1185.     SCRN = XtScreen(top_level);
  1186.     if (icon_geometry != NULL) {
  1187.         int scr, junk;
  1188.  
  1189.         for(scr = 0;    /* yyuucchh */
  1190.         SCRN != ScreenOfDisplay(DISP, scr);
  1191.         scr++);
  1192.  
  1193.         temp_args1[0].name = XtNiconX;
  1194.         temp_args1[1].name = XtNiconY;
  1195.         XGeometry(DISP, scr, icon_geometry, "", 0, 0, 0, 0, 0,
  1196.               &temp_args1[0].value, &temp_args1[1].value, &junk, &junk);
  1197.         XtSetValues(top_level, temp_args1, 2);
  1198.     }
  1199.  
  1200.     if ((font_path = getenv(FONT_PATH)) == NULL)
  1201.         font_path = default_font_path;
  1202.     else if (*font_path == ':')
  1203.         /*concatenate default_font_path before font_path */
  1204.         font_path = strcat(strcpy(malloc((unsigned)
  1205.         strlen(default_font_path) + strlen(font_path) + 1),
  1206.         default_font_path), font_path);
  1207.  
  1208.     open_dvi_file();
  1209.     if (curr_page) {
  1210.         current_page = (*curr_page ? atoi(curr_page) : total_pages) - 1;
  1211.         if (current_page < 0 || current_page >= total_pages) usage();
  1212.     }
  1213.  
  1214.         /* Set default window size and icon */
  1215.     XtGetValues(top_level, &temp_args2, 1);    /* get border width */
  1216.     screen_w = WidthOfScreen(SCRN) - 2*bwidth;
  1217.     screen_h = HeightOfScreen(SCRN) - 2*bwidth;
  1218.     temp_args3[0].value = (XtArgVal) (page_w<screen_w ? page_w : screen_w);
  1219.     temp_args3[1].value = (XtArgVal) (page_h<screen_h ? page_h : screen_h);
  1220.     temp_args3[2].value = (XtArgVal) (XCreateBitmapFromData(DISP,
  1221.                 RootWindowOfScreen(SCRN),
  1222.                 xdvi_bits, xdvi_width, xdvi_height));
  1223.     XtSetValues(top_level, temp_args3, 3);
  1224.  
  1225.     vport_widget = XtCreateManagedWidget("vport", viewportWidgetClass,
  1226.         top_level, vport_args, XtNumber(vport_args));
  1227.     clip_widget = XtNameToWidget(vport_widget, "clip");
  1228.     set_draw_args();
  1229.     draw_widget = XtCreateManagedWidget("drawing", simpleWidgetClass,
  1230.         vport_widget, draw_args, XtNumber(draw_args));
  1231.     XtAddEventHandler(vport_widget, KeyPressMask, 0, handle_key,
  1232.         (caddr_t) NULL);
  1233.     XtAddEventHandler(draw_widget, ExposureMask, GraphicsExpose, handle_exp,
  1234.         (caddr_t) &mane);
  1235.     XtAddEventHandler(draw_widget, ButtonPressMask, 0, handle_button,
  1236.         (caddr_t) NULL);
  1237.     XtAddEventHandler(draw_widget, ButtonReleaseMask, 0, handle_release,
  1238.         (caddr_t) NULL);
  1239.     XtRealizeWidget(top_level);
  1240.     curr.win = mane.win = XtWindow(draw_widget);
  1241.     /* unmapped = True;    (it was initialized this way) */
  1242.     home();            /* no need to unmap at this stage */
  1243.     unmapped = False;
  1244.  
  1245.     if (reverse) {
  1246.         if (!fore_color) fore_args.value = WhitePixelOfScreen(SCRN);
  1247.         if (!back_color) back_args.value = BlackPixelOfScreen(SCRN);
  1248.         fore_color = back_color = (char *)1;    /* nonzero */
  1249.     } else {
  1250.         if (!fore_color) fore_args.value = BlackPixelOfScreen(SCRN);
  1251.         if (!back_color) back_args.value = WhitePixelOfScreen(SCRN);
  1252.     }
  1253.     if (fore_color) XtSetValues(draw_widget, &fore_args, 1);
  1254.     if (back_color) {
  1255.         XtSetValues(draw_widget, &back_args, 1);
  1256.         XtSetValues(clip_widget, &back_args, 1);
  1257.     }
  1258.     {
  1259.         XGCValues    values;
  1260.         Pixel    set_bits = (Pixel) (fore_args.value & ~back_args.value);
  1261.         Pixel    clr_bits = (Pixel) (back_args.value & ~fore_args.value);
  1262. #define    MakeGC(fcn, fg, bg)    (values.function = fcn, values.foreground=fg,\
  1263.         values.background=bg,\
  1264.         XCreateGC(DISP, RootWindowOfScreen(SCRN),\
  1265.             GCFunction|GCForeground|GCBackground, &values))
  1266.  
  1267.         if (set_bits && clr_bits)
  1268.         ruleGC = MakeGC(GXcopy, fore_args.value, back_args.value);
  1269.         if (!thorough && ruleGC) {
  1270.         foreGC = ruleGC;
  1271.         puts("Note:  overstrike characters may be incorrect.");
  1272.         }
  1273.         else {
  1274.         if (set_bits) foreGC = MakeGC(GXor, set_bits, 0);
  1275.         if (clr_bits)
  1276.             *(foreGC ? &foreGC2 : &foreGC) =
  1277.             MakeGC(GXandInverted, clr_bits, 0);
  1278.         if (!ruleGC) ruleGC = foreGC;
  1279.         }
  1280.         highGC = ruleGC;
  1281.         if (high_color)
  1282.         highGC = MakeGC(GXcopy, hl_Color.pixel, back_args.value);
  1283.     }
  1284.  
  1285.     ready_cursor = XCreateFontCursor(DISP, XC_cross);
  1286.     redraw_cursor = XCreateFontCursor(DISP, XC_watch);
  1287.     if (!curs_color)
  1288.         if (high_color) cr_Color = hl_Color;
  1289.         else {
  1290.         cr_Color.pixel = fore_args.value;
  1291.         XQueryColor(DISP, DefaultColormapOfScreen(SCRN), &cr_Color);
  1292.         }
  1293.     {
  1294.         XColor bg_Color;
  1295.         bg_Color.pixel = back_args.value;
  1296.         XQueryColor(DISP, DefaultColormapOfScreen(SCRN), &bg_Color);
  1297.         XRecolorCursor(DISP, ready_cursor, &cr_Color, &bg_Color);
  1298.         XRecolorCursor(DISP, redraw_cursor, &cr_Color, &bg_Color);
  1299.     }
  1300.  
  1301.     image = XCreateImage(DISP, DefaultVisualOfScreen(SCRN), 1, XYBitmap, 0,
  1302.                  (char *)NULL, 0, 0, BITS_PER_BMUNIT, 0);
  1303.     image->bitmap_unit = BITS_PER_BMUNIT;
  1304. #ifndef    MSBITFIRST
  1305.     image->bitmap_bit_order = LSBFirst;
  1306. #else    MSBITFIRST
  1307.     image->bitmap_bit_order = MSBFirst;
  1308. #endif    MSBITFIRST
  1309.     {
  1310.         short endian = (MSBFirst << 8) + LSBFirst;
  1311.         image->byte_order = *((char *) &endian);
  1312.     }
  1313.  
  1314.     do_pages();
  1315. }
  1316.  
  1317. #else X10
  1318. static    char    *display;
  1319. static    char    *brdr_color;
  1320. static    char    *geometry;
  1321.  
  1322. static    struct option {
  1323.     char    *name;
  1324.     char    *resource;
  1325.     enum    {FalseArg, TrueArg, StickyArg, SepArg} argclass;
  1326.     enum    {BooleanArg, StringArg, NumberArg} argtype;
  1327.     caddr_t    address;
  1328. }    options[] = {
  1329.         /* the display option MUST be first */
  1330. {"-display",    NULL,        SepArg,    StringArg,    (caddr_t) &display},
  1331. {"-d",        "debugLevel",    SepArg,    StringArg,    (caddr_t) &debug_arg},
  1332. {"+",        NULL,        StickyArg, StringArg,    (caddr_t) &curr_page},
  1333. {"-s",        "shrinkFactor", SepArg, NumberArg,    (caddr_t) &shrink_factor},
  1334. {"-S",        "densityPercent", SepArg, NumberArg,    (caddr_t) &density},
  1335. {"-p",        "pixelsPerInch", SepArg, NumberArg,    (caddr_t) &pixels_per_inch},
  1336. {"-margins",    "margins",    SepArg,    StringArg,    (caddr_t) &margins},
  1337. {"-sidemargin",    "sideMargin",    SepArg,    StringArg,    (caddr_t) &sidemargin},
  1338. {"-topmargin",    "topMargin",    SepArg,    StringArg,    (caddr_t) &topmargin},
  1339. {"-l",        "listFonts",    TrueArg, BooleanArg,    (caddr_t) &list_fonts},
  1340. {"+l",        NULL,        FalseArg, BooleanArg,    (caddr_t) &list_fonts},
  1341. {"-rv",        "reverseVideo",    TrueArg, BooleanArg,    (caddr_t) &reverse},
  1342. {"+rv",        NULL,        FalseArg, BooleanArg,    (caddr_t) &reverse},
  1343. {"-bw",        "borderWidth",    SepArg,    NumberArg,    (caddr_t) &bwidth},
  1344. {"-borderwidth", NULL,        SepArg,    NumberArg,    (caddr_t) &bwidth},
  1345. {"-fg",        "foreground",    SepArg,    StringArg,    (caddr_t) &fore_color},
  1346. {"-foreground",    NULL,        SepArg,    StringArg,    (caddr_t) &fore_color},
  1347. {"-bg",        "background",    SepArg,    StringArg,    (caddr_t) &back_color},
  1348. {"-background",    NULL,        SepArg,    StringArg,    (caddr_t) &back_color},
  1349. {"-hl",        "highlight",    SepArg,    StringArg,    (caddr_t) &high_color},
  1350. {"-bd",        "borderColor",    SepArg,    StringArg,    (caddr_t) &brdr_color},
  1351. {"-cr",        "cursorColor",    SepArg,    StringArg,    (caddr_t) &curs_color},
  1352. {"-geometry",    "geometry",    SepArg,    StringArg,    (caddr_t) &geometry},
  1353. {"=",        NULL,        StickyArg, StringArg,    (caddr_t) &geometry},
  1354. {"-mgs",    NULL,        SepArg, NumberArg,    (caddr_t) &mg_size[0]},
  1355. {"-mgs1",    "magnifierSize1",SepArg, NumberArg,    (caddr_t) &mg_size[0]},
  1356. {"-mgs2",    "magnifierSize2",SepArg, NumberArg,    (caddr_t) &mg_size[1]},
  1357. {"-mgs3",    "magnifierSize3",SepArg, NumberArg,    (caddr_t) &mg_size[2]},
  1358. };
  1359.  
  1360. /*
  1361.  *    X10 main program
  1362.  */
  1363.  
  1364. main(argc, argv)
  1365.     int argc;
  1366.     char **argv;
  1367. {
  1368.     char    **arg;
  1369.     char    **argvend = argv + argc;
  1370.     char    *optstring;
  1371.     caddr_t    addr;
  1372.     struct option *opt, *candidate;
  1373.     int    len1, len2, matchlen;
  1374.     OpaqueFrame frame;
  1375.     char    def[32];
  1376.     int    mouspix;
  1377.     Color    cdef;
  1378.  
  1379.     prog = *argv;
  1380.     if (*prog == '/') prog = rindex(prog, '/') + 1;
  1381. /*
  1382.  *    Process the option table.  This is not guaranteed for all possible
  1383.  *    option tables, but at least it works for this one.
  1384.  */
  1385.     for (arg = argv + 1; arg < argvend; ++arg) {
  1386.         len1 = strlen(*arg);
  1387.         candidate = NULL;
  1388.         matchlen = 0;
  1389.         for (opt = options; opt < options + XtNumber(options); ++opt) {
  1390.         len2 = strlen(opt->name);
  1391.         if (opt->argclass == StickyArg) {
  1392.             if (matchlen <= len2 && !strncmp(*arg, opt->name, len2)) {
  1393.             candidate = opt;
  1394.             matchlen = len2;
  1395.             }
  1396.         }
  1397.         else if (len1 <= len2 && matchlen <= len1 &&
  1398.             !strncmp(*arg, opt->name, len1)) {
  1399.             if (len1 == len2) {
  1400.             candidate = opt;
  1401.             break;
  1402.             }
  1403.             if (matchlen < len1) candidate = opt;
  1404.             else if (candidate && candidate->argclass != StickyArg)
  1405.             candidate = NULL;
  1406.             matchlen = len1;
  1407.         }
  1408.         }
  1409.         if (candidate == NULL) {
  1410.         if (**arg == '-') usage();
  1411.         if (index(*arg, ':') != NULL) {    /* display */
  1412.             --arg;
  1413.             candidate = options;
  1414.         }
  1415.         else if (dvi_name) usage();
  1416.         else {
  1417.             dvi_name = *arg;
  1418.             continue;
  1419.         }
  1420.         }
  1421.         addr = candidate->address;
  1422.         for (opt = options; opt < options + XtNumber(options); ++opt)
  1423.         if (opt->address == addr) opt->resource = NULL;
  1424.         switch (candidate->argclass) {
  1425.         case FalseArg:    *((Boolean *) addr) = False; break;
  1426.         case TrueArg:    *((Boolean *) addr) = True; break;
  1427.         case StickyArg:    optstring = *arg + strlen(candidate->name);
  1428.             break;
  1429.         case SepArg:
  1430.             ++arg;
  1431.             if (arg >= argvend) usage();
  1432.             optstring = *arg;
  1433.             break;
  1434.         }
  1435.         switch (candidate->argtype) {
  1436.         case StringArg:    *((char **) addr) = optstring; break;
  1437.         case NumberArg:    *((int *) addr) = atoi(optstring); break;
  1438.         }
  1439.     }
  1440.  
  1441.     if (XOpenDisplay(display) == NULL)
  1442.         oops("Can't open display\n");
  1443.     for (opt = options; opt < options + XtNumber(options); ++opt)
  1444.         if (opt->resource && (optstring = XGetDefault(prog, opt->resource)))
  1445.         switch (opt->argtype) {
  1446.             case StringArg:
  1447.             *((char **) opt->address) = optstring;
  1448.             break;
  1449.             case NumberArg:
  1450.             *((int *) opt->address) = atoi(optstring);
  1451.             break;
  1452.             case BooleanArg:
  1453.             *((Boolean *) opt->address) =
  1454.                 (strcmp(optstring, "on") == 0);
  1455.         }
  1456.  
  1457.     if (shrink_factor <= 0 || density <= 0 || pixels_per_inch <= 0 ||
  1458.         dvi_name == NULL) usage();
  1459.     if (shrink_factor != 1) bak_shrink = shrink_factor;
  1460.     mane.shrinkfactor = shrink_factor;
  1461.     if (debug_arg != NULL)
  1462.         debug = isdigit(*debug_arg) ? atoi(debug_arg) : DBG_ALL;
  1463.     if (margins) home_x = home_y = atof(margins) * pixels_per_inch;
  1464.     if (sidemargin) home_x = atof(sidemargin) * pixels_per_inch;
  1465.     if (topmargin) home_y = atof(topmargin) * pixels_per_inch;
  1466.  
  1467.     if ((font_path = getenv(FONT_PATH)) == NULL)
  1468.         font_path = default_font_path;
  1469.     else if (*font_path == ':')
  1470.         /*concatenate default_font_path before font_path */
  1471.         font_path = strcat(strcpy(malloc((unsigned)
  1472.         strlen(default_font_path) + strlen(font_path) + 1),
  1473.         default_font_path), font_path);
  1474.  
  1475.     open_dvi_file();
  1476.     if (curr_page) {
  1477.         current_page = (*curr_page ? atoi(curr_page) : total_pages) - 1;
  1478.         if (current_page < 0 || current_page >= total_pages) usage();
  1479.     }
  1480.  
  1481.     if (reverse) {
  1482.         foreGC = WhitePixel;
  1483.         highGC = WhitePixel;
  1484.         backpix = BlackPixel;
  1485.         backmap = BlackPixmap;
  1486.         bdrmap = WhitePixmap;
  1487.         mouspix = WhitePixel;
  1488.         GXfunc = GXor;
  1489.     } else {
  1490.         foreGC = BlackPixel;
  1491.         highGC = BlackPixel;
  1492.         backpix = WhitePixel;
  1493.         backmap = WhitePixmap;
  1494.         bdrmap = BlackPixmap;
  1495.         mouspix = BlackPixel;
  1496.         GXfunc = GXand;
  1497.     }
  1498.     if (DisplayCells() > 2) {
  1499.         if (fore_color && XParseColor(fore_color, &cdef) &&
  1500.             XGetHardwareColor(&cdef))
  1501.             foreGC = cdef.pixel;
  1502.         if (back_color && XParseColor(back_color, &cdef) &&
  1503.             XGetHardwareColor(&cdef)) {
  1504.             backpix = cdef.pixel;
  1505.             backmap = XMakeTile(backpix);
  1506.         }
  1507.         if (high_color && XParseColor(high_color, &cdef) &&
  1508.             XGetHardwareColor(&cdef))
  1509.             highGC = cdef.pixel;
  1510.         if (brdr_color && XParseColor(brdr_color, &cdef) &&
  1511.             XGetHardwareColor(&cdef))
  1512.             bdrmap = XMakeTile(cdef.pixel);
  1513.         if (curs_color && XParseColor(curs_color, &cdef) &&
  1514.             XGetHardwareColor(&cdef))
  1515.             mouspix = cdef.pixel;
  1516.     }
  1517.  
  1518.     frame.bdrwidth = bwidth;
  1519.     screen_w = DisplayWidth() - 2*bwidth;
  1520.     screen_h = DisplayHeight() - 2*bwidth;
  1521.     frame.width = (page_w < screen_w ? page_w : screen_w);
  1522.     frame.height = (page_h < screen_h ? page_h : screen_h);
  1523.     frame.border = bdrmap;
  1524.     frame.background = backmap;
  1525.     frame.x = 0;
  1526.     frame.y = 0;
  1527.     Sprintf(def, "=%dx%d+0+0", frame.width, frame.height);
  1528.     mane.win = XCreate("DVI Previewer", prog, geometry, def,
  1529.         &frame, 50, 50);
  1530.     window_w = frame.width;
  1531.     window_h = frame.height;
  1532.     XSelectInput(mane.win,
  1533.         KeyPressed|ButtonPressed|ButtonReleased|
  1534.         ExposeWindow|ExposeRegion);
  1535.     XMapWindow(mane.win);
  1536.     XDefineCursor(mane.win,
  1537.         XCreateCursor(xdvi_width, xdvi_height, xdvi_bits, xdvi_mask_bits,
  1538.               xdvi_x_hot, xdvi_y_hot, mouspix, backpix, GXcopy));
  1539.     do_pages();
  1540. }
  1541. #endif X10
  1542.