]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - terminal.c
Add auto-recognition of BUG_SSH2_RSA_PADDING for ProFTPD.
[PuTTY.git] / terminal.c
index d6a754c916faace187bb6347933006b6cb521498..ee88974b56326bca9cfcd0d602ef2761011562c6 100644 (file)
@@ -2380,16 +2380,51 @@ static void insch(Terminal *term, int n)
 {
     int dir = (n < 0 ? -1 : +1);
     int m, j;
-    pos cursplus;
+    pos eol;
     termline *ldata;
 
     n = (n < 0 ? -n : n);
     if (n > term->cols - term->curs.x)
        n = term->cols - term->curs.x;
     m = term->cols - term->curs.x - n;
-    cursplus.y = term->curs.y;
-    cursplus.x = term->curs.x + n;
-    check_selection(term, term->curs, cursplus);
+
+    /*
+     * We must de-highlight the selection if it overlaps any part of
+     * the region affected by this operation, i.e. the region from the
+     * current cursor position to end-of-line, _unless_ the entirety
+     * of the selection is going to be moved to the left or right by
+     * this operation but otherwise unchanged, in which case we can
+     * simply move the highlight with the text.
+     */
+    eol.y = term->curs.y;
+    eol.x = term->cols;
+    if (poslt(term->curs, term->selend) && poslt(term->selstart, eol)) {
+        pos okstart = term->curs;
+        pos okend = eol;
+        if (dir > 0) {
+            /* Insertion: n characters at EOL will be splatted. */
+            okend.x -= n;
+        } else {
+            /* Deletion: n characters at cursor position will be splatted. */
+            okstart.x += n;
+        }
+        if (posle(okstart, term->selstart) && posle(term->selend, okend)) {
+            /* Selection is contained entirely in the interval
+             * [okstart,okend), so we need only adjust the selection
+             * bounds. */
+            term->selstart.x += dir * n;
+            term->selend.x += dir * n;
+            assert(term->selstart.x >= term->curs.x);
+            assert(term->selstart.x < term->cols);
+            assert(term->selend.x > term->curs.x);
+            assert(term->selend.x <= term->cols);
+        } else {
+            /* Selection is not wholly contained in that interval, so
+             * we must unhighlight it. */
+            deselect(term);
+        }
+    }
+
     check_boundary(term, term->curs.x, term->curs.y);
     if (dir < 0)
        check_boundary(term, term->curs.x + n, term->curs.y);
@@ -2482,7 +2517,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            compatibility(OTHER);
            deselect(term);
            swap_screen(term, term->no_alt_screen ? 0 : state, FALSE, FALSE);
-           term->disptop = 0;
+            if (term->scroll_on_disp)
+                term->disptop = 0;
            break;
          case 1000:                   /* xterm mouse 1 (normal) */
            term->xterm_mouse = state ? 1 : 0;
@@ -2502,7 +2538,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            compatibility(OTHER);
            deselect(term);
            swap_screen(term, term->no_alt_screen ? 0 : state, TRUE, TRUE);
-           term->disptop = 0;
+            if (term->scroll_on_disp)
+                term->disptop = 0;
            break;
          case 1048:                   /* save/restore cursor */
            if (!term->no_alt_screen)
@@ -2518,7 +2555,8 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            swap_screen(term, term->no_alt_screen ? 0 : state, TRUE, FALSE);
            if (!state && !term->no_alt_screen)
                save_cursor(term, state);
-           term->disptop = 0;
+            if (term->scroll_on_disp)
+                term->disptop = 0;
            break;
          case 2004:                   /* xterm bracketed paste */
            term->bracketed_paste = state ? TRUE : FALSE;
@@ -2980,7 +3018,8 @@ static void term_out(Terminal *term)
                if (has_compat(SCOANSI)) {
                    move(term, 0, 0, 0);
                    erase_lots(term, FALSE, FALSE, TRUE);
-                   term->disptop = 0;
+                    if (term->scroll_on_disp)
+                        term->disptop = 0;
                    term->wrapnext = FALSE;
                    seen_disp_event(term);
                    break;
@@ -3260,7 +3299,8 @@ static void term_out(Terminal *term)
                            request_resize(term->frontend, 80, term->rows);
                        term->reset_132 = 0;
                    }
-                   term->disptop = 0;
+                    if (term->scroll_on_disp)
+                        term->disptop = 0;
                    seen_disp_event(term);
                    break;
                  case 'H':            /* HTS: set a tab */
@@ -3284,7 +3324,8 @@ static void term_out(Terminal *term)
                            }
                            ldata->lattr = LATTR_NORM;
                        }
-                       term->disptop = 0;
+                        if (term->scroll_on_disp)
+                            term->disptop = 0;
                        seen_disp_event(term);
                        scrtop.x = scrtop.y = 0;
                        scrbot.x = 0;
@@ -3482,7 +3523,8 @@ static void term_out(Terminal *term)
                                erase_lots(term, FALSE, !!(i & 2), !!(i & 1));
                            }
                        }
-                       term->disptop = 0;
+                       if (term->scroll_on_disp)
+                            term->disptop = 0;
                        seen_disp_event(term);
                        break;
                      case 'K':       /* EL: erase line or parts of it */
@@ -4389,7 +4431,8 @@ static void term_out(Terminal *term)
                    break;
                  case 'J':
                    erase_lots(term, FALSE, FALSE, TRUE);
-                   term->disptop = 0;
+                    if (term->scroll_on_disp)
+                        term->disptop = 0;
                    break;
                  case 'K':
                    erase_lots(term, TRUE, FALSE, TRUE);
@@ -4444,7 +4487,8 @@ static void term_out(Terminal *term)
                    /* compatibility(ATARI) */
                    move(term, 0, 0, 0);
                    erase_lots(term, FALSE, FALSE, TRUE);
-                   term->disptop = 0;
+                    if (term->scroll_on_disp)
+                        term->disptop = 0;
                    break;
                  case 'L':
                    /* compatibility(ATARI) */
@@ -4467,7 +4511,8 @@ static void term_out(Terminal *term)
                  case 'd':
                    /* compatibility(ATARI) */
                    erase_lots(term, FALSE, TRUE, FALSE);
-                   term->disptop = 0;
+                    if (term->scroll_on_disp)
+                        term->disptop = 0;
                    break;
                  case 'e':
                    /* compatibility(ATARI) */
@@ -5851,7 +5896,7 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
      */
     if (raw_mouse &&
        (term->selstate != ABOUT_TO) && (term->selstate != DRAGGING)) {
-       int encstate = 0, r, c;
+       int encstate = 0, r, c, wheel;
        char abuf[32];
        int len = 0;
 
@@ -5860,22 +5905,35 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
            switch (braw) {
              case MBT_LEFT:
                encstate = 0x00;               /* left button down */
+                wheel = FALSE;
                break;
              case MBT_MIDDLE:
                encstate = 0x01;
+                wheel = FALSE;
                break;
              case MBT_RIGHT:
                encstate = 0x02;
+                wheel = FALSE;
                break;
              case MBT_WHEEL_UP:
                encstate = 0x40;
+                wheel = TRUE;
                break;
              case MBT_WHEEL_DOWN:
                encstate = 0x41;
+                wheel = TRUE;
                break;
-             default: break;          /* placate gcc warning about enum use */
+             default:
+                return;
            }
-           switch (a) {
+            if (wheel) {
+                /* For mouse wheel buttons, we only ever expect to see
+                 * MA_CLICK actions, and we don't try to keep track of
+                 * the buttons being 'pressed' (since without matching
+                 * click/release pairs that's pointless). */
+                if (a != MA_CLICK)
+                    return;
+            } else switch (a) {
              case MA_DRAG:
                if (term->xterm_mouse == 1)
                    return;
@@ -5892,7 +5950,8 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
                    return;
                term->mouse_is_down = braw;
                break;
-             default: break;          /* placate gcc warning about enum use */
+              default:
+                return;
            }
            if (shift)
                encstate += 0x04;