diff options
Diffstat (limited to 'drivers/char/vt.c')
-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) | |||
751 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 751 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
752 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 752 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; |
753 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; | 753 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; |
754 | unsigned int end; | ||
754 | unsigned short *newscreen; | 755 | unsigned short *newscreen; |
755 | 756 | ||
756 | WARN_CONSOLE_UNLOCKED(); | 757 | WARN_CONSOLE_UNLOCKED(); |
@@ -794,20 +795,44 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
794 | old_origin = vc->vc_origin; | 795 | old_origin = vc->vc_origin; |
795 | new_origin = (long) newscreen; | 796 | new_origin = (long) newscreen; |
796 | new_scr_end = new_origin + new_screen_size; | 797 | new_scr_end = new_origin + new_screen_size; |
797 | if (new_rows < old_rows) | 798 | |
798 | old_origin += (old_rows - new_rows) * old_row_size; | 799 | if (vc->vc_y > new_rows) { |
800 | if (old_rows - vc->vc_y < new_rows) { | ||
801 | /* | ||
802 | * Cursor near the bottom, copy contents from the | ||
803 | * bottom of buffer | ||
804 | */ | ||
805 | old_origin += (old_rows - new_rows) * old_row_size; | ||
806 | end = vc->vc_scr_end; | ||
807 | } else { | ||
808 | /* | ||
809 | * Cursor is in no man's land, copy 1/2 screenful | ||
810 | * from the top and bottom of cursor position | ||
811 | */ | ||
812 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; | ||
813 | end = old_origin + new_screen_size; | ||
814 | } | ||
815 | } else | ||
816 | /* | ||
817 | * Cursor near the top, copy contents from the top of buffer | ||
818 | */ | ||
819 | end = (old_rows > new_rows) ? old_origin + new_screen_size : | ||
820 | vc->vc_scr_end; | ||
799 | 821 | ||
800 | update_attr(vc); | 822 | update_attr(vc); |
801 | 823 | ||
802 | while (old_origin < vc->vc_scr_end) { | 824 | while (old_origin < end) { |
803 | scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth); | 825 | scr_memcpyw((unsigned short *) new_origin, |
826 | (unsigned short *) old_origin, rlth); | ||
804 | if (rrem) | 827 | if (rrem) |
805 | scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem); | 828 | scr_memsetw((void *)(new_origin + rlth), |
829 | vc->vc_video_erase_char, rrem); | ||
806 | old_origin += old_row_size; | 830 | old_origin += old_row_size; |
807 | new_origin += new_row_size; | 831 | new_origin += new_row_size; |
808 | } | 832 | } |
809 | if (new_scr_end > new_origin) | 833 | if (new_scr_end > new_origin) |
810 | scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin); | 834 | scr_memsetw((void *)new_origin, vc->vc_video_erase_char, |
835 | new_scr_end - new_origin); | ||
811 | if (vc->vc_kmalloced) | 836 | if (vc->vc_kmalloced) |
812 | kfree(vc->vc_screenbuf); | 837 | kfree(vc->vc_screenbuf); |
813 | vc->vc_screenbuf = newscreen; | 838 | vc->vc_screenbuf = newscreen; |