home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / web2c / mf / MFwindow / x11-Xlib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-28  |  9.1 KB  |  275 lines

  1. /*
  2. X Window System version 11 (release 3 et al.) interface for Metafont.
  3.  
  4. Modified from Tim Morgan's X Version 11 routines by Richard Johnson.
  5. Modified from that by Karl Berry <karl@umb.edu>.  8/3/89
  6.  
  7. MF can now understand geometry (sort of, at least on a Sun running 3.4
  8. and using uwm) in the resource database, as in the following in
  9. .Xdefaults to put a window of width 500 and height 600 at (200,50):
  10.  
  11. Metafont*geometry: 500x600+200+200
  12.  
  13. You cannot give the geometry on the command line (who would want to)?
  14.  
  15. The width and height specified in the resource must not be larger than
  16. the screenwidth and screendepth defined in ../mf/cmf.ch.
  17. If they are, then I reset them to the maximum.
  18.  
  19. We don't handle Expose events in general. This means that the window
  20. cannot be moved, resized, or obscured. The problem is that I don't know
  21. when we can look for such events. Adding a check to the main loop of
  22. Metafont was more than I wanted to do. Another problem is that Metafont
  23. does not keep track of the contents of the screen, and so I don't see
  24. how to know what to redraw. The right way to do this is probably to fork
  25. a process, and keep a Pixmap around of the contents of the window.
  26.  
  27. I could never have done this without David Rosenthal's Hello World
  28. program for X. See $X/mit/doc/HelloWorld.
  29.  
  30. All section numbers refer to Xlib -- C Language X Interface.  */
  31.  
  32.  
  33. #define    EXTERN    extern
  34. #include "../mfd.h"
  35.  
  36.  
  37. #ifdef    X11WIN
  38.  
  39. #include <X11/Xatom.h>
  40. #include <X11/Xlib.h>
  41. #include <X11/Xutil.h>
  42.  
  43.  
  44. /* Variables for communicating between the routines we'll write.  */
  45.  
  46. static Display *my_display;
  47. static int my_screen;
  48. static Window my_window;
  49. static GC my_gc;
  50. static int white, black;
  51.  
  52.  
  53. /* Window manager hints.  */
  54.  
  55. static XWMHints wm_hints = {
  56.    (InputHint|StateHint), /* flags telling which values are set */
  57.    False, /* We don't expect input. */
  58.    NormalState, /* Initial state. */
  59.    0, /* icon pixmap */
  60.    0, /* icon window */
  61.    0, 0, /* icon location (should get from resource?) */
  62.    0, /* icon mask */
  63.    0 /* window group */
  64. };
  65.  
  66.  
  67. /* Some constants for the resource database, etc.  */
  68. #define PROGRAM_NAME "Metafont"
  69. #define ARG_GEOMETRY "geometry"
  70. #define BORDER_WIDTH 1 /* Should get this from resource. */
  71. #define DEFAULT_X_POSITION 0
  72. #define DEFAULT_Y_POSITION 0
  73.  
  74.  
  75. /* Return 1 (i.e., true) if display opened successfully, else 0.  */
  76.  
  77. int
  78. mf_x11_initscreen()
  79. {
  80.     char *geometry;
  81.     int geometry_found = 0;
  82.     char default_geometry[100];
  83.     XSizeHints sizehints;
  84.     XGCValues gcvalues;
  85.  
  86.     /* We want the default display. (section 2.1 Opening the display)  */
  87.     my_display = XOpenDisplay(NULL);
  88.     if (my_display == NULL) return 0;
  89.     
  90.     /* Given a display, we can get the screen and the ``black'' and
  91.        ``white'' pixels.  (section 2.2.1 Display macros)  */
  92.     my_screen = DefaultScreen(my_display);     
  93.     white = WhitePixel(my_display, my_screen);
  94.     black = BlackPixel(my_display, my_screen);
  95.     
  96.     
  97.     sizehints.x = DEFAULT_X_POSITION;
  98.     sizehints.y = DEFAULT_Y_POSITION;
  99.     sizehints.width = screenwidth;
  100.     sizehints.height = screendepth;
  101.     sizehints.flags = PPosition|PSize;
  102.  
  103.     sprintf (default_geometry, "%ux%u+%u+%u", screenwidth, screendepth,
  104.                                DEFAULT_X_POSITION, DEFAULT_Y_POSITION);
  105.  
  106.     /* Look up the geometry for this window. (Section 10.2 Obtaining X
  107.        environment defaults)  */
  108.     geometry = XGetDefault(my_display, PROGRAM_NAME, ARG_GEOMETRY);
  109.     
  110.     if (geometry != NULL) {
  111.        /* (section 10.3 Parsing window geometry) */
  112.        int bitmask = XGeometry(my_display, my_screen,
  113.                    geometry, default_geometry,
  114.                                BORDER_WIDTH,
  115.                                1, 1, /* ``Font'' width and height. */
  116.                                0, 0, /* Interior padding. */
  117.                                &(sizehints.x), &(sizehints.y),
  118.                                &(sizehints.width), &(sizehints.height));
  119.        
  120.        /* (section 9.1.6 Setting and getting window sizing hints)  */
  121.        if (bitmask & (XValue|YValue)) {
  122.           sizehints.flags |= USPosition;
  123.           geometry_found = 1;
  124.        }
  125.        
  126.        if (bitmask & (WidthValue|HeightValue)) {
  127.           sizehints.flags |= USSize;
  128.           if (sizehints.width > screenwidth) sizehints.width = screenwidth;
  129.           if (sizehints.height > screendepth) sizehints.height = screendepth;
  130.           geometry_found = 1;
  131.        }
  132.     }
  133.     
  134.     
  135.     /* Our window is pretty simple. (section 3.3 Creating windows)  */
  136.     my_window = XCreateSimpleWindow(my_display,
  137.                           DefaultRootWindow(my_display), /* parent */
  138.                           sizehints.x, sizehints.y, /* upper left */
  139.                           sizehints.width, sizehints.height,
  140.                           BORDER_WIDTH,
  141.               black, /* border color */
  142.                           white); /* background color */
  143.     
  144.     /* (section 9.1.1 Setting standard properties)  */
  145.     XSetStandardProperties(my_display, my_window, 
  146.                            PROGRAM_NAME,  /* window name */
  147.                            PROGRAM_NAME,  /* icon name */
  148.                None,  /* pixmap for icon */
  149.                            0, 0,  /* argv and argc for restarting */
  150.                            &sizehints);
  151.     XSetWMHints(my_display, my_window, &wm_hints);
  152.     
  153.     
  154.     /* We need a graphics context if we're going to draw anything.
  155.        (section 5.3 Manipulating graphics context/state)  */
  156.     gcvalues.foreground = black;
  157.     gcvalues.background = white;
  158.     /* A ``thin'' line.  This is much faster than a line of length 1,
  159.        although the manual cautions that the results might be less
  160.        consistent across screens.  */
  161.     gcvalues.line_width = 0;
  162.     
  163.     my_gc = XCreateGC(my_display, my_window,
  164.               GCForeground|GCBackground|GCLineWidth,
  165.               &gcvalues);
  166.     
  167.     /* (section 3.5 Mapping windows)  This is the confusing part of the
  168.     program, at least to me. If no geometry spec was found, then the
  169.     window manager puts up the blinking rectangle, and the user clicks,
  170.     all before the following call returns. But if a geometry spec was
  171.     found, then we want to do a whole mess of other things, because the
  172.     window manager is going to send us an expose event so that we can
  173.     bring our window up -- and this is one expose event we have to
  174.     handle.  */
  175.     XMapWindow(my_display, my_window);
  176.  
  177.     if (geometry_found) {
  178.        /* The window manager sends us an Expose event. Yuck.
  179.        */
  180.        XEvent my_event;
  181.        /* We certainly don't want to handle anything else.
  182.           (section 8.5 Selecting events)
  183.        */
  184.        XSelectInput(my_display, my_window, ExposureMask);
  185.  
  186.        /* We also want to do this right now. This is the confusion. From
  187.           stepping through the program under the debugger, it appears
  188.           that it is this call to XSync (given the previous call to
  189.           XSelectInput) that actually brings the window up -- and yet
  190.           without the remaining code, the thing doesn't work right. Very
  191.           strange. (section 8.6 Handling the output buffer)  
  192.        */
  193.        XSync(my_display, 0);
  194.  
  195.        /* Now get the event. (section 8.8.1 Returning the next event)
  196.        */
  197.        XNextEvent(my_display, &my_event);
  198.        
  199.        /* Ignore all but the last of the Expose events.
  200.           (section 8.4.5.1 Expose event processing)
  201.        */
  202.        if (my_event.type == Expose && my_event.xexpose.count == 0) {
  203.           /* Apparently the network might STILL have my_events coming in.
  204.              Let's throw away Expose my_events again. (section 8.8.3
  205.              Selecting my_events using a window or my_event mask)
  206.           */
  207.           while (XCheckTypedEvent(my_display, Expose, &my_event)) ;
  208.  
  209.           /* Finally, let's draw the blank screen.
  210.           */
  211.           XClearWindow(my_display, my_window);
  212.        }
  213.    }
  214.     
  215.     /* That's it.  */
  216.     return 1;
  217. }
  218.  
  219.  
  220. /* Make sure the screen is up to date. (section 8.6 Handling the output
  221. buffer)  */
  222.  
  223. mf_x11_updatescreen()
  224. {
  225.     XFlush(my_display);
  226. }
  227.  
  228.  
  229. /* Blank the rectangular inside the given coordinates. We don't need to
  230. reset the foreground to black because we always set it at the beginning
  231. of paintrow (below).  */
  232.  
  233. mf_x11_blankrectangle(left, right, top, bottom)
  234.     screencol left, right;
  235.     screenrow top, bottom;
  236. {
  237.     XSetForeground(my_display, my_gc, white);
  238.     XFillRectangle(my_display, my_window, my_gc,
  239.                    (int) left,
  240.                    (int) top,
  241.                   (unsigned) (right - left + 1),
  242.                    (unsigned) (bottom - top + 1));
  243. }
  244.  
  245.  
  246. /* Paint a row with the given ``transition specifications''. We might be
  247. able to do something here with drawing many lines.  */
  248.  
  249. mf_x11_paintrow(row, init_color, tvect, vector_size)
  250.     screenrow row;
  251.     pixelcolor init_color;
  252.     transspec tvect;
  253.     register screencol vector_size;
  254. {
  255.     register int color, col;
  256.  
  257.     color = (init_color == 0) ? white : black;
  258.  
  259.     do {
  260.     col = *tvect++;
  261.     XSetForeground(my_display, my_gc, color);
  262.         
  263.         /* (section 6.3.2 Drawing single and multiple lines)
  264.         */
  265.     XDrawLine(my_display, my_window, my_gc, col, (int) row,
  266.           (int) (*tvect-1), (int) row);
  267.                   
  268.         color = (color == white) ? black : white;
  269.     } while (--vector_size > 0);
  270. }
  271.  
  272. #else
  273. int x11_dummy;
  274. #endif /* X11WIN */
  275.