]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - ldisc.c
Miscellaneous fixes to try to make other compilers happier
[PuTTY.git] / ldisc.c
1 #include <windows.h>
2 #ifndef AUTO_WINSOCK
3 #ifdef WINSOCK_TWO
4 #include <winsock2.h>
5 #else
6 #include <winsock.h>
7 #endif
8 #endif
9 #include <stdio.h>
10 #include <ctype.h>
11
12 #include "putty.h"
13
14 /*
15  * ldisc.c: PuTTY line disciplines
16  */
17
18 static void c_write (char *buf, int len) {
19     while (len--) 
20         c_write1(*buf++);
21 }
22
23 static char *term_buf = NULL;
24 static int term_buflen = 0, term_bufsiz = 0, term_quotenext = 0;
25
26 static int plen(unsigned char c) {
27     if ((c >= 32 && c <= 126) ||
28         (c >= 160))
29         return 1;
30     else if (c < 128)
31         return 2;                      /* ^x for some x */
32     else
33         return 4;                      /* <XY> for hex XY */
34 }
35
36 static void pwrite(unsigned char c) {
37     if ((c >= 32 && c <= 126) ||
38         (c >= 160)) {
39         c_write1(c);
40     } else if (c < 128) {
41         char cc[2];
42         cc[1] = (c == 127 ? '?' : c + 0x40);
43         cc[0] = '^';
44         c_write(cc, 2);
45     } else {
46         char cc[5];
47         sprintf(cc, "<%02X>", c);
48         c_write(cc, 4);
49     }
50 }
51
52 static void bsb(int n) {
53     while (n--)
54         c_write("\010 \010", 3);
55 }
56
57 #define CTRL(x) (x^'@')
58
59 static void term_send(char *buf, int len) {
60     while (len--) {
61         char c;
62         c = *buf++;
63         switch (term_quotenext ? ' ' : c) {
64             /*
65              * ^h/^?: delete one char and output one BSB
66              * ^w: delete, and output BSBs, to return to last space/nonspace
67              * boundary
68              * ^u: delete, and output BSBs, to return to BOL
69              * ^c: Do a ^u then send a telnet IP
70              * ^z: Do a ^u then send a telnet SUSP
71              * ^\: Do a ^u then send a telnet ABORT
72              * ^r: echo "^R\n" and redraw line
73              * ^v: quote next char
74              * ^d: if at BOL, end of file and close connection, else send line
75              * and reset to BOL
76              * ^m: send line-plus-\r\n and reset to BOL
77              */
78           case CTRL('H'): case CTRL('?'):      /* backspace/delete */
79             if (term_buflen > 0) {
80                 bsb(plen(term_buf[term_buflen-1]));
81                 term_buflen--;
82             }
83             break;
84           case CTRL('W'):                      /* delete word */
85             while (term_buflen > 0) {
86                 bsb(plen(term_buf[term_buflen-1]));
87                 term_buflen--;
88                 if (term_buflen > 0 &&
89                     isspace(term_buf[term_buflen-1]) &&
90                     !isspace(term_buf[term_buflen]))
91                     break;
92             }
93             break;
94           case CTRL('U'):              /* delete line */
95           case CTRL('C'):              /* Send IP */
96           case CTRL('\\'):             /* Quit */
97           case CTRL('Z'):              /* Suspend */
98             while (term_buflen > 0) {
99                 bsb(plen(term_buf[term_buflen-1]));
100                 term_buflen--;
101             }
102             back->special (TS_EL);
103             if( c == CTRL('C') )  back->special (TS_IP);
104             if( c == CTRL('Z') )  back->special (TS_SUSP);
105             if( c == CTRL('\\') ) back->special (TS_ABORT);
106             break;
107           case CTRL('R'):              /* redraw line */
108             c_write("^R\r\n", 4);
109             {
110                 int i;
111                 for (i = 0; i < term_buflen; i++)
112                     pwrite(term_buf[i]);
113             }
114             break;
115           case CTRL('V'):              /* quote next char */
116             term_quotenext = TRUE;
117             break;
118           case CTRL('D'):              /* logout or send */
119             if (term_buflen == 0) {
120                 back->special (TS_EOF);
121             } else {
122                 back->send(term_buf, term_buflen);
123                 term_buflen = 0;
124             }
125             break;
126           case CTRL('M'):              /* send with newline */
127             if (term_buflen > 0)
128                 back->send(term_buf, term_buflen);
129             if (cfg.protocol == PROT_RAW)
130                 back->send("\r\n", 2);
131             else
132                 back->send("\r", 1);
133             c_write("\r\n", 2);
134             term_buflen = 0;
135             break;
136           default:                     /* get to this label from ^V handler */
137             if (term_buflen >= term_bufsiz) {
138                 term_bufsiz = term_buflen + 256;
139                 term_buf = saferealloc(term_buf, term_bufsiz);
140             }
141             term_buf[term_buflen++] = c;
142             pwrite(c);
143             term_quotenext = FALSE;
144             break;
145         }
146     }
147 }
148
149 static void simple_send(char *buf, int len) {
150     if( term_buflen != 0 )
151     {
152         back->send(term_buf, term_buflen);
153         while (term_buflen > 0) {
154             bsb(plen(term_buf[term_buflen-1]));
155             term_buflen--;
156         }
157     }
158     if (len > 0)
159         back->send(buf, len);
160 }
161
162 Ldisc ldisc_term = { term_send };
163 Ldisc ldisc_simple = { simple_send };