static void Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) { static unsigned char compose[5]; static int composing = -2; int kind = Kraw; int c, len, minmod; KeySym k, mk; Charfunc f; Modifiers md; char buf[100] = {0}; c = 0; len = 0; /* Translate the keycode into a key symbol. */ if(e->xany.type != KeyPress) return; XkbTranslateKeyCode(xkb, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); XkbTranslateKeySym(e->xany.display, &k, e->xkey.state, buf, sizeof(buf) - 1, &len); /* Check to see if it's a specially-handled key first. */ for (Keymapping *m = keymappings; m; m = m->next){ KeySym u = NoSymbol; KeySym l = NoSymbol; XConvertCase(k, &l, &u); /* Note that magic bit manipulation here - we want to check that the * modifiers that are specified for the binding are all pressed, but * we allow other modifiers to be as well. This is because when NumLock * is on, it's always added to the modifier mask. */ if (l == m->s || m->s == XK_VoidSymbol){ if (m->m == 0 || (m->m & ~e->xkey.state) == 0){ switch (m->c){ case Cnone: return; case Cdefault: continue; default: f = ((GwinWidget)w)->gwin.gotchar; if (f) (*f)(m->c, m->k, Tcurrent, 0, 0, m->a); return; } } } } /* * The following song and dance is so we can have our chosen * modifier key behave like a compose key, i.e, press and release * and then type the compose sequence, like Plan 9. We have * to find out which key is the compose key first though. */ if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose && composing == -2 && modmap) { minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod; for (c = minmod; c < minmod+keypermod; c++) { XtTranslateKeycode(e->xany.display, modmap->modifiermap[c], e->xkey.state, &md, &mk); if (k == mk) { composing = -1; break; } } return; } /* Handle Multi_key separately, since it isn't a modifier */ if(k == XK_Multi_key) { composing = -1; return; } if(k == NoSymbol || k > 0xff00) return; /* Check to see if we are in a composition sequence */ if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask) && composing == -2) composing = -1; if (composing > -2) { compose[++composing] = k; if ((*compose == 'X') && (composing > 0)) { if ((k < '0') || (k > 'f') || ((k > '9') && (k < 'a'))) { STUFFCOMPOSE(); c = (uint16_t)k; composing = -2; } else if (composing == 4) { c = unicode(compose); if (c == -1) { STUFFCOMPOSE(); c = (uint16_t)compose[4]; } composing = -2; } } else if (composing == 1) { c = (int)latin1(compose); if (c == -1) { STUFFCOMPOSE(); c = (uint16_t)compose[1]; } composing = -2; } } else { if (composing >= 0) { composing++; STUFFCOMPOSE(); } c = keysymtoshort(k); composing = -2; } if (composing >= -1) return; f = ((GwinWidget)w)->gwin.gotchar; if(f) (*f)(c, kind, Tcurrent, 0, 0, NULL); }
static void Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) { static unsigned char compose[5]; static int composing = -2; int composed = 0; int c, minmod; KeySym k, mk; Charfunc f; Modifiers md; /* * I tried using XtGetActionKeysym, but it didn't seem to * do case conversion properly * (at least, with Xterminal servers and R4 intrinsics) */ if(e->xany.type != KeyPress) return; XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); /* * The following song and dance is so we can have our chosen * modifier key behave like a compose key, i.e, press and release * and then type the compose sequence, like Plan 9. We have * to find out which key is the compose key first 'though. */ if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose && composing == -2 && modmap) { minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod; for (c = minmod; c < minmod+keypermod; c++) { XtTranslateKeycode(e->xany.display, modmap->modifiermap[c], e->xkey.state, &md, &mk); if (k == mk) { composing = -1; break; } } return; } /* Handle Multi_key separately, since it isn't a modifier */ if(k == XK_Multi_key) { composing = -1; return; } if(k == NoSymbol) return; if(k&0xFF00){ switch(k){ case XK_BackSpace: case XK_Tab: case XK_Escape: case XK_Delete: case XK_KP_0: case XK_KP_1: case XK_KP_2: case XK_KP_3: case XK_KP_4: case XK_KP_5: case XK_KP_6: case XK_KP_7: case XK_KP_8: case XK_KP_9: case XK_KP_Divide: case XK_KP_Multiply: case XK_KP_Subtract: case XK_KP_Add: case XK_KP_Decimal: k &= 0x7F; break; case XK_Linefeed: k = '\r'; break; case XK_KP_Enter: case XK_Return: k = '\n'; break; case XK_Left: case XK_Down: case XK_Right: case XK_Next: k = 0x80; /* VIEW -- "Scroll" */ break; case XK_Up: case XK_Prior: k = 0x81; /* PREVIEW -- "Scroll back" */ break; default: return; /* not ISO-1 or tty control */ } } /* Compensate for servers that call a minus a hyphen */ if(k == XK_hyphen) k = XK_minus; /* Do control mapping ourselves if translator doesn't */ if((e->xkey.state&ControlMask) && !(md&ControlMask)) k &= 0x9f; if(k == NoSymbol) return; /* Check to see if we are in a composition sequence */ if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask) && composing == -2) composing = -1; if (composing > -2) { compose[++composing] = k; if ((*compose == 'X') && (composing > 0)) { if ((k < '0') || (k > 'f') || ((k > '9') && (k < 'a'))) { STUFFCOMPOSE(); c = (unsigned short)k; composing = -2; } else if (composing == 4) { c = unicode(compose); if (c == -1) { STUFFCOMPOSE(); c = (unsigned short)compose[4]; } else composed = 1; composing = -2; } } else if (composing == 1) { c = (int)latin1(compose); if (c == -1) { STUFFCOMPOSE(); c = (unsigned short)compose[1]; } else composed = 1; composing = -2; } } else { if (composing >= 0) { composing++; STUFFCOMPOSE(); } c = (unsigned short)k; composing = -2; } if (composing >= -1) return; f = ((GwinWidget)w)->gwin.gotchar; if(f) (*f)(c, composed); }