Fix pasting of newlines in local line editing mode. Possibly not a
[u/mdw/putty] / unicode.c
index 954015f..37df590 100644 (file)
--- a/unicode.c
+++ b/unicode.c
@@ -8,15 +8,11 @@
 #include "putty.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;
 
@@ -63,7 +59,7 @@ static wchar_t iso_8859_11[] = {
     0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
 };
 
-static wchar_t iso_8859_12[] = {
+static wchar_t iso_8859_13[] = {
     0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7,
     0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7,
@@ -108,6 +104,21 @@ static wchar_t iso_8859_15[] = {
     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
 };
 
+static wchar_t iso_8859_16[] = {
+    0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7,
+    0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B,
+    0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7,
+    0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C,
+    0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7,
+    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+    0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A,
+    0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF,
+    0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7,
+    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+    0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B,
+    0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
+};
+
 static wchar_t roman8[] = {
     0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF,
     0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4,
@@ -210,10 +221,11 @@ static struct cp_list_item cp_list[] = {
     {"ISO-8859-8:1988", 28598},
     {"ISO-8859-9:1989", 28599},
     {"ISO-8859-10:1993", 0, 96, iso_8859_10},
-    {"ISO-8859-11", 0, 96, iso_8859_11},
-    {"ISO-8859-12", 0, 96, iso_8859_12},
-    {"ISO-8859-14", 0, 96, iso_8859_14},
+    {"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},
 
     {"UTF-8", CP_UTF8},
 
@@ -233,36 +245,14 @@ static struct cp_list_item cp_list[] = {
     {"Win1257 (Baltic)", 1257},
     {"Win1258 (Vietnamese)", 1258},
 
-    /* All below here are aliases - First the windows ones. */
-    {"Central European (Win1250)", 1250},
-    {"Cyrillic (Win1251)", 1251},
-    {"Western (Win1252)", 1252},
-    {"Greek (Win1253)", 1253},
-    {"Turkish (Win1254)", 1254},
-    {"Hebrew (Win1255)", 1255},
-    {"Arabic (Win1256)", 1256},
-    {"Baltic (Win1257)", 1257},
-    {"Vietnamese (Win1258)", 1258},
-
-    {"ROMAN8", 0, 96, roman8},
-    {"R8", 0, 96, roman8},
-
-    /* Note this is Latin ->> */
-    {"LATIN0", 0, 96, iso_8859_15},
-    {"L0", 0, 96, iso_8859_15},
+    {"Win1258 (Vietnamese)", 1258},
 
+    {"CP437", 437},
     {"CP819", 28591},
     {"CP878", 20866},
-    {"L1", 28591},
-    {"L2", 28592},
-    {"L3", 28593},
-    {"L4", 28594},
-    {"L5", 28599},
-    {"LATIN1", 28591},
-    {"LATIN2", 28592},
-    {"LATIN3", 28593},
-    {"LATIN4", 28594},
-    {"LATIN5", 28599},
+
+    {"Use font encoding", -1},
+
     {0, 0}
 };
 
@@ -273,7 +263,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;
 
@@ -399,6 +389,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[] = 
@@ -426,28 +423,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(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(buf, len, interactive);
        return;
     }
 
@@ -459,10 +456,10 @@ void lpage_send(int codepage, char *buf, int len)
 
     wclen =
        MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize);
-    luni_send(widebuffer, wclen);
+    luni_send(widebuffer, wclen, interactive);
 }
 
-void luni_send(wchar_t * widebuf, int len)
+void luni_send(wchar_t * widebuf, int len, int interactive)
 {
     static char *linebuffer = 0;
     static int linesize = 0;
@@ -480,6 +477,9 @@ void luni_send(wchar_t * widebuf, int len)
        /* 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) {
@@ -517,7 +517,30 @@ void luni_send(wchar_t * widebuf, int len)
        }
     }
     if (p > linebuffer)
-       ldisc_send(linebuffer, p - linebuffer);
+       ldisc_send(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)
@@ -540,7 +563,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}, {
@@ -884,6 +907,49 @@ int decode_codepage(char *cp_name)
     int codepage = -1;
     CPINFO cpinfo;
 
+    if (!*cp_name) {
+       /*
+        * Here we select a plausible default code page based on
+        * the locale the user is in. We wish to select an ISO code
+        * page or appropriate local default _rather_ than go with
+        * the Win125* series, because it's more important to have
+        * CSI and friends enabled by default than the ghastly
+        * Windows extra quote characters, and because it's more
+        * likely the user is connecting to a remote server that
+        * does something Unixy or VMSy and hence standards-
+        * compliant than that they're connecting back to a Windows
+        * box using horrible nonstandard charsets.
+        * 
+        * Accordingly, Robert de Bath suggests a method for
+        * picking a default character set that runs as follows:
+        * first call GetACP to get the system's ANSI code page
+        * identifier, and translate as follows:
+        * 
+        * 1250 -> ISO 8859-2
+        * 1251 -> KOI8-U
+        * 1252 -> ISO 8859-1
+        * 1253 -> ISO 8859-7
+        * 1254 -> ISO 8859-9
+        * 1255 -> ISO 8859-8
+        * 1256 -> ISO 8859-6
+        * 1257 -> ISO 8859-4
+        * 
+        * and for anything else, choose direct-to-font.
+        */
+       int cp = GetACP();
+       switch (cp) {
+         case 1250: cp_name = "ISO-8859-2"; break;
+         case 1251: cp_name = "KOI8-U"; break;
+         case 1252: cp_name = "ISO-8859-1"; break;
+         case 1253: cp_name = "ISO-8859-7"; break;
+         case 1254: cp_name = "ISO-8859-9"; break;
+         case 1255: cp_name = "ISO-8859-8"; break;
+         case 1256: cp_name = "ISO-8859-6"; break;
+         case 1257: cp_name = "ISO-8859-4"; break;
+           /* default: leave it blank, which will select -1, direct->font */
+       }
+    }
+
     if (cp_name && *cp_name)
        for (cpi = cp_list; cpi->name; cpi++) {
            s = cp_name;
@@ -947,6 +1013,12 @@ char *cp_name(int codepage)
 {
     struct cp_list_item *cpi, *cpno;
     static char buf[32];
+
+    if (codepage == -1) {
+       sprintf(buf, "Use font encoding");
+       return buf;
+    }
+
     if (codepage > 0 && codepage < 65536)
        sprintf(buf, "CP%03d", codepage);
     else