charsets.c revision 0bd37d32
10bd37d32Smrg/* $XTermId: charsets.c,v 1.42 2011/09/11 14:40:17 tom Exp $ */
2d522f475Smrg
30bd37d32Smrg/*
40bd37d32Smrg * Copyright 1998-2009,2011 by Thomas E. Dickey
50bd37d32Smrg *
60bd37d32Smrg *                         All Rights Reserved
70bd37d32Smrg *
80bd37d32Smrg * Permission is hereby granted, free of charge, to any person obtaining a
90bd37d32Smrg * copy of this software and associated documentation files (the
100bd37d32Smrg * "Software"), to deal in the Software without restriction, including
110bd37d32Smrg * without limitation the rights to use, copy, modify, merge, publish,
120bd37d32Smrg * distribute, sublicense, and/or sell copies of the Software, and to
130bd37d32Smrg * permit persons to whom the Software is furnished to do so, subject to
140bd37d32Smrg * the following conditions:
150bd37d32Smrg *
160bd37d32Smrg * The above copyright notice and this permission notice shall be included
170bd37d32Smrg * in all copies or substantial portions of the Software.
180bd37d32Smrg *
190bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
200bd37d32Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
210bd37d32Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
220bd37d32Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
230bd37d32Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
240bd37d32Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
250bd37d32Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
260bd37d32Smrg *
270bd37d32Smrg * Except as contained in this notice, the name(s) of the above copyright
280bd37d32Smrg * holders shall not be used in advertising or otherwise to promote the
290bd37d32Smrg * sale, use or other dealings in this Software without prior written
300bd37d32Smrg * authorization.
310bd37d32Smrg *
320bd37d32Smrg */
33d522f475Smrg
34d522f475Smrg#include <xterm.h>
35d522f475Smrg#include <data.h>
36d522f475Smrg#include <fontutils.h>
37d522f475Smrg
38d522f475Smrg#include <X11/keysym.h>
39d522f475Smrg
40d522f475Smrg/*
41d522f475Smrg * This module performs translation as needed to support the DEC VT220 national
42d522f475Smrg * replacement character sets.  We assume that xterm's font is based on the ISO
43d522f475Smrg * 8859-1 (Latin 1) character set, which is almost the same as the DEC
44d522f475Smrg * multinational character set.  Glyph positions 0-31 have to be the DEC
45d522f475Smrg * graphic characters, though.
46d522f475Smrg *
47d522f475Smrg * References:
48d522f475Smrg *	"VT220 Programmer Pocket Guide" EK-VT220-HR-002 (2nd ed., 1984), which
49d522f475Smrg *		contains character charts for the national character sets.
50d522f475Smrg *	"VT330/VT340 Programmer Reference Manual Volume 1: Text Programming"
51d522f475Smrg *		EK-VT3XX-TP-001 (1st ed, 1987), which contains a table (2-1)
52d522f475Smrg *		listing the glyphs which are mapped from the multinational
53d522f475Smrg *		character set to the national character set.
54d522f475Smrg *
55d522f475Smrg * The latter reference, though easier to read, has a few errors and omissions.
56d522f475Smrg */
57d522f475Smrg
58d522f475Smrg/*
59d522f475Smrg * Translate an input keysym to the corresponding NRC keysym.
60d522f475Smrg */
612eaa94a1Schristosunsigned
622eaa94a1SchristosxtermCharSetIn(unsigned code, int charset)
63d522f475Smrg{
642eaa94a1Schristos#define MAP(to, from) case from: code = to; break
652eaa94a1Schristos
662eaa94a1Schristos    if (code >= 128 && code < 256) {
672eaa94a1Schristos	switch (charset) {
682eaa94a1Schristos	case 'A':		/* United Kingdom set (or Latin 1)      */
692eaa94a1Schristos	    if (code == XK_sterling)
702eaa94a1Schristos		code = 0x23;
712eaa94a1Schristos	    code &= 0x7f;
722eaa94a1Schristos	    break;
73d522f475Smrg
74d522f475Smrg#if OPT_XMC_GLITCH
752eaa94a1Schristos	case '?':
76d522f475Smrg#endif
772eaa94a1Schristos	case '1':		/* Alternate Character ROM standard characters */
782eaa94a1Schristos	case '2':		/* Alternate Character ROM special graphics */
792eaa94a1Schristos	case 'B':		/* ASCII set                            */
802eaa94a1Schristos	    break;
812eaa94a1Schristos
822eaa94a1Schristos	case '0':		/* special graphics (line drawing)      */
832eaa94a1Schristos	    break;
842eaa94a1Schristos
852eaa94a1Schristos	case '4':		/* Dutch */
862eaa94a1Schristos	    switch (code) {
872eaa94a1Schristos		MAP(0x23, XK_sterling);
882eaa94a1Schristos		MAP(0x40, XK_threequarters);
892eaa94a1Schristos		MAP(0x5b, XK_ydiaeresis);
902eaa94a1Schristos		MAP(0x5c, XK_onehalf);
912eaa94a1Schristos		MAP(0x5d, XK_bar);	/* glyph is not ISO-8859-1 */
922eaa94a1Schristos		MAP(0x7b, XK_diaeresis);
932eaa94a1Schristos		MAP(0x7c, XK_f);	/* glyph is not ISO-8859-1 */
942eaa94a1Schristos		MAP(0x7d, XK_onequarter);
952eaa94a1Schristos		MAP(0x7e, XK_acute);
962eaa94a1Schristos	    }
972eaa94a1Schristos	    break;
982eaa94a1Schristos
992eaa94a1Schristos	case 'C':
1002eaa94a1Schristos	case '5':		/* Finnish */
1012eaa94a1Schristos	    switch (code) {
1022eaa94a1Schristos		MAP(0x5b, XK_Adiaeresis);
1032eaa94a1Schristos		MAP(0x5c, XK_Odiaeresis);
1042eaa94a1Schristos		MAP(0x5d, XK_Aring);
1052eaa94a1Schristos		MAP(0x5e, XK_Udiaeresis);
1062eaa94a1Schristos		MAP(0x60, XK_eacute);
1072eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
1082eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
1092eaa94a1Schristos		MAP(0x7d, XK_aring);
1102eaa94a1Schristos		MAP(0x7e, XK_udiaeresis);
1112eaa94a1Schristos	    }
1122eaa94a1Schristos	    break;
1132eaa94a1Schristos
1142eaa94a1Schristos	case 'R':		/* French */
1152eaa94a1Schristos	    switch (code) {
1162eaa94a1Schristos		MAP(0x23, XK_sterling);
1172eaa94a1Schristos		MAP(0x40, XK_agrave);
1182eaa94a1Schristos		MAP(0x5b, XK_degree);
1192eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
1202eaa94a1Schristos		MAP(0x5d, XK_section);
1212eaa94a1Schristos		MAP(0x7b, XK_eacute);
1222eaa94a1Schristos		MAP(0x7c, XK_ugrave);
1232eaa94a1Schristos		MAP(0x7d, XK_egrave);
1242eaa94a1Schristos		MAP(0x7e, XK_diaeresis);
1252eaa94a1Schristos	    }
1262eaa94a1Schristos	    break;
1272eaa94a1Schristos
1282eaa94a1Schristos	case 'Q':		/* French Canadian */
1292eaa94a1Schristos	    switch (code) {
1302eaa94a1Schristos		MAP(0x40, XK_agrave);
1312eaa94a1Schristos		MAP(0x5b, XK_acircumflex);
1322eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
1332eaa94a1Schristos		MAP(0x5d, XK_ecircumflex);
1342eaa94a1Schristos		MAP(0x5e, XK_icircumflex);
1352eaa94a1Schristos		MAP(0x60, XK_ocircumflex);
1362eaa94a1Schristos		MAP(0x7b, XK_eacute);
1372eaa94a1Schristos		MAP(0x7c, XK_ugrave);
1382eaa94a1Schristos		MAP(0x7d, XK_egrave);
1392eaa94a1Schristos		MAP(0x7e, XK_ucircumflex);
1402eaa94a1Schristos	    }
1412eaa94a1Schristos	    break;
1422eaa94a1Schristos
1432eaa94a1Schristos	case 'K':		/* German */
1442eaa94a1Schristos	    switch (code) {
1452eaa94a1Schristos		MAP(0x40, XK_section);
1462eaa94a1Schristos		MAP(0x5b, XK_Adiaeresis);
1472eaa94a1Schristos		MAP(0x5c, XK_Odiaeresis);
1482eaa94a1Schristos		MAP(0x5d, XK_Udiaeresis);
1492eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
1502eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
1512eaa94a1Schristos		MAP(0x7d, XK_udiaeresis);
1522eaa94a1Schristos		MAP(0x7e, XK_ssharp);
1532eaa94a1Schristos	    }
1542eaa94a1Schristos	    break;
1552eaa94a1Schristos
1562eaa94a1Schristos	case 'Y':		/* Italian */
1572eaa94a1Schristos	    switch (code) {
1582eaa94a1Schristos		MAP(0x23, XK_sterling);
1592eaa94a1Schristos		MAP(0x40, XK_section);
1602eaa94a1Schristos		MAP(0x5b, XK_degree);
1612eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
1622eaa94a1Schristos		MAP(0x5d, XK_eacute);
1632eaa94a1Schristos		MAP(0x60, XK_ugrave);
1642eaa94a1Schristos		MAP(0x7b, XK_agrave);
1652eaa94a1Schristos		MAP(0x7c, XK_ograve);
1662eaa94a1Schristos		MAP(0x7d, XK_egrave);
1672eaa94a1Schristos		MAP(0x7e, XK_igrave);
1682eaa94a1Schristos	    }
1692eaa94a1Schristos	    break;
1702eaa94a1Schristos
1712eaa94a1Schristos	case 'E':
1722eaa94a1Schristos	case '6':		/* Norwegian/Danish */
1732eaa94a1Schristos	    switch (code) {
1742eaa94a1Schristos		MAP(0x40, XK_Adiaeresis);
1752eaa94a1Schristos		MAP(0x5b, XK_AE);
1762eaa94a1Schristos		MAP(0x5c, XK_Ooblique);
1772eaa94a1Schristos		MAP(0x5d, XK_Aring);
1782eaa94a1Schristos		MAP(0x5e, XK_Udiaeresis);
1792eaa94a1Schristos		MAP(0x60, XK_adiaeresis);
1802eaa94a1Schristos		MAP(0x7b, XK_ae);
1812eaa94a1Schristos		MAP(0x7c, XK_oslash);
1822eaa94a1Schristos		MAP(0x7d, XK_aring);
1832eaa94a1Schristos		MAP(0x7e, XK_udiaeresis);
1842eaa94a1Schristos	    }
1852eaa94a1Schristos	    break;
1862eaa94a1Schristos
1872eaa94a1Schristos	case 'Z':		/* Spanish */
1882eaa94a1Schristos	    switch (code) {
1892eaa94a1Schristos		MAP(0x23, XK_sterling);
1902eaa94a1Schristos		MAP(0x40, XK_section);
1912eaa94a1Schristos		MAP(0x5b, XK_exclamdown);
1922eaa94a1Schristos		MAP(0x5c, XK_Ntilde);
1932eaa94a1Schristos		MAP(0x5d, XK_questiondown);
1942eaa94a1Schristos		MAP(0x7b, XK_degree);
1952eaa94a1Schristos		MAP(0x7c, XK_ntilde);
1962eaa94a1Schristos		MAP(0x7d, XK_ccedilla);
1972eaa94a1Schristos	    }
1982eaa94a1Schristos	    break;
1992eaa94a1Schristos
2002eaa94a1Schristos	case 'H':
2012eaa94a1Schristos	case '7':		/* Swedish */
2022eaa94a1Schristos	    switch (code) {
2032eaa94a1Schristos		MAP(0x40, XK_Eacute);
2042eaa94a1Schristos		MAP(0x5b, XK_Adiaeresis);
2052eaa94a1Schristos		MAP(0x5c, XK_Odiaeresis);
2062eaa94a1Schristos		MAP(0x5d, XK_Aring);
2072eaa94a1Schristos		MAP(0x5e, XK_Udiaeresis);
2082eaa94a1Schristos		MAP(0x60, XK_eacute);
2092eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
2102eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
2112eaa94a1Schristos		MAP(0x7d, XK_aring);
2122eaa94a1Schristos		MAP(0x7e, XK_udiaeresis);
2132eaa94a1Schristos	    }
2142eaa94a1Schristos	    break;
2152eaa94a1Schristos
2162eaa94a1Schristos	case '=':		/* Swiss */
2172eaa94a1Schristos	    switch (code) {
2182eaa94a1Schristos		MAP(0x23, XK_ugrave);
2192eaa94a1Schristos		MAP(0x40, XK_agrave);
2202eaa94a1Schristos		MAP(0x5b, XK_eacute);
2212eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
2222eaa94a1Schristos		MAP(0x5d, XK_ecircumflex);
2232eaa94a1Schristos		MAP(0x5e, XK_icircumflex);
2242eaa94a1Schristos		MAP(0x5f, XK_egrave);
2252eaa94a1Schristos		MAP(0x60, XK_ocircumflex);
2262eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
2272eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
2282eaa94a1Schristos		MAP(0x7d, XK_udiaeresis);
2292eaa94a1Schristos		MAP(0x7e, XK_ucircumflex);
2302eaa94a1Schristos	    }
2312eaa94a1Schristos	    break;
2322eaa94a1Schristos
2332eaa94a1Schristos	default:		/* any character sets we don't recognize */
2342eaa94a1Schristos	    break;
235d522f475Smrg	}
2362eaa94a1Schristos	code &= 0x7f;		/* NRC in any case is 7-bit */
2372eaa94a1Schristos    }
2382eaa94a1Schristos    return code;
2392eaa94a1Schristos#undef MAP
240d522f475Smrg}
241d522f475Smrg
242d522f475Smrg/*
243d522f475Smrg * Translate a string to the display form.  This assumes the font has the
244d522f475Smrg * DEC graphic characters in cells 0-31, and otherwise is ISO-8859-1.
245d522f475Smrg */
2462eaa94a1Schristosint
2472eaa94a1SchristosxtermCharSetOut(XtermWidget xw, IChar * buf, IChar * ptr, int leftset)
248d522f475Smrg{
2492eaa94a1Schristos    IChar *s;
2502eaa94a1Schristos    TScreen *screen = TScreenOf(xw);
2512eaa94a1Schristos    int count = 0;
2522eaa94a1Schristos    int rightset = screen->gsets[(int) (screen->curgr)];
2532eaa94a1Schristos
2542eaa94a1Schristos#define MAP(from, to) case from: chr = to; break
2552eaa94a1Schristos
2562eaa94a1Schristos    TRACE(("CHARSET GL=%c(G%d) GR=%c(G%d) SS%d\n\t%s\n",
2572eaa94a1Schristos	   leftset, screen->curgl,
2582eaa94a1Schristos	   rightset, screen->curgr,
2592eaa94a1Schristos	   screen->curss,
2602eaa94a1Schristos	   visibleIChar(buf, (unsigned) (ptr - buf))));
2612eaa94a1Schristos
2622eaa94a1Schristos    for (s = buf; s < ptr; ++s) {
2632eaa94a1Schristos	int eight = CharOf(E2A(*s));
2642eaa94a1Schristos	int seven = eight & 0x7f;
2652eaa94a1Schristos	int cs = (eight >= 128) ? rightset : leftset;
2662eaa94a1Schristos	int chr = eight;
2672eaa94a1Schristos
2682eaa94a1Schristos	count++;
2692eaa94a1Schristos#if OPT_WIDE_CHARS
2702eaa94a1Schristos	/*
2712eaa94a1Schristos	 * This is only partly right - prevent inadvertant remapping of
2722eaa94a1Schristos	 * the replacement character and other non-8bit codes into bogus
2732eaa94a1Schristos	 * 8bit codes.
2742eaa94a1Schristos	 */
2752eaa94a1Schristos	if (screen->utf8_mode) {
2762eaa94a1Schristos	    if (*s > 255)
2772eaa94a1Schristos		continue;
2782eaa94a1Schristos	}
2792eaa94a1Schristos#endif
2802eaa94a1Schristos	switch (cs) {
2812eaa94a1Schristos	case 'A':		/* United Kingdom set (or Latin 1)      */
2822eaa94a1Schristos	    if ((xw->flags & NATIONAL)
2832eaa94a1Schristos		|| (screen->vtXX_level <= 1)) {
2842eaa94a1Schristos		if (chr == 0x23) {
2852eaa94a1Schristos#if OPT_WIDE_CHARS
2862eaa94a1Schristos		    chr = (screen->utf8_mode
2872eaa94a1Schristos			   ? 0xa3
2882eaa94a1Schristos			   : XTERM_POUND);
2892eaa94a1Schristos#else
2902eaa94a1Schristos		    chr = XTERM_POUND;
2912eaa94a1Schristos#endif
2922eaa94a1Schristos		}
2932eaa94a1Schristos	    } else {
2942eaa94a1Schristos		chr = (seven | 0x80);
2952eaa94a1Schristos	    }
2962eaa94a1Schristos	    break;
297d522f475Smrg
298d522f475Smrg#if OPT_XMC_GLITCH
2992eaa94a1Schristos	case '?':
300d522f475Smrg#endif
3012eaa94a1Schristos	case '1':		/* Alternate Character ROM standard characters */
3022eaa94a1Schristos	case '2':		/* Alternate Character ROM special graphics */
3032eaa94a1Schristos	case 'B':		/* ASCII set                            */
3042eaa94a1Schristos	    break;
305d522f475Smrg
3062eaa94a1Schristos	case '0':		/* special graphics (line drawing)      */
3072eaa94a1Schristos	    if (seven > 0x5f && seven <= 0x7e) {
308d522f475Smrg#if OPT_WIDE_CHARS
3092eaa94a1Schristos		if (screen->utf8_mode)
310956cc18dSsnj		    chr = (int) dec2ucs((unsigned) (seven - 0x5f));
3112eaa94a1Schristos		else
312d522f475Smrg#endif
3132eaa94a1Schristos		    chr = seven - 0x5f;
3142eaa94a1Schristos	    } else {
3152eaa94a1Schristos		chr = seven;
3162eaa94a1Schristos	    }
3172eaa94a1Schristos	    break;
3182eaa94a1Schristos
3192eaa94a1Schristos	case '4':		/* Dutch */
3202eaa94a1Schristos	    switch (chr = seven) {
3212eaa94a1Schristos		MAP(0x23, XK_sterling);
3222eaa94a1Schristos		MAP(0x40, XK_threequarters);
3232eaa94a1Schristos		MAP(0x5b, XK_ydiaeresis);
3242eaa94a1Schristos		MAP(0x5c, XK_onehalf);
3252eaa94a1Schristos		MAP(0x5d, XK_bar);
3262eaa94a1Schristos		MAP(0x7b, XK_diaeresis);
3272eaa94a1Schristos		MAP(0x7c, XK_f);
3282eaa94a1Schristos		MAP(0x7d, XK_onequarter);
3292eaa94a1Schristos		MAP(0x7e, XK_acute);
3302eaa94a1Schristos	    }
3312eaa94a1Schristos	    break;
3322eaa94a1Schristos
3332eaa94a1Schristos	case 'C':
3342eaa94a1Schristos	case '5':		/* Finnish */
3352eaa94a1Schristos	    switch (chr = seven) {
3362eaa94a1Schristos		MAP(0x5b, XK_Adiaeresis);
3372eaa94a1Schristos		MAP(0x5c, XK_Odiaeresis);
3382eaa94a1Schristos		MAP(0x5d, XK_Aring);
3392eaa94a1Schristos		MAP(0x5e, XK_Udiaeresis);
3402eaa94a1Schristos		MAP(0x60, XK_eacute);
3412eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
3422eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
3432eaa94a1Schristos		MAP(0x7d, XK_aring);
3442eaa94a1Schristos		MAP(0x7e, XK_udiaeresis);
3452eaa94a1Schristos	    }
3462eaa94a1Schristos	    break;
3472eaa94a1Schristos
3482eaa94a1Schristos	case 'R':		/* French */
3492eaa94a1Schristos	    switch (chr = seven) {
3502eaa94a1Schristos		MAP(0x23, XK_sterling);
3512eaa94a1Schristos		MAP(0x40, XK_agrave);
3522eaa94a1Schristos		MAP(0x5b, XK_degree);
3532eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
3542eaa94a1Schristos		MAP(0x5d, XK_section);
3552eaa94a1Schristos		MAP(0x7b, XK_eacute);
3562eaa94a1Schristos		MAP(0x7c, XK_ugrave);
3572eaa94a1Schristos		MAP(0x7d, XK_egrave);
3582eaa94a1Schristos		MAP(0x7e, XK_diaeresis);
3592eaa94a1Schristos	    }
3602eaa94a1Schristos	    break;
3612eaa94a1Schristos
3622eaa94a1Schristos	case 'Q':		/* French Canadian */
3632eaa94a1Schristos	    switch (chr = seven) {
3642eaa94a1Schristos		MAP(0x40, XK_agrave);
3652eaa94a1Schristos		MAP(0x5b, XK_acircumflex);
3662eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
3672eaa94a1Schristos		MAP(0x5d, XK_ecircumflex);
3682eaa94a1Schristos		MAP(0x5e, XK_icircumflex);
3692eaa94a1Schristos		MAP(0x60, XK_ocircumflex);
3702eaa94a1Schristos		MAP(0x7b, XK_eacute);
3712eaa94a1Schristos		MAP(0x7c, XK_ugrave);
3722eaa94a1Schristos		MAP(0x7d, XK_egrave);
3732eaa94a1Schristos		MAP(0x7e, XK_ucircumflex);
3742eaa94a1Schristos	    }
3752eaa94a1Schristos	    break;
3762eaa94a1Schristos
3772eaa94a1Schristos	case 'K':		/* German */
3782eaa94a1Schristos	    switch (chr = seven) {
3792eaa94a1Schristos		MAP(0x40, XK_section);
3802eaa94a1Schristos		MAP(0x5b, XK_Adiaeresis);
3812eaa94a1Schristos		MAP(0x5c, XK_Odiaeresis);
3822eaa94a1Schristos		MAP(0x5d, XK_Udiaeresis);
3832eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
3842eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
3852eaa94a1Schristos		MAP(0x7d, XK_udiaeresis);
3862eaa94a1Schristos		MAP(0x7e, XK_ssharp);
3872eaa94a1Schristos	    }
3882eaa94a1Schristos	    break;
3892eaa94a1Schristos
3902eaa94a1Schristos	case 'Y':		/* Italian */
3912eaa94a1Schristos	    switch (chr = seven) {
3922eaa94a1Schristos		MAP(0x23, XK_sterling);
3932eaa94a1Schristos		MAP(0x40, XK_section);
3942eaa94a1Schristos		MAP(0x5b, XK_degree);
3952eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
3962eaa94a1Schristos		MAP(0x5d, XK_eacute);
3972eaa94a1Schristos		MAP(0x60, XK_ugrave);
3982eaa94a1Schristos		MAP(0x7b, XK_agrave);
3992eaa94a1Schristos		MAP(0x7c, XK_ograve);
4002eaa94a1Schristos		MAP(0x7d, XK_egrave);
4012eaa94a1Schristos		MAP(0x7e, XK_igrave);
4022eaa94a1Schristos	    }
4032eaa94a1Schristos	    break;
4042eaa94a1Schristos
4052eaa94a1Schristos	case 'E':
4062eaa94a1Schristos	case '6':		/* Norwegian/Danish */
4072eaa94a1Schristos	    switch (chr = seven) {
4082eaa94a1Schristos		MAP(0x40, XK_Adiaeresis);
4092eaa94a1Schristos		MAP(0x5b, XK_AE);
4102eaa94a1Schristos		MAP(0x5c, XK_Ooblique);
4112eaa94a1Schristos		MAP(0x5d, XK_Aring);
4122eaa94a1Schristos		MAP(0x5e, XK_Udiaeresis);
4132eaa94a1Schristos		MAP(0x60, XK_adiaeresis);
4142eaa94a1Schristos		MAP(0x7b, XK_ae);
4152eaa94a1Schristos		MAP(0x7c, XK_oslash);
4162eaa94a1Schristos		MAP(0x7d, XK_aring);
4172eaa94a1Schristos		MAP(0x7e, XK_udiaeresis);
4182eaa94a1Schristos	    }
4192eaa94a1Schristos	    break;
4202eaa94a1Schristos
4212eaa94a1Schristos	case 'Z':		/* Spanish */
4222eaa94a1Schristos	    switch (chr = seven) {
4232eaa94a1Schristos		MAP(0x23, XK_sterling);
4242eaa94a1Schristos		MAP(0x40, XK_section);
4252eaa94a1Schristos		MAP(0x5b, XK_exclamdown);
4262eaa94a1Schristos		MAP(0x5c, XK_Ntilde);
4272eaa94a1Schristos		MAP(0x5d, XK_questiondown);
4282eaa94a1Schristos		MAP(0x7b, XK_degree);
4292eaa94a1Schristos		MAP(0x7c, XK_ntilde);
4302eaa94a1Schristos		MAP(0x7d, XK_ccedilla);
4312eaa94a1Schristos	    }
4322eaa94a1Schristos	    break;
4332eaa94a1Schristos
4342eaa94a1Schristos	case 'H':
4352eaa94a1Schristos	case '7':		/* Swedish */
4362eaa94a1Schristos	    switch (chr = seven) {
4372eaa94a1Schristos		MAP(0x40, XK_Eacute);
4382eaa94a1Schristos		MAP(0x5b, XK_Adiaeresis);
4392eaa94a1Schristos		MAP(0x5c, XK_Odiaeresis);
4402eaa94a1Schristos		MAP(0x5d, XK_Aring);
4412eaa94a1Schristos		MAP(0x5e, XK_Udiaeresis);
4422eaa94a1Schristos		MAP(0x60, XK_eacute);
4432eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
4442eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
4452eaa94a1Schristos		MAP(0x7d, XK_aring);
4462eaa94a1Schristos		MAP(0x7e, XK_udiaeresis);
4472eaa94a1Schristos	    }
4482eaa94a1Schristos	    break;
4492eaa94a1Schristos
4502eaa94a1Schristos	case '=':		/* Swiss */
4512eaa94a1Schristos	    switch (chr = seven) {
4522eaa94a1Schristos		MAP(0x23, XK_ugrave);
4532eaa94a1Schristos		MAP(0x40, XK_agrave);
4542eaa94a1Schristos		MAP(0x5b, XK_eacute);
4552eaa94a1Schristos		MAP(0x5c, XK_ccedilla);
4562eaa94a1Schristos		MAP(0x5d, XK_ecircumflex);
4572eaa94a1Schristos		MAP(0x5e, XK_icircumflex);
4582eaa94a1Schristos		MAP(0x5f, XK_egrave);
4592eaa94a1Schristos		MAP(0x60, XK_ocircumflex);
4602eaa94a1Schristos		MAP(0x7b, XK_adiaeresis);
4612eaa94a1Schristos		MAP(0x7c, XK_odiaeresis);
4622eaa94a1Schristos		MAP(0x7d, XK_udiaeresis);
4632eaa94a1Schristos		MAP(0x7e, XK_ucircumflex);
4642eaa94a1Schristos	    }
4652eaa94a1Schristos	    break;
4662eaa94a1Schristos
4672eaa94a1Schristos	default:		/* any character sets we don't recognize */
4682eaa94a1Schristos	    count--;
4692eaa94a1Schristos	    break;
470d522f475Smrg	}
4712eaa94a1Schristos	/*
4722eaa94a1Schristos	 * The state machine already treated DEL as a nonprinting and
4732eaa94a1Schristos	 * nonspacing character.  If we have DEL now, simply render
4742eaa94a1Schristos	 * it as a blank.
4752eaa94a1Schristos	 */
4762eaa94a1Schristos	if (chr == ANSI_DEL)
4772eaa94a1Schristos	    chr = ' ';
478956cc18dSsnj	*s = (IChar) A2E(chr);
4792eaa94a1Schristos    }
4802eaa94a1Schristos    TRACE(("%d\t%s\n",
4812eaa94a1Schristos	   count,
4822eaa94a1Schristos	   visibleIChar(buf, (unsigned) (ptr - buf))));
4832eaa94a1Schristos    return count;
4842eaa94a1Schristos#undef MAP
485d522f475Smrg}
486