Line discipline module now uses dynamically allocated data. Also
[u/mdw/putty] / unicode.c
index ad14b32..19a2e1d 100644 (file)
--- a/unicode.c
+++ b/unicode.c
@@ -1,4 +1,6 @@
+#ifdef WINDOWS
 #include <windows.h>
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,17 +8,12 @@
 
 #include <time.h>
 #include "putty.h"
+#include "terminal.h"
 #include "misc.h"
 
-void init_ucs_tables(void);
-void lpage_send(int codepage, char *buf, int len);
-void luni_send(wchar_t * widebuf, int len);
-
-static void get_unitab(int codepage, wchar_t * unitab, int ftype);
-
 /* Character conversion arrays; they are usually taken from windows,
  * the xterm one has the four scanlines that have no unicode 2.0
- * equlivents mapped into the private area.
+ * equivalents mapped to their unicode 3.0 locations.
  */
 static char **uni_tbl;
 
@@ -33,6 +30,161 @@ static WCHAR unitab_xterm_std[32] = {
  * duplicate definitions.
  */
 
+/* 
+ * Tables for ISO-8859-{1-9,13-16} derived from those downloaded
+ * 2001-10-02 from <http://www.unicode.org/Public/MAPPINGS/> -- jtn
+ */
+
+/* XXX: This could be done algorithmically, but I'm not sure it's
+ *      worth the hassle -- jtn */
+/* ISO/IEC 8859-1:1998 (Latin-1, "Western", "West European") */
+static wchar_t iso_8859_1[] = {
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+    0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+    0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
+};
+
+/* ISO 8859-2:1999 (Latin-2, "Central European", "East European") */
+static wchar_t iso_8859_2[] = {
+    0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
+    0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
+    0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
+    0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
+    0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
+    0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
+    0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
+    0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
+    0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
+    0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
+    0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
+    0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
+};
+
+/* ISO/IEC 8859-3:1999 (Latin-3, "South European", "Maltese & Esperanto") */
+static wchar_t iso_8859_3[] = {
+    0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7,
+    0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B,
+    0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
+    0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C,
+    0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
+    0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
+    0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
+};
+
+/* ISO/IEC 8859-4:1998 (Latin-4, "North European") */
+static wchar_t iso_8859_4[] = {
+    0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
+    0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
+    0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
+    0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
+    0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
+    0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
+    0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+    0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
+    0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
+    0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
+    0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+    0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
+};
+
+/* ISO 8859-5:1999 (Latin/Cyrillic) */
+static wchar_t iso_8859_5[] = {
+    0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
+    0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+    0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+    0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+    0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+    0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+    0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+    0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+    0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+    0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
+};
+
+/* ISO 8859-6:1999 (Latin/Arabic) */
+static wchar_t iso_8859_6[] = {
+    0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F,
+    0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
+    0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+    0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637,
+    0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+    0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647,
+    0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F,
+    0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
+};
+
+/* ISO 8859-7:1987 (Latin/Greek) */
+static wchar_t iso_8859_7[] = {
+    0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7,
+    0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
+    0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+    0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+    0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+    0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+    0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+    0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+    0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+    0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD
+};
+
+/* ISO/IEC 8859-8:1999 (Latin/Hebrew) */
+static wchar_t iso_8859_8[] = {
+    0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+    0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017,
+    0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+    0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+    0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+    0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD
+};
+
+/* ISO/IEC 8859-9:1999 (Latin-5, "Turkish") */
+static wchar_t iso_8859_9[] = {
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+    0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+    0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+    0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+    0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+    0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
+};
+
+/* ISO 8859-10:1993? (Latin-6, "Nordic" [Sami, Inuit, Icelandic]) */
+/* Translation table from RDB. unicode.org (ISO/IEC 8859-10:1998) has
+ * U+2015 (HORIZONTAL BAR) at codepoint 0xBD instead
+ * (U+2014 is EM DASH). -- jtn */
 static wchar_t iso_8859_10[] = {
     0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
     0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
@@ -48,6 +200,9 @@ static wchar_t iso_8859_10[] = {
     0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
 };
 
+/* "ISO 8859-11:1997" ("Thai", "TIS620") */
+/* From RDB -- ISO and unicode.org disclaim all knowledge of this one.
+ * Maybe still in draft. --jtn */
 static wchar_t iso_8859_11[] = {
     0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
     0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
@@ -63,6 +218,7 @@ static wchar_t iso_8859_11[] = {
     0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
 };
 
+/* ISO/IEC 8859-13:1998 (Latin-7, "Baltic Rim") */
 static wchar_t iso_8859_13[] = {
     0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
     0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
@@ -78,6 +234,7 @@ static wchar_t iso_8859_13[] = {
     0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
 };
 
+/* ISO/IEC 8859-14:1998 (Latin-8, "Celtic", "Gaelic/Welsh") */
 static wchar_t iso_8859_14[] = {
     0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7,
     0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178,
@@ -93,21 +250,23 @@ static wchar_t iso_8859_14[] = {
     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF
 };
 
+/* ISO/IEC 8859-15:1999 (Latin-9 aka -0, "euro") */
 static wchar_t iso_8859_15[] = {
-    0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7,
-    0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
-    0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7,
-    0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf,
-    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
-    0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
-    0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
-    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
-    0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
-    0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
-    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
-    0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+    0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7,
+    0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+    0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7,
+    0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF,
+    0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+    0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+    0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
 };
 
+/* ISO/IEC 8859-16:2001 (Latin-10, "Balkan") */
 static wchar_t iso_8859_16[] = {
     0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7,
     0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
@@ -215,21 +374,21 @@ struct cp_list_item {
 };
 
 static struct cp_list_item cp_list[] = {
-    {"ISO-8859-1:1987", 28591},
-    {"ISO-8859-2:1987", 28592},
-    {"ISO-8859-3:1988", 28593},
-    {"ISO-8859-4:1988", 28594},
-    {"ISO-8859-5:1988", 28595},
-    {"ISO-8859-6:1987", 28596},
-    {"ISO-8859-7:1987", 28597},
-    {"ISO-8859-8:1988", 28598},
-    {"ISO-8859-9:1989", 28599},
-    {"ISO-8859-10:1993", 0, 96, iso_8859_10},
-    {"ISO-8859-11:1997", 0, 96, iso_8859_11},
-    {"ISO-8859-13:1998", 0, 96, iso_8859_13},
-    {"ISO-8859-14:1998", 0, 96, iso_8859_14},
-    {"ISO-8859-15:1998", 0, 96, iso_8859_15},
-    {"ISO-8859-16:2001", 0, 96, iso_8859_16},
+    {"ISO-8859-1:1998 (Latin-1, West Europe)", 0, 96, iso_8859_1},
+    {"ISO-8859-2:1999 (Latin-2, East Europe)", 0, 96, iso_8859_2},
+    {"ISO-8859-3:1999 (Latin-3, South Europe)", 0, 96, iso_8859_3},
+    {"ISO-8859-4:1998 (Latin-4, North Europe)", 0, 96, iso_8859_4},
+    {"ISO-8859-5:1999 (Latin/Cyrillic)", 0, 96, iso_8859_5},
+    {"ISO-8859-6:1999 (Latin/Arabic)", 0, 96, iso_8859_6},
+    {"ISO-8859-7:1987 (Latin/Greek)", 0, 96, iso_8859_7},
+    {"ISO-8859-8:1999 (Latin/Hebrew)", 0, 96, iso_8859_8},
+    {"ISO-8859-9:1999 (Latin-5, Turkish)", 0, 96, iso_8859_9},
+    {"ISO-8859-10:1993 (Latin-6, Nordic)", 0, 96, iso_8859_10},
+    {"ISO-8859-11:1997 (Latin/Thai)", 0, 96, iso_8859_11},
+    {"ISO-8859-13:1998 (Latin-7, Baltic)", 0, 96, iso_8859_13},
+    {"ISO-8859-14:1998 (Latin-8, Celtic)", 0, 96, iso_8859_14},
+    {"ISO-8859-15:1999 (Latin-9, \"euro\")", 0, 96, iso_8859_15},
+    {"ISO-8859-16:2001 (Latin-10, Balkan)", 0, 96, iso_8859_16},
 
     {"UTF-8", CP_UTF8},
 
@@ -249,8 +408,6 @@ static struct cp_list_item cp_list[] = {
     {"Win1257 (Baltic)", 1257},
     {"Win1258 (Vietnamese)", 1258},
 
-    {"Win1258 (Vietnamese)", 1258},
-
     {"CP437", 437},
     {"CP819", 28591},
     {"CP878", 20866},
@@ -267,7 +424,7 @@ void init_ucs_tables(void)
     int i, j;
     int used_dtf = 0;
     char tbuf[256];
-    int old_codepage = line_codepage;
+
     for (i = 0; i < 256; i++)
        tbuf[i] = i;
 
@@ -393,6 +550,13 @@ void init_ucs_tables(void)
        link_font(unitab_xterm, unitab_oemcp, ATTR_OEMCP);
     }
 
+    if (dbcs_screenfont && font_codepage != line_codepage) {
+       /* F***ing Microsoft fonts, Japanese and Korean codepage fonts
+        * have a currency symbol at 0x5C but their unicode value is 
+        * still given as U+005C not the correct U+00A5. */
+       unitab_line['\\'] = ATTR_OEMCP + '\\';
+    }
+
     /* Last chance, if !unicode then try poorman links. */
     if (cfg.vtmode != VT_UNICODE) {
        static char poorman_scoacs[] = 
@@ -420,28 +584,28 @@ void init_ucs_tables(void)
 
 static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
 {
-    int i, j, k;
-    for (k = 0; k < 256; k++) {
-       i = ((k + 32) & 0xFF);
-       if (DIRECT_FONT(line_tbl[i]))
+    int font_index, line_index, i;
+    for (line_index = 0; line_index < 256; line_index++) {
+       if (DIRECT_FONT(line_tbl[line_index]))
            continue;
-       for (j = 0; j < 256; j++) {
-           if (line_tbl[i] == font_tbl[j]) {
-               line_tbl[i] = (WCHAR) (attr + j);
+       for(i = 0; i < 256; i++) {
+           font_index = ((32 + i) & 0xFF);
+           if (line_tbl[line_index] == font_tbl[font_index]) {
+               line_tbl[line_index] = (WCHAR) (attr + font_index);
                break;
            }
        }
     }
 }
 
-void lpage_send(int codepage, char *buf, int len)
+void lpage_send(void *ldisc, int codepage, char *buf, int len, int interactive)
 {
     static wchar_t *widebuffer = 0;
     static int widesize = 0;
     int wclen;
 
     if (codepage < 0) {
-       ldisc_send(buf, len);
+       ldisc_send(ldisc, buf, len, interactive);
        return;
     }
 
@@ -451,16 +615,15 @@ void lpage_send(int codepage, char *buf, int len)
        widesize = len * 2;
     }
 
-    wclen =
-       MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize);
-    luni_send(widebuffer, wclen);
+    wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
+    luni_send(ldisc, widebuffer, wclen, interactive);
 }
 
-void luni_send(wchar_t * widebuf, int len)
+void luni_send(void *ldisc, wchar_t * widebuf, int len, int interactive)
 {
     static char *linebuffer = 0;
     static int linesize = 0;
-    int ratio = (in_utf)?3:1;
+    int ratio = (in_utf(term))?3:1;
     int i;
     char *p;
 
@@ -470,10 +633,13 @@ void luni_send(wchar_t * widebuf, int len)
        linesize = len * ratio * 2;
     }
 
-    if (in_utf) {
+    if (in_utf(term)) {
        /* UTF is a simple algorithm */
        for (p = linebuffer, i = 0; i < len; i++) {
            wchar_t ch = widebuf[i];
+           /* Windows wchar_t is UTF-16 */
+           if ((ch&0xF800) == 0xD800) ch = '.';
+
            if (ch < 0x80) {
                *p++ = (char) (ch);
            } else if (ch < 0x800) {
@@ -487,8 +653,8 @@ void luni_send(wchar_t * widebuf, int len)
        }
     } else if (!uni_tbl) {
        int rv;
-       rv = WideCharToMultiByte(line_codepage, 0, widebuf, len,
-                                linebuffer, linesize, NULL, NULL);
+       rv = wc_to_mb(line_codepage, 0, widebuf, len,
+                     linebuffer, linesize, NULL, NULL);
        if (rv >= 0)
            p = linebuffer + rv;
        else
@@ -511,7 +677,30 @@ void luni_send(wchar_t * widebuf, int len)
        }
     }
     if (p > linebuffer)
-       ldisc_send(linebuffer, p - linebuffer);
+       ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
+}
+
+wchar_t xlat_uskbd2cyrllic(int ch)
+{
+    static wchar_t cyrtab[] = {
+            0,      1,       2,      3,      4,      5,      6,      7,
+            8,      9,      10,     11,     12,     13,     14,     15,
+            16,     17,     18,     19,     20,     21,     22,     23,
+            24,     25,     26,     27,     28,     29,     30,     31,
+            32,     33, 0x042d,     35,     36,     37,     38, 0x044d,
+            40,     41,     42, 0x0406, 0x0431, 0x0454, 0x044e, 0x002e,
+            48,     49,     50,     51,     52,     53,     54,     55,
+            56,     57, 0x0416, 0x0436, 0x0411, 0x0456, 0x042e, 0x002c,
+            64, 0x0424, 0x0418, 0x0421, 0x0412, 0x0423, 0x0410, 0x041f,
+        0x0420, 0x0428, 0x041e, 0x041b, 0x0414, 0x042c, 0x0422, 0x0429,
+        0x0417, 0x0419, 0x041a, 0x042b, 0x0415, 0x0413, 0x041c, 0x0426,
+        0x0427, 0x041d, 0x042f, 0x0445, 0x0457, 0x044a,     94, 0x0404,
+            96, 0x0444, 0x0438, 0x0441, 0x0432, 0x0443, 0x0430, 0x043f,
+        0x0440, 0x0448, 0x043e, 0x043b, 0x0434, 0x044c, 0x0442, 0x0449,
+        0x0437, 0x0439, 0x043a, 0x044b, 0x0435, 0x0433, 0x043c, 0x0446,
+        0x0447, 0x043d, 0x044f, 0x0425, 0x0407, 0x042a,    126,    127
+       };
+    return cyrtab[ch&0x7F];
 }
 
 int check_compose(int first, int second)
@@ -534,7 +723,7 @@ int check_compose(int first, int second)
        0x43, 0x2f, 0x00a2}, {
        0x43, 0x7c, 0x00a2}, {
        0x4c, 0x2d, 0x00a3}, {
-       0x4c, 0x3d, 0x00a3}, {
+       0x4c, 0x3d, 0x20a4}, {
        0x58, 0x4f, 0x00a4}, {
        0x58, 0x30, 0x00a4}, {
        0x59, 0x2d, 0x00a5}, {
@@ -934,6 +1123,8 @@ int decode_codepage(char *cp_name)
                    codepage = cpi->codepage;
                    if (codepage == CP_UTF8)
                        goto break_break;
+                   if (codepage == -1)
+                       return codepage;
                    if (codepage == 0) {
                        codepage = 65536 + (cpi - cp_list);
                        goto break_break;
@@ -1027,7 +1218,7 @@ char *cp_enumerate(int index)
     return cp_list[index].name;
 }
 
-static void get_unitab(int codepage, wchar_t * unitab, int ftype)
+void get_unitab(int codepage, wchar_t * unitab, int ftype)
 {
     char tbuf[4];
     int i, max = 256, flg = MB_ERR_INVALID_CHARS;
@@ -1037,9 +1228,13 @@ static void get_unitab(int codepage, wchar_t * unitab, int ftype)
     if (ftype == 2)
        max = 128;
 
-    if (codepage == CP_UTF8)
-       codepage = 28591;
-    else if (codepage == CP_ACP)
+    if (codepage == CP_UTF8) {
+       for (i = 0; i < max; i++)
+           unitab[i] = i;
+       return;
+    }
+
+    if (codepage == CP_ACP)
        codepage = GetACP();
     else if (codepage == CP_OEMCP)
        codepage = GetOEMCP();
@@ -1048,7 +1243,7 @@ static void get_unitab(int codepage, wchar_t * unitab, int ftype)
        for (i = 0; i < max; i++) {
            tbuf[0] = i;
 
-           if (MultiByteToWideChar(codepage, flg, tbuf, 1, unitab + i, 1)
+           if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
                != 1)
                unitab[i] = 0xFFFD;
        }