Subject: extra national support for X

From: Nickolay Saukh <[email-masked]>
Date: Thu, 24 Mar 1994 13:10:52 -0500

This set of patches introduce table of translations
from X keycodes to runes. It is handy if you already
solved national problem for X ;-). All changes protected
by #ifdef KEYMAP ... #endif. The table looks like

	X_keycode	Unicode

Codes converted by strtol, so octal, decimal, hexadecimal
numbers are allowed.

diff --new-file --unified --recursive sam-4.1.orig/libXg/Gwin.h plan9/libXg/Gwin.h
--- sam-4.1.orig/libXg/Gwin.h	Thu Mar 24 20:47:32 1994
+++ plan9/libXg/Gwin.h	Thu Mar 24 20:42:55 1994
@@ -16,6 +16,10 @@
 #define XtCP9font   "P9font"
 #define XtNcomposeMod   "composeMod"
 #define XtCComposeMod   "ComposeMod"
+#if defined(KEYMAP)
+#define XtNp9keymap   "p9keymap"
+#define XtCP9keymap   "P9keymap"
+#endif
 
 /* External reference to the class record pointer */
 extern WidgetClass gwinWidgetClass;
diff --new-file --unified --recursive sam-4.1.orig/libXg/GwinP.h plan9/libXg/GwinP.h
--- sam-4.1.orig/libXg/GwinP.h	Thu Mar 24 20:47:33 1994
+++ plan9/libXg/GwinP.h	Thu Mar 24 20:42:55 1994
@@ -17,6 +17,9 @@
 	Mousefunc	gotmouse;	/* Notify app of mouse change */
 	String		selection;	/* Current selection */
 	String		p9font;
+#if defined(KEYMAP)
+	String		p9keymap;
+#endif
 	int		compose;
 } GwinPart;
 
diff --new-file --unified --recursive sam-4.1.orig/libXg/gwin.c plan9/libXg/gwin.c
--- sam-4.1.orig/libXg/gwin.c	Thu Mar 24 20:47:38 1994
+++ plan9/libXg/gwin.c	Thu Mar 24 20:42:56 1994
@@ -48,6 +48,10 @@
 		Offset(selection), XtRString, (XtPointer) NULL},
 	{XtNp9font, XtCP9font, XtRString, sizeof(String),
 		Offset(p9font), XtRString, (XtPointer) NULL},
+#if defined(KEYMAP)
+	{XtNp9keymap, XtCP9keymap, XtRString, sizeof(String),
+		Offset(p9keymap), XtRString, (XtPointer) NULL},
+#endif
 	{XtNcomposeMod, XtCComposeMod, XtRInt, sizeof(int),
 		Offset(compose), XtRImmediate, (XtPointer) 0}
 };
@@ -213,7 +217,11 @@
 	}
 	if(k == NoSymbol)
 		return;
-	if(k&0xFF00){
+#if defined(KEYMAP)
+	if((k & 0xFF00) == 0xFF00){
+#else
+	if((k & 0xFF00)){
+#endif
 		switch(k){
 		case XK_BackSpace:
 		case XK_Tab:
@@ -254,7 +262,7 @@
 			k = 0x81; /* PREVIEW -- "Scroll back" */
 			break;
 		default:
-			return;	/* not ISO-1 or tty control */
+			return;	/* not tty control */
 		}
 	}
 	/* Compensate for servers that call a minus a hyphen */
@@ -268,6 +276,22 @@
 			&& composing == -2)
 		composing = -1;
 	if (composing > -2) {
+#if defined(KEYMAP)
+		if((c = keyxlate(k)) == -1) {
+			if((k & 0xFF00))
+				return;
+		} else if((c & 0xff00)) {
+			k = (unsigned short)c;
+			composing++;
+			STUFFCOMPOSE();
+			composing = -2;
+			f = ((GwinWidget)w)->gwin.gotchar;
+			if(f)
+				(*f)(k);
+
+		} else
+			k = (unsigned short)c;
+#endif
 		compose[++composing] = k;
 		if ((*compose == 'X') && (composing > 0)) {
 			if ((k < '0') || (k > 'f') ||
@@ -296,8 +320,18 @@
 			composing++;
 			STUFFCOMPOSE();
 		}
-		c = (unsigned short)k;
 		composing = -2;
+#if defined(KEYMAP)
+		c = keyxlate(k);
+		if(c == -1) {
+			if((k & 0xFF00))
+				return;
+			else
+				c = (unsigned short)k;
+		}
+#else
+		c = (unsigned short)k;
+#endif
 	}
 
 	if (composing >= -1)
diff --new-file --unified --recursive sam-4.1.orig/libXg/libgint.h plan9/libXg/libgint.h
--- sam-4.1.orig/libXg/libgint.h	Thu Mar 24 20:47:39 1994
+++ plan9/libXg/libgint.h	Thu Mar 24 20:42:56 1994
@@ -90,3 +90,23 @@
 	UseCopyPlane,
 	UseFillRectangle
 };
+
+#if defined(KEYMAP)
+
+typedef struct Keymap Keymap;
+typedef struct KeyXtab KeyXtab;
+
+struct Keymap {
+	int nkeys;
+	KeyXtab* keyxtab;
+};
+
+struct KeyXtab {
+	unsigned long xkey;
+	Rune ukey;
+};
+
+Keymap* rdkeymapfile(char* name);
+
+extern Keymap	*_keymap;
+#endif
diff --new-file --unified --recursive sam-4.1.orig/libXg/rdkeymapfile.c plan9/libXg/rdkeymapfile.c
--- sam-4.1.orig/libXg/rdkeymapfile.c	Thu Jan  1 03:00:00 1970
+++ plan9/libXg/rdkeymapfile.c	Thu Mar 24 20:42:56 1994
@@ -0,0 +1,109 @@
+#if defined(KEYMAP)
+#include <libc.h>
+#include <libg.h>
+#include "libgint.h"
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+static char*
+skip(char *s)
+{
+	while (*s==' ' || *s=='\n' || *s=='\t')
+		s++;
+	return s;
+}
+
+static int
+keyxcmp(const void* n1, const void* n2)
+{
+	return (int)(((const KeyXtab *)n1)->xkey -
+	((const KeyXtab *)n2)->xkey);
+}
+
+Keymap *
+rdkeymapfile(char *name)
+{
+	Keymap *keymap;
+	KeyXtab* c;
+	int fd, i;
+	char *buf, *s;
+	struct stat sbuf;
+	unsigned long xcode, ucode;
+
+	fd = open(name, O_RDONLY);
+	if (fd < 0)
+		return 0;
+	if (fstat(fd, &sbuf) < 0)
+	{
+    Err0:
+		close(fd);
+		return 0;
+	}
+	buf = (char *)malloc(sbuf.st_size+1);
+	if (buf == 0)
+		goto Err0;
+	buf[sbuf.st_size] = 0;
+	i = read(fd, buf, sbuf.st_size);
+	close(fd);
+	if (i != sbuf.st_size)
+	{
+    Err1:
+		free(buf);
+		return 0;
+	}
+
+	s = buf;
+	keymap = (Keymap *)malloc(sizeof(Keymap));
+	if (keymap == 0)
+		goto Err1;
+	memset((void*)keymap, 0, sizeof(Keymap));
+
+	do {
+		xcode = strtol(s, &s, 0);
+		s = skip(s);
+		ucode = strtol(s, &s, 0);
+		while(*s && *s++ != '\n')
+			;
+		if(ucode>=65536) {
+    Err3:
+			if(keymap->keyxtab)
+				free(keymap->keyxtab);
+			free(keymap);
+			return 0;
+		}
+		if (keymap->keyxtab)
+			keymap->keyxtab = (KeyXtab *)realloc(keymap->keyxtab, (nkeys+1)*sizeof(KeyXtab));
+		else
+			keymap->keyxtab = (KeyXtab *)malloc(sizeof(KeyXtab));
+		if (keymap->keyxtab == 0) {
+			/* realloc manual says keymap->keyxtab may have been destroyed */
+			keymap->nkeys = 0;
+			goto Err3;
+		}
+		c = &keymap->keyxtab[keymap->nkeys];
+		c->xkey = xcode;
+		c->ukey = ucode;
+		keymap->nkeys++;
+	} while(*s);
+	free(buf);
+	qsort(keymap->keyxtab, keymap->nkeys, sizeof(KeyXtab), keyxcmp);
+	return keymap;
+}
+
+int
+keyxlate(unsigned long key)
+{
+	KeyXtab *xup;
+	KeyXtab	datum;
+
+	if(_keymap == 0)
+		return (-1);
+	datum.xkey = key;
+	xup = (KeyXtab *) bsearch(&datum, _keymap->keyxtab,
+		_keymap->nkeys, sizeof(KeyXtab), keyxcmp);
+	if(xup == 0)
+		return (-1);
+	return xup->ukey;
+}
+#endif /* defined(KEYMAP) */
diff --new-file --unified --recursive sam-4.1.orig/libXg/xtbinit.c plan9/libXg/xtbinit.c
--- sam-4.1.orig/libXg/xtbinit.c	Thu Mar 24 20:47:45 1994
+++ plan9/libXg/xtbinit.c	Thu Mar 24 20:42:57 1994
@@ -43,6 +43,9 @@
 unsigned long	_ld2dmask[6] = { 0x1, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF };
 Colormap	_libg_cmap;
 int		_cmap_installed;
+#if defined(KEYMAP)
+Keymap		*_keymap;
+#endif
 
 /* xbinit implementation globals */
 #ifndef R3
@@ -112,6 +115,10 @@
 static XrmOptionDescRec optable[] = {
 	{"-p9fn",	"*p9font",	XrmoptionSepArg,        (caddr_t)NULL},
 	{"-p9font",	"*p9font",	XrmoptionSepArg,        (caddr_t)NULL},
+#if defined(KEYMAP)
+	{"-p9km",	"*p9keymap",	XrmoptionSepArg,        (caddr_t)NULL},
+	{"-p9keymap",	"*p9keymap",	XrmoptionSepArg,        (caddr_t)NULL},
+#endif
 };
 
 void
@@ -126,6 +133,9 @@
 	char *p;
 	XSetWindowAttributes attr;
 	int compose;
+#if defined(KEYMAP)
+	String keymapname;
+#endif
 
 	if(!class && argv[0]){
 		p = strrchr(argv[0], '/');
@@ -158,6 +168,9 @@
 	XtSetArg(args[n], XtNfont, &xf);		n++;
 	XtSetArg(args[n], XtNp9font, &fontname);	n++;
 	XtSetArg(args[n], XtNcomposeMod, &compose);	n++;
+#if defined(KEYMAP)
+	XtSetArg(args[n], XtNp9keymap, &keymapname);	n++;
+#endif
 	XtGetValues(widg, args, n);
 
 	if (compose < 0 || compose > 5) {
@@ -192,6 +205,12 @@
 		subfont = XFontStructtoSubfont(xf);
 		font = mkfont(subfont);
 	}
+#if defined(KEYMAP)
+	_keymap = 0;
+	if(keymapname) {
+		_keymap = rdkeymapfile(keymapname);
+	}
+#endif
 	/* leave screen rect at all zeros until reshaped() sets it */
 	while(!exposed) {
 		XFlush(_dpy);