home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Programming / tek / kn / linux / visual.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-26  |  21.4 KB  |  1,124 lines

  1.  
  2. /*
  3. **    TEKlib
  4. **    (C) 2001 TEK neoscientists
  5. **    all rights reserved.
  6. **
  7. **    Linux/X11 visual backend
  8. */
  9.  
  10.  
  11. #include <tek/type.h>
  12. #include <tek/visual.h>
  13. #include <tek/kn/visual.h>
  14.  
  15. #include <X11/Xlib.h>
  16. #include <X11/Xutil.h>
  17. #include <X11/keysym.h>
  18.  
  19.  
  20. #define DEFAULT_X11_FONT_NAME    "-misc-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*"
  21.  
  22.  
  23. typedef struct
  24. {
  25.     Display *display;
  26.     int screen;
  27.     Visual *visual;
  28.  
  29.     Window win;
  30.     Colormap colormap;
  31.     GC gc;
  32.     XFontStruct *font;
  33.     XTextProperty title_prop;
  34.     Atom atom_wm_delete_win;
  35.     
  36.     XImage *image;
  37.     int imw, imh;
  38.     
  39.     int cursor_x, cursor_y;        /* pixel position */
  40.     int font_w, font_h;        /* fixed font metrics */
  41.     int win_w, win_h;        /* window size */
  42.     int text_w, text_h;        /* text windows size */
  43.     long mask;            /* window's eventmask */
  44.     long base_mask;            /* window's base eventmask (will not be influenced by visual's setmask) */
  45.     unsigned int width, height;
  46.  
  47.     /*TAPTR pen_ht;*/
  48.  
  49.     TBOOL mousein;
  50.  
  51.     int depth;
  52.     int pixfmt;
  53.     int bpp;            /* bytes per pixel */
  54.     int swap;
  55.  
  56. } VisualX;
  57.  
  58.  
  59. static const char* eventname(int eventtype)
  60. {
  61.     static const char *name[] =
  62.     {
  63.         "",
  64.         "",
  65.         "KeyPress",
  66.         "KeyRelease",
  67.         "ButtonPress",
  68.         "ButtonRelease",
  69.         "MotionNotify",
  70.         "EnterNotify",
  71.         "LeaveNotify",
  72.         "FocusIn",
  73.         "FocusOut",
  74.         "KeymapNotify",
  75.         "Expose",
  76.         "GraphicsExpose",
  77.         "NoExpose",
  78.         "VisibleNotify",
  79.         "CreateNotify",
  80.         "DestroyNotify",
  81.         "UnmapNotify",
  82.         "MapNotify",
  83.         "MapRequest",
  84.         "ReparentNotify",
  85.         "ConfigureNotify",
  86.         "ConfigureRequest",
  87.         "GravityNotify",
  88.         "ResizeRequest",
  89.         "CirculateNotify",
  90.         "CirculateRequest",
  91.         "PropertyNotify",
  92.         "SelectionClear",
  93.         "SelectionRequest",
  94.         "SelectionNotify",
  95.         "ColormapNotify",
  96.         "ClientMessage",
  97.         "MappingNotify"
  98.     };
  99.     return name[eventtype];
  100. }
  101.  
  102.  
  103.  
  104. static void kn_window_resize(VisualX *x, int width, int height)
  105. {
  106.     x->win_w = width;
  107.     x->win_h = height;
  108.     x->text_w = (x->font_w) ? width / x->font_w : 0;
  109.     x->text_h = (x->font_h) ? height / x->font_h : 0;
  110. }
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117. #define PIXFMT_UNDEFINED    0
  118. #define PIXFMT_RGB            1
  119. #define PIXFMT_RBG            2
  120. #define PIXFMT_BRG            3
  121. #define PIXFMT_BGR            4
  122. #define PIXFMT_GRB            5
  123. #define PIXFMT_GBR            6
  124.  
  125. static char *strpixfmt(int pixfmt)
  126. {
  127.     static char *names[] = {
  128.         "PIXFMT_UNDEFINED", "PIXFMT_RGB", "PIXFMT_RBG", "PIXFMT_BRG", "PIXFMT_BGR", "PIXFMT_GRB", "PIXFMT_GBR" };
  129.         
  130.     return names[pixfmt];
  131. }
  132.  
  133. static void getdisplaydata(VisualX *x)
  134. {
  135.     int max, maxn, i, num, clas;
  136.     XVisualInfo xvi, *xvir;
  137.  
  138.  
  139.     /* 
  140.     **    client <-> server endianness
  141.     */
  142.     
  143.     if (htonl(1) == 1)
  144.     {
  145.         x->swap = (ImageByteOrder(x->display) == LSBFirst);
  146.     }
  147.     else
  148.     {
  149.         x->swap = (ImageByteOrder(x->display) == MSBFirst);
  150.     }
  151.  
  152.  
  153.     /* 
  154.     **    depth
  155.     */
  156.         
  157.     x->depth = DefaultDepth(x->display, x->screen);
  158.     
  159.  
  160.     /* 
  161.     **    RGB ordering
  162.     */
  163.  
  164.     xvi.screen = x->screen;
  165.     xvir = XGetVisualInfo(x->display, VisualScreenMask, &xvi, &num);
  166.     if (xvir)
  167.     {
  168.         max = 0;
  169.         for (i = 0; i < num; i++)
  170.         {
  171.             if (xvir[i].depth > max)
  172.             {
  173.                 max = xvir[i].depth;        /* max depth supported */
  174.             }
  175.         }
  176.         
  177.         if (max > 8)
  178.         {
  179.             x->depth = max;
  180.             clas = -1;
  181.             maxn = -1;
  182.             for (i = 0; i < num; i++)
  183.             {
  184.                 if (xvir[i].depth == x->depth)
  185.                 {
  186.                     if ((xvir[i].class > clas) && (xvir[i].class != DirectColor))
  187.                     {
  188.                         maxn = i;
  189.                         clas = xvir[i].class;
  190.                     }
  191.                 }
  192.             }
  193.         }
  194.  
  195.         if (maxn >= 0)
  196.         {
  197.             unsigned long rmsk, gmsk, bmsk;
  198.             
  199.             x->visual = xvir[maxn].visual;
  200.             rmsk = xvir[maxn].red_mask;
  201.             gmsk = xvir[maxn].green_mask;
  202.             bmsk = xvir[maxn].blue_mask;
  203.             
  204.             if ((rmsk > gmsk) && (gmsk > bmsk))
  205.             {
  206.                 x->pixfmt = PIXFMT_RGB;
  207.             }
  208.             else if ((rmsk > bmsk) && (bmsk > gmsk))
  209.             {
  210.                 x->pixfmt = PIXFMT_RBG;
  211.             }
  212.             else if ((bmsk > rmsk) && (rmsk > gmsk))
  213.             {
  214.                 x->pixfmt = PIXFMT_BRG;
  215.             }
  216.             else if ((bmsk > gmsk) && (gmsk > rmsk))
  217.             {
  218.                 x->pixfmt = PIXFMT_BGR;
  219.             }
  220.             else if ((gmsk > rmsk) && (rmsk > bmsk))
  221.             {
  222.                 x->pixfmt = PIXFMT_GRB;
  223.             }
  224.             else if ((gmsk > bmsk) && (bmsk > rmsk))
  225.             {
  226.                 x->pixfmt = PIXFMT_GBR;
  227.             }
  228.             else
  229.             {
  230.                 x->pixfmt = PIXFMT_UNDEFINED;
  231.             }
  232.         }
  233.  
  234.         XFree(xvir);
  235.     }
  236.  
  237.     if (x->depth == 16)
  238.     {
  239.         xvi.visual = x->visual;
  240.         xvi.visualid = XVisualIDFromVisual(x->visual);
  241.         xvir = XGetVisualInfo(x->display, VisualIDMask, &xvi, &num);
  242.         if (xvir)
  243.         {
  244.             if (xvir->red_mask != 0xf800)
  245.             {
  246.                 x->depth = 15;
  247.             }
  248.             XFree(xvir);
  249.         }
  250.     }
  251.  
  252.     switch (x->depth)
  253.     {
  254.         case 15:
  255.         case 16:
  256.             x->bpp = 2;
  257.             break;
  258.         case 24:
  259.         case 32:
  260.             x->bpp = 4;
  261.             break;
  262.     }
  263.  
  264.     dbvprintf1(1, "TEKLIB kn_createvisual: format: %s\n", strpixfmt(x->pixfmt));
  265.     dbvprintf1(1, "TEKLIB kn_createvisual: depth: %d\n", x->depth);
  266.     dbvprintf1(1, "TEKLIB kn_createvisual: bytesperpixel: %d\n", x->bpp);
  267.     dbvprintf1(1, "TEKLIB kn_createvisual: swap: %d\n", x->swap);
  268.  
  269. }
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276. TAPTR kn_createvisual(TAPTR mmu, TSTRPTR title, TINT prefwidth, TINT prefheight)
  277. {
  278.     VisualX *x;
  279.     unsigned long swa_mask;
  280.     unsigned long gcv_mask;
  281.     XSetWindowAttributes swa;
  282.     XGCValues gcv;
  283.     int mapped = 0;
  284.     TUINT in_win_w = 640, in_win_h = 480;
  285.     
  286.     if (prefwidth > 0)
  287.     {
  288.         in_win_w = prefwidth;
  289.     }
  290.  
  291.     if (prefheight > 0)
  292.     {
  293.         in_win_h = prefheight;
  294.     }
  295.  
  296.     if (!title)
  297.     {
  298.         title = "TEKlib visual";
  299.     }
  300.  
  301.  
  302.     
  303.     x = (VisualX*) kn_alloc0(sizeof(VisualX));
  304.  
  305.     if (!x)
  306.         goto err_return;
  307.  
  308.  
  309.     
  310.     /* open display */
  311.     
  312.     x->display = XOpenDisplay(TNULL);
  313.  
  314.     if (!x->display)
  315.         goto err_free;
  316.  
  317.     x->screen = DefaultScreen(x->display);
  318.     x->visual = DefaultVisual(x->display, x->screen);
  319.  
  320.  
  321.  
  322.     getdisplaydata(x);
  323.  
  324.  
  325.     
  326.     /* load default font and create gc */
  327.  
  328.     gcv_mask = 0;
  329.     
  330.     x->font = XLoadQueryFont(x->display, DEFAULT_X11_FONT_NAME );
  331.  
  332.     if (x->font)
  333.     {
  334.         gcv.font = x->font->fid;
  335.         gcv_mask |= GCFont;
  336.         
  337.         x->font_w = XTextWidth(x->font," ", 1);
  338.         x->font_h = x->font->ascent + x->font->descent;
  339.     }
  340.     else
  341.     {
  342.         dbvprintf(20, "can't load font\n");
  343.     }
  344.  
  345.     
  346.     /* create window */
  347.     
  348.     x->colormap = XCreateColormap(x->display, RootWindow(x->display, x->screen) , x->visual, AllocNone);
  349.  
  350.     swa_mask = CWBackPixel|CWColormap|CWEventMask;
  351.     
  352.     swa.background_pixel = BlackPixel(x->display, x->screen);
  353.     swa.colormap = x->colormap;
  354.     swa.event_mask = StructureNotifyMask;
  355.     
  356.     /* backing-store, per default.
  357.      * NOTE: no other auto-refreshing mode is supported (even no exposure-events are generated) */
  358.     if ((swa.backing_store = DoesBackingStore(ScreenOfDisplay(x->display, x->screen))) != 0)
  359.     {
  360.         swa.backing_planes = -1L;            /* all planes per default */
  361.         swa_mask |= CWBackingStore|CWBackingPlanes; 
  362.     }
  363.  
  364.  
  365.     x->base_mask = swa.event_mask;
  366.     
  367.     x->cursor_x = 0;
  368.     x->cursor_y = 0;
  369.  
  370.     kn_window_resize(x, in_win_w, in_win_h);
  371.     
  372.     x->win = XCreateWindow(x->display, RootWindow(x->display, x->screen),
  373.                    0, 0, in_win_w, in_win_h, 
  374.                    0,  CopyFromParent, CopyFromParent, CopyFromParent,  
  375.                    swa_mask, &swa);
  376.  
  377.     /* set wm properties */
  378.  
  379.     XStringListToTextProperty((char**)&title, 1, &x->title_prop);
  380.     XSetWMProperties(x->display, x->win, &x->title_prop, NULL, NULL, 0, NULL, NULL, NULL);
  381.  
  382.     x->atom_wm_delete_win = XInternAtom(x->display, "WM_DELETE_WINDOW", True);
  383.     
  384.     XSetWMProtocols(x->display, x->win, &x->atom_wm_delete_win,1);
  385.     
  386.     
  387.     /* setup graphics context */
  388.     
  389.     gcv.function = GXcopy;
  390.     gcv.fill_style = FillSolid;
  391.     gcv.graphics_exposures = False;
  392.     
  393.     gcv_mask |= GCFunction | GCFillStyle | GCGraphicsExposures;
  394.     
  395.     x->gc = XCreateGC(x->display, x->win, gcv_mask, &gcv);
  396.     
  397.     XCopyGC( x->display,
  398.          XDefaultGC(x->display, x->screen),
  399.          GCForeground|GCBackground, 
  400.          x->gc);
  401.  
  402.     
  403.     /* map window */
  404.     
  405.     XMapWindow(x->display, x->win);
  406.     
  407.     
  408.     /* wait for window */
  409.     
  410.     do
  411.     {
  412.         XEvent ev;
  413.         
  414.         XNextEvent(x->display, &ev);
  415.         switch(ev.type)
  416.         {
  417.             case MapNotify:
  418.                 mapped = 1;
  419.                 break;
  420.         }
  421.     } while(!mapped);
  422.  
  423.     if (!mapped)
  424.         goto err_free_font;
  425.  
  426.     x->mousein = TTRUE;
  427.  
  428.     return (TAPTR) x;
  429.  
  430.     
  431. err_free_font:
  432.  
  433.     if (x->font)
  434.     {
  435.         XFreeFont(x->display, x->font);
  436.     }
  437.     
  438.     XCloseDisplay(x->display);
  439.  
  440. err_free:
  441.  
  442.     kn_free(x);
  443.  
  444. err_return:
  445.  
  446.     return TNULL;
  447. }
  448.  
  449.  
  450.  
  451.  
  452. TVOID kn_destroyvisual(TAPTR v)
  453. {
  454.     VisualX *x = (VisualX*) v;
  455.  
  456.     if (x->image)
  457.     {
  458.         x->image->data = NULL;
  459.         XDestroyImage(x->image);
  460.     }
  461.  
  462.  
  463.     XUnmapWindow(x->display, x->win);
  464.     
  465.     XFreeGC(x->display, x->gc);
  466.     
  467.     XDestroyWindow(x->display, x->win);
  468.     
  469.     if (x->font)
  470.         XFreeFont(x->display, x->font);
  471.     
  472.     XCloseDisplay(x->display);
  473.     
  474.     kn_free(x);
  475. }
  476.  
  477.  
  478.  
  479.  
  480.  
  481. /*
  482. **
  483. **    newinput = kn_getnextinput(visual, newimsg, eventmask)
  484. **
  485. **    get next input event from visual object
  486. **    and fill it into the supplied TIMSG structure.
  487. **
  488. **    returns TTRUE, when there was a new message filled into the
  489. **    newimsg structure, otherwise TFALSE
  490. **
  491. */
  492.  
  493. TBOOL kn_getnextinput(TAPTR visual, TIMSG *newimsg, TUINT eventmask)
  494. {    
  495.     VisualX *x = (VisualX*) visual;
  496.     XEvent ev;
  497.     int i;
  498.  
  499.     if ((i = XEventsQueued(x->display, QueuedAfterFlush)))
  500.     {
  501.         while(i--)
  502.         {
  503.             XNextEvent(x->display, &ev);
  504.  
  505.             dbvprintf1(1,"event: %s\n", eventname(ev.type));
  506.             
  507.             newimsg->qualifier = TKEYQUAL_NONE;
  508.  
  509.             switch(ev.type)
  510.             {
  511.             #if 0
  512.                 case LeaveNotify:
  513.                     x->mousein = TFALSE;
  514.                     break;
  515.  
  516.                 case EnterNotify:
  517.                     x->mousein = TTRUE;
  518.                     break;
  519.             #endif
  520.             
  521.                 case FocusIn:
  522.                     if (eventmask & TITYPE_VISUAL_FOCUS)
  523.                     {
  524.                         newimsg->type = TITYPE_VISUAL_FOCUS;
  525.                         return TTRUE;
  526.                     }
  527.                     break;
  528.  
  529.                 case FocusOut:
  530.                     if (eventmask & TITYPE_VISUAL_UNFOCUS)
  531.                     {
  532.                         newimsg->type = TITYPE_VISUAL_UNFOCUS;
  533.                         return TTRUE;
  534.                     }
  535.                     break;
  536.             
  537.                 case ConfigureNotify:
  538.                 
  539.                     /*dbvprintf(2,"TEKLIB kn_getnextinput: configurenotify\n");*/
  540.                 
  541.                     if ((x->width  != ((XConfigureEvent*)&ev)->width) &&
  542.                         (x->height != ((XConfigureEvent*)&ev)->height))
  543.                     {
  544.                         kn_window_resize(x, ((XConfigureEvent*)&ev)->width, ((XConfigureEvent*)&ev)->height);
  545.                         if (eventmask & TITYPE_VISUAL_NEWSIZE)
  546.                         {
  547.                             newimsg->type = TITYPE_VISUAL_NEWSIZE;
  548.                             newimsg->mousex = (TINT) x->win_w;
  549.                             newimsg->mousey = (TINT) x->win_h;
  550.                             return TTRUE;
  551.                         }
  552.                     }
  553.                     break;
  554.  
  555.                 case MotionNotify:
  556.                     if (eventmask & TITYPE_MOUSEMOVE)
  557.                     {
  558.                         newimsg->type = TITYPE_MOUSEMOVE;
  559.                         newimsg->mousex = (TINT) ((XMotionEvent*)&ev)->x;
  560.                         newimsg->mousey = (TINT) ((XMotionEvent*)&ev)->y;
  561.                         return TTRUE;
  562.                     }
  563.                     break;
  564.  
  565.                 case ButtonRelease:
  566.                 case ButtonPress:
  567.                     if (eventmask & TITYPE_MOUSEBUTTON)
  568.                     {
  569.                         unsigned int button;
  570.                         newimsg->type = TITYPE_MOUSEBUTTON;
  571.                         newimsg->mousex = (TINT) ((XButtonEvent*)&ev)->x;
  572.                         newimsg->mousey = (TINT) ((XButtonEvent*)&ev)->y;
  573.  
  574.                         button = ((XButtonEvent*)&ev)->button;
  575.  
  576.                         if (ev.type == ButtonPress)
  577.                         {
  578.                             switch(button)
  579.                             {
  580.                                 case Button1:
  581.                                     newimsg->code = TMBCODE_LEFTDOWN;
  582.                                     break;
  583.                                 case Button2:
  584.                                     newimsg->code = TMBCODE_MIDDLEDOWN;
  585.                                     break;
  586.                                 case Button3:
  587.                                     newimsg->code = TMBCODE_RIGHTDOWN;
  588.                                     break;
  589.                             }
  590.                         }
  591.                         else
  592.                         {
  593.                             switch(button)
  594.                             {
  595.                                 case Button1:
  596.                                     newimsg->code = TMBCODE_LEFTUP;
  597.                                     break;
  598.                                 case Button2:
  599.                                     newimsg->code = TMBCODE_MIDDLEUP;
  600.                                     break;
  601.                                 case Button3:
  602.                                     newimsg->code = TMBCODE_RIGHTUP;
  603.                                     break;
  604.                             }
  605.                         }
  606.                         return TTRUE;
  607.                     }
  608.                     break;
  609.  
  610.                 case KeyPress:
  611.                     if (eventmask & TITYPE_KEY)
  612.                     {
  613.                         KeySym keysym;
  614.                         XComposeStatus compose;
  615.                         char buffer[10];
  616.                         XLookupString((XKeyEvent*)&ev,buffer,10,&keysym,&compose);
  617.  
  618.                         if (((signed)keysym) < 0x100)
  619.                         {
  620.                             /* normal ascii */
  621.                             /*newimsg->code = (TUINT) ((XKeyEvent*)&ev)->keycode;*/
  622.                             newimsg->code = keysym;
  623.                         }
  624.                         else if ((keysym >= XK_F1) && (keysym <= XK_F12))
  625.                         {
  626.                             newimsg->code = (TUINT) (keysym-XK_F1 + TKEYCODE_F1);
  627.                         }
  628.                         else
  629.                         {
  630.                             switch(keysym)
  631.                             {
  632.                                 case XK_Left:
  633.                                     newimsg->code = TKEYCODE_CRSRLEFT;
  634.                                     break;
  635.                                 case XK_Right:
  636.                                     newimsg->code = TKEYCODE_CRSRRIGHT;
  637.                                     break;
  638.                                 case XK_Up:
  639.                                     newimsg->code = TKEYCODE_CRSRUP;
  640.                                     break;
  641.                                 case XK_Down:
  642.                                     newimsg->code = TKEYCODE_CRSRDOWN;
  643.                                     break;
  644.                                     
  645.                                 case XK_Escape:
  646.                                     newimsg->code = TKEYCODE_ESC;
  647.                                     break;
  648.                                 case XK_Delete:
  649.                                     newimsg->code = TKEYCODE_DEL;
  650.                                     break;
  651.                                 case XK_BackSpace:
  652.                                     newimsg->code = TKEYCODE_BCKSPC;
  653.                                     break;
  654.                                 case XK_Tab:
  655.                                     newimsg->code = TKEYCODE_TAB;
  656.                                     break;
  657.                                 case XK_Return:
  658.                                     newimsg->code = TKEYCODE_ENTER;
  659.                                     break;
  660.                                     
  661.                                 case XK_Help:
  662.                                     newimsg->code = TKEYCODE_HELP;
  663.                                     break;
  664.                                 case XK_Insert:
  665.                                     newimsg->code = TKEYCODE_INSERT;
  666.                                     break;
  667.                                     /* ?? newimsg->code = TKEYCODE_OVERWRITE; ?? */
  668.                                 case XK_Page_Up:
  669.                                     newimsg->code = TKEYCODE_PAGEUP;
  670.                                     break;
  671.                                 case XK_Page_Down:
  672.                                     newimsg->code = TKEYCODE_PAGEDOWN;
  673.                                     break;
  674.                                 case XK_Begin:
  675.                                     newimsg->code = TKEYCODE_POSONE;
  676.                                     break;
  677.                                 case XK_End:
  678.                                     newimsg->code = TKEYCODE_POSEND;
  679.                                     break;
  680.                                 case XK_Print: 
  681.                                     newimsg->code = TKEYCODE_PRINT;
  682.                                     break;
  683.                                 case XK_Scroll_Lock:
  684.                                     newimsg->code = TKEYCODE_SCROLL;
  685.                                     break;
  686.                                 case XK_Pause:
  687.                                     newimsg->code = TKEYCODE_PAUSE;
  688.                                     break;
  689.                                     
  690.                                 case XK_KP_0:
  691.                                     newimsg->code = 48;
  692.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  693.                                     break;
  694.                                 case XK_KP_1:
  695.                                     newimsg->code = 49;
  696.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  697.                                     break;
  698.                                 case XK_KP_2:
  699.                                     newimsg->code = 50;
  700.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  701.                                     break;
  702.                                 case XK_KP_3:
  703.                                     newimsg->code = 51;
  704.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  705.                                     break;
  706.                                 case XK_KP_4:
  707.                                     newimsg->code = 52;
  708.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  709.                                     break;
  710.                                 case XK_KP_5:
  711.                                     newimsg->code = 53;
  712.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  713.                                     break;
  714.                                 case XK_KP_6:
  715.                                     newimsg->code = 54;
  716.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  717.                                     break;
  718.                                 case XK_KP_7:
  719.                                     newimsg->code = 55;
  720.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  721.                                     break;
  722.                                 case XK_KP_8:
  723.                                     newimsg->code = 56;
  724.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  725.                                     break;
  726.                                 case XK_KP_9:
  727.                                     newimsg->code = 57;
  728.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  729.                                     break;
  730.                                 case XK_KP_Enter:
  731.                                     newimsg->code = 13;
  732.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  733.                                     break;
  734.                                 case XK_KP_Decimal:
  735.                                     newimsg->code = '.';
  736.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  737.                                     break;
  738.                                 case XK_KP_Add:
  739.                                     newimsg->code = '+';
  740.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  741.                                     break;
  742.                                 case XK_KP_Subtract:
  743.                                     newimsg->code = '-';
  744.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  745.                                     break;
  746.                                 case XK_KP_Multiply:
  747.                                     newimsg->code = '*';
  748.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  749.                                     break;
  750.                                 case XK_KP_Divide:
  751.                                     newimsg->code = '/';
  752.                                     newimsg->qualifier = TKEYQUAL_NUMBLOCK;
  753.                                     break;
  754.                                 
  755.                                 default:
  756.                                     newimsg->code = 0;
  757.                             }
  758.                         }
  759.  
  760.                         if (newimsg->code)
  761.                         {
  762.                             newimsg->type = TITYPE_KEY;
  763.                             newimsg->mousex = (TINT) ((XKeyEvent*)&ev)->x;
  764.                             newimsg->mousey = (TINT) ((XKeyEvent*)&ev)->y;
  765.                             return TTRUE;
  766.                         }
  767.                         else
  768.                         {
  769.                             return TFALSE;
  770.                         }
  771.                     }
  772.                     break;
  773.  
  774.                 case ClientMessage:
  775.                     if ( ((XClientMessageEvent*)&ev)->data.l[0] == x->atom_wm_delete_win )
  776.                     {
  777.                         newimsg->type = TITYPE_VISUAL_CLOSE;
  778.                         return TTRUE;
  779.                     }
  780.                     break;
  781.  
  782.                 default:
  783.                     /*TDebug( TLog(get_loglevel(), "getnextinput:event not handled") );*/
  784.                     return TFALSE;
  785.             }
  786.         }
  787.     }
  788.     
  789.     return TFALSE;
  790. }
  791.  
  792.  
  793.  
  794. /*
  795. **    kn_setinputmask(visual, inputmask)
  796. **
  797. **    set a new mask of input events to be reported
  798. **    
  799. */
  800.  
  801. TVOID kn_setinputmask(TAPTR v, TUINT eventmask)
  802. {
  803.     VisualX *x = (VisualX*) v;
  804.     long x11_mask = 0;
  805.     
  806.     if (eventmask & (TITYPE_VISUAL_FOCUS|TITYPE_VISUAL_UNFOCUS))   x11_mask |= FocusChangeMask;
  807.     if (eventmask & TITYPE_VISUAL_NEWSIZE) x11_mask |= StructureNotifyMask;
  808.     if (eventmask & TITYPE_KEY)            x11_mask |= KeyPressMask;
  809.     if (eventmask & TITYPE_MOUSEMOVE)      x11_mask |= PointerMotionMask|OwnerGrabButtonMask|ButtonMotionMask|ButtonPressMask|ButtonReleaseMask/*|LeaveWindowMask|EnterWindowMask*/;
  810.     if (eventmask & TITYPE_MOUSEBUTTON)    x11_mask |= ButtonPressMask|ButtonReleaseMask|OwnerGrabButtonMask;
  811.  
  812.     if ((x->mask & TITYPE_MOUSEMOVE) &&
  813.         ((x11_mask & ~(TITYPE_MOUSEMOVE))))
  814.     {
  815.         /* flush pending motion events */
  816.         
  817.         XEvent ev;
  818.  
  819.         while (XCheckTypedWindowEvent(x->display, x->win, MotionNotify, &ev));
  820.     }
  821.     
  822.     x->mask = x->base_mask | x11_mask;
  823.     
  824.     XSelectInput(x->display, x->win, x->mask);
  825.     XFlush(x->display);
  826. }
  827.  
  828.  
  829.  
  830.  
  831.  
  832. /*
  833. **    pen = kn_allocpen(visual, pen-nr, rgbcolor)
  834. **
  835. **    allocate a coloured pen (rgbcolor format: 0x00rrggbb).
  836. **    0xffffffff if out of pens.
  837. */
  838.  
  839. TVPEN kn_allocpen(TAPTR visual, TUINT rgb)
  840. {
  841.     VisualX *x = (VisualX *) visual;
  842.     XColor color;
  843.  
  844.     color.red =   ((rgb >> 16) & 0xFF) << 8;
  845.     color.green = ((rgb >> 8)  & 0xFF) << 8;
  846.     color.blue =  ((rgb)       & 0XFF) << 8;
  847.     color.flags = DoRed | DoGreen | DoBlue;
  848.     
  849.     if (!XAllocColor(x->display, x->colormap, &color))
  850.     {
  851.         return (TVPEN) 0xffffffff;
  852.     }
  853.     
  854.     return (TVPEN) color.pixel;
  855. }
  856.  
  857.  
  858. /*
  859. **    kn_freepen(visual, pen-nr)
  860. **
  861. **    free a coloured pen
  862. */
  863.  
  864. TVOID kn_freepen(TAPTR visual, TVPEN pen)
  865. {
  866.     VisualX *x = (VisualX *) visual;
  867.     unsigned long color = (unsigned long) pen;
  868.     XFreeColors(x->display, x->colormap, &color, 1, 0);        /* what's the last argument for? */
  869. }
  870.  
  871.  
  872. /*
  873. **    kn_setbgpen(visual, pen)
  874. **
  875. **    set background pen
  876. */
  877.  
  878. TVOID kn_setbgpen(TAPTR visual, TVPEN pen)
  879. {
  880.     VisualX *x = (VisualX*) visual;
  881.     XGCValues gcv;
  882.     
  883.     gcv.background = (long) pen;
  884.  
  885.     XChangeGC(x->display, x->gc, GCBackground, &gcv);
  886. }
  887.  
  888.  
  889. /*
  890. **    kn_setfgpen(visual, pen)
  891. **
  892. **    set foreground pen
  893. */
  894.  
  895. TVOID kn_setfgpen(TAPTR visual, TVPEN pen)
  896. {
  897.     VisualX *x = (VisualX*) visual;
  898.     XGCValues gcv;
  899.     
  900.     gcv.foreground = (long) pen;
  901.  
  902.     XChangeGC(x->display, x->gc, GCForeground, &gcv);
  903. }
  904.  
  905.  
  906. /*
  907. **    kn_line(visual, x,y,x2,y2)
  908. **
  909. **    line
  910. */
  911.  
  912. TVOID kn_line(TAPTR visual, TINT x1, TINT y1, TINT x2, TINT y2)
  913. {
  914.     VisualX *x = (VisualX*) visual;
  915.     XDrawLine(x->display, x->win, x->gc, x1, y1, x2, y2);
  916. }
  917.  
  918.  
  919.  
  920. /*
  921. **    kn_frect(visual, x, y, w, h)
  922. **
  923. **    filled rectangle
  924. */
  925.  
  926. TVOID kn_frect(TAPTR v, TINT x1, TINT y1, TINT w, TINT h)
  927. {
  928.     VisualX *x = (VisualX*) v;
  929.     XFillRectangle(x->display, x->win, x->gc, x1, y1, w, h);
  930. }
  931.  
  932.  
  933.  
  934. /*
  935. **    kn_rect(visual, x, y, w, h)
  936. **
  937. **    outline rectangle
  938. */
  939.  
  940. TVOID kn_rect(TAPTR v, TINT x1, TINT y1, TINT w, TINT h)
  941. {
  942.     VisualX *x = (VisualX*) v;
  943.     XDrawRectangle(x->display, x->win, x->gc, x1, y1, w, h);
  944. }
  945.  
  946.  
  947. /*
  948. **    kn_plot(visual, x, y)
  949. **
  950. **    plot
  951. */
  952.  
  953. TVOID kn_plot(TAPTR v, TINT x1, TINT y1)
  954. {
  955.     VisualX *x = (VisualX*) v;
  956.     XDrawPoint(x->display, x->win, x->gc, x1, y1);
  957. }
  958.  
  959.  
  960.  
  961. /*
  962. **    kn_getparameters(visual, visualparameters)
  963. **
  964. **    fill a visual parameters structure
  965. */
  966.  
  967. TVOID kn_getparameters(TAPTR v, struct knvisual_parameters *p)
  968. {
  969.     VisualX *x = (VisualX*) v;
  970.     p->pixelwidth = (TUINT) x->win_w;
  971.     p->pixelheight = (TUINT) x->win_h;
  972.     p->textwidth = (TUINT) x->text_w;
  973.     p->textheight = (TUINT) x->text_h;
  974.     p->fontwidth = (TUINT) x->font_w;
  975.     p->fontheight = (TUINT) x->font_h;
  976. }
  977.  
  978.  
  979.  
  980. /*
  981. **    kn_scroll(visual, x, y, w, h, dx, dy)
  982. **
  983. **    scroll rectangle
  984. **    
  985. */
  986.  
  987. TVOID kn_scroll(TAPTR v, TINT posx, TINT posy, TINT w, TINT h, TINT dx, TINT dy)
  988. {
  989.     VisualX *x = (VisualX*) v;
  990.     XCopyArea(x->display, x->win, x->win, x->gc, (int)posx, (int)posy, (int)w, (int)h, (int)-dx, (int)-dy);
  991. }
  992.  
  993.  
  994.  
  995. /*
  996. **    kn_drawtext(visual, x, y, text, len)
  997. **
  998. **    write text to text cursor position
  999. **    
  1000. */
  1001.  
  1002. TVOID kn_drawtext(TAPTR v, TINT xpos, TINT ypos, TSTRPTR text, TUINT len)
  1003. {
  1004.     VisualX *x = (VisualX*) v;
  1005.     XDrawImageString(x->display, x->win, x->gc, x->font_w * xpos, x->font_h * ypos + x->font->ascent, (char *) text, len);
  1006. }
  1007.  
  1008.  
  1009.  
  1010. /*
  1011. **    kn_waitvisual(visual, timer, event)
  1012. **
  1013. **    wait for visual or supplied event
  1014. **    
  1015. */
  1016.  
  1017. TBOOL kn_waitvisual(TAPTR v, TKNOB *timer, TKNOB *evt)
  1018. {
  1019.     TTIME delay = {0, 10000};
  1020.     VisualX *x = (VisualX*) v;
  1021.     kn_timedwaitevent(evt, timer, &delay);
  1022.     return XPending(x->display);
  1023. }
  1024.  
  1025.  
  1026.  
  1027. /* 
  1028. **    kn_sync    
  1029. **
  1030. */
  1031.  
  1032. TVOID kn_flush(TAPTR v, TINT x, TINT y, TINT w, TINT h)
  1033. {
  1034.     XFlush(((VisualX *) v)->display);
  1035. }
  1036.  
  1037.  
  1038. /* 
  1039. **    kn_drawrgb(v, buf, x,y,w,h,totw)
  1040. **
  1041. **    draw RGB buffer
  1042. */
  1043.  
  1044. TVOID kn_drawrgb(TAPTR v, TUINT *buf, TINT x, TINT y, TINT w, TINT h, TINT totwidth)
  1045. {
  1046.     VisualX *visual = (VisualX*) v;
  1047.     XImage *image;
  1048.  
  1049.     if (w != visual->imw || h != visual->imh)
  1050.     {
  1051.         if (visual->image)
  1052.         {
  1053.             visual->image->data = NULL;
  1054.             XDestroyImage(visual->image);
  1055.             visual->image = NULL;
  1056.             visual->imw = -1;
  1057.         }
  1058.  
  1059.         visual->image = XCreateImage(visual->display, visual->visual,
  1060.             visual->depth, ZPixmap, 0, (char *) buf, w, h, visual->bpp << 3, w * visual->bpp);
  1061.  
  1062.         if (visual->image)
  1063.         {
  1064.             visual->imw = w;
  1065.             visual->imh = h;
  1066.         }
  1067.     }
  1068.     
  1069.  
  1070.     if (visual->image)
  1071.     {
  1072.         int xx, yy, i;
  1073.         TUINT p;
  1074.  
  1075.         switch ((visual->depth << 8) + visual->pixfmt)
  1076.         {
  1077.             case (15 << 8) + PIXFMT_RGB:
  1078.                 for (yy = 0; yy < h; ++yy)
  1079.                 {
  1080.                     for (xx = 0; xx < w; ++xx)
  1081.                     {
  1082.                         p = buf[xx];
  1083.                         XPutPixel(visual->image, xx, yy, 
  1084.                             ((p & 0xf80000) >> 9) | 
  1085.                             ((p & 0x00f800) >> 6) |
  1086.                             ((p & 0x0000f8) >> 3));
  1087.                     }
  1088.                     buf += totwidth;
  1089.                 }
  1090.                 break;
  1091.  
  1092.             case (16 << 8) + PIXFMT_RGB:
  1093.                 for (yy = 0; yy < h; ++yy)
  1094.                 {
  1095.                     for (xx = 0; xx < w; ++xx)
  1096.                     {
  1097.                         p = buf[xx];
  1098.                         XPutPixel(visual->image, xx, yy, 
  1099.                             ((p & 0xf80000) >> 8) | 
  1100.                             ((p & 0x00fc00) >> 5) |
  1101.                             ((p & 0x0000f8) >> 3));
  1102.                     }                
  1103.                     buf += totwidth;
  1104.                 }
  1105.                 break;
  1106.  
  1107.             case (24 << 8) + PIXFMT_RGB:
  1108.                 for (yy = 0; yy < h; ++yy)
  1109.                 {
  1110.                     for (xx = 0; xx < w; ++xx)
  1111.                     {
  1112.                         XPutPixel(visual->image, xx, yy, buf[xx]);
  1113.                     }                
  1114.                     buf += totwidth;
  1115.                 }
  1116.                 break;
  1117.         }
  1118.             
  1119.         XPutImage(visual->display, visual->win, visual->gc, visual->image, 0, 0, x, y, w, h);
  1120.     }
  1121.  
  1122. }
  1123.  
  1124.