charsets.c revision e0a2b6df
1e0a2b6dfSmrg/* $XTermId: charsets.c,v 1.67 2013/12/01 16:38:13 tom Exp $ */
2d522f475Smrg
30bd37d32Smrg/*
4e0a2b6dfSmrg * Copyright 1998-2011,2013 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
58e0a2b6dfSmrg#define map_NRCS_Dutch(code) \
59e0a2b6dfSmrg	switch (code) { \
60e0a2b6dfSmrg	    MAP(0x23, XK_sterling); \
61e0a2b6dfSmrg	    MAP(0x40, XK_threequarters); \
62e0a2b6dfSmrg	    UNI(0x5b, 0x0133); /* ij ligature */ \
63e0a2b6dfSmrg	    MAP(0x5c, XK_onehalf); \
64e0a2b6dfSmrg	    MAP(0x5d, XK_bar); \
65e0a2b6dfSmrg	    MAP(0x7b, XK_diaeresis); \
66e0a2b6dfSmrg	    UNI(0x7c, 0x0192); /* florin */ \
67e0a2b6dfSmrg	    MAP(0x7d, XK_onequarter); \
68e0a2b6dfSmrg	    MAP(0x7e, XK_acute); \
69e0a2b6dfSmrg	}
70d522f475Smrg
71e0a2b6dfSmrg#define map_NRCS_Finnish(code) \
72e0a2b6dfSmrg	switch (code) { \
73e0a2b6dfSmrg	    MAP(0x5b, XK_Adiaeresis); \
74e0a2b6dfSmrg	    MAP(0x5c, XK_Odiaeresis); \
75e0a2b6dfSmrg	    MAP(0x5d, XK_Aring); \
76e0a2b6dfSmrg	    MAP(0x5e, XK_Udiaeresis); \
77e0a2b6dfSmrg	    MAP(0x60, XK_eacute); \
78e0a2b6dfSmrg	    MAP(0x7b, XK_adiaeresis); \
79e0a2b6dfSmrg	    MAP(0x7c, XK_odiaeresis); \
80e0a2b6dfSmrg	    MAP(0x7d, XK_aring); \
81e0a2b6dfSmrg	    MAP(0x7e, XK_udiaeresis); \
82e0a2b6dfSmrg	}
832eaa94a1Schristos
84e0a2b6dfSmrg#define map_NRCS_French(code) \
85e0a2b6dfSmrg	switch (code) { \
86e0a2b6dfSmrg	    MAP(0x23, XK_sterling); \
87e0a2b6dfSmrg	    MAP(0x40, XK_agrave); \
88e0a2b6dfSmrg	    MAP(0x5b, XK_degree); \
89e0a2b6dfSmrg	    MAP(0x5c, XK_ccedilla); \
90e0a2b6dfSmrg	    MAP(0x5d, XK_section); \
91e0a2b6dfSmrg	    MAP(0x7b, XK_eacute); \
92e0a2b6dfSmrg	    MAP(0x7c, XK_ugrave); \
93e0a2b6dfSmrg	    MAP(0x7d, XK_egrave); \
94e0a2b6dfSmrg	    MAP(0x7e, XK_diaeresis); \
95e0a2b6dfSmrg	}
962eaa94a1Schristos
97e0a2b6dfSmrg#define map_NRCS_French_Canadian(code) \
98e0a2b6dfSmrg	switch (code) { \
99e0a2b6dfSmrg	    MAP(0x40, XK_agrave); \
100e0a2b6dfSmrg	    MAP(0x5b, XK_acircumflex); \
101e0a2b6dfSmrg	    MAP(0x5c, XK_ccedilla); \
102e0a2b6dfSmrg	    MAP(0x5d, XK_ecircumflex); \
103e0a2b6dfSmrg	    MAP(0x5e, XK_icircumflex); \
104e0a2b6dfSmrg	    MAP(0x60, XK_ocircumflex); \
105e0a2b6dfSmrg	    MAP(0x7b, XK_eacute); \
106e0a2b6dfSmrg	    MAP(0x7c, XK_ugrave); \
107e0a2b6dfSmrg	    MAP(0x7d, XK_egrave); \
108e0a2b6dfSmrg	    MAP(0x7e, XK_ucircumflex); \
109e0a2b6dfSmrg	}
1102eaa94a1Schristos
111e0a2b6dfSmrg#define map_NRCS_German(code) \
112e0a2b6dfSmrg	switch (code) { \
113e0a2b6dfSmrg	    MAP(0x40, XK_section); \
114e0a2b6dfSmrg	    MAP(0x5b, XK_Adiaeresis); \
115e0a2b6dfSmrg	    MAP(0x5c, XK_Odiaeresis); \
116e0a2b6dfSmrg	    MAP(0x5d, XK_Udiaeresis); \
117e0a2b6dfSmrg	    MAP(0x7b, XK_adiaeresis); \
118e0a2b6dfSmrg	    MAP(0x7c, XK_odiaeresis); \
119e0a2b6dfSmrg	    MAP(0x7d, XK_udiaeresis); \
120e0a2b6dfSmrg	    MAP(0x7e, XK_ssharp); \
121e0a2b6dfSmrg	}
1222eaa94a1Schristos
123e0a2b6dfSmrg#define map_NRCS_Italian(code) \
124e0a2b6dfSmrg	switch (code) { \
125e0a2b6dfSmrg	    MAP(0x23, XK_sterling); \
126e0a2b6dfSmrg	    MAP(0x40, XK_section); \
127e0a2b6dfSmrg	    MAP(0x5b, XK_degree); \
128e0a2b6dfSmrg	    MAP(0x5c, XK_ccedilla); \
129e0a2b6dfSmrg	    MAP(0x5d, XK_eacute); \
130e0a2b6dfSmrg	    MAP(0x60, XK_ugrave); \
131e0a2b6dfSmrg	    MAP(0x7b, XK_agrave); \
132e0a2b6dfSmrg	    MAP(0x7c, XK_ograve); \
133e0a2b6dfSmrg	    MAP(0x7d, XK_egrave); \
134e0a2b6dfSmrg	    MAP(0x7e, XK_igrave); \
135e0a2b6dfSmrg	}
1362eaa94a1Schristos
137e0a2b6dfSmrg#define map_NRCS_Norwegian_Danish(code) \
138e0a2b6dfSmrg	switch (code) { \
139e0a2b6dfSmrg	    MAP(0x40, XK_Adiaeresis); \
140e0a2b6dfSmrg	    MAP(0x5b, XK_AE); \
141e0a2b6dfSmrg	    MAP(0x5c, XK_Ooblique); \
142e0a2b6dfSmrg	    MAP(0x5d, XK_Aring); \
143e0a2b6dfSmrg	    MAP(0x5e, XK_Udiaeresis); \
144e0a2b6dfSmrg	    MAP(0x60, XK_adiaeresis); \
145e0a2b6dfSmrg	    MAP(0x7b, XK_ae); \
146e0a2b6dfSmrg	    MAP(0x7c, XK_oslash); \
147e0a2b6dfSmrg	    MAP(0x7d, XK_aring); \
148e0a2b6dfSmrg	    MAP(0x7e, XK_udiaeresis); \
149e0a2b6dfSmrg	}
1502eaa94a1Schristos
151e0a2b6dfSmrg#define map_NRCS_Portuguese(code) \
152e0a2b6dfSmrg	switch (code) { \
153e0a2b6dfSmrg	    MAP(0x5b, XK_Atilde); \
154e0a2b6dfSmrg	    MAP(0x5c, XK_Ccedilla); \
155e0a2b6dfSmrg	    MAP(0x5d, XK_Otilde); \
156e0a2b6dfSmrg	    MAP(0x7b, XK_atilde); \
157e0a2b6dfSmrg	    MAP(0x7c, XK_ccedilla); \
158e0a2b6dfSmrg	    MAP(0x7d, XK_otilde); \
159e0a2b6dfSmrg	}
1602eaa94a1Schristos
161e0a2b6dfSmrg#define map_NRCS_Spanish(code) \
162e0a2b6dfSmrg	switch (code) { \
163e0a2b6dfSmrg	    MAP(0x23, XK_sterling); \
164e0a2b6dfSmrg	    MAP(0x40, XK_section); \
165e0a2b6dfSmrg	    MAP(0x5b, XK_exclamdown); \
166e0a2b6dfSmrg	    MAP(0x5c, XK_Ntilde); \
167e0a2b6dfSmrg	    MAP(0x5d, XK_questiondown); \
168e0a2b6dfSmrg	    MAP(0x7b, XK_degree); \
169e0a2b6dfSmrg	    MAP(0x7c, XK_ntilde); \
170e0a2b6dfSmrg	    MAP(0x7d, XK_ccedilla); \
171e0a2b6dfSmrg	}
1722eaa94a1Schristos
173e0a2b6dfSmrg#define map_NRCS_Swedish(code) \
174e0a2b6dfSmrg	switch (code) { \
175e0a2b6dfSmrg	    MAP(0x40, XK_Eacute); \
176e0a2b6dfSmrg	    MAP(0x5b, XK_Adiaeresis); \
177e0a2b6dfSmrg	    MAP(0x5c, XK_Odiaeresis); \
178e0a2b6dfSmrg	    MAP(0x5d, XK_Aring); \
179e0a2b6dfSmrg	    MAP(0x5e, XK_Udiaeresis); \
180e0a2b6dfSmrg	    MAP(0x60, XK_eacute); \
181e0a2b6dfSmrg	    MAP(0x7b, XK_adiaeresis); \
182e0a2b6dfSmrg	    MAP(0x7c, XK_odiaeresis); \
183e0a2b6dfSmrg	    MAP(0x7d, XK_aring); \
184e0a2b6dfSmrg	    MAP(0x7e, XK_udiaeresis); \
185e0a2b6dfSmrg	}
1862eaa94a1Schristos
187e0a2b6dfSmrg#define map_NRCS_Swiss(code) \
188e0a2b6dfSmrg	switch (code) { \
189e0a2b6dfSmrg	    MAP(0x23, XK_ugrave); \
190e0a2b6dfSmrg	    MAP(0x40, XK_agrave); \
191e0a2b6dfSmrg	    MAP(0x5b, XK_eacute); \
192e0a2b6dfSmrg	    MAP(0x5c, XK_ccedilla); \
193e0a2b6dfSmrg	    MAP(0x5d, XK_ecircumflex); \
194e0a2b6dfSmrg	    MAP(0x5e, XK_icircumflex); \
195e0a2b6dfSmrg	    MAP(0x5f, XK_egrave); \
196e0a2b6dfSmrg	    MAP(0x60, XK_ocircumflex); \
197e0a2b6dfSmrg	    MAP(0x7b, XK_adiaeresis); \
198e0a2b6dfSmrg	    MAP(0x7c, XK_odiaeresis); \
199e0a2b6dfSmrg	    MAP(0x7d, XK_udiaeresis); \
200e0a2b6dfSmrg	    MAP(0x7e, XK_ucircumflex); \
201e0a2b6dfSmrg	}
2022eaa94a1Schristos
203e0a2b6dfSmrg/*
204e0a2b6dfSmrg * Unlike NRCS, which splices a few characters onto ASCII, the supplementary
205e0a2b6dfSmrg * character sets are complete, normally mapped to GR.  Most of these mappings
206e0a2b6dfSmrg * rely upon glyphs not found in ISO-8859-1.  We can display most of those
207e0a2b6dfSmrg * using Unicode, thereby supporting specialized applications that use SCS
208e0a2b6dfSmrg * with luit, subject to the limitation that select/paste will give meaningless
209e0a2b6dfSmrg * results in terms of the application which uses these mappings.
210e0a2b6dfSmrg *
211e0a2b6dfSmrg * Since the VT320, etc, use only 8-bit encodings, there is no plausible
212e0a2b6dfSmrg * argument to be made that these mappings "use" UTF-8, even though there is
213e0a2b6dfSmrg * a hidden step in the terminal emulator which relies upon UTF-8.
214e0a2b6dfSmrg */
215e0a2b6dfSmrg#define map_SCS_DEC_Supp(code,dft) \
216e0a2b6dfSmrg	switch (code) { \
217e0a2b6dfSmrg	    XXX(0x24, 0x2e2e); \
218e0a2b6dfSmrg	    XXX(0x26, 0x2e2e); \
219e0a2b6dfSmrg	    XXX(0x2c, 0x2e2e); \
220e0a2b6dfSmrg	    XXX(0x2d, 0x2e2e); \
221e0a2b6dfSmrg	    XXX(0x2e, 0x2e2e); \
222e0a2b6dfSmrg	    XXX(0x2f, 0x2e2e); \
223e0a2b6dfSmrg	    XXX(0x34, 0x2e2e); \
224e0a2b6dfSmrg	    XXX(0x38, 0x2e2e); \
225e0a2b6dfSmrg	    XXX(0x3e, 0x2e2e); \
226e0a2b6dfSmrg	    UNI(0x47, 0x2426); \
227e0a2b6dfSmrg	    MAP(0x48, 0xc7); \
228e0a2b6dfSmrg	    MAP(0x49, 0xc8); \
229e0a2b6dfSmrg	    MAP(0x4a, 0xc9); \
230e0a2b6dfSmrg	    MAP(0x4b, 0xca); \
231e0a2b6dfSmrg	    MAP(0x4c, 0xcb); \
232e0a2b6dfSmrg	    MAP(0x4d, 0xcc); \
233e0a2b6dfSmrg	    MAP(0x4e, 0xcd); \
234e0a2b6dfSmrg	    MAP(0x4f, 0xce); \
235e0a2b6dfSmrg	    XXX(0x50, 0x2e2e); \
236e0a2b6dfSmrg	    UNI(0x57, 0x0152); \
237e0a2b6dfSmrg	    XXX(0x5e, 0x2e2e); \
238e0a2b6dfSmrg	    XXX(0x70, 0x2e2e); \
239e0a2b6dfSmrg	    UNI(0x77, 0x0153); \
240e0a2b6dfSmrg	    MAP(0x7d, 0xff); \
241e0a2b6dfSmrg	    XXX(0x7e, 0x2e2e); \
242e0a2b6dfSmrg	    default: dft; break; \
243e0a2b6dfSmrg	}
2442eaa94a1Schristos
245e0a2b6dfSmrg#define map_SCS_DEC_Supp_Graphic(code,dft) \
246e0a2b6dfSmrg	switch (code) { \
247e0a2b6dfSmrg	    XXX(0x24, 0x2e2e); \
248e0a2b6dfSmrg	    XXX(0x26, 0x2e2e); \
249e0a2b6dfSmrg	    XXX(0x2c, 0x2e2e); \
250e0a2b6dfSmrg	    XXX(0x2d, 0x2e2e); \
251e0a2b6dfSmrg	    XXX(0x2e, 0x2e2e); \
252e0a2b6dfSmrg	    XXX(0x2f, 0x2e2e); \
253e0a2b6dfSmrg	    XXX(0x34, 0x2e2e); \
254e0a2b6dfSmrg	    XXX(0x38, 0x2e2e); \
255e0a2b6dfSmrg	    XXX(0x3e, 0x2e2e); \
256e0a2b6dfSmrg	    XXX(0x50, 0x2e2e); \
257e0a2b6dfSmrg	    UNI(0x57, 0x0152); \
258e0a2b6dfSmrg	    XXX(0x5e, 0x2e2e); \
259e0a2b6dfSmrg	    XXX(0x70, 0x2e2e); \
260e0a2b6dfSmrg	    UNI(0x77, 0x0153); \
261e0a2b6dfSmrg	    MAP(0x7d, 0xff); \
262e0a2b6dfSmrg	    XXX(0x7e, 0x2e2e); \
263e0a2b6dfSmrg	    XXX(0x7f, 0x2e2e); \
264e0a2b6dfSmrg	    default: dft; break; \
265e0a2b6dfSmrg	}
2662eaa94a1Schristos
267e0a2b6dfSmrg	/* derived from http://www.vt100.net/charsets/technical.html */
268e0a2b6dfSmrg#if OPT_WIDE_CHARS
269e0a2b6dfSmrg#define map_SCS_DEC_Technical(code) \
270e0a2b6dfSmrg	switch (code) { \
271e0a2b6dfSmrg	    UNI(0x21, 0x23b7);	/* RADICAL SYMBOL BOTTOM Centred left to right, so that it joins up with 02/02 */ \
272e0a2b6dfSmrg	    UNI(0x22, 0x250c);	/* BOX DRAWINGS LIGHT DOWN AND RIGHT */ \
273e0a2b6dfSmrg	    UNI(0x23, 0x2500);	/* BOX DRAWINGS LIGHT HORIZONTAL */ \
274e0a2b6dfSmrg	    UNI(0x24, 0x2320);	/* TOP HALF INTEGRAL with the proviso that the stem is vertical, to join with 02/06 */ \
275e0a2b6dfSmrg	    UNI(0x25, 0x2321);	/* BOTTOM HALF INTEGRAL with the proviso above. */ \
276e0a2b6dfSmrg	    UNI(0x26, 0x2502);	/* BOX DRAWINGS LIGHT VERTICAL */ \
277e0a2b6dfSmrg	    UNI(0x27, 0x23a1);	/* LEFT SQUARE BRACKET UPPER CORNER Joins vertically to 02/06, 02/08. Doesn't join to its right. */ \
278e0a2b6dfSmrg	    UNI(0x28, 0x23a3);	/* LEFT SQUARE BRACKET LOWER CORNER Joins vertically to 02/06, 02/07. Doesn't join to its right. */ \
279e0a2b6dfSmrg	    UNI(0x29, 0x23a4);	/* RIGHT SQUARE BRACKET UPPER CORNER Joins vertically to 026, 02a. Doesn't join to its left. */ \
280e0a2b6dfSmrg	    UNI(0x2a, 0x23a6);	/* RIGHT SQUARE BRACKET LOWER CORNER Joins vertically to 026, 029. Doesn't join to its left. */ \
281e0a2b6dfSmrg	    UNI(0x2b, 0x239b);	/* LEFT PARENTHESIS UPPER HOOK Joins vertically to 026, 02c, 02/15. Doesn't join to its right. */ \
282e0a2b6dfSmrg	    UNI(0x2c, 0x239d);	/* LEFT PARENTHESIS LOWER HOOK Joins vertically to 026, 02b, 02/15. Doesn't join to its right. */ \
283e0a2b6dfSmrg	    UNI(0x2d, 0x239e);	/* RIGHT PARENTHESIS UPPER HOOK Joins vertically to 026, 02e, 03/00. Doesn't join to its left. */ \
284e0a2b6dfSmrg	    UNI(0x2e, 0x23a0);	/* RIGHT PARENTHESIS LOWER HOOK Joins vertically to 026, 02d, 03/00. Doesn't join to its left. */ \
285e0a2b6dfSmrg	    UNI(0x2f, 0x23a8);	/* LEFT CURLY BRACKET MIDDLE PIECE Joins vertically to 026, 02b, 02c. */ \
286e0a2b6dfSmrg	    UNI(0x30, 0x23ac);	/* RIGHT CURLY BRACKET MIDDLE PIECE Joins vertically to 02/06, 02d, 02e. */ \
287e0a2b6dfSmrg	    XXX(0x31, 0x2426);	/* Top Left Sigma. Joins to right with 02/03, 03/05. Joins diagonally below right with 03/03, 03/07. */ \
288e0a2b6dfSmrg	    XXX(0x32, 0x2426);	/* Bottom Left Sigma. Joins to right with 02/03, 03/06. Joins diagonally above right with 03/04, 03/07. */ \
289e0a2b6dfSmrg	    XXX(0x33, 0x2426);	/* Top Diagonal Sigma. Line for joining 03/01 to 03/04 or 03/07. */ \
290e0a2b6dfSmrg	    XXX(0x34, 0x2426);	/* Bottom Diagonal Sigma. Line for joining 03/02 to 03/03 or 03/07. */ \
291e0a2b6dfSmrg	    XXX(0x35, 0x2426);	/* Top Right Sigma. Joins to left with 02/03, 03/01. */ \
292e0a2b6dfSmrg	    XXX(0x36, 0x2426);	/* Bottom Right Sigma. Joins to left with 02/03, 03/02. */ \
293e0a2b6dfSmrg	    XXX(0x37, 0x2426);	/* Middle Sigma. Joins diagonally with 03/01, 03/02, 03/03, 03/04. */ \
294e0a2b6dfSmrg	    XXX(0x38, 0x2426);	/* undefined */ \
295e0a2b6dfSmrg	    XXX(0x39, 0x2426);	/* undefined */ \
296e0a2b6dfSmrg	    XXX(0x3a, 0x2426);	/* undefined */ \
297e0a2b6dfSmrg	    XXX(0x3b, 0x2426);	/* undefined */ \
298e0a2b6dfSmrg	    UNI(0x3c, 0x2264);	/* LESS-THAN OR EQUAL TO */ \
299e0a2b6dfSmrg	    UNI(0x3d, 0x2260);	/* NOT EQUAL TO */ \
300e0a2b6dfSmrg	    UNI(0x3e, 0x2265);	/* GREATER-THAN OR EQUAL TO */ \
301e0a2b6dfSmrg	    UNI(0x3f, 0x222B);	/* INTEGRAL */ \
302e0a2b6dfSmrg	    UNI(0x40, 0x2234);	/* THEREFORE */ \
303e0a2b6dfSmrg	    UNI(0x41, 0x221d);	/* PROPORTIONAL TO */ \
304e0a2b6dfSmrg	    UNI(0x42, 0x221e);	/* INFINITY */ \
305e0a2b6dfSmrg	    UNI(0x43, 0x00f7);	/* DIVISION SIGN */ \
306e0a2b6dfSmrg	    UNI(0x44, 0x039a);	/* GREEK CAPITAL DELTA */ \
307e0a2b6dfSmrg	    UNI(0x45, 0x2207);	/* NABLA */ \
308e0a2b6dfSmrg	    UNI(0x46, 0x03a6);	/* GREEK CAPITAL LETTER PHI */ \
309e0a2b6dfSmrg	    UNI(0x47, 0x0393);	/* GREEK CAPITAL LETTER GAMMA */ \
310e0a2b6dfSmrg	    UNI(0x48, 0x223c);	/* TILDE OPERATOR */ \
311e0a2b6dfSmrg	    UNI(0x49, 0x2243);	/* ASYMPTOTICALLY EQUAL TO */ \
312e0a2b6dfSmrg	    UNI(0x4a, 0x0398);	/* GREEK CAPITAL LETTER THETA */ \
313e0a2b6dfSmrg	    UNI(0x4b, 0x00d7);	/* MULTIPLICATION SIGN */ \
314e0a2b6dfSmrg	    UNI(0x4c, 0x039b);	/* GREEK CAPITAL LETTER LAMDA */ \
315e0a2b6dfSmrg	    UNI(0x4d, 0x21d4);	/* LEFT RIGHT DOUBLE ARROW */ \
316e0a2b6dfSmrg	    UNI(0x4e, 0x21d2);	/* RIGHTWARDS DOUBLE ARROW */ \
317e0a2b6dfSmrg	    UNI(0x4f, 0x2261);	/* IDENTICAL TO */ \
318e0a2b6dfSmrg	    UNI(0x50, 0x03a0);	/* GREEK CAPITAL LETTER PI */ \
319e0a2b6dfSmrg	    UNI(0x51, 0x03a8);	/* GREEK CAPITAL LETTER PSI */ \
320e0a2b6dfSmrg	    UNI(0x52, 0x2426);	/* undefined */ \
321e0a2b6dfSmrg	    UNI(0x53, 0x03a3);	/* GREEK CAPITAL LETTER SIGMA */ \
322e0a2b6dfSmrg	    XXX(0x54, 0x2426);	/* undefined */ \
323e0a2b6dfSmrg	    XXX(0x55, 0x2426);	/* undefined */ \
324e0a2b6dfSmrg	    UNI(0x56, 0x221a);	/* SQUARE ROOT */ \
325e0a2b6dfSmrg	    UNI(0x57, 0x03a9);	/* GREEK CAPITAL LETTER OMEGA */ \
326e0a2b6dfSmrg	    UNI(0x58, 0x039e);	/* GREEK CAPITAL LETTER XI */ \
327e0a2b6dfSmrg	    UNI(0x59, 0x03a5);	/* GREEK CAPITAL LETTER UPSILON */ \
328e0a2b6dfSmrg	    UNI(0x5a, 0x2282);	/* SUBSET OF */ \
329e0a2b6dfSmrg	    UNI(0x5b, 0x2283);	/* SUPERSET OF */ \
330e0a2b6dfSmrg	    UNI(0x5c, 0x2229);	/* INTERSECTION */ \
331e0a2b6dfSmrg	    UNI(0x5d, 0x222a);	/* UNION */ \
332e0a2b6dfSmrg	    UNI(0x5e, 0x2227);	/* LOGICAL AND */ \
333e0a2b6dfSmrg	    UNI(0x5f, 0x2228);	/* LOGICAL OR */ \
334e0a2b6dfSmrg	    UNI(0x60, 0x00ac);	/* NOT SIGN */ \
335e0a2b6dfSmrg	    UNI(0x61, 0x03b1);	/* GREEK SMALL LETTER ALPHA */ \
336e0a2b6dfSmrg	    UNI(0x62, 0x03b2);	/* GREEK SMALL LETTER BETA */ \
337e0a2b6dfSmrg	    UNI(0x63, 0x03c7);	/* GREEK SMALL LETTER CHI */ \
338e0a2b6dfSmrg	    UNI(0x64, 0x03b4);	/* GREEK SMALL LETTER DELTA */ \
339e0a2b6dfSmrg	    UNI(0x65, 0x03b5);	/* GREEK SMALL LETTER EPSILON */ \
340e0a2b6dfSmrg	    UNI(0x66, 0x03c6);	/* GREEK SMALL LETTER PHI */ \
341e0a2b6dfSmrg	    UNI(0x67, 0x03b3);	/* GREEK SMALL LETTER GAMMA */ \
342e0a2b6dfSmrg	    UNI(0x68, 0x03b7);	/* GREEK SMALL LETTER ETA */ \
343e0a2b6dfSmrg	    UNI(0x69, 0x03b9);	/* GREEK SMALL LETTER IOTA */ \
344e0a2b6dfSmrg	    UNI(0x6a, 0x03b8);	/* GREEK SMALL LETTER THETA */ \
345e0a2b6dfSmrg	    UNI(0x6b, 0x03ba);	/* GREEK SMALL LETTER KAPPA */ \
346e0a2b6dfSmrg	    UNI(0x6c, 0x03bb);	/* GREEK SMALL LETTER LAMDA */ \
347e0a2b6dfSmrg	    XXX(0x6d, 0x2426);	/* undefined */ \
348e0a2b6dfSmrg	    UNI(0x6e, 0x03bd);	/* GREEK SMALL LETTER NU */ \
349e0a2b6dfSmrg	    UNI(0x6f, 0x2202);	/* PARTIAL DIFFERENTIAL */ \
350e0a2b6dfSmrg	    UNI(0x70, 0x03c0);	/* GREEK SMALL LETTER PI */ \
351e0a2b6dfSmrg	    UNI(0x71, 0x03c8);	/* GREEK SMALL LETTER PSI */ \
352e0a2b6dfSmrg	    UNI(0x72, 0x03c1);	/* GREEK SMALL LETTER RHO */ \
353e0a2b6dfSmrg	    UNI(0x73, 0x03c3);	/* GREEK SMALL LETTER SIGMA */ \
354e0a2b6dfSmrg	    UNI(0x74, 0x03c4);	/* GREEK SMALL LETTER TAU */ \
355e0a2b6dfSmrg	    XXX(0x75, 0x2426);	/* undefined */ \
356e0a2b6dfSmrg	    UNI(0x76, 0x0192);	/* LATIN SMALL LETTER F WITH HOOK Probably chosen for its meaning of "function" */ \
357e0a2b6dfSmrg	    UNI(0x77, 0x03c9);	/* GREEK SMALL LETTER OMEGA */ \
358e0a2b6dfSmrg	    UNI(0x78, 0x03bE);	/* GREEK SMALL LETTER XI */ \
359e0a2b6dfSmrg	    UNI(0x79, 0x03c5);	/* GREEK SMALL LETTER UPSILON */ \
360e0a2b6dfSmrg	    UNI(0x7a, 0x03b6);	/* GREEK SMALL LETTER ZETA */ \
361e0a2b6dfSmrg	    UNI(0x7b, 0x2190);	/* LEFTWARDS ARROW */ \
362e0a2b6dfSmrg	    UNI(0x7c, 0x2191);	/* UPWARDS ARROW */ \
363e0a2b6dfSmrg	    UNI(0x7d, 0x2192);	/* RIGHTWARDS ARROW */ \
364e0a2b6dfSmrg	    UNI(0x7e, 0x2193);	/* DOWNWARDS ARROW */ \
365d522f475Smrg	}
366e0a2b6dfSmrg#else
367e0a2b6dfSmrg#define map_SCS_DEC_Technical(code)	/* nothing */
368e0a2b6dfSmrg#endif /* OPT_WIDE_CHARS */
369e0a2b6dfSmrg
370e0a2b6dfSmrg/*
371e0a2b6dfSmrg * Translate an input keysym to the corresponding NRC keysym.
372e0a2b6dfSmrg */
373e0a2b6dfSmrgunsigned
374e0a2b6dfSmrgxtermCharSetIn(TScreen *screen, unsigned code, int charset)
375e0a2b6dfSmrg{
376e0a2b6dfSmrg#define MAP(to, from) case from: code = to; break
377e0a2b6dfSmrg
378e0a2b6dfSmrg#if OPT_WIDE_CHARS
379e0a2b6dfSmrg#define UNI(to, from) case from: if (screen->utf8_nrc_mode) code = to; break
380e0a2b6dfSmrg#else
381e0a2b6dfSmrg#define UNI(to, from) case from: break
382e0a2b6dfSmrg#endif
383e0a2b6dfSmrg
384e0a2b6dfSmrg#define XXX(to, from)		/* no defined mapping to 0..255 */
385e0a2b6dfSmrg
386e0a2b6dfSmrg    TRACE(("CHARSET-IN GL=%s(G%d) GR=%s(G%d) SS%d\n\t%s\n",
387e0a2b6dfSmrg	   visibleScsCode(screen->gsets[screen->curgl]), screen->curgl,
388e0a2b6dfSmrg	   visibleScsCode(screen->gsets[screen->curgr]), screen->curgr,
389e0a2b6dfSmrg	   screen->curss,
390e0a2b6dfSmrg	   visibleUChar(code)));
391e0a2b6dfSmrg
392e0a2b6dfSmrg    switch (charset) {
393e0a2b6dfSmrg    case nrc_British:		/* United Kingdom set (or Latin 1)      */
394e0a2b6dfSmrg	if (code == XK_sterling)
395e0a2b6dfSmrg	    code = 0x23;
396e0a2b6dfSmrg	code &= 0x7f;
397e0a2b6dfSmrg	break;
398e0a2b6dfSmrg
399e0a2b6dfSmrg#if OPT_XMC_GLITCH
400e0a2b6dfSmrg    case nrc_Unknown:
401e0a2b6dfSmrg#endif
402e0a2b6dfSmrg    case nrc_DEC_Alt_Chars:
403e0a2b6dfSmrg    case nrc_DEC_Alt_Graphics:
404e0a2b6dfSmrg    case nrc_ASCII:
405e0a2b6dfSmrg	break;
406e0a2b6dfSmrg
407e0a2b6dfSmrg    case nrc_DEC_Spec_Graphic:
408e0a2b6dfSmrg	break;
409e0a2b6dfSmrg
410e0a2b6dfSmrg    case nrc_DEC_Supp:
411e0a2b6dfSmrg	map_SCS_DEC_Supp(code, code &= 0x7f);
412e0a2b6dfSmrg	break;
413e0a2b6dfSmrg
414e0a2b6dfSmrg    case nrc_DEC_Supp_Graphic:
415e0a2b6dfSmrg	map_SCS_DEC_Supp_Graphic(code, code |= 0x80);
416e0a2b6dfSmrg	break;
417e0a2b6dfSmrg
418e0a2b6dfSmrg    case nrc_DEC_Technical:
419e0a2b6dfSmrg	map_SCS_DEC_Technical(code);
420e0a2b6dfSmrg	break;
421e0a2b6dfSmrg
422e0a2b6dfSmrg    case nrc_Dutch:
423e0a2b6dfSmrg	map_NRCS_Dutch(code);
424e0a2b6dfSmrg	break;
425e0a2b6dfSmrg
426e0a2b6dfSmrg    case nrc_Finnish:
427e0a2b6dfSmrg    case nrc_Finnish2:
428e0a2b6dfSmrg	map_NRCS_Finnish(code);
429e0a2b6dfSmrg	break;
430e0a2b6dfSmrg
431e0a2b6dfSmrg    case nrc_French:
432e0a2b6dfSmrg    case nrc_French2:
433e0a2b6dfSmrg	map_NRCS_French(code);
434e0a2b6dfSmrg	break;
435e0a2b6dfSmrg
436e0a2b6dfSmrg    case nrc_French_Canadian:
437e0a2b6dfSmrg	map_NRCS_French_Canadian(code);
438e0a2b6dfSmrg	break;
439e0a2b6dfSmrg
440e0a2b6dfSmrg    case nrc_German:
441e0a2b6dfSmrg	map_NRCS_German(code);
442e0a2b6dfSmrg	break;
443e0a2b6dfSmrg
444e0a2b6dfSmrg    case nrc_Hebrew:
445e0a2b6dfSmrg    case nrc_Hebrew2:
446e0a2b6dfSmrg	/* FIXME */
447e0a2b6dfSmrg	break;
448e0a2b6dfSmrg
449e0a2b6dfSmrg    case nrc_Italian:
450e0a2b6dfSmrg	map_NRCS_Italian(code);
451e0a2b6dfSmrg	break;
452e0a2b6dfSmrg
453e0a2b6dfSmrg    case nrc_Norwegian_Danish:
454e0a2b6dfSmrg    case nrc_Norwegian_Danish2:
455e0a2b6dfSmrg    case nrc_Norwegian_Danish3:
456e0a2b6dfSmrg	map_NRCS_Norwegian_Danish(code);
457e0a2b6dfSmrg	break;
458e0a2b6dfSmrg
459e0a2b6dfSmrg    case nrc_Portugese:
460e0a2b6dfSmrg	map_NRCS_Portuguese(code);
461e0a2b6dfSmrg	break;
462e0a2b6dfSmrg
463e0a2b6dfSmrg    case nrc_SCS_NRCS:		/* vt5xx - probably Serbo/Croatian */
464e0a2b6dfSmrg	/* FIXME */
465e0a2b6dfSmrg	break;
466e0a2b6dfSmrg
467e0a2b6dfSmrg    case nrc_Spanish:
468e0a2b6dfSmrg	map_NRCS_Spanish(code);
469e0a2b6dfSmrg	break;
470e0a2b6dfSmrg
471e0a2b6dfSmrg    case nrc_Swedish2:
472e0a2b6dfSmrg    case nrc_Swedish:
473e0a2b6dfSmrg	map_NRCS_Swedish(code);
474e0a2b6dfSmrg	break;
475e0a2b6dfSmrg
476e0a2b6dfSmrg    case nrc_Swiss:
477e0a2b6dfSmrg	map_NRCS_Swiss(code);
478e0a2b6dfSmrg	break;
479e0a2b6dfSmrg
480e0a2b6dfSmrg    case nrc_Turkish:
481e0a2b6dfSmrg    case nrc_Turkish2:
482e0a2b6dfSmrg	/* FIXME */
483e0a2b6dfSmrg	break;
484e0a2b6dfSmrg
485e0a2b6dfSmrg    default:			/* any character sets we don't recognize */
486e0a2b6dfSmrg	break;
4872eaa94a1Schristos    }
488e0a2b6dfSmrg    code &= 0x7f;		/* NRC in any case is 7-bit */
489e0a2b6dfSmrg    TRACE(("->\t%s\n",
490e0a2b6dfSmrg	   visibleUChar(code)));
4912eaa94a1Schristos    return code;
4922eaa94a1Schristos#undef MAP
493e0a2b6dfSmrg#undef UNI
494e0a2b6dfSmrg#undef XXX
495d522f475Smrg}
496d522f475Smrg
497d522f475Smrg/*
498d522f475Smrg * Translate a string to the display form.  This assumes the font has the
499d522f475Smrg * DEC graphic characters in cells 0-31, and otherwise is ISO-8859-1.
500d522f475Smrg */
5012eaa94a1Schristosint
502e0a2b6dfSmrgxtermCharSetOut(XtermWidget xw, IChar *buf, IChar *ptr, int leftset)
503d522f475Smrg{
5042eaa94a1Schristos    IChar *s;
5052eaa94a1Schristos    TScreen *screen = TScreenOf(xw);
5062eaa94a1Schristos    int count = 0;
5072eaa94a1Schristos    int rightset = screen->gsets[(int) (screen->curgr)];
5082eaa94a1Schristos
5092eaa94a1Schristos#define MAP(from, to) case from: chr = to; break
5102eaa94a1Schristos
511e0a2b6dfSmrg#if OPT_WIDE_CHARS
512e0a2b6dfSmrg#define UNI(from, to) case from: if (screen->utf8_nrc_mode) chr = to; break
513e0a2b6dfSmrg#define XXX(from, to) UNI(from, to)
514e0a2b6dfSmrg#else
515e0a2b6dfSmrg#define UNI(old, new) chr = old; break
516e0a2b6dfSmrg#define XXX(from, to)		/* nothing */
517e0a2b6dfSmrg#endif
518e0a2b6dfSmrg
519e0a2b6dfSmrg    TRACE(("CHARSET-OUT GL=%s(G%d) GR=%s(G%d) SS%d\n\t%s\n",
520e0a2b6dfSmrg	   visibleScsCode(leftset), screen->curgl,
521e0a2b6dfSmrg	   visibleScsCode(rightset), screen->curgr,
5222eaa94a1Schristos	   screen->curss,
523e0a2b6dfSmrg	   visibleIChars(buf, (unsigned) (ptr - buf))));
5242eaa94a1Schristos
5252eaa94a1Schristos    for (s = buf; s < ptr; ++s) {
5262eaa94a1Schristos	int eight = CharOf(E2A(*s));
5272eaa94a1Schristos	int seven = eight & 0x7f;
5282eaa94a1Schristos	int cs = (eight >= 128) ? rightset : leftset;
5292eaa94a1Schristos	int chr = eight;
5302eaa94a1Schristos
5312eaa94a1Schristos	count++;
5322eaa94a1Schristos#if OPT_WIDE_CHARS
5332eaa94a1Schristos	/*
5342eaa94a1Schristos	 * This is only partly right - prevent inadvertant remapping of
5352eaa94a1Schristos	 * the replacement character and other non-8bit codes into bogus
5362eaa94a1Schristos	 * 8bit codes.
5372eaa94a1Schristos	 */
538e0a2b6dfSmrg	if (screen->utf8_mode || screen->utf8_nrc_mode) {
5392eaa94a1Schristos	    if (*s > 255)
5402eaa94a1Schristos		continue;
5412eaa94a1Schristos	}
5422eaa94a1Schristos#endif
543e0a2b6dfSmrg	if (*s < 32)
544e0a2b6dfSmrg	    continue;
545e0a2b6dfSmrg
5462eaa94a1Schristos	switch (cs) {
547e0a2b6dfSmrg	case nrc_British_Latin_1:
548e0a2b6dfSmrg	    /* FALLTHRU */
549e0a2b6dfSmrg	case nrc_British:	/* United Kingdom set (or Latin 1)      */
5502eaa94a1Schristos	    if ((xw->flags & NATIONAL)
5512eaa94a1Schristos		|| (screen->vtXX_level <= 1)) {
552e0a2b6dfSmrg		if ((xw->flags & NATIONAL)) {
553e0a2b6dfSmrg		    chr = seven;
554e0a2b6dfSmrg		}
5552eaa94a1Schristos		if (chr == 0x23) {
5562eaa94a1Schristos		    chr = XTERM_POUND;
557e0a2b6dfSmrg#if OPT_WIDE_CHARS
558e0a2b6dfSmrg		    if (screen->utf8_nrc_mode) {
559e0a2b6dfSmrg			chr = 0xa3;
560e0a2b6dfSmrg		    }
5612eaa94a1Schristos#endif
5622eaa94a1Schristos		}
5632eaa94a1Schristos	    } else {
5642eaa94a1Schristos		chr = (seven | 0x80);
5652eaa94a1Schristos	    }
5662eaa94a1Schristos	    break;
567d522f475Smrg
568d522f475Smrg#if OPT_XMC_GLITCH
569e0a2b6dfSmrg	case nrc_Unknown:
570d522f475Smrg#endif
571e0a2b6dfSmrg	case nrc_DEC_Alt_Chars:
572e0a2b6dfSmrg	case nrc_DEC_Alt_Graphics:
573e0a2b6dfSmrg	case nrc_ASCII:
5742eaa94a1Schristos	    break;
575d522f475Smrg
576e0a2b6dfSmrg	case nrc_DEC_Spec_Graphic:
5772eaa94a1Schristos	    if (seven > 0x5f && seven <= 0x7e) {
578d522f475Smrg#if OPT_WIDE_CHARS
579e0a2b6dfSmrg		if (screen->utf8_mode || screen->utf8_nrc_mode)
580956cc18dSsnj		    chr = (int) dec2ucs((unsigned) (seven - 0x5f));
5812eaa94a1Schristos		else
582d522f475Smrg#endif
5832eaa94a1Schristos		    chr = seven - 0x5f;
5842eaa94a1Schristos	    } else {
5852eaa94a1Schristos		chr = seven;
5862eaa94a1Schristos	    }
5872eaa94a1Schristos	    break;
5882eaa94a1Schristos
589e0a2b6dfSmrg	case nrc_DEC_Supp:
590e0a2b6dfSmrg	    map_SCS_DEC_Supp(chr = seven, chr |= 0x80);
5912eaa94a1Schristos	    break;
5922eaa94a1Schristos
593e0a2b6dfSmrg	case nrc_DEC_Supp_Graphic:
594e0a2b6dfSmrg	    map_SCS_DEC_Supp_Graphic(chr = seven, chr |= 0x80);
5952eaa94a1Schristos	    break;
5962eaa94a1Schristos
597e0a2b6dfSmrg	case nrc_DEC_Technical:
598e0a2b6dfSmrg	    map_SCS_DEC_Technical(chr = seven);
5992eaa94a1Schristos	    break;
6002eaa94a1Schristos
601e0a2b6dfSmrg	case nrc_Dutch:
602e0a2b6dfSmrg	    map_NRCS_Dutch(chr = seven);
6032eaa94a1Schristos	    break;
6042eaa94a1Schristos
605e0a2b6dfSmrg	case nrc_Finnish:
606e0a2b6dfSmrg	case nrc_Finnish2:
607e0a2b6dfSmrg	    map_NRCS_Finnish(chr = seven);
6082eaa94a1Schristos	    break;
6092eaa94a1Schristos
610e0a2b6dfSmrg	case nrc_French:
611e0a2b6dfSmrg	case nrc_French2:
612e0a2b6dfSmrg	    map_NRCS_French(chr = seven);
6132eaa94a1Schristos	    break;
6142eaa94a1Schristos
615e0a2b6dfSmrg	case nrc_French_Canadian:
616e0a2b6dfSmrg	case nrc_French_Canadian2:
617e0a2b6dfSmrg	    map_NRCS_French_Canadian(chr = seven);
6182eaa94a1Schristos	    break;
6192eaa94a1Schristos
620e0a2b6dfSmrg	case nrc_German:
621e0a2b6dfSmrg	    map_NRCS_German(chr = seven);
6222eaa94a1Schristos	    break;
6232eaa94a1Schristos
624e0a2b6dfSmrg	case nrc_Hebrew:
625e0a2b6dfSmrg	case nrc_Hebrew2:
626e0a2b6dfSmrg	    /* FIXME */
6272eaa94a1Schristos	    break;
6282eaa94a1Schristos
629e0a2b6dfSmrg	case nrc_Italian:
630e0a2b6dfSmrg	    map_NRCS_Italian(chr = seven);
631e0a2b6dfSmrg	    break;
632e0a2b6dfSmrg
633e0a2b6dfSmrg	case nrc_Norwegian_Danish:
634e0a2b6dfSmrg	case nrc_Norwegian_Danish2:
635e0a2b6dfSmrg	case nrc_Norwegian_Danish3:
636e0a2b6dfSmrg	    map_NRCS_Norwegian_Danish(chr = seven);
637e0a2b6dfSmrg	    break;
638e0a2b6dfSmrg
639e0a2b6dfSmrg	case nrc_Portugese:
640e0a2b6dfSmrg	    map_NRCS_Portuguese(chr = seven);
641e0a2b6dfSmrg	    break;
642e0a2b6dfSmrg
643e0a2b6dfSmrg	case nrc_SCS_NRCS:	/* vt5xx - probably Serbo/Croatian */
644e0a2b6dfSmrg	    /* FIXME */
645e0a2b6dfSmrg	    break;
646e0a2b6dfSmrg
647e0a2b6dfSmrg	case nrc_Spanish:
648e0a2b6dfSmrg	    map_NRCS_Spanish(chr = seven);
649e0a2b6dfSmrg	    break;
650e0a2b6dfSmrg
651e0a2b6dfSmrg	case nrc_Swedish2:
652e0a2b6dfSmrg	case nrc_Swedish:
653e0a2b6dfSmrg	    map_NRCS_Swedish(chr = seven);
654e0a2b6dfSmrg	    break;
655e0a2b6dfSmrg
656e0a2b6dfSmrg	case nrc_Swiss:
657e0a2b6dfSmrg	    map_NRCS_Swiss(chr = seven);
658e0a2b6dfSmrg	    break;
659e0a2b6dfSmrg
660e0a2b6dfSmrg	case nrc_Turkish:
661e0a2b6dfSmrg	case nrc_Turkish2:
662e0a2b6dfSmrg	    /* FIXME */
6632eaa94a1Schristos	    break;
6642eaa94a1Schristos
6652eaa94a1Schristos	default:		/* any character sets we don't recognize */
6662eaa94a1Schristos	    count--;
6672eaa94a1Schristos	    break;
668d522f475Smrg	}
6692eaa94a1Schristos	/*
6702eaa94a1Schristos	 * The state machine already treated DEL as a nonprinting and
6712eaa94a1Schristos	 * nonspacing character.  If we have DEL now, simply render
6722eaa94a1Schristos	 * it as a blank.
6732eaa94a1Schristos	 */
6742eaa94a1Schristos	if (chr == ANSI_DEL)
6752eaa94a1Schristos	    chr = ' ';
676956cc18dSsnj	*s = (IChar) A2E(chr);
6772eaa94a1Schristos    }
6782eaa94a1Schristos    TRACE(("%d\t%s\n",
6792eaa94a1Schristos	   count,
680e0a2b6dfSmrg	   visibleIChars(buf, (unsigned) (ptr - buf))));
6812eaa94a1Schristos    return count;
6822eaa94a1Schristos#undef MAP
683e0a2b6dfSmrg#undef UNI
684e0a2b6dfSmrg#undef XXX
685d522f475Smrg}
686