charsets.c revision d522f475
1/* $XTermId: charsets.c,v 1.36 2007/03/19 23:47:00 tom Exp $ */ 2 3/* 4 * $XFree86: xc/programs/xterm/charsets.c,v 1.12 2005/01/14 01:50:02 dickey Exp $ 5 */ 6 7/************************************************************ 8 9Copyright 1998-2006,2007 by Thomas E. Dickey 10 11 All Rights Reserved 12 13Permission is hereby granted, free of charge, to any person obtaining a 14copy of this software and associated documentation files (the 15"Software"), to deal in the Software without restriction, including 16without limitation the rights to use, copy, modify, merge, publish, 17distribute, sublicense, and/or sell copies of the Software, and to 18permit persons to whom the Software is furnished to do so, subject to 19the following conditions: 20 21The above copyright notice and this permission notice shall be included 22in all copies or substantial portions of the Software. 23 24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 25OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 28CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 30SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 32Except as contained in this notice, the name(s) of the above copyright 33holders shall not be used in advertising or otherwise to promote the 34sale, use or other dealings in this Software without prior written 35authorization. 36 37********************************************************/ 38 39#include <xterm.h> 40#include <data.h> 41#include <fontutils.h> 42 43#include <X11/keysym.h> 44 45/* 46 * This module performs translation as needed to support the DEC VT220 national 47 * replacement character sets. We assume that xterm's font is based on the ISO 48 * 8859-1 (Latin 1) character set, which is almost the same as the DEC 49 * multinational character set. Glyph positions 0-31 have to be the DEC 50 * graphic characters, though. 51 * 52 * References: 53 * "VT220 Programmer Pocket Guide" EK-VT220-HR-002 (2nd ed., 1984), which 54 * contains character charts for the national character sets. 55 * "VT330/VT340 Programmer Reference Manual Volume 1: Text Programming" 56 * EK-VT3XX-TP-001 (1st ed, 1987), which contains a table (2-1) 57 * listing the glyphs which are mapped from the multinational 58 * character set to the national character set. 59 * 60 * The latter reference, though easier to read, has a few errors and omissions. 61 */ 62 63/* 64 * Translate an input keysym to the corresponding NRC keysym. 65 */ 66unsigned xtermCharSetIn(unsigned code, int charset) 67{ 68 if (code >= 128 && code < 256) { 69 switch (charset) { 70 case 'A': /* United Kingdom set (or Latin 1) */ 71 if (code == XK_sterling) 72 code = 0x23; 73 code &= 0x7f; 74 break; 75 76#if OPT_XMC_GLITCH 77 case '?': 78#endif 79 case '1': /* Alternate Character ROM standard characters */ 80 case '2': /* Alternate Character ROM special graphics */ 81 case 'B': /* ASCII set */ 82 break; 83 84 case '0': /* special graphics (line drawing) */ 85 break; 86 87 case '4': /* Dutch */ 88 switch (code) { 89 case XK_sterling: code = 0x23; break; 90 case XK_threequarters: code = 0x40; break; 91 case XK_ydiaeresis: code = 0x5b; break; 92 case XK_onehalf: code = 0x5c; break; 93 /* N/A case XK_bar: code = 0x5d; break; */ 94 case XK_diaeresis: code = 0x7b; break; 95 /* N/A case XK_f: code = 0x7c; break; */ 96 case XK_onequarter: code = 0x7d; break; 97 case XK_acute: code = 0x7e; break; 98 } 99 break; 100 101 case 'C': 102 case '5': /* Finnish */ 103 switch (code) { 104 case XK_Adiaeresis: code = 0x5b; break; 105 case XK_Odiaeresis: code = 0x5c; break; 106 case XK_Aring: code = 0x5d; break; 107 case XK_Udiaeresis: code = 0x5e; break; 108 case XK_eacute: code = 0x60; break; 109 case XK_adiaeresis: code = 0x7b; break; 110 case XK_odiaeresis: code = 0x7c; break; 111 case XK_aring: code = 0x7d; break; 112 case XK_udiaeresis: code = 0x7e; break; 113 } 114 break; 115 116 case 'R': /* French */ 117 switch (code) { 118 case XK_sterling: code = 0x23; break; 119 case XK_agrave: code = 0x40; break; 120 case XK_degree: code = 0x5b; break; 121 case XK_ccedilla: code = 0x5c; break; 122 case XK_section: code = 0x5d; break; 123 case XK_eacute: code = 0x7b; break; 124 case XK_ugrave: code = 0x7c; break; 125 case XK_egrave: code = 0x7d; break; 126 case XK_diaeresis: code = 0x7e; break; 127 } 128 break; 129 130 case 'Q': /* French Canadian */ 131 switch (code) { 132 case XK_agrave: code = 0x40; break; 133 case XK_acircumflex: code = 0x5b; break; 134 case XK_ccedilla: code = 0x5c; break; 135 case XK_ecircumflex: code = 0x5d; break; 136 case XK_icircumflex: code = 0x5e; break; 137 case XK_ocircumflex: code = 0x60; break; 138 case XK_eacute: code = 0x7b; break; 139 case XK_ugrave: code = 0x7c; break; 140 case XK_egrave: code = 0x7d; break; 141 case XK_ucircumflex: code = 0x7e; break; 142 } 143 break; 144 145 case 'K': /* German */ 146 switch (code) { 147 case XK_section: code = 0x40; break; 148 case XK_Adiaeresis: code = 0x5b; break; 149 case XK_Odiaeresis: code = 0x5c; break; 150 case XK_Udiaeresis: code = 0x5d; break; 151 case XK_adiaeresis: code = 0x7b; break; 152 case XK_odiaeresis: code = 0x7c; break; 153 case XK_udiaeresis: code = 0x7d; break; 154 case XK_ssharp: code = 0x7e; break; 155 } 156 break; 157 158 case 'Y': /* Italian */ 159 switch (code) { 160 case XK_sterling: code = 0x23; break; 161 case XK_section: code = 0x40; break; 162 case XK_degree: code = 0x5b; break; 163 case XK_ccedilla: code = 0x5c; break; 164 case XK_eacute: code = 0x5d; break; 165 case XK_ugrave: code = 0x60; break; 166 case XK_agrave: code = 0x7b; break; 167 case XK_ograve: code = 0x7c; break; 168 case XK_egrave: code = 0x7d; break; 169 case XK_igrave: code = 0x7e; break; 170 } 171 break; 172 173 case 'E': 174 case '6': /* Norwegian/Danish */ 175 switch (code) { 176 case XK_Adiaeresis: code = 0x40; break; 177 case XK_AE: code = 0x5b; break; 178 case XK_Ooblique: code = 0x5c; break; 179 case XK_Aring: code = 0x5d; break; 180 case XK_Udiaeresis: code = 0x5e; break; 181 case XK_adiaeresis: code = 0x60; break; 182 case XK_ae: code = 0x7b; break; 183 case XK_oslash: code = 0x7c; break; 184 case XK_aring: code = 0x7d; break; 185 case XK_udiaeresis: code = 0x7e; break; 186 } 187 break; 188 189 case 'Z': /* Spanish */ 190 switch (code) { 191 case XK_sterling: code = 0x23; break; 192 case XK_section: code = 0x40; break; 193 case XK_exclamdown: code = 0x5b; break; 194 case XK_Ntilde: code = 0x5c; break; 195 case XK_questiondown: code = 0x5d; break; 196 case XK_degree: code = 0x7b; break; 197 case XK_ntilde: code = 0x7c; break; 198 case XK_ccedilla: code = 0x7d; break; 199 } 200 break; 201 202 case 'H': 203 case '7': /* Swedish */ 204 switch (code) { 205 case XK_Eacute: code = 0x40; break; 206 case XK_Adiaeresis: code = 0x5b; break; 207 case XK_Odiaeresis: code = 0x5c; break; 208 case XK_Aring: code = 0x5d; break; 209 case XK_Udiaeresis: code = 0x5e; break; 210 case XK_eacute: code = 0x60; break; 211 case XK_adiaeresis: code = 0x7b; break; 212 case XK_odiaeresis: code = 0x7c; break; 213 case XK_aring: code = 0x7d; break; 214 case XK_udiaeresis: code = 0x7e; break; 215 } 216 break; 217 218 case '=': /* Swiss */ 219 switch (code) { 220 case XK_ugrave: code = 0x23; break; 221 case XK_agrave: code = 0x40; break; 222 case XK_eacute: code = 0x5b; break; 223 case XK_ccedilla: code = 0x5c; break; 224 case XK_ecircumflex: code = 0x5d; break; 225 case XK_icircumflex: code = 0x5e; break; 226 case XK_egrave: code = 0x5f; break; 227 case XK_ocircumflex: code = 0x60; break; 228 case XK_adiaeresis: code = 0x7b; break; 229 case XK_odiaeresis: code = 0x7c; break; 230 case XK_udiaeresis: code = 0x7d; break; 231 case XK_ucircumflex: code = 0x7e; break; 232 } 233 break; 234 235 default: /* any character sets we don't recognize*/ 236 break; 237 } 238 code &= 0x7f; /* NRC in any case is 7-bit */ 239 } 240 return code; 241} 242 243/* 244 * Translate a string to the display form. This assumes the font has the 245 * DEC graphic characters in cells 0-31, and otherwise is ISO-8859-1. 246 */ 247int xtermCharSetOut(IChar *buf, IChar *ptr, int leftset) 248{ 249 IChar *s; 250 register TScreen *screen = TScreenOf(term); 251 int count = 0; 252 int rightset = screen->gsets[(int)(screen->curgr)]; 253 254 TRACE(("CHARSET GL=%c(G%d) GR=%c(G%d) SS%d:%s\n", 255 leftset, screen->curgl, 256 rightset, screen->curgr, 257 screen->curss, 258 visibleIChar(buf, (unsigned)(ptr - buf)))); 259 260 for (s = buf; s < ptr; ++s) { 261 int eight = CharOf(E2A(*s)); 262 int seven = eight & 0x7f; 263 int cs = (eight >= 128) ? rightset : leftset; 264 int chr = eight; 265 266 count++; 267 switch (cs) { 268 case 'A': /* United Kingdom set (or Latin 1) */ 269 if ((term->flags & NATIONAL) 270 || (screen->vtXX_level <= 1)) { 271 if (chr == 0x23) { 272 chr = XTERM_POUND; /* UK pound sign*/ 273 } 274 } else { 275 chr = (seven | 0x80); 276 } 277 break; 278 279#if OPT_XMC_GLITCH 280 case '?': 281#endif 282 case '1': /* Alternate Character ROM standard characters */ 283 case '2': /* Alternate Character ROM special graphics */ 284 case 'B': /* ASCII set */ 285 break; 286 287 case '0': /* special graphics (line drawing) */ 288 if (seven > 0x5f && seven <= 0x7e) { 289#if OPT_WIDE_CHARS 290 if (screen->utf8_mode) 291 chr = dec2ucs((unsigned)(seven - 0x5f)); 292 else 293#endif 294 chr = seven - 0x5f; 295 } else { 296 chr = seven; 297 } 298 break; 299 300 case '4': /* Dutch */ 301 switch (chr = seven) { 302 case 0x23: chr = XK_sterling; break; 303 case 0x40: chr = XK_threequarters; break; 304 case 0x5b: chr = XK_ydiaeresis; break; 305 case 0x5c: chr = XK_onehalf; break; 306 case 0x5d: chr = XK_bar; break; 307 case 0x7b: chr = XK_diaeresis; break; 308 case 0x7c: chr = XK_f; break; 309 case 0x7d: chr = XK_onequarter; break; 310 case 0x7e: chr = XK_acute; break; 311 } 312 break; 313 314 case 'C': 315 case '5': /* Finnish */ 316 switch (chr = seven) { 317 case 0x5b: chr = XK_Adiaeresis; break; 318 case 0x5c: chr = XK_Odiaeresis; break; 319 case 0x5d: chr = XK_Aring; break; 320 case 0x5e: chr = XK_Udiaeresis; break; 321 case 0x60: chr = XK_eacute; break; 322 case 0x7b: chr = XK_adiaeresis; break; 323 case 0x7c: chr = XK_odiaeresis; break; 324 case 0x7d: chr = XK_aring; break; 325 case 0x7e: chr = XK_udiaeresis; break; 326 } 327 break; 328 329 case 'R': /* French */ 330 switch (chr = seven) { 331 case 0x23: chr = XK_sterling; break; 332 case 0x40: chr = XK_agrave; break; 333 case 0x5b: chr = XK_degree; break; 334 case 0x5c: chr = XK_ccedilla; break; 335 case 0x5d: chr = XK_section; break; 336 case 0x7b: chr = XK_eacute; break; 337 case 0x7c: chr = XK_ugrave; break; 338 case 0x7d: chr = XK_egrave; break; 339 case 0x7e: chr = XK_diaeresis; break; 340 } 341 break; 342 343 case 'Q': /* French Canadian */ 344 switch (chr = seven) { 345 case 0x40: chr = XK_agrave; break; 346 case 0x5b: chr = XK_acircumflex; break; 347 case 0x5c: chr = XK_ccedilla; break; 348 case 0x5d: chr = XK_ecircumflex; break; 349 case 0x5e: chr = XK_icircumflex; break; 350 case 0x60: chr = XK_ocircumflex; break; 351 case 0x7b: chr = XK_eacute; break; 352 case 0x7c: chr = XK_ugrave; break; 353 case 0x7d: chr = XK_egrave; break; 354 case 0x7e: chr = XK_ucircumflex; break; 355 } 356 break; 357 358 case 'K': /* German */ 359 switch (chr = seven) { 360 case 0x40: chr = XK_section; break; 361 case 0x5b: chr = XK_Adiaeresis; break; 362 case 0x5c: chr = XK_Odiaeresis; break; 363 case 0x5d: chr = XK_Udiaeresis; break; 364 case 0x7b: chr = XK_adiaeresis; break; 365 case 0x7c: chr = XK_odiaeresis; break; 366 case 0x7d: chr = XK_udiaeresis; break; 367 case 0x7e: chr = XK_ssharp; break; 368 } 369 break; 370 371 case 'Y': /* Italian */ 372 switch (chr = seven) { 373 case 0x23: chr = XK_sterling; break; 374 case 0x40: chr = XK_section; break; 375 case 0x5b: chr = XK_degree; break; 376 case 0x5c: chr = XK_ccedilla; break; 377 case 0x5d: chr = XK_eacute; break; 378 case 0x60: chr = XK_ugrave; break; 379 case 0x7b: chr = XK_agrave; break; 380 case 0x7c: chr = XK_ograve; break; 381 case 0x7d: chr = XK_egrave; break; 382 case 0x7e: chr = XK_igrave; break; 383 } 384 break; 385 386 case 'E': 387 case '6': /* Norwegian/Danish */ 388 switch (chr = seven) { 389 case 0x40: chr = XK_Adiaeresis; break; 390 case 0x5b: chr = XK_AE; break; 391 case 0x5c: chr = XK_Ooblique; break; 392 case 0x5d: chr = XK_Aring; break; 393 case 0x5e: chr = XK_Udiaeresis; break; 394 case 0x60: chr = XK_adiaeresis; break; 395 case 0x7b: chr = XK_ae; break; 396 case 0x7c: chr = XK_oslash; break; 397 case 0x7d: chr = XK_aring; break; 398 case 0x7e: chr = XK_udiaeresis; break; 399 } 400 break; 401 402 case 'Z': /* Spanish */ 403 switch (chr = seven) { 404 case 0x23: chr = XK_sterling; break; 405 case 0x40: chr = XK_section; break; 406 case 0x5b: chr = XK_exclamdown; break; 407 case 0x5c: chr = XK_Ntilde; break; 408 case 0x5d: chr = XK_questiondown; break; 409 case 0x7b: chr = XK_degree; break; 410 case 0x7c: chr = XK_ntilde; break; 411 case 0x7d: chr = XK_ccedilla; break; 412 } 413 break; 414 415 case 'H': 416 case '7': /* Swedish */ 417 switch (chr = seven) { 418 case 0x40: chr = XK_Eacute; break; 419 case 0x5b: chr = XK_Adiaeresis; break; 420 case 0x5c: chr = XK_Odiaeresis; break; 421 case 0x5d: chr = XK_Aring; break; 422 case 0x5e: chr = XK_Udiaeresis; break; 423 case 0x60: chr = XK_eacute; break; 424 case 0x7b: chr = XK_adiaeresis; break; 425 case 0x7c: chr = XK_odiaeresis; break; 426 case 0x7d: chr = XK_aring; break; 427 case 0x7e: chr = XK_udiaeresis; break; 428 } 429 break; 430 431 case '=': /* Swiss */ 432 switch (chr = seven) { 433 case 0x23: chr = XK_ugrave; break; 434 case 0x40: chr = XK_agrave; break; 435 case 0x5b: chr = XK_eacute; break; 436 case 0x5c: chr = XK_ccedilla; break; 437 case 0x5d: chr = XK_ecircumflex; break; 438 case 0x5e: chr = XK_icircumflex; break; 439 case 0x5f: chr = XK_egrave; break; 440 case 0x60: chr = XK_ocircumflex; break; 441 case 0x7b: chr = XK_adiaeresis; break; 442 case 0x7c: chr = XK_odiaeresis; break; 443 case 0x7d: chr = XK_udiaeresis; break; 444 case 0x7e: chr = XK_ucircumflex; break; 445 } 446 break; 447 448 default: /* any character sets we don't recognize*/ 449 count --; 450 break; 451 } 452 /* 453 * The state machine already treated DEL as a nonprinting and 454 * nonspacing character. If we have DEL now, simply render 455 * it as a blank. 456 */ 457 if (chr == ANSI_DEL) 458 chr = ' '; 459 *s = A2E(chr); 460 } 461 return count; 462} 463