charsets.c revision 04b94745
104b94745Smrg/* $XTermId: charsets.c,v 1.126 2024/05/22 00:27:53 tom Exp $ */
2d522f475Smrg
30bd37d32Smrg/*
404b94745Smrg * Copyright 1998-2023,2024 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
3404b94745Smrg#include <assert.h>
3504b94745Smrg#include <X11/keysym.h>
3604b94745Smrg
37d522f475Smrg#include <xterm.h>
38d522f475Smrg#include <data.h>
3904b94745Smrg#include <charsets.h>
40d522f475Smrg#include <fontutils.h>
41d522f475Smrg
42d522f475Smrg/*
43d522f475Smrg * This module performs translation as needed to support the DEC VT220 national
44f2e35a3aSmrg * replacement character sets as well as supplementary character sets (aka
45f2e35a3aSmrg * code-pages) introduced in VT320, etc.
46f2e35a3aSmrg *
47f2e35a3aSmrg * We assume that xterm's font is based on the ISO 8859-1 (Latin 1) character
48f2e35a3aSmrg * set, which is almost the same as the DEC multinational character set.  Glyph
49f2e35a3aSmrg * positions 0-31 have to be the DEC graphic characters, though.
50d522f475Smrg *
51d522f475Smrg * References:
52d522f475Smrg *	"VT220 Programmer Pocket Guide" EK-VT220-HR-002 (2nd ed., 1984), which
53d522f475Smrg *		contains character charts for the national character sets.
54d522f475Smrg *	"VT330/VT340 Programmer Reference Manual Volume 1: Text Programming"
55d522f475Smrg *		EK-VT3XX-TP-001 (1st ed, 1987), which contains a table (2-1)
56d522f475Smrg *		listing the glyphs which are mapped from the multinational
57d522f475Smrg *		character set to the national character set.
58d522f475Smrg *
59d522f475Smrg * The latter reference, though easier to read, has a few errors and omissions.
60f2e35a3aSmrg */
612eaa94a1Schristos
6204b94745Smrg#define HandleUPSS(charset) \
6304b94745Smrg    if (charset == nrc_DEC_UPSS) { \
6404b94745Smrg	charset = screen->gsets_upss; \
6504b94745Smrg	if (screen->vtXX_level >= 5) { \
6604b94745Smrg	    /* EMPTY */ ; \
6704b94745Smrg	} else if (screen->vtXX_level >= 3) { \
6804b94745Smrg	    if (charset != nrc_DEC_Supp) \
6904b94745Smrg		charset = nrc_ISO_Latin_1_Supp; \
7004b94745Smrg	} else if (screen->vtXX_level < 2) { \
7104b94745Smrg	    charset = nrc_ASCII; \
72f2e35a3aSmrg	} \
7304b94745Smrg    }
742eaa94a1Schristos
7504b94745Smrgstatic Boolean
7604b94745SmrgisSevenBit(DECNRCM_codes cs)
7704b94745Smrg{
7804b94745Smrg    Boolean result = False;
7904b94745Smrg
8004b94745Smrg    switch (cs) {
8104b94745Smrg    case nrc_ISO_Greek_Supp:
8204b94745Smrg    case nrc_ISO_Hebrew_Supp:
8304b94745Smrg    case nrc_ISO_Latin_1_Supp:
8404b94745Smrg    case nrc_ISO_Latin_2_Supp:
8504b94745Smrg    case nrc_ISO_Latin_5_Supp:
8604b94745Smrg    case nrc_ISO_Latin_Cyrillic:
8704b94745Smrg    case nrc_DEC_UPSS:
8804b94745Smrg	break;
8904b94745Smrg	/* VT100 character sets */
9004b94745Smrg    case nrc_ASCII:
9104b94745Smrg    case nrc_British:
9204b94745Smrg    case nrc_DEC_Alt_Chars:
9304b94745Smrg    case nrc_DEC_Spec_Graphic:
9404b94745Smrg	/* VT220 character sets */
9504b94745Smrg    case nrc_DEC_Alt_Graphics:
9604b94745Smrg    case nrc_DEC_Supp:
9704b94745Smrg	/* VT320 character sets */
9804b94745Smrg    case nrc_DEC_Supp_Graphic:
9904b94745Smrg    case nrc_DEC_Technical:
10004b94745Smrg	/* NRCS character sets (VT320 to VT520) */
10104b94745Smrg    case nrc_British_Latin_1:
10204b94745Smrg    case nrc_Dutch:
10304b94745Smrg    case nrc_Finnish2:
10404b94745Smrg    case nrc_Finnish:
10504b94745Smrg    case nrc_French2:
10604b94745Smrg    case nrc_French:
10704b94745Smrg    case nrc_French_Canadian2:
10804b94745Smrg    case nrc_French_Canadian:
10904b94745Smrg    case nrc_German:
11004b94745Smrg    case nrc_Greek:
11104b94745Smrg    case nrc_Hebrew:
11204b94745Smrg    case nrc_Italian:
11304b94745Smrg    case nrc_Norwegian_Danish2:
11404b94745Smrg    case nrc_Norwegian_Danish3:
11504b94745Smrg    case nrc_Norwegian_Danish:
11604b94745Smrg    case nrc_Portugese:
11704b94745Smrg    case nrc_Russian:
11804b94745Smrg    case nrc_SCS_NRCS:
11904b94745Smrg    case nrc_Spanish:
12004b94745Smrg    case nrc_Swedish2:
12104b94745Smrg    case nrc_Swedish:
12204b94745Smrg    case nrc_Swiss:
12304b94745Smrg    case nrc_Turkish:
12404b94745Smrg	/* other DEC character sets */
12504b94745Smrg    case nrc_DEC_Cyrillic:
12604b94745Smrg    case nrc_DEC_Greek_Supp:
12704b94745Smrg    case nrc_DEC_Hebrew_Supp:
12804b94745Smrg    case nrc_DEC_Turkish_Supp:
12904b94745Smrg	result = True;
13004b94745Smrg	break;
13104b94745Smrg    case nrc_Unknown:
13204b94745Smrg	break;
13304b94745Smrg    }
13404b94745Smrg    return result;
13504b94745Smrg}
136e0a2b6dfSmrg
137e0a2b6dfSmrg/*
138e0a2b6dfSmrg * Translate an input keysym to the corresponding NRC keysym.
139e0a2b6dfSmrg */
140e0a2b6dfSmrgunsigned
141f2e35a3aSmrgxtermCharSetIn(XtermWidget xw, unsigned code, DECNRCM_codes charset)
142e0a2b6dfSmrg{
143f2e35a3aSmrg    TScreen *screen = TScreenOf(xw);
14404b94745Smrg#define MAP(to, from) case from: code = to; break;
145e0a2b6dfSmrg
146e0a2b6dfSmrg#if OPT_WIDE_CHARS
14704b94745Smrg#define UNI(to, from) case from: if (screen->utf8_nrc_mode) code = to; break;
148e0a2b6dfSmrg#else
14904b94745Smrg#define UNI(to, from) case from: break;
150e0a2b6dfSmrg#endif
151e0a2b6dfSmrg
152e0a2b6dfSmrg#define XXX(to, from)		/* no defined mapping to 0..255 */
153e0a2b6dfSmrg
154e0a2b6dfSmrg    TRACE(("CHARSET-IN GL=%s(G%d) GR=%s(G%d) SS%d\n\t%s\n",
155e0a2b6dfSmrg	   visibleScsCode(screen->gsets[screen->curgl]), screen->curgl,
156e0a2b6dfSmrg	   visibleScsCode(screen->gsets[screen->curgr]), screen->curgr,
157e0a2b6dfSmrg	   screen->curss,
158e0a2b6dfSmrg	   visibleUChar(code)));
159e0a2b6dfSmrg
16004b94745Smrg    HandleUPSS(charset);
16104b94745Smrg
162e0a2b6dfSmrg    switch (charset) {
163e0a2b6dfSmrg    case nrc_British:		/* United Kingdom set (or Latin 1)      */
164e0a2b6dfSmrg	if (code == XK_sterling)
165e0a2b6dfSmrg	    code = 0x23;
166e0a2b6dfSmrg	code &= 0x7f;
167e0a2b6dfSmrg	break;
168e0a2b6dfSmrg
169e0a2b6dfSmrg    case nrc_DEC_Alt_Chars:
170e0a2b6dfSmrg    case nrc_DEC_Alt_Graphics:
171e0a2b6dfSmrg    case nrc_ASCII:
172e0a2b6dfSmrg	break;
173e0a2b6dfSmrg
174e0a2b6dfSmrg    case nrc_DEC_Spec_Graphic:
175e0a2b6dfSmrg	break;
176e0a2b6dfSmrg
177e0a2b6dfSmrg    case nrc_DEC_Supp:
178f2e35a3aSmrg	map_DEC_Supp_Graphic(code, code &= 0x7f);
179e0a2b6dfSmrg	break;
180e0a2b6dfSmrg
181e0a2b6dfSmrg    case nrc_DEC_Supp_Graphic:
182f2e35a3aSmrg	map_DEC_Supp_Graphic(code, code |= 0x80);
183e0a2b6dfSmrg	break;
184e0a2b6dfSmrg
185e0a2b6dfSmrg    case nrc_DEC_Technical:
186f2e35a3aSmrg	map_DEC_Technical(code);
187e0a2b6dfSmrg	break;
188e0a2b6dfSmrg
189e0a2b6dfSmrg    case nrc_Dutch:
190e0a2b6dfSmrg	map_NRCS_Dutch(code);
191e0a2b6dfSmrg	break;
192e0a2b6dfSmrg
193e0a2b6dfSmrg    case nrc_Finnish:
194e0a2b6dfSmrg    case nrc_Finnish2:
195e0a2b6dfSmrg	map_NRCS_Finnish(code);
196e0a2b6dfSmrg	break;
197e0a2b6dfSmrg
198e0a2b6dfSmrg    case nrc_French:
199e0a2b6dfSmrg    case nrc_French2:
200e0a2b6dfSmrg	map_NRCS_French(code);
201e0a2b6dfSmrg	break;
202e0a2b6dfSmrg
203e0a2b6dfSmrg    case nrc_French_Canadian:
204e0a2b6dfSmrg	map_NRCS_French_Canadian(code);
205e0a2b6dfSmrg	break;
206e0a2b6dfSmrg
207e0a2b6dfSmrg    case nrc_German:
208e0a2b6dfSmrg	map_NRCS_German(code);
209e0a2b6dfSmrg	break;
210e0a2b6dfSmrg
211f2e35a3aSmrg    case nrc_Greek:
212f2e35a3aSmrg	map_NRCS_Greek(code);	/* FIXME - ELOT? */
213f2e35a3aSmrg	break;
214f2e35a3aSmrg
215f2e35a3aSmrg    case nrc_DEC_Greek_Supp:
216f2e35a3aSmrg	map_DEC_Greek_Supp(code);
217f2e35a3aSmrg	break;
218f2e35a3aSmrg
219f2e35a3aSmrg    case nrc_ISO_Greek_Supp:
220f2e35a3aSmrg	map_ISO_Greek_Supp(code);
221f2e35a3aSmrg	break;
222f2e35a3aSmrg
223f2e35a3aSmrg    case nrc_DEC_Hebrew_Supp:
224f2e35a3aSmrg	map_DEC_Hebrew_Supp(code);
225f2e35a3aSmrg	break;
226f2e35a3aSmrg
227e0a2b6dfSmrg    case nrc_Hebrew:
228f2e35a3aSmrg	map_NRCS_Hebrew(code);
229f2e35a3aSmrg	break;
230f2e35a3aSmrg
231f2e35a3aSmrg    case nrc_ISO_Hebrew_Supp:
232f2e35a3aSmrg	map_ISO_Hebrew(code);
233e0a2b6dfSmrg	break;
234e0a2b6dfSmrg
235e0a2b6dfSmrg    case nrc_Italian:
236e0a2b6dfSmrg	map_NRCS_Italian(code);
237e0a2b6dfSmrg	break;
238e0a2b6dfSmrg
239f2e35a3aSmrg    case nrc_ISO_Latin_2_Supp:
240f2e35a3aSmrg	map_ISO_Latin_2(code);
241f2e35a3aSmrg	break;
242f2e35a3aSmrg
243f2e35a3aSmrg    case nrc_ISO_Latin_5_Supp:
244f2e35a3aSmrg	map_ISO_Latin_5(code);
245f2e35a3aSmrg	break;
246f2e35a3aSmrg
247f2e35a3aSmrg    case nrc_ISO_Latin_Cyrillic:
248f2e35a3aSmrg	map_ISO_Latin_Cyrillic(code);
249f2e35a3aSmrg	break;
250f2e35a3aSmrg
251e0a2b6dfSmrg    case nrc_Norwegian_Danish:
252e0a2b6dfSmrg    case nrc_Norwegian_Danish2:
253e0a2b6dfSmrg    case nrc_Norwegian_Danish3:
254e0a2b6dfSmrg	map_NRCS_Norwegian_Danish(code);
255e0a2b6dfSmrg	break;
256e0a2b6dfSmrg
257e0a2b6dfSmrg    case nrc_Portugese:
258e0a2b6dfSmrg	map_NRCS_Portuguese(code);
259e0a2b6dfSmrg	break;
260e0a2b6dfSmrg
26104b94745Smrg    case nrc_SCS_NRCS:		/* vt5xx - Serbo/Croatian */
262e0a2b6dfSmrg	/* FIXME */
263e0a2b6dfSmrg	break;
264e0a2b6dfSmrg
265e0a2b6dfSmrg    case nrc_Spanish:
266e0a2b6dfSmrg	map_NRCS_Spanish(code);
267e0a2b6dfSmrg	break;
268e0a2b6dfSmrg
269e0a2b6dfSmrg    case nrc_Swedish2:
270e0a2b6dfSmrg    case nrc_Swedish:
271e0a2b6dfSmrg	map_NRCS_Swedish(code);
272e0a2b6dfSmrg	break;
273e0a2b6dfSmrg
274e0a2b6dfSmrg    case nrc_Swiss:
275e0a2b6dfSmrg	map_NRCS_Swiss(code);
276e0a2b6dfSmrg	break;
277e0a2b6dfSmrg
278e0a2b6dfSmrg    case nrc_Turkish:
279f2e35a3aSmrg	map_NRCS_Turkish(code);
280f2e35a3aSmrg	break;
281f2e35a3aSmrg
282f2e35a3aSmrg    case nrc_DEC_Turkish_Supp:
283f2e35a3aSmrg	map_DEC_Turkish_Supp(code);
284e0a2b6dfSmrg	break;
285e0a2b6dfSmrg
286f2e35a3aSmrg    case nrc_DEC_Cyrillic:
287f2e35a3aSmrg	map_DEC_Cyrillic(code);
288f2e35a3aSmrg	break;
289f2e35a3aSmrg
290f2e35a3aSmrg    case nrc_ISO_Latin_1_Supp:
291f2e35a3aSmrg    case nrc_British_Latin_1:
292f2e35a3aSmrg    case nrc_Russian:
293f2e35a3aSmrg    case nrc_French_Canadian2:
294f2e35a3aSmrg    case nrc_Unknown:
29504b94745Smrg    case nrc_DEC_UPSS:
296e0a2b6dfSmrg    default:			/* any character sets we don't recognize */
297e0a2b6dfSmrg	break;
2982eaa94a1Schristos    }
299e0a2b6dfSmrg    code &= 0x7f;		/* NRC in any case is 7-bit */
300e0a2b6dfSmrg    TRACE(("->\t%s\n",
301e0a2b6dfSmrg	   visibleUChar(code)));
3022eaa94a1Schristos    return code;
3032eaa94a1Schristos#undef MAP
304e0a2b6dfSmrg#undef UNI
305e0a2b6dfSmrg#undef XXX
306d522f475Smrg}
307d522f475Smrg
308d522f475Smrg/*
309d522f475Smrg * Translate a string to the display form.  This assumes the font has the
310d522f475Smrg * DEC graphic characters in cells 0-31, and otherwise is ISO-8859-1.
311d522f475Smrg */
31204b94745SmrgCardinal
31304b94745SmrgxtermCharSetOut(XtermWidget xw, Cardinal length, DECNRCM_codes leftset)
314d522f475Smrg{
31504b94745Smrg    IChar *buf = xw->work.write_text;
31604b94745Smrg    IChar *ptr = buf + length;
3172eaa94a1Schristos    IChar *s;
3182eaa94a1Schristos    TScreen *screen = TScreenOf(xw);
31904b94745Smrg    Cardinal count = 0;
320f2e35a3aSmrg    DECNRCM_codes rightset = screen->gsets[(int) (screen->curgr)];
32104b94745Smrg#if OPT_DEC_RECTOPS
32204b94745Smrg    int sums = 0;
32304b94745Smrg#endif
3242eaa94a1Schristos
32504b94745Smrg#define MAP(from, to) case from: chr = to; break;
3262eaa94a1Schristos
327e0a2b6dfSmrg#if OPT_WIDE_CHARS
32804b94745Smrg#define UNI(from, to) case from: if (screen->utf8_nrc_mode) chr = to; break;
329e0a2b6dfSmrg#define XXX(from, to) UNI(from, to)
330e0a2b6dfSmrg#else
33104b94745Smrg#define UNI(old, new) case new: chr = old; break;
332e0a2b6dfSmrg#define XXX(from, to)		/* nothing */
333e0a2b6dfSmrg#endif
334e0a2b6dfSmrg
335e0a2b6dfSmrg    TRACE(("CHARSET-OUT GL=%s(G%d) GR=%s(G%d) SS%d\n\t%s\n",
336e0a2b6dfSmrg	   visibleScsCode(leftset), screen->curgl,
337e0a2b6dfSmrg	   visibleScsCode(rightset), screen->curgr,
3382eaa94a1Schristos	   screen->curss,
33904b94745Smrg	   visibleIChars(buf, (size_t) length)));
34004b94745Smrg
34104b94745Smrg    assert(length != 0);
34204b94745Smrg#if OPT_DEC_RECTOPS
34304b94745Smrg    if (length != 0 && length > xw->work.sizeof_sums) {
34404b94745Smrg	xw->work.sizeof_sums += length + 80;
34504b94745Smrg	xw->work.buffer_sums = realloc(xw->work.buffer_sums,
34604b94745Smrg				       xw->work.sizeof_sums);
34704b94745Smrg	xw->work.buffer_sets = realloc(xw->work.buffer_sets,
34804b94745Smrg				       xw->work.sizeof_sums);
34904b94745Smrg    }
35004b94745Smrg    xw->work.write_sums = xw->work.buffer_sums;
35104b94745Smrg#endif
3522eaa94a1Schristos
3532eaa94a1Schristos    for (s = buf; s < ptr; ++s) {
3542eaa94a1Schristos	int eight = CharOf(E2A(*s));
3552eaa94a1Schristos	int seven = eight & 0x7f;
356f2e35a3aSmrg	DECNRCM_codes cs = (eight >= 128) ? rightset : leftset;
3572eaa94a1Schristos	int chr = eight;
3582eaa94a1Schristos
35904b94745Smrg	HandleUPSS(cs);
36004b94745Smrg
36104b94745Smrg#if OPT_DEC_RECTOPS
36204b94745Smrg	if (xw->work.buffer_sums != NULL && xw->work.buffer_sets != NULL) {
36304b94745Smrg	    xw->work.buffer_sums[sums] = (Char) ((eight < 32 || eight > 255)
36404b94745Smrg						 ? ANSI_ESC
36504b94745Smrg						 : eight);
36604b94745Smrg	    xw->work.buffer_sets[sums] = cs;
36704b94745Smrg	    ++sums;
36804b94745Smrg	}
36904b94745Smrg#endif
3702eaa94a1Schristos	count++;
3712eaa94a1Schristos#if OPT_WIDE_CHARS
3722eaa94a1Schristos	/*
373f2e35a3aSmrg	 * This is only partly right - prevent inadvertent remapping of
3742eaa94a1Schristos	 * the replacement character and other non-8bit codes into bogus
3752eaa94a1Schristos	 * 8bit codes.
3762eaa94a1Schristos	 */
377e0a2b6dfSmrg	if (screen->utf8_mode || screen->utf8_nrc_mode) {
3782eaa94a1Schristos	    if (*s > 255)
3792eaa94a1Schristos		continue;
3802eaa94a1Schristos	}
3812eaa94a1Schristos#endif
382e0a2b6dfSmrg	if (*s < 32)
383e0a2b6dfSmrg	    continue;
384e0a2b6dfSmrg
3852eaa94a1Schristos	switch (cs) {
38604b94745Smrg	case nrc_DEC_UPSS:
38704b94745Smrg	    break;
38804b94745Smrg
389f2e35a3aSmrg	case nrc_ISO_Latin_1_Supp:
390e0a2b6dfSmrg	case nrc_British_Latin_1:
391e0a2b6dfSmrg	case nrc_British:	/* United Kingdom set (or Latin 1)      */
3922eaa94a1Schristos	    if ((xw->flags & NATIONAL)
3932eaa94a1Schristos		|| (screen->vtXX_level <= 1)) {
394e0a2b6dfSmrg		if ((xw->flags & NATIONAL)) {
395e0a2b6dfSmrg		    chr = seven;
396e0a2b6dfSmrg		}
3972eaa94a1Schristos		if (chr == 0x23) {
3982eaa94a1Schristos		    chr = XTERM_POUND;
399e0a2b6dfSmrg#if OPT_WIDE_CHARS
400e0a2b6dfSmrg		    if (screen->utf8_nrc_mode) {
401e0a2b6dfSmrg			chr = 0xa3;
402e0a2b6dfSmrg		    }
4032eaa94a1Schristos#endif
4042eaa94a1Schristos		}
4052eaa94a1Schristos	    }
4062eaa94a1Schristos	    break;
407d522f475Smrg
408e0a2b6dfSmrg	case nrc_DEC_Alt_Chars:
409e0a2b6dfSmrg	case nrc_DEC_Alt_Graphics:
410e0a2b6dfSmrg	case nrc_ASCII:
4112eaa94a1Schristos	    break;
412d522f475Smrg
413e0a2b6dfSmrg	case nrc_DEC_Spec_Graphic:
4142eaa94a1Schristos	    if (seven > 0x5f && seven <= 0x7e) {
415d522f475Smrg#if OPT_WIDE_CHARS
416e0a2b6dfSmrg		if (screen->utf8_mode || screen->utf8_nrc_mode)
417f2e35a3aSmrg		    chr = (int) dec2ucs(screen, (unsigned) (seven - 0x5f));
4182eaa94a1Schristos		else
419d522f475Smrg#endif
4202eaa94a1Schristos		    chr = seven - 0x5f;
421f2e35a3aSmrg	    } else if (chr == 0x5f) {
422f2e35a3aSmrg		chr = 0;
4232eaa94a1Schristos	    } else {
4242eaa94a1Schristos		chr = seven;
4252eaa94a1Schristos	    }
4262eaa94a1Schristos	    break;
4272eaa94a1Schristos
428e0a2b6dfSmrg	case nrc_DEC_Supp:
429e0a2b6dfSmrg	case nrc_DEC_Supp_Graphic:
43004b94745Smrg	    map_DEC_Supp_Graphic(chr = seven, chr = eight);
4312eaa94a1Schristos	    break;
4322eaa94a1Schristos
433e0a2b6dfSmrg	case nrc_DEC_Technical:
434f2e35a3aSmrg	    map_DEC_Technical(chr = seven);
4352eaa94a1Schristos	    break;
4362eaa94a1Schristos
437e0a2b6dfSmrg	case nrc_Dutch:
438e0a2b6dfSmrg	    map_NRCS_Dutch(chr = seven);
4392eaa94a1Schristos	    break;
4402eaa94a1Schristos
441e0a2b6dfSmrg	case nrc_Finnish:
442e0a2b6dfSmrg	case nrc_Finnish2:
443e0a2b6dfSmrg	    map_NRCS_Finnish(chr = seven);
4442eaa94a1Schristos	    break;
4452eaa94a1Schristos
446e0a2b6dfSmrg	case nrc_French:
447e0a2b6dfSmrg	case nrc_French2:
448e0a2b6dfSmrg	    map_NRCS_French(chr = seven);
4492eaa94a1Schristos	    break;
4502eaa94a1Schristos
451e0a2b6dfSmrg	case nrc_French_Canadian:
452e0a2b6dfSmrg	case nrc_French_Canadian2:
453e0a2b6dfSmrg	    map_NRCS_French_Canadian(chr = seven);
4542eaa94a1Schristos	    break;
4552eaa94a1Schristos
456e0a2b6dfSmrg	case nrc_German:
457e0a2b6dfSmrg	    map_NRCS_German(chr = seven);
4582eaa94a1Schristos	    break;
4592eaa94a1Schristos
460f2e35a3aSmrg	case nrc_Greek:
461f2e35a3aSmrg	    map_NRCS_Greek(chr = seven);	/* FIXME - ELOT? */
462f2e35a3aSmrg	    break;
463f2e35a3aSmrg
464f2e35a3aSmrg	case nrc_DEC_Greek_Supp:
465f2e35a3aSmrg	    map_DEC_Greek_Supp(chr = seven);
466f2e35a3aSmrg	    break;
467f2e35a3aSmrg
468f2e35a3aSmrg	case nrc_ISO_Greek_Supp:
469f2e35a3aSmrg	    map_ISO_Greek_Supp(chr = seven);
470f2e35a3aSmrg	    break;
471f2e35a3aSmrg
472f2e35a3aSmrg	case nrc_DEC_Hebrew_Supp:
473f2e35a3aSmrg	    map_DEC_Hebrew_Supp(chr = seven);
474f2e35a3aSmrg	    break;
475f2e35a3aSmrg
476e0a2b6dfSmrg	case nrc_Hebrew:
477f2e35a3aSmrg	    map_NRCS_Hebrew(chr = seven);
478f2e35a3aSmrg	    break;
479f2e35a3aSmrg
480f2e35a3aSmrg	case nrc_ISO_Hebrew_Supp:
481f2e35a3aSmrg	    map_ISO_Hebrew(chr = seven);
4822eaa94a1Schristos	    break;
4832eaa94a1Schristos
484e0a2b6dfSmrg	case nrc_Italian:
485e0a2b6dfSmrg	    map_NRCS_Italian(chr = seven);
486e0a2b6dfSmrg	    break;
487e0a2b6dfSmrg
488f2e35a3aSmrg	case nrc_ISO_Latin_2_Supp:
489f2e35a3aSmrg	    map_ISO_Latin_2(chr = seven);
490f2e35a3aSmrg	    break;
491f2e35a3aSmrg
492f2e35a3aSmrg	case nrc_ISO_Latin_5_Supp:
493f2e35a3aSmrg	    map_ISO_Latin_5(chr = seven);
494f2e35a3aSmrg	    break;
495f2e35a3aSmrg
496f2e35a3aSmrg	case nrc_ISO_Latin_Cyrillic:
497f2e35a3aSmrg	    map_ISO_Latin_Cyrillic(chr = seven);
498f2e35a3aSmrg	    break;
499f2e35a3aSmrg
500e0a2b6dfSmrg	case nrc_Norwegian_Danish:
501e0a2b6dfSmrg	case nrc_Norwegian_Danish2:
502e0a2b6dfSmrg	case nrc_Norwegian_Danish3:
503e0a2b6dfSmrg	    map_NRCS_Norwegian_Danish(chr = seven);
504e0a2b6dfSmrg	    break;
505e0a2b6dfSmrg
506e0a2b6dfSmrg	case nrc_Portugese:
507e0a2b6dfSmrg	    map_NRCS_Portuguese(chr = seven);
508e0a2b6dfSmrg	    break;
509e0a2b6dfSmrg
51004b94745Smrg	case nrc_SCS_NRCS:	/* vt5xx - Serbo/Croatian */
511e0a2b6dfSmrg	    /* FIXME */
512e0a2b6dfSmrg	    break;
513e0a2b6dfSmrg
514e0a2b6dfSmrg	case nrc_Spanish:
515e0a2b6dfSmrg	    map_NRCS_Spanish(chr = seven);
516e0a2b6dfSmrg	    break;
517e0a2b6dfSmrg
518e0a2b6dfSmrg	case nrc_Swedish2:
519e0a2b6dfSmrg	case nrc_Swedish:
520e0a2b6dfSmrg	    map_NRCS_Swedish(chr = seven);
521e0a2b6dfSmrg	    break;
522e0a2b6dfSmrg
523e0a2b6dfSmrg	case nrc_Swiss:
524e0a2b6dfSmrg	    map_NRCS_Swiss(chr = seven);
525e0a2b6dfSmrg	    break;
526e0a2b6dfSmrg
527e0a2b6dfSmrg	case nrc_Turkish:
528f2e35a3aSmrg	    map_NRCS_Turkish(chr = seven);
5292eaa94a1Schristos	    break;
5302eaa94a1Schristos
531f2e35a3aSmrg	case nrc_DEC_Turkish_Supp:
532f2e35a3aSmrg	    map_DEC_Turkish_Supp(chr = seven);
533f2e35a3aSmrg	    break;
534f2e35a3aSmrg
535f2e35a3aSmrg	case nrc_DEC_Cyrillic:
536f2e35a3aSmrg	    map_DEC_Cyrillic(chr = seven);
537f2e35a3aSmrg	    break;
538f2e35a3aSmrg
539f2e35a3aSmrg	case nrc_Russian:
540f2e35a3aSmrg	case nrc_Unknown:
5412eaa94a1Schristos	default:		/* any character sets we don't recognize */
5422eaa94a1Schristos	    break;
543d522f475Smrg	}
5442eaa94a1Schristos	/*
5452eaa94a1Schristos	 * The state machine already treated DEL as a nonprinting and
546f2e35a3aSmrg	 * nonspacing character.  If we have DEL now, remove it.
5472eaa94a1Schristos	 */
54804b94745Smrg	if (chr == ANSI_DEL && isSevenBit(cs)) {
549f2e35a3aSmrg	    IChar *s1;
550f2e35a3aSmrg	    --ptr;
551f2e35a3aSmrg	    for (s1 = s; s1 < ptr; ++s1) {
552f2e35a3aSmrg		s1[0] = s1[1];
553f2e35a3aSmrg	    }
55404b94745Smrg	    --count;
55504b94745Smrg#if OPT_DEC_RECTOPS
55604b94745Smrg	    --sums;
55704b94745Smrg#endif
558f2e35a3aSmrg	} else {
55904b94745Smrg	    if (eight >= 128 && chr < 128 && chr > 32)
56004b94745Smrg		chr |= 128;
561f2e35a3aSmrg	    *s = (IChar) A2E(chr);
562f2e35a3aSmrg	}
5632eaa94a1Schristos    }
5642eaa94a1Schristos    TRACE(("%d\t%s\n",
5652eaa94a1Schristos	   count,
56604b94745Smrg	   visibleIChars(buf, (size_t) length)));
5672eaa94a1Schristos    return count;
5682eaa94a1Schristos#undef MAP
569e0a2b6dfSmrg#undef UNI
570e0a2b6dfSmrg#undef XXX
571d522f475Smrg}
57204b94745Smrg
57304b94745Smrg#if OPT_DEC_RECTOPS
57404b94745Smrg/*
57504b94745Smrg * Given a mapped character, e.g., a Unicode value returned by xtermCharSetIn,
57604b94745Smrg * match it against the current GL/GR selection and return the corresponding
57704b94745Smrg * DEC internal character-set code for DECRQCRA.
57804b94745Smrg *
57904b94745Smrg * A hardware terminal presumably stores the original and mapped characters,
58004b94745Smrg * as well as the character set which was selected at that time  Doing that
58104b94745Smrg * in xterm adds a couple of bytes to every cell.
58204b94745Smrg */
58304b94745Smrgint
58404b94745SmrgxtermCharSetDec(XtermWidget xw, IChar chr, DECNRCM_codes cs)
58504b94745Smrg{
58604b94745Smrg#define MAP(from, to) case from: result = to; break;
58704b94745Smrg
58804b94745Smrg#define DFTMAP()      result = (actual | 0x80)
58904b94745Smrg#define DFT_94(chr)   result = ((actual) & 0x7f)
59004b94745Smrg#define DFT_96(chr)   result = ((actual) | 0x80)
59104b94745Smrg
59204b94745Smrg#if OPT_WIDE_CHARS
59304b94745Smrg#define UNI(from, to) case from: if (screen->utf8_nrc_mode) result = to; break;
59404b94745Smrg#define XXX(from, to) UNI(from, to)
59504b94745Smrg#else
59604b94745Smrg#define UNI(old, new) case new: result = old; break;
59704b94745Smrg#define XXX(from, to)		/* nothing */
59804b94745Smrg#endif
59904b94745Smrg
60004b94745Smrg    int result;
60104b94745Smrg
60204b94745Smrg    if (chr < 0x20
60304b94745Smrg#if OPT_WIDE_CHARS
60404b94745Smrg	|| chr > 0xff
60504b94745Smrg#endif
60604b94745Smrg	) {
60704b94745Smrg	result = ANSI_ESC;
60804b94745Smrg    } else {
60904b94745Smrg	Boolean isSeven = isSevenBit(cs);
61004b94745Smrg	TScreen *screen = TScreenOf(xw);
61104b94745Smrg
61204b94745Smrg	result = -1;
61304b94745Smrg
61404b94745Smrg	HandleUPSS(cs);
61504b94745Smrg
61604b94745Smrg	if (chr == 0xa0 && isSeven) {
61704b94745Smrg	    result = ANSI_ESC;
61804b94745Smrg	} else if (chr == ANSI_SPA && isSeven) {
61904b94745Smrg	    result = ANSI_SPA;
62004b94745Smrg	} else if ((chr == ANSI_DEL || chr == 0xff) && isSeven) {
62104b94745Smrg	    result = 0;
62204b94745Smrg	} else {
62304b94745Smrg	    int actual = (int) chr;
62404b94745Smrg	    chr &= 0x7f;
62504b94745Smrg
62604b94745Smrg	    switch (cs) {
62704b94745Smrg	    case nrc_DEC_Alt_Chars:
62804b94745Smrg	    case nrc_DEC_Alt_Graphics:
62904b94745Smrg	    case nrc_ASCII:
63004b94745Smrg		result = (int) chr;
63104b94745Smrg		break;
63204b94745Smrg
63304b94745Smrg	    case nrc_British:
63404b94745Smrg		if (chr >= 0xa0 && chr < 0xff) {
63504b94745Smrg		    if (chr == 0x23)
63604b94745Smrg			chr = 0xA3;
63704b94745Smrg		    result = (int) chr;
63804b94745Smrg		}
63904b94745Smrg		break;
64004b94745Smrg
64104b94745Smrg	    case nrc_DEC_Cyrillic:
64204b94745Smrg		unmap_DEC_Cyrillic(chr, DFT_94(chr));
64304b94745Smrg		break;
64404b94745Smrg
64504b94745Smrg	    case nrc_DEC_Spec_Graphic:
64604b94745Smrg		unmap_DEC_Spec_Graphic(chr, DFT_94(chr));
64704b94745Smrg		break;
64804b94745Smrg
64904b94745Smrg	    case nrc_DEC_Supp:
65004b94745Smrg		/* FALLTHRU */
65104b94745Smrg	    case nrc_DEC_Supp_Graphic:
65204b94745Smrg		unmap_DEC_Supp_Graphic(chr, DFTMAP());
65304b94745Smrg		break;
65404b94745Smrg
65504b94745Smrg	    case nrc_DEC_Technical:
65604b94745Smrg		unmap_DEC_Technical(chr, DFTMAP());
65704b94745Smrg		break;
65804b94745Smrg
65904b94745Smrg	    case nrc_Dutch:
66004b94745Smrg		unmap_NRCS_Dutch(chr, DFT_94(chr));
66104b94745Smrg		break;
66204b94745Smrg
66304b94745Smrg	    case nrc_Finnish:
66404b94745Smrg	    case nrc_Finnish2:
66504b94745Smrg		unmap_NRCS_Finnish(chr, DFT_94(chr));
66604b94745Smrg		break;
66704b94745Smrg
66804b94745Smrg	    case nrc_French:
66904b94745Smrg	    case nrc_French2:
67004b94745Smrg		unmap_NRCS_French(chr, DFT_94(chr));
67104b94745Smrg		break;
67204b94745Smrg
67304b94745Smrg	    case nrc_French_Canadian:
67404b94745Smrg	    case nrc_French_Canadian2:
67504b94745Smrg		unmap_NRCS_French_Canadian(chr, DFT_94(chr));
67604b94745Smrg		break;
67704b94745Smrg
67804b94745Smrg	    case nrc_German:
67904b94745Smrg		unmap_NRCS_German(chr, DFT_94(chr));
68004b94745Smrg		break;
68104b94745Smrg
68204b94745Smrg	    case nrc_Greek:
68304b94745Smrg		unmap_NRCS_Greek(chr, DFT_94(chr));
68404b94745Smrg		break;
68504b94745Smrg
68604b94745Smrg	    case nrc_DEC_Greek_Supp:
68704b94745Smrg		unmap_DEC_Greek_Supp(chr, DFTMAP());
68804b94745Smrg		break;
68904b94745Smrg
69004b94745Smrg	    case nrc_ISO_Greek_Supp:
69104b94745Smrg		unmap_ISO_Greek_Supp(chr, DFTMAP());
69204b94745Smrg		break;
69304b94745Smrg
69404b94745Smrg	    case nrc_DEC_Hebrew_Supp:
69504b94745Smrg		unmap_DEC_Hebrew_Supp(chr, DFTMAP());
69604b94745Smrg		break;
69704b94745Smrg
69804b94745Smrg	    case nrc_Hebrew:
69904b94745Smrg		unmap_NRCS_Hebrew(chr, DFT_94(chr));
70004b94745Smrg		break;
70104b94745Smrg
70204b94745Smrg	    case nrc_ISO_Hebrew_Supp:
70304b94745Smrg		unmap_ISO_Hebrew(chr, DFTMAP());
70404b94745Smrg		break;
70504b94745Smrg
70604b94745Smrg	    case nrc_Italian:
70704b94745Smrg		unmap_NRCS_Italian(chr, DFT_94(chr));
70804b94745Smrg		break;
70904b94745Smrg
71004b94745Smrg	    case nrc_ISO_Latin_1_Supp:
71104b94745Smrg		unmap_ISO_Latin_1(chr, DFTMAP());
71204b94745Smrg		break;
71304b94745Smrg
71404b94745Smrg	    case nrc_ISO_Latin_2_Supp:
71504b94745Smrg		unmap_ISO_Latin_2(chr, DFTMAP());
71604b94745Smrg		break;
71704b94745Smrg
71804b94745Smrg	    case nrc_ISO_Latin_5_Supp:
71904b94745Smrg		unmap_ISO_Latin_5(chr, DFTMAP());
72004b94745Smrg		break;
72104b94745Smrg
72204b94745Smrg	    case nrc_ISO_Latin_Cyrillic:
72304b94745Smrg		unmap_ISO_Latin_Cyrillic(chr, DFTMAP());
72404b94745Smrg		break;
72504b94745Smrg
72604b94745Smrg	    case nrc_Norwegian_Danish:
72704b94745Smrg	    case nrc_Norwegian_Danish2:
72804b94745Smrg	    case nrc_Norwegian_Danish3:
72904b94745Smrg		unmap_NRCS_Norwegian_Danish(chr, DFT_94(chr));
73004b94745Smrg		break;
73104b94745Smrg
73204b94745Smrg	    case nrc_Portugese:
73304b94745Smrg		unmap_NRCS_Portuguese(chr, DFT_94(chr));
73404b94745Smrg		break;
73504b94745Smrg
73604b94745Smrg	    case nrc_Spanish:
73704b94745Smrg		unmap_NRCS_Spanish(chr, DFT_94(chr));
73804b94745Smrg		break;
73904b94745Smrg
74004b94745Smrg	    case nrc_Swedish:
74104b94745Smrg	    case nrc_Swedish2:
74204b94745Smrg		unmap_NRCS_Swedish(chr, DFT_94(chr));
74304b94745Smrg		break;
74404b94745Smrg
74504b94745Smrg	    case nrc_Swiss:
74604b94745Smrg		unmap_NRCS_Swiss(chr, DFT_94(chr));
74704b94745Smrg		break;
74804b94745Smrg
74904b94745Smrg	    case nrc_DEC_Turkish_Supp:
75004b94745Smrg		unmap_DEC_Turkish_Supp(chr, DFTMAP());
75104b94745Smrg		break;
75204b94745Smrg
75304b94745Smrg	    case nrc_Turkish:
75404b94745Smrg		unmap_NRCS_Turkish(chr, DFT_94(chr));
75504b94745Smrg		break;
75604b94745Smrg
75704b94745Smrg	    case nrc_British_Latin_1:
75804b94745Smrg	    case nrc_SCS_NRCS:
75904b94745Smrg	    case nrc_Russian:
76004b94745Smrg	    case nrc_Unknown:
76104b94745Smrg	    case nrc_DEC_UPSS:
76204b94745Smrg	    default:		/* anything we cannot unmap */
76304b94745Smrg		break;
76404b94745Smrg	    }
76504b94745Smrg	    if (result < 0) {
76604b94745Smrg		if (isSeven) {
76704b94745Smrg		    DFT_94(chr);
76804b94745Smrg		} else {
76904b94745Smrg		    DFT_96(chr);
77004b94745Smrg		}
77104b94745Smrg	    }
77204b94745Smrg	}
77304b94745Smrg    }
77404b94745Smrg    return result;
77504b94745Smrg#undef MAP
77604b94745Smrg#undef UNI
77704b94745Smrg#undef XXX
77804b94745Smrg}
77904b94745Smrg#endif /* OPT_DEC_RECTOPS */
780