From 2cfa99178a7dd61fb8dc1f06f51a4cb7a47d12b1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 17 Mar 2014 20:30:09 -0700 Subject: more selection work --- st.c | 110 ++++++++++++++++++++------------------------------------ term.c | 128 +++++++++++++++++++++++++++++++++++++++++------------------------ term.h | 9 +++-- 3 files changed, 126 insertions(+), 121 deletions(-) diff --git a/st.c b/st.c index bd8d2e2..1d29b9c 100644 --- a/st.c +++ b/st.c @@ -126,12 +126,12 @@ struct st_window { struct coord fixedsize; /* kill? */ struct coord charsize; - struct coord mousepos; - unsigned mousebutton; - struct timeval mousedown; + struct timeval mousedown_time; + struct coord mousedown_pos; struct timeval mouseup[3]; + unsigned sel_type; - unsigned mousemotion:1; + unsigned mousedown:1; unsigned visible:1; unsigned focused:1; }; @@ -276,7 +276,7 @@ static void clippaste(struct st_window *xw, const union st_arg *dummy) static void selclear(struct st_window *xw, XEvent *e) { - term_sel_start(&xw->term, SEL_NONE, ORIGIN); + term_sel_stop(&xw->term); } static void selrequest(struct st_window *xw, XEvent *e) @@ -720,77 +720,37 @@ static struct coord mouse_pos(struct st_window *xw, XEvent *ev) }; } -static void mousereport(struct st_window *xw, XEvent *ev) -{ - char buf[40]; - int button = ev->xbutton.button, state = ev->xbutton.state, len; - struct coord pos = mouse_pos(xw, ev); - - /* from urxvt */ - if (ev->xbutton.type == MotionNotify) { - if (!xw->term.mousemotion || - (pos.x == xw->mousepos.x && - pos.y == xw->mousepos.y)) - return; - - button = xw->mousebutton + 32; - xw->mousepos = pos; - } else if (!xw->term.mousesgr && - (ev->xbutton.type == ButtonRelease || - button == AnyButton)) { - button = 3; - } else { - button -= Button1; - if (button >= 3) - button += 64 - 3; - if (ev->xbutton.type == ButtonPress) { - xw->mousebutton = button; - xw->mousepos = pos; - } - } - - button += (state & ShiftMask ? 4 : 0) + - (state & Mod4Mask ? 8 : 0) + - (state & ControlMask ? 16 : 0); - - if (xw->term.mousesgr) - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - button, pos.x + 1, pos.y + 1, - ev->xbutton.type == - ButtonRelease ? 'm' : 'M'); - else if (pos.x < 223 && pos.y < 223) - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32 + button, 32 + pos.x + 1, 32 + pos.y + 1); - else - return; - - ttywrite(&xw->term, buf, len); -} - 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); + term_mousereport(term, mouse_pos(xw, ev), + ev->xbutton.type, + ev->xbutton.button, + ev->xbutton.state); return; } switch (ev->xbutton.button) { case Button1: - type = SEL_REGULAR; - state = ev->xbutton.state & ~Button1Mask; + gettimeofday(&xw->mousedown_time, NULL); + xw->mousedown_pos = mouse_pos(xw, ev); + xw->mousedown = 1; + + /* Clear previous selection */ + term_sel_stop(term); + + /* Get ready for another */ + xw->sel_type = SEL_REGULAR; for (unsigned i = 1; i < ARRAY_SIZE(selmasks); i++) - if (match(selmasks[i], state)) { - type = i; + if (match(selmasks[i], + ev->xbutton.state & ~Button1Mask)) { + xw->sel_type = i; break; } - xw->mousemotion = 1; - term_sel_start(term, type, mouse_pos(xw, ev)); - gettimeofday(&xw->mousedown, NULL); break; case Button4: ttywrite(term, "\031", 1); @@ -807,13 +767,16 @@ static void brelease(struct st_window *xw, XEvent *ev) struct st_selection *sel = &term->sel; if (term->mousebtn || term->mousemotion) { - mousereport(xw, ev); + term_mousereport(term, mouse_pos(xw, ev), + ev->xbutton.type, + ev->xbutton.button, + ev->xbutton.state); return; } switch (ev->xbutton.button) { case Button1: - xw->mousemotion = 0; + xw->mousedown = 0; memmove(xw->mouseup + 1, xw->mouseup, sizeof(struct timeval) * 2); @@ -821,16 +784,17 @@ static void brelease(struct st_window *xw, XEvent *ev) struct coord end = mouse_pos(xw, ev); - if (!(sel->start.x == end.x && - sel->start.y == end.y)) - term_sel_update(term, end); + if (!(xw->mousedown_pos.x == end.x && + xw->mousedown_pos.y == end.y)) + term_sel_update(term, xw->sel_type, + xw->mousedown_pos, end); else if (TIMEDIFF(xw->mouseup[0], xw->mouseup[2]) < - tripleclicktimeout) + 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) < + else if (TIMEDIFF(xw->mouseup[0], xw->mousedown_time) < doubleclicktimeout) term_sel_stop(term); @@ -848,12 +812,16 @@ static void bmotion(struct st_window *xw, XEvent *ev) struct st_term *term = &xw->term; if (term->mousebtn || term->mousemotion) { - mousereport(xw, ev); + term_mousereport(term, mouse_pos(xw, ev), + ev->xbutton.type, + ev->xbutton.button, + ev->xbutton.state); return; } - if (xw->mousemotion) - term_sel_update(term, mouse_pos(xw, ev)); + if (xw->mousedown) + term_sel_update(term, xw->sel_type, + xw->mousedown_pos, mouse_pos(xw, ev)); } /* Resizing code */ diff --git a/term.c b/term.c index ea31fca..4d0bdcd 100644 --- a/term.c +++ b/term.c @@ -1,10 +1,12 @@ /* See LICENSE for licence details. */ +#include #include #include #include #include #include #include +#include // XXX #include @@ -29,10 +31,10 @@ static void selscroll(struct st_term *term, int orig, int n) if (sel->type == SEL_NONE) return; - if (BETWEEN(sel->start.y, orig, term->bot) || - BETWEEN(sel->end.y, orig, term->bot)) { - if ((sel->start.y += n) > term->bot || - (sel->end.y += n) < term->top) { + if (BETWEEN(sel->p1.y, orig, term->bot) || + BETWEEN(sel->p2.y, orig, term->bot)) { + if ((sel->p1.y += n) > term->bot || + (sel->p2.y += n) < term->top) { sel->type = SEL_NONE; return; } @@ -41,25 +43,22 @@ static void selscroll(struct st_term *term, int orig, int n) case SEL_NONE: break; case SEL_REGULAR: - if (sel->start.y < term->top) { - sel->start.y = term->top; - sel->start.x = 0; + if (sel->p1.y < term->top) { + sel->p1.y = term->top; + sel->p1.x = 0; } - if (sel->end.y > term->bot) { - sel->end.y = term->bot; - sel->end.x = term->size.y; + if (sel->p2.y > term->bot) { + sel->p2.y = term->bot; + sel->p2.x = term->size.y; } break; case SEL_RECTANGULAR: - if (sel->start.y < term->top) - sel->start.y = term->top; - if (sel->end.y > term->bot) - sel->end.y = term->bot; + if (sel->p1.y < term->top) + sel->p1.y = term->top; + if (sel->p2.y > term->bot) + sel->p2.y = term->bot; break; }; - - sel->p1 = sel->start; - sel->p2 = sel->end; } } @@ -132,25 +131,17 @@ out: sel->clip = (char *) str; } -void term_sel_start(struct st_term *term, unsigned type, struct coord start) +void term_sel_update(struct st_term *term, unsigned type, + struct coord start, struct coord end) { struct st_selection *sel = &term->sel; - sel->type = type; - sel->start = sel->end = sel->p1 = sel->p2 = start; - - term->dirty = true; -} - -void term_sel_update(struct st_term *term, struct coord end) -{ - struct st_selection *sel = &term->sel; - - sel->p1 = sel->start; - sel->p2 = sel->end = end; + sel->p1 = start; + sel->p2 = end; switch (sel->type) { case SEL_NONE: + sel->type = type; break; case SEL_REGULAR: if (sel->p1.y > sel->p2.y || @@ -173,12 +164,6 @@ void term_sel_update(struct st_term *term, struct coord end) 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[] = "*.!?;=&#$%^[](){}<>"; @@ -188,30 +173,33 @@ static bool isword(unsigned c) void term_sel_word(struct st_term *term, struct coord pos) { - struct st_selection *sel = &term->sel; - - sel->start = pos; + struct coord start = pos; - while (sel->start.x && - isword(term_pos(term, sel->start)[-1].c)) - sel->start.x--; + while (start.x && + isword(term_pos(term, start)[-1].c)) + start.x--; while (pos.x < term->size.x - 1 && isword(term_pos(term, pos)[1].c)) pos.x++; - term_sel_update(term, pos); + term_sel_update(term, SEL_REGULAR, start, pos); } void term_sel_line(struct st_term *term, struct coord pos) { - struct st_selection *sel = &term->sel; + struct coord start = pos; - sel->start = pos; - sel->start.x = 0; + start.x = 0; pos.x = term->size.x - 1; - term_sel_update(term, pos); + term_sel_update(term, SEL_REGULAR, start, pos); +} + +void term_sel_stop(struct st_term *term) +{ + term->sel.type = SEL_NONE; + term->dirty = true; } /* Escape handling */ @@ -1365,6 +1353,52 @@ void term_read(struct st_term *term) memmove(term->cmdbuf, ptr, term->cmdbuflen); } +void term_mousereport(struct st_term *term, struct coord pos, + unsigned type, unsigned button, unsigned state) +{ + char buf[40]; + int len; + + /* from urxvt */ + if (type == MotionNotify) { + if (!term->mousemotion || + (pos.x == term->mousepos.x && + pos.y == term->mousepos.y)) + return; + + button = term->mousebutton + 32; + term->mousepos = pos; + } else if (!term->mousesgr && + (type == ButtonRelease || + button == AnyButton)) { + button = 3; + } else { + button -= Button1; + if (button >= 3) + button += 64 - 3; + if (type == ButtonPress) { + term->mousebutton = button; + term->mousepos = pos; + } + } + + button += (state & ShiftMask ? 4 : 0) + + (state & Mod4Mask ? 8 : 0) + + (state & ControlMask ? 16 : 0); + + if (term->mousesgr) + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + button, pos.x + 1, pos.y + 1, + type == ButtonRelease ? 'm' : 'M'); + else if (pos.x < 223 && pos.y < 223) + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32 + button, 32 + pos.x + 1, 32 + pos.y + 1); + else + return; + + ttywrite(term, buf, len); +} + /* Resize code */ static void ttyresize(struct st_term *term) diff --git a/term.h b/term.h index 33fab78..604db31 100644 --- a/term.h +++ b/term.h @@ -137,7 +137,6 @@ struct st_selection { SEL_RECTANGULAR, } type; - struct coord start, end; struct coord p1, p2; char *clip; @@ -180,6 +179,9 @@ struct st_term { unsigned mousesgr:1; unsigned numlock:1; + struct coord mousepos; + unsigned mousebutton; + int esc; /* escape state flags */ struct csi_escape csiescseq; struct str_escape strescseq; @@ -194,14 +196,15 @@ struct st_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_update(struct st_term *, unsigned, struct coord, 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_mousereport(struct st_term *, struct coord, + unsigned, unsigned, unsigned); void term_resize(struct st_term *term, struct coord size); void term_shutdown(struct st_term *term); -- cgit v1.2.3