Robert de Bath's patch: be a little more careful of main and
[u/mdw/putty] / terminal.c
index ab6ffd0..b0cc354 100644 (file)
@@ -1,4 +1,3 @@
-++ terminal.c.new      Mon Nov 22 15:02:03 1999
 #include <windows.h>
 
 #include <stdio.h>
@@ -47,6 +46,8 @@ static int alt_which;
 static int esc_args[ARGS_MAX];
 static int esc_nargs;
 static int esc_query;
+#define ANSI(x,y)      ((x)+((y)<<8))
+#define ANSI_QUE(x)    ANSI(x,TRUE)
 
 #define OSC_STR_MAX 2048
 static int osc_strlen;
@@ -151,7 +152,7 @@ void term_update(void) {
     Context ctx;
     ctx = get_ctx();
     if (ctx) {
-        if ( (seen_key_event && (unscroll_event & US_KEY)) &&
+        if ( (seen_key_event && (unscroll_event & US_KEY)) ||
             (seen_disp_event && (unscroll_event & US_DISP)) ) {
            disptop = scrtop;
            seen_disp_event = seen_key_event = 0;
@@ -203,9 +204,14 @@ void term_size(int newrows, int newcols, int newsavelines) {
     unsigned long *newtext, *newdisp, *newwant, *newalt;
     int i, j, crows, ccols;
 
+    int save_alt_which = alt_which;
+
     if (newrows == rows && newcols == cols && newsavelines == savelines)
        return;                        /* nothing to do */
 
+    deselect();
+    swap_screen(0);
+
     alt_t = marg_t = 0;
     alt_b = marg_b = newrows - 1;
 
@@ -279,7 +285,8 @@ void term_size(int newrows, int newcols, int newsavelines) {
     savelines = newsavelines;
     fix_cpos;
 
-    deselect();
+    swap_screen(save_alt_which);
+
     update_sbar();
     term_update();
 }
@@ -579,13 +586,15 @@ void term_out(void) {
     int c;
 
     while ( (c = inbuf_getc()) != -1) {
-#ifdef LOG
-       {
+        /*
+         * Optionally log the session traffic to a file. Useful for
+         * debugging and possibly also useful for actual logging.
+         */
+       if (logfile) {
            static FILE *fp = NULL;
-           if (!fp) fp = fopen("putty.log", "wb");
+           if (!fp) fp = fopen(logfile, "wb");
            if (fp) fputc (c, fp);
        }
-#endif
        if( termstate < DO_CTRLS && (c&0x60) == 0 ) {
            switch (c) {
              case '\005':             /* terminal type query */
@@ -661,31 +670,30 @@ void term_out(void) {
        }
        else switch (termstate) {
          case TOPLEVEL:
-           if (c >= ' ' && c != 0234) {
-               if (wrapnext) {
-                   cpos[1] = ATTR_WRAPPED;
-                   if (curs_y == marg_b)
-                       scroll (marg_t, marg_b, 1, TRUE);
-                   else if (curs_y < rows-1)
-                       curs_y++;
-                   curs_x = 0;
-                   fix_cpos;
-                   wrapnext = FALSE;
-                   nl_count++;
-               }
-               if (insert)
-                   insch (1);
-               check_selection (cpos, cpos+1);
-               *cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr |
-                   (c <= 0x7F ? cset_attr[cset] : ATTR_ASCII);
-               curs_x++;
-               if (curs_x == cols) {
-                   cpos--;
-                   curs_x--;
-                   wrapnext = wrap;
-               }
-               seen_disp_event = 1;
+         /* Only graphic characters get this far, ctrls are stripped above */
+           if (wrapnext) {
+               cpos[1] = ATTR_WRAPPED;
+               if (curs_y == marg_b)
+                   scroll (marg_t, marg_b, 1, TRUE);
+               else if (curs_y < rows-1)
+                   curs_y++;
+               curs_x = 0;
+               fix_cpos;
+               wrapnext = FALSE;
+               nl_count++;
+           }
+           if (insert)
+               insch (1);
+           check_selection (cpos, cpos+1);
+           *cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr |
+               (c <= 0x7F ? cset_attr[cset] : ATTR_ASCII);
+           curs_x++;
+           if (curs_x == cols) {
+               cpos--;
+               curs_x--;
+               wrapnext = wrap;
            }
+           seen_disp_event = 1;
            break;
 
          case IGNORE_NEXT:
@@ -788,9 +796,8 @@ void term_out(void) {
            break;
          case SEEN_CSI:
            termstate = TOPLEVEL;      /* default */
-           switch (c) {
-             case '0': case '1': case '2': case '3': case '4':
-             case '5': case '6': case '7': case '8': case '9':
+           if( isdigit(c) )
+           {
                if (esc_nargs <= ARGS_MAX) {
                    if (esc_args[esc_nargs-1] == ARG_DEFAULT)
                        esc_args[esc_nargs-1] = 0;
@@ -798,16 +805,21 @@ void term_out(void) {
                        10 * esc_args[esc_nargs-1] + c - '0';
                }
                termstate = SEEN_CSI;
-               break;
-             case ';':
+           }
+           else if( c == ';' )
+           {
                if (++esc_nargs <= ARGS_MAX)
                    esc_args[esc_nargs-1] = ARG_DEFAULT;
                termstate = SEEN_CSI;
-               break;
-             case '?':
-               esc_query = TRUE;
+           }
+           else if( c < '@' )
+           {
+               if( esc_query )     esc_query = -1;
+               else if( c == '?' ) esc_query = TRUE;
+               else                esc_query = c;
                termstate = SEEN_CSI;
-               break;
+           }
+           else switch (ANSI(c,esc_query)) {
              case 'A':                /* move up N lines */
                move (curs_x, curs_y - def(esc_args[0], 1), 1);
                seen_disp_event = TRUE;
@@ -897,9 +909,11 @@ void term_out(void) {
                }
                break;
              case 'h':                /* toggle a mode to high */
+             case ANSI_QUE('h'):
                toggle_mode (esc_args[0], esc_query, TRUE);
                break;
              case 'l':                /* toggle a mode to low */
+             case ANSI_QUE('l'):
                toggle_mode (esc_args[0], esc_query, FALSE);
                break;
              case 'g':                /* clear tabs */
@@ -914,7 +928,7 @@ void term_out(void) {
                }
                break;
              case 'r':                /* set scroll margins */
-               if (!esc_query && esc_nargs <= 2) {
+               if (esc_nargs <= 2) {
                    int top, bot;
                    top = def(esc_args[0], 1) - 1;
                    if (top < 0)
@@ -1032,7 +1046,8 @@ void term_out(void) {
                cset_attr[termstate == SET_GL ? 0 : 1] = ATTR_ASCII;
                break;
            }
-           termstate = TOPLEVEL;
+           if( c != '%' )
+               termstate = TOPLEVEL;
            break;
          case SEEN_OSC:
            osc_w = FALSE;
@@ -1070,7 +1085,19 @@ void term_out(void) {
            }
            break;
          case OSC_STRING:
-           if (c == 0234 || c == '\007') {
+           /*
+            * This OSC stuff is EVIL. It takes just one character to get into
+            * sysline mode and it's not initially obvious how to get out.
+            * So I've added CR and LF as string aborts.
+            * This shouldn't effect compatibility as I believe embedded 
+            * control characters are supposed to be interpreted (maybe?) 
+            * and they don't display anything useful anyway.
+            *
+            * -- RDB
+            */
+           if (c == '\n' || c == '\r') {
+               termstate = TOPLEVEL;
+           } else if (c == 0234 || c == '\007' ) {
                /*
                 * These characters terminate the string; ST and BEL
                 * terminate the sequence and trigger instant