RDB's patch: thanks to improvements in OEMANSI font mode, it can now
[sgt/putty] / telnet.c
index 399c126..1cd4df4 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -174,6 +174,9 @@ static void c_write (char *buf, int len) {
        if (new_head != inbuf_reap) {
            inbuf[inbuf_head] = *buf++;
            inbuf_head = new_head;
+       } else {
+            term_out();
+            if( inbuf_head == inbuf_reap ) len++; else break;
        }
     }
 }
@@ -213,6 +216,11 @@ static void activate_option (struct Opt *o) {
         */
        deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv);
     }
+    if (o->option == TELOPT_ECHO)
+    {
+       cfg.ldisc_term = FALSE;
+       ldisc = &ldisc_simple;
+    }
 }
 
 static void refused_option (struct Opt *o) {
@@ -221,6 +229,11 @@ static void refused_option (struct Opt *o) {
        send_opt (WILL, TELOPT_OLD_ENVIRON);
        o_oenv.state = REQUESTED;
     }
+    if (o->option == TELOPT_ECHO)
+    {
+       cfg.ldisc_term = TRUE;
+       ldisc = &ldisc_term;
+    }
 }
 
 static void proc_rec_opt (int cmd, int option) {
@@ -411,9 +424,11 @@ static void do_telnet_read (char *buf, int len) {
            else if (c == WONT) telnet_state = SEENWONT;
            else if (c == SB) telnet_state = SEENSB;
            else {
-               /* ignore (and print) everything else */
-               b[0] = c;
-               c_write(b,1);
+               /* ignore everything else; print it if it's IAC */
+               if (c == IAC) {
+                   b[0] = c;
+                   c_write(b,1);
+               }
                telnet_state = TOPLEVEL;
            }
            break;
@@ -560,6 +575,15 @@ static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
     /*
      * Initialise option states.
      */
+    if( cfg.ldisc_term )
+    {
+       struct Opt **o;
+
+       for (o = opts; *o; o++)
+           if ((*o)->state == REQUESTED)
+               (*o)->state = INACTIVE;
+    }
+    else
     {
        struct Opt **o;
 
@@ -651,19 +675,41 @@ static void telnet_send (char *buf, int len) {
     char *p;
     static unsigned char iac[2] = { IAC, IAC };
     static unsigned char cr[2] = { CR, NUL };
+    static unsigned char nl[2] = { CR, LF };
 
     if (s == INVALID_SOCKET)
        return;
 
     p = buf;
-    while (p < buf+len) {
+    if (cfg.ldisc_term) {
+       while (p < buf+len) {
+           char *q = p;
+           unsigned char * cstr = 0;
+           while (p < buf+len) {
+               if ((unsigned char)*p == IAC) {
+                   cstr = iac;
+                   break;
+               }
+               if (*p == '\r') {
+                   if( p+1 >= buf+len || ( p[1] != '\n' && p[1] != '\0'))
+                   {
+                       cstr = cr;
+                       break;
+                   }
+               }
+               p++;
+           }
+           if (p!=q) s_write (q, p-q);
+           if (cstr) s_write (cstr,2), p++;
+       }
+    } else while (p < buf+len) {
        char *q = p;
 
        while (iswritable((unsigned char)*p) && p < buf+len) p++;
        s_write (q, p-q);
 
        while (p < buf+len && !iswritable((unsigned char)*p)) {
-           s_write ((unsigned char)*p == IAC ? iac : cr, 2);
+           s_write ((unsigned char)*p == IAC ? iac : nl, 2);
            p++;
        }
     }
@@ -714,8 +760,20 @@ static void telnet_special (Telnet_Special code) {
       case TS_EOF: b[1] = xEOF; s_write (b, 2); break;
       case TS_SYNCH:
        outbuf_head = outbuf_reap = 0;
-       b[0] = DM;
-       send (s, b, 1, MSG_OOB);
+       b[1] = DM;
+       send (s, b, 2, MSG_OOB);
+       break;
+      case TS_RECHO:
+       if (o_echo.state == INACTIVE || o_echo.state == REALLY_INACTIVE) {
+           o_echo.state = REQUESTED;
+           send_opt (o_echo.send, o_echo.option);
+       }
+       break;
+      case TS_LECHO:
+       if (o_echo.state == ACTIVE) {
+           o_echo.state = REQUESTED;
+           send_opt (o_echo.nsend, o_echo.option);
+       }
        break;
     }
 }