xenocara/app/xterm/charsets.c
2011-09-17 11:51:57 +00:00

486 lines
12 KiB
C

/* $XTermId: charsets.c,v 1.42 2011/09/11 14:40:17 tom Exp $ */
/*
* Copyright 1998-2009,2011 by Thomas E. Dickey
*
* All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the
* sale, use or other dealings in this Software without prior written
* authorization.
*
*/
#include <xterm.h>
#include <data.h>
#include <fontutils.h>
#include <X11/keysym.h>
/*
* This module performs translation as needed to support the DEC VT220 national
* replacement character sets. We assume that xterm's font is based on the ISO
* 8859-1 (Latin 1) character set, which is almost the same as the DEC
* multinational character set. Glyph positions 0-31 have to be the DEC
* graphic characters, though.
*
* References:
* "VT220 Programmer Pocket Guide" EK-VT220-HR-002 (2nd ed., 1984), which
* contains character charts for the national character sets.
* "VT330/VT340 Programmer Reference Manual Volume 1: Text Programming"
* EK-VT3XX-TP-001 (1st ed, 1987), which contains a table (2-1)
* listing the glyphs which are mapped from the multinational
* character set to the national character set.
*
* The latter reference, though easier to read, has a few errors and omissions.
*/
/*
* Translate an input keysym to the corresponding NRC keysym.
*/
unsigned
xtermCharSetIn(unsigned code, int charset)
{
#define MAP(to, from) case from: code = to; break
if (code >= 128 && code < 256) {
switch (charset) {
case 'A': /* United Kingdom set (or Latin 1) */
if (code == XK_sterling)
code = 0x23;
code &= 0x7f;
break;
#if OPT_XMC_GLITCH
case '?':
#endif
case '1': /* Alternate Character ROM standard characters */
case '2': /* Alternate Character ROM special graphics */
case 'B': /* ASCII set */
break;
case '0': /* special graphics (line drawing) */
break;
case '4': /* Dutch */
switch (code) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_threequarters);
MAP(0x5b, XK_ydiaeresis);
MAP(0x5c, XK_onehalf);
MAP(0x5d, XK_bar); /* glyph is not ISO-8859-1 */
MAP(0x7b, XK_diaeresis);
MAP(0x7c, XK_f); /* glyph is not ISO-8859-1 */
MAP(0x7d, XK_onequarter);
MAP(0x7e, XK_acute);
}
break;
case 'C':
case '5': /* Finnish */
switch (code) {
MAP(0x5b, XK_Adiaeresis);
MAP(0x5c, XK_Odiaeresis);
MAP(0x5d, XK_Aring);
MAP(0x5e, XK_Udiaeresis);
MAP(0x60, XK_eacute);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_aring);
MAP(0x7e, XK_udiaeresis);
}
break;
case 'R': /* French */
switch (code) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_agrave);
MAP(0x5b, XK_degree);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_section);
MAP(0x7b, XK_eacute);
MAP(0x7c, XK_ugrave);
MAP(0x7d, XK_egrave);
MAP(0x7e, XK_diaeresis);
}
break;
case 'Q': /* French Canadian */
switch (code) {
MAP(0x40, XK_agrave);
MAP(0x5b, XK_acircumflex);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_ecircumflex);
MAP(0x5e, XK_icircumflex);
MAP(0x60, XK_ocircumflex);
MAP(0x7b, XK_eacute);
MAP(0x7c, XK_ugrave);
MAP(0x7d, XK_egrave);
MAP(0x7e, XK_ucircumflex);
}
break;
case 'K': /* German */
switch (code) {
MAP(0x40, XK_section);
MAP(0x5b, XK_Adiaeresis);
MAP(0x5c, XK_Odiaeresis);
MAP(0x5d, XK_Udiaeresis);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_udiaeresis);
MAP(0x7e, XK_ssharp);
}
break;
case 'Y': /* Italian */
switch (code) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_section);
MAP(0x5b, XK_degree);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_eacute);
MAP(0x60, XK_ugrave);
MAP(0x7b, XK_agrave);
MAP(0x7c, XK_ograve);
MAP(0x7d, XK_egrave);
MAP(0x7e, XK_igrave);
}
break;
case 'E':
case '6': /* Norwegian/Danish */
switch (code) {
MAP(0x40, XK_Adiaeresis);
MAP(0x5b, XK_AE);
MAP(0x5c, XK_Ooblique);
MAP(0x5d, XK_Aring);
MAP(0x5e, XK_Udiaeresis);
MAP(0x60, XK_adiaeresis);
MAP(0x7b, XK_ae);
MAP(0x7c, XK_oslash);
MAP(0x7d, XK_aring);
MAP(0x7e, XK_udiaeresis);
}
break;
case 'Z': /* Spanish */
switch (code) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_section);
MAP(0x5b, XK_exclamdown);
MAP(0x5c, XK_Ntilde);
MAP(0x5d, XK_questiondown);
MAP(0x7b, XK_degree);
MAP(0x7c, XK_ntilde);
MAP(0x7d, XK_ccedilla);
}
break;
case 'H':
case '7': /* Swedish */
switch (code) {
MAP(0x40, XK_Eacute);
MAP(0x5b, XK_Adiaeresis);
MAP(0x5c, XK_Odiaeresis);
MAP(0x5d, XK_Aring);
MAP(0x5e, XK_Udiaeresis);
MAP(0x60, XK_eacute);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_aring);
MAP(0x7e, XK_udiaeresis);
}
break;
case '=': /* Swiss */
switch (code) {
MAP(0x23, XK_ugrave);
MAP(0x40, XK_agrave);
MAP(0x5b, XK_eacute);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_ecircumflex);
MAP(0x5e, XK_icircumflex);
MAP(0x5f, XK_egrave);
MAP(0x60, XK_ocircumflex);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_udiaeresis);
MAP(0x7e, XK_ucircumflex);
}
break;
default: /* any character sets we don't recognize */
break;
}
code &= 0x7f; /* NRC in any case is 7-bit */
}
return code;
#undef MAP
}
/*
* Translate a string to the display form. This assumes the font has the
* DEC graphic characters in cells 0-31, and otherwise is ISO-8859-1.
*/
int
xtermCharSetOut(XtermWidget xw, IChar * buf, IChar * ptr, int leftset)
{
IChar *s;
TScreen *screen = TScreenOf(xw);
int count = 0;
int rightset = screen->gsets[(int) (screen->curgr)];
#define MAP(from, to) case from: chr = to; break
TRACE(("CHARSET GL=%c(G%d) GR=%c(G%d) SS%d\n\t%s\n",
leftset, screen->curgl,
rightset, screen->curgr,
screen->curss,
visibleIChar(buf, (unsigned) (ptr - buf))));
for (s = buf; s < ptr; ++s) {
int eight = CharOf(E2A(*s));
int seven = eight & 0x7f;
int cs = (eight >= 128) ? rightset : leftset;
int chr = eight;
count++;
#if OPT_WIDE_CHARS
/*
* This is only partly right - prevent inadvertant remapping of
* the replacement character and other non-8bit codes into bogus
* 8bit codes.
*/
if (screen->utf8_mode) {
if (*s > 255)
continue;
}
#endif
switch (cs) {
case 'A': /* United Kingdom set (or Latin 1) */
if ((xw->flags & NATIONAL)
|| (screen->vtXX_level <= 1)) {
if (chr == 0x23) {
#if OPT_WIDE_CHARS
chr = (screen->utf8_mode
? 0xa3
: XTERM_POUND);
#else
chr = XTERM_POUND;
#endif
}
} else {
chr = (seven | 0x80);
}
break;
#if OPT_XMC_GLITCH
case '?':
#endif
case '1': /* Alternate Character ROM standard characters */
case '2': /* Alternate Character ROM special graphics */
case 'B': /* ASCII set */
break;
case '0': /* special graphics (line drawing) */
if (seven > 0x5f && seven <= 0x7e) {
#if OPT_WIDE_CHARS
if (screen->utf8_mode)
chr = (int) dec2ucs((unsigned) (seven - 0x5f));
else
#endif
chr = seven - 0x5f;
} else {
chr = seven;
}
break;
case '4': /* Dutch */
switch (chr = seven) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_threequarters);
MAP(0x5b, XK_ydiaeresis);
MAP(0x5c, XK_onehalf);
MAP(0x5d, XK_bar);
MAP(0x7b, XK_diaeresis);
MAP(0x7c, XK_f);
MAP(0x7d, XK_onequarter);
MAP(0x7e, XK_acute);
}
break;
case 'C':
case '5': /* Finnish */
switch (chr = seven) {
MAP(0x5b, XK_Adiaeresis);
MAP(0x5c, XK_Odiaeresis);
MAP(0x5d, XK_Aring);
MAP(0x5e, XK_Udiaeresis);
MAP(0x60, XK_eacute);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_aring);
MAP(0x7e, XK_udiaeresis);
}
break;
case 'R': /* French */
switch (chr = seven) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_agrave);
MAP(0x5b, XK_degree);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_section);
MAP(0x7b, XK_eacute);
MAP(0x7c, XK_ugrave);
MAP(0x7d, XK_egrave);
MAP(0x7e, XK_diaeresis);
}
break;
case 'Q': /* French Canadian */
switch (chr = seven) {
MAP(0x40, XK_agrave);
MAP(0x5b, XK_acircumflex);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_ecircumflex);
MAP(0x5e, XK_icircumflex);
MAP(0x60, XK_ocircumflex);
MAP(0x7b, XK_eacute);
MAP(0x7c, XK_ugrave);
MAP(0x7d, XK_egrave);
MAP(0x7e, XK_ucircumflex);
}
break;
case 'K': /* German */
switch (chr = seven) {
MAP(0x40, XK_section);
MAP(0x5b, XK_Adiaeresis);
MAP(0x5c, XK_Odiaeresis);
MAP(0x5d, XK_Udiaeresis);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_udiaeresis);
MAP(0x7e, XK_ssharp);
}
break;
case 'Y': /* Italian */
switch (chr = seven) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_section);
MAP(0x5b, XK_degree);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_eacute);
MAP(0x60, XK_ugrave);
MAP(0x7b, XK_agrave);
MAP(0x7c, XK_ograve);
MAP(0x7d, XK_egrave);
MAP(0x7e, XK_igrave);
}
break;
case 'E':
case '6': /* Norwegian/Danish */
switch (chr = seven) {
MAP(0x40, XK_Adiaeresis);
MAP(0x5b, XK_AE);
MAP(0x5c, XK_Ooblique);
MAP(0x5d, XK_Aring);
MAP(0x5e, XK_Udiaeresis);
MAP(0x60, XK_adiaeresis);
MAP(0x7b, XK_ae);
MAP(0x7c, XK_oslash);
MAP(0x7d, XK_aring);
MAP(0x7e, XK_udiaeresis);
}
break;
case 'Z': /* Spanish */
switch (chr = seven) {
MAP(0x23, XK_sterling);
MAP(0x40, XK_section);
MAP(0x5b, XK_exclamdown);
MAP(0x5c, XK_Ntilde);
MAP(0x5d, XK_questiondown);
MAP(0x7b, XK_degree);
MAP(0x7c, XK_ntilde);
MAP(0x7d, XK_ccedilla);
}
break;
case 'H':
case '7': /* Swedish */
switch (chr = seven) {
MAP(0x40, XK_Eacute);
MAP(0x5b, XK_Adiaeresis);
MAP(0x5c, XK_Odiaeresis);
MAP(0x5d, XK_Aring);
MAP(0x5e, XK_Udiaeresis);
MAP(0x60, XK_eacute);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_aring);
MAP(0x7e, XK_udiaeresis);
}
break;
case '=': /* Swiss */
switch (chr = seven) {
MAP(0x23, XK_ugrave);
MAP(0x40, XK_agrave);
MAP(0x5b, XK_eacute);
MAP(0x5c, XK_ccedilla);
MAP(0x5d, XK_ecircumflex);
MAP(0x5e, XK_icircumflex);
MAP(0x5f, XK_egrave);
MAP(0x60, XK_ocircumflex);
MAP(0x7b, XK_adiaeresis);
MAP(0x7c, XK_odiaeresis);
MAP(0x7d, XK_udiaeresis);
MAP(0x7e, XK_ucircumflex);
}
break;
default: /* any character sets we don't recognize */
count--;
break;
}
/*
* The state machine already treated DEL as a nonprinting and
* nonspacing character. If we have DEL now, simply render
* it as a blank.
*/
if (chr == ANSI_DEL)
chr = ' ';
*s = (IChar) A2E(chr);
}
TRACE(("%d\t%s\n",
count,
visibleIChar(buf, (unsigned) (ptr - buf))));
return count;
#undef MAP
}