home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Emulatoren / UAE061.LZH / uae-0.6.1 / xwin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  23.5 KB  |  906 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * X interface
  5.   * 
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/keysym.h>
  16. #include <X11/cursorfont.h>
  17.  
  18. #ifndef DONT_WANT_SHM
  19. #include <sys/ipc.h>
  20. #include <sys/shm.h>
  21. #include <X11/extensions/XShm.h>
  22. #endif
  23.  
  24. #include "config.h"
  25. #include "options.h"
  26. #include "memory.h"
  27. #include "custom.h"
  28. #include "newcpu.h"
  29. #include "xwin.h"
  30. #include "keyboard.h"
  31. #include "keybuf.h"
  32. #include "gui.h"
  33.  
  34. static Display *display;
  35. static int screen;
  36. static Window rootwin, mywin;
  37.  
  38. static GC whitegc,blackgc;
  39. static XColor black,white;
  40. static Colormap cmap;
  41.  
  42. static int need_dither;
  43.  
  44. static char *image_mem;
  45. static XImage *img;
  46. static Visual *vis;
  47. static XVisualInfo visualInfo;
  48. static int bitdepth, bit_unit;
  49. #ifndef DONT_WANT_SHM
  50. static int use_shm = 1;
  51. static XShmSegmentInfo shminfo;
  52. #endif
  53. static Cursor blankCursor, xhairCursor;
  54. static int cursorOn;
  55.  
  56. #ifdef LOW_BANDWIDTH
  57. static int use_low_bandwidth = 1;
  58. #else
  59. static int use_low_bandwidth = 0;
  60. #endif
  61.  
  62. xcolnr xcolors[4096];
  63.  
  64.  /* Keyboard and mouse */
  65.  
  66. static int keystate[256];
  67.  
  68. int buttonstate[3];
  69. int lastmx, lastmy;
  70. int newmousecounters;
  71.  
  72. static int inwindow;
  73. const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask
  74.                 |ButtonReleaseMask|PointerMotionMask
  75.                 |FocusChangeMask|EnterWindowMask
  76.                 |ExposureMask
  77.                 |LeaveWindowMask);
  78.  
  79. static int vsize, hsize, hpixels;
  80. static char *oldpixbuf;
  81.  
  82. struct vidbuf_description gfxvidinfo;
  83.  
  84. void flush_line(int y)
  85. {
  86.     int xs = 0, xe;
  87.     int len, factor;
  88.     char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
  89.     char *src, *dst;
  90.     if (gfxvidinfo.maxlinetoscr)
  91.     xe = gfxvidinfo.maxlinetoscr-1;
  92.     else
  93.     xe = hsize-1;
  94.  
  95.     if (!use_low_bandwidth)
  96.     fprintf(stderr, "Bug!\n");
  97.     
  98.     switch(gfxvidinfo.pixbytes) {
  99.      case 4:
  100.     {
  101.         int *newp = (int *)linebuf;
  102.         int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  103.         while (newp[xs] == oldp[xs]) {
  104.         if (xs == xe)
  105.             return;
  106.         xs++;
  107.         }
  108.         while (newp[xe] == oldp[xe]) xe--;
  109.         
  110.         dst = (char *)(oldp + xs); src = (char *)(newp + xs);
  111.     }
  112.     break;
  113.      case 2:
  114.     {
  115.         short *newp = (short *)linebuf;
  116.         short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  117.         while (newp[xs] == oldp[xs]) {
  118.         if (xs == xe)
  119.             return;
  120.         xs++;
  121.         }
  122.         while (newp[xe] == oldp[xe]) xe--;
  123.  
  124.         dst = (char *)(oldp + xs); src = (char *)(newp + xs);
  125.     }
  126.     break;
  127.      case 1:
  128.     {
  129.         char *newp = (char *)linebuf;
  130.         char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  131.         while (newp[xs] == oldp[xs]) {
  132.         if (xs == xe)
  133.             return;
  134.         xs++;
  135.         }
  136.         while (newp[xe] == oldp[xe]) xe--;
  137.  
  138.         dst = (char *)(oldp + xs); src = (char *)(newp + xs);
  139.     }
  140.     break;
  141.  
  142.      default:
  143.     abort();
  144.     break;
  145.     }
  146.  
  147.     len = xe - xs + 1;
  148.     memcpy (dst, src, len * gfxvidinfo.pixbytes);
  149.     
  150.     if (need_dither) {
  151.     UBYTE *target = (UBYTE *)image_mem + img->bytes_per_line * y;
  152.     xs &= ~(8/bit_unit - 1);
  153.     len = xe - xs + 1;
  154.     len += 3; len &= ~3;
  155.     len += (8/bit_unit - 1); len &= ~(8/bit_unit-1);
  156.     if (len & 3)
  157.         printf("%d\n",len);
  158.     DitherLine(target + xs*bit_unit/8, (UWORD *)linebuf + xs, xs, y, len, bit_unit);
  159.     }
  160. #ifndef DONT_WANT_SHM
  161.     if (use_shm)
  162.     XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0);
  163.     else
  164. #endif
  165.     XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1);
  166. }
  167.  
  168. void flush_block (int ystart, int ystop)
  169. {
  170.     int len, xs = 0;
  171.     
  172.     if (gfxvidinfo.maxlinetoscr)
  173.     len = gfxvidinfo.maxlinetoscr;
  174.     else
  175.     len = hsize;
  176. #ifndef DONT_WANT_SHM
  177.     if (use_shm)
  178.     XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len,
  179.              ystop - ystart + 1, 0);
  180.     else
  181. #endif
  182.     XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, 
  183.           ystop - ystart + 1);
  184. }
  185.  
  186. void flush_screen (int ystart, int ystop)
  187. {
  188. #ifndef DONT_WANT_SHM
  189.     if (use_shm) XSync(display, 0);
  190. #endif
  191. }
  192.  
  193. void calc_adjustment(void)
  194. {
  195.     switch (screen_res) {
  196.      case 0: case 1: case 2: /* LoRes, 320x300 */
  197.     gfxvidinfo.x_adjust = prev_max_diwstop - 320;
  198.     break;
  199.     
  200.      case 3: /* 640x480 */
  201.     gfxvidinfo.x_adjust = prev_max_diwstop - 640;
  202.     break;
  203.      default:
  204.     gfxvidinfo.x_adjust = 0;
  205.     break;
  206.     }
  207. }
  208.  
  209. static __inline__ int bitsInMask(unsigned long mask)
  210. {
  211.     /* count bits in mask */
  212.     int n = 0;
  213.     while(mask) {
  214.     n += mask&1;
  215.     mask >>= 1;
  216.     }
  217.     return n;
  218. }
  219.  
  220. static __inline__ int maskShift(unsigned long mask)
  221. {
  222.     /* determine how far mask is shifted */
  223.     int n = 0;
  224.     while(!(mask&1)) {
  225.     n++;
  226.     mask >>= 1;
  227.     }
  228.     return n;
  229. }
  230.  
  231. static int get_color(int r, int g, int b, xcolnr *cnp)
  232. {
  233.     XColor col;
  234.     char str[10];
  235.     sprintf(str, "rgb:%x/%x/%x", r, g, b);
  236.     XParseColor(display, cmap, str, &col);
  237.     if (XAllocColor(display, cmap, &col)) {
  238.     *cnp = col.pixel;
  239.     return 1;
  240.     }
  241.     return 0;
  242. }
  243.  
  244. static int init_colors(void)
  245. {
  246.     if (need_dither) {
  247.     if (bitdepth == 1)
  248.         setup_greydither (1, get_color);
  249.     else
  250.         setup_dither (bitdepth, get_color);
  251.     return 1;
  252.     }
  253.     
  254.     if (bitdepth != 8 && bitdepth != 12 
  255.     && bitdepth != 16 && bitdepth != 24) {
  256.         fprintf(stderr, "Unsupported bit depth (%d)\n", bitdepth);
  257.     return 0;
  258.     }
  259.     
  260. #ifdef __cplusplus
  261.     switch(visualInfo.c_class) 
  262. #else
  263.     switch(visualInfo.class) 
  264. #endif
  265.     {
  266.      case TrueColor: 
  267.     {        
  268.         int red_bits = bitsInMask(visualInfo.red_mask);
  269.         int green_bits = bitsInMask(visualInfo.green_mask);
  270.         int blue_bits = bitsInMask(visualInfo.blue_mask);
  271.         int red_shift = maskShift(visualInfo.red_mask);
  272.         int green_shift = maskShift(visualInfo.green_mask);
  273.         int blue_shift = maskShift(visualInfo.blue_mask);
  274.         alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, 
  275.                 green_shift, blue_shift);
  276.     }
  277.     break;
  278.  
  279.      case GrayScale:
  280.      case PseudoColor:
  281.     alloc_colors256(get_color);
  282.     break;
  283.     
  284.      default:
  285. #ifdef __cplusplus
  286.     fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class);
  287. #else
  288.     fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class);
  289. #endif
  290.     return 0;
  291.     }
  292.     return 1;
  293. }
  294.  
  295. int graphics_init(void)
  296. {
  297.     int i,j;
  298.     char *display_name = 0;
  299.     XSetWindowAttributes wattr;
  300.     XPixmapFormatValues *xpfvs;
  301.     need_dither = 0;
  302.     
  303.     if (screen_res < 3) {
  304.     fprintf(stderr, "Low resolution mode selected. Forcing 320x300.\n");
  305.     }
  306.     
  307.     display = XOpenDisplay(display_name);
  308.     if (display == 0)  {
  309.     fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
  310.     return 0;
  311.     }
  312.     screen = XDefaultScreen(display);
  313.     rootwin = XRootWindow(display,screen);
  314.     
  315.     /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
  316.     if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) {
  317.     } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) {
  318.     } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) {
  319.     } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
  320.     /* for our HP boxes */
  321.     } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
  322.     } else if (XMatchVisualInfo(display, screen, 4, PseudoColor, &visualInfo)) {
  323.     /* VGA16 server. Argh. */
  324.     } else if (XMatchVisualInfo(display, screen, 1, StaticGray, &visualInfo)) {
  325.     /* Mono server. Yuk */
  326.     } else {
  327.     fprintf(stderr, "Can't obtain appropriate X visual.\n");
  328.     return 0;
  329.     }
  330.     vis = visualInfo.visual;
  331.     bitdepth = visualInfo.depth;
  332.     
  333.     /* We now have the bitdepth of the display, but that doesn't tell us yet
  334.      * how many bits to use per pixel. The VGA16 server has a bitdepth of 4,
  335.      * but uses 1 byte per pixel. */
  336.     xpfvs = XListPixmapFormats(display, &i);
  337.     for (j = 0; j < i && xpfvs->depth != bitdepth; j++, xpfvs++)
  338.     ;
  339.     if (j == i) {
  340.     fprintf(stderr, "Your X server is feeling ill.\n");
  341.     return 0;
  342.     }
  343.     
  344.     bit_unit = xpfvs->bits_per_pixel;
  345.     fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit);
  346.  
  347.     vsize = correct_aspect ? 2*numscrlines : numscrlines;
  348.     switch (screen_res) {
  349.      case 0: case 1: case 2:
  350.     hsize = hpixels = 320;
  351.     break;
  352.      case 3:
  353.     hsize = hpixels = 640;
  354.     break;
  355.      case 4:
  356.     hpixels = 796; hsize = 800; /* ??? */
  357.     break;
  358.     }
  359.  
  360.     cmap = XCreateColormap(display, rootwin, vis, AllocNone);
  361.     XParseColor(display, cmap, "#000000", &black);
  362.     if (!XAllocColor(display, cmap, &black))
  363.     fprintf(stderr, "Whoops??\n");
  364.     XParseColor(display, cmap, "#ffffff", &white);
  365.     if (!XAllocColor(display, cmap, &white))
  366.     fprintf(stderr, "Whoops??\n");
  367.  
  368.     wattr.event_mask = eventmask;
  369.     wattr.background_pixel = black.pixel;
  370.     wattr.backing_store = Always;
  371.     wattr.backing_planes = bitdepth;
  372.     wattr.border_pixmap = None;
  373.     wattr.border_pixel = black.pixel;
  374.     wattr.colormap = cmap;
  375.  
  376.     mywin = XCreateWindow(display, rootwin, 0, 0, hpixels, vsize, 0,
  377.               bitdepth, InputOutput, vis,
  378.               CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
  379.               |CWBackingPlanes|CWColormap,
  380.               &wattr);
  381.     XMapWindow(display,mywin);
  382.     XStoreName(display, mywin, "UAE");
  383.     
  384.     blankCursor = XCreatePixmapCursor(display,
  385.                       XCreatePixmap(display, mywin, 1, 1, 1),
  386.                       XCreatePixmap(display, mywin, 1, 1, 1), 
  387.                       &black, &white, 0, 0);
  388.     xhairCursor = XCreateFontCursor(display, XC_crosshair);
  389.  
  390.     whitegc = XCreateGC(display,mywin,0,0);
  391.     blackgc = XCreateGC(display,mywin,0,0);
  392.     
  393.     XSetForeground(display,blackgc,black.pixel);
  394.     XSetForeground(display,whitegc,white.pixel);
  395.  
  396.     if (bitdepth < 8 || (bitdepth == 8 && color_mode == 3)) {
  397.     gfxvidinfo.pixbytes = 2;
  398.     use_low_bandwidth = 1;
  399.     need_dither = 1;
  400. #ifndef DONT_WANT_SHM
  401.     use_shm = 0;
  402. #endif
  403.     } else {
  404.     gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
  405.                    : bitdepth == 12 || bitdepth == 16 ? 2
  406.                    : 1);
  407.     }
  408.     
  409. #ifndef DONT_WANT_SHM
  410.     if (use_shm) {
  411.     img = XShmCreateImage(display, vis, bitdepth, ZPixmap, 0, &shminfo, hsize, vsize);
  412.     
  413.     shminfo.shmid = shmget(IPC_PRIVATE, vsize * img->bytes_per_line,
  414.                    IPC_CREAT | 0777);
  415.     shminfo.shmaddr = img->data = image_mem = (char *)shmat(shminfo.shmid, 0, 0);
  416.     shminfo.readOnly = False;
  417.     /* let the xserver attach */
  418.     XShmAttach(display, &shminfo);
  419.     XSync(display,0);
  420.     /* now deleting means making it temporary */
  421.     shmctl(shminfo.shmid, IPC_RMID, 0);
  422.     } else
  423. #endif
  424.     {
  425.     /* Question for people who know about X: Could we allocate the buffer
  426.      * after creating the image and then do img->data = buffer, as below in 
  427.      * the SHM case?
  428.      */
  429.     image_mem = (char *)malloc(vsize * hsize * bit_unit / 8); /* ??? */
  430.     img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, image_mem,
  431.                hsize, vsize, 32, 0);
  432.     if (img->bytes_per_line != hsize * bit_unit / 8)
  433.         fprintf (stderr, "Possible bug here... graphics may look strange.\n");
  434.     }
  435.     
  436.     if (need_dither) {
  437.     gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * hsize;
  438.     gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * vsize);
  439.     } else {
  440.     gfxvidinfo.rowbytes = img->bytes_per_line;
  441.     gfxvidinfo.bufmem = image_mem;
  442.     }
  443.     
  444.     gfxvidinfo.maxline = 100000; /* no limit */
  445.  
  446.     if (use_low_bandwidth) {
  447.     gfxvidinfo.maxblocklines = 0;
  448.     oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * vsize);
  449.     } else {
  450.     gfxvidinfo.maxblocklines = 100; /* whatever... */
  451.     }
  452.  
  453.     if (!init_colors())
  454.     return 0;
  455.  
  456.     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  457.     for(i=0; i<256; i++)
  458.     keystate[i] = 0;
  459.     
  460.     lastmx = lastmy = 0; 
  461.     newmousecounters = 0;
  462.     inwindow = 0;
  463.     
  464.     if (use_xhair)
  465.     XDefineCursor(display, mywin, xhairCursor);
  466.     else
  467.     XDefineCursor(display, mywin, blankCursor);
  468.     cursorOn = 1;
  469.     return 1;
  470. }
  471.  
  472. void graphics_leave(void)
  473. {
  474.     XAutoRepeatOn(display);
  475. }
  476.  
  477. /* Decode KeySyms. This function knows about all keys that are common 
  478.  * between different keyboard languages. */
  479. static int kc_decode (KeySym ks)
  480. {
  481.     switch (ks) {    
  482.      case XK_B: case XK_b: return AK_B;
  483.      case XK_C: case XK_c: return AK_C;
  484.      case XK_D: case XK_d: return AK_D;
  485.      case XK_E: case XK_e: return AK_E;
  486.      case XK_F: case XK_f: return AK_F;
  487.      case XK_G: case XK_g: return AK_G;
  488.      case XK_H: case XK_h: return AK_H;
  489.      case XK_I: case XK_i: return AK_I;
  490.      case XK_J: case XK_j: return AK_J;
  491.      case XK_K: case XK_k: return AK_K;
  492.      case XK_L: case XK_l: return AK_L;
  493.      case XK_N: case XK_n: return AK_N;
  494.      case XK_O: case XK_o: return AK_O;
  495.      case XK_P: case XK_p: return AK_P;
  496.      case XK_R: case XK_r: return AK_R;
  497.      case XK_S: case XK_s: return AK_S;
  498.      case XK_T: case XK_t: return AK_T;
  499.      case XK_U: case XK_u: return AK_U;
  500.      case XK_V: case XK_v: return AK_V;
  501.      case XK_W: case XK_w: return AK_W;
  502.      case XK_X: case XK_x: return AK_X;
  503.     
  504.      case XK_0: return AK_0;
  505.      case XK_1: return AK_1;
  506.      case XK_2: return AK_2;
  507.      case XK_3: return AK_3;
  508.      case XK_4: return AK_4;
  509.      case XK_5: return AK_5;
  510.      case XK_6: return AK_6;
  511.      case XK_7: return AK_7;
  512.      case XK_8: return AK_8;
  513.      case XK_9: return AK_9;
  514.     
  515.     /* You never know which Keysyms might be missing on some workstation
  516.      * This #ifdef should be enough. */
  517. #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
  518.      case XK_KP_0: case XK_KP_Insert: return AK_NP0;
  519.      case XK_KP_1: case XK_KP_End: return AK_NP1;
  520.      case XK_KP_2: case XK_KP_Down: return AK_NP2;
  521.      case XK_KP_3: case XK_KP_Next: return AK_NP3;
  522.      case XK_KP_4: case XK_KP_Left: return AK_NP4;
  523.      case XK_KP_5: case XK_KP_Begin: return AK_NP5;
  524.      case XK_KP_6: case XK_KP_Right: return AK_NP6;
  525.      case XK_KP_7: case XK_KP_Home: return AK_NP7;
  526.      case XK_KP_8: case XK_KP_Up: return AK_NP8;
  527.      case XK_KP_9: case XK_KP_Prior: return AK_NP9;
  528. #else
  529.      case XK_KP_0: return AK_NP0;
  530.      case XK_KP_1: return AK_NP1;
  531.      case XK_KP_2: return AK_NP2;
  532.      case XK_KP_3: return AK_NP3;
  533.      case XK_KP_4: return AK_NP4;
  534.      case XK_KP_5: return AK_NP5;
  535.      case XK_KP_6: return AK_NP6;
  536.      case XK_KP_7: return AK_NP7;
  537.      case XK_KP_8: return AK_NP8;
  538.      case XK_KP_9: return AK_NP9;
  539. #endif
  540.      case XK_KP_Divide: return AK_NPDIV;
  541.      case XK_KP_Multiply: return AK_NPMUL;
  542.      case XK_KP_Subtract: return AK_NPSUB;
  543.      case XK_KP_Add: return AK_NPADD;
  544.      case XK_KP_Decimal: return AK_NPDEL;
  545.      case XK_KP_Enter: return AK_ENT;
  546.  
  547.      case XK_F1: return AK_F1;
  548.      case XK_F2: return AK_F2;
  549.      case XK_F3: return AK_F3;
  550.      case XK_F4: return AK_F4;
  551.      case XK_F5: return AK_F5;
  552.      case XK_F6: return AK_F6;
  553.      case XK_F7: return AK_F7;
  554.      case XK_F8: return AK_F8;
  555.      case XK_F9: return AK_F9;
  556.      case XK_F10: return AK_F10;
  557.         
  558.      case XK_BackSpace: return AK_BS;
  559.      case XK_Delete: return AK_DEL;
  560.      case XK_Control_L: case XK_Control_R: return AK_CTRL;
  561.      case XK_Tab: return AK_TAB;
  562.      case XK_Alt_L: return AK_LALT;
  563.      case XK_Alt_R: return AK_RALT;
  564.      case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
  565.      case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
  566.      case XK_Return: return AK_RET;
  567.      case XK_space: return AK_SPC;
  568.      case XK_Shift_L: return AK_LSH;
  569.      case XK_Shift_R: return AK_RSH;
  570.      case XK_Escape: return AK_ESC;
  571.  
  572.      case XK_Insert: return AK_BACKSLASH;
  573.      case XK_End: return AK_HELP;
  574.      case XK_Caps_Lock: return AK_CAPSLOCK;
  575.     
  576.      case XK_Up: return AK_UP;
  577.      case XK_Down: return AK_DN;
  578.      case XK_Left: return AK_LF;
  579.      case XK_Right: return AK_RT;
  580.     
  581.      case XK_F11: return AK_BACKSLASH;
  582.      case XK_F12: return AK_mousestuff;
  583. #ifdef XK_F14
  584.      case XK_F14:
  585. #endif
  586.      case XK_Scroll_Lock: return AK_inhibit;
  587.  
  588. #ifdef XK_Page_Up /* These are missing occasionally */
  589.      case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
  590.      case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
  591. #endif
  592.     }
  593.     return -1;
  594. }
  595.  
  596. static int decode_fr(KeySym ks)
  597. {
  598.     switch(ks) {        /* FR specific */
  599.      case XK_A: case XK_a: return AK_Q;
  600.      case XK_M: case XK_m: return AK_SEMICOLON; 
  601.      case XK_Q: case XK_q: return AK_A;    
  602.      case XK_Y: case XK_y: return AK_Y;
  603.      case XK_Z: case XK_z: return AK_Z;
  604.      case XK_bracketleft: return AK_LBRACKET;
  605.      case XK_bracketright: return AK_RBRACKET;
  606.      case XK_comma: return AK_M;
  607.      case XK_less: case XK_greater: return AK_LTGT;
  608.      case XK_period: return AK_COMMA;
  609.      case XK_parenright: return AK_MINUS;
  610.      case XK_equal: return AK_SLASH;
  611.      case XK_numbersign: return AK_NUMBERSIGN;
  612.      case XK_slash: return AK_PERIOD;
  613.      case XK_minus: return AK_EQUAL;
  614.      case XK_backslash: return AK_BACKSLASH;
  615.     }
  616.  
  617.     return -1;
  618. }
  619.  
  620. static int decode_us(KeySym ks)
  621. {
  622.     switch(ks) {    /* US specific */    
  623.      case XK_A: case XK_a: return AK_A;
  624.      case XK_M: case XK_m: return AK_M;
  625.      case XK_Q: case XK_q: return AK_Q;
  626.      case XK_Y: case XK_y: return AK_Y;
  627.      case XK_Z: case XK_z: return AK_Z;
  628.      case XK_bracketleft: return AK_LBRACKET;
  629.      case XK_bracketright: return AK_RBRACKET;
  630.      case XK_comma: return AK_COMMA;
  631.      case XK_period: return AK_PERIOD;
  632.      case XK_slash: return AK_SLASH;
  633.      case XK_semicolon: return AK_SEMICOLON;
  634.      case XK_minus: return AK_MINUS;
  635.      case XK_equal: return AK_EQUAL;
  636.     /* this doesn't work: */
  637.      case XK_quoteright: return AK_QUOTE;
  638.      case XK_quoteleft: return AK_BACKQUOTE;
  639.      case XK_backslash: return AK_NUMBERSIGN;
  640.     }
  641.  
  642.     return -1;
  643. }
  644.  
  645. static int decode_de(KeySym ks)
  646. {
  647.     switch(ks) {
  648.     /* DE specific */
  649.      case XK_A: case XK_a: return AK_A;
  650.      case XK_M: case XK_m: return AK_M;
  651.      case XK_Q: case XK_q: return AK_Q;
  652.      case XK_Y: case XK_y: return AK_Z;
  653.      case XK_Z: case XK_z: return AK_Y;
  654.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  655.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  656.      case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
  657.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  658.      case XK_comma: return AK_COMMA;
  659.      case XK_period: return AK_PERIOD;
  660.      case XK_less: case XK_greater: return AK_LTGT;
  661.      case XK_numbersign: return AK_NUMBERSIGN;
  662.      case XK_ssharp: return AK_MINUS;
  663.      case XK_apostrophe: return AK_EQUAL;
  664.      case XK_asciicircum: return AK_BACKQUOTE;
  665.      case XK_minus: return AK_SLASH;
  666.     }
  667.  
  668.     return -1;
  669. }
  670.  
  671. static int decode_se(KeySym ks)
  672. {
  673.     switch(ks) {
  674.     /* SE specific */
  675.      case XK_A: case XK_a: return AK_A;
  676.      case XK_M: case XK_m: return AK_M;
  677.      case XK_Q: case XK_q: return AK_Q;
  678.      case XK_Y: case XK_y: return AK_Y;
  679.      case XK_Z: case XK_z: return AK_Z;
  680.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  681.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  682.      case XK_Aring: case XK_aring: return AK_LBRACKET;
  683.      case XK_comma: return AK_COMMA;
  684.      case XK_period: return AK_PERIOD;
  685.      case XK_minus: return AK_SLASH;
  686.      case XK_less: case XK_greater: return AK_LTGT;
  687.      case XK_plus: case XK_question: return AK_EQUAL;
  688.      case XK_at: case XK_onehalf: return AK_BACKQUOTE;
  689.      case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
  690.      case XK_backslash: case XK_bar: return AK_MINUS;
  691.     
  692.      case XK_numbersign: return AK_NUMBERSIGN;
  693.     }
  694.  
  695.     return -1;
  696.  }
  697.  
  698. static int decode_it(KeySym ks)
  699. {
  700.     switch(ks) {
  701.     /* IT specific */
  702.      case XK_A: case XK_a: return AK_A;
  703.      case XK_M: case XK_m: return AK_M;
  704.      case XK_Q: case XK_q: return AK_Q;
  705.      case XK_Y: case XK_y: return AK_Y;
  706.      case XK_Z: case XK_z: return AK_Z;
  707.      case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
  708.      case XK_Agrave: case XK_agrave: return AK_QUOTE;
  709.      case XK_Egrave: case XK_egrave: return AK_LBRACKET;
  710.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  711.      case XK_comma: return AK_COMMA;
  712.      case XK_period: return AK_PERIOD;
  713.      case XK_less: case XK_greater: return AK_LTGT;
  714.      case XK_backslash: case XK_bar: return AK_BACKQUOTE;               
  715.      case XK_apostrophe: return AK_MINUS;           
  716.      case XK_Igrave: case XK_igrave: return AK_EQUAL;
  717.      case XK_minus: return AK_SLASH;
  718.      case XK_numbersign: return AK_NUMBERSIGN;
  719.     }
  720.  
  721.     return -1;
  722. }
  723.  
  724. static int keycode2amiga(XKeyEvent *event)
  725. {
  726.     KeySym ks;
  727.     int as;
  728.     int index = 0;
  729.     
  730.     do {
  731.     ks = XLookupKeysym(event, index);
  732.     as = kc_decode (ks);
  733.     
  734.     if (as == -1) {        
  735.         switch(keyboard_lang) {
  736.  
  737.         case KBD_LANG_FR:
  738.         as = decode_fr(ks);
  739.         break;
  740.  
  741.          case KBD_LANG_US:
  742.         as = decode_us(ks);
  743.         break;
  744.         
  745.          case KBD_LANG_DE:
  746.         as = decode_de(ks);
  747.         break;
  748.         
  749.          case KBD_LANG_SE:
  750.         as = decode_se(ks);
  751.         break;
  752.         
  753.          case KBD_LANG_IT:
  754.         as = decode_it(ks);
  755.         break;
  756.  
  757.          default:
  758.         as = -1;
  759.         break;
  760.         }
  761.     }
  762.     if(-1 != as)
  763.         return as;
  764.     index++;
  765.     } while (ks != NoSymbol);
  766.     return -1;
  767. }
  768.  
  769. static struct timeval lastMotionTime;
  770.  
  771. void handle_events(void)
  772. {
  773.     int repeat, refresh = 0;
  774.     newmousecounters = 0;
  775.     gui_handle_events();
  776.     
  777.     do {
  778.     XEvent event;
  779.     if (!XCheckMaskEvent(display, eventmask, &event)) break;
  780.     repeat = 0;
  781.     
  782.     switch(event.type) {
  783.      case KeyPress: {        
  784.          int kc = keycode2amiga((XKeyEvent *)&event);
  785.          if (kc == -1) break;
  786.          switch (kc) {
  787.           case AK_mousestuff:
  788.          togglemouse();
  789.          break;
  790.  
  791.           case AK_inhibit:
  792.          inhibit_frame ^= 1;
  793.          break;
  794.  
  795.           default:
  796.               if (!keystate[kc]) {
  797.              keystate[kc] = 1;
  798.              record_key (kc << 1);
  799.          }
  800.          break;
  801.          }
  802.          break;
  803.      }
  804.      case KeyRelease: {         
  805.          int kc = keycode2amiga((XKeyEvent *)&event);
  806.          if (kc == -1) break;
  807.          keystate[kc] = 0;
  808.          record_key ((kc << 1) | 1);
  809.          break;
  810.      }
  811.      case ButtonPress:
  812.         buttonstate[((XButtonEvent *)&event)->button-1] = 1;
  813.         break;
  814.      case ButtonRelease:
  815.         buttonstate[((XButtonEvent *)&event)->button-1] = 0;
  816.         break;
  817.      case EnterNotify:
  818.         newmousecounters = 1;
  819.         lastmx = ((XCrossingEvent *)&event)->x;
  820.         lastmy = ((XCrossingEvent *)&event)->y;
  821.         repeat = 1;
  822.         inwindow = 1;
  823.         break;
  824.      case LeaveNotify:
  825.         inwindow = 0;
  826.         repeat = 1;
  827.         break;
  828.      case FocusIn:
  829.         XAutoRepeatOff(display);
  830.         repeat = 1;
  831.         break;
  832.      case FocusOut:
  833.         XAutoRepeatOn(display);
  834.         repeat = 1;
  835.         break;
  836.      case MotionNotify:
  837.         if (inwindow) {        
  838.         lastmx = ((XMotionEvent *)&event)->x;
  839.         lastmy = ((XMotionEvent *)&event)->y;
  840.         if(!cursorOn && use_xhair) {
  841.             XDefineCursor(display, mywin, xhairCursor);
  842.             cursorOn = 1;
  843.         }
  844.         gettimeofday(&lastMotionTime, NULL);
  845.         }
  846.         repeat = 1;
  847.         break;
  848.      case Expose:
  849.         refresh = 1;
  850.         repeat  = 1;
  851.         break;
  852.     }
  853.     } while (repeat);
  854.  
  855.     if(refresh) {
  856. #ifndef DONT_WANT_SHM
  857.     if (use_shm)
  858.         XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize, 0);
  859.     else
  860. #endif
  861.         XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize);
  862.     }
  863.     if(cursorOn && use_xhair) {
  864.     struct timeval now;
  865.     int diff;
  866.     gettimeofday(&now, NULL);
  867.     diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + 
  868.         (now.tv_usec - lastMotionTime.tv_usec);
  869.     if(diff > 1000000) {
  870.         XDefineCursor(display, mywin, blankCursor);
  871.         cursorOn = 0;
  872.     }
  873.     }
  874.     
  875.     /* "Affengriff" */
  876.     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
  877.         MC68000_reset();
  878. }
  879.  
  880. int debuggable(void)
  881. {
  882.     return 1;
  883. }
  884.  
  885. int needmousehack(void)
  886. {
  887.     return 1;
  888. }
  889.  
  890. void LED(int on)
  891. {
  892.     XKeyboardControl control;
  893.     control.led = 1; /* implementation defined */
  894.     control.led_mode = on ? LedModeOn : LedModeOff;
  895.     XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
  896. }
  897.  
  898. void target_specific_usage(void)
  899. {
  900.     printf("  -S                       : Turn off sound support (if it is configured)\n");
  901.     printf("  -x                       : Use visible cross-hair cursor\n");
  902.     printf("  -l lang                  : Set keyboard language to lang, where lang is\n"
  903.        "                             DE, SE, US, FR or IT\n");
  904.     printf("  -p command               : Use command to pipe printer output to.\n");
  905. }
  906.