home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / fermiVogle.tar.Z / fermiVogle.tar / devel / drivers / X11.c < prev    next >
C/C++ Source or Header  |  1996-03-12  |  24KB  |  1,240 lines

  1. /*
  2.  * VOGL/VOGLE driver for X11.
  3.  * 
  4.  * Define VOGLE if this driver is really for the VOGLE Libarary.
  5.  *
  6.  */
  7. #define VOGLE 1
  8.  
  9. #include <stdio.h>
  10. #include <X11/Xlib.h>
  11. #include <X11/Xutil.h>
  12.  
  13. #ifdef VOGLE
  14.  
  15. #include "vogle.h"
  16. static    char    *me = "vogle";
  17. #define LARGEFONT       "-adobe-courier-medium-r-normal--24-240-75-75-m-150-iso8859-1"
  18. #define SMALLFONT       "-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1"
  19.  
  20. #else
  21.  
  22. #include "vogl.h"
  23. static    char    *me = "vogl";
  24. #define LARGEFONT    "9x15bold"
  25. #define SMALLFONT    "6x13bold"
  26.  
  27. #endif
  28.  
  29. #define MIN(x,y)    ((x) < (y) ? (x) : (y))
  30. #define MAX(x,y)    ((x) > (y) ? (x) : (y))
  31. #define    CMAPSIZE    256
  32. #define    EV_MASK        KeyPressMask|ButtonReleaseMask|ExposureMask|ButtonPressMask
  33.  
  34. static    int        maxw = -1, maxh = -1;
  35. static    Window        winder;
  36. static    Display        *display;
  37. static    int        screen;
  38. static    unsigned long    carray[CMAPSIZE];
  39. static    Colormap    colormap;
  40.  
  41. static    Drawable    theDrawable = 0xffffffff;    /* (unsigned)-1 */
  42. static    GC        theGC;
  43. static    XGCValues    theGCvalues;
  44. static    Pixmap        bbuf;        /* Back buffer pixmap */
  45. static    int        back_used = 0;    /* Have we backbuffered ? */
  46.  
  47. static    XFontStruct    *font_id = (XFontStruct *)NULL;
  48. XEvent            event;
  49.  
  50. static    unsigned long    colour;
  51. static    unsigned int    h, w;
  52. static    char        *smallf, *largef;
  53. static    char        use_toolkit_win = 0;
  54.  
  55. int vo_xt_set_win( Display *, Drawable, int, int );
  56. int vo_xt_win( Display *, Window, int, int );
  57. void vo_xt_win_size(int xw, int xh);
  58. Display *vo_xt_get_display(void);
  59. Window vo_xt_get_window(void);
  60. GC vo_xt_get_GC(void);
  61. void vo_xt_set_GC(GC gc);
  62. static int X11_init(void);
  63. static int X11_exit(void);
  64. static void X11_draw(int x, int y);
  65. static void X11_pnt(int x, int y);
  66. static int X11_getkey(void);
  67. static int X11_checkkey(void);
  68. static int X11_locator(int *wx, int *wy);
  69. static void X11_clear(void);
  70. static void X11_color(int ind);
  71. static int X11_mapcolor(int i, int r, int g, int b);
  72. static int X11_font(char *fontfile);
  73. static void X11_char(char c);
  74. static void X11_string(char s[]);
  75. static void X11_fill(int n, int x[], int y[]);
  76. static int X11_backbuf(void);
  77. static void X11_swapbuf(void);
  78. static void X11_frontbuf(void);
  79. static void X11_sync(void);
  80. #ifdef VORTDUMP
  81. void X11_dump_pixmap(char *filename, int dx, int dy, int dw, int dh);
  82. #endif
  83. #ifndef VOGLE
  84. static void X11_setlw(int w);
  85. static void X11_setls(int lss);
  86. #else
  87. static void X11_setlw(int w);
  88. #endif
  89.  
  90. /*
  91.  * vo_xt_set_win
  92.  *
  93.  *    Just sets the drawable to the partucular window.
  94.  */
  95. int
  96. vo_xt_set_win(Display *dis, Drawable win, int xw, int xh)
  97. {
  98.     int    backb;
  99.  
  100.     backb = (theDrawable == bbuf);
  101.  
  102.     winder = win;
  103.  
  104.     vdevice.sizeX = vdevice.sizeY = MIN(xh, xw);
  105.     vdevice.sizeSx = xw;
  106.     vdevice.sizeSy = xh;
  107.  
  108.         if (xw > maxw || xh > maxh) {
  109.         if (back_used) {
  110.             back_used = 0;
  111.             XFreePixmap(display, bbuf);
  112.             X11_backbuf();
  113.         }
  114.         }
  115.  
  116.     display = dis;
  117.     if (backb)
  118.         theDrawable = bbuf;
  119.     else
  120.         theDrawable = win;
  121.  
  122.     return(1);
  123. }
  124.  
  125. /*
  126.  * vo_xt_window
  127.  *
  128.  *    Tells VOGL/VOGLE to use a window from an X11 toolkit (eg xview)
  129.  *    and not to make it's own window.
  130.  */
  131. int
  132. vo_xt_window(Display *dis, Window win, int xw, int xh)
  133. {
  134.     int    backb, i, depth;
  135.  
  136.     backb = (theDrawable == bbuf);
  137.  
  138.     display = dis;
  139.     winder = win;
  140.     screen = DefaultScreen(display);
  141.     colormap = DefaultColormap(display, screen);
  142.     depth = vdevice.depth = DefaultDepth(display, screen);
  143.     theDrawable = winder;
  144.  
  145.     use_toolkit_win = 1;
  146.     w = xw;
  147.     h = xh;
  148.  
  149.     /*
  150.      * Set our standard colors...
  151.      */
  152.     if (vdevice.depth == 1) {
  153.         /*
  154.          * Black and white - anything that's not black is white.
  155.          */
  156.         carray[0] = BlackPixel(display, screen);
  157.         for (i = 1; i < CMAPSIZE; i++)
  158.             carray[i] = WhitePixel(display, screen);
  159.     } else {
  160.         /*
  161.          * Color, try to get our colors close to what's in the
  162.          * default colormap.
  163.          */
  164.         X11_mapcolor(0, 0, 0, 0);
  165.         X11_mapcolor(1, 255, 0, 0);
  166.         X11_mapcolor(2, 0, 255, 0);
  167.         X11_mapcolor(3, 255, 255, 0);
  168.         X11_mapcolor(4, 0, 0, 255);
  169.         X11_mapcolor(5, 255, 0, 255);
  170.         X11_mapcolor(6, 0, 255, 255);
  171.         X11_mapcolor(7, 255, 255, 255);
  172.     }
  173.  
  174.     if ((smallf = XGetDefault(display, me, "smallfont")) == (char *)NULL)
  175.         smallf = SMALLFONT;
  176.  
  177.     if ((largef = XGetDefault(display, me, "largefont")) == (char *)NULL)
  178.         largef = LARGEFONT;
  179.  
  180.     /*
  181.      * Create Graphics Context and Drawable
  182.      */
  183.     theGC = XDefaultGC(display, screen);
  184.     theGCvalues.graphics_exposures = False;
  185.     theGCvalues.cap_style = CapButt;
  186.     XChangeGC(display, theGC, GCGraphicsExposures|GCCapStyle, &theGCvalues);
  187.     X11_color(0);
  188.  
  189.     vdevice.sizeX = vdevice.sizeY = MIN(xh, xw);
  190.     vdevice.sizeSx = xw;
  191.     vdevice.sizeSy = xh;
  192.  
  193.         if (back_used && (xw > maxw || xh > maxh)) {
  194.                 back_used = 0;
  195.         XFreePixmap(display, bbuf);
  196.                 X11_backbuf();
  197.         }
  198.  
  199.     if (backb)
  200.         theDrawable = bbuf;
  201.     else
  202.         theDrawable = win;
  203.  
  204.  
  205. #ifndef VOGLE
  206.     vdevice.devname = "X11";
  207. #endif
  208.  
  209.     return(1);
  210. }
  211.  
  212. /*
  213.  *    vo_xt_win_size
  214.  *
  215.  * If the X toolkit has changed the window size, then
  216.  * you might wish to call this routine to tell vogl/vogle about it.
  217.  */
  218. void
  219. vo_xt_win_size(int xw, int xh)
  220. {
  221.     char    backb;
  222.  
  223.     w = xw;
  224.     h = xh;
  225.  
  226.     vdevice.sizeX = vdevice.sizeY = MIN(h, w);
  227.     vdevice.sizeSx = w;
  228.     vdevice.sizeSy = h;
  229.  
  230.     backb = (theDrawable == bbuf);
  231.  
  232.     if (back_used) {
  233.  
  234.         /* Have to re allocate the back buffer */
  235.  
  236.         XFreePixmap(display, bbuf);
  237.  
  238.         bbuf = XCreatePixmap(display,
  239.             (Drawable)winder,
  240.             (unsigned int)vdevice.sizeSx,
  241.             (unsigned int)vdevice.sizeSy,
  242.             (unsigned int)vdevice.depth
  243.         );
  244.     }
  245.     if (backb)
  246.         theDrawable = (Drawable)bbuf;
  247. }
  248.  
  249. /*
  250.  * return the X display in use.
  251.  */
  252. Display *
  253. vo_xt_get_display(void)
  254. {
  255.     return(display);
  256. }
  257.  
  258. /*
  259.  * return the X Window in use.
  260.  */
  261. Window
  262. vo_xt_get_window(void)
  263. {
  264.     return(winder);
  265. }
  266.  
  267. /*
  268.  * return the Graphics Context in use.
  269.  */
  270. GC
  271. vo_xt_get_GC(void)
  272. {
  273.     return(theGC);
  274. }
  275.  
  276. /*
  277.  * Set the Graphics Context to use.
  278.  */
  279. void
  280. vo_xt_set_GC(GC gc)
  281. {
  282.     theGC = gc;
  283. }
  284.  
  285.  
  286. /*
  287.  * X11_init
  288.  *
  289.  *    initialises X11 display.
  290.  */
  291. static int
  292. X11_init(void)
  293. {
  294.     int        i;
  295.     int        x, y, prefx, prefy, prefxs, prefys;
  296.     unsigned int    bw, depth, mask;
  297.     Window        rootw, childw;
  298.     char        *av[2], name[128], *geom;
  299.  
  300.     XSetWindowAttributes    theWindowAttributes;
  301.     XWindowAttributes    retWindowAttributes;
  302.         XSizeHints              theSizeHints;
  303.         unsigned long           theWindowMask;
  304.     XWMHints                theWMHints;
  305.  
  306.  
  307.     if (use_toolkit_win)
  308.         return(1);
  309.  
  310.     av[0] = me;
  311.     av[1] = (char *)NULL;
  312.  
  313.     if ((display = XOpenDisplay((char *)NULL)) == (Display *)NULL) {
  314.         fprintf(stderr,"%s: X11_init: can't connect to X server\n", me);
  315.         exit(1);
  316.     }
  317.  
  318.     screen = DefaultScreen(display);
  319.     winder = RootWindow(display, screen);
  320.     colormap = DefaultColormap(display, screen);
  321.     depth = vdevice.depth = DefaultDepth(display, screen);
  322.  
  323.     /*
  324.      * Set our standard colors...
  325.      */
  326.     if (vdevice.depth == 1) {
  327.         /*
  328.          * Black and white - anything that's not black is white.
  329.          */
  330.         carray[0] = BlackPixel(display, screen);
  331.         for (i = 1; i < CMAPSIZE; i++)
  332.             carray[i] = WhitePixel(display, screen);
  333.     } else {
  334.         /*
  335.          * Color, try to get our colors close to what's in the
  336.          * default colormap.
  337.          */
  338.         X11_mapcolor(0, 0, 0, 0);
  339.         X11_mapcolor(1, 255, 0, 0);
  340.         X11_mapcolor(2, 0, 255, 0);
  341.         X11_mapcolor(3, 255, 255, 0);
  342.         X11_mapcolor(4, 0, 0, 255);
  343.         X11_mapcolor(5, 255, 0, 255);
  344.         X11_mapcolor(6, 0, 255, 255);
  345.         X11_mapcolor(7, 255, 255, 255);
  346.     }
  347.  
  348.     getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
  349.  
  350.     /*
  351.      * NEED TO USE XGRABPOINTER here???
  352.      */
  353.     XQueryPointer(display, winder, &rootw, &childw, &x, &y, &x, &y, &mask);
  354.  
  355.     if (childw == None)
  356.         childw = rootw;
  357.  
  358. /*
  359.     if (!XGetWindowAttributes(display, childw, &retWindowAttributes)) {
  360.         fprintf(stderr,"Can't get window attributes.");
  361.         exit(1);
  362.     }
  363.  
  364.     x = retWindowAttributes.x;
  365.     y = retWindowAttributes.y;
  366.     w = retWindowAttributes.width;
  367.     h = retWindowAttributes.height;
  368.     bw = retWindowAttributes.border_width;
  369.     depth = vdevice.depth = retWindowAttributes.depth;
  370.  
  371.     XTranslateCoordinates(display,
  372.             childw, retWindowAttributes.root,
  373.             0, 0,
  374.             &x, &y,
  375.             &rootw
  376.     );
  377. */
  378.  
  379.     XGetGeometry(display, childw, &rootw, &x, &y, &w, &h, &bw, &depth);
  380.  
  381.         theWindowAttributes.backing_store = WhenMapped;
  382.         theWindowAttributes.save_under = True;
  383.         theWindowAttributes.border_pixel = carray[1];
  384.  
  385.  
  386.     /*
  387.      * See if there is something in the .Xdefaults file regarding
  388.      * VOGL/VOGLE.
  389.      */
  390.  
  391.     if ((smallf = XGetDefault(display, me, "smallfont")) == (char *)NULL)
  392.         smallf = SMALLFONT;
  393.  
  394.     if ((largef = XGetDefault(display, me, "largefont")) == (char *)NULL)
  395.         largef = LARGEFONT;
  396.  
  397.     geom = XGetDefault(display, me, "Geometry");
  398.  
  399.     theSizeHints.flags = PPosition | PSize;
  400.  
  401.     if (geom != (char *)NULL) {
  402.  
  403.         theSizeHints.flags = 0;
  404.  
  405.         mask = XParseGeometry(geom, &x, &y, &w, &h);
  406.  
  407.         if (mask & XValue)
  408.             theSizeHints.flags |= USPosition;
  409.  
  410.         if (mask & YValue)
  411.             theSizeHints.flags |= USPosition;
  412.  
  413.         if (mask & WidthValue)
  414.             theSizeHints.flags |= USSize;
  415.  
  416.         if (mask & HeightValue)
  417.             theSizeHints.flags |= USSize;
  418.  
  419.         if (mask & XNegative)
  420.              x = DisplayWidth(display, screen) - 2*bw - w + x;
  421.  
  422.         if (mask & YNegative)
  423.             y = DisplayHeight(display, screen) - 2*bw - h + y;
  424.     }
  425.  
  426.     if (prefx > -1) {
  427.             x = prefx;
  428.             y = prefy;
  429.     }
  430.  
  431.     if (prefxs > -1) {
  432.             w = prefxs;
  433.             h = prefys;
  434.     }
  435.  
  436.     if (bw == 0)
  437.         bw = 4;
  438.  
  439.     x -= bw;
  440.     y -= bw;
  441.  
  442.     if (x <= 0)
  443.         x = 0;
  444.  
  445.     if (y <= 0)
  446.         y = 0;
  447.  
  448.     w -= 4 * bw;
  449.     h -= 4 * bw;
  450.  
  451.         theWindowMask = CWBorderPixel|CWBackingStore;
  452.  
  453.         winder = XCreateWindow(display,
  454.                                 winder,
  455.                                 x, y,
  456.                                 w, h,
  457.                                 bw,
  458.                                 (int)vdevice.depth,
  459.                                 InputOutput,
  460.                                 CopyFromParent,
  461.                                 theWindowMask,
  462.                                 &theWindowAttributes
  463.                         );
  464.  
  465.     XSetWindowColormap(display, winder, colormap);
  466.  
  467.         theSizeHints.x = x;
  468.         theSizeHints.y = y;
  469.         theSizeHints.width = w;
  470.         theSizeHints.height = h;
  471.  
  472. #ifndef VOGLE
  473.     if (vdevice.wintitle)
  474.         strcpy(name, vdevice.wintitle);
  475.     else
  476.         sprintf(name, "%s %d (win id 0x%x)", me, getpid(), winder);
  477. #else
  478.     sprintf(name, "%s %d (win id 0x%x)", me, getpid(), winder);
  479. #endif
  480.  
  481.     XSetStandardProperties(display,
  482.         winder,
  483.         name,
  484.         name,
  485.         None,
  486.         av,
  487.         1,
  488.         &theSizeHints
  489.     );
  490.  
  491.         theWMHints.initial_state = NormalState;
  492.         theWMHints.input = True;
  493.         theWMHints.flags = StateHint | InputHint;
  494.         XSetWMHints(display, winder, &theWMHints);
  495.  
  496.     XSelectInput(display, winder, EV_MASK);
  497.  
  498.     theDrawable = (Drawable)winder;
  499.  
  500.     /*
  501.      * Create Graphics Context and Drawable
  502.      */
  503.     theGC = XDefaultGC(display, screen);
  504.     theGCvalues.graphics_exposures = False;
  505.     theGCvalues.cap_style = CapButt;
  506.     XChangeGC(display, theGC, GCGraphicsExposures|GCCapStyle, &theGCvalues);
  507.     theDrawable = (Drawable)winder;
  508.     X11_color(0);
  509.  
  510.     XMapRaised(display, winder);
  511.     XFlush(display);
  512.  
  513.     /*
  514.      * Wait for Exposure event.
  515.     do {
  516.         XNextEvent(display, &event);
  517.     } while (event.type != Expose);
  518.      */
  519.     XWindowEvent(display, winder, ExposureMask, &event);
  520.  
  521.     /*
  522.      * Set the input Focus to us.
  523.  
  524.         if (prefx == -1 && prefxs == -1)
  525.                 XSetInputFocus(display, winder, RevertToParent, CurrentTime);
  526.      */
  527.  
  528.     /*
  529.      *  Let VOGL/VOGLE know about the window size.
  530.      *  (We may have been resized..... )
  531.      */
  532.     if (!XGetWindowAttributes(display, winder, &retWindowAttributes)) {
  533.         fprintf(stderr,"Can't get window attributes.");
  534.         exit(1);
  535.     }
  536.  
  537.     x = retWindowAttributes.x;
  538.     y = retWindowAttributes.y;
  539.     w = retWindowAttributes.width;
  540.     h = retWindowAttributes.height;
  541.  
  542.     XTranslateCoordinates(display,
  543.             winder, retWindowAttributes.root,
  544.             0, 0,
  545.             &x, &y,
  546.             &rootw
  547.     );
  548.  
  549.     vdevice.sizeX = vdevice.sizeY = MIN(h, w);
  550.     vdevice.sizeSx = w;
  551.     vdevice.sizeSy = h;
  552.  
  553.     if (back_used && (maxw < w || maxh < h)) {
  554.         back_used = 0;
  555.         X11_backbuf();
  556.     }
  557.  
  558.     return(1);
  559. }
  560.  
  561. /*
  562.  * X11_exit
  563.  *
  564.  *    cleans up before returning the window to normal.
  565.  */
  566. static int
  567. X11_exit(void)
  568. {
  569.     if (back_used) 
  570.         XFreePixmap(display, bbuf);
  571.  
  572.     back_used = 0;
  573.     bbuf = 0xffffffff;
  574.     maxw = maxh = -1;
  575.  
  576.     if (font_id != (XFontStruct *)NULL)
  577.         XFreeFont(display, font_id);
  578.  
  579.     font_id = (XFontStruct *)NULL;
  580.  
  581. #ifdef NEWCMAP
  582.     if (colormap != DefaultColormap(display, screen))
  583.         XFreeColormap(display, colormap)
  584.  
  585.     colormap = 0;
  586. #endif
  587.  
  588.     if (use_toolkit_win) {
  589.         use_toolkit_win = 0;
  590.         return(1);
  591.     }
  592.  
  593.     XDestroyWindow(display, winder);
  594.  
  595.     XSync(display, 0);
  596.  
  597.     XCloseDisplay(display);
  598.  
  599.     display = (Display *)NULL;
  600.     winder = 0;
  601.  
  602.     return(1);
  603. }
  604.  
  605. /*
  606.  * X11_draw
  607.  *
  608.  *    draws a line from the current graphics position to (x, y).
  609.  *
  610.  * Note: (0, 0) is defined as the top left of the window in X (easy
  611.  * to forget).
  612.  */
  613. static void
  614. X11_draw(int x, int y)
  615. {
  616.     if (x == vdevice.cpVx && y == vdevice.cpVy)
  617.         /*
  618.          * Hack for some X servers... my MIT X11 R5 manual states:
  619.          * CapButt    the results are device-dependent, but the
  620.          *        desired effect is that a single pixel is
  621.          *        drawn.
  622.          *
  623.          * This does work on a real MIT R5 server... but on some
  624.          * machines, we have to do this XDrawPoint thing.
  625.          * (It's probably faster this way anyway).
  626.          */
  627.         XDrawPoint(display, theDrawable, theGC, x, vdevice.sizeSy - y);
  628.     else
  629.         XDrawLine(display,
  630.             theDrawable,
  631.             theGC,
  632.             vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  633.             x, vdevice.sizeSy - y
  634.         );
  635.  
  636.     if (vdevice.sync)
  637.         XSync(display, 0);
  638. }
  639.  
  640. void
  641. X11_pnt(int x, int y)
  642. {
  643.     XDrawPoint(display,
  644.         theDrawable,
  645.         theGC,
  646.         x, vdevice.sizeSy - y
  647.     );
  648.  
  649.     if (vdevice.sync)
  650.         XSync(display, 0);
  651. }
  652.  
  653. /*
  654.  * X11_getkey
  655.  *
  656.  *    grab a character from the keyboard - blocks until one is there.
  657.  */
  658. static int
  659. X11_getkey(void)
  660. {
  661.     char    c;
  662.  
  663.     do {
  664.         XNextEvent(display, &event);
  665.         if (event.type == KeyPress) {
  666.             if (XLookupString((XKeyEvent *)&event, &c, 1, NULL, NULL) > 0)
  667.                 return((int)c);
  668.             else
  669.                 return(0);
  670.         }
  671.     } while (event.type != KeyPress);
  672. }
  673.  
  674. /*
  675.  * X11_checkkey
  676.  *
  677.  *    Check if there has been a keyboard key pressed.
  678.  *    and return it if there is.
  679.  */
  680. static int
  681. X11_checkkey(void)
  682. {
  683.     char    c;
  684.  
  685.     if (!XCheckWindowEvent(display, winder, KeyPressMask, &event))
  686.         return(0);
  687.  
  688.     if (event.type == KeyPress)
  689.         if (XLookupString((XKeyEvent *)&event, &c, 1, NULL, NULL) > 0)
  690.             return((int)c);
  691.  
  692.     return(0);
  693. }
  694.  
  695. /*
  696.  * X11_locator
  697.  *
  698.  *    return the window location of the cursor, plus which mouse button,
  699.  * if any, is been pressed.
  700.  */
  701. static int
  702. X11_locator(int *wx, int *wy)
  703. {
  704.     Window        rootw, childw;
  705.     int        x, y;
  706.     unsigned int    mask;
  707.  
  708.     XQueryPointer(display, winder, &rootw, &childw, &x, &y, wx, wy, &mask);
  709.  
  710.     *wy = (int)vdevice.sizeSy - *wy;
  711.  
  712.     return(mask >> 8);
  713. }
  714.  
  715. #ifdef VOGLE
  716. /*
  717.  * X11_clear
  718.  *
  719.  * Clear the screen (or current buffer )to current colour
  720.  */
  721. static void
  722. X11_clear(void)
  723. {
  724.     XSetBackground(display, theGC, colour);
  725.     XFillRectangle(display,
  726.         theDrawable,
  727.         theGC,
  728.         0,
  729.         0,
  730.         (unsigned int)vdevice.sizeSx,
  731.         (unsigned int)vdevice.sizeSy
  732.     );
  733.  
  734.     if (vdevice.sync)
  735.         XFlush(display);
  736. }
  737.  
  738. #else 
  739.  
  740. /*
  741.  * X11_clear
  742.  *
  743.  * Clear the screen (or current buffer )to current colour
  744.  */
  745. static void
  746. X11_clear(void)
  747. {
  748.     unsigned int    w = vdevice.maxVx - vdevice.minVx;
  749.     unsigned int    h = vdevice.maxVy - vdevice.minVy;
  750.  
  751.     XSetBackground(display, theGC, colour);
  752.  
  753.     XFillRectangle(display,
  754.         theDrawable,
  755.         theGC,
  756.         vdevice.minVx,
  757.         vdevice.sizeSy - vdevice.maxVy - 1, 
  758.         w + 1, 
  759.         h + 1
  760.     );
  761.  
  762.     if (vdevice.sync)
  763.         XFlush(display);
  764. }
  765. #endif
  766.  
  767. /*
  768.  * X11_color
  769.  *
  770.  *    set the current drawing color index.
  771.  */
  772. static void
  773. X11_color(int ind)
  774. {
  775.     colour = carray[ind];
  776.     XSetForeground(display, theGC, colour);
  777. }
  778.  
  779. /*
  780.  * X11_mapcolor
  781.  *
  782.  *    change index i in the color map to the appropriate r, g, b, value.
  783.  */
  784. static int
  785. X11_mapcolor(int i, int r, int g, int b)
  786. {
  787.     int    stat;
  788.     XColor    tmp;
  789.  
  790.     if (i >= CMAPSIZE)
  791.         return(-1);
  792.  
  793.  
  794.     /*
  795.      * For Black and White.
  796.      * If the index is 0 and r,g,b != 0 then we are remapping black.
  797.      * If the index != 0 and r,g,b == 0 then we make it black.
  798.      */
  799.     if (vdevice.depth == 1) {
  800.         if (i == 0 && (r != 0 || g != 0 || b != 0)) 
  801.             carray[i] = WhitePixel(display, screen);
  802.         else if (i != 0 && r == 0 && g == 0 && b == 0)
  803.             carray[i] = BlackPixel(display, screen);
  804.     } else {
  805.         tmp.red = (unsigned short)(r / 255.0 * 65535);
  806.         tmp.green = (unsigned short)(g / 255.0 * 65535);
  807.         tmp.blue = (unsigned short)(b / 255.0 * 65535);
  808.         tmp.flags = 0;
  809.         tmp.pixel = (unsigned long)i;
  810.  
  811.         if ((stat = XAllocColor(display, colormap, &tmp)) == 0) {
  812. #ifdef NEWCMAP
  813.             colormap = XCopyColormapAndFree(display, colormap);
  814.             XSetWindowColormap(display, winder, colormap);
  815. #else
  816.             fprintf(stderr, "XAllocColor failed (status = %d)\n", stat);
  817.  
  818.             exit(1);
  819. #endif
  820.         }
  821.         carray[i] = tmp.pixel;
  822.     }
  823.  
  824.     XFlush(display);
  825.     return(0);
  826. }
  827.     
  828. /*
  829.  * X11_font
  830.  *
  831.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  832.  *
  833.  */
  834. static int
  835. X11_font(char *fontfile)
  836. {
  837.     XGCValues    xgcvals;
  838.     char    *name = fontfile;
  839.  
  840.     if (font_id != (XFontStruct *)NULL)
  841.         XFreeFont(display, font_id);
  842.  
  843.     if (strcmp(fontfile, "small") == 0) {
  844.         if ((font_id = XLoadQueryFont(display, smallf)) == (XFontStruct *)NULL) {
  845.             fprintf(stderr, "%s X11.c couldn't open small font '%s'\n", me, smallf);
  846.             fprintf(stderr, "You'll have to redefine it....\n");
  847.             return(0);
  848.         } else
  849.             name = smallf;
  850.         
  851.     } else if (strcmp(fontfile, "large") == 0) {
  852.         if ((font_id = XLoadQueryFont(display, largef)) == (XFontStruct *)NULL) {
  853.             fprintf(stderr, "%s X11.c couldn't open large font '%s'\n", me, largef);
  854.             fprintf(stderr, "You'll have to redefine it....\n");
  855.             return(0);
  856.         }
  857.             name = largef;
  858.     } else {
  859.         if ((font_id = XLoadQueryFont(display, fontfile)) == (XFontStruct *)NULL) {
  860.             fprintf(stderr, "%s X11.c couldn't open fontfile '%s'\n", me, fontfile);
  861.             return(0);
  862.         }
  863.     }
  864.  
  865.     /*
  866.     vdevice.hheight = font_id->max_bounds.ascent + font_id->max_bounds.descent;
  867.     */
  868.     vdevice.hheight = font_id->ascent + font_id->descent;
  869.     vdevice.hwidth = font_id->max_bounds.width;
  870.  
  871.  
  872.     xgcvals.font = XLoadFont(display, name);
  873.     XChangeGC(display, theGC, GCFont, &xgcvals);
  874.  
  875.     return(1);
  876. }
  877.  
  878. /* 
  879.  * X11_char
  880.  *
  881.  *     outputs one char - is more complicated for other devices
  882.  */
  883. static void
  884. X11_char(char c)
  885. {
  886.     XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), &c, 1);
  887.  
  888.     if (vdevice.sync)
  889.         XFlush(display);
  890. }
  891.  
  892. /*
  893.  * X11_string
  894.  *
  895.  *    Display a string at the current drawing position.
  896.  */
  897. static void
  898. X11_string(char s[])
  899. {
  900.     XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, strlen(s));
  901.     if (vdevice.sync)
  902.         XFlush(display);
  903. }
  904.  
  905. /*
  906.  * X11_fill
  907.  *
  908.  *    fill a polygon
  909.  */
  910. static void
  911. X11_fill(int n, int x[], int y[])
  912. {
  913.     char    buf[BUFSIZ];
  914.     XPoint    plist[128];
  915.     int    i;
  916.  
  917.     if (n > 128) {
  918.         sprintf(buf, "%s: more than 128 points in a polygon", me);
  919.         verror(buf);
  920.     }
  921.  
  922.     for (i = 0; i < n; i++) {
  923.         plist[i].x = x[i];
  924.         plist[i].y = vdevice.sizeSy - y[i];
  925.     }
  926.  
  927.     XFillPolygon(display, theDrawable, theGC, plist, n, Nonconvex, CoordModeOrigin);
  928.  
  929.     vdevice.cpVx = x[n-1];
  930.     vdevice.cpVy = y[n-1];
  931.  
  932.     if (vdevice.sync)
  933.         XFlush(display);
  934. }
  935.  
  936. /*
  937.  * X11_backbuf
  938.  *
  939.  *    Set up double buffering by allocating the back buffer and
  940.  *    setting drawing into it.
  941.  */
  942. static int
  943. X11_backbuf(void)
  944. {
  945.     if (!back_used) {
  946.         bbuf = XCreatePixmap(display,
  947.             (Drawable)winder,
  948.             (unsigned int)vdevice.sizeSx,
  949.             (unsigned int)vdevice.sizeSy,
  950.             (unsigned int)vdevice.depth
  951.         );
  952.  
  953.         maxw = MAX(vdevice.sizeSx, maxw);
  954.         maxh = MAX(vdevice.sizeSy, maxh);
  955.     }
  956.  
  957.     theDrawable = (Drawable)bbuf;
  958.  
  959.     back_used = 1;
  960.  
  961.     return(1);
  962. }
  963.  
  964. /*
  965.  * X11_swapbuf
  966.  *
  967.  *    Swap the back and from buffers. (Really, just copy the
  968.  *    back buffer to the screen).
  969.  */
  970. static void
  971. X11_swapbuf(void)
  972. {
  973.     XCopyArea(display,
  974.         theDrawable,
  975.         winder,
  976.         theGC,
  977.         0, 0,
  978.         (unsigned int)vdevice.sizeSx,
  979.         (unsigned int)vdevice.sizeSy,
  980.         0, 0
  981.     );
  982.     XSync(display, 0);
  983. }
  984.  
  985. /*
  986.  * X11_frontbuf
  987.  *
  988.  *    Make sure we draw to the screen.
  989.  */
  990. static void
  991. X11_frontbuf(void)
  992. {
  993.     theDrawable = (Drawable)winder;
  994. }
  995.  
  996. /*
  997.  * Syncronise the display with what we think has been sent to it...
  998.  */
  999. static void
  1000. X11_sync(void)
  1001. {
  1002.     XSync(display, 0);
  1003. }
  1004.  
  1005. #undef VORTDUMP
  1006. #ifdef VORTDUMP
  1007. /*
  1008.  * HACK
  1009.  * Dump the contents of the current buffer to a VORT file....
  1010.  * ONLY WORKS WITH 8Bit Drawables!
  1011.  */
  1012. #include "vort.h"
  1013.  
  1014. void
  1015. X11_dump_pixmap(char *filename, int dx, int dy, int dw, int dh)
  1016. {
  1017.     XImage    *ximage;
  1018.     image    *im;
  1019.     unsigned char    *line, *rm, *gm, *bm;
  1020.     XColor    *cols;
  1021.     int    i;
  1022.  
  1023.     if (dw > vdevice.sizeSx || dw < 0)
  1024.         dw = vdevice.sizeSx;
  1025.     if (dh > vdevice.sizeSy || dh < 0)
  1026.         dh = vdevice.sizeSy;
  1027.  
  1028.     if (dx > vdevice.sizeSx || dx < 0)
  1029.         dx = 0;
  1030.     if (dy > vdevice.sizeSy || dy < 0)
  1031.         dy = 0;
  1032.  
  1033.     ximage = XGetImage(display, 
  1034.             theDrawable, 
  1035.             dx, dy,
  1036.             (unsigned int)dw,
  1037.             (unsigned int)dh,
  1038.             AllPlanes,
  1039.             ZPixmap
  1040.         );
  1041.  
  1042.     if (!ximage) {
  1043.         fprintf(stderr, "X11_dump_pixmap: can't do XGetImage\n");
  1044.         exit(1);
  1045.     }
  1046.  
  1047.     if ((im = openimage(filename, "w")) == (image *)NULL) {
  1048.         fprintf(stderr, "X11_dump_pixmap: can't open %s\n", filename);
  1049.         exit(1);
  1050.     }
  1051.  
  1052.     if (!(rm = (unsigned char *)malloc(256))) {
  1053.         fprintf(stderr, "X11_dump_pixmap: can't alloc rm\n");
  1054.         exit(1);
  1055.     }
  1056.     if (!(gm = (unsigned char *)malloc(256))) {
  1057.         fprintf(stderr, "X11_dump_pixmap: can't alloc gm\n");
  1058.         exit(1);
  1059.     }
  1060.     if (!(bm = (unsigned char *)malloc(256))) {
  1061.         fprintf(stderr, "X11_dump_pixmap: can't alloc bm\n");
  1062.         exit(1);
  1063.     }
  1064.     if (!(cols = (XColor *)malloc(256 * sizeof(XColor)))) {
  1065.         fprintf(stderr, "X11_dump_pixmap: can't alloc cols\n");
  1066.         exit(1);
  1067.     }
  1068.  
  1069.     /*
  1070.      * Get our colormap...
  1071.      */
  1072.     for (i = 0; i < 256; i++) {
  1073.         cols[i].pixel = (unsigned long)i;
  1074.         cols[i].red = cols[i].green = cols[i].blue = 0;
  1075.         cols[i].flags = DoRed | DoGreen | DoBlue;
  1076.     }
  1077.  
  1078.     XQueryColors(display, colormap, cols, 256);
  1079.  
  1080.     for (i = 0; i < 256; i++) {
  1081.         rm[i] = (unsigned char)(cols[i].red >> 8);
  1082.         gm[i] = (unsigned char)(cols[i].green >> 8);
  1083.         bm[i] = (unsigned char)(cols[i].blue >> 8);
  1084.     }
  1085.  
  1086.     imagetype(im) = PIX_RLECMAP;
  1087.     imageheight(im) = dh;
  1088.     imagewidth(im) = dw;
  1089.     imagedate(im) = time(0);
  1090.     titlelength(im) = 0;
  1091.     setcmap(im, 256, rm, gm, bm);
  1092.  
  1093.     writeheader(im);
  1094.  
  1095.     line = (unsigned char *)ximage->data;
  1096.     for (i = 0; i < dh; i++) {
  1097.         writemappedline(im, line);
  1098.         line += ximage->bytes_per_line;
  1099.     }
  1100.     
  1101.     closeimage(im); 
  1102.  
  1103.     free(rm);
  1104.     free(gm);
  1105.     free(bm);
  1106.     free(cols);
  1107. }
  1108.  
  1109. #endif
  1110.  
  1111. #ifndef VOGLE
  1112. /*
  1113.  * X11_setlw
  1114.  *
  1115.  *    Set the line width....
  1116.  */
  1117. static void
  1118. X11_setlw(int w)
  1119. {
  1120.     XGCValues vals;
  1121.  
  1122.     vals.line_width = w;
  1123.     XChangeGC(display, theGC, GCLineWidth, &vals);
  1124. }
  1125.  
  1126. /*
  1127.  * X11_setls
  1128.  *
  1129.  *    Set the line style....
  1130.  */
  1131. static void
  1132. X11_setls(int lss)
  1133. {
  1134.     unsigned ls = lss;
  1135.     char    dashes[16];
  1136.     int    i, n, a, b, offset;
  1137.  
  1138.     if (ls == 0xffff) {
  1139.         XSetLineAttributes(display, theGC, vdevice.attr->a.lw, LineSolid, CapButt, JoinMiter);
  1140.         return;
  1141.     }
  1142.  
  1143.     for (i = 0; i < 16; i++)
  1144.         dashes[i] = 0;
  1145.  
  1146.     for (i = 0; i < 16; i++)    /* Over 16 bits */
  1147.         if ((ls & (1 << i)))
  1148.             break;
  1149.  
  1150.     offset = i;
  1151.  
  1152. #define    ON    1
  1153. #define    OFF    0
  1154.         
  1155.     a = b = OFF;
  1156.     if (ls & (1 << 0))
  1157.         a = b = ON;
  1158.  
  1159.     n = 0;
  1160.     for (i = 0; i < 16; i++) {    /* Over 16 bits */
  1161.         if (ls & (1 << i))
  1162.             a = ON;
  1163.         else
  1164.             a = OFF;
  1165.  
  1166.         if (a != b) {
  1167.             b = a;
  1168.             n++;
  1169.         }
  1170.         dashes[n]++;
  1171.     }
  1172.     n++;
  1173.  
  1174.     XSetLineAttributes(display, theGC, vdevice.attr->a.lw, LineOnOffDash, CapButt, JoinMiter);
  1175.     XSetDashes(display, theGC, offset, dashes, n);
  1176. }
  1177.  
  1178. #else
  1179. /*
  1180.  * X11_setlw (this one for VOGLE only)
  1181.  *
  1182.  *    Set the line width....THICK or THIN
  1183.  */
  1184. static void
  1185. X11_setlw(int w)
  1186. {
  1187.     XGCValues vals;
  1188.  
  1189.     if (w == 0)
  1190.         w = 1;
  1191.     else if (w == 1)
  1192.         w = 2;
  1193.  
  1194.     vals.line_width = w;
  1195.     XChangeGC(display, theGC, GCLineWidth, &vals);
  1196. }
  1197.  
  1198. #endif 
  1199.  
  1200. /*
  1201.  * the device entry
  1202.  */
  1203. static DevEntry X11dev = {
  1204.     "X11",
  1205.     "large",
  1206.     "small",
  1207.     X11_backbuf,
  1208.     X11_char,
  1209.     X11_checkkey,
  1210.     X11_clear,
  1211.     X11_color,
  1212.     X11_draw,
  1213.     X11_exit,
  1214.     X11_fill,
  1215.     X11_font,
  1216.     X11_frontbuf,
  1217.     X11_getkey,
  1218.     X11_init,
  1219.     X11_locator,
  1220.     X11_mapcolor,
  1221. #ifndef VOGLE
  1222.     X11_setls,
  1223. #endif
  1224.     X11_setlw,
  1225.     X11_string,
  1226.     X11_swapbuf,
  1227.     X11_sync
  1228. };
  1229.  
  1230. /*
  1231.  * _X11_devcpy
  1232.  *
  1233.  *    copy the X11 device into vdevice.dev.
  1234.  */
  1235. void
  1236. _X11_devcpy(void)
  1237. {
  1238.     vdevice.dev = X11dev;
  1239. }
  1240.