diff options
author | Devin J. Pohly <djpohly@gmail.com> | 2018-02-21 23:29:41 -0600 |
---|---|---|
committer | Devin J. Pohly <djpohly@gmail.com> | 2018-02-25 21:53:24 -0600 |
commit | bcb5d3adbe57ead05a829e5144c2ba1dc465865f (patch) | |
tree | d72e99c54044e02063924f2416ceb9760c2141ec | |
parent | 5683b1f80c5ac274adf98517ce2217b4d4896243 (diff) | |
download | st-patched-bcb5d3adbe57ead05a829e5144c2ba1dc465865f.tar.bz2 st-patched-bcb5d3adbe57ead05a829e5144c2ba1dc465865f.tar.xz st-patched-bcb5d3adbe57ead05a829e5144c2ba1dc465865f.zip |
Move terminal-related selection logic into st.c
The front-end determines information about mouse clicks and motion, and
the terminal handles the actual selection start/extend/dirty logic by
row and column.
While we're in the neighborhood, we'll also rename getbuttoninfo() to
mousesel() which is, at least, less wrong.
Signed-off-by: Devin J. Pohly <djpohly@gmail.com>
-rw-r--r-- | st.c | 37 | ||||
-rw-r--r-- | st.h | 3 | ||||
-rw-r--r-- | x.c | 55 |
3 files changed, 54 insertions, 41 deletions
@@ -140,6 +140,7 @@ static void tscrollup(int, int); | |||
140 | static void tscrolldown(int, int); | 140 | static void tscrolldown(int, int); |
141 | static void tsetattr(int *, int); | 141 | static void tsetattr(int *, int); |
142 | static void tsetchar(Rune, Glyph *, int, int); | 142 | static void tsetchar(Rune, Glyph *, int, int); |
143 | static void tsetdirt(int, int); | ||
143 | static void tsetscroll(int, int); | 144 | static void tsetscroll(int, int); |
144 | static void tswapscreen(void); | 145 | static void tswapscreen(void); |
145 | static void tsetmode(int, int, int *, int); | 146 | static void tsetmode(int, int, int *, int); |
@@ -385,6 +386,42 @@ tlinelen(int y) | |||
385 | } | 386 | } |
386 | 387 | ||
387 | void | 388 | void |
389 | selstart(int col, int row, int snap) | ||
390 | { | ||
391 | selclear(); | ||
392 | sel.mode = SEL_EMPTY; | ||
393 | sel.type = SEL_REGULAR; | ||
394 | sel.snap = snap; | ||
395 | sel.oe.x = sel.ob.x = col; | ||
396 | sel.oe.y = sel.ob.y = row; | ||
397 | selnormalize(); | ||
398 | |||
399 | if (sel.snap != 0) | ||
400 | sel.mode = SEL_READY; | ||
401 | tsetdirt(sel.nb.y, sel.ne.y); | ||
402 | } | ||
403 | |||
404 | void | ||
405 | selextend(int col, int row, int type) | ||
406 | { | ||
407 | int oldey, oldex, oldsby, oldsey, oldtype; | ||
408 | oldey = sel.oe.y; | ||
409 | oldex = sel.oe.x; | ||
410 | oldsby = sel.nb.y; | ||
411 | oldsey = sel.ne.y; | ||
412 | oldtype = sel.type; | ||
413 | |||
414 | sel.alt = IS_SET(MODE_ALTSCREEN); | ||
415 | sel.oe.x = col; | ||
416 | sel.oe.y = row; | ||
417 | selnormalize(); | ||
418 | sel.type = type; | ||
419 | |||
420 | if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) | ||
421 | tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); | ||
422 | } | ||
423 | |||
424 | void | ||
388 | selnormalize(void) | 425 | selnormalize(void) |
389 | { | 426 | { |
390 | int i; | 427 | int i; |
@@ -172,7 +172,6 @@ void toggleprinter(const Arg *); | |||
172 | int tattrset(int); | 172 | int tattrset(int); |
173 | void tnew(int, int); | 173 | void tnew(int, int); |
174 | void tresize(int, int); | 174 | void tresize(int, int); |
175 | void tsetdirt(int, int); | ||
176 | void tsetdirtattr(int); | 175 | void tsetdirtattr(int); |
177 | void ttynew(char *, char *, char **); | 176 | void ttynew(char *, char *, char **); |
178 | size_t ttyread(void); | 177 | size_t ttyread(void); |
@@ -184,6 +183,8 @@ void resettitle(void); | |||
184 | 183 | ||
185 | void selclear(void); | 184 | void selclear(void); |
186 | void selinit(void); | 185 | void selinit(void); |
186 | void selstart(int, int, int); | ||
187 | void selextend(int, int, int); | ||
187 | void selnormalize(void); | 188 | void selnormalize(void); |
188 | int selected(int, int); | 189 | int selected(int, int); |
189 | char *getsel(void); | 190 | char *getsel(void); |
@@ -157,7 +157,7 @@ static void selnotify(XEvent *); | |||
157 | static void selclear_(XEvent *); | 157 | static void selclear_(XEvent *); |
158 | static void selrequest(XEvent *); | 158 | static void selrequest(XEvent *); |
159 | static void setsel(char *, Time); | 159 | static void setsel(char *, Time); |
160 | static void getbuttoninfo(XEvent *); | 160 | static void mousesel(XEvent *); |
161 | static void mousereport(XEvent *); | 161 | static void mousereport(XEvent *); |
162 | static char *kmap(KeySym, uint); | 162 | static char *kmap(KeySym, uint); |
163 | static int match(uint, uint); | 163 | static int match(uint, uint); |
@@ -313,24 +313,19 @@ y2row(int y) | |||
313 | } | 313 | } |
314 | 314 | ||
315 | void | 315 | void |
316 | getbuttoninfo(XEvent *e) | 316 | mousesel(XEvent *e) |
317 | { | 317 | { |
318 | int type; | 318 | int type, seltype = SEL_REGULAR; |
319 | uint state = e->xbutton.state & ~(Button1Mask | forceselmod); | 319 | uint state = e->xbutton.state & ~(Button1Mask | forceselmod); |
320 | 320 | ||
321 | sel.alt = IS_SET(MODE_ALTSCREEN); | ||
322 | |||
323 | sel.oe.x = x2col(e->xbutton.x); | ||
324 | sel.oe.y = y2row(e->xbutton.y); | ||
325 | selnormalize(); | ||
326 | |||
327 | sel.type = SEL_REGULAR; | ||
328 | for (type = 1; type < LEN(selmasks); ++type) { | 321 | for (type = 1; type < LEN(selmasks); ++type) { |
329 | if (match(selmasks[type], state)) { | 322 | if (match(selmasks[type], state)) { |
330 | sel.type = type; | 323 | seltype = type; |
331 | break; | 324 | break; |
332 | } | 325 | } |
333 | } | 326 | } |
327 | |||
328 | selextend(x2col(e->xbutton.x), y2row(e->xbutton.y), seltype); | ||
334 | } | 329 | } |
335 | 330 | ||
336 | void | 331 | void |
@@ -402,6 +397,7 @@ bpress(XEvent *e) | |||
402 | { | 397 | { |
403 | struct timespec now; | 398 | struct timespec now; |
404 | MouseShortcut *ms; | 399 | MouseShortcut *ms; |
400 | int snap; | ||
405 | 401 | ||
406 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { | 402 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { |
407 | mousereport(e); | 403 | mousereport(e); |
@@ -417,33 +413,22 @@ bpress(XEvent *e) | |||
417 | } | 413 | } |
418 | 414 | ||
419 | if (e->xbutton.button == Button1) { | 415 | if (e->xbutton.button == Button1) { |
420 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
421 | |||
422 | /* Clear previous selection, logically and visually. */ | ||
423 | selclear_(NULL); | ||
424 | sel.mode = SEL_EMPTY; | ||
425 | sel.type = SEL_REGULAR; | ||
426 | sel.oe.x = sel.ob.x = x2col(e->xbutton.x); | ||
427 | sel.oe.y = sel.ob.y = y2row(e->xbutton.y); | ||
428 | |||
429 | /* | 416 | /* |
430 | * If the user clicks below predefined timeouts specific | 417 | * If the user clicks below predefined timeouts specific |
431 | * snapping behaviour is exposed. | 418 | * snapping behaviour is exposed. |
432 | */ | 419 | */ |
420 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
433 | if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { | 421 | if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { |
434 | sel.snap = SNAP_LINE; | 422 | snap = SNAP_LINE; |
435 | } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { | 423 | } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { |
436 | sel.snap = SNAP_WORD; | 424 | snap = SNAP_WORD; |
437 | } else { | 425 | } else { |
438 | sel.snap = 0; | 426 | snap = 0; |
439 | } | 427 | } |
440 | selnormalize(); | ||
441 | |||
442 | if (sel.snap != 0) | ||
443 | sel.mode = SEL_READY; | ||
444 | tsetdirt(sel.nb.y, sel.ne.y); | ||
445 | xsel.tclick2 = xsel.tclick1; | 428 | xsel.tclick2 = xsel.tclick1; |
446 | xsel.tclick1 = now; | 429 | xsel.tclick1 = now; |
430 | |||
431 | selstart(x2col(e->xbutton.x), y2row(e->xbutton.y), snap); | ||
447 | } | 432 | } |
448 | } | 433 | } |
449 | 434 | ||
@@ -649,20 +634,17 @@ brelease(XEvent *e) | |||
649 | selpaste(NULL); | 634 | selpaste(NULL); |
650 | } else if (e->xbutton.button == Button1) { | 635 | } else if (e->xbutton.button == Button1) { |
651 | if (sel.mode == SEL_READY) { | 636 | if (sel.mode == SEL_READY) { |
652 | getbuttoninfo(e); | 637 | mousesel(e); |
653 | setsel(getsel(), e->xbutton.time); | 638 | setsel(getsel(), e->xbutton.time); |
654 | } else | 639 | } else |
655 | selclear_(NULL); | 640 | selclear_(NULL); |
656 | sel.mode = SEL_IDLE; | 641 | sel.mode = SEL_IDLE; |
657 | tsetdirt(sel.nb.y, sel.ne.y); | ||
658 | } | 642 | } |
659 | } | 643 | } |
660 | 644 | ||
661 | void | 645 | void |
662 | bmotion(XEvent *e) | 646 | bmotion(XEvent *e) |
663 | { | 647 | { |
664 | int oldey, oldex, oldsby, oldsey; | ||
665 | |||
666 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { | 648 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { |
667 | mousereport(e); | 649 | mousereport(e); |
668 | return; | 650 | return; |
@@ -672,14 +654,7 @@ bmotion(XEvent *e) | |||
672 | return; | 654 | return; |
673 | 655 | ||
674 | sel.mode = SEL_READY; | 656 | sel.mode = SEL_READY; |
675 | oldey = sel.oe.y; | 657 | mousesel(e); |
676 | oldex = sel.oe.x; | ||
677 | oldsby = sel.nb.y; | ||
678 | oldsey = sel.ne.y; | ||
679 | getbuttoninfo(e); | ||
680 | |||
681 | if (oldey != sel.oe.y || oldex != sel.oe.x) | ||
682 | tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); | ||
683 | } | 658 | } |
684 | 659 | ||
685 | void | 660 | void |