diff options
Diffstat (limited to 'drivers/tty/vt/vt.c')
-rw-r--r-- | drivers/tty/vt/vt.c | 127 |
1 files changed, 69 insertions, 58 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 41ec8e5010f3..d34984aa646d 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -935,8 +935,11 @@ static void flush_scrollback(struct vc_data *vc) { WARN_CONSOLE_UNLOCKED(); + set_origin(vc); if (vc->vc_sw->con_flush_scrollback) vc->vc_sw->con_flush_scrollback(vc); + else + vc->vc_sw->con_switch(vc); } /* @@ -1272,6 +1275,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, if (con_is_visible(vc)) update_screen(vc); vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num); + notify_update(vc); return err; } @@ -1341,6 +1345,8 @@ struct vc_data *vc_deallocate(unsigned int currcons) * VT102 emulator */ +enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt}; + #define set_kbd(vc, x) vt_set_kbd_mode_bit((vc)->vc_num, (x)) #define clr_kbd(vc, x) vt_clr_kbd_mode_bit((vc)->vc_num, (x)) #define is_kbd(vc, x) vt_get_kbd_mode_bit((vc)->vc_num, (x)) @@ -1502,8 +1508,10 @@ static void csi_J(struct vc_data *vc, int vpar) count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; start = (unsigned short *)vc->vc_origin; break; + case 3: /* include scrollback */ + flush_scrollback(vc); + /* fallthrough */ case 2: /* erase whole display */ - case 3: /* (and scrollback buffer later) */ vc_uniscr_clear_lines(vc, 0, vc->vc_rows); count = vc->vc_cols * vc->vc_rows; start = (unsigned short *)vc->vc_origin; @@ -1512,13 +1520,7 @@ static void csi_J(struct vc_data *vc, int vpar) return; } scr_memsetw(start, vc->vc_video_erase_char, 2 * count); - if (vpar == 3) { - set_origin(vc); - flush_scrollback(vc); - if (con_is_visible(vc)) - update_screen(vc); - } else if (con_should_update(vc)) - do_update_region(vc, (unsigned long) start, count); + update_region(vc, (unsigned long) start, count); vc->vc_need_wrap = 0; } @@ -1627,9 +1629,9 @@ static void rgb_background(struct vc_data *vc, const struct rgb *c) /* * ITU T.416 Higher colour modes. They break the usual properties of SGR codes - * and thus need to be detected and ignored by hand. Strictly speaking, that - * standard also wants : rather than ; as separators, contrary to ECMA-48, but - * no one produces such codes and almost no one accepts them. + * and thus need to be detected and ignored by hand. That standard also + * wants : rather than ; as separators but sequences containing : are currently + * completely ignored by the parser. * * Subcommands 3 (CMY) and 4 (CMYK) are so insane there's no point in * supporting them. @@ -1814,7 +1816,7 @@ static void set_mode(struct vc_data *vc, int on_off) int i; for (i = 0; i <= vc->vc_npar; i++) - if (vc->vc_ques) { + if (vc->vc_priv == EPdec) { switch(vc->vc_par[i]) { /* DEC private modes set/reset */ case 1: /* Cursor keys send ^[Ox/^[[x */ if (on_off) @@ -2021,7 +2023,7 @@ static void restore_cur(struct vc_data *vc) } enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, - EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd, + EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd, ESpalette, ESosc }; /* console_lock is held (except via vc_init()) */ @@ -2030,7 +2032,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_top = 0; vc->vc_bottom = vc->vc_rows; vc->vc_state = ESnormal; - vc->vc_ques = 0; + vc->vc_priv = EPecma; vc->vc_translate = set_translate(LAT1_MAP, vc); vc->vc_G0_charset = LAT1_MAP; vc->vc_G1_charset = GRAF_MAP; @@ -2111,6 +2113,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) lf(vc); if (!is_kbd(vc, lnm)) return; + /* fall through */ case 13: cr(vc); return; @@ -2233,9 +2236,22 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) vc->vc_state=ESfunckey; return; } - vc->vc_ques = (c == '?'); - if (vc->vc_ques) + switch (c) { + case '?': + vc->vc_priv = EPdec; return; + case '>': + vc->vc_priv = EPgt; + return; + case '=': + vc->vc_priv = EPeq; + return; + case '<': + vc->vc_priv = EPlt; + return; + } + vc->vc_priv = EPecma; + /* fall through */ case ESgetpars: if (c == ';' && vc->vc_npar < NPAR - 1) { vc->vc_npar++; @@ -2245,16 +2261,22 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) vc->vc_par[vc->vc_npar] += c - '0'; return; } + if (c >= 0x20 && c <= 0x3f) { /* 0x2x, 0x3a and 0x3c - 0x3f */ + vc->vc_state = EScsiignore; + return; + } vc->vc_state = ESnormal; switch(c) { case 'h': - set_mode(vc, 1); + if (vc->vc_priv <= EPdec) + set_mode(vc, 1); return; case 'l': - set_mode(vc, 0); + if (vc->vc_priv <= EPdec) + set_mode(vc, 0); return; case 'c': - if (vc->vc_ques) { + if (vc->vc_priv == EPdec) { if (vc->vc_par[0]) vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16); else @@ -2263,7 +2285,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } break; case 'm': - if (vc->vc_ques) { + if (vc->vc_priv == EPdec) { clear_selection(); if (vc->vc_par[0]) vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1]; @@ -2273,7 +2295,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } break; case 'n': - if (!vc->vc_ques) { + if (vc->vc_priv == EPecma) { if (vc->vc_par[0] == 5) status_report(tty); else if (vc->vc_par[0] == 6) @@ -2281,8 +2303,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } return; } - if (vc->vc_ques) { - vc->vc_ques = 0; + if (vc->vc_priv != EPecma) { + vc->vc_priv = EPecma; return; } switch(c) { @@ -2405,6 +2427,11 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; } return; + case EScsiignore: + if (c >= 20 && c <= 0x3f) + return; + vc->vc_state = ESnormal; + return; case ESpercent: vc->vc_state = ESnormal; switch (c) { @@ -2764,8 +2791,8 @@ rescan_last_byte: con_flush(vc, draw_from, draw_to, &draw_x); vc_uniscr_debug_check(vc); console_conditional_schedule(); - console_unlock(); notify_update(vc); + console_unlock(); return n; } @@ -2884,8 +2911,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) unsigned char c; static DEFINE_SPINLOCK(printing_lock); const ushort *start; - ushort cnt = 0; - ushort myx; + ushort start_x, cnt; int kmsg_console; /* console busy or not yet initialized */ @@ -2898,10 +2924,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) if (kmsg_console && vc_cons_allocated(kmsg_console - 1)) vc = vc_cons[kmsg_console - 1].d; - /* read `x' only after setting currcons properly (otherwise - the `x' macro will read the x of the foreground console). */ - myx = vc->vc_x; - if (!vc_cons_allocated(fg_console)) { /* impossible */ /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */ @@ -2916,53 +2938,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) hide_cursor(vc); start = (ushort *)vc->vc_pos; - - /* Contrived structure to try to emulate original need_wrap behaviour - * Problems caused when we have need_wrap set on '\n' character */ + start_x = vc->vc_x; + cnt = 0; while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { - if (cnt > 0) { - if (con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x); - vc->vc_x += cnt; - if (vc->vc_need_wrap) - vc->vc_x--; - cnt = 0; - } + if (cnt && con_is_visible(vc)) + vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); + cnt = 0; if (c == 8) { /* backspace */ bs(vc); start = (ushort *)vc->vc_pos; - myx = vc->vc_x; + start_x = vc->vc_x; continue; } if (c != 13) lf(vc); cr(vc); start = (ushort *)vc->vc_pos; - myx = vc->vc_x; + start_x = vc->vc_x; if (c == 10 || c == 13) continue; } + vc_uniscr_putc(vc, c); scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos); notify_write(vc, c); cnt++; - if (myx == vc->vc_cols - 1) { - vc->vc_need_wrap = 1; - continue; - } - vc->vc_pos += 2; - myx++; - } - if (cnt > 0) { - if (con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x); - vc->vc_x += cnt; - if (vc->vc_x == vc->vc_cols) { - vc->vc_x--; + if (vc->vc_x == vc->vc_cols - 1) { vc->vc_need_wrap = 1; + } else { + vc->vc_pos += 2; + vc->vc_x++; } } + if (cnt && con_is_visible(vc)) + vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); set_cursor(vc); notify_update(vc); @@ -4607,8 +4617,9 @@ EXPORT_SYMBOL_GPL(screen_pos); void getconsxy(struct vc_data *vc, unsigned char *p) { - p[0] = vc->vc_x; - p[1] = vc->vc_y; + /* clamp values if they don't fit */ + p[0] = min(vc->vc_x, 0xFFu); + p[1] = min(vc->vc_y, 0xFFu); } void putconsxy(struct vc_data *vc, unsigned char *p) |