home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / UCdomap.c < prev    next >
C/C++ Source or Header  |  1998-04-23  |  57KB  |  2,059 lines

  1. /*
  2.  *  UCdomap.c
  3.  *  =========
  4.  *
  5.  * Derived from code in the Linux kernel console driver.
  6.  * The GNU Public Licence therefore applies, see
  7.  * the file COPYING in the top-level directory
  8.  * which should come with every Lynx distribution.
  9.  *
  10.  *  [ original comment: - KW ]
  11.  *
  12.  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
  13.  * to font positions.
  14.  *
  15.  * aeb, 950210
  16.  */
  17. #include <HTUtils.h>
  18. #include <tcp.h>
  19. #include <HTMLDTD.h>
  20.  
  21. #include <LYGlobalDefs.h>
  22. #include <UCkd.h>
  23. #include <UCdomap.h>
  24. #include <UCMap.h>
  25. #include <UCDefs.h>
  26. #include <LYCharSets.h>
  27.  
  28. /*
  29.  *  Include tables & parameters.
  30.  */
  31. #include <cp1250_uni.h>     /* WinLatin2 (cp1250)    */
  32. #include <cp1251_uni.h>     /* WinCyrillic (cp1251) */
  33. #include <cp1252_uni.h>     /* WinLatin1 (cp1252)    */
  34. #include <cp1253_uni.h>     /* WinGreek (cp1253)    */
  35. #include <cp1255_uni.h>     /* WinHebrew (cp1255)    */
  36. #include <cp1256_uni.h>     /* WinArabic (cp1256)    */
  37. #include <cp1257_uni.h>     /* WinBaltRim (cp1257)    */
  38. #include <cp437_uni.h>        /* DosLatinUS (cp437)    */
  39. #include <cp737_uni.h>        /* DosGreek (cp737)    */
  40. #include <cp775_uni.h>        /* DosBaltRim (cp775)    */
  41. #include <cp850_uni.h>        /* DosLatin1 (cp850)    */
  42. #include <cp852_uni.h>        /* DosLatin2 (cp852)    */
  43. #include <cp862_uni.h>        /* DosHebrew (cp862)    */
  44. #include <cp864_uni.h>        /* DosArabic (cp864)    */
  45. #include <cp866_uni.h>        /* DosCyrillic (cp866)    */
  46. #include <cp869_uni.h>        /* DosGreek2 (cp869)    */
  47. #include <def7_uni.h>        /* 7 bit approximations */
  48. #include <dmcs_uni.h>        /* DEC Multinational    */
  49. #include <iso01_uni.h>        /* ISO Latin 1        */
  50. #include <iso02_uni.h>        /* ISO Latin 2        */
  51. #include <iso03_uni.h>        /* ISO Latin 3        */
  52. #include <iso04_uni.h>        /* ISO Latin 4        */
  53. #include <iso05_uni.h>        /* ISO 8859-5 Cyrillic    */
  54. #include <iso06_uni.h>        /* ISO 8859-6 Arabic    */
  55. #include <iso07_uni.h>        /* ISO 8859-7 Greek    */
  56. #include <iso08_uni.h>        /* ISO 8859-8 Hebrew    */
  57. #include <iso09_uni.h>        /* ISO 8859-9 (Latin 5) */
  58. #include <iso10_uni.h>        /* ISO 8859-10        */
  59. #include <koi8r_uni.h>        /* KOI8-R Cyrillic    */
  60. #include <mac_uni.h>        /* Macintosh (8 bit)    */
  61. #include <mnem2_suni.h>     /* RFC 1345 Mnemonic    */
  62. #include <next_uni.h>        /* NeXT character set    */
  63. #include <rfc_suni.h>        /* RFC 1345 w/o Intro    */
  64. #include <utf8_uni.h>        /* UNICODE UTF 8    */
  65. #include <viscii_uni.h>     /* Vietnamese (VISCII)    */
  66. #ifdef NOTDEFINED
  67. #include <mnem_suni.h>
  68. #endif /* NOTDEFINED */
  69.  
  70. #define FREE(x) if (x) {free(x); x = NULL;}
  71.  
  72. /*
  73.  *  Some of the code below, and some of the comments, are left in for
  74.  *  historical reasons.  Not all those tables below are currently
  75.  *  really needed (and what with all those hardwired codepoints),
  76.  *  but let's keep them around for now.  They may come in handy if we
  77.  *  decide to make more extended use of the mechanisms (including e.g.
  78.  *  for chars < 127...).  - KW
  79.  */
  80.  
  81. PRIVATE u16 translations[][256] = {
  82.   /*
  83.    *  8-bit Latin-1 mapped to Unicode -- trivial mapping.
  84.    */
  85.   {
  86.     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  87.     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  88.     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  89.     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  90.     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  91.     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  92.     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  93.     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  94.     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  95.     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  96.     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  97.     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  98.     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  99.     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  100.     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  101.     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
  102.     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  103.     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  104.     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  105.     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  106.     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  107.     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  108.     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  109.     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  110.     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  111.     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  112.     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  113.     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  114.     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  115.     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  116.     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  117.     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  118.   },
  119.   /*
  120.    *  VT100 graphics mapped to Unicode.
  121.    */
  122.   {
  123.     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  124.     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  125.     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  126.     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  127.     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  128.     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  129.     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  130.     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  131.     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  132.     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  133.     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  134.     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
  135.     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
  136.     0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0xf800,
  137.     0xf801, 0x2500, 0xf803, 0xf804, 0x251c, 0x2524, 0x2534, 0x252c,
  138.     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
  139.     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  140.     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  141.     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  142.     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  143.     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  144.     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  145.     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  146.     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  147.     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  148.     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  149.     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  150.     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  151.     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  152.     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  153.     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  154.     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  155.   },
  156.   /*
  157.    *  IBM Codepage 437 mapped to Unicode.
  158.    */
  159.   {
  160.     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
  161.     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
  162.     0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
  163.     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
  164.     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  165.     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  166.     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  167.     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  168.     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  169.     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  170.     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  171.     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  172.     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  173.     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  174.     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  175.     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
  176.     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
  177.     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
  178.     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
  179.     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
  180.     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
  181.     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
  182.     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
  183.     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
  184.     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
  185.     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
  186.     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
  187.     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
  188.     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
  189.     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
  190.     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
  191.     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
  192.   },
  193.   /*
  194.    *  User mapping -- default to codes for direct font mapping.
  195.    */
  196.   {
  197.     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
  198.     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
  199.     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
  200.     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
  201.     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
  202.     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
  203.     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
  204.     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
  205.     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
  206.     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
  207.     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
  208.     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
  209.     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
  210.     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
  211.     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
  212.     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
  213.     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
  214.     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
  215.     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
  216.     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
  217.     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
  218.     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
  219.     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
  220.     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
  221.     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
  222.     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
  223.     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
  224.     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
  225.     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
  226.     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
  227.     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
  228.     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
  229.   }
  230. };
  231. PRIVATE u16 *UC_translate = NULL;
  232.  
  233. PRIVATE struct UC_charset UCInfo[MAXCHARSETS];
  234.  
  235. /*
  236.  *  The standard kernel character-to-font mappings are not invertible
  237.  *  -- this is just a best effort.
  238.  */
  239. #define MAX_GLYPH 512        /* Max possible glyph value */
  240.  
  241. PRIVATE unsigned char * inv_translate = NULL;
  242. PRIVATE unsigned char inv_norm_transl[MAX_GLYPH];
  243. PRIVATE unsigned char * inverse_translations[4] = { NULL, NULL, NULL, NULL };
  244.  
  245. PRIVATE void set_inverse_transl PARAMS((
  246.     int        i));
  247. PRIVATE u16 *set_translate PARAMS((
  248.     int        m));
  249. #ifdef NOTDEFINED
  250. PRIVATE unsigned char inverse_translate PARAMS((int glyph));
  251. PRIVATE int con_set_trans_old PARAMS((unsigned char *arg));
  252. PRIVATE int con_get_trans_old PARAMS((unsigned char *arg));
  253. PRIVATE int con_set_trans_new PARAMS((u16 *arg));
  254. PRIVATE int con_get_trans_new PARAMS((u16 *arg));
  255. #endif /* NOTDEFINED */
  256. PRIVATE int UC_valid_UC_charset PARAMS((
  257.     int        UC_charset_hndl));
  258. PRIVATE void UC_con_set_trans PARAMS((
  259.     int        UC_charset_in_hndl,
  260.     int        Gn,
  261.     int        update_flag));
  262. PRIVATE int con_insert_unipair PARAMS((
  263.     u16        unicode,
  264.     u16        fontpos,
  265.     int        fordefault));
  266. PRIVATE int con_insert_unipair_str PARAMS((
  267.     u16        unicode,
  268.     char *        replace_str,
  269.     int        fordefault));
  270. PRIVATE void con_clear_unimap PARAMS((
  271.     int        fordefault));
  272. PRIVATE void con_clear_unimap_str PARAMS((
  273.     int        fordefault));
  274. #ifdef NOTDEFINED
  275. PRIVATE int con_set_unimap PARAMS((
  276.     u16            ct,
  277.     struct unipair *    list));
  278. #endif /* NOTDEFINED */
  279. PRIVATE void con_set_default_unimap NOPARAMS;
  280. PRIVATE int UC_con_set_unimap PARAMS((
  281.     int        UC_charset_out_hndl,
  282.     int        update_flag));
  283. PRIVATE int UC_con_set_unimap_str PARAMS((
  284.     u16            ct,
  285.     struct unipair_str *    list,
  286.     int            fordefault));
  287. #ifdef NOTDEFINED
  288. PRIVATE int con_get_unimap PARAMS((
  289.     u16            ct,
  290.     u16 *            uct,
  291.     struct unipair *    list));
  292. #endif /* NOTDEFINED */
  293. PRIVATE int conv_uni_to_pc PARAMS((
  294.     long            ucs,
  295.     int            usedefault));
  296. PRIVATE int conv_uni_to_str PARAMS((
  297.     char*        outbuf,
  298.     int        buflen,
  299.     long        ucs,
  300.     int        usedefault));
  301. PRIVATE void UCconsole_map_init NOPARAMS;
  302. PRIVATE int UC_MapGN PARAMS((
  303.     int        UChndl,
  304.     int        update_flag));
  305. PRIVATE int UC_FindGN_byMIME PARAMS((
  306.     CONST char *    UC_MIMEcharset));
  307. PRIVATE void UCreset_allocated_LYCharSets NOPARAMS;
  308. PRIVATE void UCfree_allocated_LYCharSets NOPARAMS;
  309. PRIVATE char ** UC_setup_LYCharSets_repl PARAMS((
  310.     int        UC_charset_in_hndl,
  311.     unsigned    lowest8));
  312. PRIVATE int UC_Register_with_LYCharSets PARAMS((
  313.     int        s,
  314.     CONST char *    UC_MIMEcharset,
  315.     CONST char *    UC_LYNXcharset,
  316.     int        lowest_eightbit));
  317. PRIVATE void UCcleanup_mem NOPARAMS;
  318.  
  319. PRIVATE int default_UChndl = -1;
  320.  
  321. PRIVATE void set_inverse_transl ARGS1(
  322.     int,        i)
  323. {
  324.     int j, glyph;
  325.     u16 *p = translations[i];
  326.     unsigned char *q = inverse_translations[i];
  327.  
  328.     if (!q) {
  329.     /*
  330.      *  Slightly messy to avoid calling kmalloc too early.
  331.      */
  332.     q = inverse_translations[i] = ((i == LAT1_MAP) ?
  333.                        inv_norm_transl :
  334.                        (unsigned char *)malloc(MAX_GLYPH));
  335.     if (!q)
  336.         return;
  337.     }
  338.     for (j = 0; j < MAX_GLYPH; j++)
  339.     q[j] = 0;
  340.  
  341.     for (j = 0; j < E_TABSZ; j++) {
  342.     glyph = conv_uni_to_pc(p[j], 0);
  343.     if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
  344.         /*
  345.          *    Prefer '-' above SHY etc.
  346.          */
  347.         q[glyph] = j;
  348.     }
  349.     }
  350. }
  351.  
  352. PRIVATE u16 *set_translate ARGS1(
  353.     int,        m)
  354. {
  355.     if (!inverse_translations[m])
  356.         set_inverse_transl(m);
  357.     inv_translate = inverse_translations[m];
  358.     return translations[m];
  359. }
  360.  
  361. #ifdef NOTDEFINED
  362. /*
  363.  * Inverse translation is impossible for several reasons:
  364.  * 1. The font<->character maps are not 1-1.
  365.  * 2. The text may have been written while a different translation map
  366.  *    was active, or using Unicode.
  367.  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
  368.  */
  369. PRIVATE unsigned char inverse_translate ARGS1(
  370.     int,        glyph)
  371. {
  372.     if (glyph < 0 || glyph >= MAX_GLYPH) {
  373.         return 0;
  374.     } else {
  375.     return ((inv_translate && inv_translate[glyph]) ?
  376.                    inv_translate[glyph] :
  377.                    (unsigned char)(glyph & 0xff));
  378.     }
  379. }
  380.  
  381. /*
  382.  *  Load customizable translation table.
  383.  *  'arg' points to a 256 byte translation table.
  384.  *
  385.  *  The "old" variants are for translation directly to font (using the
  386.  *  0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
  387.  *  Unicodes explicitly.
  388.  */
  389. PRIVATE int con_set_trans_old ARGS1(
  390.     unsigned char *,    arg)
  391. {
  392.     int i;
  393.     u16 *p = translations[USER_MAP];
  394. #if(0)
  395.     i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
  396.     if (i)
  397.     return i;
  398. #endif
  399.     for (i = 0; i < E_TABSZ; i++)
  400.     p[i] = UNI_DIRECT_BASE | (u16)arg[i];
  401.  
  402.     set_inverse_transl(USER_MAP);
  403.     return 0;
  404. }
  405.  
  406. PRIVATE int con_get_trans_old ARGS1(
  407.     unsigned char *,    arg)
  408. {
  409.     int i, ch;
  410.     u16 *p = translations[USER_MAP];
  411. #if(0)
  412.     i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
  413.     if (i)
  414.     return i;
  415. #endif
  416.     for (i = 0; i < E_TABSZ; i++) {
  417.     ch = conv_uni_to_pc(p[i]);
  418. #ifdef NOTDEFINED
  419.     put_user((ch & ~0xff) ? 0 : ch, arg+i);
  420. #endif /* NOTDEFINED */
  421.     arg[i] = (unsigned char)((ch & ~0xff) ? 0 : ch);
  422.     }
  423.     return 0;
  424. }
  425.  
  426. PRIVATE int con_set_trans_new ARGS1(
  427.     u16 *,        arg)
  428. {
  429.     int i;
  430.     u16 *p = translations[USER_MAP];
  431. #if(0)
  432.     i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ*sizeof(u16));
  433.     if (i)
  434.     return i;
  435. #endif
  436.     for (i = 0; i < E_TABSZ; i++)
  437.     p[i] = arg[i];
  438.  
  439.     set_inverse_transl(USER_MAP);
  440.     return 0;
  441. }
  442.  
  443. PRIVATE int con_get_trans_new ARGS1(
  444.     u16 *        arg)
  445. {
  446.     int i;
  447.     u16 *p = translations[USER_MAP];
  448. #if(0)
  449.     i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ*sizeof(u16));
  450.     if (i)
  451.     return i;
  452. #endif
  453.     for (i = 0; i < E_TABSZ; i++)
  454.     arg[i] = p[i];
  455.  
  456.     return 0;
  457. }
  458. #endif /* NOTDEFINED */
  459.  
  460. PRIVATE int UC_valid_UC_charset ARGS1(
  461.     int,        UC_charset_hndl)
  462. {
  463.   return (UC_charset_hndl >= 0 && UC_charset_hndl < UCNumCharsets);
  464. }
  465.  
  466. PRIVATE void UC_con_set_trans ARGS3(
  467.     int,        UC_charset_in_hndl,
  468.     int,        Gn,
  469.     int,        update_flag)
  470. {
  471.   int i, j;
  472.   u16 *p;
  473.   u16 *ptrans;
  474.  
  475.     if (!UC_valid_UC_charset(UC_charset_in_hndl)) {
  476.     CTRACE(tfp, "UC_con_set_trans: Invalid charset handle %d.\n",
  477.             UC_charset_in_hndl);
  478.     return;
  479.     }
  480.     ptrans = translations[Gn];
  481.     p = UCInfo[UC_charset_in_hndl].unitable;
  482. #if(0)
  483.   if (p == UC_current_unitable) {    /* test whether pointers are equal */
  484.     return;            /* nothing to be done */
  485.   }
  486.     /*
  487.      *    The font is always 256 characters - so far.
  488.      */
  489.   con_clear_unimap();
  490. #endif
  491.     for (i = 0; i < 256; i++) {
  492.     if ((j = UCInfo[UC_charset_in_hndl].unicount[i])) {
  493.         ptrans[i] = *p;
  494.         for (; j; j--) {
  495.         p++;
  496.         }
  497.     } else {
  498.         ptrans[i] = 0xfffd;
  499.     }
  500.     }
  501.     if (update_flag) {
  502.     set_inverse_transl(Gn); /* Update inverse translation for this one */
  503.     }
  504. }
  505.  
  506. /*
  507.  * Unicode -> current font conversion
  508.  *
  509.  * A font has at most 512 chars, usually 256.
  510.  * But one font position may represent several Unicode chars.
  511.  * A hashtable is somewhat of a pain to deal with, so use a
  512.  * "paged table" instead.  Simulation has shown the memory cost of
  513.  * this 3-level paged table scheme to be comparable to a hash table.
  514.  */
  515. PRIVATE int hashtable_contents_valid = 0; /* Use ASCII-only mode for bootup*/
  516. PRIVATE int hashtable_str_contents_valid = 0;
  517.  
  518. PRIVATE u16 **uni_pagedir[32] =
  519. {
  520.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  521.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  522.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  523.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  524. };
  525.  
  526. PRIVATE char* **uni_pagedir_str[32] =
  527. {
  528.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  529.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  530.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  531.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  532. };
  533.  
  534. PRIVATE u16 * UC_current_unitable = NULL;
  535. PRIVATE struct unimapdesc_str *UC_current_unitable_str = NULL;
  536.  
  537. /*
  538.  *  Keep a second set of structures for the translation designated
  539.  *  as "default" - kw
  540.  */
  541. PRIVATE int unidefault_contents_valid = 0; /* Use ASCII-only mode for bootup*/
  542. PRIVATE int unidefault_str_contents_valid = 0;
  543.  
  544. static u16 **unidefault_pagedir[32] =
  545. {
  546.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  547.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  548.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  549.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  550. };
  551. static char* **unidefault_pagedir_str[32] =
  552. {
  553.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  554.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  555.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  556.   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  557. };
  558.  
  559. PRIVATE u16 * UC_default_unitable = NULL;
  560. PRIVATE struct unimapdesc_str *UC_default_unitable_str = NULL;
  561.  
  562. PRIVATE int con_insert_unipair ARGS3(
  563.     u16,        unicode,
  564.     u16,        fontpos,
  565.     int,        fordefault)
  566. {
  567.     int i, n;
  568.     u16 **p1, *p2;
  569.  
  570.     if(fordefault)
  571.     p1 = unidefault_pagedir[n = unicode >> 11];
  572.     else
  573.     p1 = uni_pagedir[n = unicode >> 11];
  574.     if (!p1) {
  575.     p1 = (u16* *)malloc(32*sizeof(u16 *));
  576.     if (fordefault)
  577.         unidefault_pagedir[n] = p1;
  578.     else
  579.         uni_pagedir[n] = p1;
  580.     if ( !p1 )
  581.         return -ENOMEM;
  582.  
  583.     for (i = 0; i < 32; i++) {
  584.         p1[i] = NULL;
  585.     }
  586.     }
  587.  
  588.     if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
  589.     p2 = p1[n] = (u16 *)malloc(64*sizeof(u16));
  590.     if (!p2)
  591.         return -ENOMEM;
  592.  
  593.     for (i = 0; i < 64; i++) {
  594.         p2[i] = 0xffff;        /* No glyph for this character (yet) */
  595.     }
  596.     }
  597.  
  598.     p2[unicode & 0x3f] = fontpos;
  599.  
  600.     return 0;
  601. }
  602.  
  603. PRIVATE int con_insert_unipair_str ARGS3(
  604.     u16,        unicode,
  605.     char *,     replace_str,
  606.     int,        fordefault)
  607. {
  608.     int i, n;
  609.     char ***p1, **p2;
  610.  
  611.     if(fordefault)
  612.     p1 = unidefault_pagedir_str[n = unicode >> 11];
  613.     else
  614.     p1 = uni_pagedir_str[n = unicode >> 11];
  615.     if (!p1) {
  616.     p1 = (char** *)malloc(32*sizeof(char **));
  617.     if (fordefault)
  618.         unidefault_pagedir_str[n] = p1;
  619.     else
  620.         uni_pagedir_str[n] = p1;
  621.     if ( !p1 )
  622.         return -ENOMEM;
  623.  
  624.     for (i = 0; i < 32; i++) {
  625.         p1[i] = NULL;
  626.     }
  627.     }
  628.  
  629.     if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
  630.     p2 = p1[n] = (char* *)malloc(64*sizeof(char *));
  631.     if (!p2)
  632.         return -ENOMEM;
  633.  
  634.     for (i = 0; i < 64; i++) {
  635.         p2[i] = NULL;    /* No replace string this character (yet) */
  636.     }
  637.     }
  638.  
  639.     p2[unicode & 0x3f] = replace_str;
  640.  
  641.     return 0;
  642. }
  643.  
  644. /*
  645.  *  ui arg was a leftover, deleted. - KW
  646.  */
  647. PRIVATE void con_clear_unimap ARGS1(
  648.     int,        fordefault)
  649. {
  650.     int i, j;
  651.     u16 **p1;
  652.  
  653.     if (fordefault) {
  654.     for (i = 0; i < 32; i++) {
  655.         if ((p1 = unidefault_pagedir[i]) != NULL) {
  656.         for (j = 0; j < 32; j++) {
  657.             FREE(p1[j]);
  658.         }
  659.         FREE(p1);
  660.         }
  661.         unidefault_pagedir[i] = NULL;
  662.     }
  663.  
  664.     unidefault_contents_valid = 1;
  665.     } else {
  666.     for (i = 0; i < 32; i++) {
  667.         if ((p1 = uni_pagedir[i]) != NULL) {
  668.         for (j = 0; j < 32; j++) {
  669.             FREE(p1[j]);
  670.         }
  671.         FREE(p1);
  672.         }
  673.         uni_pagedir[i] = NULL;
  674.     }
  675.  
  676.     hashtable_contents_valid = 1;
  677.     }
  678. }
  679.  
  680. PRIVATE void con_clear_unimap_str ARGS1(int, fordefault)
  681. {
  682.   int i, j;
  683.   char ***p1;
  684.  
  685.   if (fordefault) {
  686.     for (i = 0; i < 32; i++) {
  687.     if ((p1 = unidefault_pagedir_str[i]) != NULL) {
  688.         for (j = 0; j < 32; j++) {
  689.         FREE(p1[j]);
  690.         }
  691.         FREE(p1);
  692.     }
  693.       unidefault_pagedir_str[i] = NULL;
  694.     }
  695.  
  696.     unidefault_str_contents_valid = 1;    /* ??? probably no use... */
  697.   } else {
  698.     for (i = 0; i < 32; i++) {
  699.     if ((p1 = uni_pagedir_str[i]) != NULL) {
  700.         for (j = 0; j < 32; j++) {
  701.         FREE(p1[j]);
  702.         }
  703.         FREE(p1);
  704.     }
  705.       uni_pagedir_str[i] = NULL;
  706.     }
  707.  
  708.     hashtable_str_contents_valid = 1;  /* ??? probably no use... */
  709.   }
  710. }
  711.  
  712. #ifdef NOTDEFINED
  713. PRIVATE int con_set_unimap ARGS2(
  714.     u16,            ct,
  715.     struct unipair *,    list)
  716. {
  717.     int err = 0, err1, i;
  718.  
  719.     while (ct--) {
  720.     if ((err1 = con_insert_unipair(list->unicode, list->fontpos)) != 0) {
  721.         err = err1;
  722.     }
  723.     list++;
  724.     }
  725.  
  726.     for (i = 0; i <= 3; i++) {
  727.     set_inverse_transl(i); /* Update all inverse translations */
  728.     }
  729.     return err;
  730. }
  731. #endif /* NOTDEFINED */
  732.  
  733. /*
  734.  *  Loads the unimap for the hardware font, as defined in uni_hash.tbl.
  735.  *  The representation used was the most compact I could come up
  736.  *  with.  This routine is executed at sys_setup time, and when the
  737.  *  PIO_FONTRESET ioctl is called.
  738.  */
  739. PRIVATE void con_set_default_unimap NOARGS
  740. {
  741.     int i, j;
  742.     u16 *p;
  743.  
  744.     /*
  745.      *    The default font is always 256 characters.
  746.      */
  747.     con_clear_unimap(1);
  748.  
  749.     p = dfont_unitable;
  750.     for (i = 0; i < 256; i++) {
  751.     for (j = dfont_unicount[i]; j; j--) {
  752.         con_insert_unipair(*(p++), i, 1);
  753.     }
  754.     }
  755.  
  756. #if 0
  757.     for (i = 0; i <= 3; i++) {
  758.     set_inverse_transl(i);    /* Update all inverse translations */
  759.     }
  760. #endif
  761.  
  762.     UC_default_unitable = dfont_unitable;
  763.  
  764.     con_clear_unimap_str(1);
  765.     UC_con_set_unimap_str(dfont_replacedesc.entry_ct, repl_map, 1);
  766.     UC_default_unitable_str = &dfont_replacedesc;
  767. }
  768.  
  769. PUBLIC int UCNumCharsets = 0;
  770.  
  771. PUBLIC int UCLYhndl_HTFile_for_unspec = -1;
  772. PUBLIC int UCLYhndl_HTFile_for_unrec = -1;
  773. PUBLIC int UCLYhndl_for_unspec = -1;
  774. PUBLIC int UCLYhndl_for_unrec = -1;
  775.  
  776. PRIVATE int UC_con_set_unimap ARGS2(
  777.     int,        UC_charset_out_hndl,
  778.     int,        update_flag)
  779. {
  780.     int i, j;
  781.     u16 *p;
  782.  
  783.     if (!UC_valid_UC_charset(UC_charset_out_hndl)) {
  784.     CTRACE(tfp, "UC_con_set_unimap: Invalid charset handle %d.\n",
  785.             UC_charset_out_hndl);
  786.     return -1;
  787.     }
  788.  
  789.     p = UCInfo[UC_charset_out_hndl].unitable;
  790.     if (p == UC_current_unitable) {    /* test whether pointers are equal */
  791.     return update_flag;            /* nothing to be done */
  792.     }
  793.     UC_current_unitable = p;
  794.  
  795.     /*
  796.      *    The font is always 256 characters - so far.
  797.      */
  798.     con_clear_unimap(0);
  799.  
  800.     for (i = 0; i < 256; i++) {
  801.     for (j = UCInfo[UC_charset_out_hndl].unicount[i]; j; j--) {
  802.         con_insert_unipair(*(p++), i, 0);
  803.     }
  804.     }
  805.  
  806.     if (update_flag) {
  807.     for (i = 0; i <= 3; i++) {
  808.         set_inverse_transl(i);    /* Update all inverse translations */
  809.     }
  810.     }
  811.  
  812.     return 0;
  813. }
  814.  
  815. PRIVATE int UC_con_set_unimap_str ARGS3(
  816.     u16,        ct,
  817.     struct unipair_str *, list,
  818.     int,        fordefault)
  819. {
  820.     int err = 0, err1;
  821.  
  822.     while (ct--) {
  823.     if ((err1 = con_insert_unipair_str(list->unicode,
  824.                        list->replace_str,
  825.                        fordefault)) != 0) {
  826.         err = err1;
  827.     }
  828.     list++;
  829.     }
  830.  
  831.     /*
  832.      *    No inverse translations for replacement strings!
  833.      */
  834.     if (!err) {
  835.     if (fordefault)
  836.         unidefault_str_contents_valid = 1;
  837.     else
  838.         hashtable_str_contents_valid = 1;
  839.     }
  840.  
  841.     return err;
  842. }
  843.  
  844. #ifdef NOTDEFINED
  845. PRIVATE int con_get_unimap ARGS3(
  846.     u16,            ct,
  847.     u16 *,            uct,
  848.     struct unipair *,    list)
  849. {
  850.     int i, j, k, ect;
  851.     u16 **p1, *p2;
  852.  
  853.     ect = 0;
  854.     if (hashtable_contents_valid) {
  855.     for (i = 0; i < 32; i++) {
  856.         if ((p1 = uni_pagedir[i]) != NULL) {
  857.         for (j = 0; j < 32; j++) {
  858.             if ((p2 = *(p1++)) != NULL) {
  859.             for (k = 0; k < 64; k++) {
  860.                 if (*p2 < MAX_GLYPH && ect++ < ct) {
  861.                 list->unicode = (u16) ((i<<11)+(j<<6)+k);
  862.                 list->fontpos = (u16) *p2;
  863.                 list++;
  864.                 }
  865.                 p2++;
  866.             }
  867.             }
  868.         }
  869.         }
  870.     }
  871.     }
  872.     *uct = ect;
  873.     return ((ect <= ct) ? 0 : -ENOMEM);
  874. }
  875. #endif /* NOTDEFINED */
  876.  
  877. PRIVATE int conv_uni_to_pc ARGS2(
  878.     long,        ucs,
  879.     int,        usedefault)
  880. {
  881.     int h;
  882.     u16 **p1, *p2;
  883.  
  884.     /*
  885.      *    Only 16-bit codes supported at this time.
  886.      */
  887.     if (ucs > 0xffff) {
  888.     /*
  889.      *  U+FFFD: REPLACEMENT CHARACTER.
  890.      */
  891.     ucs = 0xfffd;
  892.     } else if (ucs < 0x20 || ucs >= 0xfffe) {
  893.     /*
  894.      *  Not a printable character.
  895.      */
  896.     return -1;
  897.     } else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) {
  898.     /*
  899.      *  Zero-width space.
  900.      */
  901.     return -2;
  902.     } else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE) {
  903.     /*
  904.      *  UNI_DIRECT_BASE indicates the start of the region in the
  905.      *  User Zone which always has a 1:1 mapping to the currently
  906.      *  loaded font.  The UNI_DIRECT_MASK indicates the bit span
  907.      *  of the region.
  908.      */
  909.     return (ucs & UNI_DIRECT_MASK);
  910.     }
  911.  
  912.     if (usedefault) {
  913.     if (!unidefault_contents_valid)
  914.         return -3;
  915.     p1 = unidefault_pagedir[ucs >> 11];
  916.     } else {
  917.     if (!hashtable_contents_valid)
  918.         return -3;
  919.     p1 = uni_pagedir[ucs >> 11];
  920.     }
  921.  
  922.     if (p1 &&
  923.     (p2 = p1[(ucs >> 6) & 0x1f]) &&
  924.     (h = p2[ucs & 0x3f]) < MAX_GLYPH) {
  925.     return h;
  926.     }
  927.  
  928.     /*
  929.      *    Not found.
  930.      */
  931.     return -4;
  932. }
  933.  
  934. /*
  935.  *  Note: contents of outbuf is not changes for negative return value!
  936.  */
  937. PRIVATE int conv_uni_to_str ARGS4(
  938.     char*,        outbuf,
  939.     int,        buflen,
  940.     long,        ucs,
  941.     int,        usedefault)
  942. {
  943.     char *h;
  944.     char ***p1, **p2;
  945.  
  946.     /*
  947.      *    Only 16-bit codes supported at this time.
  948.      */
  949.     if (ucs > 0xffff) {
  950.     /*
  951.      *  U+FFFD: REPLACEMENT CHARACTER.
  952.      */
  953.     ucs = 0xfffd;
  954.     /*
  955.      *    Maybe the following two cases should be allowed here?? - KW
  956.      */
  957.     } else if (ucs < 0x20 || ucs >= 0xfffe) {
  958.     /*
  959.      *  Not a printable character.
  960.      */
  961.     return -1;
  962.     } else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) {
  963.     /*
  964.      *  Zero-width space.
  965.      */
  966.     return -2;
  967. #ifdef NOTDEFINED    /* We don't handle the following here: */
  968.     } else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE) {
  969.     /*
  970.      *  UNI_DIRECT_BASE indicates the start of the region in the
  971.      *  User Zone which always has a 1:1 mapping to the currently
  972.      *  loaded font.  The UNI_DIRECT_MASK indicates the bit span
  973.      *  of the region.
  974.      */
  975.     return ucs & UNI_DIRECT_MASK;
  976. #endif /* NOTDEFINED */
  977.     }
  978.  
  979.     if (usedefault) {
  980.     if (!unidefault_str_contents_valid)
  981.         return -3;
  982.     p1 = unidefault_pagedir_str[ucs >> 11];
  983.     } else {
  984.     if (!hashtable_str_contents_valid)
  985.         return -3;
  986.     p1 = uni_pagedir_str[ucs >> 11];
  987.     }
  988.  
  989.     if (p1 &&
  990.     (p2 = p1[(ucs >> 6) & 0x1f]) &&
  991.     (h = p2[ucs & 0x3f])) {
  992.     strncpy (outbuf,h,(size_t) (buflen-1));
  993.     return 1;     /* ok ! */
  994.     }
  995.  
  996.     /*
  997.      *    Not found.
  998.      */
  999.     return -4;
  1000. }
  1001.  
  1002. PUBLIC int UCInitialized = 0;
  1003. /*
  1004.  *  [ original comment: - KW ]
  1005.  * This is called at sys_setup time, after memory and the console are
  1006.  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
  1007.  * from this function, hence the call from sys_setup.
  1008.  */
  1009. PRIVATE void UCconsole_map_init NOARGS
  1010. {
  1011.     con_set_default_unimap();
  1012.     UCInitialized = 1;
  1013. }
  1014.  
  1015. /*
  1016.  *  OK now, finally, some stuff that is more specifically for Lynx: - KW
  1017.  */
  1018. #ifdef NOTDEFINED
  1019. PUBLIC int UCGetcharset_byMIMEname PARAMS((CONST char * UC_MIMEcharset));
  1020. PUBLIC int UCGetcharset_byLYNXname PARAMS((CONST char * UC_LYNXcharset));
  1021. #endif /* NOTDEFINED */
  1022.  
  1023. PUBLIC int UCTransUniChar ARGS2(
  1024.     long,        unicode,
  1025.     int,        charset_out)
  1026. {
  1027.     int rc = 0;
  1028.     int UChndl_out;
  1029.     int isdefault, trydefault = 0;
  1030.     u16 * ut;
  1031.  
  1032.     if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
  1033.     if ((UChndl_out = default_UChndl) < 0)
  1034.         return -12;
  1035.     isdefault = 1;
  1036.     } else {
  1037.     isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
  1038.     trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
  1039.     }
  1040.  
  1041.     if (!isdefault) {
  1042.     ut = UCInfo[UChndl_out].unitable;
  1043.     if (ut != UC_current_unitable) {
  1044.         rc = UC_con_set_unimap(UChndl_out, 1);
  1045.         if (rc < 0) {
  1046.         return rc;
  1047.         }
  1048.     }
  1049.     rc = conv_uni_to_pc(unicode, 0);
  1050.     if (rc >= 0)
  1051.         return rc;
  1052.     }
  1053.     if (isdefault || trydefault) {
  1054.     rc = conv_uni_to_pc(unicode, 1);
  1055.     if (rc >= 0)
  1056.         return rc;
  1057.     }
  1058.     if (!isdefault && (rc == -4)) {
  1059.     rc = conv_uni_to_pc(0xfffd, 0);
  1060.     }
  1061.     if ((isdefault || trydefault) && (rc == -4)) {
  1062.     rc = conv_uni_to_pc(0xfffd, 1);
  1063.     }
  1064.     return rc;
  1065. }
  1066.  
  1067. /*
  1068.  *  Returns string length, or negative value for error.
  1069.  */
  1070. PUBLIC int UCTransUniCharStr ARGS5(
  1071.     char *,     outbuf,
  1072.     int,        buflen,
  1073.     long,        unicode,
  1074.     int,        charset_out,
  1075.     int,        chk_single_flag)
  1076. {
  1077.     int rc = -14, src = 0, ignore_err;
  1078.     int UChndl_out;
  1079.     int isdefault, trydefault = 0;
  1080.     struct unimapdesc_str * repl;
  1081.     u16 * ut;
  1082.  
  1083.     if (buflen < 2)
  1084.     return -13;
  1085.  
  1086.     if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
  1087.     if ((UChndl_out = default_UChndl) < 0)
  1088.         return -12;
  1089.     isdefault = 1;
  1090.     } else {
  1091.     isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
  1092.     trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
  1093.     }
  1094.  
  1095.     if (chk_single_flag) {
  1096.     if (!isdefault) {
  1097.         ut = UCInfo[UChndl_out].unitable;
  1098.         if (ut != UC_current_unitable) {
  1099.         src = UC_con_set_unimap(UChndl_out, 1);
  1100.         if (src < 0) {
  1101.             return src;
  1102.         }
  1103.         }
  1104.     }
  1105.     src = conv_uni_to_pc(unicode, isdefault);
  1106.     if (src >= 32) {
  1107.         outbuf[0] = src; outbuf[1] = '\0';
  1108.         return 1;
  1109.     }
  1110.     }
  1111.  
  1112.     repl = &(UCInfo[UChndl_out].replacedesc);
  1113.     if (!isdefault) {
  1114.     if (repl != UC_current_unitable_str)  {
  1115.         con_clear_unimap_str(0);
  1116.         ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries, 0);
  1117.         UC_current_unitable_str = repl;
  1118.     }
  1119.     rc = conv_uni_to_str(outbuf, buflen, unicode, 0);
  1120.     if (rc >= 0)
  1121.         return (strlen(outbuf));
  1122.     }
  1123.     if (trydefault && chk_single_flag) {
  1124.     src = conv_uni_to_pc(unicode, 1);
  1125.     if (src >= 32) {
  1126.         outbuf[0] = src; outbuf[1] = '\0';
  1127.         return 1;
  1128.     }
  1129.     }
  1130.     if (isdefault || trydefault) {
  1131.     rc = conv_uni_to_str(outbuf, buflen, unicode, 1);
  1132.     if (rc >= 0)
  1133.         return (strlen(outbuf));
  1134.     }
  1135.     if (rc == -4) {
  1136.     if (!isdefault)
  1137.         rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 0);
  1138.     if ((rc == -4) && (isdefault || trydefault))
  1139.         rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 1);
  1140.     if (rc >= 0)
  1141.         return (strlen(outbuf));
  1142.     }
  1143.     if (chk_single_flag && src == -4) {
  1144.     if (!isdefault)
  1145.         rc = conv_uni_to_pc(0xfffd, 0);
  1146.     if ((rc == -4) && (isdefault || trydefault))
  1147.         rc = conv_uni_to_pc(0xfffd, 1);
  1148.     if (rc >= 32) {
  1149.         outbuf[0] = rc; outbuf[1] = '\0';
  1150.         return 1;
  1151.     }
  1152.     return rc;
  1153.     }
  1154.     return -4;
  1155. }
  1156.  
  1157. PRIVATE int UC_lastautoGN = 0;
  1158.  
  1159. PRIVATE int UC_MapGN ARGS2(
  1160.     int,        UChndl,
  1161.     int,        update_flag)
  1162. {
  1163.     int i, Gn, found, lasthndl;
  1164.     found = 0;
  1165.     Gn = -1;
  1166.     for (i = 0; i < 4 && Gn < 0; i++) {
  1167.     if (UC_GNhandles[i] < 0) {
  1168.         Gn = i;
  1169.     } else if (UC_GNhandles[i] == UChndl) {
  1170.         Gn = i;
  1171.         found = 1;
  1172.     }
  1173.     }
  1174.     if (found)
  1175.     return Gn;
  1176.     if (Gn >= 0) {
  1177.     UCInfo[UChndl].GN = Gn;
  1178.     UC_GNhandles[Gn] = UChndl;
  1179.     } else {
  1180.     if (UC_lastautoGN == GRAF_MAP) {
  1181.         Gn = IBMPC_MAP;
  1182.     } else {
  1183.         Gn = GRAF_MAP;
  1184.     }
  1185.     UC_lastautoGN = Gn;
  1186.     lasthndl = UC_GNhandles[Gn];
  1187.     UCInfo[lasthndl].GN = -1;
  1188.     UCInfo[UChndl].GN = Gn;
  1189.     UC_GNhandles[Gn] = UChndl;
  1190.     }
  1191.     CTRACE(tfp, "UC_MapGN: Using %d <- %d (%s)\n",
  1192.         Gn, UChndl, UCInfo[UChndl].MIMEname);
  1193.     UC_con_set_trans(UChndl,Gn,update_flag);
  1194.     return Gn;
  1195. }
  1196.  
  1197. PUBLIC int UCTransChar ARGS3(
  1198.     char,        ch_in,
  1199.     int,        charset_in,
  1200.     int,        charset_out)
  1201. {
  1202.     int unicode, Gn;
  1203.     int rc = -4;
  1204.     int UChndl_in, UChndl_out;
  1205.     int isdefault, trydefault = 0;
  1206.     u16 * ut;
  1207.     int upd = 0;
  1208.  
  1209. #ifndef UC_NO_SHORTCUTS
  1210.     if (charset_in == charset_out)
  1211.     return (unsigned char)ch_in;
  1212. #endif /* UC_NO_SHORTCUTS */
  1213.     if (charset_in < 0)
  1214.     return -11;
  1215.     if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
  1216.     return -11;
  1217.     if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
  1218.     if ((UChndl_out = default_UChndl) < 0)
  1219.         return -12;
  1220.     isdefault = 1;
  1221.     } else {
  1222.     isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
  1223.     trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
  1224.     }
  1225.     if (!UCInfo[UChndl_in].num_uni)
  1226.     return -11;
  1227.     if ((Gn = UCInfo[UChndl_in].GN) < 0) {
  1228.     Gn = UC_MapGN(UChndl_in,0);
  1229.     upd = 1;
  1230.     }
  1231.  
  1232.     ut = UCInfo[UChndl_out].unitable;
  1233.     if (!isdefault) {
  1234.     if (ut == UC_current_unitable) {
  1235.         if (upd) {
  1236.         set_inverse_transl(Gn);
  1237.         }
  1238.     } else {
  1239.         rc = UC_con_set_unimap(UChndl_out, 1);
  1240.         if (rc > 0) {
  1241.         set_inverse_transl(Gn);
  1242.         } else if (rc < 0) {
  1243.         return rc;
  1244.         }
  1245.     }
  1246.     }
  1247.     UC_translate = set_translate(Gn);
  1248.     unicode = UC_translate[(unsigned char)ch_in];
  1249.     if (!isdefault) {
  1250.     rc = conv_uni_to_pc(unicode, 0);
  1251.     if (rc >= 0)
  1252.         return rc;
  1253.     }
  1254.     if ((rc == -4) && (isdefault || trydefault)) {
  1255.     rc = conv_uni_to_pc(unicode, 1);
  1256.     }
  1257.     if ((rc == -4) && !isdefault) {
  1258.     rc = conv_uni_to_pc(0xfffd, 0);
  1259.     }
  1260.     if ((rc == -4) && (isdefault || trydefault)) {
  1261.     rc = conv_uni_to_pc(0xfffd, 1);
  1262.     }
  1263.     return rc;
  1264. }
  1265.  
  1266. PUBLIC long int UCTransToUni ARGS2(
  1267.     char,        ch_in,
  1268.     int,        charset_in)
  1269. {
  1270.   int unicode, Gn;
  1271.   unsigned char ch_iu;
  1272.   int UChndl_in;
  1273.  
  1274.   ch_iu = (unsigned char)ch_in;
  1275. #ifndef UC_NO_SHORTCUTS
  1276.     if (charset_in == 0)
  1277.     return ch_iu;
  1278.     if ((unsigned char)ch_in < 128 && (unsigned char)ch_in >= 32)
  1279.     return ch_iu;
  1280. #endif /* UC_NO_SHORTCUTS */
  1281.     if (charset_in < 0)
  1282.     return -11;
  1283.     if ((unsigned char)ch_in < 32 &&
  1284.     LYCharSet_UC[charset_in].enc != UCT_ENC_8BIT_C0)
  1285.     /*
  1286.      *  Don't translate C0 chars except for specific charsets.
  1287.      */
  1288.     return ch_iu;
  1289.     if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
  1290.     return -11;
  1291.     if (!UCInfo[UChndl_in].num_uni)
  1292.     return -11;
  1293.     if ((Gn = UCInfo[UChndl_in].GN) < 0) {
  1294.     Gn = UC_MapGN(UChndl_in,1);
  1295.     }
  1296.  
  1297.   UC_translate = set_translate(Gn);
  1298.   unicode = UC_translate[(unsigned char)ch_in];
  1299.  
  1300.   return unicode;
  1301. }
  1302.  
  1303. PUBLIC int UCReverseTransChar ARGS3(
  1304.     char,        ch_out,
  1305.     int,        charset_in,
  1306.     int,        charset_out)
  1307. {
  1308.     int Gn;
  1309.     int rc;
  1310.     int UChndl_in, UChndl_out;
  1311.     int isdefault;
  1312.     int i_ch = (unsigned char)ch_out;
  1313.     u16 * ut;
  1314.  
  1315. #ifndef UC_NO_SHORTCUTS
  1316.     if (charset_in == charset_out)
  1317.     return ch_out;
  1318. #endif /* UC_NO_SHORTCUTS */
  1319.     if (charset_in < 0)
  1320.     return -11;
  1321.     if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
  1322.     return -11;
  1323.     if (!UCInfo[UChndl_in].num_uni)
  1324.     return -11;
  1325.     if (charset_out < 0)
  1326.     return -12;
  1327.     if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
  1328.     if ((UChndl_out = default_UChndl) < 0)
  1329.         return -12;
  1330.     isdefault = 1;
  1331.     } else {
  1332.     isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
  1333.     }
  1334.  
  1335.     if (!isdefault) {
  1336.     /*
  1337.      *  Try to use the inverse table if charset_out is not equivalent
  1338.      *  to using just the default table.  If it is, it should have
  1339.      *  just ASCII chars and trying to back-translate those should
  1340.      *  not give anything but themselves. - kw
  1341.      */
  1342.     ut = UCInfo[UChndl_out].unitable;
  1343.     if (ut == UC_current_unitable) {
  1344.         if ((Gn = UCInfo[UChndl_in].GN) >= 0) {
  1345.         UC_translate = set_translate(Gn);
  1346.         rc = inv_translate[i_ch];
  1347.         if (rc >= 32) {
  1348.             return rc;
  1349.         }
  1350.         } else {
  1351.         Gn = UC_MapGN(UChndl_in,1);
  1352.         UC_translate = set_translate(Gn);
  1353.         rc = inv_translate[i_ch];
  1354.         if (rc >= 32) {
  1355.             return rc;
  1356.         }
  1357.         }
  1358.     }
  1359.     }
  1360.     return UCTransChar(ch_out, charset_out, charset_in);
  1361. }
  1362.  
  1363. /*
  1364.  *  Returns string length, or negative value for error.
  1365.  */
  1366. PUBLIC int UCTransCharStr ARGS6(
  1367.     char *,     outbuf,
  1368.     int,        buflen,
  1369.     char,        ch_in,
  1370.     int,        charset_in,
  1371.     int,        charset_out,
  1372.     int,        chk_single_flag)
  1373. {
  1374.     int unicode, Gn;
  1375.     int rc = -14, src = 0, ignore_err;
  1376.     int UChndl_in, UChndl_out;
  1377.     int isdefault, trydefault = 0;
  1378.     struct unimapdesc_str * repl;
  1379.     u16 * ut;
  1380.     int upd = 0;
  1381.  
  1382.     if (buflen < 2)
  1383.     return -13;
  1384. #ifndef UC_NO_SHORTCUTS
  1385.     if (chk_single_flag && charset_in == charset_out) {
  1386.     outbuf[0] = ch_in;
  1387.     outbuf[1] = '\0';
  1388.     return 1;
  1389.     }
  1390. #endif /* UC_NO_SHORTCUTS */
  1391.     if (charset_in < 0)
  1392.     return -11;
  1393.     if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
  1394.     return -11;
  1395.     if (!UCInfo[UChndl_in].num_uni)
  1396.     return -11;
  1397.     if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
  1398.     if ((UChndl_out = default_UChndl) < 0)
  1399.         return -12;
  1400.     isdefault = 1;
  1401.     } else {
  1402.     isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
  1403.     trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
  1404.     }
  1405.     if ((Gn = UCInfo[UChndl_in].GN) < 0) {
  1406.     Gn = UC_MapGN(UChndl_in, !chk_single_flag);
  1407.     upd = chk_single_flag;
  1408.     }
  1409.  
  1410.     UC_translate = set_translate(Gn);
  1411.     unicode = UC_translate[(unsigned char)ch_in];
  1412.  
  1413.     if (chk_single_flag) {
  1414.     if (!isdefault) {
  1415.         ut = UCInfo[UChndl_out].unitable;
  1416.         if (ut == UC_current_unitable) {
  1417.         if (upd) set_inverse_transl(Gn);
  1418.         } else {
  1419.         src = UC_con_set_unimap(UChndl_out, 1);
  1420.         if (src > 0) {
  1421.             set_inverse_transl(Gn);
  1422.         } else if (src < 0) {
  1423.             return src;
  1424.         }
  1425.         }
  1426.     }
  1427.     src = conv_uni_to_pc(unicode, isdefault);
  1428.     if (src >= 32) {
  1429.         outbuf[0] = src; outbuf[1] = '\0';
  1430.         return 1;
  1431.     }
  1432.     }
  1433.  
  1434.     repl = &(UCInfo[UChndl_out].replacedesc);
  1435.     if (!isdefault) {
  1436.     if (repl != UC_current_unitable_str) {
  1437.         con_clear_unimap_str(0);
  1438.         ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries, 0);
  1439.         UC_current_unitable_str = repl;
  1440.     }
  1441.     rc = conv_uni_to_str(outbuf, buflen, unicode, 0);
  1442.     if (rc >= 0)
  1443.         return (strlen(outbuf));
  1444.     }
  1445.     if (trydefault && chk_single_flag) {
  1446.     src = conv_uni_to_pc(unicode, 1);
  1447.     if (src >= 32) {
  1448.         outbuf[0] = src; outbuf[1] = '\0';
  1449.         return 1;
  1450.     }
  1451.     }
  1452.     if (isdefault || trydefault) {
  1453.     rc = conv_uni_to_str(outbuf, buflen, unicode, 1);
  1454.     if (rc >= 0)
  1455.         return (strlen(outbuf));
  1456.     }
  1457.     if (rc == -4) {
  1458.     if (!isdefault)
  1459.         rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 0);
  1460.     if ((rc == -4) && (isdefault || trydefault))
  1461.         rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 1);
  1462.     if (rc >= 0)
  1463.         return (strlen(outbuf));
  1464.     }
  1465.     if (chk_single_flag && src == -4) {
  1466.     if (!isdefault)
  1467.         rc = conv_uni_to_pc(0xfffd, 0);
  1468.     if ((rc == -4) && (isdefault || trydefault))
  1469.         rc = conv_uni_to_pc(0xfffd, 1);
  1470.     if (rc >= 32) {
  1471.         outbuf[0] = rc; outbuf[1] = '\0';
  1472.         return 1;
  1473.     } else if (rc <= 0) {
  1474.         outbuf[0] = '\0';
  1475.         return rc;
  1476.     }
  1477.     return rc;
  1478.     }
  1479.     return -4;
  1480. }
  1481.  
  1482. PRIVATE int UC_FindGN_byMIME ARGS1(
  1483.     CONST char *,    UC_MIMEcharset)
  1484. {
  1485.   int i;
  1486.  
  1487.     for (i = 0; i < 4; i++) {
  1488.     if (!strcmp(UC_MIMEcharset,UC_GNsetMIMEnames[i])) {
  1489.       return i;
  1490.     }
  1491.     }
  1492.   return -1;
  1493. }
  1494.  
  1495. PUBLIC int UCGetRawUniMode_byLYhndl ARGS1(
  1496.     int,        i)
  1497. {
  1498.     if (i < 0)
  1499.     return 0;
  1500.   return LYCharSet_UC[i].enc;
  1501. }
  1502.  
  1503. /*
  1504.  *  Currently the charset name has to match exactly -- not substring
  1505.  *  matching as was done before (see HTMIME.c, HTML.c).
  1506.  */
  1507. PUBLIC int UCGetLYhndl_byMIME ARGS1(
  1508.     CONST char *,    UC_MIMEcharset)
  1509. {
  1510.   int i;
  1511.   int LYhndl = -1;
  1512.  
  1513.     if (!UC_MIMEcharset || !(*UC_MIMEcharset))
  1514.     return -1;
  1515.  
  1516.     for (i = 0;
  1517.      (i < MAXCHARSETS && i < LYNumCharsets &&
  1518.       LYchar_set_names[i] && LYhndl < 0); i++) {
  1519.     if (LYCharSet_UC[i].MIMEname &&
  1520.         !strcmp(UC_MIMEcharset, LYCharSet_UC[i].MIMEname)) {
  1521.         LYhndl = i;
  1522.     }
  1523.     }
  1524.     if (LYhndl < 0) {
  1525.     /*
  1526.      *  Not yet found, try synonyms. - FM
  1527.      */
  1528.     if (!strcmp(UC_MIMEcharset, "unicode-1-1-utf-8") ||
  1529.         !strcmp(UC_MIMEcharset, "utf8")) {
  1530.         /*
  1531.          *    Treat these as synonyms for the IANA registered name. - FM
  1532.          */
  1533.         return UCGetLYhndl_byMIME("utf-8");
  1534.     }
  1535.     if (!strncmp(UC_MIMEcharset, "iso-2022-jp", 11) ||
  1536.         !strcmp(UC_MIMEcharset, "x-euc-jp")) {
  1537.         return UCGetLYhndl_byMIME("euc-jp");
  1538.     }
  1539.     if (!strcmp(UC_MIMEcharset, "x-shift-jis")) {
  1540.         return UCGetLYhndl_byMIME("shift_jis");
  1541.     }
  1542.     if (!strcmp(UC_MIMEcharset, "iso-2022-kr")) {
  1543.         return UCGetLYhndl_byMIME("euc-kr");
  1544.     }
  1545.     if (!strcmp(UC_MIMEcharset, "gb2312") ||
  1546.         !strncmp(UC_MIMEcharset, "cn-gb", 5) ||
  1547.         !strcmp(UC_MIMEcharset, "iso-2022-cn")) {
  1548.         return UCGetLYhndl_byMIME("euc-cn");
  1549.     }
  1550.     if (!strcmp(UC_MIMEcharset, "cn-big5")) {
  1551.         return UCGetLYhndl_byMIME("big5");
  1552.     }
  1553.     if (!strcmp(UC_MIMEcharset, "x-mac-roman") ||
  1554.         !strcmp(UC_MIMEcharset, "mac-roman")) {
  1555.         return UCGetLYhndl_byMIME("macintosh");
  1556.     }
  1557.     if (!strcmp(UC_MIMEcharset, "x-next") ||
  1558.         !strcmp(UC_MIMEcharset, "nextstep") ||
  1559.         !strcmp(UC_MIMEcharset, "x-nextstep")) {
  1560.         return UCGetLYhndl_byMIME("next");
  1561.     }
  1562.     if (!strcmp(UC_MIMEcharset, "iso-8859-1-windows-3.1-latin-1") ||
  1563.         !strcmp(UC_MIMEcharset, "cp1252") ||
  1564.         !strcmp(UC_MIMEcharset, "cp-1252") ||
  1565.         !strcmp(UC_MIMEcharset, "ibm1252") ||
  1566.         !strcmp(UC_MIMEcharset, "iso-8859-1-windows-3.0-latin-1")) {
  1567.         /*
  1568.          *    Treat these as synonyms for windows-1252, which is more
  1569.          *    commonly used than the IANA registered name. - FM
  1570.          */
  1571.         return UCGetLYhndl_byMIME("windows-1252");
  1572.     }
  1573.     if (!strcmp(UC_MIMEcharset, "iso-8859-2-windows-latin-2") ||
  1574.         !strcmp(UC_MIMEcharset, "cp1250") ||
  1575.         !strcmp(UC_MIMEcharset, "cp-1250") ||
  1576.         !strcmp(UC_MIMEcharset, "ibm1250")) {
  1577.         /*
  1578.          *    Treat these as synonyms for windows-1250. - FM
  1579.          */
  1580.         return UCGetLYhndl_byMIME("windows-1250");
  1581.     }
  1582.     if ((!strncmp(UC_MIMEcharset, "ibm", 3) ||
  1583.          !strncmp(UC_MIMEcharset, "cp-", 3)) &&
  1584.         isdigit((unsigned char)UC_MIMEcharset[3]) &&
  1585.         isdigit((unsigned char)UC_MIMEcharset[4]) &&
  1586.         isdigit((unsigned char)UC_MIMEcharset[5])) {
  1587.         /*
  1588.          *    For "ibmNNN<...>" or "cp-NNN", try "cpNNN<...>"
  1589.          *    if not yet found. - KW & FM
  1590.          */
  1591.         char * cptmp = NULL;
  1592.  
  1593.         StrAllocCopy(cptmp, (UC_MIMEcharset + 1));
  1594.         cptmp[0] = 'c';
  1595.         cptmp[1] = 'p';
  1596.         if ((LYhndl = UCGetLYhndl_byMIME(cptmp)) >= 0) {
  1597.         FREE(cptmp);
  1598.         return LYhndl;
  1599.         }
  1600.         /*
  1601.          *    Try windows-NNN<...> if not yet found. - FM
  1602.          */
  1603.         StrAllocCopy(cptmp, "windows-");
  1604.         StrAllocCat(cptmp, (UC_MIMEcharset + 3));
  1605.         LYhndl = UCGetLYhndl_byMIME(cptmp);
  1606.         FREE(cptmp);
  1607.         return LYhndl;
  1608.     }
  1609.     if (!strncmp(UC_MIMEcharset, "windows-", 8) &&
  1610.         isdigit((unsigned char)UC_MIMEcharset[8]) &&
  1611.         isdigit((unsigned char)UC_MIMEcharset[9]) &&
  1612.         isdigit((unsigned char)UC_MIMEcharset[10])) {
  1613.         /*
  1614.          *    For "windows-NNN<...>", try "cpNNN<...>" - FM
  1615.          */
  1616.         char * cptmp = NULL;
  1617.  
  1618.         StrAllocCopy(cptmp, (UC_MIMEcharset + 6));
  1619.         cptmp[0] = 'c';
  1620.         cptmp[1] = 'p';
  1621.         LYhndl = UCGetLYhndl_byMIME(cptmp);
  1622.         FREE(cptmp);
  1623.         return LYhndl;
  1624.     }
  1625.     if (!strcmp(UC_MIMEcharset, "koi-8")) { /* accentsoft bugosity */
  1626.       return UCGetLYhndl_byMIME("koi8-r");
  1627.   }
  1628.     }
  1629.   return LYhndl;    /* returns -1 if no charset found by that MIME name */
  1630. }
  1631.  
  1632. /*
  1633.  *  Function UC_setup_LYCharSets_repl() tries to set up a subtable in
  1634.  *  LYCharSets[] appropriate for this new charset, for compatibility
  1635.  *  with the "old method".  Maybe not nice (maybe not even necessary
  1636.  *  any more), but it works (as far as it goes..).
  1637.  *
  1638.  *  We try to be conservative and only allocate new memory for this
  1639.  *  if needed.    If not needed, just point to SevenBitApproximations[i].
  1640.  *  [Could do the same for ISO_Latin1[] if it's identical to that, but
  1641.  *   would make it even *more* messy than it already is...]
  1642.  *  This the only function in this file that knows, or cares, about the
  1643.  *  HTMLDTD or details of LYCharSets[] subtables (and therefore somewhat
  1644.  *  violates the idea that this file should be independent of those).
  1645.  *  As in other places, we rely on ISO_Latin1 being the *first* table
  1646.  *  in LYCharSets. - KW
  1647.  */
  1648.  
  1649. /*
  1650.  *  We need to remember which ones were allocated and which are static.
  1651.  */
  1652. PRIVATE char ** remember_allocated_LYCharSets[MAXCHARSETS];
  1653.  
  1654. PRIVATE void UCreset_allocated_LYCharSets NOARGS
  1655. {
  1656.     int i = 0;
  1657.  
  1658.     for (; i < MAXCHARSETS; i++) {
  1659.     remember_allocated_LYCharSets[i] = NULL;
  1660.     }
  1661. }
  1662.  
  1663. PRIVATE void UCfree_allocated_LYCharSets NOARGS
  1664. {
  1665.     int i = 0;
  1666.  
  1667.     for (; i < MAXCHARSETS; i++) {
  1668.     if (remember_allocated_LYCharSets[i] != NULL) {
  1669.         FREE(remember_allocated_LYCharSets[i]);
  1670.     }
  1671.     }
  1672. }
  1673.  
  1674. PRIVATE char ** UC_setup_LYCharSets_repl ARGS2(
  1675.     int,        UC_charset_in_hndl,
  1676.     unsigned,    lowest8)
  1677. {
  1678.     char **ISO_Latin1 = LYCharSets[0];
  1679.     char **p;
  1680.     char **prepl;
  1681.     u16 *pp;
  1682.     char **tp;
  1683.     char *s7;
  1684.     char *s8;
  1685.     size_t i;
  1686.     int j, changed;
  1687.     u16 k;
  1688.     u8 *ti;
  1689.  
  1690.     /*
  1691.      *    Create a temporary table for reverse lookup of latin1 codes:
  1692.      */
  1693.     tp = (char **)malloc(96 * sizeof(char *));
  1694.     if (!tp)
  1695.     return NULL;
  1696.     for (i = 0; i < 96; i++)
  1697.     tp[i] = NULL;
  1698.     ti = (u8 *)malloc(96 * sizeof(u8));
  1699.     if (!ti) {
  1700.     FREE(tp);
  1701.     return NULL;
  1702.     }
  1703.     for (i = 0; i < 96; i++)
  1704.     ti[i] = 0;
  1705.  
  1706.     pp = UCInfo[UC_charset_in_hndl].unitable;
  1707.  
  1708.     /*
  1709.      *    Determine if we have any mapping of a Unicode in the range 160-255
  1710.      *    to an allowed code point > 0x80 in our new charset...
  1711.      *    Store any mappings found in ti[].
  1712.      */
  1713.     if (UCInfo[UC_charset_in_hndl].num_uni > 0) {
  1714.     for (i = 0; i < 256; i++) {
  1715.         if ((j = UCInfo[UC_charset_in_hndl].unicount[i])) {
  1716.         if ((k = *pp) >= 160 && k < 256 && i >= lowest8) {
  1717.            ti[k-160] = i;
  1718.         }
  1719.         for (; j; j--) {
  1720.             pp++;
  1721.         }
  1722.         }
  1723.     }
  1724.     }
  1725.     {
  1726.     u16 ct;
  1727.     struct unipair_str *list;
  1728.  
  1729.     /*
  1730.      *  Determine if we have any mapping of a Unicode in the range
  1731.      *  160-255 to a replacement string for our new charset...
  1732.      *  Store any mappings found in tp[].
  1733.      */
  1734.     ct = UCInfo[UC_charset_in_hndl].replacedesc.entry_ct;
  1735.     list = UCInfo[UC_charset_in_hndl].replacedesc.entries;
  1736.     while (ct--) {
  1737.         if ((k = list->unicode) >= 160 && k < 256) {
  1738.         tp[k-160] = list->replace_str;
  1739.         }
  1740.         list++;
  1741.     }
  1742.     }
  1743.     /*
  1744.      *    Now allocate a new table compatible with LYCharSets[]
  1745.      *    and with the HTMLDTD for entities.
  1746.      *    We don't know yet whether we'll keep it around. */
  1747.     p = prepl = (char **)malloc(HTML_dtd.number_of_entities * sizeof(char *));
  1748.     if (!p) {
  1749.     FREE(tp);
  1750.     FREE(ti);
  1751.     return NULL;
  1752.     }
  1753.     changed = 0;
  1754.     for (i = 0; i < HTML_dtd.number_of_entities; i++, p++) {
  1755.     /*
  1756.      *  For each of those entities, we check what the "old method"
  1757.      *  ISO_Latin1[] mapping does with them.  If it is nothing we
  1758.      *  want to use, just point to the SevenBitApproximations[] string.
  1759.      */
  1760.     s7 = SevenBitApproximations[i];
  1761.     s8 = ISO_Latin1[i];
  1762.     *p = s7;
  1763.     if (s8 && (unsigned char)(*s8) >= 160 && strlen(s8) == 1) {
  1764.         /*
  1765.          *    We have an entity that is mapped to
  1766.          *    one valid eightbit latin1 char.
  1767.          */
  1768.         if (ti[(unsigned char)(*s8) - 160] >= lowest8 &&
  1769.         !(s7[0] == ti[(unsigned char)(*s8) - 160] &&
  1770.         s7[1] == '\0')) {
  1771.         /*
  1772.          *  ...which in turn is mapped, by our "new method",
  1773.          *   to another valid eightbit char for this new
  1774.          *   charset: either to itself...
  1775.          */
  1776.         if (ti[(unsigned char)(*s8) - 160] == (unsigned char)(*s8)) {
  1777.             *p = s8;
  1778.         } else {
  1779.             /*
  1780.              *                  ...or another byte...
  1781.              */
  1782. #ifdef NOTDEFINED
  1783.             *p = (char *)malloc(2*sizeof(char));
  1784.             if (!*p) {
  1785.             FREE(tp);
  1786.             FREE(ti);
  1787.             FREE(prepl);
  1788.             return NULL;
  1789.             }
  1790.             (*p)[0] = ti[(unsigned char)(*s8) - 160];
  1791.             (*p)[1] = '\0';
  1792. #else
  1793.             /*
  1794.              *    Use this instead... make those 1-char strings
  1795.              *    into HTAtoms, so they will be cleaned up
  1796.              *    at exit... all for the sake of preventing
  1797.              *    memory leaks, sigh.
  1798.              */
  1799.             static char dummy[2];    /* one char dummy string */
  1800.  
  1801.             dummy[0] = ti[(unsigned char)(*s8) - 160];
  1802.             *p = HTAtom_name(HTAtom_for(dummy));
  1803. #endif /* NOTDEFINED */
  1804.         }
  1805.         changed = 1;
  1806.         } else if (tp[(unsigned char)(*s8) - 160] &&
  1807.                strcmp(s7, tp[(unsigned char)(*s8) - 160])) {
  1808.         /*
  1809.          *  ...or which is mapped, by our "new method",
  1810.          *  to a replacement string for this new charset.
  1811.          */
  1812.         *p = tp[(unsigned char)(*s8) - 160];
  1813.         changed = 1;
  1814.         }
  1815.     }
  1816.     }
  1817.     FREE(tp);
  1818.     FREE(ti);
  1819.     if (!changed) {
  1820.     FREE(prepl);
  1821.     return NULL;
  1822.     }
  1823.     return prepl;
  1824. }
  1825.  
  1826. /*
  1827.  *  "New method" meets "Old method" ...
  1828.  */
  1829. PRIVATE int UC_Register_with_LYCharSets ARGS4(
  1830.     int,        s,
  1831.     CONST char *,    UC_MIMEcharset,
  1832.     CONST char *,    UC_LYNXcharset,
  1833.     int,        lowest_eightbit)
  1834. {
  1835.     int i, LYhndl, found;
  1836.     char **repl;
  1837.  
  1838.     LYhndl = -1;
  1839.     if (LYNumCharsets == 0) {
  1840.     /*
  1841.      *  Initialize here; so whoever changes
  1842.      *  LYCharSets.c doesn't have to count...
  1843.      */
  1844.     for (i = 0; (i < MAXCHARSETS) && LYchar_set_names[i]; i++) {
  1845.         LYNumCharsets = i+1;
  1846.     }
  1847.     }
  1848.  
  1849.     /*
  1850.      *    Do different kinds of searches...
  1851.      *    Normally the first should find the match if there is one!
  1852.      */
  1853.     for (i = 0; i < MAXCHARSETS && LYchar_set_names[i] && LYhndl < 0; i++) {
  1854.     if (!strcmp(UC_LYNXcharset, LYchar_set_names[i])) {
  1855.         LYhndl = i;
  1856.     }
  1857.     }
  1858.     for (i = 0; i < MAXCHARSETS && LYchar_set_names[i] && LYhndl < 0; i++) {
  1859.     if (LYCharSet_UC[i].MIMEname &&
  1860.         !strcmp(UC_MIMEcharset, LYCharSet_UC[i].MIMEname)) {
  1861.         LYhndl = i;
  1862.     }
  1863.     }
  1864.  
  1865.     if (LYhndl < 0) {        /* not found */
  1866.     found = 0;
  1867.     if (LYNumCharsets >= MAXCHARSETS) {
  1868.         CTRACE(tfp, "UC_Register_with_LYCharSets: Too many. Ignoring %s/%s.",
  1869.             UC_MIMEcharset, UC_LYNXcharset);
  1870.         return -1;
  1871.     }
  1872.     /*
  1873.      *  Add to LYCharSets.c lists.
  1874.      */
  1875.     LYhndl = LYNumCharsets;
  1876.     LYNumCharsets ++;
  1877.     LYlowest_eightbit[LYhndl] = 999;
  1878.     LYCharSets[LYhndl] = SevenBitApproximations;
  1879.     /*
  1880.      *  Hmm, try to be conservative here.
  1881.      */
  1882.     LYchar_set_names[LYhndl] = UC_LYNXcharset;
  1883.     LYchar_set_names[LYhndl+1] = NULL;
  1884.     /*
  1885.     *  Terminating NULL may be looked for by Lynx code.
  1886.     */
  1887.     } else {
  1888.     found = 1;
  1889.     }
  1890.     LYCharSet_UC[LYhndl].UChndl = s;
  1891.     /*
  1892.      *    Can we just copy the pointer?  Hope so...
  1893.      */
  1894.     LYCharSet_UC[LYhndl].MIMEname = UC_MIMEcharset;
  1895.     LYCharSet_UC[LYhndl].enc = UCInfo[s].enc;
  1896.  
  1897.     /*
  1898.      *    @@@ We really SHOULD get more info from the table files,
  1899.      *    and set relevant flags in the LYCharSet_UC[] entry with
  1900.      *    that info...  For now, let's try it without. - KW
  1901.      */
  1902.     if (lowest_eightbit < LYlowest_eightbit[LYhndl]) {
  1903.     LYlowest_eightbit[LYhndl] = lowest_eightbit;
  1904.     } else if (lowest_eightbit > LYlowest_eightbit[LYhndl]) {
  1905.     UCInfo[s].lowest_eight = LYlowest_eightbit[LYhndl];
  1906.     }
  1907.  
  1908.     if (!found && LYhndl > 0) {
  1909.     repl = UC_setup_LYCharSets_repl(s,UCInfo[s].lowest_eight);
  1910.     if (repl) {
  1911.         LYCharSets[LYhndl] = repl;
  1912.         /*
  1913.          *    Remember to FREE at exit.
  1914.          */
  1915.         remember_allocated_LYCharSets[LYhndl]=repl;
  1916.     }
  1917.     }
  1918.     return LYhndl;
  1919. }
  1920.  
  1921. /*
  1922.  *  This only sets up the structure - no initialization of the tables
  1923.  * is done here yet.
  1924.  */
  1925. PUBLIC void UC_Charset_Setup ARGS8(
  1926.     CONST char *,        UC_MIMEcharset,
  1927.     CONST char *,        UC_LYNXcharset,
  1928.     u8 *,            unicount,
  1929.     u16 *,            unitable,
  1930.     int,            nnuni,
  1931.     struct unimapdesc_str,    replacedesc,
  1932.     int,            lowest_eight,
  1933.     int,            UC_rawuni)
  1934. {
  1935.     int s, Gn;
  1936.     int i, status = 0, found;
  1937.  
  1938.     /*
  1939.      *    Get (new?) slot.
  1940.      */
  1941.     found = -1;
  1942.     for (i = 0; i < UCNumCharsets && found < 0; i++) {
  1943.     if (!strcmp(UCInfo[i].MIMEname, UC_MIMEcharset)) {
  1944.         found = i;
  1945.     }
  1946.     }
  1947.     if (found >= 0) {
  1948.     s = found;
  1949.     } else {
  1950.     if (UCNumCharsets >= MAXCHARSETS) {
  1951.         CTRACE(tfp, "UC_Charset_Setup: Too many. Ignoring %s/%s.",
  1952.             UC_MIMEcharset, UC_LYNXcharset);
  1953.         return;
  1954.     }
  1955.     s = UCNumCharsets;
  1956.     UCInfo[s].MIMEname = UC_MIMEcharset;
  1957.     }
  1958.     UCInfo[s].LYNXname = UC_LYNXcharset;
  1959.     UCInfo[s].unicount = unicount;
  1960.     UCInfo[s].unitable = unitable;
  1961.     UCInfo[s].num_uni = nnuni;
  1962.     UCInfo[s].replacedesc = replacedesc;
  1963.     if (replacedesc.isdefault) {
  1964.     default_UChndl = s;
  1965.     }
  1966.     Gn = UC_FindGN_byMIME(UC_MIMEcharset);
  1967.     if (Gn >= 0)
  1968.     UC_GNhandles[Gn] = s;
  1969.     UCInfo[s].GN = Gn;
  1970.     if (UC_rawuni == UCT_ENC_UTF8)
  1971.     lowest_eight = 128;  /* cheat here */
  1972.     UCInfo[s].lowest_eight = lowest_eight;
  1973.     UCInfo[s].enc = UC_rawuni;
  1974.     UCInfo[s].LYhndl = UC_Register_with_LYCharSets(s,
  1975.                            UC_MIMEcharset,
  1976.                            UC_LYNXcharset,
  1977.                            lowest_eight);
  1978.     UCInfo[s].uc_status = status;
  1979.     if (found < 0)
  1980.     UCNumCharsets++;
  1981.     return;
  1982. }
  1983.  
  1984. PRIVATE void UCcleanup_mem NOARGS
  1985. {
  1986.     int i;
  1987.  
  1988.     UCfree_allocated_LYCharSets();
  1989.     con_clear_unimap_str(0);
  1990.     con_clear_unimap_str(1);
  1991.     con_clear_unimap(0);
  1992.     con_clear_unimap(1);
  1993.     for (i = 1; i < 4; i++) {    /* first one is static! */
  1994.     FREE(inverse_translations[i]);
  1995.     }
  1996. }
  1997.  
  1998. PUBLIC void UCInit NOARGS
  1999. {
  2000.     UCreset_allocated_LYCharSets();
  2001.     atexit(UCcleanup_mem);
  2002.     UCconsole_map_init();
  2003.  
  2004.     UC_CHARSET_SETUP;    /* us-ascii */      /* 7 bit approximations */
  2005.  
  2006. /*
  2007.  *  The order of charset names visible in Lynx Options menu
  2008.  *  correspond to the order of lines below,
  2009.  *  except for CJK and others described in LYCharSet.c
  2010.  */
  2011.  
  2012.     UC_CHARSET_SETUP_iso_8859_1;      /* ISO Latin 1      */
  2013.     UC_CHARSET_SETUP_cp850;          /* DosLatin1 (cp850)      */
  2014.     UC_CHARSET_SETUP_windows_1252;      /* WinLatin1 (cp1252)   */
  2015.     UC_CHARSET_SETUP_cp437;          /* DosLatinUS (cp437)   */
  2016.  
  2017.     UC_CHARSET_SETUP_dec_mcs;          /* DEC Multinational      */
  2018.     UC_CHARSET_SETUP_macintosh;       /* Macintosh (8 bit)      */
  2019.     UC_CHARSET_SETUP_next;          /* NeXT character set   */
  2020.  
  2021.     UC_CHARSET_SETUP_viscii;          /* Vietnamese (VISCII)  */
  2022.  
  2023.     UC_CHARSET_SETUP_iso_8859_2;      /* ISO Latin 2      */
  2024.     UC_CHARSET_SETUP_cp852;          /* DosLatin2 (cp852)      */
  2025.     UC_CHARSET_SETUP_windows_1250;      /* WinLatin2 (cp1250)   */
  2026.     UC_CHARSET_SETUP_iso_8859_3;      /* ISO Latin 3      */
  2027.     UC_CHARSET_SETUP_iso_8859_4;      /* ISO Latin 4      */
  2028.     UC_CHARSET_SETUP_cp775;          /* DosBaltRim (cp775)   */
  2029.     UC_CHARSET_SETUP_windows_1257;      /* WinBaltRim (cp1257)  */
  2030.     UC_CHARSET_SETUP_iso_8859_5;      /* ISO 8859-5 Cyrillic  */
  2031.     UC_CHARSET_SETUP_cp866;          /* DosCyrillic (cp866)  */
  2032.     UC_CHARSET_SETUP_windows_1251;      /* WinCyrillic (cp1251) */
  2033.     UC_CHARSET_SETUP_koi8_r;          /* KOI8-R Cyrillic      */
  2034.     UC_CHARSET_SETUP_iso_8859_6;      /* ISO 8869-6 Arabic      */
  2035.     UC_CHARSET_SETUP_cp864;          /* DosArabic (cp864)      */
  2036.     UC_CHARSET_SETUP_windows_1256;      /* WinArabic (cp1256)   */
  2037.     UC_CHARSET_SETUP_iso_8859_7;      /* ISO 8859-7 Greek      */
  2038.     UC_CHARSET_SETUP_cp737;          /* DosGreek (cp737)      */
  2039.     UC_CHARSET_SETUP_cp869;          /* DosGreek2 (cp869)      */
  2040.     UC_CHARSET_SETUP_windows_1253;      /* WinGreek (cp1253)      */
  2041.     UC_CHARSET_SETUP_iso_8859_8;      /* ISO 8859-8 Hebrew      */
  2042.     UC_CHARSET_SETUP_cp862;          /* DosHebrew (cp862)      */
  2043.     UC_CHARSET_SETUP_windows_1255;      /* WinHebrew (cp1255)   */
  2044.     UC_CHARSET_SETUP_iso_8859_9;      /* ISO 8859-9 (Latin 5) */
  2045.     UC_CHARSET_SETUP_iso_8859_10;      /* ISO 8859-10      */
  2046.  
  2047.     UC_CHARSET_SETUP_utf_8;          /* UNICODE UTF-8      */
  2048.     UC_CHARSET_SETUP_mnemonic_ascii_0;      /* RFC 1345 w/o Intro   */
  2049.     UC_CHARSET_SETUP_mnemonic;          /* RFC 1345 Mnemonic      */
  2050. #ifdef NOTDEFINED
  2051.     UC_CHARSET_SETUP_mnem;
  2052. #endif /* NOTDEFINED */
  2053.  
  2054. /*
  2055.  *  To add synonyms for any charset name
  2056.  *  check function UCGetLYhndl_byMIME in this file.
  2057.  */
  2058. }
  2059.