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