Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[powerpc.git] / drivers / char / vt.c
index b8d0c29..e91268e 100644 (file)
@@ -751,6 +751,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
        unsigned int old_cols, old_rows, old_row_size, old_screen_size;
        unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+       unsigned int end;
        unsigned short *newscreen;
 
        WARN_CONSOLE_UNLOCKED();
@@ -794,20 +795,45 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        old_origin = vc->vc_origin;
        new_origin = (long) newscreen;
        new_scr_end = new_origin + new_screen_size;
-       if (new_rows < old_rows)
-               old_origin += (old_rows - new_rows) * old_row_size;
+
+       if (vc->vc_y > new_rows) {
+               if (old_rows - vc->vc_y < new_rows) {
+                       /*
+                        * Cursor near the bottom, copy contents from the
+                        * bottom of buffer
+                        */
+                       old_origin += (old_rows - new_rows) * old_row_size;
+                       end = vc->vc_scr_end;
+               } else {
+                       /*
+                        * Cursor is in no man's land, copy 1/2 screenful
+                        * from the top and bottom of cursor position
+                        */
+                       old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+                       end = old_origin + (old_row_size * new_rows);
+               }
+       } else
+               /*
+                * Cursor near the top, copy contents from the top of buffer
+                */
+               end = (old_rows > new_rows) ? old_origin +
+                       (old_row_size * new_rows) :
+                       vc->vc_scr_end;
 
        update_attr(vc);
 
-       while (old_origin < vc->vc_scr_end) {
-               scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
+       while (old_origin < end) {
+               scr_memcpyw((unsigned short *) new_origin,
+                           (unsigned short *) old_origin, rlth);
                if (rrem)
-                       scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
+                       scr_memsetw((void *)(new_origin + rlth),
+                                   vc->vc_video_erase_char, rrem);
                old_origin += old_row_size;
                new_origin += new_row_size;
        }
        if (new_scr_end > new_origin)
-               scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+               scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+                           new_scr_end - new_origin);
        if (vc->vc_kmalloced)
                kfree(vc->vc_screenbuf);
        vc->vc_screenbuf = newscreen;