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