home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / vid_x.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  26.0 KB  |  1,117 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // vid_x.c -- general x video driver
  21.  
  22. #define _BSD
  23.  
  24. typedef unsigned short PIXEL;
  25.  
  26. #include <ctype.h>
  27. #include <sys/time.h>
  28. #include <sys/types.h>
  29. #include <unistd.h>
  30. #include <signal.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <sys/ipc.h>
  35. #include <sys/shm.h>
  36. #include <X11/Xlib.h>
  37. #include <X11/Xutil.h>
  38. #include <X11/Xatom.h>
  39. #include <X11/keysym.h>
  40. #include <X11/extensions/XShm.h>
  41.  
  42. #include "quakedef.h"
  43. #include "d_local.h"
  44.  
  45. cvar_t    _windowed_mouse = {"_windowed_mouse","0", true};
  46. cvar_t    m_filter = {"m_filter","0", true};
  47. float old_windowed_mouse;
  48.  
  49. // not used
  50. int   VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
  51. byte  *VGA_pagebase;
  52.  
  53.  
  54. qboolean        mouse_avail;
  55. int             mouse_buttons=3;
  56. int             mouse_oldbuttonstate;
  57. int             mouse_buttonstate;
  58. float   mouse_x, mouse_y;
  59. float   old_mouse_x, old_mouse_y;
  60. int p_mouse_x;
  61. int p_mouse_y;
  62. int ignorenext;
  63. int bits_per_pixel;
  64.  
  65. typedef struct
  66. {
  67.   int input;
  68.   int output;
  69. } keymap_t;
  70.  
  71. viddef_t vid; // global video state
  72. unsigned short d_8to16table[256];
  73.  
  74. int   num_shades=32;
  75.  
  76. int d_con_indirect = 0;
  77.  
  78. int   vid_buffersize;
  79.  
  80. static qboolean     doShm;
  81. static Display      *x_disp;
  82. static Colormap     x_cmap;
  83. static Window     x_win;
  84. static GC       x_gc;
  85. static Visual     *x_vis;
  86. static XVisualInfo    *x_visinfo;
  87. //static XImage     *x_image;
  88.  
  89. static int        x_shmeventtype;
  90. //static XShmSegmentInfo  x_shminfo;
  91.  
  92. static qboolean     oktodraw = false;
  93.  
  94. int XShmQueryExtension(Display *);
  95. int XShmGetEventBase(Display *);
  96.  
  97. int current_framebuffer;
  98. static XImage     *x_framebuffer[2] = { 0, 0 };
  99. static XShmSegmentInfo  x_shminfo[2];
  100.  
  101. static int verbose=0;
  102.  
  103. static byte current_palette[768];
  104.  
  105. static long X11_highhunkmark;
  106. static long X11_buffersize;
  107.  
  108. int vid_surfcachesize;
  109. void *vid_surfcache;
  110.  
  111. void (*vid_menudrawfn)(void);
  112. void (*vid_menukeyfn)(int key);
  113. void VID_MenuKey (int key);
  114.  
  115. static PIXEL st2d_8to16table[256];
  116. static int shiftmask_fl=0;
  117. static long r_shift,g_shift,b_shift;
  118. static unsigned long r_mask,g_mask,b_mask;
  119.  
  120. void shiftmask_init()
  121. {
  122.     unsigned int x;
  123.     r_mask=x_vis->red_mask;
  124.     g_mask=x_vis->green_mask;
  125.     b_mask=x_vis->blue_mask;
  126.     for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
  127.     for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
  128.     for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
  129.     shiftmask_fl=1;
  130. }
  131.  
  132. PIXEL xlib_rgb(int r,int g,int b)
  133. {
  134.     PIXEL p;
  135.     if(shiftmask_fl==0) shiftmask_init();
  136.     p=0;
  137.  
  138.     if(r_shift>0) {
  139.         p=(r<<(r_shift))&r_mask;
  140.     } else if(r_shift<0) {
  141.         p=(r>>(-r_shift))&r_mask;
  142.     } else p|=(r&r_mask);
  143.  
  144.     if(g_shift>0) {
  145.         p|=(g<<(g_shift))&g_mask;
  146.     } else if(g_shift<0) {
  147.         p|=(g>>(-g_shift))&g_mask;
  148.     } else p|=(g&g_mask);
  149.  
  150.     if(b_shift>0) {
  151.         p|=(b<<(b_shift))&b_mask;
  152.     } else if(b_shift<0) {
  153.         p|=(b>>(-b_shift))&b_mask;
  154.     } else p|=(b&b_mask);
  155.  
  156.     return p;
  157. }
  158.  
  159. void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
  160. {
  161.   int xi,yi;
  162.   unsigned char *src;
  163.   PIXEL *dest;
  164.  
  165.   if( (x<0)||(y<0) )return;
  166.  
  167.   for (yi = y; yi < (y+height); yi++) {
  168.     src = &framebuf->data [yi * framebuf->bytes_per_line];
  169.     dest = (PIXEL*)src;
  170.     for(xi = (x+width-1); xi >= x; xi--) {
  171.       dest[xi] = st2d_8to16table[src[xi]];
  172.     }
  173.   }
  174. }
  175.  
  176.  
  177. // ========================================================================
  178. // Tragic death handler
  179. // ========================================================================
  180.  
  181. void TragicDeath(int signal_num)
  182. {
  183.   XAutoRepeatOn(x_disp);
  184.   XCloseDisplay(x_disp);
  185.   Sys_Error("This death brought to you by the number %d\n", signal_num);
  186. }
  187.  
  188. // ========================================================================
  189. // makes a null cursor
  190. // ========================================================================
  191.  
  192. static Cursor CreateNullCursor(Display *display, Window root)
  193. {
  194.     Pixmap cursormask; 
  195.     XGCValues xgc;
  196.     GC gc;
  197.     XColor dummycolour;
  198.     Cursor cursor;
  199.  
  200.     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
  201.     xgc.function = GXclear;
  202.     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
  203.     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
  204.     dummycolour.pixel = 0;
  205.     dummycolour.red = 0;
  206.     dummycolour.flags = 04;
  207.     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
  208.           &dummycolour,&dummycolour, 0,0);
  209.     XFreePixmap(display,cursormask);
  210.     XFreeGC(display,gc);
  211.     return cursor;
  212. }
  213.  
  214. void ResetFrameBuffer(void)
  215. {
  216.   int mem;
  217.   int pwidth;
  218.  
  219.   if (x_framebuffer[0])
  220.   {
  221.     free(x_framebuffer[0]->data);
  222.     free(x_framebuffer[0]);
  223.   }
  224.  
  225.   if (d_pzbuffer)
  226.   {
  227.     D_FlushCaches ();
  228.     Hunk_FreeToHighMark (X11_highhunkmark);
  229.     d_pzbuffer = NULL;
  230.   }
  231.   X11_highhunkmark = Hunk_HighMark ();
  232.  
  233. // alloc an extra line in case we want to wrap, and allocate the z-buffer
  234.   X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
  235.  
  236.   vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
  237.  
  238.   X11_buffersize += vid_surfcachesize;
  239.  
  240.   d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
  241.   if (d_pzbuffer == NULL)
  242.     Sys_Error ("Not enough memory for video mode\n");
  243.  
  244.   vid_surfcache = (byte *) d_pzbuffer
  245.     + vid.width * vid.height * sizeof (*d_pzbuffer);
  246.  
  247.   D_InitCaches(vid_surfcache, vid_surfcachesize);
  248.  
  249.   pwidth = x_visinfo->depth / 8;
  250.   if (pwidth == 3) pwidth = 4;
  251.   mem = ((vid.width*pwidth+7)&~7) * vid.height;
  252.  
  253.   x_framebuffer[0] = XCreateImage(  x_disp,
  254.     x_vis,
  255.     x_visinfo->depth,
  256.     ZPixmap,
  257.     0,
  258.     malloc(mem),
  259.     vid.width, vid.height,
  260.     32,
  261.     0);
  262.  
  263.   if (!x_framebuffer[0])
  264.     Sys_Error("VID: XCreateImage failed\n");
  265.  
  266.   vid.buffer = (byte*) (x_framebuffer[0]);
  267.   vid.conbuffer = vid.buffer;
  268.  
  269. }
  270.  
  271. void ResetSharedFrameBuffers(void)
  272. {
  273.  
  274.   int size;
  275.   int key;
  276.   int minsize = getpagesize();
  277.   int frm;
  278.  
  279.   if (d_pzbuffer)
  280.   {
  281.     D_FlushCaches ();
  282.     Hunk_FreeToHighMark (X11_highhunkmark);
  283.     d_pzbuffer = NULL;
  284.   }
  285.  
  286.   X11_highhunkmark = Hunk_HighMark ();
  287.  
  288. // alloc an extra line in case we want to wrap, and allocate the z-buffer
  289.   X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
  290.  
  291.   vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
  292.  
  293.   X11_buffersize += vid_surfcachesize;
  294.  
  295.   d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
  296.   if (d_pzbuffer == NULL)
  297.     Sys_Error ("Not enough memory for video mode\n");
  298.  
  299.   vid_surfcache = (byte *) d_pzbuffer
  300.     + vid.width * vid.height * sizeof (*d_pzbuffer);
  301.  
  302.   D_InitCaches(vid_surfcache, vid_surfcachesize);
  303.  
  304.   for (frm=0 ; frm<2 ; frm++)
  305.   {
  306.  
  307.   // free up old frame buffer memory
  308.  
  309.     if (x_framebuffer[frm])
  310.     {
  311.       XShmDetach(x_disp, &x_shminfo[frm]);
  312.       free(x_framebuffer[frm]);
  313.       shmdt(x_shminfo[frm].shmaddr);
  314.     }
  315.  
  316.   // create the image
  317.  
  318.     x_framebuffer[frm] = XShmCreateImage( x_disp,
  319.             x_vis,
  320.             x_visinfo->depth,
  321.             ZPixmap,
  322.             0,
  323.             &x_shminfo[frm],
  324.             vid.width,
  325.             vid.height );
  326.  
  327.   // grab shared memory
  328.  
  329.     size = x_framebuffer[frm]->bytes_per_line
  330.       * x_framebuffer[frm]->height;
  331.     if (size < minsize)
  332.       Sys_Error("VID: Window must use at least %d bytes\n", minsize);
  333.  
  334.     key = random();
  335.     x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
  336.     if (x_shminfo[frm].shmid==-1)
  337.       Sys_Error("VID: Could not get any shared memory\n");
  338.  
  339.     // attach to the shared memory segment
  340.     x_shminfo[frm].shmaddr =
  341.       (void *) shmat(x_shminfo[frm].shmid, 0, 0);
  342.  
  343.     printf("VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid,
  344.       (long) x_shminfo[frm].shmaddr);
  345.  
  346.     x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
  347.  
  348.   // get the X server to attach to it
  349.  
  350.     if (!XShmAttach(x_disp, &x_shminfo[frm]))
  351.       Sys_Error("VID: XShmAttach() failed\n");
  352.     XSync(x_disp, 0);
  353.     shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
  354.  
  355.   }
  356.  
  357. }
  358.  
  359. // Called at startup to set up translation tables, takes 256 8 bit RGB values
  360. // the palette data will go away after the call, so it must be copied off if
  361. // the video driver will need it again
  362.  
  363. void  VID_Init (unsigned char *palette)
  364. {
  365.  
  366.    int pnum, i;
  367.    XVisualInfo template;
  368.    int num_visuals;
  369.    int template_mask;
  370.  
  371.   S_Init();
  372.    
  373.    ignorenext=0;
  374.    vid.width = 320;
  375.    vid.height = 200;
  376.    vid.maxwarpwidth = WARP_WIDTH;
  377.    vid.maxwarpheight = WARP_HEIGHT;
  378.    vid.numpages = 2;
  379.    vid.colormap = host_colormap;
  380.    // vid.cbits = VID_CBITS;
  381.    // vid.grades = VID_GRADES;
  382.    vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
  383.    
  384.   srandom(getpid());
  385.  
  386.   verbose=COM_CheckParm("-verbose");
  387.  
  388. // open the display
  389.   x_disp = XOpenDisplay(0);
  390.   if (!x_disp)
  391.   {
  392.     if (getenv("DISPLAY"))
  393.       Sys_Error("VID: Could not open display [%s]\n",
  394.         getenv("DISPLAY"));
  395.     else
  396.       Sys_Error("VID: Could not open local display\n");
  397.   }
  398.  
  399. // catch signals so i can turn on auto-repeat
  400.  
  401.   {
  402.     struct sigaction sa;
  403.     sigaction(SIGINT, 0, &sa);
  404.     sa.sa_handler = TragicDeath;
  405.     sigaction(SIGINT, &sa, 0);
  406.     sigaction(SIGTERM, &sa, 0);
  407.   }
  408.  
  409.   XAutoRepeatOff(x_disp);
  410.  
  411. // for debugging only
  412.   XSynchronize(x_disp, True);
  413.  
  414. // check for command-line window size
  415.   if ((pnum=COM_CheckParm("-winsize")))
  416.   {
  417.     if (pnum >= com_argc-2)
  418.       Sys_Error("VID: -winsize <width> <height>\n");
  419.     vid.width = Q_atoi(com_argv[pnum+1]);
  420.     vid.height = Q_atoi(com_argv[pnum+2]);
  421.     if (!vid.width || !vid.height)
  422.       Sys_Error("VID: Bad window width/height\n");
  423.   }
  424.   if ((pnum=COM_CheckParm("-width"))) {
  425.     if (pnum >= com_argc-1)
  426.       Sys_Error("VID: -width <width>\n");
  427.     vid.width = Q_atoi(com_argv[pnum+1]);
  428.     if (!vid.width)
  429.       Sys_Error("VID: Bad window width\n");
  430.   }
  431.   if ((pnum=COM_CheckParm("-height"))) {
  432.     if (pnum >= com_argc-1)
  433.       Sys_Error("VID: -height <height>\n");
  434.     vid.height = Q_atoi(com_argv[pnum+1]);
  435.     if (!vid.height)
  436.       Sys_Error("VID: Bad window height\n");
  437.   }
  438.  
  439.   template_mask = 0;
  440.  
  441. // specify a visual id
  442.   if ((pnum=COM_CheckParm("-visualid")))
  443.   {
  444.     if (pnum >= com_argc-1)
  445.       Sys_Error("VID: -visualid <id#>\n");
  446.     template.visualid = Q_atoi(com_argv[pnum+1]);
  447.     template_mask = VisualIDMask;
  448.   }
  449.  
  450. // If not specified, use default visual
  451.   else
  452.   {
  453.     int screen;
  454.     screen = XDefaultScreen(x_disp);
  455.     template.visualid =
  456.       XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
  457.     template_mask = VisualIDMask;
  458.   }
  459.  
  460. // pick a visual- warn if more than one was available
  461.   x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
  462.   if (num_visuals > 1)
  463.   {
  464.     printf("Found more than one visual id at depth %d:\n", template.depth);
  465.     for (i=0 ; i<num_visuals ; i++)
  466.       printf("  -visualid %d\n", (int)(x_visinfo[i].visualid));
  467.   }
  468.   else if (num_visuals == 0)
  469.   {
  470.     if (template_mask == VisualIDMask)
  471.       Sys_Error("VID: Bad visual id %d\n", template.visualid);
  472.     else
  473.       Sys_Error("VID: No visuals at depth %d\n", template.depth);
  474.   }
  475.  
  476.   if (verbose)
  477.   {
  478.     printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
  479.     printf("  screen %d\n", x_visinfo->screen);
  480.     printf("  red_mask 0x%x\n", (int)(x_visinfo->red_mask));
  481.     printf("  green_mask 0x%x\n", (int)(x_visinfo->green_mask));
  482.     printf("  blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
  483.     printf("  colormap_size %d\n", x_visinfo->colormap_size);
  484.     printf("  bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
  485.   }
  486.  
  487.   x_vis = x_visinfo->visual;
  488.  
  489. // setup attributes for main window
  490.   {
  491.      int attribmask = CWEventMask  | CWColormap | CWBorderPixel;
  492.      XSetWindowAttributes attribs;
  493.      Colormap tmpcmap;
  494.      
  495.      tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
  496.                x_visinfo->screen), x_vis, AllocNone);
  497.      
  498.            attribs.event_mask = StructureNotifyMask | KeyPressMask
  499.        | KeyReleaseMask | ExposureMask | PointerMotionMask |
  500.        ButtonPressMask | ButtonReleaseMask;
  501.      attribs.border_pixel = 0;
  502.      attribs.colormap = tmpcmap;
  503.  
  504. // create the main window
  505.     x_win = XCreateWindow(  x_disp,
  506.       XRootWindow(x_disp, x_visinfo->screen),
  507.       0, 0, // x, y
  508.       vid.width, vid.height,
  509.       0, // borderwidth
  510.       x_visinfo->depth,
  511.       InputOutput,
  512.       x_vis,
  513.       attribmask,
  514.       &attribs );
  515.     XStoreName( x_disp,x_win,"xquake");
  516.  
  517.  
  518.     if (x_visinfo->class != TrueColor)
  519.       XFreeColormap(x_disp, tmpcmap);
  520.  
  521.   }
  522.  
  523.   if (x_visinfo->depth == 8)
  524.   {
  525.  
  526.   // create and upload the palette
  527.     if (x_visinfo->class == PseudoColor)
  528.     {
  529.       x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
  530.       VID_SetPalette(palette);
  531.       XSetWindowColormap(x_disp, x_win, x_cmap);
  532.     }
  533.  
  534.   }
  535.  
  536. // inviso cursor
  537.   XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
  538.  
  539. // create the GC
  540.   {
  541.     XGCValues xgcvalues;
  542.     int valuemask = GCGraphicsExposures;
  543.     xgcvalues.graphics_exposures = False;
  544.     x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
  545.   }
  546.  
  547. // map the window
  548.   XMapWindow(x_disp, x_win);
  549.  
  550. // wait for first exposure event
  551.   {
  552.     XEvent event;
  553.     do
  554.     {
  555.       XNextEvent(x_disp, &event);
  556.       if (event.type == Expose && !event.xexpose.count)
  557.         oktodraw = true;
  558.     } while (!oktodraw);
  559.   }
  560. // now safe to draw
  561.  
  562. // even if MITSHM is available, make sure it's a local connection
  563.   if (XShmQueryExtension(x_disp))
  564.   {
  565.     char *displayname;
  566.     doShm = true;
  567.     displayname = (char *) getenv("DISPLAY");
  568.     if (displayname)
  569.     {
  570.       char *d = displayname;
  571.       while (*d && (*d != ':')) d++;
  572.       if (*d) *d = 0;
  573.       if (!(!strcasecmp(displayname, "unix") || !*displayname))
  574.         doShm = false;
  575.     }
  576.   }
  577.  
  578.   if (doShm)
  579.   {
  580.     x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
  581.     ResetSharedFrameBuffers();
  582.   }
  583.   else
  584.     ResetFrameBuffer();
  585.  
  586.   current_framebuffer = 0;
  587.   vid.rowbytes = x_framebuffer[0]->bytes_per_line;
  588.   vid.buffer = x_framebuffer[0]->data;
  589.   vid.direct = 0;
  590.   vid.conbuffer = x_framebuffer[0]->data;
  591.   vid.conrowbytes = vid.rowbytes;
  592.   vid.conwidth = vid.width;
  593.   vid.conheight = vid.height;
  594.   vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
  595.  
  596. //  XSynchronize(x_disp, False);
  597.  
  598. }
  599.  
  600. void VID_ShiftPalette(unsigned char *p)
  601. {
  602.   VID_SetPalette(p);
  603. }
  604.  
  605.  
  606.  
  607. void VID_SetPalette(unsigned char *palette)
  608. {
  609.  
  610.   int i;
  611.   XColor colors[256];
  612.  
  613.   for(i=0;i<256;i++)
  614.     st2d_8to16table[i]= xlib_rgb(palette[i*3],
  615.       palette[i*3+1],palette[i*3+2]);
  616.  
  617.   if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
  618.   {
  619.     if (palette != current_palette)
  620.       memcpy(current_palette, palette, 768);
  621.     for (i=0 ; i<256 ; i++)
  622.     {
  623.       colors[i].pixel = i;
  624.       colors[i].flags = DoRed|DoGreen|DoBlue;
  625.       colors[i].red = palette[i*3] * 257;
  626.       colors[i].green = palette[i*3+1] * 257;
  627.       colors[i].blue = palette[i*3+2] * 257;
  628.     }
  629.     XStoreColors(x_disp, x_cmap, colors, 256);
  630.   }
  631.  
  632. }
  633.  
  634. // Called at shutdown
  635.  
  636. void  VID_Shutdown (void)
  637. {
  638.   Con_Printf("VID_Shutdown\n");
  639.   XAutoRepeatOn(x_disp);
  640.   XCloseDisplay(x_disp);
  641. }
  642.  
  643. int XLateKey(XKeyEvent *ev)
  644. {
  645.  
  646.   int key;
  647.   char buf[64];
  648.   KeySym keysym;
  649.  
  650.   key = 0;
  651.  
  652.   XLookupString(ev, buf, sizeof buf, &keysym, 0);
  653.  
  654.   switch(keysym)
  655.   {
  656.     case XK_KP_Page_Up:
  657.     case XK_Page_Up:   key = K_PGUP; break;
  658.  
  659.     case XK_KP_Page_Down:
  660.     case XK_Page_Down:   key = K_PGDN; break;
  661.  
  662.     case XK_KP_Home:
  663.     case XK_Home:  key = K_HOME; break;
  664.  
  665.     case XK_KP_End:
  666.     case XK_End:   key = K_END; break;
  667.  
  668.     case XK_KP_Left:
  669.     case XK_Left:  key = K_LEFTARROW; break;
  670.  
  671.     case XK_KP_Right:
  672.     case XK_Right:  key = K_RIGHTARROW;   break;
  673.  
  674.     case XK_KP_Down:
  675.     case XK_Down:  key = K_DOWNARROW; break;
  676.  
  677.     case XK_KP_Up:
  678.     case XK_Up:    key = K_UPARROW;  break;
  679.  
  680.     case XK_Escape: key = K_ESCAPE;   break;
  681.  
  682.     case XK_KP_Enter:
  683.     case XK_Return: key = K_ENTER;     break;
  684.  
  685.     case XK_Tab:    key = K_TAB;       break;
  686.  
  687.     case XK_F1:    key = K_F1;        break;
  688.  
  689.     case XK_F2:    key = K_F2;        break;
  690.  
  691.     case XK_F3:    key = K_F3;        break;
  692.  
  693.     case XK_F4:    key = K_F4;        break;
  694.  
  695.     case XK_F5:    key = K_F5;        break;
  696.  
  697.     case XK_F6:    key = K_F6;        break;
  698.  
  699.     case XK_F7:    key = K_F7;        break;
  700.  
  701.     case XK_F8:    key = K_F8;        break;
  702.  
  703.     case XK_F9:    key = K_F9;        break;
  704.  
  705.     case XK_F10:    key = K_F10;       break;
  706.  
  707.     case XK_F11:    key = K_F11;       break;
  708.  
  709.     case XK_F12:    key = K_F12;       break;
  710.  
  711.     case XK_BackSpace: key = K_BACKSPACE; break;
  712.  
  713.     case XK_KP_Delete:
  714.     case XK_Delete: key = K_DEL; break;
  715.  
  716.     case XK_Pause:  key = K_PAUSE;     break;
  717.  
  718.     case XK_Shift_L:
  719.     case XK_Shift_R:  key = K_SHIFT;    break;
  720.  
  721.     case XK_Execute: 
  722.     case XK_Control_L: 
  723.     case XK_Control_R:  key = K_CTRL;    break;
  724.  
  725.     case XK_Alt_L:  
  726.     case XK_Meta_L: 
  727.     case XK_Alt_R:  
  728.     case XK_Meta_R: key = K_ALT;      break;
  729.  
  730.     case XK_KP_Begin: key = K_AUX30;  break;
  731.  
  732.     case XK_Insert:
  733.     case XK_KP_Insert: key = K_INS; break;
  734.  
  735.     case XK_KP_Multiply: key = '*'; break;
  736.     case XK_KP_Add: key = '+'; break;
  737.     case XK_KP_Subtract: key = '-'; break;
  738.     case XK_KP_Divide: key = '/'; break;
  739.  
  740. #if 0
  741.     case 0x021: key = '1';break;/* [!] */
  742.     case 0x040: key = '2';break;/* [@] */
  743.     case 0x023: key = '3';break;/* [#] */
  744.     case 0x024: key = '4';break;/* [$] */
  745.     case 0x025: key = '5';break;/* [%] */
  746.     case 0x05e: key = '6';break;/* [^] */
  747.     case 0x026: key = '7';break;/* [&] */
  748.     case 0x02a: key = '8';break;/* [*] */
  749.     case 0x028: key = '9';;break;/* [(] */
  750.     case 0x029: key = '0';break;/* [)] */
  751.     case 0x05f: key = '-';break;/* [_] */
  752.     case 0x02b: key = '=';break;/* [+] */
  753.     case 0x07c: key = '\'';break;/* [|] */
  754.     case 0x07d: key = '[';break;/* [}] */
  755.     case 0x07b: key = ']';break;/* [{] */
  756.     case 0x022: key = '\'';break;/* ["] */
  757.     case 0x03a: key = ';';break;/* [:] */
  758.     case 0x03f: key = '/';break;/* [?] */
  759.     case 0x03e: key = '.';break;/* [>] */
  760.     case 0x03c: key = ',';break;/* [<] */
  761. #endif
  762.  
  763.     default:
  764.       key = *(unsigned char*)buf;
  765.       if (key >= 'A' && key <= 'Z')
  766.         key = key - 'A' + 'a';
  767. //      fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym);
  768.       break;
  769.   } 
  770.  
  771.   return key;
  772. }
  773.  
  774. struct
  775. {
  776.   int key;
  777.   int down;
  778. } keyq[64];
  779. int keyq_head=0;
  780. int keyq_tail=0;
  781.  
  782. int config_notify=0;
  783. int config_notify_width;
  784. int config_notify_height;
  785.                   
  786. void GetEvent(void)
  787. {
  788.   XEvent x_event;
  789.   int b;
  790.    
  791.   XNextEvent(x_disp, &x_event);
  792.   switch(x_event.type) {
  793.   case KeyPress:
  794.     keyq[keyq_head].key = XLateKey(&x_event.xkey);
  795.     keyq[keyq_head].down = true;
  796.     keyq_head = (keyq_head + 1) & 63;
  797.     break;
  798.   case KeyRelease:
  799.     keyq[keyq_head].key = XLateKey(&x_event.xkey);
  800.     keyq[keyq_head].down = false;
  801.     keyq_head = (keyq_head + 1) & 63;
  802.     break;
  803.  
  804.   case MotionNotify:
  805.     if (_windowed_mouse.value) {
  806.       mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
  807.       mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
  808. //printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n", 
  809. //  x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
  810.  
  811.       /* move the mouse to the window center again */
  812.       XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
  813.         |KeyReleaseMask|ExposureMask
  814.         |ButtonPressMask
  815.         |ButtonReleaseMask);
  816.       XWarpPointer(x_disp,None,x_win,0,0,0,0, 
  817.         (vid.width/2),(vid.height/2));
  818.       XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
  819.         |KeyReleaseMask|ExposureMask
  820.         |PointerMotionMask|ButtonPressMask
  821.         |ButtonReleaseMask);
  822.     } else {
  823.       mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
  824.       mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
  825.       p_mouse_x=x_event.xmotion.x;
  826.       p_mouse_y=x_event.xmotion.y;
  827.     }
  828.     break;
  829.  
  830.   case ButtonPress:
  831.     b=-1;
  832.     if (x_event.xbutton.button == 1)
  833.       b = 0;
  834.     else if (x_event.xbutton.button == 2)
  835.       b = 2;
  836.     else if (x_event.xbutton.button == 3)
  837.       b = 1;
  838.     if (b>=0)
  839.       mouse_buttonstate |= 1<<b;
  840.     break;
  841.  
  842.   case ButtonRelease:
  843.     b=-1;
  844.     if (x_event.xbutton.button == 1)
  845.       b = 0;
  846.     else if (x_event.xbutton.button == 2)
  847.       b = 2;
  848.     else if (x_event.xbutton.button == 3)
  849.       b = 1;
  850.     if (b>=0)
  851.       mouse_buttonstate &= ~(1<<b);
  852.     break;
  853.   
  854.   case ConfigureNotify:
  855. //printf("config notify\n");
  856.     config_notify_width = x_event.xconfigure.width;
  857.     config_notify_height = x_event.xconfigure.height;
  858.     config_notify = 1;
  859.     break;
  860.  
  861.   default:
  862.     if (doShm && x_event.type == x_shmeventtype)
  863.       oktodraw = true;
  864.   }
  865.    
  866.   if (old_windowed_mouse != _windowed_mouse.value) {
  867.     old_windowed_mouse = _windowed_mouse.value;
  868.  
  869.     if (!_windowed_mouse.value) {
  870.       /* ungrab the pointer */
  871.       XUngrabPointer(x_disp,CurrentTime);
  872.     } else {
  873.       /* grab the pointer */
  874.       XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
  875.         GrabModeAsync,x_win,None,CurrentTime);
  876.     }
  877.   }
  878. }
  879.  
  880. // flushes the given rectangles from the view buffer to the screen
  881.  
  882. void  VID_Update (vrect_t *rects)
  883. {
  884.  
  885. // if the window changes dimension, skip this frame
  886.  
  887.   if (config_notify)
  888.   {
  889.     fprintf(stderr, "config notify\n");
  890.     config_notify = 0;
  891.     vid.width = config_notify_width & ~7;
  892.     vid.height = config_notify_height;
  893.     if (doShm)
  894.       ResetSharedFrameBuffers();
  895.     else
  896.       ResetFrameBuffer();
  897.     vid.rowbytes = x_framebuffer[0]->bytes_per_line;
  898.     vid.buffer = x_framebuffer[current_framebuffer]->data;
  899.     vid.conbuffer = vid.buffer;
  900.     vid.conwidth = vid.width;
  901.     vid.conheight = vid.height;
  902.     vid.conrowbytes = vid.rowbytes;
  903.     vid.recalc_refdef = 1;        // force a surface cache flush
  904.     Con_CheckResize();
  905.     Con_Clear_f();
  906.     return;
  907.   }
  908.  
  909.   if (doShm)
  910.   {
  911.  
  912.     while (rects)
  913.     {
  914.       if (x_visinfo->depth != 8)
  915.         st2_fixup( x_framebuffer[current_framebuffer], 
  916.           rects->x, rects->y, rects->width,
  917.           rects->height);
  918.       if (!XShmPutImage(x_disp, x_win, x_gc,
  919.         x_framebuffer[current_framebuffer], rects->x, rects->y,
  920.         rects->x, rects->y, rects->width, rects->height, True))
  921.           Sys_Error("VID_Update: XShmPutImage failed\n");
  922.       oktodraw = false;
  923.       while (!oktodraw) GetEvent();
  924.       rects = rects->pnext;
  925.     }
  926.     current_framebuffer = !current_framebuffer;
  927.     vid.buffer = x_framebuffer[current_framebuffer]->data;
  928.     vid.conbuffer = vid.buffer;
  929.     XSync(x_disp, False);
  930.   }
  931.   else
  932.   {
  933.     while (rects)
  934.     {
  935.       if (x_visinfo->depth != 8)
  936.         st2_fixup( x_framebuffer[current_framebuffer], 
  937.           rects->x, rects->y, rects->width,
  938.           rects->height);
  939.       XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x,
  940.         rects->y, rects->x, rects->y, rects->width, rects->height);
  941.       rects = rects->pnext;
  942.     }
  943.     XSync(x_disp, False);
  944.   }
  945.  
  946. }
  947.  
  948. static int dither;
  949.  
  950. void VID_DitherOn(void)
  951. {
  952.     if (dither == 0)
  953.     {
  954.     vid.recalc_refdef = 1;
  955.         dither = 1;
  956.     }
  957. }
  958.  
  959. void VID_DitherOff(void)
  960. {
  961.     if (dither)
  962.     {
  963.     vid.recalc_refdef = 1;
  964.         dither = 0;
  965.     }
  966. }
  967.  
  968. int Sys_OpenWindow(void)
  969. {
  970.   return 0;
  971. }
  972.  
  973. void Sys_EraseWindow(int window)
  974. {
  975. }
  976.  
  977. void Sys_DrawCircle(int window, int x, int y, int r)
  978. {
  979. }
  980.  
  981. void Sys_DisplayWindow(int window)
  982. {
  983. }
  984.  
  985. void Sys_SendKeyEvents(void)
  986. {
  987. // get events from x server
  988.   if (x_disp)
  989.   {
  990.     while (XPending(x_disp)) GetEvent();
  991.     while (keyq_head != keyq_tail)
  992.     {
  993.       Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
  994.       keyq_tail = (keyq_tail + 1) & 63;
  995.     }
  996.   }
  997. }
  998.  
  999. #if 0
  1000. char *Sys_ConsoleInput (void)
  1001. {
  1002.  
  1003.   static char text[256];
  1004.   int   len;
  1005.   fd_set  readfds;
  1006.   int   ready;
  1007.   struct timeval timeout;
  1008.  
  1009.   timeout.tv_sec = 0;
  1010.   timeout.tv_usec = 0;
  1011.   FD_ZERO(&readfds);
  1012.   FD_SET(0, &readfds);
  1013.   ready = select(1, &readfds, 0, 0, &timeout);
  1014.  
  1015.   if (ready>0)
  1016.   {
  1017.     len = read (0, text, sizeof(text));
  1018.     if (len >= 1)
  1019.     {
  1020.       text[len-1] = 0;  // rip off the /n and terminate
  1021.       return text;
  1022.     }
  1023.   }
  1024.  
  1025.   return 0;
  1026.   
  1027. }
  1028. #endif
  1029.  
  1030. void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
  1031. {
  1032. // direct drawing of the "accessing disk" icon isn't supported under Linux
  1033. }
  1034.  
  1035. void D_EndDirectRect (int x, int y, int width, int height)
  1036. {
  1037. // direct drawing of the "accessing disk" icon isn't supported under Linux
  1038. }
  1039.  
  1040. void IN_Init (void)
  1041. {
  1042.   Cvar_RegisterVariable (&_windowed_mouse);
  1043.   Cvar_RegisterVariable (&m_filter);
  1044.    if ( COM_CheckParm ("-nomouse") )
  1045.      return;
  1046.    mouse_x = mouse_y = 0.0;
  1047.    mouse_avail = 1;
  1048. }
  1049.  
  1050. void IN_Shutdown (void)
  1051. {
  1052.    mouse_avail = 0;
  1053. }
  1054.  
  1055. void IN_Commands (void)
  1056. {
  1057.   int i;
  1058.    
  1059.   if (!mouse_avail) return;
  1060.    
  1061.   for (i=0 ; i<mouse_buttons ; i++) {
  1062.     if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
  1063.       Key_Event (K_MOUSE1 + i, true);
  1064.  
  1065.     if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
  1066.       Key_Event (K_MOUSE1 + i, false);
  1067.   }
  1068.   mouse_oldbuttonstate = mouse_buttonstate;
  1069. }
  1070.  
  1071. void IN_Move (usercmd_t *cmd)
  1072. {
  1073.   if (!mouse_avail)
  1074.     return;
  1075.    
  1076.   if (m_filter.value) {
  1077.     mouse_x = (mouse_x + old_mouse_x) * 0.5;
  1078.     mouse_y = (mouse_y + old_mouse_y) * 0.5;
  1079.   }
  1080.  
  1081.   old_mouse_x = mouse_x;
  1082.   old_mouse_y = mouse_y;
  1083.    
  1084.   mouse_x *= sensitivity.value;
  1085.   mouse_y *= sensitivity.value;
  1086.    
  1087.   if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
  1088.     cmd->sidemove += m_side.value * mouse_x;
  1089.   else
  1090.     cl.viewangles[YAW] -= m_yaw.value * mouse_x;
  1091.   if (in_mlook.state & 1)
  1092.     V_StopPitchDrift ();
  1093.    
  1094.   if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
  1095.     cl.viewangles[PITCH] += m_pitch.value * mouse_y;
  1096.     if (cl.viewangles[PITCH] > 80)
  1097.       cl.viewangles[PITCH] = 80;
  1098.     if (cl.viewangles[PITCH] < -70)
  1099.       cl.viewangles[PITCH] = -70;
  1100.   } else {
  1101.     if ((in_strafe.state & 1) && noclip_anglehack)
  1102.       cmd->upmove -= m_forward.value * mouse_y;
  1103.     else
  1104.       cmd->forwardmove -= m_forward.value * mouse_y;
  1105.   }
  1106.   mouse_x = mouse_y = 0.0;
  1107. }
  1108.  
  1109. void VID_LockBuffer (void)
  1110. {
  1111. }
  1112.  
  1113. void VID_UnlockBuffer (void)
  1114. {
  1115. }
  1116.  
  1117.