Introduce a sane interface function, from_backend(), for backends to
[u/mdw/putty] / ldisc.c
diff --git a/ldisc.c b/ldisc.c
index ca5625d..10576d2 100644 (file)
--- a/ldisc.c
+++ b/ldisc.c
@@ -1,4 +1,11 @@
 #include <windows.h>
+#ifndef AUTO_WINSOCK
+#ifdef WINSOCK_TWO
+#include <winsock2.h>
+#else
+#include <winsock.h>
+#endif
+#endif
 #include <stdio.h>
 #include <ctype.h>
 
  */
 
 static void c_write (char *buf, int len) {
-    while (len--) {
-       int new_head = (inbuf_head + 1) & INBUF_MASK;
-       int c = (unsigned char) *buf;
-       if (new_head != inbuf_reap) {
-           inbuf[inbuf_head] = *buf++;
-           inbuf_head = new_head;
-       }
-    }
+    from_backend(0, buf, len);
+}
+
+static void c_write1 (char c) {
+    c_write(&c, 1);
 }
 
 static char *term_buf = NULL;
@@ -35,8 +39,7 @@ static int plen(unsigned char c) {
 static void pwrite(unsigned char c) {
     if ((c >= 32 && c <= 126) ||
         (c >= 160)) {
-        char cc = (char)c;
-        c_write(&cc, 1);
+        c_write1(c);
     } else if (c < 128) {
         char cc[2];
         cc[1] = (c == 127 ? '?' : c + 0x40);
@@ -54,6 +57,8 @@ static void bsb(int n) {
        c_write("\010 \010", 3);
 }
 
+#define CTRL(x) (x^'@')
+
 static void term_send(char *buf, int len) {
     while (len--) {
        char c;
@@ -64,19 +69,22 @@ static void term_send(char *buf, int len) {
             * ^w: delete, and output BSBs, to return to last space/nonspace
             * boundary
             * ^u: delete, and output BSBs, to return to BOL
+            * ^c: Do a ^u then send a telnet IP
+            * ^z: Do a ^u then send a telnet SUSP
+            * ^\: Do a ^u then send a telnet ABORT
             * ^r: echo "^R\n" and redraw line
             * ^v: quote next char
             * ^d: if at BOL, end of file and close connection, else send line
             * and reset to BOL
-            * ^m/^j: send line-plus-\r\n and reset to BOL
+            * ^m: send line-plus-\r\n and reset to BOL
             */
-         case 8: case 127:            /* backspace/delete */
+         case CTRL('H'): case CTRL('?'):      /* backspace/delete */
            if (term_buflen > 0) {
                bsb(plen(term_buf[term_buflen-1]));
                term_buflen--;
            }
            break;
-         case 23:                     /* ^W delete word */
+         case CTRL('W'):                      /* delete word */
            while (term_buflen > 0) {
                bsb(plen(term_buf[term_buflen-1]));
                term_buflen--;
@@ -86,13 +94,20 @@ static void term_send(char *buf, int len) {
                    break;
            }
            break;
-         case 21:                     /* ^U delete line */
+         case CTRL('U'):              /* delete line */
+         case CTRL('C'):              /* Send IP */
+         case CTRL('\\'):             /* Quit */
+         case CTRL('Z'):              /* Suspend */
            while (term_buflen > 0) {
                bsb(plen(term_buf[term_buflen-1]));
                term_buflen--;
            }
+           back->special (TS_EL);
+           if( c == CTRL('C') )  back->special (TS_IP);
+           if( c == CTRL('Z') )  back->special (TS_SUSP);
+           if( c == CTRL('\\') ) back->special (TS_ABORT);
             break;
-         case 18:                     /* ^R redraw line */
+         case CTRL('R'):              /* redraw line */
            c_write("^R\r\n", 4);
            {
                int i;
@@ -100,20 +115,24 @@ static void term_send(char *buf, int len) {
                    pwrite(term_buf[i]);
            }
            break;
-         case 22:                     /* ^V quote next char */
+         case CTRL('V'):              /* quote next char */
            term_quotenext = TRUE;
            break;
-         case 4:                      /* ^D logout or send */
+         case CTRL('D'):              /* logout or send */
            if (term_buflen == 0) {
-               /* FIXME: eof */;
+               back->special (TS_EOF);
            } else {
                back->send(term_buf, term_buflen);
                term_buflen = 0;
            }
            break;
-         case 13: case 10:            /* ^M/^J send with newline */
-           back->send(term_buf, term_buflen);
-           back->send("\r\n", 2);
+         case CTRL('M'):              /* send with newline */
+           if (term_buflen > 0)
+                back->send(term_buf, term_buflen);
+           if (cfg.protocol == PROT_RAW)
+               back->send("\r\n", 2);
+           else
+               back->send("\r", 1);
            c_write("\r\n", 2);
            term_buflen = 0;
            break;
@@ -131,7 +150,16 @@ static void term_send(char *buf, int len) {
 }
 
 static void simple_send(char *buf, int len) {
-    back->send(buf, len);
+    if( term_buflen != 0 )
+    {
+       back->send(term_buf, term_buflen);
+       while (term_buflen > 0) {
+           bsb(plen(term_buf[term_buflen-1]));
+           term_buflen--;
+       }
+    }
+    if (len > 0)
+        back->send(buf, len);
 }
 
 Ldisc ldisc_term = { term_send };