diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/vt.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index b8d0c290b0db..1e33cb032e07 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -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,44 @@ 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 + new_screen_size; + } + } else + /* + * Cursor near the top, copy contents from the top of buffer + */ + end = (old_rows > new_rows) ? old_origin + new_screen_size : + 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; |