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