From 530cda19ce88332b9c1f3590a19f56ce676c0933 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 15 Mar 2014 12:53:58 -0700 Subject: selection improvements --- st.c | 75 +++++++++++++++++++++++++++++++----------------------------------- term.c | 47 +++++++++++++++++++++++++++++++++++++++-- term.h | 16 +++++++------- 3 files changed, 89 insertions(+), 49 deletions(-) diff --git a/st.c b/st.c index 0b4adcc..6780069 100644 --- a/st.c +++ b/st.c @@ -769,12 +769,17 @@ static void mousereport(struct st_window *xw, XEvent *ev) static void bpress(struct st_window *xw, XEvent *ev) { struct st_term *term = &xw->term; + unsigned type, state; if (term->mousebtn || term->mousemotion) { mousereport(xw, ev); - } else if (ev->xbutton.button == Button1) { - unsigned type = SEL_REGULAR; - unsigned state = ev->xbutton.state & ~Button1Mask; + return; + } + + switch (ev->xbutton.button) { + case Button1: + type = SEL_REGULAR; + state = ev->xbutton.state & ~Button1Mask; for (unsigned i = 1; i < ARRAY_SIZE(selmasks); i++) if (match(selmasks[i], state)) { @@ -785,18 +790,16 @@ static void bpress(struct st_window *xw, XEvent *ev) xw->mousemotion = 1; term_sel_start(term, type, mouse_pos(xw, ev)); gettimeofday(&xw->mousedown, NULL); - } else if (ev->xbutton.button == Button4) { + break; + case Button4: ttywrite(term, "\031", 1); - } else if (ev->xbutton.button == Button5) { + break; + case Button5: ttywrite(term, "\005", 1); + break; } } -static bool isword(unsigned c) -{ - return c && !isspace(c); -} - static void brelease(struct st_window *xw, XEvent *ev) { struct st_term *term = &xw->term; @@ -807,43 +810,35 @@ static void brelease(struct st_window *xw, XEvent *ev) return; } - if (ev->xbutton.button == Button2) { - selpaste(xw, NULL); - } else if (ev->xbutton.button == Button1) { - struct coord end = mouse_pos(xw, ev); + switch (ev->xbutton.button) { + case Button1: + xw->mousemotion = 0; memmove(xw->mouseup + 1, xw->mouseup, sizeof(struct timeval) * 2); gettimeofday(xw->mouseup, NULL); - if (sel->start.x == end.x && - sel->start.y == end.y) { - if (TIMEDIFF(xw->mouseup[0], xw->mouseup[2]) < - tripleclicktimeout) { - /* triple click on the line */ - sel->start.x = 0; - end.x = term->size.x - 1; - } else if (TIMEDIFF(xw->mouseup[0], xw->mouseup[1]) < - doubleclicktimeout) { - /* double click to select word */ - while (sel->start.x && - isword(term_pos(term, sel->start)[-1].c)) - sel->start.x--; - - while (end.x < term->size.x - 1 && - isword(term_pos(term, end)[1].c)) - end.x++; - } else if (TIMEDIFF(xw->mouseup[0], xw->mousedown) < - doubleclicktimeout) { - sel->type = SEL_NONE; - } - } + struct coord end = mouse_pos(xw, ev); + + if (!(sel->start.x == end.x && + sel->start.y == end.y)) + term_sel_update(term, end); + else if (TIMEDIFF(xw->mouseup[0], xw->mouseup[2]) < + tripleclicktimeout) + term_sel_line(term, end); + else if (TIMEDIFF(xw->mouseup[0], xw->mouseup[1]) < + doubleclicktimeout) + term_sel_word(term, end); + else if (TIMEDIFF(xw->mouseup[0], xw->mousedown) < + doubleclicktimeout) + term_sel_stop(term); - xw->mousemotion = 0; - term_sel_end(term, end); - term_sel_copy(term); if (sel->clip) xsetsel(xw); + break; + case Button2: + selpaste(xw, NULL); + break; } } @@ -857,7 +852,7 @@ static void bmotion(struct st_window *xw, XEvent *ev) } if (xw->mousemotion) - term_sel_end(term, mouse_pos(xw, ev)); + term_sel_update(term, mouse_pos(xw, ev)); } /* Resizing code */ diff --git a/term.c b/term.c index 0758c85..ea31fca 100644 --- a/term.c +++ b/term.c @@ -87,7 +87,7 @@ bool term_selected(struct st_selection *sel, int x, int y) return false; } -void term_sel_copy(struct st_term *term) +static void term_sel_copy(struct st_term *term) { struct st_selection *sel = &term->sel; unsigned char *str = NULL, *ptr; @@ -142,7 +142,7 @@ void term_sel_start(struct st_term *term, unsigned type, struct coord start) term->dirty = true; } -void term_sel_end(struct st_term *term, struct coord end) +void term_sel_update(struct st_term *term, struct coord end) { struct st_selection *sel = &term->sel; @@ -158,6 +158,7 @@ void term_sel_end(struct st_term *term, struct coord end) sel->p1.x > sel->p2.x)) swap(sel->p1, sel->p2); + term_sel_copy(term); break; case SEL_RECTANGULAR: if (sel->p1.x > sel->p2.x) @@ -165,12 +166,54 @@ void term_sel_end(struct st_term *term, struct coord end) if (sel->p1.y > sel->p2.y) swap(sel->p1.y, sel->p2.y); + term_sel_copy(term); break; } term->dirty = true; } +void term_sel_stop(struct st_term *term) +{ + term->sel.type = SEL_NONE; + term->dirty = true; +} + +static bool isword(unsigned c) +{ + static const char not_word[] = "*.!?;=&#$%^[](){}<>"; + + return c && !isspace(c) && !strchr(not_word, c); +} + +void term_sel_word(struct st_term *term, struct coord pos) +{ + struct st_selection *sel = &term->sel; + + sel->start = pos; + + while (sel->start.x && + isword(term_pos(term, sel->start)[-1].c)) + sel->start.x--; + + while (pos.x < term->size.x - 1 && + isword(term_pos(term, pos)[1].c)) + pos.x++; + + term_sel_update(term, pos); +} + +void term_sel_line(struct st_term *term, struct coord pos) +{ + struct st_selection *sel = &term->sel; + + sel->start = pos; + sel->start.x = 0; + pos.x = term->size.x - 1; + + term_sel_update(term, pos); +} + /* Escape handling */ static void csiparse(struct csi_escape *csi) diff --git a/term.h b/term.h index e72e5b6..33fab78 100644 --- a/term.h +++ b/term.h @@ -193,13 +193,15 @@ struct st_term { void (*seturgent)(struct st_term *, int); }; -bool term_selected(struct st_selection *sel, int x, int y); -void term_sel_copy(struct st_term *term); -void term_sel_start(struct st_term *term, unsigned type, struct coord start); -void term_sel_end(struct st_term *term, struct coord end); - -void term_echo(struct st_term *term, char *buf, int len); -void term_read(struct st_term *term); +bool term_selected(struct st_selection *, int, int); +void term_sel_start(struct st_term *, unsigned, struct coord); +void term_sel_update(struct st_term *, struct coord); +void term_sel_stop(struct st_term *); +void term_sel_word(struct st_term *, struct coord); +void term_sel_line(struct st_term *, struct coord); + +void term_echo(struct st_term *, char *, int); +void term_read(struct st_term *); void term_resize(struct st_term *term, struct coord size); void term_shutdown(struct st_term *term); -- cgit v1.2.3