home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume17 / xdvi / part04a < prev    next >
Encoding:
Text File  |  1992-03-22  |  50.2 KB  |  1,914 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!zaphod.mps.ohio-state.edu!mips!msi!dcmartin
  3. From: vojta@powdermilk.berkeley.edu (Paul Vojta)
  4. Subject: v17i040: xdvi, dvi previewer, Part04/05, Part01/02
  5. Message-ID: <1992Mar23.190000.18799@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. Date: Mon, 23 Mar 1992 19:00:00 GMT
  10. Approved: dcmartin@msi.com
  11.  
  12. [ Sorry for the problem on this one.. it was over 64k bytes, and 
  13.   I needed to split it up. If your unshar program has problems, you
  14.   might just want to use /bin/sh - dcm ]
  15.  
  16. Submitted-by: vojta@powdermilk.berkeley.edu (Paul Vojta)
  17. Posting-number: Volume 17, Issue 40
  18. Archive-name: xdvi/part04a
  19.  
  20. # This is a shell archive (produced by shar 3.49)
  21. # To extract the files from this archive, save it to a file, remove
  22. # everything above the "!/bin/sh" line above, and type "sh file_name".
  23. #
  24. # made 03/23/1992 18:56 UTC by dcmartin@fascet
  25. # Source directory /n/merlin/u2/ftp/pub/comp.sources.x/volume17/xdvi
  26. #
  27. # existing files will NOT be overwritten unless -c is specified
  28. #
  29. # This is part 1 of a multipart archive                                    
  30. # do not concatenate these parts, unpack them in order with /bin/sh        
  31. #
  32. # This shar contains:
  33. # length  mode       name
  34. # ------ ---------- ------------------------------------------
  35. #  79591 -rw-r--r-- xdvi.c
  36. #
  37. if test -r _shar_seq_.tmp; then
  38.     echo 'Must unpack archives in sequence!'
  39.     echo Please unpack part `cat _shar_seq_.tmp` next
  40.     exit 1
  41. fi
  42. # ============= xdvi.c ==============
  43. if test -f 'xdvi.c' -a X"$1" != X"-c"; then
  44.     echo 'x - skipping xdvi.c (File already exists)'
  45.     rm -f _shar_wnt_.tmp
  46. else
  47. > _shar_wnt_.tmp
  48. echo 'x - extracting xdvi.c (Text)'
  49. sed 's/^X//' << 'SHAR_EOF' > 'xdvi.c' &&
  50. /*
  51. X * DVI previewer for X.
  52. X *
  53. X * Eric Cooper, CMU, September 1985.
  54. X *
  55. X * Code derived from dvi-imagen.c.
  56. X *
  57. X * Modification history:
  58. X * 1/1986    Modified for X.10 by Bob Scheifler, MIT LCS.
  59. X * 7/1988    Modified for X.11 by Mark Eichin, MIT
  60. X * 12/1988    Added 'R' option, toolkit, magnifying glass
  61. X *            --Paul Vojta, UC Berkeley.
  62. X * 2/1989    Added tpic support    --Jeffrey Lee, U of Toronto
  63. X * 4/1989    Modified for System V by Donald Richardson, Clarkson Univ.
  64. X * 3/1990    Added VMS support    --Scott Allendorf, U of Iowa
  65. X *
  66. X *    Compilation options:
  67. X *    SYSV    compile for System V
  68. X *    VMS    compile for VMS
  69. X *    X10    compile for X10
  70. X *    NOTOOL    compile without toolkit (X11 only)
  71. X *    BUTTONS    compile with buttons on the side of the window (needs toolkit)
  72. X *    MSBITFIRST    store bitmaps internally with most significant bit first
  73. X *    BMSHORT    store bitmaps in shorts instead of bytes
  74. X *    BMLONG    store bitmaps in longs instead of bytes
  75. X *    ALTFONT    default for -altfont option
  76. X *    A4    use European size paper
  77. X */
  78. X
  79. #ifndef    ALTFONT
  80. #define    ALTFONT    "cmr10"
  81. #endif
  82. X
  83. #ifndef    A4
  84. #define    DEFAULT_PAPER        "us"
  85. #else
  86. #define    DEFAULT_PAPER        "a4"
  87. #endif
  88. X
  89. #if    !defined(X10) && !defined(NOTOOL)
  90. #define    TOOLKIT
  91. #else
  92. #undef    TOOLKIT
  93. #undef    BUTTONS
  94. #endif
  95. X
  96. #include <ctype.h>
  97. X
  98. #define    EXTERN
  99. #define    INIT(x)    =x
  100. #include "xdvi.h"
  101. X
  102. #ifndef lint
  103. #include "patchlevel.h"
  104. static    struct {_Xconst char    a[36], b, c, d;}
  105. #ifndef X10
  106. X    header = {"$Header: xdvi.c (X11), patchlevel = ", '0' + PATCHLEVEL / 10,
  107. X        '0' + PATCHLEVEL % 10, 0};
  108. #else
  109. X    header = {"$Header: xdvi.c (X10), patchlevel = ", '0' + PATCHLEVEL / 10,
  110. X        '0' + PATCHLEVEL % 10, 0};
  111. #endif
  112. #endif    /* lint */
  113. X
  114. #ifndef    X_NOT_STDC_ENV
  115. #include <stdlib.h>
  116. #endif
  117. X
  118. #ifndef X10
  119. /* Xlib is already included */
  120. #include <X11/Xutil.h>
  121. #include <X11/cursorfont.h>
  122. #include <X11/keysym.h>
  123. #include "xdvi.icon"
  124. #endif /* X10 */
  125. X
  126. #ifdef    TOOLKIT
  127. #undef Boolean
  128. #include <X11/Intrinsic.h>
  129. #ifdef OLD_X11_TOOLKIT
  130. #include <X11/Atoms.h>
  131. #else /* not OLD_X11_TOOLKIT */
  132. #include <X11/Xatom.h>
  133. #include <X11/StringDefs.h>
  134. #endif /* not OLD_X11_TOOLKIT */
  135. #include <X11/Shell.h>    /* needed for def. of XtNiconX */
  136. #ifndef    XtSpecificationRelease
  137. #define    XtSpecificationRelease    0
  138. #endif
  139. #if    XtSpecificationRelease >= 4
  140. #include <X11/Xaw/Viewport.h>
  141. #ifdef    BUTTONS
  142. #include <X11/Xaw/Command.h>
  143. #endif
  144. #else    /* XtSpecificationRelease < 4 */
  145. #include <X11/Viewport.h>
  146. #ifdef    BUTTONS
  147. #include <X11/Command.h>
  148. #endif
  149. #endif    /* XtSpecificationRelease */
  150. #else    /* !TOOLKIT */
  151. #define    XtNumber(arr)    (sizeof(arr)/sizeof(arr[0]))
  152. typedef    int        Position;
  153. typedef    unsigned int    Dimension;
  154. #ifndef X10
  155. typedef    unsigned int    Pixel;
  156. #define    XtPending()    XPending(DISP)
  157. #else
  158. #define    XtPending    XPending
  159. #define    XMoveResizeWindow XConfigureWindow
  160. #endif
  161. #endif    /* TOOLKIT */
  162. X
  163. #ifdef    HAS_SIGIO
  164. #include <fcntl.h>
  165. #include <signal.h>
  166. #endif
  167. X
  168. #ifndef X10
  169. static    Display    *DISP;
  170. #define    DPY    DISP,
  171. static    Screen    *SCRN;
  172. static    Cursor    redraw_cursor, ready_cursor;
  173. X
  174. #ifdef    VMS
  175. /*
  176. X * Magnifying glass cursor
  177. X *
  178. X * Developed by Tom Sawyer, April 1990
  179. X * Contibuted by Hunter Goatley, January 1991
  180. X *
  181. X */
  182. X
  183. #define mag_glass_width 16
  184. #define mag_glass_height 16
  185. #define mag_glass_x_hot 6
  186. #define mag_glass_y_hot 6
  187. static char mag_glass_bits[] = {
  188. X    0xf8, 0x03, 0x0c, 0x06, 0xe2, 0x09, 0x13, 0x1a, 0x01, 0x14, 0x01, 0x14,
  189. X    0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x03, 0x10, 0x02, 0x18, 0x0c, 0x34,
  190. X    0xf8, 0x6f, 0x00, 0xd8, 0x00, 0xb0, 0x00, 0xe0
  191. };
  192. #include <decw$cursor.h>    /* Include the DECWindows cursor symbols */
  193. static    int    DECWCursorFont;    /* Space for the DECWindows cursor font  */
  194. static    Pixmap    MagnifyPixmap;    /* Pixmap to hold our special mag-glass  */
  195. #endif    /* VMS */
  196. X
  197. #define    SetCursor(x)    XDefineCursor(DISP, WINDOW(mane), x)
  198. #define    ClearPage(wr)    XClearWindow(DISP, WINDOW(wr));
  199. #define    ClearArea(win, x, y, w, h)    XClearArea(DISP, win, x, y, w, h, False)
  200. #define    DarkenArea(win, x, y, w, h) \
  201. X            XFillRectangle(DISP, win, ruleGC, x, y, w, h)
  202. #define    CopyArea(win, x, y, w, h, x2, y2) \
  203. X            XCopyArea(DISP, win, win, DefaultGCOfScreen(SCRN), \
  204. X                x, y, w, h, x2, y2)
  205. #define    Flush()        XFlush(DISP)
  206. #ifndef X11HEIGHT
  207. #define    X11HEIGHT    8    /* Height of server default font */
  208. #endif
  209. #else    /* X10 */
  210. #define    DPY
  211. #define    GC        int
  212. #define    SetCursor(x)
  213. #define    ClearPage(wr)    XClear(WINDOW(wr));
  214. #define    ClearArea(win, x, y, w, h)    XPixSet(win, x, y, w, h, backpix)
  215. #define    DarkenArea(win, x, y, w, h)    XPixSet(win, x, y, w, h, foreGC)
  216. #define    CopyArea(win, x, y, w, h, x2, y2) \
  217. X            XMoveArea(win, x, y, x2, y2, w, h, GXcopy);
  218. #define    XBell(a,b)    XFeep(b/10-1)
  219. #define    Flush()        XFlush()
  220. #define    ConnectionNumber(DISP)    (_XlibCurrentDisplay->fd)
  221. #ifndef X10FONT
  222. #define    X10FONT    "helv10b"    /* Font for X10 error messages */
  223. #define    X10HEIGHT    10
  224. #endif
  225. #endif    /* X10 */
  226. X
  227. #define    MAGBORD    1    /* border size for magnifier */
  228. X
  229. /*
  230. X * Command line flags.
  231. X */
  232. static    _Xconst    char    *paper        = DEFAULT_PAPER;
  233. static    char    *sidemargin, *topmargin;
  234. static    char    *xoffset, *yoffset;
  235. static    Boolean    reverse;
  236. static    Dimension    bwidth    = 2;
  237. static    int    bak_shrink;
  238. static    char    *debug_arg;
  239. static    int    mg_size[5] = {200, 350, 600, 900, 1200};
  240. static    char    *curr_page;
  241. X
  242. static    int    pageno_correct    = 1;
  243. static    Boolean    keep_flag    = False;
  244. #ifdef    BUTTONS
  245. Boolean    expert        = False;
  246. #endif
  247. X
  248. #ifndef X10
  249. #ifdef    TOOLKIT
  250. X        /* fg and bg colors */
  251. static    Arg    fore_args = {XtNforeground,    (XtArgVal) 0};
  252. #define    fore_Pixel    fore_args.value
  253. static    Arg    back_args = {XtNbackground,    (XtArgVal) 0};
  254. #define    back_Pixel    back_args.value
  255. #else    /* !TOOLKIT */
  256. static    Pixel    fore_Pixel, back_Pixel;
  257. #endif    /* TOOLKIT */
  258. static    Pixel    brdr_Pixel, hl_Pixel, cr_Pixel;
  259. #endif    /* X10 */
  260. X
  261. static    char    *fore_color;
  262. static    char    *back_color;
  263. static    char    *brdr_color;
  264. static    char    *high_color;
  265. static    char    *curs_color;
  266. static    GC    foreGC, highGC;
  267. #ifndef X10
  268. static    GC    ruleGC;
  269. static    GC    foreGC2;
  270. #else    /* X10 */
  271. #define    ruleGC    foreGC
  272. #endif    /* X10 */
  273. X
  274. #define    clip_w    mane.width
  275. #define    clip_h    mane.height
  276. static    Dimension    window_w, window_h;
  277. #ifndef X10
  278. static    Position    main_x, main_y;
  279. static    XImage    *image;
  280. #else    /* X10 */
  281. #define    main_x    0
  282. #define    main_y    0
  283. static    int    GXfunc;
  284. static    int    backpix, backmap, bdrmap;
  285. /*
  286. X * Cursor and mask for valid cursor
  287. X */
  288. #include "xdvi_curs.h"
  289. #include "xdvi_mask.h"
  290. #endif    /* X10 */
  291. X
  292. static    Position mag_x, mag_y, new_mag_x, new_mag_y;
  293. static    Boolean    mag_moved = False;
  294. static    int    home_x, home_y;
  295. static    int    min_x, max_x, min_y, max_y;
  296. X
  297. struct WindowRec mane    = {NULL, 3, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0};
  298. struct WindowRec alt    = {NULL, 1, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0};
  299. /*    currwin is temporary storage except for within redraw() */
  300. struct WindowRec currwin = {NULL, 3, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0};
  301. X
  302. #ifdef    TOOLKIT
  303. static    Widget    top_level, vport_widget, draw_widget, clip_widget;
  304. #ifdef    BUTTONS
  305. static    Widget    form_widget, line_widget, right_widget;
  306. #endif
  307. static    Widget    x_bar, y_bar;    /* horizontal and vertical scroll bars */
  308. X
  309. static    Arg    vport_args[] = {
  310. #ifdef    BUTTONS
  311. X    {XtNborderWidth, (XtArgVal) 0},
  312. X    {XtNtop,    (XtArgVal) XtChainTop},
  313. X    {XtNbottom,    (XtArgVal) XtChainBottom},
  314. X    {XtNleft,    (XtArgVal) XtChainLeft},
  315. X    {XtNright,    (XtArgVal) XtChainRight},
  316. #endif
  317. X    {XtNallowHoriz,    (XtArgVal) True},
  318. X    {XtNallowVert,    (XtArgVal) True},
  319. };
  320. X
  321. /*    Note:  Argument order in the following is important! */
  322. X
  323. static    Arg    draw_args[] = {
  324. X    {XtNwidth,    (XtArgVal) 0},
  325. X    {XtNheight,    (XtArgVal) 0},
  326. X    {XtNx,        (XtArgVal) 0},
  327. X    {XtNy,        (XtArgVal) 0},
  328. X    {XtNlabel,    (XtArgVal) ""},
  329. };
  330. X
  331. #ifdef    BUTTONS
  332. static    Arg    form_args[] = {
  333. X    {XtNdefaultDistance, (XtArgVal) 0},
  334. };
  335. #define    XTRA_WID    79
  336. X
  337. static    Arg    line_args[] = {
  338. X    {XtNbackground,    (XtArgVal) 0},
  339. X    {XtNwidth,    (XtArgVal) 1},
  340. X    {XtNheight,    (XtArgVal) 0},
  341. X    {XtNfromHoriz,    (XtArgVal) NULL},
  342. X    {XtNborderWidth, (XtArgVal) 0},
  343. X    {XtNtop,    (XtArgVal) XtChainTop},
  344. X    {XtNbottom,    (XtArgVal) XtChainBottom},
  345. X    {XtNleft,    (XtArgVal) XtChainRight},
  346. X    {XtNright,    (XtArgVal) XtChainRight},
  347. };
  348. X
  349. static    Arg    right_args[] = {
  350. X    {XtNfromHoriz,    (XtArgVal) NULL},
  351. X    {XtNwidth,    (XtArgVal) (XTRA_WID - 1)},
  352. X    {XtNheight,    (XtArgVal) 0},
  353. X    {XtNborderWidth, (XtArgVal) 0},
  354. X    {XtNtop,    (XtArgVal) XtChainTop},
  355. X    {XtNbottom,    (XtArgVal) XtChainBottom},
  356. X    {XtNleft,    (XtArgVal) XtChainRight},
  357. X    {XtNright,    (XtArgVal) XtChainRight},
  358. };
  359. X
  360. static    struct {
  361. X    _Xconst    char    *label;
  362. X    _Xconst    char    *name;
  363. X    int    closure;
  364. X    int    y_pos;
  365. X    }
  366. X    command_table[] = {
  367. X        {"Quit",    "quit",        'q',        50},
  368. X        {"Shrink1",    "sh1",        1 << 8 | 's',    150},
  369. X        {"Shrink2",    "sh2",        2 << 8 | 's',    200},
  370. X        {"Shrink3",    "sh3",        3 << 8 | 's',    250},
  371. X        {"Shrink4",    "sh4",        4 << 8 | 's',    300},
  372. X        {"Page-10",    "prev10",    10 << 8 | 'p',    400},
  373. X        {"Page-5",    "prev5",    5 << 8 | 'p',    450},
  374. X        {"Prev",    "prev",        'p',        500},
  375. X        {"Next",    "next",        'n',        600},
  376. X        {"Page+5",    "next5",    5 << 8 | 'n',    650},
  377. X        {"Page+10",    "next10",    10 << 8 | 'n',    700},
  378. };
  379. X
  380. static    void    handle_command();
  381. X
  382. static    XtCallbackRec    command_call[] = {
  383. X    {handle_command, NULL},
  384. X    {NULL,        NULL},
  385. };
  386. X
  387. static    Arg    command_args[] = {
  388. X    {XtNlabel,    NULL},
  389. X    {XtNx,        (XtArgVal) 6},
  390. X    {XtNy,        (XtArgVal) 0},
  391. X    {XtNwidth,    (XtArgVal) 64},
  392. X    {XtNheight,    (XtArgVal) 30},
  393. X    {XtNcallback,    (XtArgVal) command_call},
  394. };
  395. X
  396. #ifdef    NOQUERY
  397. #define    drawWidgetClass    widgetClass;
  398. #else
  399. X
  400. /* ARGSUSED */
  401. static    XtGeometryResult
  402. QueryGeometry(w, constraints, reply)
  403. X    Widget    w;
  404. X    XtWidgetGeometry *constraints, *reply;
  405. {
  406. X    reply->request_mode = CWWidth | CWHeight;
  407. X    reply->width = page_w;
  408. X    reply->height = page_h;
  409. X    return XtGeometryAlmost;
  410. }
  411. X
  412. #include <X11/IntrinsicP.h>
  413. #include <X11/CoreP.h>
  414. X
  415. X    /* if the following gives you trouble, just compile with -DNOQUERY */
  416. static    WidgetClassRec    drawingWidgetClass = {
  417. X  {
  418. X    /* superclass         */    &widgetClassRec,
  419. X    /* class_name         */    "Draw",
  420. X    /* widget_size        */    sizeof(WidgetRec),
  421. X    /* class_initialize   */    NULL,
  422. X    /* class_part_initialize*/  NULL,
  423. X    /* class_inited       */    FALSE,
  424. X    /* initialize         */    NULL,
  425. X    /* initialize_hook    */    NULL,
  426. X    /* realize            */    XtInheritRealize,
  427. X    /* actions            */    NULL,
  428. X    /* num_actions        */    0,
  429. X    /* resources          */    NULL,
  430. X    /* num_resources      */    0,
  431. X    /* xrm_class          */    NULLQUARK,
  432. X    /* compress_motion    */    FALSE,
  433. X    /* compress_exposure  */    TRUE,
  434. X    /* compress_enterleave*/    FALSE,
  435. X    /* visible_interest   */    FALSE,
  436. X    /* destroy            */    NULL,
  437. X    /* resize             */    XtInheritResize,
  438. X    /* expose             */    XtInheritExpose,
  439. X    /* set_values         */    NULL,
  440. X    /* set_values_hook    */    NULL,
  441. X    /* set_values_almost  */    XtInheritSetValuesAlmost,
  442. X    /* get_values_hook    */    NULL,
  443. X    /* accept_focus       */    XtInheritAcceptFocus,
  444. X    /* version            */    XtVersion,
  445. X    /* callback_offsets   */    NULL,
  446. X    /* tm_table           */    XtInheritTranslations,
  447. X    /* query_geometry       */  QueryGeometry,
  448. X    /* display_accelerator  */  XtInheritDisplayAccelerator,
  449. X    /* extension            */  NULL
  450. X  }
  451. };
  452. X
  453. #define    drawWidgetClass    &drawingWidgetClass
  454. X
  455. #endif    /* NOQUERY */
  456. X
  457. static    void
  458. create_buttons(h)
  459. X    XtArgVal    h;
  460. {
  461. X    int i;
  462. X
  463. X    line_args[2].value = h;
  464. X    line_args[3].value = (XtArgVal) vport_widget;
  465. X    line_widget = XtCreateManagedWidget("line", widgetClass, form_widget,
  466. X        line_args, XtNumber(line_args));
  467. X    right_args[0].value = (XtArgVal) line_widget;
  468. X    right_args[2].value = h;
  469. X    right_widget = XtCreateManagedWidget("right", compositeWidgetClass,
  470. X        form_widget, right_args, XtNumber(right_args));
  471. X
  472. X    command_args[2].value = (XtArgVal) vport_widget;
  473. X    for (i = 0; i < XtNumber(command_table); ++i) {
  474. X        command_args[0].value = (XtArgVal) command_table[i].label;
  475. X        command_args[2].value = (XtArgVal) command_table[i].y_pos;
  476. X        command_call[0].closure = (caddr_t) command_table[i].closure;
  477. X        (void) XtCreateManagedWidget(command_table[i].name,
  478. X        commandWidgetClass, right_widget,
  479. X        command_args, XtNumber(command_args));
  480. X    }
  481. }
  482. #endif    /* BUTTONS */
  483. X
  484. #else    /* !TOOLKIT */
  485. #define    BAR_WID        12    /* width of darkened area */
  486. #define    BAR_THICK    15    /* gross amount removed */
  487. X
  488. static    Window    top_level;
  489. static    Window    x_bar, y_bar;
  490. static    int    x_bgn, x_end, y_bgn, y_end;    /* scrollbar positions */
  491. #endif    /* TOOLKIT */
  492. X
  493. /*
  494. X *    Mechanism to keep track of the magnifier window.  The problems are,
  495. X *    (a) if the button is released while the window is being drawn, this
  496. X *    could cause an X error if we continue drawing in it after it is
  497. X *    destroyed, and
  498. X *    (b) creating and destroying the window too quickly confuses the window
  499. X *    manager, which is avoided by waiting for an expose event before
  500. X *    destroying it.
  501. X */
  502. static    short    alt_stat;    /* 1 = wait for expose, */
  503. X                /* -1 = destroy upon expose */
  504. static    Boolean    alt_canit;    /* stop drawing this window */
  505. X
  506. /*
  507. X *    Data for buffered events.
  508. X */
  509. X
  510. static    Boolean    canit        = False,
  511. X        has_arg        = False;
  512. static    short    event_counter    = 0,
  513. X        event_freq    = 70;
  514. static    int    number        = 0,
  515. X        sign        = 1;
  516. static    jmp_buf    canit_env;
  517. X
  518. static    void    can_exposures(), read_events(), keystroke();
  519. X
  520. #ifdef    lint
  521. #ifndef    X10
  522. char    xdvi_bits[288];
  523. #ifdef    TOOLKIT
  524. WidgetClass    viewportWidgetClass, widgetClass;
  525. WidgetClassRec    widgetClassRec;
  526. #ifdef    BUTTONS
  527. WidgetClass    formWidgetClass, compositeWidgetClass, commandWidgetClass;
  528. #endif    /* BUTTONS */
  529. #endif    /* TOOLKIT */
  530. #else    /* X10 */
  531. short    xdvi_bits[15], xdvi_mask_bits[15];
  532. Display    *_XlibCurrentDisplay;
  533. #endif    /* X10 */
  534. #endif    /* lint */
  535. X
  536. #ifdef    sun
  537. extern    char    *sprintf();
  538. #endif
  539. X
  540. extern    double    atof();
  541. extern    volatile void    exit();
  542. X
  543. /********************************
  544. X *      tpic routines        *
  545. X *******************************/
  546. X
  547. /* Things we need from spec_draw, unfortunately */
  548. X
  549. /* (ignored for now)
  550. extern int pen_size, blacken, whiten, shade;
  551. */
  552. X
  553. #define    toint(x)    ((int) ((x) + 0.5))
  554. #define    xconv(x)    (toint(specialConv*(x))/shrink_factor + PXL_H)
  555. #define    yconv(y)    (toint(specialConv*(y))/shrink_factor + PXL_V)
  556. X
  557. /*
  558. X *    Draw a line from (fx,fy) to (tx,ty).
  559. X *    Right now, we ignore pen_size.
  560. X */
  561. void
  562. line_btw(fx, fy, tx, ty)
  563. int fx, fy, tx, ty;
  564. {
  565. X    register int    fcx = xconv(fx),
  566. X            tcx = xconv(tx),
  567. X            fcy = yconv(fy),
  568. X            tcy = yconv(ty);
  569. X
  570. X    if ((fcx < max_x || tcx < max_x) && (fcx >= min_x || tcx >= min_x) &&
  571. X        (fcy < max_y || tcy < max_y) && (fcy >= min_y || tcy >= min_y))
  572. #ifndef X10
  573. X        XDrawLine(DISP, WINDOW(currwin), ruleGC,
  574. X            fcx - currwin.base_x, fcy - currwin.base_y,
  575. X            tcx - currwin.base_x, tcy - currwin.base_y);
  576. #else
  577. X        XLine(WINDOW(currwin),
  578. X            fcx - currwin.base_x, fcy - currwin.base_y,
  579. X            tcx - currwin.base_x, tcy - currwin.base_y,
  580. X            1, 1, ruleGC, GXcopy, AllPlanes);
  581. #endif
  582. }
  583. X
  584. /*
  585. X *    Draw a dot at (x,y)
  586. X */
  587. void
  588. dot_at(x, y)
  589. X    int    x, y;
  590. {
  591. X    register int    cx = xconv(x),
  592. X            cy = yconv(y);
  593. X
  594. X    if (cx < max_x && cx >= min_x && cy < max_y && cy >= min_y)
  595. #ifndef X10
  596. X        XDrawPoint(DISP, WINDOW(currwin), ruleGC,
  597. X        cx - currwin.base_x, cy - currwin.base_y);
  598. #else
  599. X        XPixSet(WINDOW(currwin), cx - currwin.base_x, cy - currwin.base_y,
  600. X        1, 1, ruleGC);
  601. #endif
  602. }
  603. X
  604. /*
  605. X *    Apply the requested attributes to the last path (box) drawn.
  606. X *    Attributes are reset.
  607. X *    (Not currently implemented.)
  608. X */
  609. X    /* ARGSUSED */
  610. void
  611. do_attribute_path(last_min_x, last_max_x, last_min_y, last_max_y)
  612. int last_min_x, last_max_x, last_min_y, last_max_y;
  613. {
  614. }
  615. X
  616. /*
  617. X *    Put a rectangle on the screen.  hl determines the GC.
  618. X */
  619. X
  620. void
  621. put_rectangle(x, y, w, h, hl)
  622. X    int x, y, w, h;
  623. X    Boolean hl;
  624. {
  625. X    if (x < max_x && x + w >= min_x && y < max_y && y + h >= min_y) {
  626. X        if (--event_counter == 0) read_events(False);
  627. #ifndef X10
  628. X        XFillRectangle(DISP, WINDOW(currwin), hl ? highGC : ruleGC,
  629. X            x - currwin.base_x, y - currwin.base_y,
  630. X            w ? w : 1, h ? h : 1);
  631. #else
  632. X        XPixSet(WINDOW(currwin), x - currwin.base_x, y - currwin.base_y,
  633. X            w ? w : 1, h ? h : 1, hl ? highGC : ruleGC);
  634. #endif
  635. X    }
  636. }
  637. X
  638. void
  639. put_bitmap(bitmap, x, y)
  640. X    register struct bitmap *bitmap;
  641. X    register int x, y;
  642. {
  643. X
  644. X    if (debug & DBG_BITMAP)
  645. X        Printf("X(%d,%d)\n", x - currwin.base_x, y - currwin.base_y);
  646. X    if (x < max_x && x + bitmap->w >= min_x &&
  647. X        y < max_y && y + bitmap->h >= min_y) {
  648. X        if (--event_counter == 0) read_events(False);
  649. #ifndef X10
  650. X        image->width = bitmap->w;
  651. X        image->height = bitmap->h;
  652. X        image->data = bitmap->bits;
  653. X        image->bytes_per_line = bitmap->bytes_wide;
  654. X        XPutImage(DISP, WINDOW(currwin), foreGC, image,
  655. X            0, 0,
  656. X            x - currwin.base_x, y - currwin.base_y,
  657. X            bitmap->w, bitmap->h);
  658. X        if (foreGC2)
  659. X            XPutImage(DISP, WINDOW(currwin), foreGC2, image,
  660. X            0, 0,
  661. X            x - currwin.base_x, y - currwin.base_y,
  662. X            bitmap->w, bitmap->h);
  663. #else
  664. X        XBitmapBitsPut(WINDOW(currwin),
  665. X            x - currwin.base_x, y - currwin.base_y,
  666. X            bitmap->w, bitmap->h, bitmap->bits,
  667. X            foreGC, backpix, NULL, GXfunc, AllPlanes);
  668. #endif
  669. X    }
  670. }
  671. X
  672. /*
  673. X *    Event-handling routines
  674. X */
  675. X
  676. static    void
  677. expose(windowrec, x, y, w, h)
  678. X    register struct WindowRec *windowrec;
  679. X    int    x, y, w, h;
  680. {
  681. X    if (windowrec->min_x > x) windowrec->min_x = x;
  682. X    if (windowrec->max_x < x + w)
  683. X        windowrec->max_x = x + w;
  684. X    if (windowrec->min_y > y) windowrec->min_y = y;
  685. X    if (windowrec->max_y < y + h)
  686. X        windowrec->max_y = y + h;
  687. }
  688. X
  689. static    void
  690. clearexpose(windowrec, x, y, w, h)
  691. X    struct WindowRec *windowrec;
  692. X    int    x, y, w, h;
  693. {
  694. X    ClearArea(WINDOW(*windowrec), x, y, w, h);
  695. X    expose(windowrec, x, y, w, h);
  696. }
  697. X
  698. static    void
  699. scrollwindow(windowrec, x0, y0)
  700. X    register struct WindowRec *windowrec;
  701. X    int    x0, y0;
  702. {
  703. X    int    x, y;
  704. X    int    x2 = 0, y2 = 0;
  705. X    int    ww, hh;
  706. X
  707. X    x = x0 - windowrec->base_x;
  708. X    y = y0 - windowrec->base_y;
  709. X    ww = windowrec->width - x;
  710. X    hh = windowrec->height - y;
  711. X    windowrec->base_x = x0;
  712. X    windowrec->base_y = y0;
  713. X    if (currwin.win == windowrec->win) {
  714. X        currwin.base_x = x0;
  715. X        currwin.base_y = y0;
  716. X    }
  717. X    windowrec->min_x -= x;
  718. X    if (windowrec->min_x < 0) windowrec->min_x = 0;
  719. X    windowrec->max_x -= x;
  720. X    if (windowrec->max_x > windowrec->width)
  721. X        windowrec->max_x = windowrec->width;
  722. X    windowrec->min_y -= y;
  723. X    if (windowrec->min_y < 0) windowrec->min_y = 0;
  724. X    windowrec->max_y -= y;
  725. X    if (windowrec->max_y > windowrec->height)
  726. X        windowrec->max_y = windowrec->height;
  727. X    if (x < 0) {
  728. X        x2 = -x;
  729. X        x = 0;
  730. X        ww = windowrec->width - x2;
  731. X    }
  732. X    if (y < 0) {
  733. X        y2 = -y;
  734. X        y = 0;
  735. X        hh = windowrec->height - y2;
  736. X    }
  737. X    if (ww <= 0 || hh <= 0) {
  738. X        ClearPage(*windowrec);
  739. X        windowrec->min_x = windowrec->min_y = 0;
  740. X        windowrec->max_x = windowrec->width;
  741. X        windowrec->max_y = windowrec->height;
  742. X    }
  743. X    else {
  744. X        CopyArea(WINDOW(*windowrec), x, y, ww, hh, x2, y2);
  745. X        if (x > 0) clearexpose(windowrec, ww, 0, x, windowrec->height);
  746. X        if (x2 > 0) clearexpose(windowrec, 0, 0, x2, windowrec->height);
  747. X        if (y > 0) clearexpose(windowrec, 0, hh, windowrec->width, y);
  748. X        if (y2 > 0) clearexpose(windowrec, 0, 0, windowrec->width, y2);
  749. X    }
  750. }
  751. X
  752. #ifdef    TOOLKIT
  753. /*
  754. X *    routines for X11 toolkit
  755. X */
  756. X
  757. static    Arg    arg_wh[] = {
  758. X    {XtNwidth,    (XtArgVal) &window_w},
  759. X    {XtNheight,    (XtArgVal) &window_h},
  760. };
  761. X
  762. static    Position    window_x, window_y;
  763. static    Arg    arg_xy[] = {
  764. X    {XtNx,        (XtArgVal) &window_x},
  765. X    {XtNy,        (XtArgVal) &window_y},
  766. };
  767. X
  768. #define    get_xy()    XtGetValues(draw_widget, arg_xy, XtNumber(arg_xy))
  769. X
  770. #define    mane_base_x    0
  771. #define    mane_base_y    0
  772. X
  773. static    void
  774. home(scrl)
  775. X    Boolean    scrl;
  776. {
  777. X    register int coord;
  778. X
  779. X    if (!scrl) XUnmapWindow(DISP, WINDOW(mane));
  780. X    get_xy();
  781. X    coord = 0;
  782. X    if (page_w > clip_w) {
  783. X        coord = (page_w - clip_w) / 2;
  784. X        if (coord > home_x / mane.shrinkfactor)
  785. X        coord = home_x / mane.shrinkfactor;
  786. X        XtCallCallbacks(x_bar, XtNscrollProc,
  787. X        (XtPointer) (window_x + coord));
  788. X    }
  789. X    coord = 0;
  790. X    if (page_h > clip_h) {
  791. X        coord = (page_h - clip_h) / 2;
  792. X        if (coord > home_y / mane.shrinkfactor)
  793. X        coord = home_y / mane.shrinkfactor;
  794. X        XtCallCallbacks(y_bar, XtNscrollProc,
  795. X        (XtPointer) (window_y + coord));
  796. X    }
  797. X    if (!scrl) {
  798. X        XMapWindow(DISP, WINDOW(mane));
  799. X        /* Wait for the server to catch up---this eliminates flicker. */
  800. X        XSync(DISP, False);
  801. X    }
  802. }
  803. X
  804. static    Boolean    resized    = False;
  805. X
  806. static    void
  807. get_geom()
  808. {
  809. X    static    Dimension    new_clip_w, new_clip_h;
  810. X    static    Arg    arg_wh_clip[] = {
  811. X        {XtNwidth,    (XtArgVal) &new_clip_w},
  812. X        {XtNheight,    (XtArgVal) &new_clip_h},
  813. X    };
  814. X    register int    old_clip_w;
  815. X
  816. X    XtGetValues(vport_widget, arg_wh, XtNumber(arg_wh));
  817. X    XtGetValues(clip_widget, arg_wh_clip, XtNumber(arg_wh_clip));
  818. X    /* Note:  widgets may be destroyed but not forgotten */
  819. X    x_bar = page_w <= new_clip_w ? NULL
  820. X        : XtNameToWidget(vport_widget, "horizontal");
  821. X    y_bar = page_h <= new_clip_h ? NULL
  822. X        : XtNameToWidget(vport_widget, "vertical");
  823. X    old_clip_w = clip_w;
  824. X            /* we need to do this because */
  825. X            /* sizeof(Dimension) != sizeof(int) */
  826. X    clip_w = new_clip_w;
  827. X    clip_h = new_clip_h;
  828. X    if (old_clip_w == 0) home(False);
  829. X    resized = False;
  830. }
  831. X
  832. static    void
  833. center(x, y)
  834. X    int x, y;
  835. {
  836. /*    We use the clip widget here because it gives a more exact value. */
  837. X    x -= clip_w/2;
  838. X    y -= clip_h/2;
  839. X    if (x_bar) XtCallCallbacks(x_bar, XtNscrollProc, (XtPointer) x);
  840. X    if (y_bar) XtCallCallbacks(y_bar, XtNscrollProc, (XtPointer) y);
  841. X    XWarpPointer(DISP, None, None, 0, 0, 0, 0, -x, -y);
  842. }
  843. X
  844. /*
  845. X *    callback routines
  846. X */
  847. X
  848. /* The following callback routine should never be called. */
  849. X    /*ARGSUSED*/
  850. static    void
  851. handle_key(widget, junk, event)
  852. X    Widget    widget;
  853. X    caddr_t    junk;
  854. X    XEvent    *event;
  855. {
  856. X    XBell(DISP, 20);
  857. }
  858. X
  859. X    /*ARGSUSED*/
  860. static    void
  861. handle_resize(widget, junk, event)
  862. X    Widget    widget;
  863. X    caddr_t    junk;
  864. X    XEvent    *event;
  865. {
  866. X    resized = True;
  867. }
  868. X
  869. #ifdef    BUTTONS
  870. X    /*ARGSUSED*/
  871. static    void
  872. handle_command(widget, client_data, call_data)
  873. X    Widget    widget;
  874. X    caddr_t    client_data;
  875. X    caddr_t    call_data;
  876. {
  877. X    keystroke(((int) client_data) & 0xff, ((int) client_data) >> 8,
  878. X        (((int) client_data) >> 8) != 0, (XEvent *) NULL);
  879. }
  880. #endif    /* BUTTONS */
  881. X
  882. #else    /* !TOOLKIT */
  883. X
  884. /*
  885. X *    brute force scrollbar routines
  886. X */
  887. X
  888. static    void
  889. paint_x_bar()
  890. {
  891. X    register int    new_x_bgn = mane.base_x * clip_w / page_w;
  892. X    register int    new_x_end = (mane.base_x + clip_w) * clip_w / page_w;
  893. X
  894. X    if (new_x_bgn >= x_end || x_bgn >= new_x_end) {    /* no overlap */
  895. X        ClearArea(x_bar, x_bgn, 1, x_end - x_bgn, BAR_WID);
  896. X        DarkenArea(x_bar, new_x_bgn, 1, new_x_end - new_x_bgn, BAR_WID);
  897. X    }
  898. X    else {        /* this stuff avoids flicker */
  899. X        if (x_bgn < new_x_bgn)
  900. X        ClearArea(x_bar, x_bgn, 1, new_x_bgn - x_bgn, BAR_WID);
  901. X        else
  902. X        DarkenArea(x_bar, new_x_bgn, 1, x_bgn - new_x_bgn, BAR_WID);
  903. X        if (new_x_end < x_end)
  904. X        ClearArea(x_bar, new_x_end, 1, x_end - new_x_end, BAR_WID);
  905. X        else
  906. X        DarkenArea(x_bar, x_end, 1, new_x_end - x_end, BAR_WID);
  907. X    }
  908. X    x_bgn = new_x_bgn;
  909. X    x_end = new_x_end;
  910. }
  911. X
  912. static    void
  913. paint_y_bar()
  914. {
  915. X    register int    new_y_bgn = mane.base_y * clip_h / page_h;
  916. X    register int    new_y_end = (mane.base_y + clip_h) * clip_h / page_h;
  917. X
  918. X    if (new_y_bgn >= y_end || y_bgn >= new_y_end) {    /* no overlap */
  919. X        ClearArea(y_bar, 1, y_bgn, BAR_WID, y_end - y_bgn);
  920. X        DarkenArea(y_bar, 1, new_y_bgn, BAR_WID, new_y_end - new_y_bgn);
  921. X    }
  922. X    else {        /* this stuff avoids flicker */
  923. X        if (y_bgn < new_y_bgn)
  924. X        ClearArea(y_bar, 1, y_bgn, BAR_WID, new_y_bgn - y_bgn);
  925. X        else
  926. X        DarkenArea(y_bar, 1, new_y_bgn, BAR_WID, y_bgn - new_y_bgn);
  927. X        if (new_y_end < y_end)
  928. X        ClearArea(y_bar, 1, new_y_end, BAR_WID, y_end - new_y_end);
  929. X        else
  930. X        DarkenArea(y_bar, 1, y_end, BAR_WID, new_y_end - y_end);
  931. X    }
  932. X    y_bgn = new_y_bgn;
  933. X    y_end = new_y_end;
  934. }
  935. X
  936. static    void
  937. scrollmane(x, y)
  938. X    int    x, y;
  939. {
  940. X    register int    old_base_x = mane.base_x;
  941. X    register int    old_base_y = mane.base_y;
  942. X    if (x > page_w - clip_w) x = page_w - clip_w;
  943. X    if (x < 0) x = 0;
  944. X    if (y > page_h - clip_h) y = page_h - clip_h;
  945. X    if (y < 0) y = 0;
  946. X    scrollwindow(&mane, x, y);
  947. X    if (old_base_x != mane.base_x && x_bar) paint_x_bar();
  948. X    if (old_base_y != mane.base_y && y_bar) paint_y_bar();
  949. }
  950. X
  951. static    void
  952. reconfig()
  953. {
  954. X    int    x_thick = 0;
  955. X    int    y_thick = 0;
  956. #ifdef    X10
  957. X    int    old_clip_w = clip_w;
  958. X    int    old_clip_h = clip_h;
  959. X    int    old_x_thick = x_thick;
  960. X    int    old_y_thick = y_thick;
  961. #endif
  962. X
  963. X        /* determine existence of scrollbars */
  964. X    if (window_w < page_w) x_thick = BAR_THICK;
  965. X    if (window_h - x_thick < page_h) y_thick = BAR_THICK;
  966. X    clip_w = window_w - y_thick;
  967. X    if (clip_w < page_w) x_thick = BAR_THICK;
  968. X    clip_h = window_h - x_thick;
  969. X
  970. X        /* process drawing (clip) window */
  971. X    if (mane.win == NULL) {    /* initial creation */
  972. #ifndef X10
  973. X        mane.win = XCreateSimpleWindow(DISP, top_level, y_thick, x_thick,
  974. X            (unsigned int) clip_w, (unsigned int) clip_h, 0,
  975. X            brdr_Pixel, back_Pixel);
  976. X        XSelectInput(DPY WINDOW(mane), ExposureMask |
  977. X            ButtonPressMask | ButtonMotionMask | ButtonReleaseMask);
  978. #else
  979. X        mane.win = XCreateWindow(top_level, y_thick, x_thick,
  980. X            clip_w, clip_h, 0, bdrmap, backmap);
  981. X        XSelectInput(WINDOW(mane),  ExposeRegion | ExposeCopy |
  982. X            ButtonPressed | ButtonReleased |
  983. X            LeftDownMotion | MiddleDownMotion | RightDownMotion);
  984. #endif
  985. X        XMapWindow(DPY WINDOW(mane));
  986. X    }
  987. X    else
  988. #ifdef    X10
  989. X    if (clip_w != old_clip_w || clip_h != old_clip_h ||
  990. X        x_thick != old_x_thick || y_thick != old_y_thick) {
  991. #endif
  992. X        XMoveResizeWindow(DPY WINDOW(mane),
  993. X        y_thick, x_thick, clip_w, clip_h);
  994. #ifdef    X10
  995. X        XSync(False);
  996. X    }
  997. #endif
  998. X
  999. X        /* process scroll bars */
  1000. X    if (x_thick) {
  1001. X        if (x_bar) {
  1002. X        XMoveResizeWindow(DPY x_bar,
  1003. X            y_thick - 1, -1, clip_w, BAR_THICK - 1);
  1004. X        paint_x_bar();
  1005. X        }
  1006. X        else {
  1007. #ifndef X10
  1008. X        x_bar = XCreateSimpleWindow(DISP, top_level, y_thick - 1, -1,
  1009. X                (unsigned int) clip_w, BAR_THICK - 1, 1,
  1010. X                brdr_Pixel, back_Pixel);
  1011. X        XSelectInput(DISP, x_bar,
  1012. X            ExposureMask | ButtonPressMask | Button2MotionMask);
  1013. #else
  1014. X        x_bar = XCreateWindow(top_level,
  1015. X                y_thick - 1, -1, clip_w, BAR_THICK - 1, 1,
  1016. X                bdrmap, backmap);
  1017. X        XSelectInput(x_bar,
  1018. X            ExposeRegion | ButtonPressed | MiddleDownMotion);
  1019. #endif
  1020. X        XMapWindow(DPY x_bar);
  1021. X        }
  1022. X        x_bgn = mane.base_x * clip_w / page_w;
  1023. X        x_end = (mane.base_x + clip_w) * clip_w / page_w;
  1024. X    }
  1025. X    else
  1026. X        if (x_bar) {
  1027. X        XDestroyWindow(DPY x_bar);
  1028. X        x_bar = NULL;
  1029. X        }
  1030. X
  1031. X    if (y_thick) {
  1032. X        if (y_bar) {
  1033. X        XMoveResizeWindow(DPY y_bar,
  1034. X            -1, x_thick - 1, BAR_THICK - 1, clip_h);
  1035. X        paint_y_bar();
  1036. X        }
  1037. X        else {
  1038. #ifndef X10
  1039. X        y_bar = XCreateSimpleWindow(DISP, top_level, -1, x_thick - 1,
  1040. X                BAR_THICK - 1, (unsigned int) clip_h, 1,
  1041. X                brdr_Pixel, back_Pixel);
  1042. X        XSelectInput(DISP, y_bar,
  1043. X            ExposureMask | ButtonPressMask | Button2MotionMask);
  1044. #else
  1045. X        y_bar = XCreateWindow(top_level,
  1046. X                -1, x_thick - 1, BAR_THICK - 1, clip_h, 1,
  1047. X                bdrmap, backmap);
  1048. X        XSelectInput(y_bar,
  1049. X            ExposeRegion | ButtonPressed | MiddleDownMotion);
  1050. #endif
  1051. X        XMapWindow(DPY y_bar);
  1052. X        }
  1053. X        y_bgn = mane.base_y * clip_h / page_h;
  1054. X        y_end = (mane.base_y + clip_h) * clip_h / page_h;
  1055. X    }
  1056. X    else
  1057. X        if (y_bar) {
  1058. X        XDestroyWindow(DPY y_bar);
  1059. X        y_bar = NULL;
  1060. X        }
  1061. }
  1062. X
  1063. static    void
  1064. home(scrl)
  1065. X    Boolean    scrl;
  1066. {
  1067. X    int    x = 0, y = 0;
  1068. X
  1069. X    if (page_w > clip_w) {
  1070. X        x = (page_w - clip_w) / 2;
  1071. X        if (x > home_x / mane.shrinkfactor)
  1072. X        x = home_x / mane.shrinkfactor;
  1073. X    }
  1074. X    if (page_h > clip_h) {
  1075. X        y = (page_h - clip_h) / 2;
  1076. X        if (y > home_y / mane.shrinkfactor)
  1077. X        y = home_y / mane.shrinkfactor;
  1078. X    }
  1079. X    if (scrl)
  1080. X        scrollmane(x, y);
  1081. X    else {
  1082. X        mane.base_x = x;
  1083. X        mane.base_y = y;
  1084. X        if (currwin.win == mane.win) {
  1085. X        currwin.base_x = x;
  1086. X        currwin.base_y = y;
  1087. X        }
  1088. X        if (x_bar) paint_x_bar();
  1089. X        if (y_bar) paint_y_bar();
  1090. X    }
  1091. }
  1092. X
  1093. #define    get_xy()
  1094. #define    window_x 0
  1095. #define    window_y 0
  1096. #define    mane_base_x    mane.base_x
  1097. #define    mane_base_y    mane.base_y
  1098. #endif    /* TOOLKIT */
  1099. X
  1100. static    void
  1101. compute_mag_pos(xp, yp)
  1102. X    int    *xp, *yp;
  1103. {
  1104. X    register int t;
  1105. X
  1106. X    t = mag_x + main_x - alt.width/2;
  1107. #ifndef X10
  1108. X    if (t > WidthOfScreen(SCRN) - alt.width - 2*MAGBORD)
  1109. X        t = WidthOfScreen(SCRN) - alt.width - 2*MAGBORD;
  1110. #else
  1111. X    if (t > (int) window_w - alt.width - 2*MAGBORD)
  1112. X        t = window_w - alt.width - 2*MAGBORD;
  1113. #endif
  1114. X    if (t < 0) t = 0;
  1115. X    *xp = t;
  1116. X    t = mag_y + main_y - alt.height/2;
  1117. #ifndef X10
  1118. X    if (t > HeightOfScreen(SCRN) - alt.height - 2*MAGBORD)
  1119. X        t = HeightOfScreen(SCRN) - alt.height - 2*MAGBORD;
  1120. #else
  1121. X    if (t > (int) window_h - alt.height - 2*MAGBORD)
  1122. X        t = window_h - alt.height - 2*MAGBORD;
  1123. #endif
  1124. X    if (t < 0) t = 0;
  1125. X    *yp = t;
  1126. }
  1127. X
  1128. #ifdef    TOOLKIT
  1129. X    /*ARGSUSED*/
  1130. static    void
  1131. handle_button(widget, junk, event)
  1132. X    Widget    widget;
  1133. X    caddr_t    junk;
  1134. #else    /* !TOOLKIT */
  1135. static    void
  1136. handle_button(event)
  1137. #endif    /* TOOLKIT */
  1138. X    XButtonEvent *event;
  1139. {
  1140. X    int x, y;
  1141. #ifndef X10
  1142. X    XSetWindowAttributes attr;
  1143. X
  1144. X    alt.width = alt.height = mg_size[event->button - 1];
  1145. #else
  1146. X    alt.width = alt.height = mg_size[2 - (event->detail & ValueMask)];
  1147. #endif
  1148. X    if (alt.win != NULL || mane.shrinkfactor == 1 || alt.width <= 0)
  1149. X        XBell(DISP, 20);
  1150. X    else {
  1151. X        mag_x = event->x;
  1152. X        mag_y = event->y;
  1153. #ifndef X10
  1154. X        main_x = event->x_root - mag_x;
  1155. X        main_y = event->y_root - mag_y;
  1156. #endif
  1157. X        compute_mag_pos(&x, &y);
  1158. X        alt.base_x = (event->x + mane_base_x) * mane.shrinkfactor -
  1159. X        alt.width/2;
  1160. X        alt.base_y = (event->y + mane_base_y) * mane.shrinkfactor -
  1161. X        alt.height/2;
  1162. #ifndef X10
  1163. X        attr.save_under = True;
  1164. X        attr.border_pixel = brdr_Pixel;
  1165. X        attr.background_pixel = back_Pixel;
  1166. X        attr.override_redirect = True;
  1167. X        alt.win = XCreateWindow(DISP, RootWindowOfScreen(SCRN),
  1168. X            x, y, alt.width, alt.height, MAGBORD,
  1169. X            0,    /* depth from parent */
  1170. X            InputOutput, CopyFromParent,
  1171. X            CWSaveUnder | CWBorderPixel | CWBackPixel |
  1172. X            CWOverrideRedirect, &attr);
  1173. X        XSelectInput(DISP, WINDOW(alt), ExposureMask);
  1174. #else
  1175. X        alt.win = XCreateWindow(WINDOW(mane),
  1176. X            x, y, alt.width, alt.height, MAGBORD,
  1177. X            bdrmap, backmap);
  1178. X        XSelectInput(WINDOW(alt), ExposeRegion);
  1179. #endif
  1180. X        XMapWindow(DPY WINDOW(alt));
  1181. X        alt_stat = 1;    /* waiting for exposure */
  1182. X    }
  1183. }
  1184. X
  1185. #ifdef    TOOLKIT
  1186. X    /*ARGSUSED*/
  1187. static    void
  1188. handle_motion(widget, junk, event)
  1189. X    Widget    widget;
  1190. X    caddr_t    junk;
  1191. X    XMotionEvent *event;
  1192. {
  1193. X    new_mag_x = event->x;
  1194. X    main_x = event->x_root - new_mag_x;
  1195. X    new_mag_y = event->y;
  1196. X    main_y = event->y_root - new_mag_y;
  1197. X    mag_moved = (new_mag_x != mag_x || new_mag_y != mag_y);
  1198. }
  1199. #endif    /* TOOLKIT */
  1200. X
  1201. static    void
  1202. movemag(x, y)
  1203. X    int    x, y;
  1204. {
  1205. X    int    xx, yy;
  1206. X
  1207. X    mag_x = x;
  1208. X    mag_y = y;
  1209. X    if (mag_x == new_mag_x && mag_y == new_mag_y) mag_moved = False;
  1210. X    compute_mag_pos(&xx, &yy);
  1211. X    XMoveWindow(DPY WINDOW(alt), xx, yy);
  1212. X    scrollwindow(&alt, (x + mane_base_x) * mane.shrinkfactor - alt.width/2,
  1213. X        (y + mane_base_y) * mane.shrinkfactor - alt.height/2);
  1214. }
  1215. X
  1216. #ifdef    TOOLKIT
  1217. X    /*ARGSUSED*/
  1218. static    void
  1219. handle_release(widget, junk, event)
  1220. X    Widget    widget;
  1221. X    caddr_t    junk;
  1222. X    XButtonEvent *event;
  1223. #else    /* !TOOLKIT */
  1224. static    void
  1225. handle_release()
  1226. #endif    /* TOOLKIT */
  1227. {
  1228. X    if (alt.win)
  1229. X        if (alt_stat) alt_stat = -1;    /* destroy upon expose */
  1230. X        else {
  1231. X        XDestroyWindow(DPY WINDOW(alt));
  1232. X        if (currwin.win == alt.win) alt_canit = True;
  1233. X        alt.win = NULL;
  1234. X        mag_moved = False;
  1235. X        can_exposures(&alt);
  1236. X        }
  1237. }
  1238. X
  1239. #ifdef    TOOLKIT
  1240. X    /*ARGSUSED*/
  1241. static    void
  1242. handle_exp(widget, windowrec, event)
  1243. X    Widget    widget;
  1244. X    struct WindowRec *windowrec;
  1245. X    register XExposeEvent *event;
  1246. {
  1247. X    if (windowrec == &alt)
  1248. X        if (alt_stat < 0) {    /* destroy upon exposure */
  1249. X        alt_stat = 0;
  1250. X        handle_release(widget, (caddr_t) NULL, (XButtonEvent *) event);
  1251. X        return;
  1252. X        }
  1253. X        else
  1254. X        alt_stat = 0;
  1255. X    expose(windowrec, event->x, event->y, event->width, event->height);
  1256. }
  1257. #endif    /* TOOLKIT */
  1258. X
  1259. /* |||
  1260. X *    Currently the event handler does not coordinate XCopyArea requests
  1261. X *    with GraphicsExpose events.  This can lead to problems if the window
  1262. X *    is partially obscured and one, for example, drags a scrollbar.
  1263. X */
  1264. X
  1265. #ifndef X10
  1266. #define    XKEY(ev)    (ev).xkey
  1267. #ifndef    TOOLKIT
  1268. #define    XANY(ev)    (ev).xany
  1269. #define    XCONFIG(ev)    (ev).xconfigure
  1270. #define    XEXPOSE(ev)    (ev).xexpose
  1271. #define    XMOTION(ev)    (ev).xmotion
  1272. #define    XBUTTON(ev)    (ev).xbutton
  1273. #define    ISEXPOSE(ev)    ((ev).type == Expose)
  1274. #endif    /* TOOLKIT */
  1275. #else    /* X10 */
  1276. #define    XANY(ev)    (ev)
  1277. #define    XCONFIG(ev)    (*((XExposeEvent *) &(ev)))
  1278. #define    XEXPOSE(ev)    (*((XExposeEvent *) &(ev)))
  1279. #define    XMOTION(ev)    (*((XMouseMovedEvent *) &(ev)))
  1280. #define    XBUTTON(ev)    (*((XButtonEvent *) &(ev)))
  1281. #define    XKEY(ev)    (*((XKeyEvent *) &(ev)))
  1282. #define    ConfigureNotify    ExposeWindow
  1283. #define    Expose        ExposeRegion
  1284. #define    ISEXPOSE(ev)    ((ev).type == ExposeWindow || (ev).type == ExposeRegion)
  1285. #define    MotionNotify    MouseMoved
  1286. #define    ButtonPress    ButtonPressed
  1287. #define    ButtonRelease    ButtonReleased
  1288. #define    KeyPress    KeyPressed
  1289. #endif    /* X10 */
  1290. X
  1291. static    void
  1292. keystroke(ch, number0, arg0, eventp)
  1293. X    char    ch;
  1294. X    int    number0;
  1295. X    Boolean    arg0;
  1296. X    XEvent    *eventp;
  1297. {
  1298. X    int    next_page;
  1299. #ifdef    TOOLKIT
  1300. X    Window    ww;
  1301. #endif
  1302. X
  1303. X    next_page = current_page;
  1304. X    switch (ch) {
  1305. X        case 'q':
  1306. X        case '\003':    /* control-C */
  1307. X        case '\004':    /* control-D */
  1308. #ifdef    VMS
  1309. X        case '\032':    /* control-Z */
  1310. #endif
  1311. X        exit(0);
  1312. X        case 'n':
  1313. X        case 'f':
  1314. X        case ' ':
  1315. X        case '\r':
  1316. X        case '\n':
  1317. X        /* scroll forward; i.e. go to relative page */
  1318. X        next_page = current_page + (arg0 ? number0 : 1);
  1319. X        break;
  1320. X        case 'p':
  1321. X        case 'b':
  1322. X        case '\b':
  1323. X        case '\177':    /* Del */
  1324. X        /* scroll backward */
  1325. X        next_page = current_page - (arg0 ? number0 : 1);
  1326. X        break;
  1327. X        case 'g':
  1328. X        /* go to absolute page */
  1329. X        next_page = (arg0 ? number0 - pageno_correct :
  1330. X            total_pages - 1);
  1331. X        break;
  1332. X        case 'P':        /* declare current page */
  1333. X        pageno_correct = arg0 * number0 - current_page;
  1334. X        return;
  1335. X        case 'k':        /* toggle keep-position flag */
  1336. X        keep_flag = (arg0 ? number0 : !keep_flag);
  1337. X        return;
  1338. X        case '\f':
  1339. X        /* redisplay current page */
  1340. X        break;
  1341. X        case '^':
  1342. X        home(True);
  1343. X        return;
  1344. #ifdef    TOOLKIT
  1345. X        case 'l':
  1346. X        if (!x_bar) goto bad;
  1347. X        XtCallCallbacks(x_bar, XtNscrollProc,
  1348. X            (XtPointer) (-2 * (int) clip_w / 3));
  1349. X        return;
  1350. X        case 'r':
  1351. X        if (!x_bar) goto bad;
  1352. X        XtCallCallbacks(x_bar, XtNscrollProc,
  1353. X            (XtPointer) (2 * (int) clip_w / 3));
  1354. X        return;
  1355. X        case 'u':
  1356. X        if (!y_bar) goto bad;
  1357. X        XtCallCallbacks(y_bar, XtNscrollProc,
  1358. X            (XtPointer) (-2 * (int) clip_h / 3));
  1359. X        return;
  1360. X        case 'd':
  1361. X        if (!y_bar) goto bad;
  1362. X        XtCallCallbacks(y_bar, XtNscrollProc,
  1363. X            (XtPointer) (2 * (int) clip_h / 3));
  1364. X        return;
  1365. X        case 'c':
  1366. X        center(eventp->xkey.x, eventp->xkey.y);
  1367. X        return;
  1368. X        case 'M':
  1369. X        XTranslateCoordinates(DISP, eventp->xkey.window,
  1370. X            WINDOW(mane), eventp->xkey.x, eventp->xkey.y,
  1371. X            &home_x, &home_y, &ww);    /* throw away last argument */
  1372. X        home_x *= mane.shrinkfactor;
  1373. X        home_y *= mane.shrinkfactor;
  1374. X        return;
  1375. #ifdef    BUTTONS
  1376. X        case 'x':
  1377. X        if (arg0 && expert == (number0 != 0)) return;
  1378. X        if (expert) {    /* create buttons */
  1379. X            XtResizeWidget(vport_widget, window_w -= XTRA_WID, window_h,
  1380. X            0);
  1381. X            create_buttons((XtArgVal) window_h);
  1382. X            expert = False;
  1383. X        }
  1384. X        else {        /* destroy buttons */
  1385. X            XtResizeWidget(vport_widget, window_w += XTRA_WID, window_h,
  1386. X            0);
  1387. X            XtDestroyWidget(right_widget);
  1388. X            XtDestroyWidget(line_widget);
  1389. X            expert = True;
  1390. X        }
  1391. X        return;
  1392. #endif    /* BUTTONS */
  1393. #else    /* !TOOLKIT */
  1394. X        case 'l':
  1395. X        if (mane.base_x <= 0) goto bad;
  1396. X        scrollmane(mane.base_x - 2 * clip_w / 3, mane.base_y);
  1397. X        return;
  1398. X        case 'r':
  1399. X        if (mane.base_x >= page_w - clip_w) goto bad;
  1400. X        scrollmane(mane.base_x + 2 * clip_w / 3, mane.base_y);
  1401. X        return;
  1402. X        case 'u':
  1403. X        if (mane.base_y <= 0) goto bad;
  1404. X        scrollmane(mane.base_x, mane.base_y - 2 * clip_h / 3);
  1405. X        return;
  1406. X        case 'd':
  1407. X        if (mane.base_y >= page_h - clip_h) goto bad;
  1408. X        scrollmane(mane.base_x, mane.base_y + 2 * clip_h / 3);
  1409. X        return;
  1410. X        case 'c':    /* unchecked scrollmane() */
  1411. X        scrollwindow(&mane, mane.base_x + XKEY(*eventp).x - clip_w/2,
  1412. X            mane.base_y + XKEY(*eventp).y - clip_h/2);
  1413. X        if (x_bar) paint_x_bar();
  1414. X        if (y_bar) paint_y_bar();
  1415. #ifndef X10
  1416. X        XWarpPointer(DISP, None, None, 0, 0, 0, 0,
  1417. X            clip_w/2 - XKEY(*eventp).x, clip_h/2 - XKEY(*eventp).y);
  1418. #else
  1419. X        XWarpMouse(WINDOW(mane), clip_w/2, clip_h/2, GXcopy);
  1420. #endif
  1421. X        return;
  1422. X        case 'M':
  1423. X        home_x = (XKEY(*eventp).x - (y_bar ? BAR_THICK : 0)
  1424. X            + mane.base_x) * mane.shrinkfactor;
  1425. X        home_y = (XKEY(*eventp).y - (x_bar ? BAR_THICK : 0)
  1426. X            + mane.base_y) * mane.shrinkfactor;
  1427. X        return;
  1428. #endif    /* TOOLKIT */
  1429. X
  1430. #ifndef X10
  1431. X        case '\020':    /* Control P */
  1432. X        Printf("Unit = %d, bitord = %d, byteord = %d\n",
  1433. X            BitmapUnit(DISP), BitmapBitOrder(DISP),
  1434. X            ImageByteOrder(DISP));
  1435. X        return;
  1436. #endif
  1437. X        case 's':
  1438. X        if (!arg0) {
  1439. X            int temp;
  1440. X            number0 = ROUNDUP(unshrunk_page_w, window_w - 2);
  1441. X            temp = ROUNDUP(unshrunk_page_h, window_h - 2);
  1442. X            if (number0 < temp) number0 = temp;
  1443. X        }
  1444. X        if (number0 <= 0) goto bad;
  1445. X        if (number0 == mane.shrinkfactor) return;
  1446. X        mane.shrinkfactor = number0;
  1447. X        init_page();
  1448. X        if (number0 != 1 && number0 != bak_shrink) {
  1449. X            bak_shrink = number0;
  1450. X            reset_fonts();
  1451. X        }
  1452. #ifdef    TOOLKIT
  1453. X        draw_args[0].value = (XtArgVal) page_w;
  1454. X        draw_args[1].value = (XtArgVal) page_h;
  1455. X        XtSetValues(draw_widget, draw_args, (Cardinal) 2);
  1456. X        get_geom();
  1457. X        home(False);
  1458. #else    /* TOOLKIT */
  1459. X        reconfig();
  1460. X        home(False);
  1461. #endif    /* TOOLKIT */
  1462. X        break;
  1463. X        case 'S':
  1464. X        if (!arg0) goto bad;
  1465. X        if (number0 < 0) goto bad;
  1466. X        if (number0 == density) return;
  1467. X        density = number0;
  1468. X        reset_fonts();
  1469. X        if (mane.shrinkfactor == 1) return;
  1470. X        break;
  1471. X        case 'R':
  1472. X        /* reread DVI file */
  1473. X        --dvi_time;    /* then it will notice a change */
  1474. X        break;
  1475. X        default:
  1476. X        goto bad;
  1477. X    }
  1478. X    if (0 <= next_page && next_page < total_pages) {
  1479. X        if (current_page != next_page) {
  1480. X        current_page = next_page;
  1481. X        hush_spec_now = hush_spec;
  1482. X        if (!keep_flag) home(False);
  1483. X        }
  1484. X        canit = True;
  1485. X        Flush();
  1486. X        return;    /* don't use longjmp here:  it might be called from
  1487. X             * within the toolkit, and we don't want to longjmp out
  1488. X             * of Xt routines. */
  1489. X    }
  1490. X    bad:  XBell(DISP, 10);
  1491. }
  1492. X
  1493. #ifndef X10
  1494. #define    TRSIZE    100
  1495. #endif    /* X10 */
  1496. static    void
  1497. read_events(wait)
  1498. X    Boolean    wait;
  1499. {
  1500. X    char    ch;
  1501. X    Boolean    arg0;
  1502. X    int    number0;
  1503. X    XEvent    event;
  1504. #ifndef X10
  1505. X    char    trbuf[TRSIZE];
  1506. #endif
  1507. X    char    *string;
  1508. X    int    nbytes;
  1509. X
  1510. X    alt_canit = False;
  1511. X    for (;;) {
  1512. X        ch = '\0';
  1513. X        event_counter = event_freq;
  1514. X        /*
  1515. X         * The above line clears the flag indicating that an event is
  1516. X         * pending.  So if an event comes in right now, the flag will be
  1517. X         * set again needlessly, but we just end up making an extra call.
  1518. X         * Also, watch out, if we destroy the magnifying glass while
  1519. X         * writing it.
  1520. X         */
  1521. X        if (!XtPending() && (!wait || canit || mane.min_x < MAXDIM ||
  1522. X            alt.min_x < MAXDIM || mag_moved))
  1523. X        if (!wait && (canit || alt_canit)) longjmp(canit_env, 1);
  1524. X        else return;
  1525. #ifdef    TOOLKIT
  1526. X        XtNextEvent(&event);
  1527. X        if (resized) get_geom();
  1528. X        if (event.xany.window == WINDOW(alt) &&
  1529. X            event.type == Expose) {
  1530. X        handle_exp((Widget) NULL, &alt, &event.xexpose);
  1531. X        continue;
  1532. X        }
  1533. X        if (event.type != KeyPress) {
  1534. X        XtDispatchEvent(&event);
  1535. X        continue;
  1536. X        }
  1537. X        string = trbuf;
  1538. X        nbytes = XLookupString(&event.xkey, string, TRSIZE, NULL, NULL);
  1539. X        if (nbytes > 1) ch = '?';
  1540. X        if (nbytes != 0) ch = *string;
  1541. #else    /* !TOOLKIT */
  1542. X
  1543. X        XNextEvent(DPY &event);
  1544. X        if (XANY(event).window == WINDOW(mane) ||
  1545. X        XANY(event).window == WINDOW(alt)) {
  1546. X
  1547. X        struct WindowRec *wr = &mane;
  1548. X
  1549. X        if (XANY(event).window == WINDOW(alt)) {
  1550. X            wr = &alt;
  1551. X            /* check in case we already destroyed the window */
  1552. X            if (alt_stat < 0) { /* destroy upon exposure */
  1553. X            alt_stat = 0;
  1554. X            handle_release();
  1555. X            continue;
  1556. X            }
  1557. X            else
  1558. X            alt_stat = 0;
  1559. X        }
  1560. X        switch (event.type) {
  1561. #ifndef X10
  1562. X        case GraphicsExpose:
  1563. #else
  1564. X        case ExposeWindow:
  1565. #endif
  1566. X        case Expose:
  1567. #ifdef X10
  1568. X            if (XEXPOSE(event).detail & ExposeCopy)
  1569. X            ClearArea(event.window,
  1570. X                XEXPOSE(event).x, XEXPOSE(event).y,
  1571. X                XEXPOSE(event).width, XEXPOSE(event).height);
  1572. #endif
  1573. X            expose(wr, XEXPOSE(event).x, XEXPOSE(event).y,
  1574. X            XEXPOSE(event).width, XEXPOSE(event).height);
  1575. #ifdef X10
  1576. X        case ExposeCopy:    /* throw away junk event */
  1577. #endif
  1578. X            break;
  1579. X
  1580. X        case MotionNotify:
  1581. #ifdef X10
  1582. X        case LeftDownMotion:
  1583. X        case MiddleDownMotion:
  1584. X        case RightDownMotion:
  1585. #endif
  1586. X            new_mag_x = XMOTION(event).x;
  1587. X            new_mag_y = XMOTION(event).y;
  1588. X            mag_moved = (new_mag_x != mag_x || new_mag_y != mag_y);
  1589. X            break;
  1590. X
  1591. X        case ButtonPress:
  1592. X            handle_button(&XBUTTON(event));
  1593. X            break;
  1594. X
  1595. X        case ButtonRelease:
  1596. X            handle_release();
  1597. X            break;
  1598. X        }    /* end switch */
  1599. X        }    /* end if window == {mane,alt}.win */
  1600. X
  1601. X        else if (XANY(event).window == x_bar) {
  1602. X        if (ISEXPOSE(event))
  1603. X            DarkenArea(x_bar, x_bgn, 1, x_end - x_bgn, BAR_WID);
  1604. X        else if (event.type == MotionNotify)
  1605. X            scrollmane(XMOTION(event).x * page_w / clip_w,
  1606. X            mane.base_y);
  1607. #ifndef X10
  1608. X        else switch (XBUTTON(event).button)
  1609. #else
  1610. X        else if (event.type == ButtonPress)
  1611. X            switch (3 - (XBUTTON(event).detail & ValueMask))
  1612. #endif
  1613. X        {
  1614. X            case 1:
  1615. X            scrollmane(mane.base_x + XBUTTON(event).x, mane.base_y);
  1616. X            break;
  1617. X            case 2:
  1618. X            scrollmane(XBUTTON(event).x * page_w / clip_w,
  1619. X                mane.base_y);
  1620. X            break;
  1621. X            case 3:
  1622. X            scrollmane(mane.base_x - XBUTTON(event).x, mane.base_y);
  1623. X        }
  1624. X        }
  1625. X
  1626. X        else if (XANY(event).window == y_bar) {
  1627. X        if (ISEXPOSE(event))
  1628. X            DarkenArea(y_bar, 1, y_bgn, BAR_WID, y_end - y_bgn);
  1629. X        else if (event.type == MotionNotify)
  1630. X            scrollmane(mane.base_x,
  1631. X            XMOTION(event).y * page_h / clip_h);
  1632. #ifndef X10
  1633. X        else switch (XBUTTON(event).button)
  1634. #else
  1635. X        else if (event.type == ButtonPress)
  1636. X            switch (3 - (XBUTTON(event).detail & ValueMask))
  1637. #endif
  1638. X        {
  1639. X            case 1:
  1640. X            scrollmane(mane.base_x, mane.base_y + XBUTTON(event).y);
  1641. X            break;
  1642. X            case 2:
  1643. X            scrollmane(mane.base_x,
  1644. X                XBUTTON(event).y * page_h / clip_h);
  1645. X            break;
  1646. X            case 3:
  1647. X            scrollmane(mane.base_x, mane.base_y - XBUTTON(event).y);
  1648. X        }
  1649. X        }
  1650. X
  1651. X        else if (XANY(event).window == top_level)
  1652. X        switch (event.type) {
  1653. X        case ConfigureNotify:
  1654. X            if (XANY(event).window == top_level &&
  1655. X            (XCONFIG(event).width != window_w ||
  1656. X            XCONFIG(event).height != window_h)) {
  1657. X                register Window old_mane_win = mane.win;
  1658. X
  1659. X                window_w = XCONFIG(event).width;
  1660. X                window_h = XCONFIG(event).height;
  1661. X                reconfig();
  1662. X                if (old_mane_win == NULL) home(False);
  1663. X            }
  1664. X            break;
  1665. X
  1666. #ifndef X10
  1667. X        case MapNotify:        /* if running w/o WM */
  1668. X            if (mane.win == NULL) {
  1669. X            reconfig();
  1670. X            home(False);
  1671. X            }
  1672. X            break;
  1673. #endif
  1674. X
  1675. X        case KeyPress:
  1676. #ifndef X10
  1677. X            string = trbuf;
  1678. X            nbytes = XLookupString(&event.xkey, string, TRSIZE, NULL,
  1679. X            NULL);
  1680. #else
  1681. X            string = XLookupMapping(&event, &nbytes);
  1682. #endif
  1683. X            if (nbytes > 1) ch = '?';
  1684. X            if (nbytes != 0) ch = *string;
  1685. X            break;
  1686. X        }
  1687. #endif    /* TOOLKIT */
  1688. X        if (ch == '\0') continue;
  1689. X        if (ch >= '0' && ch <= '9') {
  1690. X        has_arg = True;
  1691. X        number = number * 10 + sign * (ch - '0');
  1692. X        continue;
  1693. X        }
  1694. X        else if (ch == '-') {
  1695. X        has_arg = True;
  1696. X        sign = -1;
  1697. X        number = 0;
  1698. X        continue;
  1699. X        }
  1700. X        number0 = number;
  1701. X        number = 0;
  1702. X        sign = 1;
  1703. X        arg0 = has_arg;
  1704. X        has_arg = False;
  1705. X        keystroke(ch, number0, arg0, &event);
  1706. X    }
  1707. }
  1708. X
  1709. static    void
  1710. redraw(windowrec)
  1711. X    struct WindowRec *windowrec;
  1712. {
  1713. X    char    *errtext;
  1714. #ifdef X10
  1715. X    static FontInfo *font = 0;
  1716. #endif
  1717. X
  1718. X    currwin = *windowrec;
  1719. X    min_x = currwin.min_x + currwin.base_x;
  1720. X    min_y = currwin.min_y + currwin.base_y;
  1721. X    max_x = currwin.max_x + currwin.base_x;
  1722. X    max_y = currwin.max_y + currwin.base_y;
  1723. X    can_exposures(windowrec);
  1724. X
  1725. X    if (debug & DBG_EVENT)
  1726. X        Printf("Redraw %d x %d at (%d, %d) (base=%d,%d)\n", max_x - min_x,
  1727. X        max_y - min_y, min_x, min_y, currwin.base_x, currwin.base_y);
  1728. X    SetCursor(redraw_cursor);
  1729. X    Flush();
  1730. X    if (errtext = (char *) setjmp(dvi_env)) {
  1731. X        ClearPage(mane);
  1732. #ifndef X10
  1733. X        get_xy();
  1734. X        XDrawString(DISP, WINDOW(mane), foreGC,
  1735. X        5 - window_x, 5 + X11HEIGHT - window_y,
  1736. X        errtext, strlen(errtext));
  1737. #else
  1738. X        if (!font) font = XOpenFont(X10FONT);
  1739. X        XTextMask(WINDOW(mane), 5, 5 + X10HEIGHT, errtext, strlen(errtext),
  1740. X        font->id, foreGC);
  1741. #endif
  1742. X        if (dvi_file) {
  1743. X        Fclose(dvi_file);
  1744. X        dvi_file = NULL;
  1745. X        }
  1746. X    }
  1747. X    else {
  1748. X        draw_page();
  1749. X        hush_spec_now = True;
  1750. X    }
  1751. }
  1752. X
  1753. void
  1754. redraw_page()
  1755. {
  1756. X    if (debug & DBG_EVENT) Fputs("Redraw page:  ", stdout);
  1757. X    get_xy();
  1758. X    ClearPage(mane);
  1759. X    mane.min_x = -window_x;
  1760. X    mane.max_x = -window_x + clip_w;
  1761. X    mane.min_y = -window_y;
  1762. X    mane.max_y = -window_y + clip_h;
  1763. X    redraw(&mane);
  1764. }
  1765. X
  1766. /*
  1767. X *    Interrupt system for receiving events.  The program sets a flag
  1768. X *    whenever an event comes in, so that at the proper time (i.e., when
  1769. X *    reading a new dvi item), we can check incoming events to see if we
  1770. X *    still want to go on printing this page.  This way, one can stop
  1771. X *    displaying a page if it is about to be erased anyway.  We try to read
  1772. X *    as many events as possible before doing anything and base the next
  1773. X *    action on all events read.
  1774. X *    Note that the Xlib and Xt routines are not reentrant, so the most we
  1775. X *    can do is set a flag in the interrupt routine and check it later.
  1776. X *    Also, sometimes the interrupts are not generated (some systems only
  1777. X *    guarantee that SIGIO is generated for terminal files, and on the system
  1778. X *    I use, the interrupts are not generated if I use "(xdvi foo &)" instead
  1779. X *    of "xdvi foo").  Therefore, there is also a mechanism to check the
  1780. X *    event queue every 70 drawing operations or so.  This mechanism is
  1781. X *    disabled if it turns out that the interrupts do work.
  1782. X *    For a fuller discussion of some of the above, see xlife in
  1783. X *    comp.sources.x.
  1784. X */
  1785. X
  1786. static    void
  1787. can_exposures(windowrec)
  1788. X    struct WindowRec *windowrec;
  1789. {
  1790. X    windowrec->min_x = windowrec->min_y = MAXDIM;
  1791. X    windowrec->max_x = windowrec->max_y = 0;
  1792. }
  1793. X
  1794. static    void
  1795. handle_intr() {
  1796. X    event_counter = 1;
  1797. X    event_freq = -1;    /* forget Plan B */
  1798. }
  1799. X
  1800. #ifdef    HAS_SIGIO
  1801. static    void
  1802. enable_intr() {
  1803. X    int    socket    = ConnectionNumber(DISP);
  1804. X    if (!isatty(0)) {
  1805. X        puts("trying...");
  1806. X        if (dup2(socket, 0) == -1) perror(prog);
  1807. X        socket = 0;
  1808. X    }
  1809. X    (void) signal(SIGIO, handle_intr);
  1810. X    (void) fcntl(socket, F_SETOWN, getpid());
  1811. X    (void) fcntl(socket, F_SETFL, fcntl(socket, F_GETFL, 0) | FASYNC);
  1812. }
  1813. #endif    /* HAS_SIGIO */
  1814. X
  1815. static    void
  1816. do_pages()
  1817. {
  1818. X    if (debug & DBG_BATCH) {
  1819. #ifdef    TOOLKIT
  1820. X        while (mane.min_x == MAXDIM) read_events(True);
  1821. #else    /* !TOOLKIT */
  1822. X        while (mane.min_x == MAXDIM)
  1823. X        if (setjmp(canit_env)) break;
  1824. X        else read_events(True);
  1825. #endif    /* TOOLKIT */
  1826. X        for (current_page = 0; current_page < total_pages; ++current_page)
  1827. X        redraw_page();
  1828. X    }
  1829. X    else {    /* normal operation */
  1830. #ifdef    HAS_SIGIO
  1831. X        enable_intr();
  1832. #endif
  1833. X        (void) setjmp(canit_env);
  1834. X        for (;;) {
  1835. X        if (mane.win) SetCursor(ready_cursor);
  1836. X        read_events(True);
  1837. X        if (canit) {
  1838. X            canit = False;
  1839. X            can_exposures(&mane);
  1840. X            can_exposures(&alt);
  1841. X            redraw_page();
  1842. X        }
  1843. X        else if (mag_moved) {
  1844. X            if (alt.win == NULL) mag_moved = False;
  1845. X            else if (abs(new_mag_x - mag_x) >
  1846. X            2 * abs(new_mag_y - mag_y))
  1847. X                movemag(new_mag_x, mag_y);
  1848. X            else if (abs(new_mag_y - mag_y) >
  1849. X            2 * abs(new_mag_x - mag_x))
  1850. X                movemag(mag_x, new_mag_y);
  1851. X            else movemag(new_mag_x, new_mag_y);
  1852. X        }
  1853. X        else if (alt.min_x < MAXDIM) redraw(&alt);
  1854. X        else if (mane.min_x < MAXDIM) redraw(&mane);
  1855. X        Flush();
  1856. X        }
  1857. X    }
  1858. }
  1859. X
  1860. static    volatile void
  1861. usage() {
  1862. #ifndef X10
  1863. #ifndef    VMS
  1864. #ifdef    BUTTONS
  1865. X    Fputs("\
  1866. Usage: xdvi [+[<page>]] [-s <shrink>] [-S <density>] [-p <pixels>] [-l] [-rv]\n\
  1867. X    [-expert] [-paper <papertype>] [-mgs[n] <size>] [-altfont <font>]\n\
  1868. X    [-margins <dimen>] [-sidemargin <dimen>] [-topmargin <dimen>]\n\
  1869. X    [-offsets <dimen>] [-xoffset <dimen>] [-yoffset <dimen>] [-keep]\n\
  1870. X    [-hushspecials] [-hushchars] [-hush]\n\
  1871. X    [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] \
  1872. [-cr <color>]\n\
  1873. X    [-bw <width>] [-geometry <geometry>] [-icongeometry <geometry>]\n\
  1874. X    [-iconic] [-display <host:display>] [-copy] [-thorough] dvi_file\n",
  1875. X    stderr);
  1876. #else    /* !BUTTONS */
  1877. X    Fputs("\
  1878. Usage: xdvi [+[<page>]] [-s <shrink>] [-S <density>] [-p <pixels>] [-l] [-rv]\n\
  1879. X    [-paper <papertype>] [-mgs[n] <size>] [-altfont <font>]\n\
  1880. X    [-margins <dimen>] [-sidemargin <dimen>] [-topmargin <dimen>]\n\
  1881. X    [-offsets <dimen>] [-xoffset <dimen>] [-yoffset <dimen>] [-keep]\n\
  1882. X    [-hushspecials] [-hushchars] [-hush]\n\
  1883. X    [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] \
  1884. [-cr <color>]\n\
  1885. X    [-bw <width>] [-geometry <geometry>] [-icongeometry <geometry>]\n\
  1886. X    [-iconic] [-display <host:display>] [-copy] [-thorough] dvi_file\n",
  1887. X    stderr);
  1888. #endif    /* BUTTONS */
  1889. #else    /* VMS */
  1890. X    Fputs("\
  1891. Usage: xdvi [+[<page>]] [-s <shrink>] [-density <%>] [-p <pixels>] [-l] [-rv]\n\
  1892. X    [-paper <papertype>] [-mgs[n] <size>] [-altfont <font>]\n\
  1893. X    [-margins <dimen>] [-sidemargin <dimen>] [-topmargin <dimen>]\
  1894. \n", stderr);
  1895. X    Fputs("\
  1896. X    [-offsets <dimen>] [-xoffset <dimen>] [-yoffset <dimen>] [-keep]\n\
  1897. X    [-hushspecials] [-hushchars] [-hush]\n\
  1898. X    [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] \
  1899. [-cr <color>]\n\
  1900. X    [-bw <width>] [-geometry <geometry>] [-icongeometry <geometry>]\n\
  1901. X    [-iconic] [-display <host::display>] [-copy] [-thorough] dvi_file\n",
  1902. SHAR_EOF
  1903. true || echo 'restore of xdvi.c failed'
  1904. fi
  1905. echo 'End of  part 1'
  1906. echo 'File xdvi.c is continued in part 2'
  1907. echo 2 > _shar_seq_.tmp
  1908. exit 0
  1909. -- 
  1910. --
  1911. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1912. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1913. Sunnyvale, California 94086            at&t: 408/522-9236
  1914.