Subject: Re: Codeset support for wscons - pass 2
To: None <tech-kern@netbsd.org>
From: None <jakym@volny.cz>
List: tech-kern
Date: 04/05/2002 21:16:36
--KsGdsel6WgEHnImy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

> The translation maps don't need to be per-screen. I'll send a modified
> version of your patch tomorrow (with iso02 added btw).

Here it is.

Regards,
	--Jachym _Freza_ Holecek

--KsGdsel6WgEHnImy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="wscons.diff"

diff -u -2 --unidirectional-new-file ../wscons.orig/Makefile ./Makefile
--- ../wscons.orig/Makefile	Fri Mar  8 16:35:27 2002
+++ ./Makefile	Wed Apr  3 22:36:23 2002
@@ -4,5 +4,5 @@
 
 # Only install includes which are used by userland
-INCS=	wsconsio.h wsdisplay_usl_io.h wsksymdef.h wsksymdef.h wsksymvar.h
+INCS=	wscodeset.h wsconsio.h wsdisplay_usl_io.h wsksymdef.h wsksymvar.h
 
 .include <bsd.kinc.mk>
diff -u -2 --unidirectional-new-file ../wscons.orig/files.wscons ./files.wscons
--- ../wscons.orig/files.wscons	Fri Mar  8 16:35:27 2002
+++ ./files.wscons	Wed Apr  3 22:36:23 2002
@@ -36,4 +36,5 @@
 file	dev/wscons/wsdisplay.c		wsdisplay		needs-flag
 file	dev/wscons/wsdisplay_compat_usl.c wsdisplay & wsdisplay_compat_usl
+file	dev/wscons/wscodeset.c		wsdisplay
 file	dev/wscons/wsemulconf.c		wsdisplay
 file	dev/wscons/wsemul_dumb.c	wsdisplay & !wsemul_no_dumb
diff -u -2 --unidirectional-new-file ../wscons.orig/wscodeset.c ./wscodeset.c
--- ../wscons.orig/wscodeset.c	Thu Jan  1 01:00:00 1970
+++ ./wscodeset.c	Fri Apr  5 20:53:10 2002
@@ -0,0 +1,333 @@
+/*	$NetBSD: $	*/
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Juergen Hannken-Illjes.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: $");
+
+#define DEBUG
+
+#include <sys/param.h>
+#include <sys/cdefs.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+#include <dev/wscons/wscodeset.h>
+
+struct translation_s {
+	keysym_t ksym;
+	u_int8_t value;
+};
+
+struct codeset_table_s {
+	int codeset;
+	struct translation_s *map;
+	int size;
+	int refs;
+};
+
+struct codeset_s {
+	int codeset;
+	u_int8_t first_char;
+	u_int8_t last_char;
+	keysym_t *ksym_tab;
+};
+
+struct codeset_tag_s {
+	int codeset;
+	struct codeset_table_s *table;
+	char result[8];
+};
+
+static keysym_t iso8859_1_tab[] = {
+/*a0*/	KS_nobreakspace, KS_exclamdown, KS_cent, KS_sterling,
+/*a4*/	KS_currency, KS_yen, KS_brokenbar, KS_section,
+/*a8*/	KS_diaeresis, KS_copyright, KS_ordfeminine, KS_guillemotleft,
+/*ac*/	KS_notsign, KS_hyphen, KS_registered, KS_macron,
+/*b0*/	KS_degree, KS_plusminus, KS_twosuperior, KS_threesuperior,
+/*b4*/	KS_acute, KS_mu, KS_paragraph, KS_periodcentered,
+/*b8*/	KS_cedilla, KS_onesuperior, KS_masculine, KS_guillemotright,
+/*bc*/	KS_onequarter, KS_onehalf, KS_threequarters, KS_questiondown,
+/*c0*/	KS_Agrave, KS_Aacute, KS_Acircumflex, KS_Atilde,
+/*c4*/	KS_Adiaeresis, KS_Aring, KS_AE, KS_Ccedilla,
+/*c8*/	KS_Egrave, KS_Eacute, KS_Ecircumflex, KS_Ediaeresis,
+/*cc*/	KS_Igrave, KS_Iacute, KS_Icircumflex, KS_Idiaeresis,
+/*d0*/	KS_ETH, KS_Ntilde, KS_Ograve, KS_Oacute,
+/*d4*/	KS_Ocircumflex, KS_Otilde, KS_Odiaeresis, KS_multiply,
+/*d8*/	KS_Ooblique, KS_Ugrave, KS_Uacute, KS_Ucircumflex,
+/*dc*/	KS_Udiaeresis, KS_Yacute, KS_THORN, KS_ssharp,
+/*e0*/	KS_agrave, KS_aacute, KS_acircumflex, KS_atilde,
+/*e4*/	KS_adiaeresis, KS_aring, KS_ae, KS_ccedilla,
+/*e8*/	KS_egrave, KS_eacute, KS_ecircumflex, KS_ediaeresis,
+/*ec*/	KS_igrave, KS_iacute, KS_icircumflex, KS_idiaeresis,
+/*f0*/	KS_eth, KS_ntilde, KS_ograve, KS_oacute,
+/*f4*/	KS_ocircumflex, KS_otilde, KS_odiaeresis, KS_division,
+/*f8*/	KS_oslash, KS_ugrave, KS_uacute, KS_ucircumflex,
+/*fc*/	KS_udiaeresis, KS_yacute, KS_thorn, KS_ydiaeresis
+};
+
+static keysym_t iso8859_2_tab[] = {
+/*a0*/	KS_nobreakspace, KS_Aogonek, KS_breve, KS_Lstroke, KS_currency,
+/*a5*/	KS_Lcaron, KS_Sacute, KS_section, KS_diaeresis, KS_Scaron, KS_Scedilla,
+/*ab*/	KS_Tcaron, KS_Zacute, KS_hyphen, KS_Zcaron, KS_Zabovedot, KS_degree,
+/*b1*/	KS_aogonek, KS_ogonek, KS_lstroke, KS_acute, KS_lcaron, KS_sacute,
+/*b8*/	KS_cedilla, KS_scaron, KS_scedilla, KS_tcaron, KS_zacute,
+/*bd*/	KS_doubleacute, KS_zcaron, KS_zabovedot, KS_Racute, KS_Aacute,
+/*c2*/	KS_Acircumflex, KS_Abreve, KS_Adiaeresis, KS_Lacute, KS_Cacute,
+/*c7*/	KS_Ccedilla, KS_Ccaron, KS_Eacute, KS_Eogonek, KS_Ediaeresis, KS_Ecaron,
+/*cd*/	KS_Iacute, KS_Icircumflex, KS_Dcaron, KS_Dstroke, KS_Nacute, KS_Ncaron,
+/*d3*/	KS_Oacute, KS_Ocircumflex, KS_Odoubleacute, KS_Odiaeresis, KS_multiply,
+/*d8*/	KS_Rcaron, KS_Uabovering, KS_Uacute, KS_Udoubleacute, KS_Udiaeresis,
+/*dd*/	KS_Yacute, KS_Tcedilla, KS_ssharp, KS_racute, KS_aacute, KS_acircumflex,
+/*e3*/	KS_abreve, KS_adiaeresis, KS_lacute, KS_cacute, KS_ccedilla, KS_ccaron,
+/*e9*/	KS_eacute, KS_eogonek, KS_ediaeresis, KS_ecaron, KS_iacute,
+/*ee*/	KS_icircumflex, KS_dcaron, KS_dstroke, KS_nacute, KS_ncaron, KS_oacute,
+/*f4*/	KS_ocircumflex, KS_odoubleacute, KS_odiaeresis, KS_division, KS_rcaron,
+/*f9*/	KS_uabovering, KS_uacute, KS_udoubleacute, KS_udiaeresis, KS_yacute,
+/*fe*/	KS_tcedilla, KS_abovedot
+};
+
+static keysym_t koi8_u_tab[] = {
+/*a0*/	KS_voidSymbol, KS_voidSymbol, KS_voidSymbol, KS_Cyrillic_io,
+/*a4*/	KS_Cyrillic_ieukr, KS_voidSymbol, KS_Cyrillic_iukr, KS_Cyrillic_yi,
+/*a8*/	KS_voidSymbol, KS_voidSymbol, KS_voidSymbol, KS_voidSymbol,
+/*ac*/	KS_voidSymbol, KS_Cyrillic_gheukr, KS_voidSymbol, KS_voidSymbol,
+/*b0*/	KS_voidSymbol, KS_voidSymbol, KS_voidSymbol, KS_Cyrillic_IO,
+/*b4*/	KS_Cyrillic_IEUKR, KS_voidSymbol, KS_Cyrillic_IUKR, KS_Cyrillic_YI,
+/*b8*/	KS_voidSymbol, KS_voidSymbol, KS_voidSymbol, KS_voidSymbol,
+/*bc*/	KS_voidSymbol, KS_Cyrillic_GHEUKR, KS_voidSymbol, KS_voidSymbol,
+/*c0*/	KS_Cyrillic_yu, KS_Cyrillic_a, KS_Cyrillic_be, KS_Cyrillic_tse,
+/*c4*/	KS_Cyrillic_de, KS_Cyrillic_ie, KS_Cyrillic_ef, KS_Cyrillic_ghe,
+/*c8*/	KS_Cyrillic_ha, KS_Cyrillic_i, KS_Cyrillic_shorti, KS_Cyrillic_ka,
+/*cc*/	KS_Cyrillic_el, KS_Cyrillic_em, KS_Cyrillic_en, KS_Cyrillic_o,
+/*d0*/	KS_Cyrillic_pe, KS_Cyrillic_ya, KS_Cyrillic_er, KS_Cyrillic_es,
+/*d4*/	KS_Cyrillic_te, KS_Cyrillic_u, KS_Cyrillic_zhe, KS_Cyrillic_ve,
+/*d8*/	KS_Cyrillic_softsign, KS_Cyrillic_yeru, KS_Cyrillic_ze, KS_Cyrillic_sha,
+/*dc*/	KS_Cyrillic_e, KS_Cyrillic_shcha, KS_Cyrillic_che, KS_Cyrillic_hardsign,
+/*e0*/	KS_Cyrillic_YU, KS_Cyrillic_A, KS_Cyrillic_BE, KS_Cyrillic_TSE,
+/*e4*/	KS_Cyrillic_DE, KS_Cyrillic_IE, KS_Cyrillic_EF, KS_Cyrillic_GHE,
+/*e8*/	KS_Cyrillic_HA, KS_Cyrillic_I, KS_Cyrillic_SHORTI, KS_Cyrillic_KA,
+/*ec*/	KS_Cyrillic_EL, KS_Cyrillic_EM, KS_Cyrillic_EN, KS_Cyrillic_O,
+/*f0*/	KS_Cyrillic_PE, KS_Cyrillic_YA, KS_Cyrillic_ER, KS_Cyrillic_ES,
+/*f4*/	KS_Cyrillic_TE, KS_Cyrillic_U, KS_Cyrillic_ZHE, KS_Cyrillic_VE,
+/*f8*/	KS_Cyrillic_SOFTSIGN, KS_Cyrillic_YERU, KS_Cyrillic_ZE, KS_Cyrillic_SHA,
+/*fc*/	KS_Cyrillic_E, KS_Cyrillic_SHCHA, KS_Cyrillic_CHE, KS_Cyrillic_HARDSIGN
+};
+
+/* XXX: lock translation tables? */
+static struct codeset_table_s tables[] = {
+	{ CODESET_ISO8859_1,  NULL, 0, 0 },
+	{ CODESET_ISO8859_2,  NULL, 0, 0 },
+	{ CODESET_KOI8_U,     NULL, 0, 0 },
+};
+
+static struct codeset_s codesets[] = {
+	{ CODESET_ISO8859_1,  0xa0, 0xff, iso8859_1_tab },
+	{ CODESET_ISO8859_2,  0xa0, 0xff, iso8859_2_tab },
+	{ CODESET_KOI8_U,     0xa0, 0xff, koi8_u_tab },
+};
+
+/* Default codeset. No malloc because it may be the console. */
+#ifdef WSCODESET_DEFAULT
+#define CODESET_DEFAULT WSCODESET_DEFAULT
+#else
+#define CODESET_DEFAULT CODESET_ISO8859_1
+#endif
+
+static struct translation_s 	map_default[256];
+static struct codeset_table_s 	table_default = {
+	CODESET_DEFAULT,
+	map_default,
+	0,
+	0
+};
+static struct codeset_tag_s 	codeset_tag_default = {
+	CODESET_DEFAULT,
+	&table_default,
+	{ 0,0,0,0,0,0,0,0 }
+};
+
+/*
+ * Create a codeset translator. Return a cookie for this translator.
+ */
+void *
+wscodeset_create(int codeset)
+{
+	int i, j;
+	struct codeset_s *cs;
+	struct codeset_tag_s *cs_tag;
+	struct codeset_table_s *table;
+	struct translation_s v;
+
+	/* lookup codeset */
+	if (codeset == 0) {
+		codeset = CODESET_DEFAULT;
+		cs_tag = &codeset_tag_default;
+		table = cs_tag->table;
+	} else {
+		table = NULL;
+
+		for (i = 0; i < sizeof(tables)/sizeof(tables[0]); i++)
+			if (tables[i].codeset == codeset) {
+				table = tables + i;
+				break;
+			}
+
+		if (table == NULL)
+			return(NULL);
+
+		cs_tag = malloc(sizeof(*cs_tag), M_DEVBUF, M_WAITOK);
+		cs_tag->codeset = cs->codeset;
+		cs_tag->table = table;
+	}
+
+#ifdef DEBUG
+	printf("Creating tag for codeset %d\n", cs_tag->codeset);
+#endif
+
+	/* XXX: lock? */
+	if (table->refs == 0) {
+		if (cs_tag != &codeset_tag_default)
+			table->map = malloc(256*sizeof(struct translation_s),
+				M_DEVBUF, M_WAITOK);
+	} else {
+		table->refs++;
+		return(cs_tag);
+	}
+
+	cs = NULL;
+	table->size = 0;
+
+	for (i = 0; i < sizeof(codesets)/sizeof(codesets[0]); i++)
+		if (codesets[i].codeset == codeset) {
+			cs = codesets + i;
+			break;
+		}
+
+#ifdef DEBUG
+	printf("Building translation table for %d\n", cs->codeset);
+#endif
+
+	/* Enter 7-bit ascii */
+	for (i = 0; i < 0x80; i++) {
+		table->map[table->size].ksym = i;
+		table->map[table->size].value = i;
+		table->size++;
+	}
+
+	/* Enter this codeset */
+	for (i = cs->first_char; i <= cs->last_char; i++)
+		if (cs->ksym_tab[i - cs->first_char] != KS_voidSymbol) {
+			table->map[table->size].ksym = cs->ksym_tab[i - cs->first_char];
+			table->map[table->size].value = i;
+			table->size++;
+		}
+
+	/* Insertion sort. */
+	for (i = 1; i < table->size; i++) {
+		v = table->map[i];
+		/* find correct slot, moving others up */
+		for (j = i; --j >= 0 && v.ksym < table->map[j].ksym; )
+			table->map[j + 1] = table->map[j];
+		table->map[j + 1] = v;
+	}
+
+	table->refs++;
+	return(cs_tag);
+}
+
+/*
+ * Destroy a codeset translator.
+ */
+void
+wscodeset_destroy(void *cookie)
+{
+	struct codeset_tag_s *cs_tag = cookie;
+	struct codeset_table_s *table = cs_tag->table;
+	
+	if (cs_tag == &codeset_tag_default || table->refs-- > 1)
+		return;
+	else {
+		free(table->map, M_DEVBUF);
+		cs_tag->table->refs = 0;
+		free(cs_tag, M_DEVBUF);
+	}
+}
+
+/*
+ * Return codeset name from cookie.
+ */
+int
+wscodeset_getname(void *cookie)
+{
+	struct codeset_tag_s *cs_tag = cookie;
+
+	return(cs_tag->codeset);
+}
+
+/*
+ * Translate a keysym. Return the number of characters in result or -1 on error.
+ */
+int
+wscodeset_translate(void *cookie, keysym_t ksym, char **result)
+{
+	int i, j;
+	struct codeset_tag_s *cs_tag = cookie;
+	struct codeset_table_s *table = cs_tag->table;
+
+	*result = cs_tag->result;
+
+	for (j = 0, i = table->size; i != 0; i /= 2) {
+		if (table->map[j + i/2].ksym == ksym) {
+			cs_tag->result[0] = table->map[j + i/2].value;
+			return(1);
+		} else if (table->map[j + i/2].ksym < ksym) {
+			j += i/2 + 1;
+			i--;
+		}
+	}
+
+#ifdef DEBUG
+	printf("wscodeset_translate: codeset=%d, keysym %04x not found\n",
+	       cs_tag->codeset, ksym);
+#endif
+
+	return(0);
+}
diff -u -2 --unidirectional-new-file ../wscons.orig/wscodeset.h ./wscodeset.h
--- ../wscons.orig/wscodeset.h	Thu Jan  1 01:00:00 1970
+++ ./wscodeset.h	Fri Apr  5 19:46:34 2002
@@ -0,0 +1,63 @@
+/*	$NetBSD: $	*/
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Juergen Hannken-Illjes.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef _DEV_WSCONS_WSCODESET_H_
+#define _DEV_WSCONS_WSCODESET_H_
+
+#ifdef _KERNEL
+#include <dev/wscons/wsksymvar.h>
+#endif
+
+#define CODESET_ISO8859_1	  1
+#define CODESET_ISO8859_2	  2
+#define CODESET_KOI8_U		100
+
+#define CODESET_TAB \
+	{ CODESET_ISO8859_1,	"iso8859-1" }, \
+	{ CODESET_ISO8859_2,	"iso8859-2" }, \
+	{ CODESET_KOI8_U,	"koi8-u" }, \
+
+#ifdef _KERNEL
+void	*wscodeset_create(int);
+void	wscodeset_destroy(void *);
+int	wscodeset_getname(void *);
+int	wscodeset_translate(void *, keysym_t, char **);
+#endif
+
+#endif /* !_DEV_WSCONS_WSCODESET_H_ */
diff -u -2 --unidirectional-new-file ../wscons.orig/wsconsio.h ./wsconsio.h
--- ../wscons.orig/wsconsio.h	Fri Mar  8 16:35:27 2002
+++ ./wsconsio.h	Wed Apr  3 22:36:23 2002
@@ -376,4 +376,7 @@
 #define	WSDISPLAYIO_SETPARAM	_IOWR('W', 83, struct wsdisplay_param)
 
+#define WSDISPLAYIO_GCODESET	_IOR('W', 84, int)
+#define WSDISPLAYIO_SCODESET	_IOW('W', 85, int)
+
 /* XXX NOT YET DEFINED */
 /* Mapping information retrieval. */
diff -u -2 --unidirectional-new-file ../wscons.orig/wsdisplay.c ./wsdisplay.c
--- ../wscons.orig/wsdisplay.c	Fri Mar  8 16:35:27 2002
+++ ./wsdisplay.c	Fri Apr  5 14:25:15 2002
@@ -62,4 +62,5 @@
 #include <dev/wscons/wsksymdef.h>
 #include <dev/wscons/wsemulvar.h>
+#include <dev/wscons/wscodeset.h>
 #include <dev/wscons/wscons_callbacks.h>
 #include <dev/cons.h>
@@ -73,4 +74,5 @@
 	const struct wsemul_ops *wsemul;
 	void	*wsemulcookie;
+	void	*wscodesetcookie;
 };
 
@@ -247,4 +249,5 @@
 		} else
 			dconf->wsemul = NULL;
+		dconf->wscodesetcookie = wscodeset_create(0);
 		dconf->scrdata = type;
 	}
@@ -657,4 +660,6 @@
 								  defattr);
 
+	wsdisplay_console_conf.wscodesetcookie = wscodeset_create(0);
+
 	cn_tab = &wsdisplay_cons;
 	wsdisplay_console_initted = 1;
@@ -917,4 +922,5 @@
 	int error;
 	char namebuf[16];
+	void *cookie;
 	struct wsdisplay_font fd;
 
@@ -986,4 +992,16 @@
 		return (error);
 #undef d
+
+	case WSDISPLAYIO_GCODESET:
+		*(int *)data = wscodeset_getname(scr->scr_dconf->wscodesetcookie);
+		return (0);
+
+	case WSDISPLAYIO_SCODESET:
+		cookie = wscodeset_create(*(int *)data);
+		if (cookie == NULL)
+			return (EINVAL);
+		wscodeset_destroy(scr->scr_dconf->wscodesetcookie);
+		scr->scr_dconf->wscodesetcookie = cookie;
+		return (0);
 	}
 
@@ -1282,7 +1300,9 @@
 	tp = scr->scr_tty;
 
-	if (KS_GROUP(ks) == KS_GROUP_Ascii)
-		(*tp->t_linesw->l_rint)(KS_VALUE(ks), tp);
-	else if (WSSCREEN_HAS_EMULATOR(scr)) {
+	if (KS_GROUP(ks) == KS_GROUP_Ascii) {
+		count = wscodeset_translate(scr->scr_dconf->wscodesetcookie, ks, &dp);
+		while (count-- > 0)
+			(*tp->t_linesw->l_rint)((u_char)*dp++, tp);
+	} else if (WSSCREEN_HAS_EMULATOR(scr)) {
 		count = (*scr->scr_dconf->wsemul->translate)
 		    (scr->scr_dconf->wsemulcookie, ks, &dp);
diff -u -2 --unidirectional-new-file ../wscons.orig/wsksymdef.h ./wsksymdef.h
--- ../wscons.orig/wsksymdef.h	Fri Mar  8 16:35:27 2002
+++ ./wsksymdef.h	Thu Apr  4 22:43:00 2002
@@ -43,5 +43,5 @@
  * Keysymbols encoded as 16-bit Unicode. Special symbols
  * are encoded in the private area (0xe000 - 0xf8ff).
- * Currently only ISO Latin-1 subset is supported.
+ * Currently only a subset of Unicode is supported.
  *
  * This file is parsed from userland. Encode keysyms as:
@@ -259,8 +259,137 @@
 #define	KS_ydiaeresis 		0xff
 
-#define KS_Odoubleacute 	0x150
-#define KS_odoubleacute 	0x151
-#define KS_Udoubleacute 	0x170
-#define KS_udoubleacute 	0x171
+#define KS_Abreve		0x0102
+#define KS_abreve		0x0103
+#define KS_Aogonek		0x0104
+#define KS_aogonek		0x0105
+#define KS_Cacute		0x0106
+#define KS_cacute		0x0107
+#define KS_Ccaron		0x010c
+#define KS_ccaron		0x010d
+#define KS_Dcaron		0x010e
+#define KS_dcaron		0x010f
+#define KS_Dstroke		0x0110
+#define KS_dstroke		0x0111
+#define KS_Eogonek		0x0118
+#define KS_eogonek		0x0119
+#define KS_Ecaron		0x011a
+#define KS_ecaron		0x011b
+#define KS_Lacute		0x0139
+#define KS_lacute		0x013a
+#define KS_Lcaron		0x013d
+#define KS_lcaron		0x013e
+#define KS_Lstroke		0x0141
+#define KS_lstroke		0x0141
+#define KS_Nacute		0x0143
+#define KS_nacute		0x0144
+#define KS_Ncaron		0x0147
+#define KS_ncaron		0x0148
+#define KS_Odoubleacute 	0x0150
+#define KS_odoubleacute 	0x0151
+#define KS_Racute		0x0154
+#define KS_racute		0x0155
+#define KS_Rcaron		0x0158
+#define KS_rcaron		0x0159
+#define KS_Sacute		0x015a
+#define KS_sacute		0x015b
+#define KS_Scedilla		0x015e
+#define KS_scedilla		0x015f
+#define KS_Scaron		0x0160
+#define KS_scaron		0x0161
+#define KS_Tcedilla		0x0162
+#define KS_tcedilla		0x0163
+#define KS_Tcaron		0x0164
+#define KS_tcaron		0x0165
+#define KS_Uabovering		0x016e
+#define KS_uabovering		0x016f
+#define KS_Udoubleacute 	0x0170
+#define KS_udoubleacute 	0x0171
+#define KS_Zacute		0x0179
+#define KS_zacute		0x017a
+#define KS_Zabovedot		0x017b
+#define KS_zabovedot		0x017c
+#define KS_Zcaron		0x017d
+#define KS_zcaron		0x017e
+
+#define KS_caron		0x02c7
+#define KS_breve		0x02d8
+#define KS_abovedot		0x02d9
+#define KS_ogonek		0x02db
+#define KS_doubleacute		0x02dd
+
+#define KS_Cyrillic_IO		0x0401
+#define KS_Cyrillic_IEUKR	0x0404
+#define KS_Cyrillic_IUKR	0x0406
+#define KS_Cyrillic_YI		0x0407
+#define KS_Cyrillic_A		0x0410
+#define KS_Cyrillic_BE		0x0411
+#define KS_Cyrillic_VE		0x0412
+#define KS_Cyrillic_GHE		0x0413
+#define KS_Cyrillic_DE		0x0414
+#define KS_Cyrillic_IE		0x0415
+#define KS_Cyrillic_ZHE		0x0416
+#define KS_Cyrillic_ZE		0x0417
+#define KS_Cyrillic_I		0x0418
+#define KS_Cyrillic_SHORTI	0x0419
+#define KS_Cyrillic_KA		0x041a
+#define KS_Cyrillic_EL		0x041b
+#define KS_Cyrillic_EM		0x041c
+#define KS_Cyrillic_EN		0x041d
+#define KS_Cyrillic_O		0x041e
+#define KS_Cyrillic_PE		0x041f
+#define KS_Cyrillic_ER		0x0420
+#define KS_Cyrillic_ES		0x0421
+#define KS_Cyrillic_TE		0x0422
+#define KS_Cyrillic_U		0x0423
+#define KS_Cyrillic_EF		0x0424
+#define KS_Cyrillic_HA		0x0425
+#define KS_Cyrillic_TSE		0x0426
+#define KS_Cyrillic_CHE		0x0427
+#define KS_Cyrillic_SHA		0x0428
+#define KS_Cyrillic_SHCHA	0x0429
+#define KS_Cyrillic_HARDSIGN	0x042a
+#define KS_Cyrillic_YERU	0x042b
+#define KS_Cyrillic_SOFTSIGN	0x042c
+#define KS_Cyrillic_E		0x042d
+#define KS_Cyrillic_YU		0x042e
+#define KS_Cyrillic_YA		0x042f
+#define KS_Cyrillic_a		0x0430
+#define KS_Cyrillic_be		0x0431
+#define KS_Cyrillic_ve		0x0432
+#define KS_Cyrillic_ghe		0x0433
+#define KS_Cyrillic_de		0x0434
+#define KS_Cyrillic_ie		0x0435
+#define KS_Cyrillic_zhe		0x0436
+#define KS_Cyrillic_ze		0x0437
+#define KS_Cyrillic_i		0x0438
+#define KS_Cyrillic_shorti	0x0439
+#define KS_Cyrillic_ka		0x043a
+#define KS_Cyrillic_el		0x043b
+#define KS_Cyrillic_em		0x043c
+#define KS_Cyrillic_en		0x043d
+#define KS_Cyrillic_o		0x043e
+#define KS_Cyrillic_pe		0x043f
+#define KS_Cyrillic_er		0x0440
+#define KS_Cyrillic_es		0x0441
+#define KS_Cyrillic_te		0x0442
+#define KS_Cyrillic_u		0x0443
+#define KS_Cyrillic_ef		0x0444
+#define KS_Cyrillic_ha		0x0445
+#define KS_Cyrillic_tse	0x0446
+#define KS_Cyrillic_che	0x0447
+#define KS_Cyrillic_sha	0x0448
+#define KS_Cyrillic_shcha	0x0449
+#define KS_Cyrillic_hardsign	0x044a
+#define KS_Cyrillic_yeru	0x044b
+#define KS_Cyrillic_softsign	0x044c
+#define KS_Cyrillic_e		0x044d
+#define KS_Cyrillic_yu		0x044e
+#define KS_Cyrillic_ya		0x044f
+#define KS_Cyrillic_io		0x0451
+#define KS_Cyrillic_ieukr	0x0454
+#define KS_Cyrillic_iukr	0x0456
+#define KS_Cyrillic_yi		0x0457
+#define KS_Cyrillic_GHEUKR	0x0490
+#define KS_Cyrillic_gheukr	0x0491
 
 /*
@@ -272,6 +401,8 @@
 #define	KS_dead_circumflex 	0x0302
 #define	KS_dead_tilde 		0x0303
+#define KS_dead_breve		0x0306
 #define	KS_dead_diaeresis 	0x0308
 #define	KS_dead_abovering 	0x030a
+#define KS_dead_caron		0x030c
 #define	KS_dead_cedilla 	0x0327
 

--KsGdsel6WgEHnImy--