summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-10-18 22:06:43 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-10-18 22:06:43 +0000
commitda16c4a585db0f4d4c68c63f8e1ec68bad619792 (patch)
tree1dd99714301bad2a62381dbe13004d2239dffef4 /sys
parent0c0471767b4261526224c8ef1d331039f4c50a3a (diff)
UTF-8 support for wsdisplay emulation modes. Both vt100 and sun emulation
will now recognize xterm-compatible escape sequences ESC % G and ESC % @ to enter and leave UTF-8 mode, respectively. Not enabled on SMALL_KERNEL. Most of this written during c2k7, completed during b2k13. Note that the value of several international keysyms change, to switch from ISO Latin-[257] values to the real Unicode values. Be sure to update your includes and rebuild and install wsconsctl.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/wscons/files.wscons3
-rw-r--r--sys/dev/wscons/wscons_callbacks.h4
-rw-r--r--sys/dev/wscons/wscons_features.h6
-rw-r--r--sys/dev/wscons/wsdisplay.c20
-rw-r--r--sys/dev/wscons/wsemul_dumb.c7
-rw-r--r--sys/dev/wscons/wsemul_subr.c706
-rw-r--r--sys/dev/wscons/wsemul_sun.c198
-rw-r--r--sys/dev/wscons/wsemul_vt100.c289
-rw-r--r--sys/dev/wscons/wsemul_vt100_chars.c4
-rw-r--r--sys/dev/wscons/wsemul_vt100_keys.c23
-rw-r--r--sys/dev/wscons/wsemul_vt100_subr.c20
-rw-r--r--sys/dev/wscons/wsemul_vt100var.h17
-rw-r--r--sys/dev/wscons/wsemulvar.h26
-rw-r--r--sys/dev/wscons/wskbd.c4
-rw-r--r--sys/dev/wscons/wsksymdef.h404
15 files changed, 1358 insertions, 373 deletions
diff --git a/sys/dev/wscons/files.wscons b/sys/dev/wscons/files.wscons
index 724347eba54..9893665ea92 100644
--- a/sys/dev/wscons/files.wscons
+++ b/sys/dev/wscons/files.wscons
@@ -1,4 +1,4 @@
-# $OpenBSD: files.wscons,v 1.15 2007/05/31 22:23:13 tedu Exp $
+# $OpenBSD: files.wscons,v 1.16 2013/10/18 22:06:40 miod Exp $
# $NetBSD: files.wscons,v 1.34 2005/05/04 01:52:16 augustss Exp $
#
@@ -35,6 +35,7 @@ file dev/wscons/wsmux.c wsmux needs-flag
# emulation code
file dev/wscons/wsemulconf.c wsdisplay
file dev/wscons/wsemul_dumb.c wsdisplay & wsemul_dumb
+file dev/wscons/wsemul_subr.c wsdisplay
file dev/wscons/wsemul_sun.c wsdisplay & wsemul_sun
file dev/wscons/wsemul_vt100.c wsdisplay & !wsemul_no_vt100
file dev/wscons/wsemul_vt100_subr.c wsdisplay & !wsemul_no_vt100
diff --git a/sys/dev/wscons/wscons_callbacks.h b/sys/dev/wscons/wscons_callbacks.h
index 48933af6332..ddfd08d36e9 100644
--- a/sys/dev/wscons/wscons_callbacks.h
+++ b/sys/dev/wscons/wscons_callbacks.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wscons_callbacks.h,v 1.8 2010/11/20 20:52:10 miod Exp $ */
+/* $OpenBSD: wscons_callbacks.h,v 1.9 2013/10/18 22:06:40 miod Exp $ */
/* $NetBSD: wscons_callbacks.h,v 1.16 2001/11/10 17:14:51 augustss Exp $ */
/*
@@ -41,7 +41,7 @@ void wsdisplay_set_console_kbd(struct wsevsrc *);
/*
* Calls to the display interface from the keyboard interface.
*/
-void wsdisplay_kbdinput(struct device *v, keysym_t *, int);
+void wsdisplay_kbdinput(struct device *v, kbd_t, keysym_t *, int);
void wsdisplay_rawkbdinput(struct device *v, u_char *, int);
int wsdisplay_switch(struct device *, int, int);
enum wsdisplay_resetops {
diff --git a/sys/dev/wscons/wscons_features.h b/sys/dev/wscons/wscons_features.h
index b18603fe4e8..58ffaeb2ca7 100644
--- a/sys/dev/wscons/wscons_features.h
+++ b/sys/dev/wscons/wscons_features.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wscons_features.h,v 1.2 2013/10/18 14:17:23 miod Exp $ */
+/* $OpenBSD: wscons_features.h,v 1.3 2013/10/18 22:06:40 miod Exp $ */
/* public domain */
/*
@@ -15,6 +15,9 @@
* wsdisplay supports this
* HAVE_JUMP_SCROLL
* defined to enable jump scroll in the textmode emulation code
+ * HAVE_UTF8_SUPPORT
+ * defined to enable UTF-8 mode and escape sequences in the textmode
+ * emulation code
* HAVE_RESTARTABLE_EMULOPS
* defined to disable most of the restartable emulops code (to be used
* only if all wsdisplay drivers are compliant, i.e. no udl(4) in the
@@ -28,6 +31,7 @@
#define HAVE_BURNER_SUPPORT
#define HAVE_SCROLLBACK_SUPPORT
#define HAVE_JUMP_SCROLL
+#define HAVE_UTF8_SUPPORT
#define HAVE_RESTARTABLE_EMULOPS
#endif
diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c
index 867be152a9f..f32a2fbdfeb 100644
--- a/sys/dev/wscons/wsdisplay.c
+++ b/sys/dev/wscons/wsdisplay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsdisplay.c,v 1.113 2013/10/18 13:54:08 miod Exp $ */
+/* $OpenBSD: wsdisplay.c,v 1.114 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */
/*
@@ -1602,11 +1602,11 @@ wsdisplay_emulinput(void *v, const u_char *data, u_int count)
* Calls from the keyboard interface.
*/
void
-wsdisplay_kbdinput(struct device *dev, keysym_t *ks, int num)
+wsdisplay_kbdinput(struct device *dev, kbd_t layout, keysym_t *ks, int num)
{
struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
struct wsscreen *scr;
- const char *dp;
+ const u_char *dp;
int count;
struct tty *tp;
@@ -1616,15 +1616,11 @@ wsdisplay_kbdinput(struct device *dev, keysym_t *ks, int num)
tp = scr->scr_tty;
- for (; num > 0; num--, ks++) {
- if (KS_GROUP(*ks) == KS_GROUP_Ascii)
- (*linesw[tp->t_line].l_rint)(KS_VALUE(*ks), tp);
- else {
- count = (*scr->scr_dconf->wsemul->translate)
- (scr->scr_dconf->wsemulcookie, *ks, &dp);
- while (count-- > 0)
- (*linesw[tp->t_line].l_rint)(*dp++, tp);
- }
+ for (; num > 0; num--) {
+ count = (*scr->scr_dconf->wsemul->translate)
+ (scr->scr_dconf->wsemulcookie, layout, *ks++, &dp);
+ while (count-- > 0)
+ (*linesw[tp->t_line].l_rint)(*dp++, tp);
}
}
diff --git a/sys/dev/wscons/wsemul_dumb.c b/sys/dev/wscons/wsemul_dumb.c
index 86010f0666a..1226cb2cd72 100644
--- a/sys/dev/wscons/wsemul_dumb.c
+++ b/sys/dev/wscons/wsemul_dumb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_dumb.c,v 1.10 2010/08/28 12:48:14 miod Exp $ */
+/* $OpenBSD: wsemul_dumb.c,v 1.11 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_dumb.c,v 1.7 2000/01/05 11:19:36 drochner Exp $ */
/*
@@ -47,7 +47,7 @@ void *wsemul_dumb_cnattach(const struct wsscreen_descr *, void *,
void *wsemul_dumb_attach(int, const struct wsscreen_descr *,
void *, int, int, void *, long);
u_int wsemul_dumb_output(void *, const u_char *, u_int, int);
-int wsemul_dumb_translate(void *, keysym_t, const char **);
+int wsemul_dumb_translate(void *, kbd_t, keysym_t, const u_char **);
void wsemul_dumb_detach(void *, u_int *, u_int *);
void wsemul_dumb_resetop(void *, enum wsemul_resetops);
@@ -285,7 +285,8 @@ wsemul_dumb_output(void *cookie, const u_char *data, u_int count, int kernel)
}
int
-wsemul_dumb_translate(void *cookie, keysym_t in, const char **out)
+wsemul_dumb_translate(void *cookie, kbd_t layout, keysym_t in,
+ const u_char **out)
{
return (0);
}
diff --git a/sys/dev/wscons/wsemul_subr.c b/sys/dev/wscons/wsemul_subr.c
new file mode 100644
index 00000000000..50d7b7a2436
--- /dev/null
+++ b/sys/dev/wscons/wsemul_subr.c
@@ -0,0 +1,706 @@
+/* $OpenBSD: wsemul_subr.c,v 1.1 2013/10/18 22:06:41 miod Exp $ */
+
+/*
+ * Copyright (c) 2007, 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+
+#include <dev/wscons/wscons_features.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsemulvar.h>
+#include <dev/wscons/wsksymdef.h>
+
+int wsemul_local_translate(u_int32_t, kbd_t, u_char *);
+
+/*
+ * Get characters from an input stream and update the input state.
+ * Processing stops when the stream is empty, or a complete character
+ * sequence has been recognized, in which case it returns zero.
+ */
+int
+wsemul_getchar(const u_char **inbuf, u_int *inlen,
+ struct wsemul_inputstate *state, int allow_utf8)
+{
+#ifndef HAVE_UTF8_SUPPORT
+ u_int len = *inlen;
+ const u_char *buf = *inbuf;
+
+ if (len == 0)
+ return (EAGAIN);
+
+ state->inchar = *buf++;
+ state->mbleft = 0;
+ len--;
+ *inlen = len;
+ *inbuf = buf;
+ return (0);
+#else
+ u_int len = *inlen;
+ const u_char *buf = *inbuf;
+ int rc = EAGAIN;
+ u_int32_t tmpchar;
+ u_int mbleft;
+
+ if (len == 0)
+ return (rc);
+
+ /*
+ * If we do not allow multibyte sequences, process as quickly
+ * as possible.
+ */
+ if (!allow_utf8) {
+ state->inchar = *buf++;
+ state->mbleft = 0;
+ len--;
+ *inlen = len;
+ *inbuf = buf;
+ return (0);
+ }
+
+ tmpchar = state->inchar;
+ mbleft = state->mbleft;
+
+ while (len != 0) {
+ u_int32_t frag = (u_int32_t)*buf++;
+ len--;
+
+ /*
+ * If we are in the middle of a multibyte sequence, try
+ * to complete it.
+ */
+
+ if (mbleft != 0) {
+ if ((frag & 0xc0) != 0x80) {
+ /* Abort the sequence and continue */
+ mbleft = 0;
+ tmpchar = 0;
+ rc = EILSEQ;
+ } else {
+ tmpchar = (tmpchar << 6) | (frag & 0x3f);
+ mbleft--;
+ if (mbleft == 0) {
+ rc = 0;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Otherwise let's decide if this is the start of a new
+ * multibyte sequence, or a 7-bit character.
+ */
+
+ if ((frag & 0x80) == 0) {
+ tmpchar = frag;
+ rc = 0;
+ break;
+ }
+
+ if (frag == 0xfe || frag == 0xff || (frag & 0x40) == 0) {
+ /* Abort the sequence and continue */
+ mbleft = 0;
+ tmpchar = 0;
+ rc = EILSEQ;
+ } else {
+ frag &= ~(0x80 | 0x40);
+ mbleft = 1;
+
+ if (frag & 0x20) {
+ frag &= ~0x20;
+ mbleft++;
+ }
+ if (frag & 0x10) {
+ frag &= ~0x10;
+ mbleft++;
+ }
+ if (frag & 0x08) {
+ frag &= ~0x08;
+ mbleft++;
+ }
+ if (frag & 0x04) {
+ frag &= ~0x04;
+ mbleft++;
+ }
+
+ tmpchar = frag;
+ }
+ }
+
+ state->inchar = tmpchar;
+ state->mbleft = mbleft;
+ *inlen = len;
+ *inbuf = buf;
+ return (rc);
+#endif
+}
+
+/*
+ * Unicode Cyrillic to KOI8 translation table (starts at U+0400),
+ * from RFC 2319.
+ */
+const u_int8_t cyrillic_to_koi8[] = {
+ 0x00, /* IE grave */ /* 0400 */
+ 0xb3, /* IO */
+ 0x00, /* DJE */
+ 0x00, /* GJE */
+ 0xb4, /* UKR IE */
+ 0x00, /* DZE */
+ 0xb6, /* BYE/UKR I */
+ 0xb7, /* YI */
+ 0x00, /* JE */
+ 0x00, /* LJE */
+ 0x00, /* NJE */
+ 0x00, /* TSHE */
+ 0x00, /* KJE */
+ 0x00, /* I grave */
+ 0x00, /* short U */
+ 0x00, /* DZHE */
+ 0xe1, /* A */ /* 0410 */
+ 0xe2, /* BE */
+ 0xf7, /* VE */
+ 0xe7, /* GHE */
+ 0xe4, /* DE */
+ 0xe5, /* IE */
+ 0xf6, /* ZHE */
+ 0xfa, /* ZE */
+ 0xe9, /* I */
+ 0xea, /* short I */
+ 0xeb, /* KA */
+ 0xec, /* EL */
+ 0xed, /* EM */
+ 0xee, /* EN */
+ 0xef, /* O */
+ 0xf0, /* PE */
+ 0xf2, /* ER */ /* 0420 */
+ 0xf3, /* ES */
+ 0xf4, /* TE */
+ 0xf5, /* U */
+ 0xe6, /* EF */
+ 0xe8, /* HA */
+ 0xe3, /* TSE */
+ 0xfe, /* CHE */
+ 0xfb, /* SHA */
+ 0xfd, /* SHCHA */
+ 0xff, /* HARD SIGN */
+ 0xf9, /* YERU */
+ 0xf8, /* SOFT SIGN */
+ 0xfc, /* E */
+ 0xe0, /* YU */
+ 0xf1, /* YA */
+ 0xc1, /* a */ /* 0430 */
+ 0xc2, /* be */
+ 0xd7, /* ve */
+ 0xc7, /* ghe */
+ 0xc4, /* de */
+ 0xc5, /* ie */
+ 0xd6, /* zhe */
+ 0xda, /* ze */
+ 0xc9, /* i */
+ 0xca, /* short i */
+ 0xcb, /* ka */
+ 0xcc, /* el */
+ 0xcd, /* em */
+ 0xce, /* en */
+ 0xcf, /* o */
+ 0xd0, /* pe */
+ 0xd2, /* er */ /* 0440 */
+ 0xd3, /* es */
+ 0xd4, /* te */
+ 0xd5, /* u */
+ 0xc6, /* ef */
+ 0xc8, /* ha */
+ 0xc3, /* tse */
+ 0xde, /* che */
+ 0xdb, /* sha */
+ 0xdd, /* shcha */
+ 0xdf, /* hard sign */
+ 0xd9, /* yeru */
+ 0xd8, /* soft sign */
+ 0xdc, /* e */
+ 0xc0, /* yu */
+ 0xd1, /* ya */
+ 0x00, /* ie grave */ /* 0450 */
+ 0xa3, /* io */
+ 0x00, /* dje */
+ 0x00, /* GJE */
+ 0xa4, /* UKR ie */
+ 0x00, /* DZE */
+ 0xa6, /* BYE/UKR I */
+ 0xa7, /* YI */
+ 0x00, /* JE */
+ 0x00, /* LJE */
+ 0x00, /* NJE */
+ 0x00, /* TSHE */
+ 0x00, /* KJE */
+ 0x00, /* I grave */
+ 0x00, /* short U */
+ 0x00 /* DZHE */
+};
+
+/*
+ * Europe to Latin-2 translation table (starts at U+0100).
+ */
+const u_int8_t unicode_to_latin2[] = {
+ 0x00, /* A macron */ /* 0100 */
+ 0x00, /* a macron */
+ 0xc3, /* A breve */
+ 0xe3, /* a breve */
+ 0xa1, /* A ogonek */
+ 0xb1, /* a ogonek */
+ 0xc6, /* C acute */
+ 0xe6, /* c acute */
+ 0x00, /* C circumflex */
+ 0x00, /* c circumflex */
+ 0x00, /* C abovering */
+ 0x00, /* c abovering */
+ 0xc8, /* C caron */
+ 0xe8, /* c caron */
+ 0xcf, /* D caron */
+ 0xef, /* d caron */
+ 0xd0, /* D stroke */ /* 0110 */
+ 0xf0, /* d stroke */
+ 0x00, /* E macron */
+ 0x00, /* e macron */
+ 0x00, /* E breve */
+ 0x00, /* e breve */
+ 0x00, /* E abovering */
+ 0x00, /* e abovering */
+ 0xca, /* E ogonek */
+ 0xea, /* e ogonek */
+ 0xcc, /* E caron */
+ 0xec, /* e caron */
+ 0x00, /* G circumflex */
+ 0x00, /* g circumflex */
+ 0x00, /* G breve */
+ 0x00, /* g breve */
+ 0x00, /* G abovering */ /* 0120 */
+ 0x00, /* g abovering */
+ 0x00, /* G cedilla */
+ 0x00, /* g cedilla */
+ 0x00, /* H circumflex */
+ 0x00, /* h circumflex */
+ 0x00, /* H stroke */
+ 0x00, /* h stroke */
+ 0x00, /* I tilde */
+ 0x00, /* i tilde */
+ 0x00, /* I macron */
+ 0x00, /* i macron */
+ 0x00, /* I breve */
+ 0x00, /* i breve */
+ 0x00, /* I ogonek */
+ 0x00, /* i ogonek */
+ 0x00, /* dotted I */ /* 0130 */
+ 0x00, /* non-dotted i */
+ 0x00, /* ligature IJ */
+ 0x00, /* ligature ij */
+ 0x00, /* J circumflex */
+ 0x00, /* j circumflex */
+ 0x00, /* K cedilla */
+ 0x00, /* k cedilla */
+ 0x00, /* kra */
+ 0xc5, /* L acute */
+ 0xe5, /* l acute */
+ 0x00, /* L cedilla */
+ 0x00, /* l cedilla */
+ 0xa5, /* L caron */
+ 0xb5, /* l caron */
+ 0x00, /* L middle dot */
+ 0x00, /* l middle dot */ /* 0140 */
+ 0xa3, /* L stroke */
+ 0xb3, /* l stroke */
+ 0xd1, /* N acute */
+ 0xf1, /* n acute */
+ 0x00, /* N cedilla */
+ 0x00, /* n cedilla */
+ 0xd2, /* N caron */
+ 0xf2, /* n caron */
+ 0x00, /* N preceded by apostrophe */
+ 0x00, /* ENG */
+ 0x00, /* eng */
+ 0x00, /* O macron */
+ 0x00, /* o macron */
+ 0x00, /* O breve */
+ 0x00, /* o breve */
+ 0xd5, /* O double acute */ /* 0150 */
+ 0xf5, /* o double acute */
+ 0x00, /* ligature OE */
+ 0x00, /* ligature oe */
+ 0xc0, /* R acute */
+ 0xe0, /* r acute */
+ 0x00, /* R cedilla */
+ 0x00, /* r cedilla */
+ 0xd8, /* R caron */
+ 0xf8, /* r caron */
+ 0xa6, /* S acute */
+ 0xb6, /* s acute */
+ 0x00, /* S circumflex */
+ 0x00, /* s circumflex */
+ 0xaa, /* S cedilla */
+ 0xba, /* s cedilla */
+ 0xa9, /* S caron */ /* 0160 */
+ 0xb9, /* s caron */
+ 0xde, /* T cedilla */
+ 0xfe, /* t cedilla */
+ 0xab, /* T caron */
+ 0xbb, /* t caron */
+ 0x00, /* T stroke */
+ 0x00, /* t stroke */
+ 0x00, /* U tilde */
+ 0x00, /* u tilde */
+ 0x00, /* U macron */
+ 0x00, /* u macron */
+ 0x00, /* U breve */
+ 0x00, /* u breve */
+ 0xd9, /* U abovering */
+ 0xf9, /* u abovering */
+ 0xdb, /* U double acute */ /* 0170 */
+ 0xfb, /* u double acute */
+ 0x00, /* U ogonek */
+ 0x00, /* u ogonek */
+ 0x00, /* W circumflex */
+ 0x00, /* w circumflex */
+ 0x00, /* Y circumflex */
+ 0x00, /* y circumflex */
+ 0x00, /* Y diaeresis */
+ 0xac, /* Z acute */
+ 0xbc, /* z acute */
+ 0xaf, /* Z abovering */
+ 0xbf, /* z abovering */
+ 0xae, /* Z caron */
+ 0xbe, /* z caron */
+ 0x00 /* long s */
+};
+
+/*
+ * Baltic to Latin-7 translation table.
+ */
+const u_int8_t unicode_to_latin7[] = {
+ 0xc2, /* A macron */ /* 0100 */
+ 0xe2, /* a macron */
+ 0x00, /* A breve */
+ 0x00, /* a breve */
+ 0xc0, /* A ogonek */
+ 0xe0, /* a ogonek */
+ 0xc3, /* C acute */
+ 0xe3, /* c acute */
+ 0x00, /* C circumflex */
+ 0x00, /* c circumflex */
+ 0x00, /* C abovering */
+ 0x00, /* c abovering */
+ 0xc8, /* C caron */
+ 0xe8, /* c caron */
+ 0x00, /* D caron */
+ 0x00, /* d caron */
+ 0x00, /* D stroke */ /* 0110 */
+ 0x00, /* d stroke */
+ 0xc7, /* E macron */
+ 0xe7, /* e macron */
+ 0x00, /* E breve */
+ 0x00, /* e breve */
+ 0xcb, /* E abovering */
+ 0xeb, /* e abovering */
+ 0xc6, /* E ogonek */
+ 0xe6, /* e ogonek */
+ 0x00, /* E caron */
+ 0x00, /* e caron */
+ 0x00, /* G circumflex */
+ 0x00, /* g circumflex */
+ 0x00, /* G breve */
+ 0x00, /* g breve */
+ 0x00, /* G abovering */ /* 0120 */
+ 0x00, /* g abovering */
+ 0xcc, /* G cedilla */
+ 0xec, /* g cedilla */
+ 0x00, /* H circumflex */
+ 0x00, /* h circumflex */
+ 0x00, /* H stroke */
+ 0x00, /* h stroke */
+ 0x00, /* I tilde */
+ 0x00, /* i tilde */
+ 0xce, /* I macron */
+ 0xee, /* i macron */
+ 0x00, /* I breve */
+ 0x00, /* i breve */
+ 0xc1, /* I ogonek */
+ 0xe1, /* i ogonek */
+ 0x00, /* dotted I */ /* 0130 */
+ 0x00, /* non-dotted I */
+ 0x00, /* ligature IJ */
+ 0x00, /* ligature ij */
+ 0x00, /* J circumflex */
+ 0x00, /* j circumflex */
+ 0xcd, /* K cedilla */
+ 0xed, /* k cedilla */
+ 0x00, /* kra */
+ 0x00, /* L acute */
+ 0x00, /* l acute */
+ 0xcf, /* L cedilla */
+ 0xef, /* l cedilla */
+ 0x00, /* L caron */
+ 0x00, /* l caron */
+ 0x00, /* L middle dot */
+ 0x00, /* l middle dot */ /* 0140 */
+ 0xd9, /* L stroke */
+ 0xf9, /* l stroke */
+ 0xd1, /* N acute */
+ 0xf1, /* n acute */
+ 0xd2, /* N cedilla */
+ 0xf2, /* n cedilla */
+ 0x00, /* N caron */
+ 0x00, /* n caron */
+ 0x00, /* N preceded by apostrophe */
+ 0x00, /* ENG */
+ 0x00, /* eng */
+ 0xd4, /* O macron */
+ 0xf4, /* o macron */
+ 0x00, /* O breve */
+ 0x00, /* o breve */
+ 0x00, /* O double acute */ /* 0150 */
+ 0x00, /* o double acute */
+ 0x00, /* ligature OE */
+ 0x00, /* ligature oe */
+ 0x00, /* R acute */
+ 0x00, /* r acute */
+ 0xaa, /* R cedilla */
+ 0xba, /* r cedilla */
+ 0x00, /* R caron */
+ 0x00, /* r caron */
+ 0xda, /* S acute */
+ 0xfa, /* s acute */
+ 0x00, /* S circumflex */
+ 0x00, /* s circumflex */
+ 0x00, /* S cedilla */
+ 0x00, /* s cedilla */
+ 0xd0, /* S caron */ /* 0160 */
+ 0xf0, /* s caron */
+ 0x00, /* T cedilla */
+ 0x00, /* t cedilla */
+ 0x00, /* T caron */
+ 0x00, /* t caron */
+ 0x00, /* T stroke */
+ 0x00, /* t stroke */
+ 0x00, /* U tilde */
+ 0x00, /* u tilde */
+ 0xdb, /* U macron */
+ 0xfb, /* u macron */
+ 0x00, /* U breve */
+ 0x00, /* u breve */
+ 0x00, /* U abovering */
+ 0x00, /* u abovering */
+ 0x00, /* U double acute */ /* 0170 */
+ 0x00, /* u double acute */
+ 0xd8, /* U ogonek */
+ 0xf8, /* u ogonek */
+ 0x00, /* W circumflex */
+ 0x00, /* w circumflex */
+ 0x00, /* Y circumflex */
+ 0x00, /* y circumflex */
+ 0x00, /* Y diaeresis */
+ 0xca, /* Z acute */
+ 0xea, /* z acute */
+ 0xdd, /* Z abovering */
+ 0xfd, /* z abovering */
+ 0xde, /* Z caron */
+ 0xfe, /* z caron */
+ 0x00 /* long s */
+};
+
+/*
+ * Keysym to local 8-bit charset sequence translation function.
+ * The out buffer is at least one character long.
+ * The keyboard layout is used as a hint to decide which latin charset to
+ * assume.
+ */
+int
+wsemul_local_translate(u_int32_t unisym, kbd_t layout, u_char *out)
+{
+ switch (unisym >> 7) {
+ case 0x0080 >> 7:
+ switch (KB_ENCODING(layout)) {
+ case KB_LT:
+ case KB_LV:
+ switch (unisym) {
+ case KS_L7_AE:
+ unisym = 0xaf;
+ break;
+ case KS_L7_Ostroke:
+ unisym = 0xa8;
+ break;
+ case KS_L7_ae:
+ unisym = 0xbf;
+ break;
+ case KS_L7_ostroke:
+ unisym = 0xb8;
+ break;
+ }
+ }
+ break;
+
+ case 0x0100 >> 7:
+ switch (KB_ENCODING(layout)) {
+ case KB_LT:
+ case KB_LV:
+ if (unisym < 0x100 + nitems(unicode_to_latin7) &&
+ unicode_to_latin7[unisym - 0x100] != 0)
+ unisym = unicode_to_latin7[unisym - 0x100];
+ break;
+ case KB_TR:
+ switch (unisym) {
+ case KS_L5_Gbreve:
+ unisym = 0xd0;
+ break;
+ case KS_L5_gbreve:
+ unisym = 0xf0;
+ break;
+ case KS_L5_Idotabove:
+ unisym = 0xdd;
+ break;
+ case KS_L5_idotless:
+ unisym = 0xfd;
+ break;
+ case KS_L5_Scedilla:
+ unisym = 0xde;
+ break;
+ case KS_L5_scedilla:
+ unisym = 0xfe;
+ break;
+ }
+ break;
+ case KB_PL:
+ case KB_SI:
+ if (unisym < 0x100 + nitems(unicode_to_latin2) &&
+ unicode_to_latin2[unisym - 0x100] != 0)
+ unisym = unicode_to_latin2[unisym - 0x100];
+ break;
+ }
+ break;
+
+ case 0x0280 >> 7:
+ switch (KB_ENCODING(layout)) {
+ case KB_PL:
+ case KB_SI:
+ switch (unisym) {
+ case KS_L2_caron:
+ unisym = 0xb7;
+ break;
+ case KS_L2_breve:
+ unisym = 0xa2;
+ break;
+ case KS_L2_dotabove:
+ unisym = 0xff;
+ break;
+ case KS_L2_ogonek:
+ unisym = 0xb2;
+ break;
+ case KS_L2_dblacute:
+ unisym = 0xbd;
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0x0400 >> 7:
+ if (unisym < 0x400 +
+ sizeof(cyrillic_to_koi8) / sizeof(cyrillic_to_koi8[0]) &&
+ cyrillic_to_koi8[unisym - 0x400] != 0)
+ unisym = cyrillic_to_koi8[unisym - 0x400];
+ break;
+ case 0x0480 >> 7:
+ if (unisym == KS_Cyrillic_GHEUKR)
+ unisym = 0xbd; /* ukrainian GHE */
+ else if (unisym == KS_Cyrillic_gheukr)
+ unisym = 0xad; /* ukrainian ghe */
+ break;
+
+ case 0x2000 >> 7:
+ switch (KB_ENCODING(layout)) {
+ case KB_LT:
+ case KB_LV:
+ switch (unisym) {
+ case KS_L7_rightsnglquot:
+ unisym = 0xff;
+ break;
+ case KS_L7_leftdblquot:
+ unisym = 0xb4;
+ break;
+ case KS_L7_rightdblquot:
+ unisym = 0xa1;
+ break;
+ case KS_L7_dbllow9quot:
+ unisym = 0xa5;
+ break;
+ }
+ }
+ break;
+
+ }
+
+ out[0] = unisym & 0xff;
+ return (1);
+}
+
+/*
+ * Keysym to UTF-8 sequence translation function.
+ * The out buffer is at least 6 characters long.
+ */
+int
+wsemul_utf8_translate(u_int32_t unisym, kbd_t layout, u_char *out,
+ int allow_utf8)
+{
+#ifndef HAVE_UTF8_SUPPORT
+ return (wsemul_local_translate(unisym, layout, out));
+#else
+ u_int pos, length, headpat;
+
+ if (!allow_utf8)
+ return (wsemul_local_translate(unisym, layout, out));
+
+ if (unisym >= 0x80000000) {
+ return (0);
+ } else if (unisym > 0x04000000) {
+ headpat = 0xfc;
+ length = 6;
+ } else if (unisym > 0x00200000) {
+ headpat = 0xf8;
+ length = 5;
+ } else if (unisym > 0x00010000) {
+ headpat = 0xf0;
+ length = 4;
+ } else if (unisym > 0x00000800) {
+ headpat = 0xe0;
+ length = 3;
+ } else if (unisym > 0x00000080) {
+ headpat = 0xc0;
+ length = 2;
+ } else {
+ headpat = 0x00;
+ length = 1;
+ }
+
+ for (pos = length - 1; pos > 0; pos--) {
+ out[pos] = 0x80 | (unisym & 0x3f);
+ unisym >>= 6;
+ }
+ out[0] = headpat | unisym;
+
+ return (length);
+#endif
+}
diff --git a/sys/dev/wscons/wsemul_sun.c b/sys/dev/wscons/wsemul_sun.c
index d490894077b..b698fd3c03f 100644
--- a/sys/dev/wscons/wsemul_sun.c
+++ b/sys/dev/wscons/wsemul_sun.c
@@ -1,7 +1,23 @@
-/* $OpenBSD: wsemul_sun.c,v 1.29 2013/10/18 13:54:09 miod Exp $ */
+/* $OpenBSD: wsemul_sun.c,v 1.30 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_sun.c,v 1.11 2000/01/05 11:19:36 drochner Exp $ */
/*
+ * Copyright (c) 2007, 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,7 +72,7 @@ void *wsemul_sun_cnattach(const struct wsscreen_descr *, void *,
void *wsemul_sun_attach(int, const struct wsscreen_descr *,
void *, int, int, void *, long);
u_int wsemul_sun_output(void *, const u_char *, u_int, int);
-int wsemul_sun_translate(void *, keysym_t, const char **);
+int wsemul_sun_translate(void *, kbd_t, keysym_t, const u_char **);
void wsemul_sun_detach(void *, u_int *, u_int *);
void wsemul_sun_resetop(void *, enum wsemul_resetops);
@@ -72,7 +88,10 @@ const struct wsemul_ops wsemul_sun_ops = {
#define SUN_EMUL_STATE_NORMAL 0 /* normal processing */
#define SUN_EMUL_STATE_HAVEESC 1 /* seen start of ctl seq */
-#define SUN_EMUL_STATE_CONTROL 2 /* processing ctl seq */
+#define SUN_EMUL_STATE_CONTROL 2 /* processing ESC [ ctl seq */
+#define SUN_EMUL_STATE_PERCENT 3 /* processing ESC % ctl seq */
+
+#define SUN_EMUL_FLAGS_UTF8 0x01 /* UTF-8 character set */
#define SUN_EMUL_NARGS 2 /* max # of args to a command */
@@ -86,6 +105,7 @@ struct wsemul_sun_emuldata {
long defattr; /* default attribute (rendition) */
u_int state; /* processing state */
+ u_int flags;
u_int args[SUN_EMUL_NARGS]; /* command args, if CONTROL */
int nargs; /* number of args */
@@ -94,6 +114,15 @@ struct wsemul_sun_emuldata {
long kernattr; /* attribute for kernel output */
int attrflags, fgcol, bgcol; /* properties of curattr */
+ struct wsemul_inputstate instate; /* userland input state */
+ struct wsemul_inputstate kstate; /* kernel input state */
+
+#ifdef HAVE_UTF8_SUPPORT
+ u_char translatebuf[6];
+#else
+ u_char translatebuf[1];
+#endif
+
#ifdef DIAGNOSTIC
int console;
#endif
@@ -104,11 +133,18 @@ void wsemul_sun_init(struct wsemul_sun_emuldata *,
int wsemul_sun_jump_scroll(struct wsemul_sun_emuldata *, const u_char *,
u_int, int);
void wsemul_sun_reset(struct wsemul_sun_emuldata *);
-int wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *, u_char, int);
-int wsemul_sun_output_normal(struct wsemul_sun_emuldata *, u_char, int);
-void wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *, u_char);
-int wsemul_sun_output_control(struct wsemul_sun_emuldata *, u_char);
-int wsemul_sun_control(struct wsemul_sun_emuldata *, u_char);
+int wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *,
+ struct wsemul_inputstate *, int);
+int wsemul_sun_output_normal(struct wsemul_sun_emuldata *,
+ struct wsemul_inputstate *, int);
+int wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *,
+ struct wsemul_inputstate *);
+int wsemul_sun_output_control(struct wsemul_sun_emuldata *,
+ struct wsemul_inputstate *);
+int wsemul_sun_output_percent(struct wsemul_sun_emuldata *,
+ struct wsemul_inputstate *);
+int wsemul_sun_control(struct wsemul_sun_emuldata *,
+ struct wsemul_inputstate *);
int wsemul_sun_selectattribute(struct wsemul_sun_emuldata *, int, int, int,
long *, long *);
int wsemul_sun_scrollup(struct wsemul_sun_emuldata *, u_int);
@@ -141,12 +177,17 @@ wsemul_sun_init(struct wsemul_sun_emuldata *edp,
void
wsemul_sun_reset(struct wsemul_sun_emuldata *edp)
{
+ edp->flags = 0;
edp->state = SUN_EMUL_STATE_NORMAL;
edp->bkgdattr = edp->curattr = edp->defattr;
edp->attrflags = 0;
edp->fgcol = WSCOL_BLACK;
edp->bgcol = WSCOL_WHITE;
edp->scrolldist = 1;
+ edp->instate.inchar = 0;
+ edp->instate.mbleft = 0;
+ edp->kstate.inchar = 0;
+ edp->kstate.mbleft = 0;
}
void *
@@ -222,13 +263,13 @@ wsemul_sun_attach(int console, const struct wsscreen_descr *type, void *cookie,
}
int
-wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *edp, u_char c,
- int kernel)
+wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *edp,
+ struct wsemul_inputstate *instate, int kernel)
{
u_int n;
int rc = 0;
- switch (c) {
+ switch (instate->inchar) {
case ASCII_NUL:
default:
/* ignore */
@@ -298,13 +339,16 @@ wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *edp, u_char c,
}
int
-wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp, u_char c, int kernel)
+wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp,
+ struct wsemul_inputstate *instate, int kernel)
{
int rc;
+ u_int outchar;
+ (*edp->emulops->mapchar)(edp->emulcookie, instate->inchar, &outchar);
WSEMULOP(rc, edp, &edp->abortstate, putchar,
(edp->emulcookie, edp->crow, edp->ccol,
- c, kernel ? edp->kernattr : edp->curattr));
+ outchar, kernel ? edp->kernattr : edp->curattr));
if (rc != 0)
return rc;
@@ -327,34 +371,41 @@ wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp, u_char c, int kernel)
return 0;
}
-void
-wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *edp, u_char c)
+int
+wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- switch (c) {
+ switch (instate->inchar) {
case '[': /* continuation of multi-char sequence */
edp->nargs = 0;
bzero(edp->args, sizeof (edp->args));
edp->state = SUN_EMUL_STATE_CONTROL;
break;
-
+#ifdef HAVE_UTF8_SUPPORT
+ case '%':
+ edp->state = SUN_EMUL_STATE_PERCENT;
+ break;
+#endif
default:
#ifdef DEBUG
- printf("ESC%c unknown\n", c);
+ printf("ESC %x unknown\n", instate->inchar);
#endif
edp->state = SUN_EMUL_STATE_NORMAL; /* XXX is this wise? */
break;
}
+ return 0;
}
int
-wsemul_sun_control(struct wsemul_sun_emuldata *edp, u_char c)
+wsemul_sun_control(struct wsemul_sun_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
u_int n, src, dst;
int flags, fgcol, bgcol;
long attr, bkgdattr;
int rc = 0;
- switch (c) {
+ switch (instate->inchar) {
case '@': /* "Insert Character (ICH)" */
n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1);
src = edp->ccol;
@@ -541,12 +592,13 @@ setattr:
}
int
-wsemul_sun_output_control(struct wsemul_sun_emuldata *edp, u_char c)
+wsemul_sun_output_control(struct wsemul_sun_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
int oargs;
int rc;
- switch (c) {
+ switch (instate->inchar) {
case '0': case '1': case '2': case '3': case '4': /* argument digit */
case '5': case '6': case '7': case '8': case '9':
/*
@@ -559,7 +611,7 @@ wsemul_sun_output_control(struct wsemul_sun_emuldata *edp, u_char c)
edp->args[edp->nargs = SUN_EMUL_NARGS - 1] = 0;
}
edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
- (c - '0');
+ (instate->inchar - '0');
break;
case ';': /* argument terminator */
@@ -570,7 +622,7 @@ wsemul_sun_output_control(struct wsemul_sun_emuldata *edp, u_char c)
oargs = edp->nargs++;
if (edp->nargs > SUN_EMUL_NARGS)
edp->nargs = SUN_EMUL_NARGS;
- rc = wsemul_sun_control(edp, c);
+ rc = wsemul_sun_control(edp, instate);
if (rc != 0) {
/* undo nargs progress */
edp->nargs = oargs;
@@ -584,12 +636,31 @@ wsemul_sun_output_control(struct wsemul_sun_emuldata *edp, u_char c)
return 0;
}
+#ifdef HAVE_UTF8_SUPPORT
+int
+wsemul_sun_output_percent(struct wsemul_sun_emuldata *edp,
+ struct wsemul_inputstate *instate)
+{
+ switch (instate->inchar) {
+ case 'G':
+ edp->flags |= SUN_EMUL_FLAGS_UTF8;
+ edp->kstate.mbleft = edp->instate.mbleft = 0;
+ break;
+ case '@':
+ edp->flags &= ~SUN_EMUL_FLAGS_UTF8;
+ break;
+ }
+ edp->state = SUN_EMUL_STATE_NORMAL;
+ return 0;
+}
+#endif
+
u_int
wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
{
struct wsemul_sun_emuldata *edp = cookie;
+ struct wsemul_inputstate *instate;
u_int processed = 0;
- u_char c;
#ifdef HAVE_JUMP_SCROLL
int lines;
#endif
@@ -600,6 +671,8 @@ wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
panic("wsemul_sun_output: kernel output, not console");
#endif
+ instate = kernel ? &edp->kstate : &edp->instate;
+
switch (edp->abortstate.state) {
case ABORT_FAILED_CURSOR:
/*
@@ -622,7 +695,7 @@ wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
break;
}
- for (; count > 0; data++, count--) {
+ for (;;) {
#ifdef HAVE_JUMP_SCROLL
switch (edp->abortstate.state) {
case ABORT_FAILED_JUMP_SCROLL:
@@ -671,9 +744,18 @@ wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
wsemul_resume_abort(&edp->abortstate);
- c = *data;
- if (c < ' ') {
- rc = wsemul_sun_output_lowchars(edp, c, kernel);
+ if (wsemul_getchar(&data, &count, instate,
+#ifdef HAVE_UTF8_SUPPORT
+ (edp->state == SUN_EMUL_STATE_NORMAL && !kernel) ?
+ edp->flags & SUN_EMUL_FLAGS_UTF8 : 0
+#else
+ 0
+#endif
+ ) != 0)
+ break;
+
+ if (instate->inchar < ' ') {
+ rc = wsemul_sun_output_lowchars(edp, instate, kernel);
if (rc != 0)
break;
processed++;
@@ -681,7 +763,7 @@ wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
}
if (kernel) {
- rc = wsemul_sun_output_normal(edp, c, 1);
+ rc = wsemul_sun_output_normal(edp, instate, 1);
if (rc != 0)
break;
processed++;
@@ -690,21 +772,26 @@ wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
switch (edp->state) {
case SUN_EMUL_STATE_NORMAL:
- rc = wsemul_sun_output_normal(edp, c, 0);
+ rc = wsemul_sun_output_normal(edp, instate, 0);
break;
case SUN_EMUL_STATE_HAVEESC:
- wsemul_sun_output_haveesc(edp, c);
+ rc = wsemul_sun_output_haveesc(edp, instate);
break;
case SUN_EMUL_STATE_CONTROL:
- rc = wsemul_sun_output_control(edp, c);
+ rc = wsemul_sun_output_control(edp, instate);
+ break;
+#ifdef HAVE_UTF8_SUPPORT
+ case SUN_EMUL_STATE_PERCENT:
+ rc = wsemul_sun_output_percent(edp, instate);
break;
+#endif
default:
#ifdef DIAGNOSTIC
panic("wsemul_sun: invalid state %d", edp->state);
#else
/* try to recover, if things get screwed up... */
edp->state = SUN_EMUL_STATE_NORMAL;
- rc = wsemul_sun_output_normal(edp, c, 0);
+ rc = wsemul_sun_output_normal(edp, instate, 0);
#endif
break;
}
@@ -740,18 +827,26 @@ int
wsemul_sun_jump_scroll(struct wsemul_sun_emuldata *edp, const u_char *data,
u_int count, int kernel)
{
- u_char curchar;
u_int pos, lines;
+ struct wsemul_inputstate tmpstate;
lines = 0;
pos = edp->ccol;
- for (; count != 0; data++, count--) {
- curchar = *data;
- if (curchar == ASCII_FF ||
- curchar == ASCII_VT || curchar == ASCII_ESC)
+ tmpstate = kernel ? edp->kstate : edp->instate; /* structure copy */
+
+ while (wsemul_getchar(&data, &count, &tmpstate,
+#ifdef HAVE_UTF8_SUPPORT
+ kernel ? 0 : edp->flags & SUN_EMUL_FLAGS_UTF8
+#else
+ 0
+#endif
+ ) == 0) {
+ if (tmpstate.inchar == ASCII_FF ||
+ tmpstate.inchar == ASCII_VT ||
+ tmpstate.inchar == ASCII_ESC)
break;
- switch (curchar) {
+ switch (tmpstate.inchar) {
case ASCII_BS:
if (pos > 0)
pos--;
@@ -769,11 +864,11 @@ wsemul_sun_jump_scroll(struct wsemul_sun_emuldata *edp, const u_char *data,
default:
if (++pos >= edp->ncols) {
pos = 0;
- curchar = ASCII_LF;
+ tmpstate.inchar = ASCII_LF;
}
break;
}
- if (curchar == ASCII_LF) {
+ if (tmpstate.inchar == ASCII_LF) {
if (++lines >= edp->nrows - 1)
break;
}
@@ -849,7 +944,7 @@ wsemul_sun_selectattribute(struct wsemul_sun_emuldata *edp, int flags,
return (0);
}
-static const char *sun_fkeys[] = {
+static const u_char *sun_fkeys[] = {
"\033[224z", /* F1 */
"\033[225z",
"\033[226z",
@@ -864,7 +959,7 @@ static const char *sun_fkeys[] = {
"\033[235z", /* F12 */
};
-static const char *sun_lkeys[] = {
+static const u_char *sun_lkeys[] = {
"\033[207z", /* KS_Help */
NULL, /* KS_Execute */
"\033[200z", /* KS_Find */
@@ -880,13 +975,20 @@ static const char *sun_lkeys[] = {
};
int
-wsemul_sun_translate(void *cookie, keysym_t in, const char **out)
+wsemul_sun_translate(void *cookie, kbd_t layout, keysym_t in,
+ const u_char **out)
{
- static char c;
+ struct wsemul_sun_emuldata *edp = cookie;
+
+ if (KS_GROUP(in) == KS_GROUP_Ascii) {
+ *out = edp->translatebuf;
+ return (wsemul_utf8_translate(KS_VALUE(in), layout,
+ edp->translatebuf, edp->flags & SUN_EMUL_FLAGS_UTF8));
+ }
if (KS_GROUP(in) == KS_GROUP_Keypad && (in & 0x80) == 0) {
- c = in & 0xff; /* turn into ASCII */
- *out = &c;
+ edp->translatebuf[0] = in & 0xff; /* turn into ASCII */
+ *out = edp->translatebuf;
return (1);
}
diff --git a/sys/dev/wscons/wsemul_vt100.c b/sys/dev/wscons/wsemul_vt100.c
index ae6b918fc12..20ec8b12d57 100644
--- a/sys/dev/wscons/wsemul_vt100.c
+++ b/sys/dev/wscons/wsemul_vt100.c
@@ -1,7 +1,23 @@
-/* $OpenBSD: wsemul_vt100.c,v 1.30 2013/10/18 13:54:09 miod Exp $ */
+/* $OpenBSD: wsemul_vt100.c,v 1.31 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft Exp $ */
/*
+ * Copyright (c) 2007, 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice, this permission notice, and the disclaimer below
+ * appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
* Copyright (c) 1998
* Matthias Drochner. All rights reserved.
*
@@ -64,10 +80,14 @@ void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
const struct wsscreen_descr *, void *, int, int, long);
int wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *,
const u_char *, u_int, int);
-int wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *, u_char, int);
-int wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *, u_char, int);
+int wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
+ struct wsemul_inputstate *, int);
+int wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
+ struct wsemul_inputstate *, int);
int wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
-typedef int vt100_handler(struct wsemul_vt100_emuldata *, u_char);
+
+typedef int vt100_handler(struct wsemul_vt100_emuldata *, struct
+ wsemul_inputstate *);
vt100_handler
wsemul_vt100_output_esc,
wsemul_vt100_output_csi,
@@ -80,7 +100,8 @@ vt100_handler
wsemul_vt100_output_string,
wsemul_vt100_output_string_esc,
wsemul_vt100_output_dcs,
- wsemul_vt100_output_dcs_dollar;
+ wsemul_vt100_output_dcs_dollar,
+ wsemul_vt100_output_esc_percent;
#define VT100_EMUL_STATE_NORMAL 0 /* normal processing */
#define VT100_EMUL_STATE_ESC 1 /* got ESC */
@@ -95,6 +116,7 @@ vt100_handler
#define VT100_EMUL_STATE_STRING_ESC 10 /* waiting for ST, got ESC */
#define VT100_EMUL_STATE_DCS 11 /* got DCS (ESC P) */
#define VT100_EMUL_STATE_DCS_DOLLAR 12 /* got DCS<p>$ */
+#define VT100_EMUL_STATE_ESC_PERCENT 13 /* got ESC% */
vt100_handler *vt100_output[] = {
wsemul_vt100_output_esc,
@@ -109,6 +131,7 @@ vt100_handler *vt100_output[] = {
wsemul_vt100_output_string_esc,
wsemul_vt100_output_dcs,
wsemul_vt100_output_dcs_dollar,
+ wsemul_vt100_output_esc_percent,
};
void
@@ -313,10 +336,11 @@ wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
*/
int
-wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp, u_char c,
- int kernel)
+wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate, int kernel)
{
u_int *ct, dc;
+ u_char c;
int oldsschartab = edp->sschartab;
int rc = 0;
@@ -329,17 +353,25 @@ wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp, u_char c,
edp->flags &= ~VTFL_LASTCHAR;
}
- if (c & 0x80) {
- c &= 0x7f;
- ct = edp->chartab_G[edp->chartab1];
- } else {
- if (edp->sschartab) {
- ct = edp->chartab_G[edp->sschartab];
- edp->sschartab = 0;
- } else
- ct = edp->chartab_G[edp->chartab0];
+#ifdef HAVE_UTF8_SUPPORT
+ if (edp->flags & VTFL_UTF8) {
+ (*edp->emulops->mapchar)(edp->emulcookie, instate->inchar, &dc);
+ } else
+#endif
+ {
+ c = instate->inchar & 0xff;
+ if (c & 0x80) {
+ c &= 0x7f;
+ ct = edp->chartab_G[edp->chartab1];
+ } else {
+ if (edp->sschartab) {
+ ct = edp->chartab_G[edp->sschartab];
+ edp->sschartab = 0;
+ } else
+ ct = edp->chartab_G[edp->chartab0];
+ }
+ dc = ct ? ct[c] : c;
}
- dc = (ct ? ct[c] : c);
if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT) {
WSEMULOP(rc, edp, &edp->abortstate, copycols,
@@ -371,13 +403,13 @@ wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp, u_char c,
}
int
-wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp, u_char c,
- int kernel)
+wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate, int kernel)
{
u_int n;
int rc = 0;
- switch (c) {
+ switch (instate->inchar) {
case ASCII_NUL:
default:
/* ignore */
@@ -413,9 +445,11 @@ wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp, u_char c,
edp->ccol = n;
break;
case ASCII_SO: /* LS1 */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab0 = 1;
break;
case ASCII_SI: /* LS0 */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab0 = 0;
break;
case ASCII_ESC:
@@ -471,13 +505,14 @@ wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp, u_char c,
}
int
-wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
u_int newstate = VT100_EMUL_STATE_NORMAL;
int rc = 0;
int i;
- switch (c) {
+ switch (instate->inchar) {
case '[': /* CSI */
edp->nargs = 0;
memset(edp->args, 0, sizeof (edp->args));
@@ -530,24 +565,31 @@ wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
edp->tabs[edp->ccol] = 1;
break;
case '~': /* LS1R */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab1 = 1;
break;
case 'n': /* LS2 */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab0 = 2;
break;
case '}': /* LS2R */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab1 = 2;
break;
case 'o': /* LS3 */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab0 = 3;
break;
case '|': /* LS3R */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab1 = 3;
break;
case 'N': /* SS2 */
+ edp->flags &= ~VTFL_UTF8;
edp->sschartab = 2;
break;
case 'O': /* SS3 */
+ edp->flags &= ~VTFL_UTF8;
edp->sschartab = 3;
break;
case 'M': /* RI */
@@ -571,11 +613,11 @@ wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
edp->ccol = edp->crow = 0;
break;
case '(': case ')': case '*': case '+': /* SCS */
- edp->designating = c - '(';
+ edp->designating = instate->inchar - '(';
newstate = VT100_EMUL_STATE_SCS94;
break;
case '-': case '.': case '/': /* SCS */
- edp->designating = c - '-' + 1;
+ edp->designating = instate->inchar - '-' + 1;
newstate = VT100_EMUL_STATE_SCS96;
break;
case '#':
@@ -592,9 +634,12 @@ wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
break;
case '<': /* exit VT52 mode - ignored */
break;
+ case '%': /* UTF-8 encoding sequences */
+ newstate = VT100_EMUL_STATE_ESC_PERCENT;
+ break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC%c unknown\n", c);
+ printf("ESC %x unknown\n", instate->inchar);
#endif
break;
}
@@ -610,33 +655,40 @@ wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
u_int newstate = VT100_EMUL_STATE_NORMAL;
- switch (c) {
+ switch (instate->inchar) {
case '%': /* probably DEC supplemental graphic */
newstate = VT100_EMUL_STATE_SCS94_PERCENT;
break;
case 'A': /* british / national */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = edp->nrctab;
break;
case 'B': /* ASCII */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = 0;
break;
case '<': /* user preferred supplemental */
/* XXX not really "user" preferred */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = edp->isolatin1tab;
break;
case '0': /* DEC special graphic */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = edp->decgraphtab;
break;
case '>': /* DEC tech */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = edp->dectechtab;
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC%c%c unknown\n", edp->designating + '(', c);
+ printf("ESC%c %x unknown\n", edp->designating + '(',
+ instate->inchar);
#endif
break;
}
@@ -646,16 +698,19 @@ wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- switch (c) {
+ switch (instate->inchar) {
case '5': /* DEC supplemental graphic */
/* XXX there are differences */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = edp->isolatin1tab;
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
+ printf("ESC%c%% %x unknown\n", edp->designating + '(',
+ instate->inchar);
#endif
break;
}
@@ -665,16 +720,18 @@ wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
u_int newstate = VT100_EMUL_STATE_NORMAL;
int nrc;
- switch (c) {
+ switch (instate->inchar) {
case '%': /* probably portuguese */
newstate = VT100_EMUL_STATE_SCS96_PERCENT;
break;
case 'A': /* ISO-latin-1 supplemental */
+ edp->flags &= ~VTFL_UTF8;
edp->chartab_G[edp->designating] = edp->isolatin1tab;
break;
case '4': /* dutch */
@@ -712,7 +769,8 @@ setnrc:
/* else FALLTHROUGH */
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
+ printf("ESC%c %x unknown\n", edp->designating + '-' - 1,
+ instate->inchar);
#endif
break;
}
@@ -722,16 +780,18 @@ setnrc:
}
int
-wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- switch (c) {
+ switch (instate->inchar) {
case '6': /* portuguese */
if (vt100_setnrc(edp, 8) == 0)
break;
/* else FALLTHROUGH */
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC%c%%%c unknown\n", edp->designating + '-' - 1, c);
+ printf("ESC%c%% %x unknown\n", edp->designating + '-' - 1,
+ instate->inchar);
#endif
break;
}
@@ -741,18 +801,19 @@ wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- switch (c) {
+ switch (instate->inchar) {
case 'F': /* 7-bit controls */
case 'G': /* 8-bit controls */
#ifdef VT100_PRINTNOTIMPL
- printf("ESC<SPC>%c ignored\n", c);
+ printf("ESC<SPC> %x ignored\n", instate->inchar);
#endif
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC<SPC>%c unknown\n", c);
+ printf("ESC<SPC> %x unknown\n", instate->inchar);
#endif
break;
}
@@ -762,19 +823,27 @@ wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- if (edp->dcstype && edp->dcspos < DCS_MAXLEN)
- edp->dcsarg[edp->dcspos++] = c;
+ if (edp->dcstype && edp->dcspos < DCS_MAXLEN) {
+ if (instate->inchar & ~0xff) {
+#ifdef VT100_PRINTUNKNOWN
+ printf("unknown char %x in DCS\n", instate->inchar);
+#endif
+ } else
+ edp->dcsarg[edp->dcspos++] = (char)instate->inchar;
+ }
edp->state = VT100_EMUL_STATE_STRING;
return 0;
}
int
-wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- if (c == '\\') { /* ST complete */
+ if (instate->inchar == '\\') { /* ST complete */
wsemul_vt100_handle_dcs(edp);
edp->state = VT100_EMUL_STATE_NORMAL;
} else
@@ -784,18 +853,19 @@ wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
u_int newstate = VT100_EMUL_STATE_DCS;
- switch (c) {
+ switch (instate->inchar) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* argument digit */
if (edp->nargs > VT100_EMUL_NARGS - 1)
break;
edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
- (c - '0');
+ (instate->inchar - '0');
break;
case ';': /* argument terminator */
edp->nargs++;
@@ -809,7 +879,7 @@ wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
edp->nargs = VT100_EMUL_NARGS;
}
newstate = VT100_EMUL_STATE_STRING;
- switch (c) {
+ switch (instate->inchar) {
case '$':
newstate = VT100_EMUL_STATE_DCS_DOLLAR;
break;
@@ -818,12 +888,13 @@ wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
/* 'u' must follow - need another state */
case '|': /* DECUDK program F6..F20 */
#ifdef VT100_PRINTNOTIMPL
- printf("DCS%c ignored\n", c);
+ printf("DCS%c ignored\n", (char)instate->inchar);
#endif
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
+ printf("DCS %x (%d, %d) unknown\n", instate->inchar,
+ ARG(0), ARG(1));
#endif
break;
}
@@ -834,13 +905,14 @@ wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
- switch (c) {
+ switch (instate->inchar) {
case 'p': /* DECRSTS terminal state restore */
case 'q': /* DECRQSS control function request */
#ifdef VT100_PRINTNOTIMPL
- printf("DCS$%c ignored\n", c);
+ printf("DCS$%c ignored\n", (char)instate->inchar);
#endif
break;
case 't': /* DECRSPS restore presentation state */
@@ -865,7 +937,8 @@ wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp, u_char c)
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
+ printf("DCS$ %x (%d, %d) unknown\n",
+ instate->inchar, ARG(0), ARG(1));
#endif
break;
}
@@ -875,12 +948,37 @@ wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_esc_percent(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
+{
+ switch (instate->inchar) {
+#ifdef HAVE_UTF8_SUPPORT
+ case 'G':
+ edp->flags |= VTFL_UTF8;
+ edp->kstate.mbleft = edp->instate.mbleft = 0;
+ break;
+ case '@':
+ edp->flags &= ~VTFL_UTF8;
+ break;
+#endif
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC% %x unknown\n", instate->inchar);
+#endif
+ break;
+ }
+ edp->state = VT100_EMUL_STATE_NORMAL;
+ return 0;
+}
+
+int
+wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
int i;
int rc = 0;
- switch (c) {
+ switch (instate->inchar) {
case '5': /* DECSWL single width, single height */
if (edp->dblwid != NULL && edp->dw != 0) {
for (i = 0; i < edp->ncols / 2; i++) {
@@ -936,7 +1034,7 @@ wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp, u_char c)
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("ESC#%c unknown\n", c);
+ printf("ESC# %x unknown\n", instate->inchar);
#endif
break;
}
@@ -949,33 +1047,34 @@ wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp, u_char c)
}
int
-wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
u_int newstate = VT100_EMUL_STATE_CSI;
int oargs;
int rc = 0;
- switch (c) {
+ switch (instate->inchar) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* argument digit */
if (edp->nargs > VT100_EMUL_NARGS - 1)
break;
edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
- (c - '0');
+ (instate->inchar - '0');
break;
case ';': /* argument terminator */
edp->nargs++;
break;
case '?': /* DEC specific */
case '>': /* DA query */
- edp->modif1 = c;
+ edp->modif1 = (char)instate->inchar;
break;
case '!':
case '"':
case '$':
case '&':
- edp->modif2 = c;
+ edp->modif2 = (char)instate->inchar;
break;
default: /* end of escape sequence */
oargs = edp->nargs++;
@@ -985,7 +1084,7 @@ wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp, u_char c)
#endif
edp->nargs = VT100_EMUL_NARGS;
}
- rc = wsemul_vt100_handle_csi(edp, c);
+ rc = wsemul_vt100_handle_csi(edp, instate);
if (rc != 0) {
edp->nargs = oargs;
return rc;
@@ -1005,8 +1104,8 @@ u_int
wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
{
struct wsemul_vt100_emuldata *edp = cookie;
+ struct wsemul_inputstate *instate;
u_int processed = 0;
- u_char c;
#ifdef HAVE_JUMP_SCROLL
int lines;
#endif
@@ -1017,6 +1116,8 @@ wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
panic("wsemul_vt100_output: kernel output, not console");
#endif
+ instate = kernel ? &edp->kstate : &edp->instate;
+
switch (edp->abortstate.state) {
case ABORT_FAILED_CURSOR:
/*
@@ -1042,7 +1143,7 @@ wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
break;
}
- for (; count > 0; data++, count--) {
+ for (;;) {
#ifdef HAVE_JUMP_SCROLL
switch (edp->abortstate.state) {
case ABORT_FAILED_JUMP_SCROLL:
@@ -1090,17 +1191,27 @@ wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
wsemul_resume_abort(&edp->abortstate);
- c = *data;
- if ((c & 0x7f) < 0x20) {
- rc = wsemul_vt100_output_c0c1(edp, c, kernel);
+ if (wsemul_getchar(&data, &count, instate,
+#ifdef HAVE_UTF8_SUPPORT
+ (edp->state == VT100_EMUL_STATE_NORMAL && !kernel) ?
+ edp->flags & VTFL_UTF8 : 0
+#else
+ 0
+#endif
+ ) != 0)
+ break;
+
+ if (!(instate->inchar & ~0xff) &&
+ (instate->inchar & 0x7f) < 0x20) {
+ rc = wsemul_vt100_output_c0c1(edp, instate, kernel);
if (rc != 0)
break;
processed++;
- continue;
- }
-
+ continue;
+ }
+
if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
- rc = wsemul_vt100_output_normal(edp, c, kernel);
+ rc = wsemul_vt100_output_normal(edp, instate, kernel);
if (rc != 0)
break;
processed++;
@@ -1110,7 +1221,7 @@ wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
if (edp->state > nitems(vt100_output))
panic("wsemul_vt100: invalid state %d", edp->state);
#endif
- rc = vt100_output[edp->state - 1](edp, c);
+ rc = vt100_output[edp->state - 1](edp, instate);
if (rc != 0)
break;
processed++;
@@ -1147,23 +1258,30 @@ int
wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *edp, const u_char *data,
u_int count, int kernel)
{
- u_char curchar;
+ struct wsemul_inputstate tmpstate;
u_int pos, lines;
lines = 0;
pos = edp->ccol;
- for (; count != 0; data++, count--) {
- curchar = *data;
+ tmpstate = kernel ? edp->kstate : edp->instate; /* structure copy */
+
+ while (wsemul_getchar(&data, &count, &tmpstate,
+#ifdef HAVE_UTF8_SUPPORT
+ kernel ? 0 : edp->flags & VTFL_UTF8
+#else
+ 0
+#endif
+ ) == 0) {
/*
* Only char causing a transition from
* VT100_EMUL_STATE_NORMAL to another state, for now.
* Revisit this if this changes...
*/
- if (curchar == ASCII_ESC)
+ if (tmpstate.inchar == ASCII_ESC)
break;
if (ISSET(edp->flags, VTFL_DECAWM))
- switch (curchar) {
+ switch (tmpstate.inchar) {
case ASCII_BS:
if (pos > 0)
pos--;
@@ -1184,18 +1302,19 @@ wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *edp, const u_char *data,
}
break;
default:
- if ((curchar & 0x7f) < 0x20)
+ if (!(tmpstate.inchar & ~0xff) &&
+ (tmpstate.inchar & 0x7f) < 0x20)
break;
if (pos++ >= NCOLS) {
pos = 0;
- curchar = ASCII_LF;
+ tmpstate.inchar = ASCII_LF;
}
break;
}
- if (curchar == ASCII_LF ||
- curchar == ASCII_VT ||
- curchar == ASCII_FF) {
+ if (tmpstate.inchar == ASCII_LF ||
+ tmpstate.inchar == ASCII_VT ||
+ tmpstate.inchar == ASCII_FF) {
if (++lines >= edp->scrreg_nrows - 1)
break;
}
diff --git a/sys/dev/wscons/wsemul_vt100_chars.c b/sys/dev/wscons/wsemul_vt100_chars.c
index 373a34ab4fd..521a91d9dcd 100644
--- a/sys/dev/wscons/wsemul_vt100_chars.c
+++ b/sys/dev/wscons/wsemul_vt100_chars.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100_chars.c,v 1.7 2009/12/10 16:35:28 oga Exp $ */
+/* $OpenBSD: wsemul_vt100_chars.c,v 1.8 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_vt100_chars.c,v 1.4 1999/02/20 18:20:02 drochner Exp $ */
/*
@@ -29,6 +29,8 @@
#include <sys/param.h>
#include <sys/systm.h>
+
+#include <dev/wscons/wscons_features.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wscons/wsksymvar.h>
diff --git a/sys/dev/wscons/wsemul_vt100_keys.c b/sys/dev/wscons/wsemul_vt100_keys.c
index e90f918fc70..d94618b4bbf 100644
--- a/sys/dev/wscons/wsemul_vt100_keys.c
+++ b/sys/dev/wscons/wsemul_vt100_keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100_keys.c,v 1.6 2013/04/14 19:40:12 miod Exp $ */
+/* $OpenBSD: wsemul_vt100_keys.c,v 1.7 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_vt100_keys.c,v 1.3 1999/04/22 20:06:02 mycroft Exp $ */
/*
@@ -30,6 +30,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <dev/wscons/wscons_features.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wscons/wsksymvar.h>
@@ -37,7 +38,7 @@
#include <dev/wscons/wsemulvar.h>
#include <dev/wscons/wsemul_vt100var.h>
-static const char *vt100_fkeys[] = {
+static const u_char *vt100_fkeys[] = {
"\033[11~", /* F1 */
"\033[12~",
"\033[13~", /* F1-F5 normally don't send codes */
@@ -64,14 +65,14 @@ static const char *vt100_fkeys[] = {
"\033[38~"
};
-static const char *vt100_pfkeys[] = {
+static const u_char *vt100_pfkeys[] = {
"\033OP", /* PF1 */
"\033OQ",
"\033OR",
"\033OS", /* PF4 */
};
-static const char *vt100_numpad[] = {
+static const u_char *vt100_numpad[] = {
"\033Op", /* KP 0 */
"\033Oq", /* KP 1 */
"\033Or", /* KP 2 */
@@ -85,10 +86,16 @@ static const char *vt100_numpad[] = {
};
int
-wsemul_vt100_translate(void *cookie, keysym_t in, const char **out)
+wsemul_vt100_translate(void *cookie, kbd_t layout, keysym_t in,
+ const u_char **out)
{
struct wsemul_vt100_emuldata *edp = cookie;
- static char c;
+
+ if (KS_GROUP(in) == KS_GROUP_Ascii) {
+ *out = edp->translatebuf;
+ return (wsemul_utf8_translate(KS_VALUE(in), layout,
+ edp->translatebuf, edp->flags & VTFL_UTF8));
+ }
if (in >= KS_f1 && in <= KS_f24) {
*out = vt100_fkeys[in - KS_f1];
@@ -135,8 +142,8 @@ wsemul_vt100_translate(void *cookie, keysym_t in, const char **out)
}
} else {
if (!(in & 0x80)) {
- c = in & 0xff; /* turn into ASCII */
- *out = &c;
+ edp->translatebuf[0] = in & 0xff; /* turn into ASCII */
+ *out = edp->translatebuf;
return (1);
}
}
diff --git a/sys/dev/wscons/wsemul_vt100_subr.c b/sys/dev/wscons/wsemul_vt100_subr.c
index ecb03a0549d..5f463bb5998 100644
--- a/sys/dev/wscons/wsemul_vt100_subr.c
+++ b/sys/dev/wscons/wsemul_vt100_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100_subr.c,v 1.18 2013/06/11 18:15:55 deraadt Exp $ */
+/* $OpenBSD: wsemul_vt100_subr.c,v 1.19 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_vt100_subr.c,v 1.7 2000/04/28 21:56:16 mycroft Exp $ */
/*
@@ -30,6 +30,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <dev/wscons/wscons_features.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsksymvar.h>
#include <dev/wscons/wsdisplayvar.h>
@@ -214,11 +215,18 @@ wsemul_vt100_el(struct wsemul_vt100_emuldata *edp, int arg)
* handle commands after CSI (ESC[)
*/
int
-wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp, u_char c)
+wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp,
+ struct wsemul_inputstate *instate)
{
int n, help, flags, fgcol, bgcol;
long attr, bkgdattr;
+ u_char c;
int rc = 0;
+
+ if (instate->inchar >= 0x100)
+ c = 0x00; /* cause the switch below to end in default: */
+ else
+ c = (u_char)instate->inchar;
#define A3(a, b, c) (((a) << 16) | ((b) << 8) | (c))
switch (A3(edp->modif1, edp->modif2, c)) {
@@ -666,7 +674,8 @@ wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp, u_char c)
break;
default:
#ifdef VT100_PRINTUNKNOWN
- printf("CSI%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
+ printf("CSI %x (%d, %d) unknown\n",
+ instate->inchar, ARG(0), ARG(1));
#endif
break;
}
@@ -793,7 +802,10 @@ wsemul_vt100_handle_dcs(struct wsemul_vt100_emuldata *edp)
}
break;
default:
- panic("wsemul_vt100_handle_dcs: bad type %d", edp->dcstype);
+#ifdef VT100_PRINTUNKNOWN
+ printf("wsemul_vt100_handle_dcs: bad type %d\n", edp->dcstype);
+#endif
+ break;
}
edp->dcstype = 0;
}
diff --git a/sys/dev/wscons/wsemul_vt100var.h b/sys/dev/wscons/wsemul_vt100var.h
index 3926eb734fc..460913387c5 100644
--- a/sys/dev/wscons/wsemul_vt100var.h
+++ b/sys/dev/wscons/wsemul_vt100var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100var.h,v 1.9 2009/09/05 14:49:20 miod Exp $ */
+/* $OpenBSD: wsemul_vt100var.h,v 1.10 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemul_vt100var.h,v 1.5 2000/04/28 21:56:17 mycroft Exp $ */
/*
@@ -54,6 +54,7 @@ struct wsemul_vt100_emuldata {
#define VTFL_CURSORON 0x040
#define VTFL_NATCHARSET 0x080 /* national replacement charset mode */
#define VTFL_SAVEDCURS 0x100 /* we have a saved cursor state */
+#define VTFL_UTF8 0x200 /* utf-8 character set */
long curattr, bkgdattr; /* currently used attribute */
int attrflags, fgcol, bgcol; /* properties of curattr */
u_int scrreg_startrow;
@@ -87,6 +88,15 @@ struct wsemul_vt100_emuldata {
int savedattrflags, savedfgcol, savedbgcol;
int savedchartab0, savedchartab1;
u_int *savedchartab_G[4];
+
+ struct wsemul_inputstate instate; /* userland input state */
+ struct wsemul_inputstate kstate; /* kernel input state */
+
+#ifdef HAVE_UTF8_SUPPORT
+ u_char translatebuf[6];
+#else
+ u_char translatebuf[1];
+#endif
};
/* some useful utility macros */
@@ -133,10 +143,11 @@ int wsemul_vt100_scrollup(struct wsemul_vt100_emuldata *, int);
int wsemul_vt100_scrolldown(struct wsemul_vt100_emuldata *, int);
int wsemul_vt100_ed(struct wsemul_vt100_emuldata *, int);
int wsemul_vt100_el(struct wsemul_vt100_emuldata *, int);
-int wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *, u_char);
+int wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *,
+ struct wsemul_inputstate *);
void wsemul_vt100_handle_dcs(struct wsemul_vt100_emuldata *);
-int wsemul_vt100_translate(void *cookie, keysym_t, const char **);
+int wsemul_vt100_translate(void *cookie, kbd_t, keysym_t, const u_char **);
void vt100_initchartables(struct wsemul_vt100_emuldata *);
int vt100_setnrc(struct wsemul_vt100_emuldata *, int);
diff --git a/sys/dev/wscons/wsemulvar.h b/sys/dev/wscons/wsemulvar.h
index 77a9fd38fed..5d70a02ff9c 100644
--- a/sys/dev/wscons/wsemulvar.h
+++ b/sys/dev/wscons/wsemulvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemulvar.h,v 1.14 2013/10/18 14:17:23 miod Exp $ */
+/* $OpenBSD: wsemulvar.h,v 1.15 2013/10/18 22:06:41 miod Exp $ */
/* $NetBSD: wsemulvar.h,v 1.6 1999/01/17 15:46:15 drochner Exp $ */
/*
@@ -68,11 +68,20 @@ struct wsemul_ops {
void *(*attach)(int, const struct wsscreen_descr *, void *,
int, int, void *, long);
u_int (*output)(void *, const u_char *, u_int, int);
- int (*translate)(void *, keysym_t, const char **);
+ int (*translate)(void *, kbd_t, keysym_t, const u_char **);
void (*detach)(void *, u_int *, u_int *);
void (*reset)(void *, enum wsemul_resetops);
};
+/*
+ * Structure carrying the state of multi-byte character sequences
+ * decoding.
+ */
+struct wsemul_inputstate {
+ u_int32_t inchar; /* character being reconstructed */
+ u_int mbleft; /* multibyte bytes left until char complete */
+};
+
extern const struct wsemul_ops wsemul_dumb_ops;
extern const struct wsemul_ops wsemul_sun_ops;
extern const struct wsemul_ops wsemul_vt100_ops;
@@ -87,6 +96,19 @@ void wsdisplay_emulbell(void *v);
void wsdisplay_emulinput(void *v, const u_char *, u_int);
/*
+ * Get characters from an input stream and update the input state.
+ * Processing stops when the stream is empty, or a complete character
+ * sequence has been recognized, in which case it returns zero.
+ */
+int wsemul_getchar(const u_char **, u_int *, struct wsemul_inputstate *,
+ int);
+
+/*
+ * Keysym to UTF-8 sequence translation function.
+ */
+int wsemul_utf8_translate(u_int32_t, kbd_t, u_char *, int);
+
+/*
* emulops failure abort/recovery state
*
* The tty layer needs a character output to be atomic. Since this may
diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c
index 0fafe4d48c8..0cc9e91d46d 100644
--- a/sys/dev/wscons/wskbd.c
+++ b/sys/dev/wscons/wskbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wskbd.c,v 1.73 2013/10/18 13:54:09 miod Exp $ */
+/* $OpenBSD: wskbd.c,v 1.74 2013/10/18 22:06:42 miod Exp $ */
/* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */
/*
@@ -511,6 +511,7 @@ wskbd_repeat(void *v)
/* deliver keys */
if (sc->sc_displaydv != NULL)
wsdisplay_kbdinput(sc->sc_displaydv,
+ sc->id->t_keymap->layout,
sc->id->t_symbols, sc->sc_repeating);
} else {
/* queue event */
@@ -629,6 +630,7 @@ wskbd_input(struct device *dev, u_int type, int value)
}
#endif
wsdisplay_kbdinput(sc->sc_displaydv,
+ sc->id->t_keymap->layout,
sc->id->t_symbols, num);
}
diff --git a/sys/dev/wscons/wsksymdef.h b/sys/dev/wscons/wsksymdef.h
index 5c8d58978e4..b1abb46f393 100644
--- a/sys/dev/wscons/wsksymdef.h
+++ b/sys/dev/wscons/wsksymdef.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsksymdef.h,v 1.34 2011/04/05 19:12:13 miod Exp $ */
+/* $OpenBSD: wsksymdef.h,v 1.35 2013/10/18 22:06:42 miod Exp $ */
/* $NetBSD: wsksymdef.h,v 1.34.4.1 2000/07/07 09:49:54 hannken Exp $ */
/*-
@@ -36,7 +36,6 @@
/*
* Keysymbols encoded as 16-bit Unicode. Special symbols
* are encoded in the private area (0xe000 - 0xf8ff).
- * Currently only ISO Latin-1 subset is supported.
*
* This file is parsed from userland. Encode keysyms as:
*
@@ -251,10 +250,10 @@
#define KS_thorn 0xfe
#define KS_ydiaeresis 0xff
-#define KS_Odoubleacute 0x150
-#define KS_odoubleacute 0x151
-#define KS_Udoubleacute 0x170
-#define KS_udoubleacute 0x171
+#define KS_Odoubleacute 0x0150
+#define KS_odoubleacute 0x0151
+#define KS_Udoubleacute 0x0170
+#define KS_udoubleacute 0x0171
/*
* Group Dead (dead accents)
@@ -269,216 +268,217 @@
#define KS_dead_cedilla 0x0327
/*
- * Group Cyrillic (koi8-r)
+ * Group Cyrillic
*/
-#define KS_Cyrillic_A 0xe1
-#define KS_Cyrillic_BE 0xe2
-#define KS_Cyrillic_VE 0xf7
-#define KS_Cyrillic_GE 0xe7
-#define KS_Cyrillic_DE 0xe4
-#define KS_Cyrillic_IE 0xe5
-#define KS_Cyrillic_YO 0xb3
-#define KS_Cyrillic_ZHE 0xf6
-#define KS_Cyrillic_ZE 0xfa
-#define KS_Cyrillic_I 0xe9
-#define KS_Cyrillic_ISHORT 0xea
-#define KS_Cyrillic_IUKR 0xb6
-#define KS_Cyrillic_YI 0xb7
-#define KS_Cyrillic_KA 0xeb
-#define KS_Cyrillic_EL 0xec
-#define KS_Cyrillic_EM 0xed
-#define KS_Cyrillic_EN 0xee
-#define KS_Cyrillic_O 0xef
-#define KS_Cyrillic_PE 0xf0
-#define KS_Cyrillic_ER 0xf2
-#define KS_Cyrillic_ES 0xf3
-#define KS_Cyrillic_TE 0xf4
-#define KS_Cyrillic_U 0xf5
-#define KS_Cyrillic_EF 0xe6
-#define KS_Cyrillic_HA 0xe8
-#define KS_Cyrillic_TSE 0xe3
-#define KS_Cyrillic_CHE 0xfe
-#define KS_Cyrillic_SHA 0xfb
-#define KS_Cyrillic_SCHA 0xfd
-#define KS_Cyrillic_HSIGHN 0xff
-#define KS_Cyrillic_YERU 0xf9
-#define KS_Cyrillic_SSIGHN 0xf8
-#define KS_Cyrillic_E 0xfc
-#define KS_Cyrillic_YU 0xe0
-#define KS_Cyrillic_YA 0xf1
-#define KS_Cyrillic_a 0xc1
-#define KS_Cyrillic_be 0xc2
-#define KS_Cyrillic_ve 0xd7
-#define KS_Cyrillic_ge 0xc7
-#define KS_Cyrillic_de 0xc4
-#define KS_Cyrillic_ie 0xc5
-#define KS_Cyrillic_yo 0xa3
-#define KS_Cyrillic_zhe 0xd6
-#define KS_Cyrillic_ze 0xda
-#define KS_Cyrillic_i 0xc9
-#define KS_Cyrillic_ishort 0xca
-#define KS_Cyrillic_iukr 0xa6
-#define KS_Cyrillic_yi 0xa7
-#define KS_Cyrillic_ka 0xcb
-#define KS_Cyrillic_el 0xcc
-#define KS_Cyrillic_em 0xcd
-#define KS_Cyrillic_en 0xce
-#define KS_Cyrillic_o 0xcf
-#define KS_Cyrillic_pe 0xd0
-#define KS_Cyrillic_er 0xd2
-#define KS_Cyrillic_es 0xd3
-#define KS_Cyrillic_te 0xd4
-#define KS_Cyrillic_u 0xd5
-#define KS_Cyrillic_ef 0xc6
-#define KS_Cyrillic_ha 0xc8
-#define KS_Cyrillic_tse 0xc3
-#define KS_Cyrillic_che 0xde
-#define KS_Cyrillic_sha 0xdb
-#define KS_Cyrillic_scha 0xdd
-#define KS_Cyrillic_hsighn 0xdf
-#define KS_Cyrillic_yeru 0xd9
-#define KS_Cyrillic_ssighn 0xd8
-#define KS_Cyrillic_e 0xdc
-#define KS_Cyrillic_yu 0xc0
-#define KS_Cyrillic_ya 0xd1
-#define KS_Cyrillic_gheukr 0xad
-#define KS_Cyrillic_GHEUKR 0xbd
-#define KS_Cyrillic_yeukr 0xa4
-#define KS_Cyrillic_YEUKR 0xb4
+#define KS_Cyrillic_YO 0x0401
+#define KS_Cyrillic_YEUKR 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_GE 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_ISHORT 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_SCHA 0x0429
+#define KS_Cyrillic_HSIGHN 0x042a
+#define KS_Cyrillic_YERU 0x042b
+#define KS_Cyrillic_SSIGHN 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_ge 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_ishort 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_scha 0x0449
+#define KS_Cyrillic_hsighn 0x044a
+#define KS_Cyrillic_yeru 0x044b
+#define KS_Cyrillic_ssighn 0x044c
+#define KS_Cyrillic_e 0x044d
+#define KS_Cyrillic_yu 0x044e
+#define KS_Cyrillic_ya 0x044f
+#define KS_Cyrillic_yo 0x0451
+#define KS_Cyrillic_yeukr 0x0454
+#define KS_Cyrillic_iukr 0x0456
+#define KS_Cyrillic_yi 0x0457
+#define KS_Cyrillic_GHEUKR 0x0490
+#define KS_Cyrillic_gheukr 0x0491
/*
- * Group Latin-2 (iso8859-2)
+ * Group Latin-2
*/
-#define KS_L2_Aogonek 0xa1
-#define KS_L2_breve 0xa2
-#define KS_L2_Lstroke 0xa3
-#define KS_L2_Lcaron 0xa5
-#define KS_L2_Sacute 0xa6
-#define KS_L2_Scaron 0xa9
-#define KS_L2_Scedilla 0xaa
-#define KS_L2_Tcaron 0xab
-#define KS_L2_Zacute 0xac
-#define KS_L2_Zcaron 0xae
-#define KS_L2_Zdotabove 0xaf
-#define KS_L2_aogonek 0xb1
-#define KS_L2_ogonek 0xb2
-#define KS_L2_lstroke 0xb3
-#define KS_L2_lcaron 0xb5
-#define KS_L2_sacute 0xb6
-#define KS_L2_caron 0xb7
-#define KS_L2_scaron 0xb9
-#define KS_L2_scedilla 0xba
-#define KS_L2_tcaron 0xbb
-#define KS_L2_zacute 0xbc
-#define KS_L2_dblacute 0xbd
-#define KS_L2_zcaron 0xbe
-#define KS_L2_zdotabove 0xbf
-#define KS_L2_Racute 0xc0
-#define KS_L2_Abreve 0xc3
-#define KS_L2_Lacute 0xc5
-#define KS_L2_Cacute 0xc6
-#define KS_L2_Ccaron 0xc8
-#define KS_L2_Eogonek 0xca
-#define KS_L2_Ecaron 0xcc
-#define KS_L2_Dcaron 0xcf
-#define KS_L2_Dstroke 0xd0
-#define KS_L2_Nacute 0xd1
-#define KS_L2_Ncaron 0xd2
-#define KS_L2_Odoubleacute 0xd5
-#define KS_L2_Rcaron 0xd8
-#define KS_L2_Uring 0xd9
-#define KS_L2_Udoubleacute 0xdb
-#define KS_L2_Tcedilla 0xde
-#define KS_L2_racute 0xe0
-#define KS_L2_abreve 0xe3
-#define KS_L2_lacute 0xe5
-#define KS_L2_cacute 0xe6
-#define KS_L2_ccaron 0xe8
-#define KS_L2_eogonek 0xea
-#define KS_L2_ecaron 0xec
-#define KS_L2_dcaron 0xef
-#define KS_L2_dstroke 0xf0
-#define KS_L2_nacute 0xf1
-#define KS_L2_odoubleacute 0xf5
-#define KS_L2_rcaron 0xf8
-#define KS_L2_uring 0xf9
-#define KS_L2_udoubleacute 0xfb
-#define KS_L2_tcedilla 0xfe
-#define KS_L2_dotabove 0xff
+#define KS_L2_Abreve 0x0102
+#define KS_L2_abreve 0x0103
+#define KS_L2_Aogonek 0x0104
+#define KS_L2_aogonek 0x0105
+#define KS_L2_Cacute 0x0106
+#define KS_L2_cacute 0x0107
+#define KS_L2_Ccaron 0x010c
+#define KS_L2_ccaron 0x010d
+#define KS_L2_Dcaron 0x010e
+#define KS_L2_dcaron 0x010f
+#define KS_L2_Dstroke 0x0110
+#define KS_L2_dstroke 0x0111
+#define KS_L2_Eogonek 0x0118
+#define KS_L2_eogonek 0x0119
+#define KS_L2_Ecaron 0x011a
+#define KS_L2_ecaron 0x011b
+#define KS_L2_Lacute 0x0139
+#define KS_L2_lacute 0x013a
+#define KS_L2_Lcaron 0x013d
+#define KS_L2_lcaron 0x013e
+#define KS_L2_Lstroke 0x0141
+#define KS_L2_lstroke 0x0142
+#define KS_L2_Nacute 0x0143
+#define KS_L2_nacute 0x0144
+#define KS_L2_Ncaron 0x0147
+#define KS_L2_Odoubleacute 0x0150
+#define KS_L2_odoubleacute 0x0151
+#define KS_L2_Racute 0x0154
+#define KS_L2_racute 0x0155
+#define KS_L2_Rcaron 0x0158
+#define KS_L2_rcaron 0x0159
+#define KS_L2_Sacute 0x015a
+#define KS_L2_sacute 0x015b
+#define KS_L2_Scedilla 0x015e
+#define KS_L2_scedilla 0x015f
+#define KS_L2_Scaron 0x0160
+#define KS_L2_scaron 0x0161
+#define KS_L2_Tcedilla 0x0162
+#define KS_L2_tcedilla 0x0163
+#define KS_L2_Tcaron 0x0164
+#define KS_L2_tcaron 0x0165
+#define KS_L2_Uring 0x016e
+#define KS_L2_uring 0x016f
+#define KS_L2_Udoubleacute 0x0170
+#define KS_L2_udoubleacute 0x0171
+#define KS_L2_Zacute 0x0179
+#define KS_L2_zacute 0x017a
+#define KS_L2_Zdotabove 0x017b
+#define KS_L2_zdotabove 0x017c
+#define KS_L2_Zcaron 0x017d
+#define KS_L2_zcaron 0x017e
+
+#define KS_L2_caron 0x02c7
+#define KS_L2_breve 0x02d8
+#define KS_L2_dotabove 0x02d9
+#define KS_L2_ogonek 0x02db
+#define KS_L2_dblacute 0x02dd
/*
- * Group Latin-5 (iso8859-9)
+ * Group Latin-5
*/
-#define KS_L5_Gbreve 0xd0
-#define KS_L5_Idotabove 0xdd
-#define KS_L5_Scedilla 0xde
-#define KS_L5_gbreve 0xf0
-#define KS_L5_idotless 0xfd
-#define KS_L5_scedilla 0xfe
+#define KS_L5_Gbreve 0x011e
+#define KS_L5_gbreve 0x011f
+#define KS_L5_Idotabove 0x0130
+#define KS_L5_idotless 0x0131
+#define KS_L5_Scedilla 0x015e
+#define KS_L5_scedilla 0x015f
/*
- * Group Latin-7 (iso8859-13)
+ * Group Latin-7
*/
-#define KS_L7_rightdblquot 0xa1
-#define KS_L7_dbllow9quot 0xa5
-#define KS_L7_Ostroke 0xa8
-#define KS_L7_Rcedilla 0xaa
-#define KS_L7_AE 0xaf
-#define KS_L7_leftdblquot 0xb4
-#define KS_L7_ostroke 0xb8
-#define KS_L7_rcedilla 0xba
-#define KS_L7_ae 0xbf
-#define KS_L7_Aogonek 0xc0
-#define KS_L7_Iogonek 0xc1
-#define KS_L7_Amacron 0xc2
-#define KS_L7_Cacute 0xc3
-#define KS_L7_Eogonek 0xc6
-#define KS_L7_Emacron 0xc7
-#define KS_L7_Ccaron 0xc8
-#define KS_L7_Zacute 0xca
-#define KS_L7_Edot 0xcb
-#define KS_L7_Gcedilla 0xcc
-#define KS_L7_Kcedilla 0xcd
-#define KS_L7_Imacron 0xce
-#define KS_L7_Lcedilla 0xcf
-#define KS_L7_Scaron 0xd0
-#define KS_L7_Nacute 0xd1
-#define KS_L7_Ncedilla 0xd2
-#define KS_L7_Omacron 0xd4
-#define KS_L7_Uogonek 0xd8
-#define KS_L7_Lstroke 0xd9
-#define KS_L7_Sacute 0xda
-#define KS_L7_Umacron 0xdb
-#define KS_L7_Zdot 0xdd
-#define KS_L7_Zcaron 0xde
-#define KS_L7_aogonek 0xe0
-#define KS_L7_iogonek 0xe1
-#define KS_L7_amacron 0xe2
-#define KS_L7_cacute 0xe3
-#define KS_L7_eogonek 0xe6
-#define KS_L7_emacron 0xe7
-#define KS_L7_ccaron 0xe8
-#define KS_L7_zacute 0xea
-#define KS_L7_edot 0xeb
-#define KS_L7_gcedilla 0xec
-#define KS_L7_kcedilla 0xed
-#define KS_L7_imacron 0xee
-#define KS_L7_lcedilla 0xef
-#define KS_L7_scaron 0xf0
-#define KS_L7_nacute 0xf1
-#define KS_L7_ncedilla 0xf2
-#define KS_L7_omacron 0xf4
-#define KS_L7_uogonek 0xf8
-#define KS_L7_lstroke 0xf9
-#define KS_L7_sacute 0xfa
-#define KS_L7_umacron 0xfb
-#define KS_L7_zdot 0xfd
-#define KS_L7_zcaron 0xfe
-#define KS_L7_rightsnglquot 0xff
+#define KS_L7_rightdblquot 0x201d
+#define KS_L7_dbllow9quot 0x201e
+#define KS_L7_Ostroke 0x00d8
+#define KS_L7_Rcedilla 0x0156
+#define KS_L7_AE 0x00c0
+#define KS_L7_leftdblquot 0x201c
+#define KS_L7_ostroke 0x00f8
+#define KS_L7_rcedilla 0x0157
+#define KS_L7_ae 0x00e6
+#define KS_L7_Aogonek 0x0104
+#define KS_L7_Iogonek 0x012e
+#define KS_L7_Amacron 0x0100
+#define KS_L7_Cacute 0x0106
+#define KS_L7_Eogonek 0x0118
+#define KS_L7_Emacron 0x0112
+#define KS_L7_Ccaron 0x010c
+#define KS_L7_Zacute 0x0179
+#define KS_L7_Edot 0x0116
+#define KS_L7_Gcedilla 0x0122
+#define KS_L7_Kcedilla 0x0136
+#define KS_L7_Imacron 0x012a
+#define KS_L7_Lcedilla 0x013b
+#define KS_L7_Scaron 0x0160
+#define KS_L7_Nacute 0x0143
+#define KS_L7_Ncedilla 0x0145
+#define KS_L7_Omacron 0x014c
+#define KS_L7_Uogonek 0x0172
+#define KS_L7_Lstroke 0x0141
+#define KS_L7_Sacute 0x015a
+#define KS_L7_Umacron 0x016a
+#define KS_L7_Zdot 0x017b
+#define KS_L7_Zcaron 0x017d
+#define KS_L7_aogonek 0x0105
+#define KS_L7_iogonek 0x012f
+#define KS_L7_amacron 0x0101
+#define KS_L7_cacute 0x0107
+#define KS_L7_eogonek 0x0119
+#define KS_L7_emacron 0x0113
+#define KS_L7_ccaron 0x010d
+#define KS_L7_zacute 0x017a
+#define KS_L7_edot 0x0117
+#define KS_L7_gcedilla 0x0123
+#define KS_L7_kcedilla 0x0137
+#define KS_L7_imacron 0x012b
+#define KS_L7_lcedilla 0x013c
+#define KS_L7_scaron 0x0161
+#define KS_L7_nacute 0x0144
+#define KS_L7_ncedilla 0x0146
+#define KS_L7_omacron 0x014d
+#define KS_L7_uogonek 0x0173
+#define KS_L7_lstroke 0x0142
+#define KS_L7_sacute 0x015b
+#define KS_L7_umacron 0x016b
+#define KS_L7_zdot 0x017c
+#define KS_L7_zcaron 0x017e
+#define KS_L7_rightsnglquot 0x2019
/*
* Group 1 (modifiers)