home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / DRIVERS / DECX11.C < prev    next >
C/C++ Source or Header  |  2000-02-11  |  12KB  |  590 lines

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