charsets.c revision 5104ee6e
1/* $XTermId: charsets.c,v 1.129 2024/10/03 22:21:32 tom Exp $ */ 2 3/* 4 * Copyright 1998-2023,2024 by Thomas E. Dickey 5 * 6 * All Rights Reserved 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the 29 * sale, use or other dealings in this Software without prior written 30 * authorization. 31 * 32 */ 33 34#include <assert.h> 35#include <X11/keysym.h> 36 37#include <xterm.h> 38#include <data.h> 39#include <charsets.h> 40#include <fontutils.h> 41 42/* 43 * This module performs translation as needed to support the DEC VT220 national 44 * replacement character sets as well as supplementary character sets (aka 45 * code-pages) introduced in VT320, etc. 46 * 47 * We assume that xterm's font is based on the ISO 8859-1 (Latin 1) character 48 * set, which is almost the same as the DEC multinational character set. Glyph 49 * positions 0-31 have to be the DEC graphic characters, though. 50 * 51 * References: 52 * "VT220 Programmer Pocket Guide" EK-VT220-HR-002 (2nd ed., 1984), which 53 * contains character charts for the national character sets. 54 * "VT330/VT340 Programmer Reference Manual Volume 1: Text Programming" 55 * EK-VT3XX-TP-001 (1st ed, 1987), which contains a table (2-1) 56 * listing the glyphs which are mapped from the multinational 57 * character set to the national character set. 58 * 59 * The latter reference, though easier to read, has a few errors and omissions. 60 */ 61 62#define HandleUPSS(charset) \ 63 if (charset == nrc_DEC_UPSS) { \ 64 charset = screen->gsets_upss; \ 65 if (screen->vtXX_level >= 5) { \ 66 /* EMPTY */ ; \ 67 } else if (screen->vtXX_level >= 3) { \ 68 if (charset != nrc_DEC_Supp) \ 69 charset = nrc_ISO_Latin_1_Supp; \ 70 } else if (screen->vtXX_level < 2) { \ 71 charset = nrc_ASCII; \ 72 } \ 73 } 74 75static Boolean 76isSevenBit(DECNRCM_codes cs) 77{ 78 Boolean result = False; 79 80 switch (cs) { 81 case nrc_ISO_Greek_Supp: 82 case nrc_ISO_Hebrew_Supp: 83 case nrc_ISO_Latin_1_Supp: 84 case nrc_ISO_Latin_2_Supp: 85 case nrc_ISO_Latin_5_Supp: 86 case nrc_ISO_Latin_Cyrillic: 87 case nrc_DEC_UPSS: 88 break; 89 /* VT100 character sets */ 90 case nrc_ASCII: 91 case nrc_British: 92 case nrc_DEC_Alt_Chars: 93 case nrc_DEC_Spec_Graphic: 94 /* VT220 character sets */ 95 case nrc_DEC_Alt_Graphics: 96 case nrc_DEC_Supp: 97 /* VT320 character sets */ 98 case nrc_DEC_Supp_Graphic: 99 case nrc_DEC_Technical: 100 /* NRCS character sets (VT320 to VT520) */ 101 case nrc_British_Latin_1: 102 case nrc_Dutch: 103 case nrc_Finnish2: 104 case nrc_Finnish: 105 case nrc_French2: 106 case nrc_French: 107 case nrc_French_Canadian2: 108 case nrc_French_Canadian: 109 case nrc_German: 110 case nrc_Greek: 111 case nrc_Hebrew: 112 case nrc_Italian: 113 case nrc_JIS_Katakana: 114 case nrc_JIS_Roman: 115 case nrc_Norwegian_Danish2: 116 case nrc_Norwegian_Danish3: 117 case nrc_Norwegian_Danish: 118 case nrc_Portugese: 119 case nrc_Russian: 120 case nrc_SCS_NRCS: 121 case nrc_Spanish: 122 case nrc_Swedish2: 123 case nrc_Swedish: 124 case nrc_Swiss: 125 case nrc_Turkish: 126 /* other DEC character sets */ 127 case nrc_DEC_Cyrillic: 128 case nrc_DEC_Greek_Supp: 129 case nrc_DEC_Hebrew_Supp: 130 case nrc_DEC_Turkish_Supp: 131 result = True; 132 break; 133 case nrc_Unknown: 134 break; 135 } 136 return result; 137} 138 139/* 140 * Translate an input keysym to the corresponding NRC keysym. 141 */ 142unsigned 143xtermCharSetIn(XtermWidget xw, unsigned code, DECNRCM_codes charset) 144{ 145 TScreen *screen = TScreenOf(xw); 146#define MAP(to, from) case from: code = to; break; 147 148#if OPT_WIDE_CHARS 149#define UNI(to, from) case from: if (screen->utf8_nrc_mode) code = to; break; 150#else 151#define UNI(to, from) case from: break; 152#endif 153 154#define XXX(to, from) /* no defined mapping to 0..255 */ 155 156 TRACE(("CHARSET-IN GL=%s(G%d) GR=%s(G%d) SS%d\n\t%s\n", 157 visibleScsCode(screen->gsets[screen->curgl]), screen->curgl, 158 visibleScsCode(screen->gsets[screen->curgr]), screen->curgr, 159 screen->curss, 160 visibleUChar(code))); 161 162 HandleUPSS(charset); 163 164 switch (charset) { 165 case nrc_British: /* United Kingdom set (or Latin 1) */ 166 if (code == XK_sterling) 167 code = 0x23; 168 code &= 0x7f; 169 break; 170 171 case nrc_DEC_Alt_Chars: 172 case nrc_DEC_Alt_Graphics: 173 case nrc_ASCII: 174 break; 175 176 case nrc_DEC_Spec_Graphic: 177 break; 178 179 case nrc_DEC_Supp: 180 map_DEC_Supp_Graphic(code, code &= 0x7f); 181 break; 182 183 case nrc_DEC_Supp_Graphic: 184 map_DEC_Supp_Graphic(code, code |= 0x80); 185 break; 186 187 case nrc_DEC_Technical: 188 map_DEC_Technical(code); 189 break; 190 191 case nrc_Dutch: 192 map_NRCS_Dutch(code); 193 break; 194 195 case nrc_Finnish: 196 case nrc_Finnish2: 197 map_NRCS_Finnish(code); 198 break; 199 200 case nrc_French: 201 case nrc_French2: 202 map_NRCS_French(code); 203 break; 204 205 case nrc_French_Canadian: 206 map_NRCS_French_Canadian(code); 207 break; 208 209 case nrc_German: 210 map_NRCS_German(code); 211 break; 212 213 case nrc_Greek: 214 map_NRCS_Greek(code); /* FIXME - ELOT? */ 215 break; 216 217 case nrc_DEC_Greek_Supp: 218 map_DEC_Greek_Supp(code); 219 break; 220 221 case nrc_ISO_Greek_Supp: 222 map_ISO_Greek_Supp(code); 223 break; 224 225 case nrc_DEC_Hebrew_Supp: 226 map_DEC_Hebrew_Supp(code); 227 break; 228 229 case nrc_Hebrew: 230 map_NRCS_Hebrew(code); 231 break; 232 233 case nrc_ISO_Hebrew_Supp: 234 map_ISO_Hebrew(code); 235 break; 236 237 case nrc_Italian: 238 map_NRCS_Italian(code); 239 break; 240 241 case nrc_ISO_Latin_2_Supp: 242 map_ISO_Latin_2(code); 243 break; 244 245 case nrc_ISO_Latin_5_Supp: 246 map_ISO_Latin_5(code); 247 break; 248 249 case nrc_ISO_Latin_Cyrillic: 250 map_ISO_Latin_Cyrillic(code); 251 break; 252 253 case nrc_JIS_Katakana: 254 map_JIS_Katakana(code); 255 break; 256 257 case nrc_JIS_Roman: 258 map_JIS_Roman(code); 259 break; 260 261 case nrc_Norwegian_Danish: 262 case nrc_Norwegian_Danish2: 263 case nrc_Norwegian_Danish3: 264 map_NRCS_Norwegian_Danish(code); 265 break; 266 267 case nrc_Portugese: 268 map_NRCS_Portuguese(code); 269 break; 270 271 case nrc_Russian: 272 map_NRCS_Russian(code); 273 break; 274 275 case nrc_SCS_NRCS: /* vt5xx - Serbo/Croatian */ 276 map_NRCS_Serbo_Croatian(code); 277 break; 278 279 case nrc_Spanish: 280 map_NRCS_Spanish(code); 281 break; 282 283 case nrc_Swedish2: 284 case nrc_Swedish: 285 map_NRCS_Swedish(code); 286 break; 287 288 case nrc_Swiss: 289 map_NRCS_Swiss(code); 290 break; 291 292 case nrc_Turkish: 293 map_NRCS_Turkish(code); 294 break; 295 296 case nrc_DEC_Turkish_Supp: 297 map_DEC_Turkish_Supp(code); 298 break; 299 300 case nrc_DEC_Cyrillic: 301 map_DEC_Cyrillic(code); 302 break; 303 304 case nrc_ISO_Latin_1_Supp: 305 case nrc_British_Latin_1: 306 case nrc_French_Canadian2: 307 case nrc_Unknown: 308 case nrc_DEC_UPSS: 309 default: /* any character sets we don't recognize */ 310 break; 311 } 312 code &= 0x7f; /* NRC in any case is 7-bit */ 313 TRACE(("->\t%s\n", 314 visibleUChar(code))); 315 return code; 316#undef MAP 317#undef UNI 318#undef XXX 319} 320 321/* 322 * Translate a string to the display form. This assumes the font has the 323 * DEC graphic characters in cells 0-31, and otherwise is ISO-8859-1. 324 */ 325Cardinal 326xtermCharSetOut(XtermWidget xw, Cardinal length, DECNRCM_codes leftset) 327{ 328 IChar *buf = xw->work.write_text; 329 IChar *ptr = buf + length; 330 IChar *s; 331 TScreen *screen = TScreenOf(xw); 332 Cardinal count = 0; 333 DECNRCM_codes rightset = screen->gsets[(int) (screen->curgr)]; 334#if OPT_DEC_RECTOPS 335 int sums = 0; 336#endif 337 338#define MAP(from, to) case from: chr = to; break; 339 340#if OPT_WIDE_CHARS 341#define UNI(from, to) case from: if (screen->utf8_nrc_mode) chr = to; break; 342#define XXX(from, to) UNI(from, to) 343#else 344#define UNI(old, new) case new: chr = old; break; 345#define XXX(from, to) /* nothing */ 346#endif 347 348 TRACE(("CHARSET-OUT GL=%s(G%d) GR=%s(G%d) SS%d\n\t%s\n", 349 visibleScsCode(leftset), screen->curgl, 350 visibleScsCode(rightset), screen->curgr, 351 screen->curss, 352 visibleIChars(buf, (size_t) length))); 353 354 assert(length != 0); 355#if OPT_DEC_RECTOPS 356 if (length != 0 && length > xw->work.sizeof_sums) { 357 xw->work.sizeof_sums += length + 80; 358 xw->work.buffer_sums = realloc(xw->work.buffer_sums, 359 xw->work.sizeof_sums); 360 xw->work.buffer_sets = realloc(xw->work.buffer_sets, 361 xw->work.sizeof_sums); 362 } 363 xw->work.write_sums = xw->work.buffer_sums; 364#endif 365 366 for (s = buf; s < ptr; ++s) { 367 int eight = CharOf(*s); 368 int seven = eight & 0x7f; 369 DECNRCM_codes cs = (eight >= 128) ? rightset : leftset; 370 int chr = eight; 371 372 HandleUPSS(cs); 373 374#if OPT_DEC_RECTOPS 375 if (xw->work.buffer_sums != NULL && xw->work.buffer_sets != NULL) { 376 xw->work.buffer_sums[sums] = (Char) ((eight < 32 || eight > 255) 377 ? ANSI_ESC 378 : eight); 379 xw->work.buffer_sets[sums] = cs; 380 ++sums; 381 } 382#endif 383 count++; 384#if OPT_WIDE_CHARS 385 /* 386 * This is only partly right - prevent inadvertent remapping of 387 * the replacement character and other non-8bit codes into bogus 388 * 8bit codes. 389 */ 390 if (screen->utf8_mode || screen->utf8_nrc_mode) { 391 if (*s > 255) 392 continue; 393 } 394#endif 395 if (*s < 32) 396 continue; 397 398 switch (cs) { 399 case nrc_DEC_UPSS: 400 break; 401 402 case nrc_ISO_Latin_1_Supp: 403 case nrc_British_Latin_1: 404 case nrc_British: /* United Kingdom set (or Latin 1) */ 405 if ((xw->flags & NATIONAL) 406 || (screen->vtXX_level <= 1)) { 407 if ((xw->flags & NATIONAL)) { 408 chr = seven; 409 } 410 if (chr == 0x23) { 411 chr = XTERM_POUND; 412#if OPT_WIDE_CHARS 413 if (screen->utf8_nrc_mode) { 414 chr = 0xa3; 415 } 416#endif 417 } 418 } 419 break; 420 421 case nrc_DEC_Alt_Chars: 422 case nrc_DEC_Alt_Graphics: 423 case nrc_ASCII: 424 break; 425 426 case nrc_DEC_Spec_Graphic: 427 if (seven > 0x5f && seven <= 0x7e) { 428#if OPT_WIDE_CHARS 429 if (screen->utf8_mode || screen->utf8_nrc_mode) 430 chr = (int) dec2ucs(screen, (unsigned) (seven - 0x5f)); 431 else 432#endif 433 chr = seven - 0x5f; 434 } else if (chr == 0x5f) { 435 chr = 0; 436 } else { 437 chr = seven; 438 } 439 break; 440 441 case nrc_DEC_Supp: 442 case nrc_DEC_Supp_Graphic: 443 map_DEC_Supp_Graphic(chr = seven, chr = eight); 444 break; 445 446 case nrc_DEC_Technical: 447 map_DEC_Technical(chr = seven); 448 break; 449 450 case nrc_Dutch: 451 map_NRCS_Dutch(chr = seven); 452 break; 453 454 case nrc_Finnish: 455 case nrc_Finnish2: 456 map_NRCS_Finnish(chr = seven); 457 break; 458 459 case nrc_French: 460 case nrc_French2: 461 map_NRCS_French(chr = seven); 462 break; 463 464 case nrc_French_Canadian: 465 case nrc_French_Canadian2: 466 map_NRCS_French_Canadian(chr = seven); 467 break; 468 469 case nrc_German: 470 map_NRCS_German(chr = seven); 471 break; 472 473 case nrc_Greek: 474 map_NRCS_Greek(chr = seven); /* FIXME - ELOT? */ 475 break; 476 477 case nrc_DEC_Greek_Supp: 478 map_DEC_Greek_Supp(chr = seven); 479 break; 480 481 case nrc_ISO_Greek_Supp: 482 map_ISO_Greek_Supp(chr = seven); 483 break; 484 485 case nrc_DEC_Hebrew_Supp: 486 map_DEC_Hebrew_Supp(chr = seven); 487 break; 488 489 case nrc_Hebrew: 490 map_NRCS_Hebrew(chr = seven); 491 break; 492 493 case nrc_ISO_Hebrew_Supp: 494 map_ISO_Hebrew(chr = seven); 495 break; 496 497 case nrc_Italian: 498 map_NRCS_Italian(chr = seven); 499 break; 500 501 case nrc_ISO_Latin_2_Supp: 502 map_ISO_Latin_2(chr = seven); 503 break; 504 505 case nrc_ISO_Latin_5_Supp: 506 map_ISO_Latin_5(chr = seven); 507 break; 508 509 case nrc_ISO_Latin_Cyrillic: 510 map_ISO_Latin_Cyrillic(chr = seven); 511 break; 512 513 case nrc_JIS_Katakana: 514 map_JIS_Katakana(chr = seven); 515 break; 516 517 case nrc_JIS_Roman: 518 map_JIS_Roman(chr = seven); 519 break; 520 521 case nrc_Norwegian_Danish: 522 case nrc_Norwegian_Danish2: 523 case nrc_Norwegian_Danish3: 524 map_NRCS_Norwegian_Danish(chr = seven); 525 break; 526 527 case nrc_Portugese: 528 map_NRCS_Portuguese(chr = seven); 529 break; 530 531 case nrc_Russian: 532 map_NRCS_Russian(chr = seven); 533 break; 534 535 case nrc_SCS_NRCS: /* vt5xx - Serbo/Croatian */ 536 map_NRCS_Serbo_Croatian(chr = seven); 537 break; 538 539 case nrc_Spanish: 540 map_NRCS_Spanish(chr = seven); 541 break; 542 543 case nrc_Swedish2: 544 case nrc_Swedish: 545 map_NRCS_Swedish(chr = seven); 546 break; 547 548 case nrc_Swiss: 549 map_NRCS_Swiss(chr = seven); 550 break; 551 552 case nrc_Turkish: 553 map_NRCS_Turkish(chr = seven); 554 break; 555 556 case nrc_DEC_Turkish_Supp: 557 map_DEC_Turkish_Supp(chr = seven); 558 break; 559 560 case nrc_DEC_Cyrillic: 561 map_DEC_Cyrillic(chr = seven); 562 break; 563 564 case nrc_Unknown: 565 default: /* any character sets we don't recognize */ 566 break; 567 } 568 /* 569 * The state machine already treated DEL as a nonprinting and 570 * nonspacing character. If we have DEL now, remove it. 571 */ 572 if (chr == ANSI_DEL && isSevenBit(cs)) { 573 IChar *s1; 574 --ptr; 575 for (s1 = s; s1 < ptr; ++s1) { 576 s1[0] = s1[1]; 577 } 578 --count; 579#if OPT_DEC_RECTOPS 580 --sums; 581#endif 582 } else { 583 if (eight >= 128 && chr < 128 && chr > 32) 584 chr |= 128; 585 *s = (IChar) chr; 586 } 587 } 588 TRACE(("%d\t%s\n", 589 count, 590 visibleIChars(buf, (size_t) length))); 591 return count; 592#undef MAP 593#undef UNI 594#undef XXX 595} 596 597#if OPT_DEC_RECTOPS 598/* 599 * Given a mapped character, e.g., a Unicode value returned by xtermCharSetIn, 600 * match it against the current GL/GR selection and return the corresponding 601 * DEC internal character-set code for DECRQCRA. 602 * 603 * A hardware terminal presumably stores the original and mapped characters, 604 * as well as the character set which was selected at that time Doing that 605 * in xterm adds a couple of bytes to every cell. 606 */ 607int 608xtermCharSetDec(XtermWidget xw, IChar chr, DECNRCM_codes cs) 609{ 610#define MAP(from, to) case from: result = to; break; 611 612#define DFTMAP() result = (actual | 0x80) 613#define DFT_94(chr) result = ((actual) & 0x7f) 614#define DFT_96(chr) result = ((actual) | 0x80) 615 616#if OPT_WIDE_CHARS 617#define UNI(from, to) case from: if (screen->utf8_nrc_mode) result = to; break; 618#define XXX(from, to) UNI(from, to) 619#else 620#define UNI(old, new) case new: result = old; break; 621#define XXX(from, to) /* nothing */ 622#endif 623 624 int result; 625 626 if (chr < 0x20 627#if OPT_WIDE_CHARS 628 || chr > 0xff 629#endif 630 ) { 631 result = ANSI_ESC; 632 } else { 633 Boolean isSeven = isSevenBit(cs); 634 TScreen *screen = TScreenOf(xw); 635 636 result = -1; 637 638 HandleUPSS(cs); 639 640 if (chr == 0xa0 && isSeven) { 641 result = ANSI_ESC; 642 } else if (chr == ANSI_SPA && isSeven) { 643 result = ANSI_SPA; 644 } else if ((chr == ANSI_DEL || chr == 0xff) && isSeven) { 645 result = 0; 646 } else { 647 int actual = (int) chr; 648 chr &= 0x7f; 649 650 switch (cs) { 651 case nrc_DEC_Alt_Chars: 652 case nrc_DEC_Alt_Graphics: 653 case nrc_ASCII: 654 result = (int) chr; 655 break; 656 657 case nrc_British: 658 if (chr >= 0xa0 && chr < 0xff) { 659 if (chr == 0x23) 660 chr = 0xA3; 661 result = (int) chr; 662 } 663 break; 664 665 case nrc_DEC_Cyrillic: 666 unmap_DEC_Cyrillic(chr, DFT_94(chr)); 667 break; 668 669 case nrc_DEC_Spec_Graphic: 670 unmap_DEC_Spec_Graphic(chr, DFT_94(chr)); 671 break; 672 673 case nrc_DEC_Supp: 674 /* FALLTHRU */ 675 case nrc_DEC_Supp_Graphic: 676 unmap_DEC_Supp_Graphic(chr, DFTMAP()); 677 break; 678 679 case nrc_DEC_Technical: 680 unmap_DEC_Technical(chr, DFTMAP()); 681 break; 682 683 case nrc_Dutch: 684 unmap_NRCS_Dutch(chr, DFT_94(chr)); 685 break; 686 687 case nrc_Finnish: 688 case nrc_Finnish2: 689 unmap_NRCS_Finnish(chr, DFT_94(chr)); 690 break; 691 692 case nrc_French: 693 case nrc_French2: 694 unmap_NRCS_French(chr, DFT_94(chr)); 695 break; 696 697 case nrc_French_Canadian: 698 case nrc_French_Canadian2: 699 unmap_NRCS_French_Canadian(chr, DFT_94(chr)); 700 break; 701 702 case nrc_German: 703 unmap_NRCS_German(chr, DFT_94(chr)); 704 break; 705 706 case nrc_Greek: 707 unmap_NRCS_Greek(chr, DFT_94(chr)); 708 break; 709 710 case nrc_DEC_Greek_Supp: 711 unmap_DEC_Greek_Supp(chr, DFTMAP()); 712 break; 713 714 case nrc_ISO_Greek_Supp: 715 unmap_ISO_Greek_Supp(chr, DFTMAP()); 716 break; 717 718 case nrc_DEC_Hebrew_Supp: 719 unmap_DEC_Hebrew_Supp(chr, DFTMAP()); 720 break; 721 722 case nrc_Hebrew: 723 unmap_NRCS_Hebrew(chr, DFT_94(chr)); 724 break; 725 726 case nrc_ISO_Hebrew_Supp: 727 unmap_ISO_Hebrew(chr, DFTMAP()); 728 break; 729 730 case nrc_Italian: 731 unmap_NRCS_Italian(chr, DFT_94(chr)); 732 break; 733 734 case nrc_JIS_Katakana: 735 unmap_JIS_Katakana(chr, DFT_94(chr)); 736 break; 737 738 case nrc_JIS_Roman: 739 unmap_JIS_Roman(chr, DFT_94(chr)); 740 break; 741 742 case nrc_ISO_Latin_1_Supp: 743 unmap_ISO_Latin_1(chr, DFTMAP()); 744 break; 745 746 case nrc_ISO_Latin_2_Supp: 747 unmap_ISO_Latin_2(chr, DFTMAP()); 748 break; 749 750 case nrc_ISO_Latin_5_Supp: 751 unmap_ISO_Latin_5(chr, DFTMAP()); 752 break; 753 754 case nrc_ISO_Latin_Cyrillic: 755 unmap_ISO_Latin_Cyrillic(chr, DFTMAP()); 756 break; 757 758 case nrc_Norwegian_Danish: 759 case nrc_Norwegian_Danish2: 760 case nrc_Norwegian_Danish3: 761 unmap_NRCS_Norwegian_Danish(chr, DFT_94(chr)); 762 break; 763 764 case nrc_Portugese: 765 unmap_NRCS_Portuguese(chr, DFT_94(chr)); 766 break; 767 768 case nrc_Russian: 769 unmap_NRCS_Russian(chr, DFT_94(chr)); 770 break; 771 772 case nrc_SCS_NRCS: 773 unmap_NRCS_Serbo_Croatian(chr, DFT_94(chr)); 774 break; 775 776 case nrc_Spanish: 777 unmap_NRCS_Spanish(chr, DFT_94(chr)); 778 break; 779 780 case nrc_Swedish: 781 case nrc_Swedish2: 782 unmap_NRCS_Swedish(chr, DFT_94(chr)); 783 break; 784 785 case nrc_Swiss: 786 unmap_NRCS_Swiss(chr, DFT_94(chr)); 787 break; 788 789 case nrc_DEC_Turkish_Supp: 790 unmap_DEC_Turkish_Supp(chr, DFTMAP()); 791 break; 792 793 case nrc_Turkish: 794 unmap_NRCS_Turkish(chr, DFT_94(chr)); 795 break; 796 797 case nrc_British_Latin_1: 798 case nrc_Unknown: 799 case nrc_DEC_UPSS: 800 default: /* anything we cannot unmap */ 801 break; 802 } 803 if (result < 0) { 804 if (isSeven) { 805 DFT_94(chr); 806 } else { 807 DFT_96(chr); 808 } 809 } 810 } 811 } 812 return result; 813#undef MAP 814#undef UNI 815#undef XXX 816} 817#endif /* OPT_DEC_RECTOPS */ 818