Word-by-word (double-click) selection now spans line breaks if the
[u/mdw/putty] / terminal.c
index a65d715..1e2d50c 100644 (file)
@@ -63,7 +63,7 @@ static unsigned long curstype;               /* type of cursor on real screen */
 
 struct beeptime {
     struct beeptime *next;
-    long ticks;
+    unsigned long ticks;
 };
 static struct beeptime *beephead, *beeptail;
 int nbeeps;
@@ -97,7 +97,7 @@ static int cset;                     /* 0 or 1: which char set */
 static int save_cset, save_csattr;     /* saved with cursor position */
 static int save_utf;                  /* saved with cursor position */
 static int rvideo;                    /* global reverse video flag */
-static int rvbell_timeout;            /* for ESC[?5hESC[?5l vbell */
+static unsigned long rvbell_startpoint;/* for ESC[?5hESC[?5l vbell */
 static int cursor_on;                 /* cursor enabled flag */
 static int reset_132;                 /* Flag ESC c resets to 80 cols */
 static int use_bce;                   /* Use Background coloured erase */
@@ -676,7 +676,7 @@ static void scroll(int topline, int botline, int lines, int sb)
             * selection), and also selanchor (for one being
             * selected as we speak).
             */
-           seltop = sb ? -savelines : 0;
+           seltop = sb ? -savelines : topline;
 
            if (selstart.y >= seltop && selstart.y <= botline) {
                selstart.y--;
@@ -848,7 +848,7 @@ static void insch(int n)
  */
 static void toggle_mode(int mode, int query, int state)
 {
-    long ticks;
+    unsigned long ticks;
 
     if (query)
        switch (mode) {
@@ -877,14 +877,20 @@ static void toggle_mode(int mode, int query, int state)
             * always be an actually _visible_ visual bell.
             */
            ticks = GetTickCount();
-           if (rvideo && !state &&    /* we're turning it off */
-               ticks < rvbell_timeout) {       /* and it's not long since it was turned on */
+           /* turn off a previous vbell to avoid inconsistencies */
+           if (ticks - vbell_startpoint >= VBELL_TIMEOUT)
+               in_vbell = FALSE;
+           if (rvideo && !state &&    /* we're turning it off... */
+               (ticks - rvbell_startpoint) < VBELL_TIMEOUT) {  /* ...soon */
+               /* If there's no vbell timeout already, or this one lasts
+                * longer, replace vbell_timeout with ours. */
+               if (!in_vbell ||
+                   (rvbell_startpoint - vbell_startpoint < VBELL_TIMEOUT))
+                   vbell_startpoint = rvbell_startpoint;
                in_vbell = TRUE;       /* we may clear rvideo but we set in_vbell */
-               if (vbell_timeout < rvbell_timeout)     /* don't move vbell end forward */
-                   vbell_timeout = rvbell_timeout;     /* vbell end is at least then */
            } else if (!rvideo && state) {
                /* This is an ON, so we notice the time and save it. */
-               rvbell_timeout = ticks + VBELL_TIMEOUT;
+               rvbell_startpoint = ticks;
            }
            rvideo = state;
            seen_disp_event = TRUE;
@@ -1194,7 +1200,7 @@ void term_out(void)
              case '\007':
                {
                    struct beeptime *newbeep;
-                   long ticks;
+                   unsigned long ticks;
 
                    ticks = GetTickCount();
 
@@ -1225,7 +1231,7 @@ void term_out(void)
                    }
 
                    if (cfg.bellovl && beep_overloaded &&
-                       ticks - lastbeep >= cfg.bellovl_s) {
+                       ticks - lastbeep >= (unsigned)cfg.bellovl_s) {
                        /*
                         * If we're currently overloaded and the
                         * last beep was more than s seconds ago,
@@ -1250,7 +1256,7 @@ void term_out(void)
                        beep(cfg.beep);
                        if (cfg.beep == BELL_VISUAL) {
                            in_vbell = TRUE;
-                           vbell_timeout = ticks + VBELL_TIMEOUT;
+                           vbell_startpoint = ticks;
                            term_update();
                        }
                    }
@@ -2528,16 +2534,16 @@ static void do_paint(Context ctx, int may_optimise)
     pos scrpos;
     char ch[1024];
     long cursor_background = ERASE_CHAR;
-    long ticks;
+    unsigned long ticks;
 
     /*
      * Check the visual bell state.
      */
     if (in_vbell) {
        ticks = GetTickCount();
-       if (ticks - vbell_timeout >= 0)
-           in_vbell = FALSE;
-    }
+       if (ticks - vbell_startpoint >= VBELL_TIMEOUT)
+           in_vbell = FALSE; 
+   }
 
     rv = (!rvideo ^ !in_vbell ? ATTR_REVERSE : 0);
 
@@ -3061,6 +3067,7 @@ static pos sel_spread_half(pos p, int dir)
 {
     unsigned long *ldata;
     short wvalue;
+    int topy = -count234(scrollback);
 
     ldata = lineptr(p.y);
 
@@ -3087,11 +3094,47 @@ static pos sel_spread_half(pos p, int dir)
         */
        wvalue = wordtype(ldata[p.x]);
        if (dir == +1) {
-           while (p.x < cols && wordtype(ldata[p.x + 1]) == wvalue)
-               p.x++;
+           while (1) {
+               if (p.x < cols-1) {
+                   if (wordtype(ldata[p.x + 1]) == wvalue)
+                       p.x++;
+                   else
+                       break;
+               } else {
+                   if (ldata[cols] & LATTR_WRAPPED) {
+                       unsigned long *ldata2;
+                       ldata2 = lineptr(p.y+1);
+                       if (wordtype(ldata2[0]) == wvalue) {
+                           p.x = 0;
+                           p.y++;
+                           ldata = ldata2;
+                       } else
+                           break;
+                   } else
+                       break;
+               }
+           }
        } else {
-           while (p.x > 0 && wordtype(ldata[p.x - 1]) == wvalue)
-               p.x--;
+           while (1) {
+               if (p.x > 0) {
+                   if (wordtype(ldata[p.x - 1]) == wvalue)
+                       p.x--;
+                   else
+                       break;
+               } else {
+                   unsigned long *ldata2;
+                   if (p.y <= topy)
+                       break;
+                   ldata2 = lineptr(p.y-1);
+                   if ((ldata2[cols] & LATTR_WRAPPED) &&
+                       wordtype(ldata2[cols-1]) == wvalue) {
+                       p.x = cols-1;
+                       p.y--;
+                       ldata = ldata2;
+                   } else
+                       break;
+               }
+           }
        }
        break;
       case SM_LINE: