summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2015-01-21 22:56:16 +0100
committerBoris Faure <billiob@gmail.com>2015-02-06 22:09:52 +0100
commit788f3e7eb7bc7262ab196e8362a4e90ca8af3cc7 (patch)
tree92bbf3a9d805ebfa2cfe679aa36a9de3618d7a72 /src
parent6a2b3ae871a44e15873ba670551d2666029d6c23 (diff)
rewrite selection system. Closes T1893
Diffstat (limited to 'src')
-rw-r--r--src/bin/termio.c961
-rw-r--r--src/bin/termpty.h7
2 files changed, 628 insertions, 340 deletions
diff --git a/src/bin/termio.c b/src/bin/termio.c
index 58c1a61..df56a3a 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -137,19 +137,32 @@ termio_scroll(Evas_Object *obj, int direction, int start_y, int end_y)
137 ty = sd->pty; 137 ty = sd->pty;
138 if (ty->selection.is_active) 138 if (ty->selection.is_active)
139 { 139 {
140 if (start_y <= ty->selection.start.y && 140 int sel_start_y, sel_end_y;
141 end_y >= ty->selection.end.y) 141
142 sel_start_y = ty->selection.start.y;
143 sel_end_y = ty->selection.end.y;
144
145 if (!ty->selection.is_top_to_bottom)
146 INT_SWAP(sel_start_y, sel_end_y);
147 if (start_y <= sel_start_y &&
148 end_y >= sel_end_y)
142 { 149 {
143 ty->selection.start.y += direction; 150 ty->selection.start.y += direction;
144 ty->selection.end.y += direction; 151 ty->selection.end.y += direction;
145 if (!(start_y <= ty->selection.start.y && 152 sel_start_y += direction;
146 end_y >= ty->selection.end.y)) 153 sel_end_y += direction;
147 _sel_set(sd, EINA_FALSE); 154 if (!(start_y <= sel_start_y &&
155 end_y >= sel_end_y))
156 {
157 _sel_set(sd, EINA_FALSE);
158 }
148 } 159 }
149 else 160 else
150 if (!((start_y > ty->selection.end.y) || 161 if (!((start_y > sel_end_y) ||
151 (end_y < ty->selection.start.y))) 162 (end_y < sel_start_y)))
152 _sel_set(sd, EINA_FALSE); 163 {
164 _sel_set(sd, EINA_FALSE);
165 }
153 else 166 else
154 { 167 {
155 ty->selection.start.y += direction; 168 ty->selection.start.y += direction;
@@ -203,15 +216,16 @@ termio_content_change(Evas_Object *obj, Evas_Coord x, Evas_Coord y,
203 start_y = sd->pty->selection.start.y; 216 start_y = sd->pty->selection.start.y;
204 end_x = sd->pty->selection.end.x; 217 end_x = sd->pty->selection.end.x;
205 end_y = sd->pty->selection.end.y; 218 end_y = sd->pty->selection.end.y;
219
220 if (!sd->pty->selection.is_top_to_bottom)
221 {
222 INT_SWAP(start_y, end_y);
223 INT_SWAP(start_x, end_x);
224 }
206 if (ty->selection.is_box) 225 if (ty->selection.is_box)
207 { 226 {
208 int _y = y + (x + n) / ty->w; 227 int _y = y + (x + n) / ty->w;
209 228
210 if (start_y > end_y)
211 INT_SWAP(start_y, end_y);
212 if (start_x > end_x)
213 INT_SWAP(start_x, end_x);
214
215 y = MAX(y, start_y); 229 y = MAX(y, start_y);
216 for (; y <= MIN(_y, end_y); y++) 230 for (; y <= MIN(_y, end_y); y++)
217 { 231 {
@@ -230,21 +244,15 @@ termio_content_change(Evas_Object *obj, Evas_Coord x, Evas_Coord y,
230 int sel_len; 244 int sel_len;
231 Termcell *cells_changed, *cells_selection; 245 Termcell *cells_changed, *cells_selection;
232 246
233 /* probably doing that way too much… */
234 if ((start_y > end_y) ||
235 ((start_y == end_y) && (end_x < start_x)))
236 {
237 INT_SWAP(start_y, end_y);
238 INT_SWAP(start_x, end_x);
239 }
240
241 sel_len = end_x - start_x + ty->w * (end_y - start_y); 247 sel_len = end_x - start_x + ty->w * (end_y - start_y);
242 cells_changed = &(TERMPTY_SCREEN(ty, x, y)); 248 cells_changed = &(TERMPTY_SCREEN(ty, x, y));
243 cells_selection = &(TERMPTY_SCREEN(ty, start_x, start_y)); 249 cells_selection = &(TERMPTY_SCREEN(ty, start_x, start_y));
244 250
245 if (!((cells_changed > (cells_selection + sel_len)) || 251 if (!((cells_changed > (cells_selection + sel_len)) ||
246 (cells_selection > (cells_changed + n)))) 252 (cells_selection > (cells_changed + n))))
247 _sel_set(sd, EINA_FALSE); 253 {
254 _sel_set(sd, EINA_FALSE);
255 }
248 } 256 }
249} 257}
250 258
@@ -2089,7 +2097,11 @@ _sel_set(Termio *sd, Eina_Bool enable)
2089 if (enable) 2097 if (enable)
2090 evas_object_smart_callback_call(sd->win, "selection,on", NULL); 2098 evas_object_smart_callback_call(sd->win, "selection,on", NULL);
2091 else 2099 else
2092 evas_object_smart_callback_call(sd->win, "selection,off", NULL); 2100 {
2101 evas_object_smart_callback_call(sd->win, "selection,off", NULL);
2102 sd->pty->selection.by_word = EINA_FALSE;
2103 sd->pty->selection.by_line = EINA_FALSE;
2104 }
2093} 2105}
2094 2106
2095static void _lost_selection(void *data, Elm_Sel_Type selection); 2107static void _lost_selection(void *data, Elm_Sel_Type selection);
@@ -2183,6 +2195,12 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
2183 start_y = sd->pty->selection.start.y; 2195 start_y = sd->pty->selection.start.y;
2184 end_x = sd->pty->selection.end.x; 2196 end_x = sd->pty->selection.end.x;
2185 end_y = sd->pty->selection.end.y; 2197 end_y = sd->pty->selection.end.y;
2198
2199 if (!sd->pty->selection.is_top_to_bottom)
2200 {
2201 INT_SWAP(start_y, end_y);
2202 INT_SWAP(start_x, end_x);
2203 }
2186 } 2204 }
2187 2205
2188 if (sd->pty->selection.is_box) 2206 if (sd->pty->selection.is_box)
@@ -2190,11 +2208,6 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
2190 int i; 2208 int i;
2191 Eina_Strbuf *sb; 2209 Eina_Strbuf *sb;
2192 2210
2193 if (start_y > end_y)
2194 INT_SWAP(start_y, end_y);
2195 if (start_x > end_x)
2196 INT_SWAP(start_x, end_x);
2197
2198 sb = eina_strbuf_new(); 2211 sb = eina_strbuf_new();
2199 for (i = start_y; i <= end_y; i++) 2212 for (i = start_y; i <= end_y; i++)
2200 { 2213 {
@@ -2220,11 +2233,6 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
2220 } 2233 }
2221 else if ((start_x != end_x) || (start_y != end_y)) 2234 else if ((start_x != end_x) || (start_y != end_y))
2222 { 2235 {
2223 if ((start_y > end_y) || ((start_y == end_y) && (end_x < start_x)))
2224 {
2225 INT_SWAP(start_y, end_y);
2226 INT_SWAP(start_x, end_x);
2227 }
2228 s = termio_selection_get(obj, start_x, start_y, end_x, end_y, &len); 2236 s = termio_selection_get(obj, start_x, start_y, end_x, end_y, &len);
2229 } 2237 }
2230 2238
@@ -2316,6 +2324,7 @@ _sel_line(Termio *sd, int cy)
2316 2324
2317 _sel_set(sd, EINA_TRUE); 2325 _sel_set(sd, EINA_TRUE);
2318 sd->pty->selection.makesel = EINA_FALSE; 2326 sd->pty->selection.makesel = EINA_FALSE;
2327
2319 sd->pty->selection.start.x = 0; 2328 sd->pty->selection.start.x = 0;
2320 sd->pty->selection.start.y = cy; 2329 sd->pty->selection.start.y = cy;
2321 sd->pty->selection.end.x = sd->grid.w - 1; 2330 sd->pty->selection.end.x = sd->grid.w - 1;
@@ -2342,66 +2351,120 @@ _sel_line(Termio *sd, int cy)
2342 } 2351 }
2343 sd->pty->selection.end.y = y; 2352 sd->pty->selection.end.y = y;
2344 2353
2354 sd->pty->selection.by_line = EINA_TRUE;
2355 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2356
2345 termpty_cellcomp_thaw(sd->pty); 2357 termpty_cellcomp_thaw(sd->pty);
2346} 2358}
2347 2359
2348static void 2360static void
2349_sel_line_to(Termio *sd, int cy) 2361_sel_line_to(Termio *sd, int cy, Eina_Bool extend)
2350{ 2362{
2351 int start_y, end_y; 2363 int start_y, end_y, c_start_y, c_end_y,
2364 orig_y, orig_start_y, orig_end_y;
2352 2365
2353 EINA_SAFETY_ON_NULL_RETURN(sd); 2366 EINA_SAFETY_ON_NULL_RETURN(sd);
2354 2367
2368 /* Only change the end position */
2369 orig_y = sd->pty->selection.orig.y;
2355 start_y = sd->pty->selection.start.y; 2370 start_y = sd->pty->selection.start.y;
2356 end_y = sd->pty->selection.end.y; 2371 end_y = sd->pty->selection.end.y;
2357 2372
2373 if (!sd->pty->selection.is_top_to_bottom)
2374 INT_SWAP(start_y, end_y);
2375
2376 _sel_line(sd, cy);
2377 c_start_y = sd->pty->selection.start.y;
2378 c_end_y = sd->pty->selection.end.y;
2379
2380 _sel_line(sd, orig_y);
2381 orig_start_y = sd->pty->selection.start.y;
2382 orig_end_y = sd->pty->selection.end.y;
2383
2358 if (sd->pty->selection.is_box) 2384 if (sd->pty->selection.is_box)
2359 { 2385 {
2360 if (start_y > end_y) 2386 if (extend)
2361 INT_SWAP(start_y, end_y);
2362 if (cy > start_y && cy < end_y)
2363 { 2387 {
2364 _sel_set(sd, EINA_FALSE); 2388 if (start_y <= cy && cy <= end_y )
2365 return; 2389 {
2366 } 2390 start_y = MIN(c_start_y, orig_start_y);
2367 } 2391 end_y = MAX(c_end_y, orig_end_y);
2368 else 2392 }
2369 { 2393 else
2370 if (start_y >= end_y) 2394 {
2371 { 2395 if (c_end_y > end_y)
2372 INT_SWAP(start_y, end_y); 2396 {
2397 orig_y = start_y;
2398 end_y = c_end_y;
2399 }
2400 if (c_start_y < start_y)
2401 {
2402 orig_y = end_y;
2403 start_y = c_start_y;
2404 }
2405 }
2406 goto end;
2373 } 2407 }
2374 if ((cy > start_y) && (cy < end_y)) 2408 else
2375 { 2409 {
2376 _sel_set(sd, EINA_FALSE); 2410 start_y = MIN(c_start_y, orig_start_y);
2377 return; 2411 end_y = MAX(c_end_y, orig_end_y);
2412 goto end;
2378 } 2413 }
2379 } 2414 }
2380
2381 _sel_line(sd, cy);
2382
2383 if (sd->pty->selection.is_box)
2384 {
2385 start_y = MIN(start_y, sd->pty->selection.start.y);
2386 end_y = MAX(end_y, sd->pty->selection.end.y);
2387 }
2388 else 2415 else
2389 { 2416 {
2390 if (sd->pty->selection.start.y <= start_y) 2417 if (c_start_y < start_y)
2391 { 2418 {
2392 start_y = sd->pty->selection.start.y; 2419 /* orig is at bottom */
2420 if (extend)
2421 {
2422 orig_y = end_y;
2423 }
2424 sd->pty->selection.is_top_to_bottom = EINA_FALSE;
2425 end_y = c_start_y;
2426 start_y = orig_end_y;
2427 }
2428 else if (c_end_y > end_y)
2429 {
2430 if (extend)
2431 {
2432 orig_y = start_y;
2433 }
2434 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2435 start_y = orig_start_y;
2436 end_y = c_end_y;
2393 } 2437 }
2394 else 2438 else
2395 if (sd->pty->selection.end.y >= end_y)
2396 { 2439 {
2397 end_y = sd->pty->selection.end.y; 2440 if (c_start_y < orig_start_y)
2441 {
2442 sd->pty->selection.is_top_to_bottom = EINA_FALSE;
2443 start_y = orig_end_y;
2444 end_y = c_start_y;
2445 }
2446 else
2447 {
2448 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2449 start_y = orig_start_y;
2450 end_y = c_end_y;
2451 }
2398 } 2452 }
2399 } 2453 }
2400 2454end:
2401 sd->pty->selection.start.x = 0; 2455 sd->pty->selection.orig.y = orig_y;
2402 sd->pty->selection.end.x = sd->grid.w - 1;
2403 sd->pty->selection.start.y = start_y; 2456 sd->pty->selection.start.y = start_y;
2404 sd->pty->selection.end.y = end_y; 2457 sd->pty->selection.end.y = end_y;
2458 if (sd->pty->selection.is_top_to_bottom)
2459 {
2460 sd->pty->selection.start.x = 0;
2461 sd->pty->selection.end.x = sd->grid.w - 1;
2462 }
2463 else
2464 {
2465 sd->pty->selection.end.x = 0;
2466 sd->pty->selection.start.x = sd->grid.w - 1;
2467 }
2405} 2468}
2406 2469
2407static Eina_Bool 2470static Eina_Bool
@@ -2602,7 +2665,9 @@ _sel_word(Termio *sd, int cx, int cy)
2602 termpty_cellcomp_freeze(sd->pty); 2665 termpty_cellcomp_freeze(sd->pty);
2603 2666
2604 _sel_set(sd, EINA_TRUE); 2667 _sel_set(sd, EINA_TRUE);
2605 sd->pty->selection.makesel = EINA_FALSE; 2668 sd->pty->selection.makesel = EINA_TRUE;
2669 sd->pty->selection.orig.x = cx;
2670 sd->pty->selection.orig.y = cy;
2606 sd->pty->selection.start.x = cx; 2671 sd->pty->selection.start.x = cx;
2607 sd->pty->selection.start.y = cy; 2672 sd->pty->selection.start.y = cy;
2608 sd->pty->selection.end.x = cx; 2673 sd->pty->selection.end.x = cx;
@@ -2657,7 +2722,7 @@ _sel_word(Termio *sd, int cx, int cy)
2657 cells = termpty_cellrow_get(sd->pty, y, &w); 2722 cells = termpty_cellrow_get(sd->pty, y, &w);
2658 if (!cells) goto end; 2723 if (!cells) goto end;
2659 } 2724 }
2660 x = sd->pty->selection.end.x; 2725 x = cx;
2661 2726
2662 do 2727 do
2663 { 2728 {
@@ -2691,78 +2756,294 @@ _sel_word(Termio *sd, int cx, int cy)
2691 while (!done); 2756 while (!done);
2692 2757
2693 end: 2758 end:
2759
2760 sd->pty->selection.by_word = EINA_TRUE;
2761 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2762
2694 termpty_cellcomp_thaw(sd->pty); 2763 termpty_cellcomp_thaw(sd->pty);
2695} 2764}
2696 2765
2697static void 2766static void
2698_sel_word_to(Termio *sd, int cx, int cy) 2767_sel_word_to(Termio *sd, int cx, int cy, Eina_Bool extend)
2699{ 2768{
2700 int start_x, start_y, end_x, end_y; 2769 int start_x, start_y, end_x, end_y, orig_x, orig_y,
2770 c_start_x, c_start_y, c_end_x, c_end_y,
2771 orig_start_x, orig_start_y, orig_end_x, orig_end_y;
2701 2772
2702 EINA_SAFETY_ON_NULL_RETURN(sd); 2773 EINA_SAFETY_ON_NULL_RETURN(sd);
2703 2774
2775 orig_x = sd->pty->selection.orig.x;
2776 orig_y = sd->pty->selection.orig.y;
2704 start_x = sd->pty->selection.start.x; 2777 start_x = sd->pty->selection.start.x;
2705 start_y = sd->pty->selection.start.y; 2778 start_y = sd->pty->selection.start.y;
2706 end_x = sd->pty->selection.end.x; 2779 end_x = sd->pty->selection.end.x;
2707 end_y = sd->pty->selection.end.y; 2780 end_y = sd->pty->selection.end.y;
2708 2781
2782 if (!sd->pty->selection.is_top_to_bottom)
2783 {
2784 INT_SWAP(start_x, end_x);
2785 INT_SWAP(start_y, end_y);
2786 }
2787
2788 _sel_word(sd, cx, cy);
2789 c_start_x = sd->pty->selection.start.x;
2790 c_start_y = sd->pty->selection.start.y;
2791 c_end_x = sd->pty->selection.end.x;
2792 c_end_y = sd->pty->selection.end.y;
2793
2794 _sel_word(sd, orig_x, orig_y);
2795 orig_start_x = sd->pty->selection.start.x;
2796 orig_start_y = sd->pty->selection.start.y;
2797 orig_end_x = sd->pty->selection.end.x;
2798 orig_end_y = sd->pty->selection.end.y;
2799
2709 if (sd->pty->selection.is_box) 2800 if (sd->pty->selection.is_box)
2710 { 2801 {
2711 if (start_y > end_y) 2802 if (extend)
2712 INT_SWAP(start_y, end_y);
2713 if (start_x > end_x)
2714 INT_SWAP(start_x, end_x);
2715 if ((cy >= start_y && cy <= end_y) &&
2716 (cx >= start_x && cx <= end_x))
2717 { 2803 {
2718 _sel_set(sd, EINA_FALSE); 2804 /* special case: kind of line selection */
2719 return; 2805 if (c_start_y != c_end_y)
2806 {
2807 start_x = 0;
2808 end_x = sd->grid.w - 1;
2809 if (start_y <= cy && cy <= end_y )
2810 {
2811 start_y = MIN(c_start_y, orig_start_y);
2812 end_y = MAX(c_end_y, orig_end_y);
2813 }
2814 else
2815 {
2816 if (c_end_y > end_y)
2817 {
2818 orig_y = start_y;
2819 end_y = c_end_y;
2820 }
2821 if (c_start_y < start_y)
2822 {
2823 orig_y = end_y;
2824 start_y = c_start_y;
2825 }
2826 }
2827 goto end;
2828 }
2829 if ((start_y <= cy && cy <= end_y ) &&
2830 (start_x <= cx && cx <= end_x ))
2831 {
2832 start_x = MIN(c_start_x, orig_start_x);
2833 end_x = MAX(c_end_x, orig_end_x);
2834 start_y = MIN(c_start_y, orig_start_y);
2835 end_y = MAX(c_end_y, orig_end_y);
2836 }
2837 else
2838 {
2839 if (c_end_x > end_x)
2840 {
2841 orig_x = start_x;
2842 end_x = c_end_x;
2843 }
2844 if (c_start_x < start_x)
2845 {
2846 orig_x = end_x;
2847 start_x = c_start_x;
2848 }
2849 if (c_end_y > end_y)
2850 {
2851 orig_y = start_y;
2852 end_y = c_end_y;
2853 }
2854 if (c_start_y < start_y)
2855 {
2856 orig_y = end_y;
2857 start_y = c_start_y;
2858 }
2859 end_x = MAX(c_end_x, end_x);
2860 start_y = MIN(c_start_y, start_y);
2861 end_y = MAX(c_end_y, end_y);
2862 }
2863 }
2864 else
2865 {
2866 /* special case: kind of line selection */
2867 if (c_start_y != c_end_y || orig_start_y != orig_end_y)
2868 {
2869 start_x = 0;
2870 end_x = sd->grid.w - 1;
2871 start_y = MIN(c_start_y, orig_start_y);
2872 end_y = MAX(c_end_y, orig_end_y);
2873 goto end;
2874 }
2875
2876 start_x = MIN(c_start_x, orig_start_x);
2877 end_x = MAX(c_end_x, orig_end_x);
2878 start_y = MIN(c_start_y, orig_start_y);
2879 end_y = MAX(c_end_y, orig_end_y);
2720 } 2880 }
2721 } 2881 }
2722 else 2882 else
2723 { 2883 {
2724 if ((start_y > end_y) || 2884 if (c_start_y < start_y ||
2725 ((start_y == end_y) && (end_x < start_x))) 2885 (c_start_y == start_y &&
2886 c_start_x < start_x))
2726 { 2887 {
2727 INT_SWAP(start_y, end_y); 2888 /* orig is at bottom */
2728 INT_SWAP(start_x, end_x); 2889 if (extend)
2890 {
2891 orig_x = end_x;
2892 orig_y = end_y;
2893 }
2894 sd->pty->selection.is_top_to_bottom = EINA_FALSE;
2895 end_x = c_start_x;
2896 end_y = c_start_y;
2897 start_x = orig_end_x;
2898 start_y = orig_end_y;
2729 } 2899 }
2730 if ((cy > start_y || (cy == start_y && cx >= start_x)) && 2900 else if (c_end_y > end_y ||
2731 (cy < end_y || (cy == end_y && cx <= end_x))) 2901 (c_end_y == end_y && c_end_x >= end_x))
2732 { 2902 {
2733 _sel_set(sd, EINA_FALSE); 2903 if (extend)
2734 return; 2904 {
2905 orig_x = start_x;
2906 orig_y = start_y;
2907 }
2908 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2909 start_x = orig_start_x;
2910 start_y = orig_start_y;
2911 end_x = c_end_x;
2912 end_y = c_end_y;
2913 }
2914 else
2915 {
2916 if (c_start_y < orig_start_y ||
2917 (c_start_y == orig_start_y && c_start_x <= orig_start_x))
2918 {
2919 sd->pty->selection.is_top_to_bottom = EINA_FALSE;
2920 start_x = orig_end_x;
2921 start_y = orig_end_y;
2922 end_x = c_start_x;
2923 end_y = c_start_y;
2924 }
2925 else
2926 {
2927 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2928 start_x = orig_start_x;
2929 start_y = orig_start_y;
2930 end_x = c_end_x;
2931 end_y = c_end_y;
2932 }
2735 } 2933 }
2736 } 2934 }
2737 2935
2738 _sel_word(sd, cx, cy); 2936end:
2937 sd->pty->selection.orig.x = orig_x;
2938 sd->pty->selection.orig.y = orig_y;
2939 sd->pty->selection.start.x = start_x;
2940 sd->pty->selection.start.y = start_y;
2941 sd->pty->selection.end.x = end_x;
2942 sd->pty->selection.end.y = end_y;
2943}
2944
2945static void
2946_sel_to(Termio *sd, int cx, int cy, Eina_Bool extend)
2947{
2948 int start_x, start_y, end_x, end_y, orig_x, orig_y;
2949
2950 EINA_SAFETY_ON_NULL_RETURN(sd);
2951
2952 orig_x = sd->pty->selection.orig.x;
2953 orig_y = sd->pty->selection.orig.y;
2954 start_x = sd->pty->selection.start.x;
2955 start_y = sd->pty->selection.start.y;
2956 end_x = sd->pty->selection.end.x;
2957 end_y = sd->pty->selection.end.y;
2739 2958
2740 if (sd->pty->selection.is_box) 2959 if (sd->pty->selection.is_box)
2741 { 2960 {
2742 start_y = MIN(start_y, sd->pty->selection.start.y); 2961 if (!sd->pty->selection.is_top_to_bottom)
2743 start_x = MIN(start_x, sd->pty->selection.start.x); 2962 INT_SWAP(start_y, end_y);
2744 end_y = MAX(end_y, sd->pty->selection.end.y); 2963 if (start_x > end_x)
2745 end_x = MAX(end_x, sd->pty->selection.end.x); 2964 INT_SWAP(start_x, end_x);
2965
2966 if (cy < start_y)
2967 {
2968 start_y = cy;
2969 }
2970 else if (cy > end_y)
2971 {
2972 end_y = cy;
2973 }
2974 else
2975 {
2976 start_y = orig_y;
2977 end_y = cy;
2978 }
2979
2980 if (cx < start_x)
2981 {
2982 start_x = cx;
2983 }
2984 else if (cx > end_x)
2985 {
2986 end_x = cx;
2987 }
2988 else
2989 {
2990 start_x = orig_x;
2991 end_x = cx;
2992 }
2993 sd->pty->selection.is_top_to_bottom = (end_y > start_y);
2994 if (sd->pty->selection.is_top_to_bottom)
2995 {
2996 if (start_x > end_x)
2997 INT_SWAP(start_x, end_x);
2998 }
2999 else
3000 {
3001 if (start_x < end_x)
3002 INT_SWAP(start_x, end_x);
3003 }
2746 } 3004 }
2747 else 3005 else
2748 { 3006 {
2749 if (sd->pty->selection.start.y < start_y || 3007 if (!sd->pty->selection.is_top_to_bottom)
2750 (sd->pty->selection.start.y == start_y && 3008 {
2751 sd->pty->selection.start.x < start_x)) 3009 INT_SWAP(start_x, end_x);
3010 INT_SWAP(start_y, end_y);
3011 }
3012 if (cy < start_y ||
3013 (cy == start_y &&
3014 cx < start_x))
2752 { 3015 {
2753 start_x = sd->pty->selection.start.x; 3016 /* orig is at bottom */
2754 start_y = sd->pty->selection.start.y; 3017 if (sd->pty->selection.is_top_to_bottom && extend)
3018 {
3019 orig_x = end_x;
3020 orig_y = end_y;
3021 }
3022 sd->pty->selection.is_top_to_bottom = EINA_FALSE;
3023 }
3024 else if (cy > end_y ||
3025 (cy == end_y && cx >= end_x))
3026 {
3027 if (!sd->pty->selection.is_top_to_bottom && extend)
3028 {
3029 orig_x = start_x;
3030 orig_y = start_y;
3031 }
3032 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
2755 } 3033 }
2756 else 3034 else
2757 if (sd->pty->selection.end.y > end_y ||
2758 (sd->pty->selection.end.y == end_y &&
2759 sd->pty->selection.end.x > end_x))
2760 { 3035 {
2761 end_x = sd->pty->selection.end.x; 3036 sd->pty->selection.is_top_to_bottom =
2762 end_y = sd->pty->selection.end.y; 3037 (cy > orig_y) || (cy == orig_y && cx > orig_x);
2763 } 3038 }
3039 start_x = orig_x;
3040 start_y = orig_y;
3041 end_x = cx;
3042 end_y = cy;
2764 } 3043 }
2765 3044
3045 sd->pty->selection.orig.x = orig_x;
3046 sd->pty->selection.orig.y = orig_y;
2766 sd->pty->selection.start.x = start_x; 3047 sd->pty->selection.start.x = start_x;
2767 sd->pty->selection.start.y = start_y; 3048 sd->pty->selection.start.y = start_y;
2768 sd->pty->selection.end.x = end_x; 3049 sd->pty->selection.end.x = end_x;
@@ -2770,78 +3051,102 @@ _sel_word_to(Termio *sd, int cx, int cy)
2770} 3051}
2771 3052
2772static void 3053static void
2773_selection_dbl_fix(Evas_Object *obj 3054_selection_dbl_fix(Termio *sd
2774#if defined(SUPPORT_DBLWIDTH) 3055#if defined(SUPPORT_DBLWIDTH)
2775 EINA_UNUSED 3056 EINA_UNUSED
2776#endif 3057#endif
2777 ) 3058 )
2778{ 3059{
2779#if defined(SUPPORT_DBLWIDTH) 3060#if defined(SUPPORT_DBLWIDTH)
2780 Termio *sd = evas_object_smart_data_get(obj); 3061 int start_x, start_y, end_x, end_y;
2781 int w = 0; 3062 int w = 0;
2782 Termcell *cells; 3063 Termcell *cells;
3064 /* Only change the end position */
2783 3065
2784 EINA_SAFETY_ON_NULL_RETURN(sd); 3066 EINA_SAFETY_ON_NULL_RETURN(sd);
3067
3068 start_x = sd->pty->selection.start.x;
3069 start_y = sd->pty->selection.start.y;
3070 end_x = sd->pty->selection.end.x;
3071 end_y = sd->pty->selection.end.y;
3072 if (!sd->pty->selection.is_top_to_bottom)
3073 {
3074 INT_SWAP(start_y, end_y);
3075 INT_SWAP(start_x, end_x);
3076 }
3077
2785 termpty_cellcomp_freeze(sd->pty); 3078 termpty_cellcomp_freeze(sd->pty);
2786 cells = termpty_cellrow_get(sd->pty, sd->pty->selection.end.y - sd->scroll, &w); 3079 cells = termpty_cellrow_get(sd->pty, end_y - sd->scroll, &w);
2787 if (cells) 3080 if (cells)
2788 { 3081 {
2789 // if sel2 after sel1 3082 // if sel2 after sel1
2790 if ((sd->pty->selection.end.y > sd->pty->selection.start.y) || 3083 if ((end_y > start_y) ||
2791 ((sd->pty->selection.end.y == sd->pty->selection.start.y) && 3084 ((end_y == start_y) &&
2792 (sd->pty->selection.end.x >= sd->pty->selection.start.x))) 3085 (end_x >= start_x)))
2793 { 3086 {
2794 if (sd->pty->selection.end.x < (w - 1)) 3087 if (end_x < (w - 1))
2795 { 3088 {
2796 if ((cells[sd->pty->selection.end.x].codepoint != 0) && 3089 if ((cells[end_x].codepoint != 0) &&
2797 (cells[sd->pty->selection.end.x].att.dblwidth)) 3090 (cells[end_x].att.dblwidth))
2798 sd->pty->selection.end.x++; 3091 end_x++;
2799 } 3092 }
2800 } 3093 }
2801 // else sel1 after sel 2 3094 // else sel1 after sel 2
2802 else 3095 else
2803 { 3096 {
2804 if (sd->pty->selection.end.x > 0) 3097 if (end_x > 0)
2805 { 3098 {
2806 if ((cells[sd->pty->selection.end.x].codepoint == 0) && 3099 if ((cells[end_x].codepoint == 0) &&
2807 (cells[sd->pty->selection.end.x].att.dblwidth)) 3100 (cells[end_x].att.dblwidth))
2808 sd->pty->selection.end.x--; 3101 end_x--;
2809 } 3102 }
2810 } 3103 }
2811 } 3104 }
2812 cells = termpty_cellrow_get(sd->pty, sd->pty->selection.start.y - sd->scroll, &w); 3105 cells = termpty_cellrow_get(sd->pty, start_y - sd->scroll, &w);
2813 if (cells) 3106 if (cells)
2814 { 3107 {
2815 // if sel2 after sel1 3108 // if sel2 after sel1
2816 if ((sd->pty->selection.end.y > sd->pty->selection.start.y) || 3109 if ((end_y > start_y) ||
2817 ((sd->pty->selection.end.y == sd->pty->selection.start.y) && 3110 ((end_y == start_y) &&
2818 (sd->pty->selection.end.x >= sd->pty->selection.start.x))) 3111 (end_x >= start_x)))
2819 { 3112 {
2820 if (sd->pty->selection.start.x > 0) 3113 if (start_x > 0)
2821 { 3114 {
2822 if ((cells[sd->pty->selection.start.x].codepoint == 0) && 3115 if ((cells[start_x].codepoint == 0) &&
2823 (cells[sd->pty->selection.start.x].att.dblwidth)) 3116 (cells[start_x].att.dblwidth))
2824 sd->pty->selection.start.x--; 3117 start_x--;
2825 } 3118 }
2826 } 3119 }
2827 // else sel1 after sel 2 3120 // else sel1 after sel 2
2828 else 3121 else
2829 { 3122 {
2830 if (sd->pty->selection.start.x < (w - 1)) 3123 if (start_x < (w - 1))
2831 { 3124 {
2832 if ((cells[sd->pty->selection.start.x].codepoint != 0) && 3125 if ((cells[start_x].codepoint != 0) &&
2833 (cells[sd->pty->selection.start.x].att.dblwidth)) 3126 (cells[start_x].att.dblwidth))
2834 sd->pty->selection.start.x++; 3127 start_x++;
2835 } 3128 }
2836 } 3129 }
2837 } 3130 }
2838 termpty_cellcomp_thaw(sd->pty); 3131 termpty_cellcomp_thaw(sd->pty);
3132
3133 if (!sd->pty->selection.is_top_to_bottom)
3134 {
3135 INT_SWAP(start_y, end_y);
3136 INT_SWAP(start_x, end_x);
3137 }
3138 sd->pty->selection.start.x = start_x;
3139 sd->pty->selection.start.y = start_y;
3140 sd->pty->selection.end.x = end_x;
3141 sd->pty->selection.end.y = end_y;
3142
2839#endif 3143#endif
2840} 3144}
2841 3145
2842static void 3146static void
2843_selection_newline_extend_fix(Evas_Object *obj) 3147_selection_newline_extend_fix(Evas_Object *obj)
2844{ 3148{
3149 int start_x, start_y, end_x, end_y;
2845 Termio *sd; 3150 Termio *sd;
2846 ssize_t w; 3151 ssize_t w;
2847 3152
@@ -2852,29 +3157,49 @@ _selection_newline_extend_fix(Evas_Object *obj)
2852 3157
2853 termpty_cellcomp_freeze(sd->pty); 3158 termpty_cellcomp_freeze(sd->pty);
2854 3159
2855 if ((sd->pty->selection.end.y > sd->pty->selection.start.y) || 3160 start_x = sd->pty->selection.start.x;
2856 ((sd->pty->selection.end.y == sd->pty->selection.start.y) && 3161 start_y = sd->pty->selection.start.y;
2857 (sd->pty->selection.end.x > sd->pty->selection.start.x))) 3162 end_x = sd->pty->selection.end.x;
3163 end_y = sd->pty->selection.end.y;
3164 if (!sd->pty->selection.is_top_to_bottom)
3165 {
3166 INT_SWAP(start_y, end_y);
3167 INT_SWAP(start_x, end_x);
3168 }
3169
3170 if ((end_y > start_y) ||
3171 ((end_y == start_y) &&
3172 (end_x > start_x)))
2858 { 3173 {
2859 /* going down/right */ 3174 /* going down/right */
2860 w = termpty_row_length(sd->pty, sd->pty->selection.start.y); 3175 w = termpty_row_length(sd->pty, start_y);
2861 if (w < sd->pty->selection.start.x) 3176 if (w < start_x)
2862 sd->pty->selection.start.x = w; 3177 start_x = w;
2863 w = termpty_row_length(sd->pty, sd->pty->selection.end.y); 3178 w = termpty_row_length(sd->pty, end_y);
2864 if (w <= sd->pty->selection.end.x) 3179 if (w <= end_x)
2865 sd->pty->selection.end.x = sd->pty->w; 3180 end_x = sd->pty->w;
2866 } 3181 }
2867 else 3182 else
2868 { 3183 {
2869 /* going up/left */ 3184 /* going up/left */
2870 w = termpty_row_length(sd->pty, sd->pty->selection.end.y); 3185 w = termpty_row_length(sd->pty, end_y);
2871 if (w < sd->pty->selection.end.x) 3186 if (w < end_x)
2872 sd->pty->selection.end.x = w; 3187 end_x = w;
2873 w = termpty_row_length(sd->pty, sd->pty->selection.start.y); 3188 w = termpty_row_length(sd->pty, start_y);
2874 if (w <= sd->pty->selection.start.x) 3189 if (w <= start_x)
2875 sd->pty->selection.start.x = sd->pty->w; 3190 start_x = sd->pty->w;
2876 } 3191 }
2877 3192
3193 if (!sd->pty->selection.is_top_to_bottom)
3194 {
3195 INT_SWAP(start_y, end_y);
3196 INT_SWAP(start_x, end_x);
3197 }
3198 sd->pty->selection.start.x = start_x;
3199 sd->pty->selection.start.y = start_y;
3200 sd->pty->selection.end.x = end_x;
3201 sd->pty->selection.end.y = end_y;
3202
2878 termpty_cellcomp_thaw(sd->pty); 3203 termpty_cellcomp_thaw(sd->pty);
2879} 3204}
2880 3205
@@ -3359,17 +3684,114 @@ _edje_cb_top_left_out(void *data, Evas_Object *obj EINA_UNUSED,
3359} 3684}
3360 3685
3361static void 3686static void
3687_handle_mouse_down_single_click(Termio *sd,
3688 int cx, int cy,
3689 int ctrl, int alt, int shift)
3690{
3691 sd->didclick = EINA_FALSE;
3692 /* SINGLE CLICK */
3693 if (sd->pty->selection.is_active &&
3694 (sd->top_left || sd->bottom_right))
3695 {
3696 /* stretch selection */
3697 int start_x, start_y, end_x, end_y;
3698
3699 start_x = sd->pty->selection.start.x;
3700 start_y = sd->pty->selection.start.y;
3701 end_x = sd->pty->selection.end.x;
3702 end_y = sd->pty->selection.end.y;
3703
3704 if (!sd->pty->selection.is_top_to_bottom)
3705 {
3706 INT_SWAP(start_y, end_y);
3707 INT_SWAP(start_x, end_x);
3708 }
3709
3710 cy -= sd->scroll;
3711
3712 sd->pty->selection.makesel = EINA_TRUE;
3713
3714 if (sd->pty->selection.is_box)
3715 {
3716 if (end_x < start_x)
3717 INT_SWAP(end_x, start_x);
3718 }
3719 if (sd->top_left)
3720 {
3721 sd->pty->selection.orig.x = end_x;
3722 sd->pty->selection.orig.y = end_y;
3723 sd->pty->selection.is_top_to_bottom = EINA_FALSE;
3724 }
3725 else
3726 {
3727 /* sd->bottom_right */
3728 sd->pty->selection.orig.x = start_x;
3729 sd->pty->selection.orig.y = start_y;
3730 sd->pty->selection.is_top_to_bottom = EINA_TRUE;
3731 }
3732
3733 sd->pty->selection.start.x = sd->pty->selection.orig.x;
3734 sd->pty->selection.start.y = sd->pty->selection.orig.y;
3735 sd->pty->selection.end.x = cx;
3736 sd->pty->selection.end.y = cy;
3737 _selection_dbl_fix(sd);
3738 }
3739 else if (!shift && !sd->pty->selection.is_active)
3740 {
3741 /* New selection */
3742 sd->moved = EINA_FALSE;
3743 _sel_set(sd, EINA_FALSE);
3744 sd->pty->selection.is_box = (ctrl || alt);
3745 sd->pty->selection.start.x = cx;
3746 sd->pty->selection.start.y = cy - sd->scroll;
3747 sd->pty->selection.orig.x = sd->pty->selection.start.x;
3748 sd->pty->selection.orig.y = sd->pty->selection.start.y;
3749 sd->pty->selection.end.x = cx;
3750 sd->pty->selection.end.y = cy - sd->scroll;
3751 sd->pty->selection.makesel = EINA_TRUE;
3752 sd->pty->selection.by_line = EINA_FALSE;
3753 sd->pty->selection.by_word = EINA_FALSE;
3754 _selection_dbl_fix(sd);
3755 }
3756 else if (shift && sd->pty->selection.is_active)
3757 {
3758 /* let cb_up handle it */
3759 /* do nothing */
3760 return;
3761 }
3762 else if (shift &&
3763 (time(NULL) - sd->pty->selection.last_click) <= 60)
3764 {
3765 sd->pty->selection.is_box = ctrl;
3766 _sel_to(sd, cx, cy - sd->scroll, EINA_FALSE);
3767 sd->pty->selection.is_active = EINA_TRUE;
3768 _selection_dbl_fix(sd);
3769 }
3770 else
3771 {
3772 sd->pty->selection.start.x = sd->pty->selection.end.x = cx;
3773 sd->pty->selection.orig.x = cx;
3774 sd->pty->selection.start.y = sd->pty->selection.end.y = cy - sd->scroll;
3775 sd->pty->selection.orig.y = cy - sd->scroll;
3776 sd->pty->selection.makesel = EINA_TRUE;
3777 sd->didclick = !sd->pty->selection.is_active;
3778 sd->pty->selection.is_active = EINA_FALSE;
3779 }
3780}
3781
3782static void
3362_smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) 3783_smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
3363{ 3784{
3364 Evas_Event_Mouse_Down *ev = event; 3785 Evas_Event_Mouse_Down *ev = event;
3365 Termio *sd = evas_object_smart_data_get(data); 3786 Termio *sd = evas_object_smart_data_get(data);
3366 int cx = 0, cy = 0; 3787 int cx = 0, cy = 0;
3367 int shift, ctrl; 3788 int shift, ctrl, alt;
3368 3789
3369 EINA_SAFETY_ON_NULL_RETURN(sd); 3790 EINA_SAFETY_ON_NULL_RETURN(sd);
3370 3791
3371 shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); 3792 shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
3372 ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); 3793 ctrl = evas_key_modifier_is_set(ev->modifiers, "Control");
3794 alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
3373 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy); 3795 _smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy);
3374 if ((ev->button == 3) && ctrl) 3796 if ((ev->button == 3) && ctrl)
3375 { 3797 {
@@ -3380,10 +3802,11 @@ _smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUS
3380 if (_rep_mouse_down(sd, ev, cx, cy)) return; 3802 if (_rep_mouse_down(sd, ev, cx, cy)) return;
3381 if (ev->button == 1) 3803 if (ev->button == 1)
3382 { 3804 {
3805 sd->pty->selection.makesel = EINA_TRUE;
3383 if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) 3806 if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
3384 { 3807 {
3385 if (shift && sd->pty->selection.is_active) 3808 if (shift && sd->pty->selection.is_active)
3386 _sel_line_to(sd, cy - sd->scroll); 3809 _sel_line_to(sd, cy - sd->scroll, EINA_TRUE);
3387 else 3810 else
3388 _sel_line(sd, cy - sd->scroll); 3811 _sel_line(sd, cy - sd->scroll);
3389 if (sd->pty->selection.is_active) 3812 if (sd->pty->selection.is_active)
@@ -3395,7 +3818,7 @@ _smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUS
3395 if (!sd->pty->selection.is_active && sd->didclick) 3818 if (!sd->pty->selection.is_active && sd->didclick)
3396 sd->pty->selection.is_active = EINA_TRUE; 3819 sd->pty->selection.is_active = EINA_TRUE;
3397 if (shift && sd->pty->selection.is_active) 3820 if (shift && sd->pty->selection.is_active)
3398 _sel_word_to(sd, cx, cy - sd->scroll); 3821 _sel_word_to(sd, cx, cy - sd->scroll, EINA_TRUE);
3399 else 3822 else
3400 _sel_word(sd, cx, cy - sd->scroll); 3823 _sel_word(sd, cx, cy - sd->scroll);
3401 if (sd->pty->selection.is_active) 3824 if (sd->pty->selection.is_active)
@@ -3404,151 +3827,7 @@ _smart_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUS
3404 } 3827 }
3405 else 3828 else
3406 { 3829 {
3407 sd->didclick = EINA_FALSE; 3830 _handle_mouse_down_single_click(sd, cx, cy, ctrl, alt, shift);
3408 /* SINGLE CLICK */
3409 if (sd->pty->selection.is_active &&
3410 (sd->top_left || sd->bottom_right))
3411 {
3412 /* stretch selection */
3413 int start_x, start_y, end_x, end_y;
3414
3415 start_x = sd->pty->selection.start.x;
3416 start_y = sd->pty->selection.start.y;
3417 end_x = sd->pty->selection.end.x;
3418 end_y = sd->pty->selection.end.y;
3419 sd->pty->selection.makesel = EINA_TRUE;
3420 if (sd->pty->selection.is_box)
3421 {
3422 if (sd->top_left)
3423 {
3424 if (start_y < end_y)
3425 INT_SWAP(start_y, end_y);
3426 if (start_x < end_x)
3427 INT_SWAP(start_x, end_x);
3428 }
3429 else
3430 {
3431 if (start_y > end_y)
3432 INT_SWAP(start_y, end_y);
3433 if (start_x > end_x)
3434 INT_SWAP(start_x, end_x);
3435 }
3436 }
3437 else
3438 {
3439 if (sd->top_left)
3440 {
3441 if ((start_y < end_y) ||
3442 ((start_y == end_y) && (end_x > start_x)))
3443 {
3444 INT_SWAP(start_y, end_y);
3445 INT_SWAP(start_x, end_x);
3446 }
3447 }
3448 else
3449 {
3450 if ((start_y > end_y) ||
3451 ((start_y == end_y) && (end_x < start_x)))
3452 {
3453 INT_SWAP(start_y, end_y);
3454 INT_SWAP(start_x, end_x);
3455 }
3456 }
3457 }
3458 sd->pty->selection.start.x = start_x;
3459 sd->pty->selection.start.y = start_y;
3460 sd->pty->selection.end.x = cx;
3461 sd->pty->selection.end.y = cy - sd->scroll;
3462 _selection_dbl_fix(data);
3463 }
3464 else if (!shift && !sd->pty->selection.is_active)
3465 {
3466 /* New selection */
3467 sd->moved = EINA_FALSE;
3468 _sel_set(sd, EINA_FALSE);
3469 sd->pty->selection.is_box =
3470 (ctrl ||
3471 evas_key_modifier_is_set(ev->modifiers, "Alt"));
3472 sd->pty->selection.start.x = cx;
3473 sd->pty->selection.start.y = cy - sd->scroll;
3474 sd->pty->selection.end.x = cx;
3475 sd->pty->selection.end.y = cy - sd->scroll;
3476 sd->pty->selection.makesel = EINA_TRUE;
3477 _selection_dbl_fix(data);
3478 }
3479 else if (shift &&
3480 (time(NULL) - sd->pty->selection.last_click) <= 60)
3481 {
3482 int start_x, start_y, end_x, end_y, cy_rel;
3483
3484 if (!sd->pty->selection.is_active)
3485 sd->pty->selection.is_box = ctrl;
3486
3487 start_x = sd->pty->selection.start.x;
3488 start_y = sd->pty->selection.start.y;
3489 end_x = sd->pty->selection.end.x;
3490 end_y = sd->pty->selection.end.y;
3491
3492 cy_rel = cy - sd->scroll;
3493
3494 if (sd->pty->selection.is_box)
3495 {
3496 if (start_y > end_y)
3497 INT_SWAP(start_y, end_y);
3498 if (start_x > end_x)
3499 INT_SWAP(start_x, end_x);
3500 if (cy_rel < start_y)
3501 start_y = cy;
3502 else if (cy_rel > end_y)
3503 end_y = cy;
3504 if (cx < start_x)
3505 start_x = cx;
3506 else if (cx > end_x)
3507 end_x = cx;
3508 }
3509 else
3510 {
3511 if ((start_y > end_y) ||
3512 ((start_y == end_y) && (end_x < start_x)))
3513 {
3514 INT_SWAP(start_y, end_y);
3515 INT_SWAP(start_x, end_x);
3516 }
3517 if ((cy_rel < start_y) ||
3518 (cy_rel == start_y && cx <= start_x))
3519 {
3520 start_y = cy_rel;
3521 start_x = cx;
3522 }
3523 else if ((cy_rel > end_y) ||
3524 (cy_rel == end_y && cx >= end_x))
3525 {
3526 end_y = cy_rel;
3527 end_x = cx;
3528 }
3529 else
3530 {
3531 sd->pty->selection.makesel = EINA_FALSE;
3532 _sel_set(sd, EINA_FALSE);
3533 _smart_update_queue(data, sd);
3534 return;
3535 }
3536 }
3537 sd->pty->selection.start.x = start_x;
3538 sd->pty->selection.start.y = start_y;
3539 sd->pty->selection.end.x = end_x;
3540 sd->pty->selection.end.y = end_y;
3541 sd->pty->selection.is_active = EINA_TRUE;
3542 _selection_dbl_fix(data);
3543 }
3544 else
3545 {
3546 sd->pty->selection.start.x = sd->pty->selection.end.x = cx;
3547 sd->pty->selection.start.y = sd->pty->selection.end.y = cy - sd->scroll;
3548 sd->pty->selection.makesel = EINA_FALSE;
3549 sd->didclick = !sd->pty->selection.is_active;
3550 sd->pty->selection.is_active = EINA_FALSE;
3551 }
3552 } 3831 }
3553 _smart_update_queue(data, sd); 3832 _smart_update_queue(data, sd);
3554 } 3833 }
@@ -3590,37 +3869,49 @@ _smart_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED
3590 } 3869 }
3591 sd->pty->selection.makesel = EINA_FALSE; 3870 sd->pty->selection.makesel = EINA_FALSE;
3592 3871
3872 /* Only change the end position */
3593 if (((sd->pty->selection.start.x == sd->pty->selection.end.x) && 3873 if (((sd->pty->selection.start.x == sd->pty->selection.end.x) &&
3594 (sd->pty->selection.start.y == sd->pty->selection.end.y)) || 3874 (sd->pty->selection.start.y == sd->pty->selection.end.y)) &&
3595 (!sd->moved)) 3875 (!sd->moved))
3596 { 3876 {
3597 _sel_set(sd, EINA_FALSE); 3877 _sel_set(sd, EINA_FALSE);
3598 sd->didclick = EINA_FALSE; 3878 sd->didclick = EINA_FALSE;
3599 sd->pty->selection.last_click = time(NULL); 3879 sd->pty->selection.last_click = time(NULL);
3880 sd->pty->selection.by_line = EINA_FALSE;
3881 sd->pty->selection.by_word = EINA_FALSE;
3600 _smart_update_queue(data, sd); 3882 _smart_update_queue(data, sd);
3601 return; 3883 return;
3602 } 3884 }
3603 3885
3604 if (sd->pty->selection.is_active) 3886 if (sd->pty->selection.is_active)
3605 { 3887 {
3606 sd->didclick = EINA_TRUE; 3888 if (sd->pty->selection.by_line)
3607 sd->pty->selection.end.x = cx; 3889 {
3608 sd->pty->selection.end.y = cy - sd->scroll; 3890 _sel_line_to(sd, cy - sd->scroll, shift);
3609 _selection_dbl_fix(data); 3891 }
3610 if (sd->pty->selection.is_box) 3892 else if (sd->pty->selection.by_word)
3611 { 3893 {
3612 sd->pty->selection.end.x = cx; 3894 _sel_word_to(sd, cx, cy - sd->scroll, shift);
3613 sd->pty->selection.end.y = cy - sd->scroll; 3895 }
3614 _smart_update_queue(data, sd); 3896 else
3615 termio_take_selection(data, ELM_SEL_TYPE_PRIMARY); 3897 {
3616 } 3898 if (shift)
3617 else 3899 {
3618 { 3900 /* extend selection */
3619 _selection_newline_extend_fix(data); 3901 _sel_to(sd, cx, cy - sd->scroll, EINA_TRUE);
3620 _smart_update_queue(data, sd); 3902 }
3621 termio_take_selection(data, ELM_SEL_TYPE_PRIMARY); 3903 else
3622 } 3904 {
3623 sd->pty->selection.makesel = EINA_FALSE; 3905 sd->didclick = EINA_TRUE;
3906 sd->pty->selection.end.x = cx;
3907 sd->pty->selection.end.y = cy - sd->scroll;
3908 }
3909 }
3910 _selection_dbl_fix(sd);
3911 _selection_newline_extend_fix(data);
3912 _smart_update_queue(data, sd);
3913 termio_take_selection(data, ELM_SEL_TYPE_PRIMARY);
3914 sd->pty->selection.makesel = EINA_FALSE;
3624 } 3915 }
3625 } 3916 }
3626} 3917}
@@ -3719,30 +4010,33 @@ _smart_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUS
3719 } 4010 }
3720 if (sd->pty->selection.makesel) 4011 if (sd->pty->selection.makesel)
3721 { 4012 {
3722 int start_x, start_y, end_x, end_y; 4013 int start_x, start_y;
4014
4015 /* Only change the end position */
4016 start_x = sd->pty->selection.start.x;
4017 start_y = sd->pty->selection.start.y;
3723 4018
3724 if (!sd->pty->selection.is_active) 4019 if (!sd->pty->selection.is_active)
3725 { 4020 {
3726 if ((cx != sd->pty->selection.start.x) || 4021 if ((cx != start_x) ||
3727 ((cy - sd->scroll) != sd->pty->selection.start.y)) 4022 ((cy - sd->scroll) != start_y))
3728 _sel_set(sd, EINA_TRUE); 4023 _sel_set(sd, EINA_TRUE);
3729 } 4024 }
3730 start_x = sd->pty->selection.start.x; 4025
3731 start_y = sd->pty->selection.start.y; 4026 if (sd->pty->selection.by_line)
3732 end_x = sd->pty->selection.end.x;
3733 end_y = sd->pty->selection.end.y;
3734 if ((start_y > end_y) || ((start_y == end_y) && (end_x < start_x)))
3735 { 4027 {
3736 INT_SWAP(start_y, end_y); 4028 _sel_line_to(sd, cy - sd->scroll, EINA_FALSE);
3737 INT_SWAP(start_x, end_x); 4029 }
4030 else if (sd->pty->selection.by_word)
4031 {
4032 _sel_word_to(sd, cx, cy - sd->scroll, EINA_FALSE);
4033 }
4034 else
4035 {
4036 _sel_to(sd, cx, cy - sd->scroll, EINA_FALSE);
3738 } 4037 }
3739 cy -= sd->scroll;
3740 sd->top_left = EINA_FALSE;
3741 sd->bottom_right = EINA_FALSE;
3742 sd->pty->selection.end.x = cx;
3743 sd->pty->selection.end.y = cy;
3744 4038
3745 _selection_dbl_fix(data); 4039 _selection_dbl_fix(sd);
3746 if (!sd->pty->selection.is_box) 4040 if (!sd->pty->selection.is_box)
3747 _selection_newline_extend_fix(data); 4041 _selection_newline_extend_fix(data);
3748 _smart_update_queue(data, sd); 4042 _smart_update_queue(data, sd);
@@ -4283,22 +4577,11 @@ _smart_apply(Evas_Object *obj)
4283 end_x = sd->pty->selection.end.x; 4577 end_x = sd->pty->selection.end.x;
4284 end_y = sd->pty->selection.end.y; 4578 end_y = sd->pty->selection.end.y;
4285 4579
4286 if (sd->pty->selection.is_box) 4580 if (!sd->pty->selection.is_top_to_bottom)
4287 { 4581 {
4288 if (start_y > end_y) 4582 INT_SWAP(start_y, end_y);
4289 INT_SWAP(start_y, end_y); 4583 INT_SWAP(start_x, end_x);
4290 if (start_x > end_x) 4584 }
4291 INT_SWAP(start_x, end_x);
4292 }
4293 else
4294 {
4295 if ((start_y > end_y) ||
4296 ((start_y == end_y) && (end_x < start_x)))
4297 {
4298 INT_SWAP(start_y, end_y);
4299 INT_SWAP(start_x, end_x);
4300 }
4301 }
4302 size_top = start_x * sd->font.chw; 4585 size_top = start_x * sd->font.chw;
4303 4586
4304 size_bottom = (sd->grid.w - end_x - 1) * sd->font.chw; 4587 size_bottom = (sd->grid.w - end_x - 1) * sd->font.chw;
diff --git a/src/bin/termpty.h b/src/bin/termpty.h
index 619a7f7..e5452d8 100644
--- a/src/bin/termpty.h
+++ b/src/bin/termpty.h
@@ -145,13 +145,18 @@ struct _Termpty
145 unsigned char on : 1; 145 unsigned char on : 1;
146 } block; 146 } block;
147 struct { 147 struct {
148 /* start is always the start of the selection
149 * so end.y can be < start.y */
148 struct { 150 struct {
149 int x, y; 151 int x, y;
150 } start, end, start_backup, end_backup; 152 } start, end, orig;
151 time_t last_click; 153 time_t last_click;
152 unsigned char is_active : 1; 154 unsigned char is_active : 1;
153 unsigned char is_box : 1; 155 unsigned char is_box : 1;
154 unsigned char makesel : 1; 156 unsigned char makesel : 1;
157 unsigned char by_word : 1;
158 unsigned char by_line : 1;
159 unsigned char is_top_to_bottom : 1;
155 } selection; 160 } selection;
156 Termstate state, save, swap; 161 Termstate state, save, swap;
157 int exit_code; 162 int exit_code;