]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/tty/vt/vt.c
vt: perform safe console erase in the right order
[linux.git] / drivers / tty / vt / vt.c
index bba75560d11e2eca421638aef7a2a928c44878b3..d34984aa646dc4d30813fdfb91290fbef958d0fb 100644 (file)
@@ -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);
 }
 
 /*
@@ -1342,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))
@@ -1503,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;
@@ -1513,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;
 }
 
@@ -1628,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.
@@ -1815,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)
@@ -2022,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()) */
@@ -2031,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;
@@ -2112,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;
@@ -2234,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++;
@@ -2246,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
@@ -2264,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];
@@ -2274,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)
@@ -2282,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) {
@@ -2406,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) {
@@ -4591,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)