home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / avogl.tar.gz / avogl.tar / vogl / drivers / X11.c < prev   
C/C++ Source or Header  |  1992-09-22  |  12KB  |  640 lines

  1. /*
  2.  * VOGLE driver for X11.
  3.  */
  4. #include <stdio.h>
  5. #include <X11/Xlib.h>
  6. #include <X11/Xutil.h>
  7.  
  8. #include "vogl.h"
  9.  
  10. #define LARGEX11R2    "courier12f.snf"
  11. #define SMALLX11R2    "courier10f.snf"
  12.  
  13. #define LARGEX11R3    "9x15bold"
  14. #define SMALLX11R3    "6x13bold"
  15.  
  16.  
  17. #define MIN(x,y)    ((x) < (y) ? (x) : (y))
  18. #define    CMAPSIZE    256
  19. #define    EV_MASK        KeyPressMask|ButtonReleaseMask|ExposureMask|ButtonPressMask
  20.  
  21. static    Window        winder;
  22. static    Display        *display;
  23. static    int        screen;
  24. static    unsigned long    carray[CMAPSIZE];
  25. static    Colormap    colormap;
  26.  
  27. static    Drawable    theDrawable;
  28. static    GC        theGC;
  29. static    Pixmap        bbuf;        /* Back buffer pixmap */
  30. static    int        back_used;    /* Have we backbuffered ? */
  31.  
  32. static    XFontStruct    *font_id;
  33. XEvent            event;
  34.  
  35. static    int        size;
  36. static    unsigned long    colour;
  37. static    unsigned int    h, w;
  38.  
  39. /*
  40.  * X11_init
  41.  *
  42.  *    initialises X11 display.
  43.  */
  44. X11_init()
  45. {
  46.     int        i;
  47.     int        x, y, prefx, prefy, prefxs, prefys;
  48.     unsigned int    bw, depth, mask;
  49.     Window        rootw, childw;
  50.     char        *av[2], name[128];
  51.  
  52.     XSetWindowAttributes    theWindowAttributes;
  53.     XWindowAttributes    retWindowAttributes;
  54.         XSizeHints              theSizeHints;
  55.         unsigned long           theWindowMask;
  56.     XWMHints                theWMHints;
  57.  
  58.  
  59.     av[0] = "vogl.X11";
  60.     av[1] = (char *)NULL;
  61.  
  62.     if ((display = XOpenDisplay((char *)NULL)) == (Display *)NULL) {
  63.         fprintf(stderr,"vogl: X11_init: can't connect to X server\n");
  64.         exit(1);
  65.     }
  66.  
  67.     winder = DefaultRootWindow(display);
  68.     screen = DefaultScreen(display);
  69.     colormap = DefaultColormap(display, screen);
  70.  
  71.     /*
  72.      * Set our standard colors...
  73.      */
  74.     if (vdevice.depth == 1) {
  75.         /*
  76.          * Black and white - anything that's not black is white.
  77.          */
  78.         carray[0] = BlackPixel(display, screen);
  79.         for (i = 1; i < CMAPSIZE; i++)
  80.             carray[i] = WhitePixel(display, screen);
  81.     } else {
  82.         /*
  83.          * Color, try to get our colors close to what's in the
  84.          * default colormap.
  85.          */
  86.         X11_mapcolor(0, 0, 0, 0);
  87.         X11_mapcolor(1, 255, 0, 0);
  88.         X11_mapcolor(2, 0, 255, 0);
  89.         X11_mapcolor(3, 255, 255, 0);
  90.         X11_mapcolor(4, 0, 0, 255);
  91.         X11_mapcolor(5, 255, 0, 255);
  92.         X11_mapcolor(6, 0, 255, 255);
  93.         X11_mapcolor(7, 255, 255, 255);
  94.     }
  95.  
  96.     getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
  97.  
  98.     /*
  99.      * NEED TO USE XGRABPOINTER here???
  100.      */
  101.     XQueryPointer(display, winder, &rootw, &childw, &x, &y, &x, &y, &mask);
  102.  
  103.     if (childw == None)
  104.         childw = rootw;
  105.  
  106. /*
  107.     if (!XGetWindowAttributes(display, childw, &retWindowAttributes)) {
  108.         fprintf(stderr,"Can't get window attributes.");
  109.         exit(1);
  110.     }
  111.  
  112.     x = retWindowAttributes.x;
  113.     y = retWindowAttributes.y;
  114.     w = retWindowAttributes.width;
  115.     h = retWindowAttributes.height;
  116.     bw = retWindowAttributes.border_width;
  117.     depth = vdevice.depth = retWindowAttributes.depth;
  118.  
  119.     XTranslateCoordinates(display,
  120.             childw, retWindowAttributes.root,
  121.             0, 0,
  122.             &x, &y,
  123.             &rootw
  124.     );
  125. */
  126.  
  127.     XGetGeometry(display, childw, &rootw, &x, &y, &w, &h, &bw, &depth);
  128.  
  129.     vdevice.depth = depth;
  130.  
  131.         theWindowAttributes.backing_store = Always;
  132.         theWindowAttributes.save_under = True;
  133.         theWindowAttributes.border_pixel = carray[1];
  134.  
  135.     if (prefx > -1) {
  136.             x = prefx;
  137.             y = prefy;
  138.     }
  139.  
  140.     if (prefxs > -1) {
  141.             w = prefxs;
  142.             h = prefys;
  143.     }
  144.  
  145.     if (bw == 0)
  146.         bw = 4;
  147.  
  148.     x -= bw;
  149.     y -= bw;
  150.  
  151.     if (x <= 0)
  152.         x = 0;
  153.  
  154.     if (y <= 0)
  155.         y = 0;
  156.  
  157.     w -= 4 * bw;
  158.     h -= 4 * bw;
  159.  
  160.         theWindowMask = CWBorderPixel;
  161.  
  162.         winder = XCreateWindow(display,
  163.                                 winder,
  164.                                 x, y,
  165.                                 w, h,
  166.                                 bw,
  167.                                 (int)depth,
  168.                                 InputOutput,
  169.                                 CopyFromParent,
  170.                                 theWindowMask,
  171.                                 &theWindowAttributes
  172.                         );
  173.  
  174.  
  175.         theSizeHints.flags = PPosition|PSize;
  176.         theSizeHints.x = x;
  177.         theSizeHints.y = y;
  178.         theSizeHints.width = w;
  179.         theSizeHints.height = h;
  180.  
  181.     if (vdevice.wintitle)
  182.         strcpy(name, vdevice.wintitle);
  183.     else
  184.         sprintf(name, "vogl %d (win id 0x%x)", getpid(), winder);
  185.  
  186.     XSetStandardProperties(display,
  187.         winder,
  188.         name,
  189.         name,
  190.         None,
  191.         av,
  192.         1,
  193.         &theSizeHints
  194.     );
  195.  
  196.         theWMHints.initial_state = NormalState;
  197.         theWMHints.input = True;
  198.         theWMHints.flags = StateHint | InputHint;
  199.         XSetWMHints(display, winder, &theWMHints);
  200.  
  201.     XSelectInput(display, winder, EV_MASK);
  202.  
  203.     theDrawable = (Drawable)winder;
  204.  
  205.     /*
  206.      * Create Graphics Context and Drawable
  207.      */
  208.     theGC = XDefaultGC(display, screen);
  209.     theDrawable = (Drawable)winder;
  210.     X11_color(0);
  211.  
  212.     XMapRaised(display, winder);
  213.     XFlush(display);
  214.  
  215.     /*
  216.      * Wait for Exposure event.
  217.      */
  218.     do {
  219.         XNextEvent(display, &event);
  220.     } while (event.type != Expose && event.type != MapNotify);
  221.  
  222.     /*
  223.      * Set the input Focus to us.
  224.  
  225.         if (prefx == -1 && prefxs == -1)
  226.                 XSetInputFocus(display, winder, RevertToParent, CurrentTime);
  227.      */
  228.  
  229.     /*
  230.      *  Let VOGLE know about the window size.
  231.      *  (We may have been resized..... )
  232.      */
  233.     if (!XGetWindowAttributes(display, winder, &retWindowAttributes)) {
  234.         fprintf(stderr,"Can't get window attributes.");
  235.         exit(1);
  236.     }
  237.  
  238.     x = retWindowAttributes.x;
  239.     y = retWindowAttributes.y;
  240.     w = retWindowAttributes.width;
  241.     h = retWindowAttributes.height;
  242.  
  243.     XTranslateCoordinates(display,
  244.             winder, retWindowAttributes.root,
  245.             0, 0,
  246.             &x, &y,
  247.             &rootw
  248.     );
  249.  
  250.     vdevice.sizeX = vdevice.sizeY = MIN(h, w) - 1;
  251.     vdevice.sizeSx = w - 1;
  252.     vdevice.sizeSy = h - 1;
  253.  
  254.  
  255.     back_used = 0;
  256.     return(1);
  257. }
  258.  
  259. /*
  260.  * X11_exit
  261.  *
  262.  *    cleans up before returning the window to normal.
  263.  */
  264. X11_exit()
  265. {
  266.     XFreeGC(display, theGC);
  267.  
  268.     if (back_used) 
  269.         XFreePixmap(display, bbuf);
  270.  
  271.     XUnmapWindow(display, winder);
  272.  
  273.     XDestroyWindow(display, winder);
  274.  
  275.     return(1);
  276. }
  277.  
  278. /*
  279.  * X11_draw
  280.  *
  281.  *    draws a line from the current graphics position to (x, y).
  282.  *
  283.  * Note: (0, 0) is defined as the top left of the window in X (easy
  284.  * to forget).
  285.  */
  286. X11_draw(x, y)
  287.     int    x, y;
  288. {
  289.     XDrawLine(display,
  290.         theDrawable,
  291.         theGC,
  292.         vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  293.         x, vdevice.sizeSy - y
  294.     );
  295.  
  296.     XFlush(display);
  297. }
  298.  
  299. /*
  300.  * X11_getkey
  301.  *
  302.  *    grab a character from the keyboard - blocks until one is there.
  303.  */
  304. int
  305. X11_getkey()
  306. {
  307.     char    c;
  308.  
  309.     do {
  310.         XNextEvent(display, &event);
  311.         if (event.type == KeyPress) {
  312.             if (XLookupString(&event, &c, 1, NULL, NULL) > 0)
  313.                 return((int)c);
  314.             else
  315.                 return(0);
  316.         }
  317.     } while (event.type != KeyPress);
  318. }
  319.  
  320. /*
  321.  * X11_checkkey
  322.  *
  323.  *    Check if there has been a keyboard key pressed.
  324.  *    and return it if there is.
  325.  */
  326. int
  327. X11_checkkey()
  328. {
  329.     char    c;
  330.     int    i;
  331.  
  332.     if (!XCheckWindowEvent(display, winder, KeyPressMask, &event))
  333.         return(0);
  334.  
  335.     if (event.type == KeyPress)
  336.         if (XLookupString(&event, &c, 1, NULL, NULL) > 0)
  337.             return((int)c);
  338.  
  339.     return(0);
  340. }
  341.  
  342. /*
  343.  * X11_locator
  344.  *
  345.  *    return the window location of the cursor, plus which mouse button,
  346.  * if any, is been pressed.
  347.  */
  348. int
  349. X11_locator(wx, wy)
  350.     int    *wx, *wy;
  351. {
  352.     Window    rootw, childw;
  353.     int    x, y, mask;
  354.  
  355.     XQueryPointer(display, winder, &rootw, &childw, &x, &y, wx, wy, &mask);
  356.  
  357.     *wy = (int)vdevice.sizeSy - *wy;
  358.  
  359.     return(mask >> 8);
  360. }
  361.  
  362. /*
  363.  * X11_clear
  364.  *
  365.  * Clear the screen (or current buffer )to current colour
  366.  */
  367. X11_clear()
  368. {
  369.     int    x[4], y[4];
  370.  
  371.     XSetBackground(display, theGC, colour);
  372.  
  373.     if (vdevice.maxVx != vdevice.sizeSx
  374.        || vdevice.maxVy != vdevice.sizeSy
  375.        || vdevice.minVx != vdevice.sizeSx
  376.        || vdevice.minVy != vdevice.sizeSy) {
  377.         x[0] = x[1] = vdevice.maxVx;
  378.         y[0] = vdevice.maxVy;
  379.         y[1] = y[2] = vdevice.minVy;
  380.         x[2] = x[3] = vdevice.minVx;
  381.         y[3] = vdevice.maxVy;
  382.  
  383.         X11_fill(4, x, y);
  384.     } else {
  385.         XFillRectangle(display,
  386.             theDrawable,
  387.             theGC,
  388.             vdevice.minVx,
  389.             vdevice.minVy, 
  390.             (unsigned int)vdevice.maxVx,
  391.             (unsigned int)vdevice.maxVy
  392.         );
  393.         XFlush(display);
  394.     }
  395.  
  396. }
  397.  
  398. /*
  399.  * X11_color
  400.  *
  401.  *    set the current drawing color index.
  402.  */
  403. X11_color(ind)
  404.         int    ind;
  405. {
  406.     colour = carray[ind];
  407.     XSetForeground(display, theGC, colour);
  408. }
  409.  
  410. /*
  411.  * X11_mapcolor
  412.  *
  413.  *    change index i in the color map to the appropriate r, g, b, value.
  414.  */
  415. X11_mapcolor(i, r, g, b)
  416.     int    i;
  417.     int    r, g, b;
  418. {
  419.     int    stat;
  420.     XColor    tmp;
  421.  
  422.     if (i >= CMAPSIZE)
  423.         return(-1);
  424.  
  425.  
  426.     /*
  427.      * For Black and White.
  428.      * If the index is 0 and r,g,b != 0 then we are remapping black.
  429.      * If the index != 0 and r,g,b == 0 then we make it black.
  430.      */
  431.     if (vdevice.depth == 1) {
  432.         if (i == 0 && (r != 0 || g != 0 || b != 0)) 
  433.             carray[i] = WhitePixel(display, screen);
  434.         else if (i != 0 && r == 0 && g == 0 && b == 0)
  435.             carray[i] = BlackPixel(display, screen);
  436.     } else {
  437.         tmp.red = (unsigned short)(r / 255.0 * 65535);
  438.         tmp.green = (unsigned short)(g / 255.0 * 65535);
  439.         tmp.blue = (unsigned short)(b / 255.0 * 65535);
  440.         tmp.flags = 0;
  441.         tmp.pixel = (unsigned long)i;
  442.  
  443.         if ((stat = XAllocColor(display, colormap, &tmp)) == 0) {
  444.             fprintf(stderr, "XAllocColor failed (status = %d)\n", stat);
  445.             exit(1);
  446.         }
  447.         carray[i] = tmp.pixel;
  448.     }
  449.  
  450.     XFlush(display);
  451.     return(0);
  452. }
  453.     
  454. /*
  455.  * X11_font
  456.  *
  457.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  458.  *
  459.  */
  460. X11_font(fontfile)
  461.         char    *fontfile;
  462. {
  463.     XGCValues    xgcvals;
  464.  
  465.     if (font_id != (XFontStruct *)NULL)
  466.         XFreeFont(display, font_id);
  467.  
  468.     if (strcmp(fontfile, "small") == 0) {
  469.         if ((font_id = XLoadQueryFont(display, SMALLX11R2)) == (XFontStruct *)NULL) {        /* X11 R2 */
  470.             if ((font_id = XLoadQueryFont(display, SMALLX11R3)) == (XFontStruct *)NULL)         /* X11 R3 */
  471.                 return(0);
  472.             else
  473.                 fontfile = SMALLX11R3;
  474.         } else
  475.             fontfile = SMALLX11R2;
  476.     } else if (strcmp(fontfile, "large") == 0) {
  477.         if ((font_id = XLoadQueryFont(display, LARGEX11R2)) == (XFontStruct *)NULL) {        /* X11 R2 */
  478.             if ((font_id = XLoadQueryFont(display, LARGEX11R3)) == (XFontStruct *)NULL)         /* X11 R3 */
  479.                 return(0);
  480.             else
  481.                 fontfile = LARGEX11R3;
  482.         } else
  483.             fontfile = LARGEX11R2;
  484.     } else if ((font_id = XLoadQueryFont(display, fontfile)) == (XFontStruct *)NULL)
  485.         return(0);
  486.  
  487.     vdevice.hheight = font_id->max_bounds.ascent + font_id->max_bounds.descent;
  488.     vdevice.hwidth = font_id->max_bounds.width;
  489.  
  490.     xgcvals.font = XLoadFont(display, fontfile);
  491.     XChangeGC(display, theGC, GCFont, &xgcvals);
  492.  
  493.     return(1);
  494. }
  495.  
  496. /* 
  497.  * X11_char
  498.  *
  499.  *     outputs one char - is more complicated for other devices
  500.  */
  501. X11_char(c)
  502.     char    c;
  503. {
  504.     char    *s = " ";
  505.  
  506.     s[0] = c;
  507.     XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, 1);
  508.     XFlush(display);
  509. }
  510.  
  511. /*
  512.  * X11_string
  513.  *
  514.  *    Display a string at the current drawing position.
  515.  */
  516. X11_string(s)
  517.         char    s[];
  518. {
  519.     XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, strlen(s));
  520.     XSync(display, 0);
  521. }
  522.  
  523. /*
  524.  * X11_fill
  525.  *
  526.  *    fill a polygon
  527.  */
  528. X11_fill(n, x, y)
  529.     int    n, x[], y[];
  530. {
  531.     XPoint    plist[128];
  532.     int    i;
  533.  
  534.     if (n > 128)
  535.         verror("vogl: more than 128 points in a polygon");
  536.  
  537.     for (i = 0; i < n; i++) {
  538.         plist[i].x = x[i];
  539.         plist[i].y = vdevice.sizeSy - y[i];
  540.     }
  541.  
  542.     XFillPolygon(display, theDrawable, theGC, plist, n, Nonconvex, CoordModeOrigin);
  543.  
  544.     vdevice.cpVx = x[n-1];
  545.     vdevice.cpVy = y[n-1];
  546.  
  547.     XFlush(display);
  548. }
  549.  
  550. #define    GC_COPY_MASK    ~0
  551.  
  552. /*
  553.  * X11_backbuf
  554.  *
  555.  *    Set up double buffering by allocating the back buffer and
  556.  *    setting drawing into it.
  557.  */
  558. X11_backbuf()
  559. {
  560.     if (!back_used)
  561.         bbuf = XCreatePixmap(display,
  562.             (Drawable)winder,
  563.             (unsigned int)vdevice.sizeSx + 1,
  564.             (unsigned int)vdevice.sizeSy + 1,
  565.             (unsigned int)vdevice.depth
  566.         );
  567.  
  568.     theDrawable = (Drawable)bbuf;
  569.  
  570.     back_used = 1;
  571.  
  572.     return(1);
  573. }
  574.  
  575. /*
  576.  * X11_swapbuf
  577.  *
  578.  *    Swap the back and from buffers. (Really, just copy the
  579.  *    back buffer to the screen).
  580.  */
  581. X11_swapbuf()
  582. {
  583.     XCopyArea(display,
  584.         theDrawable,
  585.         winder,
  586.         theGC,
  587.         0, 0,
  588.         (unsigned int)vdevice.sizeSx + 1,
  589.         (unsigned int)vdevice.sizeSy + 1,
  590.         0, 0
  591.     );
  592.  
  593.     XSync(display, 0);    /* Not XFlush */
  594. }
  595.  
  596. /*
  597.  * X11_frontbuf
  598.  *
  599.  *    Make sure we draw to the screen.
  600.  */
  601. X11_frontbuf()
  602. {
  603.     theDrawable = (Drawable)winder;
  604. }
  605.  
  606. /*
  607.  * the device entry
  608.  */
  609. static DevEntry X11dev = {
  610.     "X11",
  611.     "large",
  612.     "small",
  613.     X11_backbuf,
  614.     X11_char,
  615.     X11_checkkey,
  616.     X11_clear,
  617.     X11_color,
  618.     X11_draw,
  619.     X11_exit,
  620.     X11_fill,
  621.     X11_font,
  622.     X11_frontbuf,
  623.     X11_getkey,
  624.     X11_init,
  625.     X11_locator,
  626.     X11_mapcolor,
  627.     X11_string,
  628.     X11_swapbuf
  629. };
  630.  
  631. /*
  632.  * _X11_devcpy
  633.  *
  634.  *    copy the X11 device into vdevice.dev.
  635.  */
  636. _X11_devcpy()
  637. {
  638.     vdevice.dev = X11dev;
  639. }
  640.