File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / lib / X / XKeyBind.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include "copyright.h"

/* $Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/lib/X/XKeyBind.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $ */
/* Copyright 1985, 1987, Massachusetts Institute of Technology */

/* Beware, here be monsters (still under construction... - JG */

#define NEED_EVENTS
#include "Xlib.h"
#include "Xlibint.h"
#include "Xutil.h"
#include "keysym.h"
#include <stdio.h>

#define HAS_CTRL(c)  ((c) >= '@' && (c) <= '\177')

struct XKeytrans {
	struct XKeytrans *next;/* next on list */
	char *string;		/* string to return when the time comes */
	int len;		/* length of string (since NULL is legit)*/
	KeySym key;		/* keysym rebound */
	unsigned int state;	/* modifier state */
	KeySym *modifiers;	/* modifier keysyms you want */
	int mlen;		/* length of modifier list */
};

static struct XKeytrans *trans = NULL;

static KeySym KeyCodetoKeySym(dpy, keycode, col)
     register Display *dpy;
     int keycode;
     int col;
{
     int ind;
     /*
      * if keycode not defined in set, this should really be impossible.
      * in any case, if sanity check fails, return NoSymbol.
      */
     if (col < 0 || col > dpy->keysyms_per_keycode) return (NoSymbol);
     if (keycode < dpy->min_keycode || keycode > dpy->max_keycode) 
       return(NoSymbol);

     ind = (keycode - dpy->min_keycode) * dpy->keysyms_per_keycode + col;
     return (dpy->keysyms[ind]);
}

KeySym XKeycodeToKeysym(dpy, kc, col)
    Display *dpy;
    KeyCode kc;
    int col;
{
     if (dpy->keysyms == NULL)
         Initialize(dpy);
     return (KeyCodetoKeySym(dpy, kc, col));
}

KeyCode XKeysymToKeycode(dpy, ks)
    Display *dpy;
    KeySym ks;
{
    int         i;

     if (dpy->keysyms == NULL)
         Initialize(dpy);
    for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
	int         j;

	for (j = 0; j < dpy->keysyms_per_keycode; j++) {
	    int ind = (i - dpy->min_keycode) * dpy->keysyms_per_keycode + j;

	    if (ks == dpy->keysyms[ind])
		return (i);
	}
    }
    return (0);
}

KeySym XLookupKeysym(event, col)
     register XKeyEvent *event;
     int col;
{
     if (event->display->keysyms == NULL)
         Initialize(event->display);
     return (XKeycodeToKeysym(event->display, event->keycode, col));
}

XRefreshKeyboardMapping(event)
     register XMappingEvent *event;
{
     LockDisplay(event->display);
     /* XXX should really only refresh what is necessary, for now, make
	initialize test fail */
     if(event->request == MappingKeyboard) 
	    if (event->display->keysyms != NULL) {
	         Xfree ((char *)event->display->keysyms);
	         event->display->keysyms = NULL;
	    }
     if(event->request == MappingModifier) {
	    XFreeModifiermap(event->display->modifiermap);
	    event->display->keysyms = NULL;/* XXX - looks like astorage leak */
     }
     UnlockDisplay(event->display);
}
static InitTranslationList()
{
	/* not yet implemented */
	/* should read keymap file and initialize list */
}

/*ARGSUSED*/
int XUseKeymap(filename) 
    char *filename;
{
  /* not yet implemented */
}

/* XXX not sure locking is race free here */
static Initialize(dpy)
Display *dpy;
{
    register KeySym *bd;
    int nbd;

    if (trans == NULL) InitTranslationList();
    /* 
     * lets go get the keysyms from the server.
     */
    if (dpy->keysyms == NULL) {
	dpy->keysyms = XGetKeyboardMapping (dpy, dpy->min_keycode,
	dpy->max_keycode - dpy->min_keycode + 1, &dpy->keysyms_per_keycode);
	LockDisplay(dpy);
	nbd = (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
	for (bd = dpy->keysyms; bd < (dpy->keysyms + nbd); bd += 2) {
	if ((*(bd + 1) == NoSymbol) && (*bd >= XK_A) && (*bd <= XK_Z)) {
	    *(bd + 1) = *bd;
	    *bd += 0x20;
	    }
	}
	UnlockDisplay(dpy);
    }
    if (dpy->modifiermap == NULL) {
	dpy->modifiermap = XGetModifierMapping(dpy);
    }
}

static int KeySymRebound(event, buf, symbol)
    XKeyEvent *event;
    char *buf;
    KeySym symbol;
{
    register struct XKeytrans *p;

    p = trans;
    while (p != NULL) {
	if (MatchEvent(event, symbol, p)) {
		bcopy (p->string, buf, p->len);
		return p->len;
		}
	p = p->next;
	}
    return -1;
}
  
Bool MatchEvent(event, symbol, p)
    XKeyEvent *event;
    KeySym symbol;
    register struct XKeytrans *p;
{
    if ((event->state == p->state) && (symbol == p->key)) return True;
    return False;
}

int XLookupString (event, buffer, nbytes, keysym, status)
     XKeyEvent *event;
     char *buffer;	/* buffer */
     int nbytes;	/* space in buffer for characters */
     KeySym *keysym;
     XComposeStatus *status;
{
     register KeySym symbol, lsymbol, usymbol;
     int length = 0;
     char buf[BUFSIZ];
     unsigned char byte3, byte4;

     if (event->display->keysyms == NULL)
         Initialize(event->display);

     lsymbol =  XKeycodeToKeysym(event->display, event->keycode, 0);
     usymbol =  XKeycodeToKeysym(event->display, event->keycode, 1);
     /*
      * we have to find out what kind of lock we are dealing with, if any.
      * if caps lock, only shift caps.
      */
     symbol = lsymbol;
     if (event->state & LockMask) {
	XModifierKeymap *m = event->display->modifiermap;
	int i;

	if (usymbol != NoSymbol)
	    symbol = usymbol;
	for (i = m->max_keypermod; i < 2*m->max_keypermod; i++) {
	    /*
	     *	Run through all the keys setting LOCK and,  if
	     *  ANY of them are CAPS_LOCK,  do Caps Lock.
	     *  This is kind of bogus,  but what else to do?
	     *  Supposing we have CAPS_LOCK,  but on the shifted
	     *  part of the key?
	     */
	    if (XKeycodeToKeysym(event->display, m->modifiermap[i], 0)
		    == XK_Caps_Lock) {
			if (usymbol >= XK_A && usymbol <= XK_Z)
			    symbol = usymbol;
			else
			    symbol = lsymbol;
			break;
		    }
	}
     }
     if ((event->state & ShiftMask) && usymbol != NoSymbol)
	     symbol = usymbol;

     if (keysym != NULL) *keysym = symbol;

     byte4 = symbol & 0xFF;
     byte3 = (symbol >> 8 ) & 0xFF;

     /*
      * see if symbol rebound, if so, return that string.
      * if any of high order 16 bits set, can only do ascii.
      * (reserved for future use, and for vendors).
      */
     if ((length = KeySymRebound(event, buf, symbol)) == -1) {
	    if ( IsModifierKey(symbol)   || IsCursorKey(symbol)
		|| IsPFKey (symbol)      || IsFunctionKey(symbol)
		|| IsMiscFunctionKey(symbol)
		|| (symbol == XK_Multi_key) || (symbol == XK_Kanji))  return 0;
            buf[0] = byte4;
	    /* if X keysym, convert to ascii by grabbing low 7 bits */
	    if (byte3 == 0xFF) buf[0] &= 0x7F;
	    /* only apply Control key if it makes sense, else ignore it */
	    if ((event->state & ControlMask) && HAS_CTRL(buf[0]))
	        buf[0] = buf[0] & 0x1F;
     	    length = 1;
      }
      if (length > nbytes) length = nbytes;
      bcopy (buf, buffer, length);
      return (length);
}

XRebindKeysym (dpy, keysym, mlist, nm, str, nbytes)
    Display *dpy;
    KeySym keysym;
    KeySym *mlist;
    int nm;		/* number of modifiers in mlist */
    unsigned char *str;
    int nbytes;
{
    register struct XKeytrans *tmp, *p;
    int nb;

    if (dpy->keysyms == NULL)
    	Initialize(dpy);
    LockDisplay(dpy);
    tmp = trans;
    trans = p = (struct XKeytrans *)Xmalloc(sizeof(struct XKeytrans));
    p->next = tmp;	/* chain onto list */
    p->string = (char *) Xmalloc(nbytes);
    bcopy (str, p->string, nbytes);
    p->len = nbytes;
    nb = sizeof (KeySym) * nm;
    p->modifiers = (KeySym *) Xmalloc(nb);
    bcopy (mlist, p->modifiers, nb);
    p->key = keysym;
    p->mlen = nm;
    ComputeMaskFromKeytrans(dpy, p);
    UnlockDisplay(dpy);
    return;
}

/*
 * given a KeySym, returns the first keycode found after the index value
 * in the table.  (Hopefully, can be found quickly).
 */
static CARD8 FindKeyCode(dpy, ind, code)
    register Display *dpy;
    int ind;
    register int code;
{

    register KeySym *kmax = dpy->keysyms + 
	(dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
    register KeySym *k = dpy->keysyms;	/* XXX not yet dealing with ind */
    if ((ind < dpy->min_keycode) || (ind > dpy->max_keycode)) return 0;
    while (k < kmax) {
	if (*k == code)
	    return(((k - dpy->keysyms)
		/ dpy->keysyms_per_keycode) + dpy->min_keycode);
	k += 1;
	}
    return 0;
}

	
/*
 * given a list of modifiers, computes the mask necessary for later matching.
 * This routine must lookup the key in the Keymap and then search to see
 * what modifier it is bound to, if any.
 */
static ComputeMaskFromKeytrans(dpy, p)
    Display *dpy;
    register struct XKeytrans *p;
{
    register int i;
    register CARD8 code;
    register XModifierKeymap *m = dpy->modifiermap;

    p->state = 0;
    for (i = 0; i < p->mlen; i++) {
	/* if not found, then not on current keyboard */
	if ((code = FindKeyCode(dpy, dpy->min_keycode, p->modifiers[i])) == 0)
		continue;
	/* code is now the keycode for the modifier you want */
	{
	    register int j;

	    for (j = 0; j < (m->max_keypermod<<3); j++) {
		if (m->modifiermap[j] && code == m->modifiermap[j])
		    p->state |= (1<<(j/m->max_keypermod));
	    }
	}
    }
    return;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.