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