aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevin J. Pohly <djpohly@gmail.com>2018-02-21 23:29:41 -0600
committerDevin J. Pohly <djpohly@gmail.com>2018-02-25 21:53:24 -0600
commitbcb5d3adbe57ead05a829e5144c2ba1dc465865f (patch)
treed72e99c54044e02063924f2416ceb9760c2141ec
parent5683b1f80c5ac274adf98517ce2217b4d4896243 (diff)
downloadst-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.c37
-rw-r--r--st.h3
-rw-r--r--x.c55
3 files changed, 54 insertions, 41 deletions
diff --git a/st.c b/st.c
index ea0726c..21cba9e 100644
--- a/st.c
+++ b/st.c
@@ -140,6 +140,7 @@ static void tscrollup(int, int);
140static void tscrolldown(int, int); 140static void tscrolldown(int, int);
141static void tsetattr(int *, int); 141static void tsetattr(int *, int);
142static void tsetchar(Rune, Glyph *, int, int); 142static void tsetchar(Rune, Glyph *, int, int);
143static void tsetdirt(int, int);
143static void tsetscroll(int, int); 144static void tsetscroll(int, int);
144static void tswapscreen(void); 145static void tswapscreen(void);
145static void tsetmode(int, int, int *, int); 146static void tsetmode(int, int, int *, int);
@@ -385,6 +386,42 @@ tlinelen(int y)
385} 386}
386 387
387void 388void
389selstart(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
404void
405selextend(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
424void
388selnormalize(void) 425selnormalize(void)
389{ 426{
390 int i; 427 int i;
diff --git a/st.h b/st.h
index 79dd47e..c5ff5cf 100644
--- a/st.h
+++ b/st.h
@@ -172,7 +172,6 @@ void toggleprinter(const Arg *);
172int tattrset(int); 172int tattrset(int);
173void tnew(int, int); 173void tnew(int, int);
174void tresize(int, int); 174void tresize(int, int);
175void tsetdirt(int, int);
176void tsetdirtattr(int); 175void tsetdirtattr(int);
177void ttynew(char *, char *, char **); 176void ttynew(char *, char *, char **);
178size_t ttyread(void); 177size_t ttyread(void);
@@ -184,6 +183,8 @@ void resettitle(void);
184 183
185void selclear(void); 184void selclear(void);
186void selinit(void); 185void selinit(void);
186void selstart(int, int, int);
187void selextend(int, int, int);
187void selnormalize(void); 188void selnormalize(void);
188int selected(int, int); 189int selected(int, int);
189char *getsel(void); 190char *getsel(void);
diff --git a/x.c b/x.c
index 9f506b1..ddae6b6 100644
--- a/x.c
+++ b/x.c
@@ -157,7 +157,7 @@ static void selnotify(XEvent *);
157static void selclear_(XEvent *); 157static void selclear_(XEvent *);
158static void selrequest(XEvent *); 158static void selrequest(XEvent *);
159static void setsel(char *, Time); 159static void setsel(char *, Time);
160static void getbuttoninfo(XEvent *); 160static void mousesel(XEvent *);
161static void mousereport(XEvent *); 161static void mousereport(XEvent *);
162static char *kmap(KeySym, uint); 162static char *kmap(KeySym, uint);
163static int match(uint, uint); 163static int match(uint, uint);
@@ -313,24 +313,19 @@ y2row(int y)
313} 313}
314 314
315void 315void
316getbuttoninfo(XEvent *e) 316mousesel(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
336void 331void
@@ -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
661void 645void
662bmotion(XEvent *e) 646bmotion(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
685void 660void