Fix many bugs in resizeline().
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 15 Oct 2004 10:48:27 +0000 (10:48 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 15 Oct 2004 10:48:27 +0000 (10:48 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@4629 cda61777-01e9-0310-a592-d414129be87e

terminal.c

index 0857462..800a4f3 100644 (file)
@@ -845,9 +845,12 @@ static termline *decompressline(unsigned char *data, int *bytes_used)
  */
 static void resizeline(Terminal *term, termline *line, int cols)
 {
-    int i, oldlen;
+    int i, oldcols;
 
     if (line->cols != cols) {
+
+       oldcols = line->cols;
+
        /*
         * This line is the wrong length, which probably means it
         * hasn't been accessed since a resize. Resize it now.
@@ -856,24 +859,36 @@ static void resizeline(Terminal *term, termline *line, int cols)
         * out in the resize (if we're shrinking the line) and
         * return their cc lists to the cc free list.
         */
-       for (i = cols; i < line->cols; i++)
+       for (i = cols; i < oldcols; i++)
            clear_cc(line, i);
 
        /*
+        * If we're shrinking the line, we now bodily move the
+        * entire cc section from where it started to where it now
+        * needs to be. (We have to do this before the resize, so
+        * that the data we're copying is still there. However, if
+        * we're expanding, we have to wait until _after_ the
+        * resize so that the space we're copying into is there.)
+        */
+       if (cols < oldcols)
+           memmove(line->chars + cols, line->chars + oldcols,
+                   (line->size - line->cols) * TSIZE);
+
+       /*
         * Now do the actual resize, leaving the _same_ amount of
         * cc space as there was to begin with.
         */
-       oldlen = line->cols;
-       line->size += cols - oldlen;
+       line->size += cols - oldcols;
        line->chars = sresize(line->chars, line->size, TTYPE);
        line->cols = cols;
 
        /*
-        * Bodily move the entire cc section from where it started
-        * to where it now needs to be.
+        * If we're expanding the line, _now_ we move the cc
+        * section.
         */
-       memmove(line->chars + line->cols, line->chars + oldlen,
-               (line->size - line->cols) * TSIZE);
+       if (cols > oldcols)
+           memmove(line->chars + cols, line->chars + oldcols,
+                   (line->size - line->cols) * TSIZE);
 
        /*
         * Go through what's left of the original line, and adjust
@@ -882,18 +897,18 @@ static void resizeline(Terminal *term, termline *line, int cols)
         * relative offsets within the cc block.) Also do the same
         * to the head of the cc_free list.
         */
-       for (i = 0; i < oldlen && i < line->cols; i++)
+       for (i = 0; i < oldcols && i < cols; i++)
            if (line->chars[i].cc_next)
-               line->chars[i].cc_next += cols - oldlen;
+               line->chars[i].cc_next += cols - oldcols;
        if (line->cc_free)
-           line->cc_free += cols - oldlen;
+           line->cc_free += cols - oldcols;
 
        /*
         * And finally fill in the new space with erase chars. (We
         * don't have to worry about cc lists here, because we
         * _know_ the erase char doesn't have one.)
         */
-       for (i = oldlen; i < cols; i++)
+       for (i = oldcols; i < cols; i++)
            line->chars[i] = term->basic_erase_char;
 
        cc_check(line);                /* XXX-REMOVE-BEFORE-RELEASE */