terminal: Handle selection for pointer positions outside widget correctly
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 29 Jun 2012 15:35:24 +0000 (11:35 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 29 Jun 2012 16:28:41 +0000 (12:28 -0400)
That is, don't crash and select entire first/last line when the pointer
is above or below widget.

clients/terminal.c

index 28d8ada..62bb020 100644 (file)
@@ -2279,8 +2279,9 @@ recompute_selection(struct terminal *terminal)
        side_margin = allocation.x + (allocation.width - width) / 2;
        top_margin = allocation.y + (allocation.height - height) / 2;
 
-       start_row = (terminal->selection_start_y - top_margin) / ch;
-       end_row = (terminal->selection_end_y - top_margin) / ch;
+       start_row = (terminal->selection_start_y - top_margin + ch) / ch - 1;
+       end_row = (terminal->selection_end_y - top_margin + ch) / ch - 1;
+
        if (start_row < end_row ||
            (start_row == end_row &&
             terminal->selection_start_x < terminal->selection_end_x)) {
@@ -2295,39 +2296,50 @@ recompute_selection(struct terminal *terminal)
                end_x = terminal->selection_start_x;
        }
 
-       x = side_margin + cw / 2;
-       data = terminal_get_row(terminal, terminal->selection_start_row);
-       word_start = 0;
-       for (col = 0; col < terminal->width; col++, x += cw) {
-               if (col == 0 || wordsep(data[col - 1].ch))
-                       word_start = col;
-               if (start_x < x)
-                       break;
-       }
-
-       switch (terminal->dragging) {
-       case SELECT_LINE:
+       if (terminal->selection_start_row < 0) {
+               terminal->selection_start_row = 0;
                terminal->selection_start_col = 0;
-               break;
-       case SELECT_WORD:
-               terminal->selection_start_col = word_start;
-               break;
-       case SELECT_CHAR:
-               terminal->selection_start_col = col;
-               break;
-       }
+       } else {
+               x = side_margin + cw / 2;
+               data = terminal_get_row(terminal,
+                                       terminal->selection_start_row);
+               word_start = 0;
+               for (col = 0; col < terminal->width; col++, x += cw) {
+                       if (col == 0 || wordsep(data[col - 1].ch))
+                               word_start = col;
+                       if (start_x < x)
+                               break;
+               }
 
-       x = side_margin + cw / 2;
-       data = terminal_get_row(terminal, terminal->selection_end_row);
-       for (col = 0; col < terminal->width; col++, x += cw) {
-               if (terminal->dragging == SELECT_CHAR && end_x < x)
+               switch (terminal->dragging) {
+               case SELECT_LINE:
+                       terminal->selection_start_col = 0;
+                       break;
+               case SELECT_WORD:
+                       terminal->selection_start_col = word_start;
                        break;
-               if (terminal->dragging == SELECT_WORD &&
-                   end_x < x && wordsep(data[col].ch))
+               case SELECT_CHAR:
+                       terminal->selection_start_col = col;
                        break;
+               }
        }
 
-       terminal->selection_end_col = col;
+       if (terminal->selection_end_row >= terminal->height) {
+               terminal->selection_end_row = terminal->height;
+               terminal->selection_end_col = 0;
+       } else {
+               x = side_margin + cw / 2;
+               data = terminal_get_row(terminal, terminal->selection_end_row);
+               for (col = 0; col < terminal->width; col++, x += cw) {
+                       if (terminal->dragging == SELECT_CHAR && end_x < x)
+                               break;
+                       if (terminal->dragging == SELECT_WORD &&
+                           end_x < x && wordsep(data[col].ch))
+                               break;
+               }
+
+               terminal->selection_end_col = col;
+       }
 
        return 1;
 }