[PATCH] Fix backspace on wrapped lines in console (virtual terminal)

From: Joe Peterson
Date: Sat Sep 20 2008 - 12:26:05 EST


Attached is a patch that fixes virtual terminal problems when backspace
is used on wrapped lines (see patch text for the specific issues). The
issues can be demonstrated by trying two things in the console (vt):

#1

1) issue the "cat" command
2) type characters until you have wrapped cursor to next line
3) hit backspace (nothing happens visually, but char(s) are erased
in buf, as seen when enter is hit and line is printed to display)

#2

1) issue the "cat" command
2) type characters until you are at the very end of the line
(cursor now on last char - i.e. in "need_wrap" state)
3) hit backspace (it moves back and visually erases 2nd to last char,
but hitting enter shows that last char was actually erased in buffer)

-Joe
Fix backspace in the virtual terminal when line is wrapped:

1) Enable backspace to work when wrapped to next line.

2) Correct backspace behavior when most recently typed
character is in the rightmost column (i.e. in need_wrap state).

Signed-off-by: Joe Peterson <joe@xxxxxxxxxxx>
---

--- linux-2.6.27-rc6-git5/drivers/char/vt.c.orig 2008-09-20 09:04:55.000000000 -0600
+++ linux-2.6.27-rc6-git5/drivers/char/vt.c 2008-09-20 09:49:22.000000000 -0600
@@ -1130,12 +1130,36 @@ static inline void cr(struct vc_data *vc

static inline void bs(struct vc_data *vc)
{
- if (vc->vc_x) {
- vc->vc_pos -= 2;
- vc->vc_x--;
+ if (vc->vc_need_wrap) {
+ /*
+ * If in need_wrap state, do not move cursor,
+ * but unset need_wrap.
+ */
vc->vc_need_wrap = 0;
- notify_write(vc, '\b');
+ } else {
+ if (vc->vc_x == 0) {
+ /*
+ * If at leftmost column, move cursor to end
+ * of previous line (only if autowrap is on).
+ */
+ if (vc->vc_decawm) {
+ vc->vc_x = vc->vc_cols - 1;
+ if (vc->vc_y == vc->vc_top) {
+ scrdown(vc,
+ vc->vc_top, vc->vc_bottom, 1);
+ vc->vc_pos += vc->vc_size_row - 2;
+ } else if (vc->vc_y > 0) {
+ vc->vc_y--;
+ vc->vc_pos -= 2;
+ }
+ }
+ } else {
+ /* Normal case: just move cursor back */
+ vc->vc_x--;
+ vc->vc_pos -= 2;
+ }
}
+ notify_write(vc, '\b');
}

static inline void del(struct vc_data *vc)