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