Small terminal fix from RDB: CSI 1 K should erase the cursor
[u/mdw/putty] / terminal.c
index 9abb848..b01ef80 100644 (file)
@@ -82,7 +82,7 @@ typedef struct {
 #define poslt(p1,p2) ( (p1).y < (p2).y || ( (p1).y == (p2).y && (p1).x < (p2).x ) )
 #define posle(p1,p2) ( (p1).y < (p2).y || ( (p1).y == (p2).y && (p1).x <= (p2).x ) )
 #define poseq(p1,p2) ( (p1).y == (p2).y && (p1).x == (p2).x )
-#define posdiff(p1,p2) ( ((p2).y - (p1).y) * (cols+1) + (p2).x - (p1).x )
+#define posdiff(p1,p2) ( ((p1).y - (p2).y) * (cols+1) + (p1).x - (p2).x )
 #define incpos(p) ( (p).x == cols ? ((p).x = 0, (p).y++, 1) : ((p).x++, 0) )
 #define decpos(p) ( (p).x == 0 ? ((p).x = cols, (p).y--, 1) : ((p).x--, 0) )
 
@@ -201,15 +201,40 @@ static FILE *lgfp = NULL;
 static void logtraffic(unsigned char c, int logmode);
 
 /*
+ * Resize a line to make it `cols' columns wide.
+ */
+unsigned long *resizeline(unsigned long *line, int cols)
+{
+    int i, oldlen;
+    unsigned long lineattrs;
+
+    if (line[0] != (unsigned long)cols) {
+       /*
+        * This line is the wrong length, which probably means it
+        * hasn't been accessed since a resize. Resize it now.
+        */
+       oldlen = line[0];
+       lineattrs = line[oldlen + 1];
+       line = srealloc(line, TSIZE * (2 + cols));
+       line[0] = cols;
+       for (i = oldlen; i < cols; i++)
+           line[i + 1] = ERASE_CHAR;
+       line[cols + 1] = lineattrs & LATTR_MODE;
+    }
+
+    return line;
+}
+
+/*
  * Retrieve a line of the screen or of the scrollback, according to
  * whether the y coordinate is non-negative or negative
  * (respectively).
  */
 unsigned long *lineptr(int y, int lineno)
 {
-    unsigned long *line, lineattrs;
+    unsigned long *line, *newline;
     tree234 *whichtree;
-    int i, treeindex, oldlen;
+    int treeindex;
 
     if (y >= 0) {
        whichtree = screen;
@@ -223,20 +248,10 @@ unsigned long *lineptr(int y, int lineno)
     /* We assume that we don't screw up and retrieve something out of range. */
     assert(line != NULL);
 
-    if (line[0] != cols) {
-       /*
-        * This line is the wrong length, which probably means it
-        * hasn't been accessed since a resize. Resize it now.
-        */
-       oldlen = line[0];
-       lineattrs = line[oldlen + 1];
+    newline = resizeline(line, cols);
+    if (newline != line) {
        delpos234(whichtree, treeindex);
-       line = srealloc(line, TSIZE * (2 + cols));
-       line[0] = cols;
-       for (i = oldlen; i < cols; i++)
-           line[i + 1] = ERASE_CHAR;
-       line[cols + 1] = lineattrs & LATTR_MODE;
-       addpos234(whichtree, line, treeindex);
+       addpos234(whichtree, newline, treeindex);
     }
 
     return line + 1;
@@ -298,11 +313,12 @@ void term_update(void)
     Context ctx;
     ctx = get_ctx();
     if (ctx) {
+       if (seen_disp_event)
+           update_sbar();
        if ((seen_key_event && (cfg.scroll_on_key)) ||
            (seen_disp_event && (cfg.scroll_on_disp))) {
            disptop = 0;               /* return to main screen */
            seen_disp_event = seen_key_event = 0;
-           update_sbar();
        }
        do_paint(ctx, TRUE);
        sys_cursor(curs.x, curs.y - disptop);
@@ -358,9 +374,9 @@ void term_init(void)
  */
 void term_size(int newrows, int newcols, int newsavelines)
 {
-    tree234 *newsb, *newscreen, *newalt;
-    unsigned long *newdisp, *oldline, *line;
-    int i, j, ccols;
+    tree234 *newalt;
+    unsigned long *newdisp, *line;
+    int i, j;
     int sblen;
     int save_alt_which = alt_which;
 
@@ -567,6 +583,7 @@ static void scroll(int topline, int botline, int lines, int sb)
     if (lines < 0) {
        while (lines < 0) {
            line = delpos234(screen, botline);
+            line = resizeline(line, cols);
            for (i = 0; i < cols; i++)
                line[i + 1] = erase_char;
            line[cols + 1] = 0;
@@ -609,6 +626,7 @@ static void scroll(int topline, int botline, int lines, int sb)
                addpos234(scrollback, line, sblen);
                line = line2;
            }
+            line = resizeline(line, cols);
            for (i = 0; i < cols; i++)
                line[i + 1] = erase_char;
            line[cols + 1] = 0;
@@ -717,6 +735,7 @@ static void erase_lots(int line_only, int from_begin, int to_end)
     }
     if (!to_end) {
        end = curs;
+       incpos(end);
     }
     check_selection(start, end);
 
@@ -1142,11 +1161,9 @@ void term_out(void)
                    /*
                     * Perform an actual beep if we're not overloaded.
                     */
-                   if ((!cfg.bellovl || !beep_overloaded)
-                       && cfg.beep != 0) {
-                       if (cfg.beep != 2)
-                           beep(cfg.beep);
-                       else if (cfg.beep == 2) {
+                   if (!cfg.bellovl || !beep_overloaded) {
+                       beep(cfg.beep);
+                       if (cfg.beep == BELL_VISUAL) {
                            in_vbell = TRUE;
                            vbell_timeout = ticks + VBELL_TIMEOUT;
                            term_update();
@@ -1444,7 +1461,7 @@ void term_out(void)
                          case ANSI('5', '#'):
                            nlattr = LATTR_NORM;
                            break;
-                         case ANSI('6', '#'):
+                         default: /* spiritually case ANSI('6', '#'): */
                            nlattr = LATTR_WIDE;
                            break;
                        }
@@ -2064,8 +2081,10 @@ void term_out(void)
                        val = c - 'A' + 10;
                    else if (c >= 'a' && c <= 'a' + max - 10)
                        val = c - 'a' + 10;
-                   else
+                   else {
                        termstate = TOPLEVEL;
+                       break;
+                   }
                    osc_string[osc_strlen++] = val;
                    if (osc_strlen >= 7) {
                        palette_set(osc_string[0],
@@ -2359,6 +2378,7 @@ void term_out(void)
                                    ATTR_BLINK)));
                break;
 #endif
+             default: break;          /* placate gcc warning about enum use */
            }
        if (selstate != NO_SELECTION) {
            pos cursplus = curs;
@@ -2950,6 +2970,54 @@ static void sel_spread(void)
     incpos(selend);
 }
 
+void term_do_paste(void)
+{
+    wchar_t *data;
+    int len;
+
+    get_clip(&data, &len);
+    if (data) {
+        wchar_t *p, *q;
+
+        if (paste_buffer)
+            sfree(paste_buffer);
+        paste_pos = paste_hold = paste_len = 0;
+        paste_buffer = smalloc(len * sizeof(wchar_t));
+
+        p = q = data;
+        while (p < data + len) {
+            while (p < data + len &&
+                   !(p <= data + len - sel_nl_sz &&
+                     !memcmp(p, sel_nl, sizeof(sel_nl))))
+                p++;
+
+            {
+                int i;
+                for (i = 0; i < p - q; i++) {
+                    paste_buffer[paste_len++] = q[i];
+                }
+            }
+
+            if (p <= data + len - sel_nl_sz &&
+                !memcmp(p, sel_nl, sizeof(sel_nl))) {
+                paste_buffer[paste_len++] = '\r';
+                p += sel_nl_sz;
+            }
+            q = p;
+        }
+
+        /* Assume a small paste will be OK in one go. */
+        if (paste_len < 256) {
+            luni_send(paste_buffer, paste_len);
+            if (paste_buffer)
+                sfree(paste_buffer);
+            paste_buffer = 0;
+            paste_pos = paste_hold = paste_len = 0;
+        }
+    }
+    get_clip(NULL, NULL);
+}
+
 void term_mouse(Mouse_Button b, Mouse_Action a, int x, int y,
                int shift, int ctrl)
 {
@@ -2997,6 +3065,7 @@ void term_mouse(Mouse_Button b, Mouse_Action a, int x, int y,
          case MBT_WHEEL_DOWN:
            encstate = 0x61;
            break;
+         default: break;              /* placate gcc warning about enum use */
        }
        switch (a) {
          case MA_DRAG:
@@ -3013,6 +3082,7 @@ void term_mouse(Mouse_Button b, Mouse_Action a, int x, int y,
                return;
            is_down = b;
            break;
+         default: break;              /* placate gcc warning about enum use */
        }
        if (shift)
            encstate += 0x04;
@@ -3080,50 +3150,7 @@ void term_mouse(Mouse_Button b, Mouse_Action a, int x, int y,
            selstate = NO_SELECTION;
     } else if (b == MBT_PASTE
               && (a == MA_CLICK || a == MA_2CLK || a == MA_3CLK)) {
-       wchar_t *data;
-       int len;
-
-       get_clip(&data, &len);
-       if (data) {
-           wchar_t *p, *q;
-
-           if (paste_buffer)
-               sfree(paste_buffer);
-           paste_pos = paste_hold = paste_len = 0;
-           paste_buffer = smalloc(len * sizeof(wchar_t));
-
-           p = q = data;
-           while (p < data + len) {
-               while (p < data + len &&
-                      !(p <= data + len - sel_nl_sz &&
-                        !memcmp(p, sel_nl, sizeof(sel_nl))))
-                   p++;
-
-               {
-                   int i;
-                   for (i = 0; i < p - q; i++) {
-                       paste_buffer[paste_len++] = q[i];
-                   }
-               }
-
-               if (p <= data + len - sel_nl_sz &&
-                   !memcmp(p, sel_nl, sizeof(sel_nl))) {
-                   paste_buffer[paste_len++] = '\r';
-                   p += sel_nl_sz;
-               }
-               q = p;
-           }
-
-           /* Assume a small paste will be OK in one go. */
-           if (paste_len < 256) {
-               luni_send(paste_buffer, paste_len);
-               if (paste_buffer)
-                   sfree(paste_buffer);
-               paste_buffer = 0;
-               paste_pos = paste_hold = paste_len = 0;
-           }
-       }
-       get_clip(NULL, NULL);
+        term_do_paste();
     }
 
     term_update();