diff --git a/cfg.c b/cfg.c index 1153de67..bfcdaea4 100644 --- a/cfg.c +++ b/cfg.c @@ -31,6 +31,7 @@ struct cmd_q *cfg_cmd_q; int cfg_finished; int cfg_references; struct causelist cfg_causes; +struct client *cfg_client; int load_cfg(const char *path, struct cmd_q *cmdq, char **cause) @@ -127,6 +128,20 @@ cfg_default_done(unused struct cmd_q *cmdq) cmdq_free(cfg_cmd_q); cfg_cmd_q = NULL; + + if (cfg_client != NULL) { + /* + * The client command queue starts with client_exit set to 1 so + * only continue if not empty (that is, we have been delayed + * during configuration parsing for long enough that the + * MSG_COMMAND has arrived), else the client will exit before + * the MSG_COMMAND which might tell it not to. + */ + if (!TAILQ_EMPTY(&cfg_client->cmdq->queue)) + cmdq_continue(cfg_client->cmdq); + cfg_client->references--; + cfg_client = NULL; + } } void diff --git a/client.c b/client.c index d1a3b177..26c095c0 100644 --- a/client.c +++ b/client.c @@ -468,7 +468,7 @@ client_callback(unused int fd, short events, void *data) } if (events & EV_WRITE) { - if (msgbuf_write(&client_ibuf.w) < 0) + if (msgbuf_write(&client_ibuf.w) < 0 && errno != EAGAIN) goto lost_server; } diff --git a/mode-key.c b/mode-key.c index 1ed6d40b..dfa3fb28 100644 --- a/mode-key.c +++ b/mode-key.c @@ -292,6 +292,7 @@ const struct mode_key_entry mode_key_vi_copy[] = { { 'k', 0, MODEKEYCOPY_UP }, { 'l', 0, MODEKEYCOPY_RIGHT }, { 'n', 0, MODEKEYCOPY_SEARCHAGAIN }, + { 'o', 0, MODEKEYCOPY_OTHEREND }, { 't', 0, MODEKEYCOPY_JUMPTO }, { 'q', 0, MODEKEYCOPY_CANCEL }, { 'v', 0, MODEKEYCOPY_RECTANGLETOGGLE }, diff --git a/server-client.c b/server-client.c index cc18a96f..d3d70eab 100644 --- a/server-client.c +++ b/server-client.c @@ -155,8 +155,8 @@ server_client_lost(struct client *c) free(c->ttyname); free(c->term); - evbuffer_free (c->stdin_data); - evbuffer_free (c->stdout_data); + evbuffer_free(c->stdin_data); + evbuffer_free(c->stdout_data); if (c->stderr_data != c->stdout_data) evbuffer_free (c->stderr_data); @@ -222,7 +222,8 @@ server_client_callback(int fd, short events, void *data) return; if (fd == c->ibuf.fd) { - if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) < 0) + if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) < 0 && + errno != EAGAIN) goto client_lost; if (c->flags & CLIENT_BAD) { @@ -932,7 +933,10 @@ server_client_msg_command(struct client *c, struct imsg *imsg) } cmd_free_argv(argc, argv); - cmdq_run(c->cmdq, cmdlist); + if (c != cfg_client || cfg_finished) + cmdq_run(c->cmdq, cmdlist); + else + cmdq_append(c->cmdq, cmdlist); cmd_list_free(cmdlist); return; diff --git a/server.c b/server.c index bd28d517..f372de4f 100644 --- a/server.c +++ b/server.c @@ -169,6 +169,9 @@ server_start(int lockfd, char *lockfile) cfg_finished = 0; cfg_references = 1; ARRAY_INIT(&cfg_causes); + cfg_client = ARRAY_FIRST(&clients); + if (cfg_client != NULL) + cfg_client->references++; if (access(TMUX_CONF, R_OK) == 0) { if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1) { diff --git a/tmux.1 b/tmux.1 index 1eb02feb..1146faf8 100644 --- a/tmux.1 +++ b/tmux.1 @@ -874,6 +874,7 @@ The following keys are supported as appropriate for the mode: .It Li "Next space, end of word" Ta "E" Ta "" .It Li "Next word" Ta "w" Ta "" .It Li "Next word end" Ta "e" Ta "M-f" +.It Li "Other end of selection" Ta "o" Ta "" .It Li "Paste buffer" Ta "p" Ta "C-y" .It Li "Previous page" Ta "C-b" Ta "Page up" .It Li "Previous word" Ta "b" Ta "M-b" diff --git a/tmux.h b/tmux.h index 84ad1643..dbc2c491 100644 --- a/tmux.h +++ b/tmux.h @@ -557,6 +557,7 @@ enum mode_key_cmd { MODEKEYCOPY_NEXTSPACEEND, MODEKEYCOPY_NEXTWORD, MODEKEYCOPY_NEXTWORDEND, + MODEKEYCOPY_OTHEREND, MODEKEYCOPY_PREVIOUSPAGE, MODEKEYCOPY_PREVIOUSSPACE, MODEKEYCOPY_PREVIOUSWORD, @@ -1503,6 +1504,7 @@ extern struct cmd_q *cfg_cmd_q; extern int cfg_finished; extern int cfg_references; extern struct causelist cfg_causes; +extern struct client *cfg_client; int load_cfg(const char *, struct cmd_q *, char **); void cfg_default_done(struct cmd_q *); void cfg_show_causes(struct session *); diff --git a/tty.c b/tty.c index d5b1aec0..98f603f4 100644 --- a/tty.c +++ b/tty.c @@ -224,7 +224,7 @@ tty_start_tty(struct tty *tty) tty->flags |= TTY_FOCUS; tty_puts(tty, "\033[?1004h"); } - tty_puts(tty, "\033[c\033[>4;1m\033[m"); + tty_puts(tty, "\033[c"); } tty->cx = UINT_MAX; @@ -292,7 +292,6 @@ tty_stop_tty(struct tty *tty) tty->flags &= ~TTY_FOCUS; tty_puts(tty, "\033[?1004l"); } - tty_raw(tty, "\033[>4m\033[m"); } tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); diff --git a/window-copy.c b/window-copy.c index f690c7c4..37b65c87 100644 --- a/window-copy.c +++ b/window-copy.c @@ -18,6 +18,7 @@ #include +#include #include #include @@ -41,17 +42,17 @@ void window_copy_write_lines( void window_copy_scroll_to(struct window_pane *, u_int, u_int); int window_copy_search_compare( - struct grid *, u_int, u_int, struct grid *, u_int); + struct grid *, u_int, u_int, struct grid *, u_int, int); int window_copy_search_lr( - struct grid *, struct grid *, u_int *, u_int, u_int, u_int); + struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int); int window_copy_search_rl( - struct grid *, struct grid *, u_int *, u_int, u_int, u_int); + struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int); void window_copy_search_up(struct window_pane *, const char *); void window_copy_search_down(struct window_pane *, const char *); void window_copy_goto_line(struct window_pane *, const char *); void window_copy_update_cursor(struct window_pane *, u_int, u_int); void window_copy_start_selection(struct window_pane *); -int window_copy_update_selection(struct window_pane *); +int window_copy_update_selection(struct window_pane *, int); void *window_copy_get_selection(struct window_pane *, size_t *); void window_copy_copy_buffer(struct window_pane *, int, void *, size_t); void window_copy_copy_pipe( @@ -65,6 +66,7 @@ u_int window_copy_find_length(struct window_pane *, u_int); void window_copy_cursor_start_of_line(struct window_pane *); void window_copy_cursor_back_to_indentation(struct window_pane *); void window_copy_cursor_end_of_line(struct window_pane *); +void window_copy_other_end(struct window_pane *); void window_copy_cursor_left(struct window_pane *); void window_copy_cursor_right(struct window_pane *); void window_copy_cursor_up(struct window_pane *, int); @@ -328,7 +330,7 @@ window_copy_pageup(struct window_pane *wp) data->oy = screen_hsize(data->backing); else data->oy += n; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); } @@ -415,6 +417,10 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) case MODEKEYCOPY_CANCEL: window_pane_reset_mode(wp); return; + case MODEKEYCOPY_OTHEREND: + for (; np != 0; np--) + window_copy_other_end(wp); + break; case MODEKEYCOPY_LEFT: for (; np != 0; np--) window_copy_cursor_left(wp); @@ -453,7 +459,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) else data->oy -= n; } - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_HALFPAGEUP: @@ -464,7 +470,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) else data->oy += n; } - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_HALFPAGEDOWN: @@ -475,39 +481,39 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) else data->oy -= n; } - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_TOPLINE: data->cx = 0; data->cy = 0; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_MIDDLELINE: data->cx = 0; data->cy = (screen_size_y(s) - 1) / 2; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_BOTTOMLINE: data->cx = 0; data->cy = screen_size_y(s) - 1; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_HISTORYTOP: data->cx = 0; data->cy = 0; data->oy = screen_hsize(data->backing); - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_HISTORYBOTTOM: data->cx = 0; data->cy = screen_size_y(s) - 1; data->oy = 0; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); break; case MODEKEYCOPY_STARTSELECTION: @@ -860,7 +866,7 @@ window_copy_mouse( if (s->mode & MODE_MOUSE_BUTTON) { if (~m->event & MOUSE_EVENT_UP) { window_copy_update_cursor(wp, m->x, m->y); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_screen(wp); return; } @@ -910,13 +916,13 @@ window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py) } data->oy = gd->hsize - offset; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); } int window_copy_search_compare( - struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx) + struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx, int cis) { const struct grid_cell *gc, *sgc; struct utf8_data ud, sud; @@ -928,21 +934,28 @@ window_copy_search_compare( if (ud.size != sud.size || ud.width != sud.width) return (0); + + if (cis && ud.size == 1) + return (tolower(ud.data[0]) == sud.data[0]); + return (memcmp(ud.data, sud.data, ud.size) == 0); } int window_copy_search_lr(struct grid *gd, - struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last) + struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last, int cis) { u_int ax, bx, px; + int matched; for (ax = first; ax < last; ax++) { if (ax + sgd->sx >= gd->sx) break; for (bx = 0; bx < sgd->sx; bx++) { px = ax + bx; - if (!window_copy_search_compare(gd, px, py, sgd, bx)) + matched = window_copy_search_compare(gd, px, py, sgd, + bx, cis); + if (!matched) break; } if (bx == sgd->sx) { @@ -955,16 +968,19 @@ window_copy_search_lr(struct grid *gd, int window_copy_search_rl(struct grid *gd, - struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last) + struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last, int cis) { u_int ax, bx, px; + int matched; for (ax = last + 1; ax > first; ax--) { if (gd->sx - (ax - 1) < sgd->sx) continue; for (bx = 0; bx < sgd->sx; bx++) { px = ax - 1 + bx; - if (!window_copy_search_compare(gd, px, py, sgd, bx)) + matched = window_copy_search_compare(gd, px, py, sgd, + bx, cis); + if (!matched) break; } if (bx == sgd->sx) { @@ -985,7 +1001,8 @@ window_copy_search_up(struct window_pane *wp, const char *searchstr) struct grid_cell gc; size_t searchlen; u_int i, last, fx, fy, px; - int utf8flag, n, wrapped, wrapflag; + int utf8flag, n, wrapped, wrapflag, cis; + const char *ptr; if (*searchstr == '\0') return; @@ -1011,13 +1028,21 @@ window_copy_search_up(struct window_pane *wp, const char *searchstr) fx--; n = wrapped = 0; + cis = 1; + for (ptr = searchstr; *ptr != '\0'; ptr++) { + if (*ptr != tolower(*ptr)) { + cis = 0; + break; + } + } + retry: sgd = ss.grid; for (i = fy + 1; i > 0; i--) { last = screen_size_x(s); if (i == fy + 1) last = fx; - n = window_copy_search_rl(gd, sgd, &px, i - 1, 0, last); + n = window_copy_search_rl(gd, sgd, &px, i - 1, 0, last, cis); if (n) { window_copy_scroll_to(wp, px, i - 1); break; @@ -1043,7 +1068,8 @@ window_copy_search_down(struct window_pane *wp, const char *searchstr) struct grid_cell gc; size_t searchlen; u_int i, first, fx, fy, px; - int utf8flag, n, wrapped, wrapflag; + int utf8flag, n, wrapped, wrapflag, cis; + const char *ptr; if (*searchstr == '\0') return; @@ -1069,13 +1095,22 @@ window_copy_search_down(struct window_pane *wp, const char *searchstr) fx++; n = wrapped = 0; + cis = 1; + for (ptr = searchstr; *ptr != '\0'; ptr++) { + if (*ptr != tolower(*ptr)) { + cis = 0; + break; + } + } + retry: sgd = ss.grid; for (i = fy + 1; i < gd->hsize + gd->sy + 1; i++) { first = 0; if (i == fy + 1) first = fx; - n = window_copy_search_lr(gd, sgd, &px, i - 1, first, gd->sx); + n = window_copy_search_lr(gd, sgd, &px, i - 1, first, gd->sx, + cis); if (n) { window_copy_scroll_to(wp, px, i - 1); break; @@ -1103,7 +1138,7 @@ window_copy_goto_line(struct window_pane *wp, const char *linestr) return; data->oy = lineno; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); } @@ -1216,11 +1251,11 @@ window_copy_start_selection(struct window_pane *wp) data->sely = screen_hsize(data->backing) + data->cy - data->oy; s->sel.flag = 1; - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); } int -window_copy_update_selection(struct window_pane *wp) +window_copy_update_selection(struct window_pane *wp, int may_redraw) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; @@ -1255,7 +1290,7 @@ window_copy_update_selection(struct window_pane *wp) screen_set_selection(s, sx, sy, data->cx, screen_hsize(s) + data->cy, data->rectflag, &gc); - if (data->rectflag) { + if (data->rectflag && may_redraw) { /* * Can't rely on the caller to redraw the right lines for * rectangle selection - find the highest line and the number @@ -1559,7 +1594,7 @@ window_copy_cursor_start_of_line(struct window_pane *wp) } } window_copy_update_cursor(wp, 0, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } @@ -1584,7 +1619,7 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp) } window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } @@ -1614,10 +1649,43 @@ window_copy_cursor_end_of_line(struct window_pane *wp) } window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } +void +window_copy_other_end(struct window_pane *wp) +{ + struct window_copy_mode_data *data = wp->modedata; + struct screen *s = &data->screen; + u_int selx, sely, cx, cy, yy; + + if (!s->sel.flag) + return; + + selx = data->selx; + sely = data->sely; + cx = data->cx; + cy = data->cy; + yy = screen_hsize(data->backing) + data->cy - data->oy; + + data->selx = cx; + data->sely = yy; + data->cx = selx; + + if (sely < screen_hsize(data->backing) - data->oy) { + data->oy = screen_hsize(data->backing) - sely; + data->cy = 0; + } else if (sely > screen_hsize(data->backing) - data->oy + screen_size_y(s)) { + data->oy = screen_hsize(data->backing) - sely + screen_size_y(s) - 1; + data->cy = screen_size_y(s) - 1; + + } else + data->cy = cy + sely - yy; + + window_copy_redraw_screen(wp); +} + void window_copy_cursor_left(struct window_pane *wp) { @@ -1628,7 +1696,7 @@ window_copy_cursor_left(struct window_pane *wp) window_copy_cursor_end_of_line(wp); } else { window_copy_update_cursor(wp, data->cx - 1, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } } @@ -1651,7 +1719,7 @@ window_copy_cursor_right(struct window_pane *wp) window_copy_cursor_down(wp, 0); } else { window_copy_update_cursor(wp, data->cx + 1, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } } @@ -1681,7 +1749,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only) } } else { window_copy_update_cursor(wp, data->cx, data->cy - 1); - if (window_copy_update_selection(wp)) { + if (window_copy_update_selection(wp, 1)) { if (data->cy == screen_size_y(s) - 1) window_copy_redraw_lines(wp, data->cy, 1); else @@ -1719,7 +1787,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only) window_copy_redraw_lines(wp, data->cy - 1, 2); } else { window_copy_update_cursor(wp, data->cx, data->cy + 1); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy - 1, 2); } @@ -1751,7 +1819,7 @@ window_copy_cursor_jump(struct window_pane *wp) if (!(gc->flags & GRID_FLAG_PADDING) && ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); return; } @@ -1780,7 +1848,7 @@ window_copy_cursor_jump_back(struct window_pane *wp) if (!(gc->flags & GRID_FLAG_PADDING) && ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); return; } @@ -1809,7 +1877,7 @@ window_copy_cursor_jump_to(struct window_pane *wp) if (!(gc->flags & GRID_FLAG_PADDING) && ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px - 1, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); return; } @@ -1838,7 +1906,7 @@ window_copy_cursor_jump_to_back(struct window_pane *wp) if (!(gc->flags & GRID_FLAG_PADDING) && ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px + 1, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); return; } @@ -1886,7 +1954,7 @@ window_copy_cursor_next_word(struct window_pane *wp, const char *separators) } while (expected == 1); window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } @@ -1936,7 +2004,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators) px--; window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } @@ -1974,7 +2042,7 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators) out: window_copy_update_cursor(wp, px, data->cy); - if (window_copy_update_selection(wp)) + if (window_copy_update_selection(wp, 1)) window_copy_redraw_lines(wp, data->cy, 1); } @@ -1991,6 +2059,8 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny) return; data->oy -= ny; + window_copy_update_selection(wp, 0); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_deleteline(&ctx, ny); @@ -2000,12 +2070,9 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny) window_copy_write_line(wp, &ctx, 1); if (screen_size_y(s) > 3) window_copy_write_line(wp, &ctx, screen_size_y(s) - 2); - if (s->sel.flag && screen_size_y(s) > ny) { - window_copy_update_selection(wp); + if (s->sel.flag && screen_size_y(s) > ny) window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1); - } screen_write_cursormove(&ctx, data->cx, data->cy); - window_copy_update_selection(wp); screen_write_stop(&ctx); } @@ -2025,17 +2092,17 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny) return; data->oy += ny; + window_copy_update_selection(wp, 0); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, ny); window_copy_write_lines(wp, &ctx, 0, ny); - if (s->sel.flag && screen_size_y(s) > ny) { - window_copy_update_selection(wp); + if (s->sel.flag && screen_size_y(s) > ny) window_copy_write_line(wp, &ctx, ny); - } else if (ny == 1) /* nuke position */ + else if (ny == 1) /* nuke position */ window_copy_write_line(wp, &ctx, 1); screen_write_cursormove(&ctx, data->cx, data->cy); - window_copy_update_selection(wp); screen_write_stop(&ctx); } @@ -2052,6 +2119,6 @@ window_copy_rectangle_toggle(struct window_pane *wp) if (data->cx > px) window_copy_update_cursor(wp, px, data->cy); - window_copy_update_selection(wp); + window_copy_update_selection(wp, 1); window_copy_redraw_screen(wp); }