home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / video / x11.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  18.0 KB  |  745 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    DOOM graphics stuff for X11, UNIX.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24. #include <stdlib.h>
  25. #include <unistd.h>
  26. #include <sys/ipc.h>
  27. #include <sys/shm.h>
  28.  
  29. #include <X11/Xlib.h>
  30. #include <X11/Xutil.h>
  31. #include <X11/keysym.h>
  32.  
  33. #include <X11/extensions/XShm.h>
  34. // Had to dig up XShm.c for this one.
  35. // It is in the libXext, but not in the XFree86 headers.
  36. #ifdef LINUX
  37. int XShmGetEventBase( Display* dpy ); // problems with g++?
  38. #endif
  39.  
  40. #include <stdarg.h>
  41. #include <sys/time.h>
  42. #include <sys/types.h>
  43. #include <sys/socket.h>
  44.  
  45. #include <netinet/in.h>
  46. #include <errnos.h>
  47.  
  48. #include "doomstat.h"
  49. #include "i_system.h"
  50. #include "v_video.h"
  51. #include "i_video.h"
  52. #include "i_version.h"
  53.  
  54. #include "m_argv.h"
  55. #include "d_main.h"
  56.  
  57. #include "doomdef.h"
  58. #include "r_local.h"
  59. #include "am_map.h"
  60. #include "f_wipe.h"
  61. #include "f_finale.h"
  62.  
  63. #include "z_zone.h"
  64. #include "i_zoom.h"
  65.  
  66. #include "video/x11.h"
  67.  
  68. #define POINTER_WARP_COUNTDOWN    1
  69.  
  70. void CreateImageBuffer(void);
  71.  
  72. Display*    X_display=0;
  73. Window        X_mainWindow;
  74. Colormap    X_cmap;
  75. Visual*        X_visual;
  76. GC            X_gc;
  77. XEvent        X_event;
  78. Screen        *X_screen;
  79. XVisualInfo    X_visualinfo;
  80.  
  81. XImage*        image;
  82. int            X_width;
  83. int            X_height;
  84. // MIT SHared Memory extension.
  85. boolean        doShm;
  86.  
  87. XShmSegmentInfo    X_shminfo;
  88. int        X_shmeventtype;
  89.  
  90. // Fake mouse handling.
  91. // This cannot work properly w/o DGA.
  92. // Needs an invisible mouse cursor at least.
  93. boolean        grabMouse;
  94. int        doPointerWarp = POINTER_WARP_COUNTDOWN;
  95.  
  96. //
  97. //  Translates the key currently in X_event
  98. //
  99.  
  100. int xlatekey(void)
  101. {
  102.     int rc;
  103.  
  104.     switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0))
  105.     {
  106.         case XK_Left:    rc = KEY_LEFTARROW;    break;
  107.         case XK_Right:    rc = KEY_RIGHTARROW;break;
  108.         case XK_Down:    rc = KEY_DOWNARROW;    break;
  109.         case XK_Up:        rc = KEY_UPARROW;    break;
  110.         case XK_Escape:    rc = KEY_ESCAPE;    break;
  111.         case XK_Return:    rc = KEY_ENTER;        break;
  112.         case XK_Tab:    rc = KEY_TAB;        break;
  113.         case XK_F1:    rc = KEY_F1;        break;
  114.         case XK_F2:    rc = KEY_F2;        break;
  115.         case XK_F3:    rc = KEY_F3;        break;
  116.         case XK_F4:    rc = KEY_F4;        break;
  117.         case XK_F5:    rc = KEY_F5;        break;
  118.         case XK_F6:    rc = KEY_F6;        break;
  119.         case XK_F7:    rc = KEY_F7;        break;
  120.         case XK_F8:    rc = KEY_F8;        break;
  121.         case XK_F9:    rc = KEY_F9;        break;
  122.         case XK_F10:    rc = KEY_F10;        break;
  123.         case XK_F11:    rc = KEY_F11;        break;
  124.         case XK_F12:    rc = KEY_F12;        break;
  125.     
  126.         case XK_BackSpace:
  127.         case XK_Delete:    rc = KEY_BACKSPACE;    break;
  128.  
  129.         case XK_Pause:    rc = KEY_PAUSE;        break;
  130.  
  131.         case XK_KP_Equal:
  132.         case XK_equal:    rc = KEY_EQUALS;    break;
  133.  
  134.         case XK_KP_Subtract:
  135.         case XK_minus:    rc = KEY_MINUS;        break;
  136.  
  137.         case XK_Shift_L:
  138.         case XK_Shift_R:
  139.             rc = KEY_RSHIFT;
  140.             break;
  141.  
  142.         case XK_Control_L:
  143.         case XK_Control_R:
  144.             rc = KEY_RCTRL;
  145.             break;
  146.     
  147.         case XK_Alt_L:
  148.         case XK_Meta_L:
  149.         case XK_Alt_R:
  150.         case XK_Meta_R:
  151.             rc = KEY_RALT;
  152.             break;
  153.  
  154.         case XK_KP_End:        rc='1';    break;
  155.         case XK_KP_Down:    rc='2';    break;
  156.         case XK_KP_Page_Down:    rc='3';    break;
  157.         case XK_KP_Left:    rc='4';    break;
  158.         case XK_KP_Begin:    rc='5';    break;
  159.         case XK_KP_Right:    rc='6';    break;
  160.         case XK_KP_Home:    rc='7';    break;
  161.         case XK_KP_Up:        rc='8';    break;
  162.         case XK_KP_Page_Up:    rc='9';    break;
  163.     
  164.         default:
  165.             if (rc >= XK_space && rc <= XK_asciitilde)
  166.                 rc = rc - XK_space + ' ';
  167.             if (rc >= 'A' && rc <= 'Z')
  168.                 rc = rc - 'A' + 'a';
  169.             break;
  170.     }
  171.  
  172.     return rc;
  173. }
  174.  
  175. void I_ShutdownGraphics_x11(void)
  176. {
  177.     // Detach from X server
  178.     if (!XShmDetach(X_display, &X_shminfo))
  179.         I_Error("XShmDetach() failed in I_ShutdownGraphics()");
  180.  
  181.     // Release shared memory.
  182.     shmdt(X_shminfo.shmaddr);
  183.     shmctl(X_shminfo.shmid, IPC_RMID, 0);
  184.  
  185.     // Paranoia.
  186.     image->data = NULL;
  187. }
  188.  
  189. static int    lastmousex = 0;
  190. static int    lastmousey = 0;
  191. boolean        mousemoved = false;
  192. boolean        shmFinished;
  193.  
  194. void I_GetEvent(void)
  195. {
  196.     event_t event;
  197.  
  198.     // put event-grabbing stuff in here
  199.     XNextEvent(X_display, &X_event);
  200.     switch (X_event.type)
  201.     {
  202.         case KeyPress:
  203.             event.type = ev_keydown;
  204.             event.data1 = xlatekey();
  205.             D_PostEvent(&event);
  206.             // fprintf(stderr, "k");
  207.             break;
  208.         case KeyRelease:
  209.             event.type = ev_keyup;
  210.             event.data1 = xlatekey();
  211.             D_PostEvent(&event);
  212.             // fprintf(stderr, "ku");
  213.             break;
  214.         case ButtonPress:
  215.             event.type = ev_mouse;
  216.             event.data1 =
  217.                 (X_event.xbutton.state & Button1Mask)
  218.                 | (X_event.xbutton.state & Button2Mask ? 2 : 0)
  219.                 | (X_event.xbutton.state & Button3Mask ? 4 : 0)
  220.                 | (X_event.xbutton.button == Button1)
  221.                 | (X_event.xbutton.button == Button2 ? 2 : 0)
  222.                 | (X_event.xbutton.button == Button3 ? 4 : 0);
  223.             event.data2 = event.data3 = 0;
  224.             D_PostEvent(&event);
  225.             // fprintf(stderr, "b");
  226.             break;
  227.         case ButtonRelease:
  228.             if ( I_UpdateMouse == I_UpdateMouse_x11 )
  229.             {
  230.                 event.type = ev_mouse;
  231.                 event.data1 =
  232.                     (X_event.xbutton.state & Button1Mask)
  233.                     | (X_event.xbutton.state & Button2Mask ? 2 : 0)
  234.                     | (X_event.xbutton.state & Button3Mask ? 4 : 0);
  235.                 // suggest parentheses around arithmetic in operand of |
  236.                 event.data1 = event.data1
  237.                     ^ (X_event.xbutton.button == Button1 ? 1 : 0)
  238.                     ^ (X_event.xbutton.button == Button2 ? 2 : 0)
  239.                     ^ (X_event.xbutton.button == Button3 ? 4 : 0);
  240.                 event.data2 = event.data3 = 0;
  241.                 D_PostEvent(&event);
  242.                 // fprintf(stderr, "bu");
  243.             }
  244.             break;
  245.         case MotionNotify:
  246.             if ( I_UpdateMouse == I_UpdateMouse_x11)
  247.             {
  248.                 event.type = ev_mouse;
  249.                 event.data1 =
  250.                     (X_event.xmotion.state & Button1Mask)
  251.                     | (X_event.xmotion.state & Button2Mask ? 2 : 0)
  252.                     | (X_event.xmotion.state & Button3Mask ? 4 : 0);
  253.                 event.data2 = (X_event.xmotion.x - lastmousex) << 2;
  254.                 event.data3 = (lastmousey - X_event.xmotion.y) << 2;
  255.  
  256.                 if (event.data2 || event.data3)
  257.                 {
  258.                     lastmousex = X_event.xmotion.x;
  259.                     lastmousey = X_event.xmotion.y;
  260.                     if (X_event.xmotion.x != X_width/2 &&
  261.                         X_event.xmotion.y != X_height/2)
  262.                     {
  263.                         D_PostEvent(&event);
  264.                         // fprintf(stderr, "m");
  265.                         mousemoved = false;
  266.                     } else
  267.                         mousemoved = true;
  268.                 }
  269.             }
  270.             break;
  271.         //case Expose:
  272.         case ConfigureNotify:
  273.             if (X_event.xany.window==X_mainWindow &&
  274.                 (X_width!=X_event.xconfigure.width ||
  275.                 X_height!=X_event.xconfigure.height))
  276.             {
  277.                 /* Kill old shared memory and image */
  278.                 if (doShm)
  279.                 {
  280.                     XShmDetach (X_display, &X_shminfo);
  281.                     shmdt (X_shminfo.shmaddr);
  282.                 } else {
  283.                     XDestroyImage (image);
  284.                     image=NULL;
  285.                 }
  286.  
  287.                 /* Create new shared memory and image */
  288.                 X_width=X_event.xconfigure.width;
  289.                 X_height=X_event.xconfigure.height;
  290.  
  291.                 CreateImageBuffer();
  292.             }
  293.             break;
  294.         default:
  295.             if (doShm && X_event.type == X_shmeventtype)
  296.                 shmFinished = true;
  297.         break;
  298.     }
  299. }
  300.  
  301. Cursor createnullcursor( Display*    display,Window    root )
  302. {
  303.     Pixmap cursormask;
  304.     XGCValues xgc;
  305.     GC gc;
  306.     XColor dummycolour;
  307.     Cursor cursor;
  308.  
  309.     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
  310.     xgc.function = GXclear;
  311.     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
  312.     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
  313.     dummycolour.pixel = 0;
  314.     dummycolour.red = 0;
  315.     dummycolour.flags = 04;
  316.     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
  317.                  &dummycolour,&dummycolour, 0,0);
  318.     XFreePixmap(display,cursormask);
  319.     XFreeGC(display,gc);
  320.     return cursor;
  321. }
  322.  
  323. //
  324. // I_StartTic
  325. //
  326. void I_UpdateKeyboard_x11 (void)
  327. {
  328.     if (!X_display)
  329.         return;
  330.  
  331.     while (XPending(X_display))
  332.         I_GetEvent();
  333. }
  334.  
  335. void I_UpdateMouse_x11 (void)
  336. {
  337.     if (!X_display)
  338.         return;
  339.  
  340.     // Warp the pointer back to the middle of the window
  341.     //  or it will wander off - that is, the game will
  342.     //  loose input focus within X11.
  343.     if (grabMouse)
  344.     {
  345.         if (!--doPointerWarp)
  346.         {
  347.             XWarpPointer( X_display,
  348.               None,
  349.               X_mainWindow,
  350.               0, 0,
  351.               0, 0,
  352.               X_width/2, X_height/2);
  353.  
  354.             doPointerWarp = POINTER_WARP_COUNTDOWN;
  355.         }
  356.     }
  357.  
  358.     mousemoved = false;
  359. }
  360.  
  361. void I_VidUpdate_x11 (void)
  362. {
  363.     I_Zoom(screens[0],image->data);
  364.  
  365.     if (doShm)
  366.     {
  367.         if (!XShmPutImage(    X_display,
  368.                 X_mainWindow,
  369.                 X_gc,
  370.                 image,
  371.                 0, 0,
  372.                 0, 0,
  373.                 X_width, X_height,
  374.                 True ))
  375.             I_Error("XShmPutImage() failed\n");
  376.  
  377.         // wait for it to finish and processes all input events
  378.         shmFinished = false;
  379.         do
  380.         {
  381.             I_GetEvent();
  382.         } while (!shmFinished);
  383.     }
  384.     else
  385.     {
  386.         // draw the image
  387.         XPutImage(    X_display,
  388.             X_mainWindow,
  389.             X_gc,
  390.             image,
  391.             0, 0,
  392.             0, 0,
  393.             X_width, X_height );
  394.  
  395.         // sync up with server
  396.         XSync(X_display, False);
  397.     }
  398. }
  399.  
  400. //
  401. // Palette stuff.
  402. //
  403. static XColor    colors[256];
  404.  
  405. //
  406. // I_SetPalette
  407. //
  408. void I_SetPalette256_x11(byte *palette)
  409. {
  410.     int        i,c;
  411.     static boolean    firstcall = true;
  412.  
  413.     if (firstcall)
  414.     {
  415.         firstcall = false;
  416.         for (i=0 ; i<256 ; i++)
  417.         {
  418.             colors[i].pixel = i;
  419.             colors[i].flags = DoRed|DoGreen|DoBlue;
  420.         }
  421.     }
  422.  
  423.     for(i = 0; i < 256; i++)
  424.     {
  425.         c = gammatable[usegamma][*palette++];    
  426.         colors[i].red = (c<<8) + c;
  427.         c = gammatable[usegamma][*palette++];
  428.         colors[i].green = (c<<8) + c;
  429.         c = gammatable[usegamma][*palette++];
  430.         colors[i].blue = (c<<8) + c;
  431.     }
  432.     XStoreColors(X_display,X_cmap,colors,256);
  433. }
  434.  
  435. void I_InitGraphics_x11(void)
  436. {
  437.     char*        displayname;
  438.     char*        d;
  439.     int            n;
  440.     int            pnum;
  441.     int            x=0;
  442.     int            y=0;
  443.  
  444.     // warning: char format, different type arg
  445.     char        xsign=' ';
  446.     char        ysign=' ';
  447.     
  448.     int            oktodraw;
  449.     unsigned long    attribmask;
  450.     XSetWindowAttributes attribs;
  451.     XGCValues        xgcvalues;
  452.     int            valuemask;
  453.     static int        firsttime=1;
  454.  
  455.     if (!firsttime)
  456.         return;
  457.     firsttime = 0;
  458.  
  459.     X_width = SCREENWIDTH;
  460.     X_height = SCREENHEIGHT;
  461.  
  462.     // check for command-line display name
  463.     if ( (pnum=M_CheckParm("-disp")) ) // suggest parentheses around assignment
  464.         displayname = myargv[pnum+1];
  465.     else
  466.         displayname = 0;
  467.  
  468.     // check if the user wants to grab the mouse (quite unnice)
  469.     grabMouse = !!M_CheckParm("-grabmouse");
  470.  
  471.     // check for command-line geometry
  472.     if ( (pnum=M_CheckParm("-geom")) ) // suggest parentheses around assignment
  473.     {
  474.         // warning: char format, different type arg 3,5
  475.         n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y);
  476.     
  477.         if (n==2)
  478.             x = y = 0;
  479.         else if (n==6)
  480.             if (xsign == '-')
  481.                 x = -x;
  482.             if (ysign == '-')
  483.                 y = -y;
  484.         else
  485.             I_Error("bad -geom parameter");
  486.     }
  487.  
  488.     /* open the display */
  489.     X_display = XOpenDisplay(displayname);
  490.     if (!X_display)
  491.         if (displayname)
  492.             I_Error("Could not open display [%s]", displayname);
  493.     else
  494.         I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY"));
  495.  
  496.     /* use the default visual */
  497.     X_screen = DefaultScreenOfDisplay(X_display);
  498.  
  499.        /* Read screen depth */
  500.     bpp = DefaultDepthOfScreen(X_screen);
  501.     switch (bpp)
  502.     {
  503.         case 8:
  504.             R_DrawColumn=R_DrawColumn8;
  505.             R_DrawColumnLow=R_DrawColumnLow8;
  506.             R_DrawFuzzColumn=R_DrawFuzzColumn8;
  507.             R_DrawFuzzColumnLow=R_DrawFuzzColumnLow8;
  508.             R_DrawTranslatedColumn=R_DrawTranslatedColumn8;
  509.             R_DrawTranslatedColumnLow=R_DrawTranslatedColumnLow8;
  510.             R_DrawSpan=R_DrawSpan8;
  511.             R_DrawSpanLow=R_DrawSpanLow8;
  512.             AM_DrawFline=AM_drawFline8;
  513.             wipe_doMelt=wipe_doMelt8;
  514.             V_DrawPatch=V_DrawPatch8;
  515.             V_DrawPatchFlipped=V_DrawPatchFlipped8;
  516.             F_DrawPatchCol=F_DrawPatchCol8;
  517.             I_Zoom=I_Zoom8;
  518.             pixel_size=1;
  519.             break;
  520.         case 15:
  521.             R_DrawColumn=R_DrawColumn16;
  522.             R_DrawColumnLow=R_DrawColumnLow16;
  523.             R_DrawFuzzColumn=R_DrawFuzzColumn16;
  524.             R_DrawFuzzColumnLow=R_DrawFuzzColumnLow16;
  525.             R_DrawTranslatedColumn=R_DrawTranslatedColumn16;
  526.             R_DrawTranslatedColumnLow=R_DrawTranslatedColumnLow16;
  527.             R_DrawSpan=R_DrawSpan16;
  528.             R_DrawSpanLow=R_DrawSpanLow16;
  529.             AM_DrawFline=AM_drawFline16;
  530.             wipe_doMelt=wipe_doMelt16;
  531.             V_DrawPatch=V_DrawPatch16;
  532.             V_DrawPatchFlipped=V_DrawPatchFlipped16;
  533.             F_DrawPatchCol=F_DrawPatchCol16;
  534.             I_Zoom=I_Zoom16;
  535.             pixel_size=2;
  536.             fuzzmask=0x3DEF3DEF;
  537.             break;
  538.         case 16:
  539.             R_DrawColumn=R_DrawColumn16;
  540.             R_DrawColumnLow=R_DrawColumnLow16;
  541.             R_DrawFuzzColumn=R_DrawFuzzColumn16;
  542.             R_DrawFuzzColumnLow=R_DrawFuzzColumnLow16;
  543.             R_DrawTranslatedColumn=R_DrawTranslatedColumn16;
  544.             R_DrawTranslatedColumnLow=R_DrawTranslatedColumnLow16;
  545.             R_DrawSpan=R_DrawSpan16;
  546.             R_DrawSpanLow=R_DrawSpanLow16;
  547.             AM_DrawFline=AM_drawFline16;
  548.             wipe_doMelt=wipe_doMelt16;
  549.             V_DrawPatch=V_DrawPatch16;
  550.             V_DrawPatchFlipped=V_DrawPatchFlipped16;
  551.             F_DrawPatchCol=F_DrawPatchCol16;
  552.             I_Zoom=I_Zoom16;
  553.             pixel_size=2;
  554.             fuzzmask=0x7BEF7BEF;
  555.             break;
  556.         case 24:
  557.             R_DrawColumn=R_DrawColumn24;
  558.             R_DrawColumnLow=R_DrawColumnLow24;
  559.             R_DrawFuzzColumn=R_DrawFuzzColumn24;
  560.             R_DrawFuzzColumnLow=R_DrawFuzzColumnLow24;
  561.             R_DrawTranslatedColumn=R_DrawTranslatedColumn24;
  562.             R_DrawTranslatedColumnLow=R_DrawTranslatedColumnLow24;
  563.             R_DrawSpan=R_DrawSpan24;
  564.             R_DrawSpanLow=R_DrawSpanLow24;
  565.             AM_DrawFline=AM_drawFline24;
  566.             wipe_doMelt=wipe_doMelt24;
  567.             V_DrawPatch=V_DrawPatch24;
  568.             V_DrawPatchFlipped=V_DrawPatchFlipped24;
  569.             F_DrawPatchCol=F_DrawPatchCol24;
  570.             I_Zoom=I_Zoom24;
  571.             pixel_size=3;
  572.             break;
  573.         case 32:
  574.             R_DrawColumn=R_DrawColumn32;
  575.             R_DrawColumnLow=R_DrawColumnLow32;
  576.             R_DrawFuzzColumn=R_DrawFuzzColumn32;
  577.             R_DrawFuzzColumnLow=R_DrawFuzzColumnLow32;
  578.             R_DrawTranslatedColumn=R_DrawTranslatedColumn32;
  579.             R_DrawTranslatedColumnLow=R_DrawTranslatedColumnLow32;
  580.             R_DrawSpan=R_DrawSpan32;
  581.             R_DrawSpanLow=R_DrawSpanLow32;
  582.             AM_DrawFline=AM_drawFline32;
  583.             wipe_doMelt=wipe_doMelt32;
  584.             V_DrawPatch=V_DrawPatch32;
  585.             V_DrawPatchFlipped=V_DrawPatchFlipped32;
  586.             F_DrawPatchCol=F_DrawPatchCol32;
  587.             I_Zoom=I_Zoom32;
  588.             pixel_size=4;
  589.             fuzzmask=0x007F7F7F;
  590.             break;
  591.         default:
  592.             I_Error("Unknown pixel size for screen\n");
  593.     }
  594.  
  595.     if (bpp==8)
  596.         if (!XMatchVisualInfo(X_display, DefaultScreen(X_display),
  597.             bpp, PseudoColor, &X_visualinfo))
  598.             I_Error("Could not get PseudoColor visual!\n");
  599.     else
  600.         if (!XMatchVisualInfo(X_display, DefaultScreen(X_display),
  601.             bpp, TrueColor, &X_visualinfo))
  602.             I_Error("Could not get TrueColor visual!\n");
  603.  
  604.     X_visual = X_visualinfo.visual;
  605.  
  606.     // check for the MITSHM extension
  607.     doShm = XShmQueryExtension(X_display);
  608.  
  609.     // even if it's available, make sure it's a local connection
  610.     if (doShm)
  611.     {
  612.         if (!displayname)
  613.             displayname = (char *) getenv("DISPLAY");
  614.         if (displayname)
  615.         {
  616.             d = displayname;
  617.             while (*d && (*d != ':'))
  618.                 d++;
  619.             if (*d)
  620.                 *d = 0;
  621.             if (!(!strcasecmp(displayname, "unix") || !*displayname))
  622.                 doShm = false;
  623.         }
  624.     }
  625.  
  626.     // create the colormap
  627.     if (bpp==8)
  628.         X_cmap = XCreateColormap(    X_display,
  629.                         RootWindowOfScreen(X_screen),
  630.                         X_visual,
  631.                         AllocAll);
  632.     else
  633.           X_cmap = DefaultColormapOfScreen(X_screen);
  634.  
  635.     // setup attributes for main window
  636.     attribmask = CWEventMask | CWColormap | CWBorderPixel;
  637.     attribs.event_mask = KeyPressMask | KeyReleaseMask
  638.         | StructureNotifyMask | ExposureMask;
  639.     // | PointerMotionMask | ButtonPressMask | ButtonReleaseMask
  640.  
  641.     attribs.colormap = X_cmap;
  642.     attribs.border_pixel = 0;
  643.  
  644.     // create the main window
  645.     X_mainWindow = XCreateWindow(    X_display,
  646.                     RootWindowOfScreen(X_screen),
  647.                     x, y,
  648.                     X_width, X_height,
  649.                     0, // borderwidth
  650.                     bpp, // depth
  651.                     InputOutput,
  652.                     X_visual,
  653.                     attribmask,
  654.                     &attribs );
  655.  
  656.     XDefineCursor(X_display, X_mainWindow,
  657.           createnullcursor( X_display, X_mainWindow ) );
  658.  
  659.     // create the GC
  660.     valuemask = GCGraphicsExposures;
  661.     xgcvalues.graphics_exposures = False;
  662.     X_gc = XCreateGC(    X_display,
  663.               X_mainWindow,
  664.               valuemask,
  665.               &xgcvalues );
  666.  
  667.     // map the window
  668.     XMapWindow(X_display, X_mainWindow);
  669.  
  670.     // wait until it is OK to draw
  671.     oktodraw = 0;
  672.     while (!oktodraw)
  673.     {
  674.         XNextEvent(X_display, &X_event);
  675.         if ((X_event.type == Expose) && (!X_event.xexpose.count))
  676.             oktodraw = 1;
  677.     }
  678.  
  679.     // grabs the pointer so it is restricted to this window
  680.     if (grabMouse)
  681.         XGrabPointer(X_display, X_mainWindow, True,
  682.             ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
  683.             GrabModeAsync, GrabModeAsync,X_mainWindow, None, CurrentTime);
  684.  
  685.     if (doShm)
  686.     {
  687.         fprintf(stderr, "Using MITSHM extension\n");
  688.         X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion;
  689.     }
  690.  
  691.     CreateImageBuffer();
  692.  
  693.     XStoreName (X_display, X_mainWindow, version_name);
  694.     XFlush (X_display);
  695. }
  696.  
  697. void CreateImageBuffer(void)
  698. {
  699.     /* Create new zoom tables */
  700.     I_ZoomInit(X_width,X_height);
  701.  
  702.     if (doShm)
  703.     {
  704.         // create the image
  705.         image = XShmCreateImage(    X_display,
  706.                     X_visual,
  707.                     bpp,
  708.                     ZPixmap,
  709.                     0,
  710.                     &X_shminfo,
  711.                     X_width,
  712.                     X_height );
  713.  
  714.         //grabsharedmemory(image->bytes_per_line * image->height);
  715.  
  716.         X_shminfo.shmid = shmget( (key_t) random() /*SHMKEY*/, image->bytes_per_line * image->height, IPC_CREAT|0777);
  717.         if (X_shminfo.shmid==-1)
  718.             I_Error("Could not get any shared memory\n");
  719.  
  720.         // attach to the shared memory segment
  721.         X_shminfo.shmaddr = (void *) shmat(X_shminfo.shmid, 0, 0);
  722.  
  723.         image->data = X_shminfo.shmaddr;
  724.  
  725.         // get the X server to attach to it
  726.         if (!XShmAttach(X_display, &X_shminfo))
  727.             I_Error("XShmAttach() failed in InitGraphics()");
  728.  
  729.         shmctl (X_shminfo.shmid, IPC_RMID, 0);
  730.     }
  731.     else
  732.     {
  733.         image = XCreateImage(    X_display,
  734.                     X_visual,
  735.                     bpp,
  736.                     ZPixmap,
  737.                     0,
  738.                     (char*)malloc(X_width * X_height * pixel_size),
  739.                     X_width, X_height,
  740.                     bpp,
  741.                     X_width *pixel_size);
  742.  
  743.     }
  744. }
  745.