OSDN Git Service

eda383b6fa98d928bd166054d1de10c120dac634
[ffftp/ffftp.git] / putty / LDISCUCS.C
1 /*\r
2  * ldisc.c: PuTTY line discipline. Sits between the input coming\r
3  * from keypresses in the window, and the output channel leading to\r
4  * the back end. Implements echo and/or local line editing,\r
5  * depending on what's currently configured.\r
6  */\r
7 \r
8 #include <stdio.h>\r
9 #include <ctype.h>\r
10 \r
11 #include "putty.h"\r
12 #include "terminal.h"\r
13 #include "ldisc.h"\r
14 \r
15 void lpage_send(void *handle,\r
16                 int codepage, char *buf, int len, int interactive)\r
17 {\r
18     Ldisc ldisc = (Ldisc)handle;\r
19     wchar_t *widebuffer = 0;\r
20     int widesize = 0;\r
21     int wclen;\r
22 \r
23     if (codepage < 0) {\r
24         ldisc_send(ldisc, buf, len, interactive);\r
25         return;\r
26     }\r
27 \r
28     widesize = len * 2;\r
29     widebuffer = snewn(widesize, wchar_t);\r
30 \r
31     wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);\r
32     luni_send(ldisc, widebuffer, wclen, interactive);\r
33 \r
34     sfree(widebuffer);\r
35 }\r
36 \r
37 void luni_send(void *handle, wchar_t * widebuf, int len, int interactive)\r
38 {\r
39     Ldisc ldisc = (Ldisc)handle;\r
40     int ratio = (in_utf(ldisc->term))?3:1;\r
41     char *linebuffer;\r
42     int linesize;\r
43     int i;\r
44     char *p;\r
45 \r
46     linesize = len * ratio * 2;\r
47     linebuffer = snewn(linesize, char);\r
48 \r
49     if (in_utf(ldisc->term)) {\r
50         /* UTF is a simple algorithm */\r
51         for (p = linebuffer, i = 0; i < len; i++) {\r
52             unsigned long ch = widebuf[i];\r
53 \r
54             if ((ch & 0xF800) == 0xD800) {\r
55 #ifdef PLATFORM_IS_UTF16\r
56                 if (i+1 < len) {\r
57                     unsigned long ch2 = widebuf[i+1];\r
58                     if ((ch & 0xFC00) == 0xD800 &&\r
59                         (ch2 & 0xFC00) == 0xDC00) {\r
60                         ch = 0x10000 + ((ch & 0x3FF) << 10) + (ch2 & 0x3FF);\r
61                         i++;\r
62                     }\r
63                 } else\r
64 #endif\r
65                 {\r
66                     /* Unrecognised UTF-16 sequence */\r
67                     ch = '.';\r
68                 }\r
69             }\r
70 \r
71             if (ch < 0x80) {\r
72                 *p++ = (char) (ch);\r
73             } else if (ch < 0x800) {\r
74                 *p++ = (char) (0xC0 | (ch >> 6));\r
75                 *p++ = (char) (0x80 | (ch & 0x3F));\r
76             } else if (ch < 0x10000) {\r
77                 *p++ = (char) (0xE0 | (ch >> 12));\r
78                 *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));\r
79                 *p++ = (char) (0x80 | (ch & 0x3F));\r
80             } else {\r
81                 *p++ = (char) (0xF0 | (ch >> 18));\r
82                 *p++ = (char) (0x80 | ((ch >> 12) & 0x3F));\r
83                 *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));\r
84                 *p++ = (char) (0x80 | (ch & 0x3F));\r
85             }\r
86         }\r
87     } else {\r
88         int rv;\r
89         rv = wc_to_mb(ldisc->term->ucsdata->line_codepage, 0, widebuf, len,\r
90                       linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata);\r
91         if (rv >= 0)\r
92             p = linebuffer + rv;\r
93         else\r
94             p = linebuffer;\r
95     }\r
96     if (p > linebuffer)\r
97         ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);\r
98 \r
99     sfree(linebuffer);\r
100 }\r