示例#1
0
文件: gwin.c 项目: deadpixi/sam
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);
}
示例#2
0
文件: gwin.c 项目: chneukirchen/sam
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);
}