/* This file is part of STonX, the Atari ST Emulator for Unix/X * ============================================================ * STonX is free software and comes with NO WARRANTY - read the file * COPYING for details */ /* TODO in the next few releases: * - allocate colors on demand (not all 4096 immediately) * - clean up code, remove dead flags and code * - test on more displays */ #include "defs.h" #include "tosdefs.h" #include "debug.h" #include "ikbd.h" #include "main.h" #include "screen.h" #include "utils.h" #include "xlib_vdi.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef CLK_TCK #define CLK_TCK HZ #endif #define GCURX 0x25a #define GCURY 0x258 UW stcolor_buf[320*200]; #define GRABMODE 0 #define HIDEMODE 1 #define REDRAW 1 #define BENCH_REFRESH 0 #define NUM_AVG 100 #define SET_MOUSE 1 #ifdef SH_MEM #include #include #include #include #ifndef SHMMAX #define SHMMAX (1<<22) #endif static XShmSegmentInfo shminfo; static shm_used; #endif static char txt[256]; Cursor cursors[2]; static int cursidx=0; static int warped=0; #if BENCH_REFRESH static int cref=0; static clock_t reftime; static int chunks_seen=0,chunks_drawn=0; #endif static Pixmap empty; #if GRABMODE static int grabbed=1; #endif static Window in_which=None; static XVisualInfo vi; static int tc_cols[16]; /* new stuff */ #define STE_COLORS 4096 static int mono_mode; static int bits_per_pixel; static int indexed_color; static unsigned long pixel_value[STE_COLORS]; static unsigned long pixel_value_by_index[16]; static unsigned char pixel_index[16]; static int is_allocated[STE_COLORS]; SCRDEF scr_def[3]; /* some interesting events: */ #define E_MASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \ |ButtonReleaseMask|PointerMotionMask|ColormapChangeMask|\ EnterWindowMask|LeaveWindowMask|ExposureMask) static int old_shiftmod=-1; /* last known shift mode, used to detect changes */ static UW old_color[16]; /* last known color palette */ static int shm_mono=1; static char **ksyms; static int redraw_flag=0; static char win_name[64]; static Visual *visual = NULL; static Status status; static unsigned long wp, bp; /* pixel values for black & white */ static int screen, nplanes, ncolors; static int Max_x, Max_y; static XEvent event; static XSetWindowAttributes attrib; static GC gc; static XGCValues gc_val; static XSizeHints sizehints; Window imagewin; /* window ID for image */ static XImage *image = NULL; static Colormap hlcmap; static char keybuf[64]; static int refcount=0; static int lastmx=0,lastmy=0; static unsigned char *buf; static int shm_ct; Display *display; int kmin,kmax; int shmflag = 1; Colormap cmap=0; #define BUF(a,b) buf[(viewy * (b)) + (a)] #undef SHM_WAIT static int get_bpp(void) { int count, i; XPixmapFormatValues *x; x=XListPixmapFormats(display,&count); for (i=0; ibytes_per_line * image->height, IPC_CREAT | 0777); if (shminfo.shmid < 0) { fprintf(stderr, "Unable to allocate shared memory segment of size %ld bytes.\n" "Please increase the max. size of a segment (now %ld).\n", (long)image->bytes_per_line * image->height,(long) SHMMAX); } shminfo.shmaddr = image->data = shmat (shminfo.shmid, 0, 0); if (indexed_color) { buf = (unsigned char *)shminfo.shmaddr; } else { #if 0 dprintf("Allocating separate buffer for conversion\n"); #endif buf = (unsigned char *)malloc(image->height * image->width); #if 0 dprintf("buf=%lx, shm=%lx\n", (long)buf,(long)shminfo.shmaddr); #endif } shminfo.readOnly = False; XShmAttach (display, &shminfo); XSync(display, False); shmctl(shminfo.shmid, IPC_RMID, 0); shm_used = 1; #if 0 bzero (&shminfo, sizeof(shminfo)); #endif } else #endif { unsigned char *bb; #if 0 dprintf("Creating a plain XImage\n"); #endif /* 8 because that's what the conversion routines return at the moment*/ buf = (unsigned char *)malloc (w * h / (format == XYBitmap ? 8 : 1)); /* we can write to the image directly in these cases: */ if (indexed_color || format == XYBitmap) bb=buf; else { /* need a buffer since display != 8bpp */ bb=(unsigned char *)malloc(w*h*BitmapUnit(display)/8); #if 0 dprintf("Allocating separate buffer for conversion (size=%ld)\n",(long)w*h*BitmapUnit(display)/8); dprintf("buf=%lx, shm=%lx\n",(long)buf,(long)bb); #endif } image = XCreateImage (display, DefaultVisual(display,screen), format == XYBitmap ? 1 : DisplayPlanes(display,screen), format, 0, (char *)bb, w, h, 16, 0); #if 0 dprintf("Image->data=%lx, bb=%lx, buf=%lx\n", (long)image->data,(long)bb,(long)buf); #endif if (image == NULL) { fprintf(stderr,"Error allocating an XImage\n"); XSync(display,False); exit(6); } #ifdef SH_MEM shm_used=0; #endif } if (planes == 1) { image -> bitmap_bit_order = MSBFirst; image -> byte_order = MSBFirst; } XSync(display,False); } static void allocate_color(UW stcolor) { if (!is_allocated[stcolor]) { XColor col; int c=stcolor; col.flags = DoRed | DoGreen | DoBlue; col.red = (((c>>8)&7)<<13)|((c>>11)<<12); col.green = (((c>>4)&7)<<13)|(((c>>7)&1)<<12); col.blue = ((c&7)<<13)|(((c>>3)&1)<<12); if (!XAllocColor(display,cmap,&col)) { fprintf(stderr, "Color allocation failed, exiting. This should" " never happen, please notify the author!\n"); exit(4); } pixel_value[c]=col.pixel; is_allocated[c]=1; #if 0 dprintf("Allocating %04x -> %08lx\n",stcolor,col.pixel); #endif } } /* Change the window colormap according to the contents of old_color[]. * The colors are converted from ST/STe format (least-significant 9/12 bits * of a 16 bit integer) to the 16 bit per RGB component format used in X11. */ static int allocatedcols[COLS]; char mapcol[COLS]; static void change_colors (void) { XColor colors[COLS]; UW c; int i; int q=0; unsigned long pixels[COLS]; int j,k; if (shiftmod == 2) { for (i=0; i>8)&7)<<13)|((c>>11)<<12); colors[i].green = (((c>>4)&7)<<13)|(((c>>7)&1)<<12); colors[i].blue = ((c&7)<<13)|(((c>>3)&1)<<12); } } else { /* saves one indirection in the conversion routines... */ for (i=0; i>8)&7)<<13)|((c>>11)<<12); col.green = (((c>>4)&7)<<13)|(((c>>7)&1)<<12); col.blue = ((c&7)<<13)|(((c>>3)&1)<<12); if (!XAllocColor(display,cmap,&col)) { fprintf(stderr, "Color allocation failed, exiting. This should" " never happen, please notify the author!\n"); exit(4); } #if 0 dprintf("Allocating %3x to pixel value %06lx\n", c,col.pixel); #endif pixel_value[c]=col.pixel; is_allocated[c]=1; } pixel_value_by_index[i]=pixel_value[old_color[i]]; } } } if (indexed_color) { if (!priv_cmap) { for (i=0; i=0) { pixels[q++]=allocatedcols[i]; } } if (q>0) XFreeColors(display, cmap, pixels, q, 0); for (i=0; i>shiftmod; #if 0 dprintf("Screen is now %dx%d, shift mode %d\n",scr_width,scr_height,shiftmod); #endif switch (shiftmod) { case 0: XResizeWindow (display, imagewin, scr_width, scr_height); destroy_image(); create_image (scr_width, scr_height, ZPixmap); change_colors(); break; case 1: XResizeWindow (display, imagewin, scr_width, scr_height*2); destroy_image(); create_image (scr_width, scr_height*2, ZPixmap); change_colors(); break; case 2: XResizeWindow (display, imagewin, scr_width, scr_height); destroy_image(); create_image (scr_width, scr_height, XYBitmap); change_colors(); break; } } /* Process all events that occured since we last came here... */ void x_process_events (void) { int tx,ty; XEvent e; XExposeEvent *x; while (XCheckMaskEvent (display, E_MASK, &e)) { switch (e.type) { case EnterNotify: #if 0 dprintf("Entering STonX window\n"); #endif XAutoRepeatOff(display); #if XLIB_VDI if (vdi && xw != None) vdi_mode = (e.xcrossing.window != imagewin); #endif in_which = e.xcrossing.window; if (in_which == imagewin) { #if SET_MOUSE if (abase != 0) { lastmx = LM_W(MEM(abase-GCURX)); lastmy = LM_W(MEM(abase-GCURY)); } if (lastmx >= 0 && lastmx < scr_width && lastmy >= 0 && lastmy < scr_height) { XWarpPointer (display, None, imagewin, 0, 0, 0, 0, lastmx, lastmy); XDefineCursor (display, imagewin, cursors[cursidx]); warped=1; } #else int mx,my,nx,ny; #if 0 mx=LM_W(MEM(abase-GCURX)); my=LM_W(MEM(abase-GCURY)); #endif nx=(((XCrossingEvent *)&e)->x); ny=(((XCrossingEvent *)&e)->y); #if 0 dprintf("Repositioning mouse from %d,%d to %d,%d\n", mx,my,nx,ny); ikbd_adjust(nx-lastmx,ny-lastmy); lastmx=mx; lastmy=my; #endif ikbd_pointer(nx,ny,Max_x,Max_y); #endif } break; case LeaveNotify: #if 0 dprintf("Leaving STonX window\n"); #endif XAutoRepeatOn(display); /* BUG: should restore previous value */ if (e.xcrossing.window == imagewin) XUndefineCursor(display,imagewin); in_which = None; break; case KeyPress: /* fprintf (stderr, "Keypress: %d\n", ((XKeyEvent *)&e)->keycode);*/ if (XLookupKeysym ((XKeyEvent *)&e,0) == XK_Pause) flags |= F_CONFIG; else ikbd_key (((XKeyEvent *)&e)->keycode, 1); break; case KeyRelease: if (XLookupKeysym ((XKeyEvent *)&e,0) != XK_Pause) ikbd_key (((XKeyEvent *)&e)->keycode, 0); break; case ButtonPress: if (((XButtonEvent *)&e)->button == 3 && (((XButtonEvent *)&e)->state & ControlMask)) exit(0); #if GRABMODE if (((XButtonEvent *)&e)->button == 3) { #if 0 dprintf( "in window %lx\n",(long)in_which); #endif if (grabbed) { XUngrabKeyboard (display, CurrentTime); XUngrabPointer (display, CurrentTime); grabbed=0; } else #if XLIB_VDI if (in_which != xw) #endif { XGrabPointer (display, imagewin, True, PointerMotionMask |ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, hidden, CurrentTime); XGrabKeyboard (display, imagewin,True, GrabModeAsync, GrabModeAsync, CurrentTime); grabbed=1; fprintf (stderr, "grabbed\n"); } } #elif HIDEMODE if (((XButtonEvent *)&e)->button == 3) { cursidx = !cursidx; XDefineCursor (display, imagewin, cursors[cursidx]); break; } #endif ikbd_button (((XButtonEvent *)&e)->button, 1); break; case ButtonRelease: #if 0 fprintf (stderr, "Buttonrelease: %d\n", ((XButtonEvent *)&e)->button); #endif ikbd_button (((XButtonEvent *)&e)->button, 0); break; case Expose: x = (XExposeEvent *)&e; #if XBUFFER #if XLIB_VDI if (xw == x->window) vdi_redraw(x->x,x->y,x->width,x->height); #endif #endif { int i; for (i=0; ix; lastmy = ((XMotionEvent *)&e)->y; break; #endif } #if 0 #if 0 if (e.xmotion.window == imagewin) #endif /* fprintf (stderr, "Pointer: %d,%d\n", ((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y); */ #if 0 SM_W(MEM(abase-GCURX),((XMotionEvent *)&e)->x); SM_W(MEM(abase-GCURY),((XMotionEvent *)&e)->y); SM_W(MEM(abase-0x158),((XMotionEvent *)&e)->x); SM_W(MEM(abase-0x156),((XMotionEvent *)&e)->y); SM_B(MEM(abase-0x154),0xff); #endif #if 0 #if 1 if (abase != 0) { tx=LM_W(MEM(abase-0x158)); ty=LM_W(MEM(abase-0x156)); } #if 1 if (tx==lastmx && ty==lastmy) break; #endif lastmx=tx; lastmy=ty; #endif dprintf("Adjusting: (%d,%d)->(%d,%d)\n",lastmx,lastmy, ((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y); ikbd_adjust (((XMotionEvent *)&e)->x-lastmx, ((XMotionEvent *)&e)->y-lastmy); #else ikbd_adjust (((XMotionEvent *)&e)->x-lastmx, ((XMotionEvent *)&e)->y-lastmy); lastmx = ((XMotionEvent *)&e)->x; lastmy = ((XMotionEvent *)&e)->y; #endif #else #if 0 ikbd_pointer (((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y,Max_x,Max_y); #else ikbd_adjust (((XMotionEvent *)&e)->x-lastmx, ((XMotionEvent *)&e)->y-lastmy); lastmx = ((XMotionEvent *)&e)->x; lastmy = ((XMotionEvent *)&e)->y; #endif #endif break; } } } void x_screen_open (void) { int i, j; int shm_major, shm_minor; Bool shm_pixmaps; XSizeHints h; XFontStruct *font_info; XImage *t; XColor ccols[2]; XSetWindowAttributes xa; scr_width = scr_def[shiftmod].w; scr_height = scr_def[shiftmod].h; strcpy (win_name, "STonX Main Window"); if ((display = XOpenDisplay (NULL)) == NULL) { fprintf (stderr,"Could not open display.\n"); exit (1); } #if 0 XAutoRepeatOff(display); #endif fprintf (stderr,"Obtaining Keysym mappings for display...\n"); XDisplayKeycodes (display, &kmin, &kmax); fprintf (stderr,"Keycode range = %d..%d\n", kmin, kmax); ksyms = (char **)malloc(sizeof(char *)*(kmax-kmin+1)); for (i=kmin; i<=kmax; i++) { char *s = XKeysymToString(XKeycodeToKeysym(display,i,0)); ksyms[i-kmin] = (s == NULL ? s : strdup(s)); #if 0 fprintf (stderr, "Keycode %d = %s\n", i,s); #endif } #ifdef SH_MEM if (shmflag) { if (!XShmQueryVersion (display, &shm_major, &shm_minor, &shm_pixmaps)) { fprintf(stderr, "MIT Shared Memory Extension not supported.\n"); shmflag = 0; } else { int foo; fprintf (stderr,"Using MIT Shared Memory Extension %d.%d," \ " %s shared pixmaps.\n", shm_major, shm_minor, (shm_pixmaps ? "with" : "without")); foo = XShmPixmapFormat (display); fprintf (stderr,"XShm Pixmap format: %s\n", ((foo == XYBitmap ? "XYBitmap" : (foo == XYPixmap ? "XYPixmap" : "ZPixmap")))); fprintf (stderr, "If you get a BadAccess error, try the -noshm option!\n"); } } #endif screen = XDefaultScreen (display); depth = DefaultDepth (display, screen); if (depth == 1) { SM_B(MEM(0xff8260),2); /* old_shiftmod = 2; */ } visual = DefaultVisual (display, screen); nplanes = XDisplayPlanes (display, screen); /* See if we are on a local little-endian display - in that case, XShmPutImage will refuse to swap bits most of the time! */ if (shmflag) { char *c=(char *)malloc(64); t = XCreateImage (display, visual, 1, XYBitmap, 0, c, 32, 16, 8, 0); if (t->bitmap_bit_order == LSBFirst) { #if 0 fprintf (stderr, "NOTE: Because XShmPutImage apparently can't swap bits, shared memory support\nwas turned off for monochrome mode!\n"); #endif shm_mono=0; } XDestroyImage (t); } h.width = scr_width; h.height = scr_height; h.x = 100; h.y = 0; h.flags = PSize | PPosition; bp = BlackPixel (display, screen); wp = WhitePixel (display, screen); #if 0 dprintf("Black=%ld, White=%ld\n",bp,wp); #endif if (XMatchVisualInfo(display,screen,8,PseudoColor, &vi)) { fprintf(stderr,"Using 8 bpp PseudoColor visual\n"); indexed_color = 1; bits_per_pixel = 8; } else { indexed_color = 0; bits_per_pixel = get_bpp(); priv_cmap = 1; /* temp kludge for screen XXX */ } fprintf(stderr, "Indexed=%d, bits per pixel=%d\n",indexed_color,bits_per_pixel); #if 0 dprintf("Trying to create a (%d,%d,%d,%d) window\n", h.x,h.y,h.width,h.height); #endif imagewin = XCreateWindow (display, RootWindow (display, screen), h.x, h.y, h.width, h.height, 0, DefaultDepth(display,screen), InputOutput, visual, 0, &xa); XSelectInput (display, imagewin, StructureNotifyMask|E_MASK); XSetStandardProperties (display, imagewin, win_name, win_name, None, NULL, 0, &h); XMapWindow (display, imagewin); for (;;) { XEvent e; XNextEvent (display, &e); if (e.type == MapNotify && e.xmap.event == imagewin) break; } gc_val.background = 0; gc_val.foreground = 1; gc = XCreateGC (display, imagewin, GCForeground | GCBackground, &gc_val); #ifdef SH_MEM shm_ct = XShmGetEventBase (display) + ShmCompletion; #endif if (indexed_color) { if (priv_cmap) cmap = XCreateColormap (display, RootWindow(display,screen), visual, AllocAll); else { cmap = DefaultColormap (display, screen); for (i=0; i>8)&7)<<13)|((i>>11)<<12); col.green = (((i>>4)&7)<<13)|(((i>>7)&1)<<12); col.blue = ((i&7)<<13)|(((i>>3)&1)<<12); if (!XAllocColor(display,cmap,&col)) { fprintf(stderr,"Color allocation failed, exiting.\n"); exit(4); } pixel_value[i]=col.pixel; } else pixel_value[i]=pixel_value[i&0x777]; if (++pr == pr0) { putc('.',stderr); pr=0; } } fprintf(stderr,"\n"); #else cmap = DefaultColormap (display, screen); #endif } XClearWindow (display, imagewin); #if 0 XWarpPointer (display, None, imagewin, 0, 0, 0, 0, 320, 200); #endif XSelectInput (display, imagewin, E_MASK); #if !MONITOR && GRAB XGrabPointer (display, imagewin, False, ButtonPressMask|ButtonReleaseMask |PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); #endif if (depth == 1) create_image (scr_width,scr_height,XYBitmap); empty = XCreatePixmapFromBitmapData (display, imagewin, (char*)calloc(32,1), 16, 16,0,0,1); ccols[0].pixel = 0; ccols[1].pixel = 0; cursors[0] = XCreatePixmapCursor (display, empty, empty, &ccols[0], &ccols[1], 0,0); cursors[1] = XCreateFontCursor (display, XC_tcross); #if GRABMODE XGrabPointer (display, imagewin, True, PointerMotionMask |ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, hidden, CurrentTime); XGrabKeyboard (display, imagewin,True, GrabModeAsync, GrabModeAsync, CurrentTime); fprintf (stderr, "The X pointer and keyboard have been grabbed by STonX - press the 3rd mouse\nbutton to release/grab again.\n"); #endif OnExit (x_screen_close); } /* * What about unaligned buffers here? */ static void stcolor_to_image (UW *b, unsigned char *p, int y0, int nlines) { int n,i,cv; b += image->width * y0 * 2; p += (image->width * y0 * bits_per_pixel)/8; /* XXX for <8 bpp... */ n = nlines * image->width; /* pixels to convert */ switch(bits_per_pixel) { case 32: for (i=0; i>16; *p++ = (cv>>8)&0xff; *p++ = cv&0xff; } break; case 16: /* UNTESTED */ for (i=0; iwidth * y0; p += (image->width * y0 * bits_per_pixel)/8; /* XXX for <8 bpp... */ n = nlines * image->width; /* pixels to convert */ switch(bits_per_pixel) { case 32: for (i=0; i>16; *p++ = (cv>>8)&0xff; *p++ = cv&0xff; } break; case 16: /* UNTESTED */ for (i=0; idata, yzoom*i*CHUNK_LINES, yzoom*CHUNK_LINES); XShmPutImage (display, imagewin, gc, image, 0, yzoom*i*CHUNK_LINES, 0, yzoom*i*CHUNK_LINES, w, yzoom*CHUNK_LINES, False); draw_chunk[i]=0; #if BENCH_REFRESH chunks_drawn++; #endif } #if BENCH_REFRESH chunks_seen+=h/CHUNK_LINES; #endif } else { buffer_to_image(buf,(unsigned char *)image->data,0,h*yzoom); XShmPutImage (display, imagewin, gc, image, 0, 0, 0, 0, w, h*yzoom, False); } #if 1 XSync (display,False); #endif #ifdef SHM_WAIT do { XNextEvent (display, &xev); } while (xev.type != shm_ct); #endif } else #endif { if (chunky) { int i; for (i=0; idata,0,h*yzoom); XPutImage (display, imagewin, gc, image, 0, yzoom*i*CHUNK_LINES, 0, yzoom*i*CHUNK_LINES, w, yzoom*CHUNK_LINES); draw_chunk[i]=0; #if BENCH_REFRESH chunks_drawn++; #endif } #if BENCH_REFRESH chunks_seen+=h/CHUNK_LINES; #endif } else { buffer_to_image(buf,(unsigned char *)image->data,0,h*yzoom); XPutImage (display, imagewin, gc, image, 0, 0, 0, 0, w, h*yzoom); } XFlush (display); } #if 1 XSync (display, False); #endif } static void manage_window (void) { XKeyEvent *keypress; KeySym keysym; XComposeStatus cstat; keypress = (XKeyEvent *) & event; if (XPending (display)) { XNextEvent (display, &event); switch ((int) event.type) { case KeyPress: if (XLookupString (keypress, keybuf, sizeof (keybuf), &keysym, &cstat) != 0) { /* update_IKBD_BUFFER (); */ } break; default: break; } } } /* This function is called periodically (from a signal handler) to check what's * new with the shifter mode, colors, and update ("shift") the screen. It * should probably rewritten to check whether it's necessary to update the * screen, since for color modes this is a very costly operation... * * The Shifter status information is changed in hw.c, where the hardware regs * are read. */ void x_screen_shifter (void) { int i, w, pal = 0; x_process_events(); if (++refcount < refresh) return; refcount=0; for (i=0; i<16; i++) { if ((w = LM_UW(&color[i])) != old_color[i]) { pal = 1; /* palette has changed */ old_color[i] = w & 0xfff; } } if (pal) change_colors(); /* update the window colormap */ /* if (depth > 1 && old_shiftmod != shiftmod)*/ if (old_shiftmod != shiftmod) { old_shiftmod = shiftmod; change_mode(); } #if XLIB_VDI if (!vdi_mode || xw == None) #endif { #if BENCH_REFRESH struct tms ta; clock_t rt; times(&ta); rt=ta.tms_utime+ta.tms_stime; show_screen(); times(&ta); reftime += ta.tms_utime+ta.tms_stime-rt; cref++; if (cref==NUM_AVG) { fprintf(stderr, "Refresh time (%d samples): %lf ms\n", NUM_AVG, 1000.0*(double)reftime/(NUM_AVG*CLK_TCK)); if (chunky) dprintf("Chunks drawn/seen = %d/%d\n",chunks_drawn,chunks_seen); reftime=0; cref=0; } #else show_screen(); #endif } #if 0 check_ui(); #endif } #define KB_DEBUG 0 #define KEYMAP_HARDCODED 0 struct { int c; char *s; } st_keysyms[] = { {ST_1, "ST_1"}, {ST_2, "ST_2"}, {ST_3, "ST_3"}, {ST_4, "ST_4"}, {ST_5, "ST_5"}, {ST_6, "ST_6"}, {ST_7, "ST_7"}, {ST_8, "ST_8"}, {ST_9, "ST_9"}, {ST_0, "ST_0"}, {ST_F1, "ST_F1"}, {ST_F2, "ST_F2"}, {ST_F3, "ST_F3"}, {ST_F4, "ST_F4"}, {ST_F5, "ST_F5"}, {ST_F6, "ST_F6"}, {ST_F7, "ST_F7"}, {ST_F8, "ST_F8"}, {ST_F9, "ST_F9"}, {ST_F10, "ST_F10"}, {ST_A, "ST_A"}, {ST_B, "ST_B"}, {ST_C, "ST_C"}, {ST_D, "ST_D"}, {ST_E, "ST_E"}, {ST_F, "ST_F"}, {ST_G, "ST_G"}, {ST_H, "ST_H"}, {ST_I, "ST_I"}, {ST_J, "ST_J"}, {ST_K, "ST_K"}, {ST_L, "ST_L"}, {ST_M, "ST_M"}, {ST_N, "ST_N"}, {ST_O, "ST_O"}, {ST_P, "ST_P"}, {ST_Q, "ST_Q"}, {ST_R, "ST_R"}, {ST_S, "ST_S"}, {ST_T, "ST_T"}, {ST_U, "ST_U"}, {ST_V, "ST_V"}, {ST_W, "ST_W"}, {ST_X, "ST_X"}, {ST_Y, "ST_Y"}, {ST_Z, "ST_Z"}, {ST_SPACE, "ST_SPACE"}, {ST_ALT, "ST_ALT"}, {ST_ESC, "ST_ESC"}, {ST_MINUS, "ST_MINUS"}, {ST_EQUAL, "ST_EQUAL"}, {ST_GRAVE, "ST_GRAVE"}, {ST_BS, "ST_BS"}, {ST_DELETE, "ST_DELETE"}, {ST_ISO, "ST_ISO"}, {ST_INSERT, "ST_INSERT"}, {ST_TAB, "ST_TAB"}, {ST_SQ_OPEN, "ST_SQ_OPEN"}, {ST_SQ_CLOSE, "ST_SQ_CLOSE"}, {ST_UP, "ST_UP"}, {ST_LEFT, "ST_LEFT"}, {ST_RIGHT, "ST_RIGHT"}, {ST_DOWN, "ST_DOWN"}, {ST_CONTROL, "ST_CONTROL"}, {ST_LSH, "ST_LSH"}, {ST_RSH, "ST_RSH"}, {ST_CAPSLOCK, "ST_CAPSLOCK"}, {ST_SEMIC, "ST_SEMIC"}, {ST_APOST, "ST_APOST"}, {ST_BACKSL, "ST_BACKSL"}, {ST_COMMA, "ST_COMMA"}, {ST_DOT, "ST_DOT"}, {ST_SLASH, "ST_SLASH"}, {ST_RETURN, "ST_RETURN"}, {ST_KP_ENTER, "ST_KP_ENTER"}, {ST_KP_MINUS, "ST_KP_MINUS"}, {ST_KP_PLUS, "ST_KP_PLUS"}, {ST_HELP, "ST_HELP"}, {ST_UNDO, "ST_UNDO"}, {ST_KP_OPEN, "ST_KP_OPEN"}, {ST_KP_CLOSE, "ST_KP_CLOSE"}, {ST_KP_DIV, "ST_KP_DIV"}, {ST_KP_MULT, "ST_KP_MULT"}, {ST_KP_DOT, "ST_KP_DOT"}, {ST_KP_0, "ST_KP_0"}, {ST_KP_1, "ST_KP_1"}, {ST_KP_2, "ST_KP_2"}, {ST_KP_3, "ST_KP_3"}, {ST_KP_4, "ST_KP_4"}, {ST_KP_5, "ST_KP_5"}, {ST_KP_6, "ST_KP_6"}, {ST_KP_7, "ST_KP_7"}, {ST_KP_8, "ST_KP_8"}, {ST_KP_9, "ST_KP_9"}, {ST_HOME, "ST_HOME"}, }; #define NUM_STK (sizeof(st_keysyms)/sizeof(st_keysyms[0])) static char mapped[NUM_STK]; extern char **ksyms; /* This is the keycode translation table. It is dependent on your kind of X * terminal, and on the mapping you want to use for the ST keys. * To make your own table, you'll need to examine the `xmodmap -pke' output * on your system, and write the corresponding ST keycode as the item with * the index of the keycode you want it on in the array below. * * Maybe, sometime in the future, a translation table based on Keysyms would * be a better idea... */ #if 0 int keycodes[] = { #if KEYMAP_HARDCODED ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_F1, ST_F2, ST_F10, ST_F3, ST_UNDEF, ST_F4, ST_UNDEF, ST_F5, ST_UNDEF, ST_F6, ST_UNDEF, ST_F7, ST_F8, ST_F9, ST_ALT, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDO, ST_UNDEF, ST_UNDEF, ST_ESC, ST_1, ST_2, ST_3, ST_4, ST_5, ST_6, ST_7, ST_8, ST_9, ST_0, ST_MINUS, ST_EQUAL, ST_GRAVE, ST_BS, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_DELETE, ST_UNDEF, ST_UNDEF, ST_TAB, ST_Q, ST_W, ST_E, ST_R, ST_T, ST_Y, ST_U, ST_I, ST_O, ST_P, ST_SQ_OPEN, ST_SQ_CLOSE, ST_DELETE, ST_UNDEF, ST_UNDEF, ST_UP, ST_UNDEF, ST_KP_MINUS, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_CONTROL, ST_A, ST_S, ST_D, ST_F, ST_G, ST_H, ST_J, ST_K, ST_L, ST_SEMIC, ST_APOST, ST_BACKSL, ST_RETURN, ST_KP_ENTER, ST_LEFT, ST_UNDEF, ST_RIGHT, ST_INSERT, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_LSH, ST_Z, ST_X, ST_C, ST_V, ST_B, ST_N, ST_M, ST_COMMA, ST_DOT, ST_SLASH, ST_RSH, ST_UNDEF, ST_UNDEF, ST_DOWN, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_HELP, ST_CAPSLOCK, ST_UNDEF, ST_SPACE, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_KP_PLUS #else #include "keytab.c" #endif }; #endif char *kdefsfile = "Keysyms"; void x_init_keys(void) { int i, l=0, j; FILE *f; char b[1000], x[1000], y[1000]; keycodes = (int *)malloc(sizeof(int)*(kmax+1)); for (i=0; i<=kmax; i++) keycodes[i] = ST_UNDEF; fprintf (stderr,"Reading keycode mappings from `%s'...\n", kdefsfile); f = fopen(kdefsfile, "r"); if (f == NULL) { fprintf(stderr,"FATAL error: File `%s' not found - exiting...\n", kdefsfile); exit(1); } while (fgets(b, 1000, f) != NULL) { l++; if (b[0] == '#') continue; if (sscanf(b, "%s %s", x, y) < 2) { fprintf (stderr,"Malformed line %d in file %s, ignoring it\n", l, kdefsfile); } else { int q; int ok=0, u; for (j=kmin; j<=kmax; j++) { #if KB_DEBUG if (*x == 'F') { dprintf ("x=<%s>, ksyms[%d]=<%s>, cmp=%d\n", x,j-kmin,ksyms[j-kmin],(ksyms[j-kmin]==NULL?999:strcasecmp(x,ksyms[j-kmin]))); } #endif if (ksyms[j-kmin] != NULL && strcasecmp (x, ksyms[j-kmin]) == 0) { q = /*XKeysymToKeycode(display, XStringToKeysym(ksyms[*/ j /* -kmin ]))*/; for (u=0; u