summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2014-03-15 12:53:58 -0700
committerKent Overstreet <kmo@daterainc.com>2014-03-15 14:22:03 -0700
commit530cda19ce88332b9c1f3590a19f56ce676c0933 (patch)
treebf7f4318100e9dad8550e99b9ccf7da45cd5db57
parentfd29f21e3d455efda90605a1c46b2b42baf54cca (diff)
selection improvements
-rw-r--r--st.c75
-rw-r--r--term.c47
-rw-r--r--term.h16
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);