]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - ldiscucs.c
Arrgh! _Another_ missed commit. I really must do something about
[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, 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 = smalloc(widesize * sizeof(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, 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 = smalloc(linesize * sizeof(wchar_t));
48
49     if (in_utf(ldisc->term)) {
50         /* UTF is a simple algorithm */
51         for (p = linebuffer, i = 0; i < len; i++) {
52             wchar_t ch = widebuf[i];
53             /* We only deal with 16-bit wide chars */
54             if ((ch&0xF800) == 0xD800) ch = '.';
55
56             if (ch < 0x80) {
57                 *p++ = (char) (ch);
58             } else if (ch < 0x800) {
59                 *p++ = (0xC0 | (ch >> 6));
60                 *p++ = (0x80 | (ch & 0x3F));
61             } else {
62                 *p++ = (0xE0 | (ch >> 12));
63                 *p++ = (0x80 | ((ch >> 6) & 0x3F));
64                 *p++ = (0x80 | (ch & 0x3F));
65             }
66         }
67     } else {
68         int rv;
69         rv = wc_to_mb(line_codepage, 0, widebuf, len,
70                       linebuffer, linesize, NULL, NULL);
71         if (rv >= 0)
72             p = linebuffer + rv;
73         else
74             p = linebuffer;
75     }
76     if (p > linebuffer)
77         ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
78
79     sfree(linebuffer);
80 }