diff --git a/file.c b/file.c index 9bea5179..4498ff10 100644 --- a/file.c +++ b/file.c @@ -361,7 +361,7 @@ file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata) size_t msglen; int fd = -1; u_int stream = file_next_stream++; - FILE *f; + FILE *f = NULL; size_t size; char buffer[BUFSIZ]; @@ -401,7 +401,6 @@ file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata) cf->error = EIO; goto done; } - fclose(f); goto done; } @@ -424,6 +423,8 @@ skip: return cf; done: + if (f != NULL) + fclose(f); file_fire_done(cf); return NULL; } diff --git a/format.c b/format.c index d17b9c66..cedb552b 100644 --- a/format.c +++ b/format.c @@ -4421,14 +4421,14 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt) l = xreallocarray(l, lsz, sizeof *l); } l[n++] = s; - } + } - qsort(l, n, sizeof *l, format_cmp_session); + qsort(l, n, sizeof *l, format_cmp_session); value = xcalloc(1, 1); valuelen = 1; - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { s = l[i]; format_log(es, "session loop: $%u", s->id); if (active != NULL && s->id == ft->c->session->id) @@ -4546,7 +4546,7 @@ format_loop_windows(struct format_expand_state *es, const char *fmt) l = xreallocarray(l, lsz, sizeof *l); } l[n++] = wl; - } + } if (sc->field != FORMAT_LOOP_BY_INDEX) qsort(l, n, sizeof *l, format_cmp_window); @@ -4645,9 +4645,9 @@ format_loop_panes(struct format_expand_state *es, const char *fmt) l = xreallocarray(l, lsz, sizeof *l); } l[n++] = wp; - } + } - qsort(l, n, sizeof *l, format_cmp_pane); + qsort(l, n, sizeof *l, format_cmp_pane); value = xcalloc(1, 1); valuelen = 1; @@ -4741,7 +4741,7 @@ format_loop_clients(struct format_expand_state *es, const char *fmt) l = xreallocarray(l, lsz, sizeof *l); } l[n++] = c; - } + } if (sc->field != FORMAT_LOOP_BY_INDEX) qsort(l, n, sizeof *l, format_cmp_client); @@ -4756,7 +4756,7 @@ format_loop_clients(struct format_expand_state *es, const char *fmt) } } - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { c = l[i]; format_log(es, "client loop: %s", c->name); if (i == n - 1) diff --git a/input.c b/input.c index 969f21d3..d418ae2a 100644 --- a/input.c +++ b/input.c @@ -747,6 +747,20 @@ input_table_compare(const void *key, const void *value) return (strcmp(ictx->interm_buf, entry->interm)); } +/* Stop UTF-8 and enter an invalid character. */ +static void +input_stop_utf8(struct input_ctx *ictx) +{ + struct screen_write_ctx *sctx = &ictx->ctx; + static struct utf8_data rc = { "\357\277\275", 3, 3, 1 }; + + if (ictx->utf8started) { + utf8_copy(&ictx->cell.cell.data, &rc); + screen_write_collect_add(sctx, &ictx->cell.cell); + } + ictx->utf8started = 0; +} + /* * Timer - if this expires then have been waiting for a terminator for too * long, so reset to ground. @@ -1144,7 +1158,7 @@ input_print(struct input_ctx *ictx) struct screen_write_ctx *sctx = &ictx->ctx; int set; - ictx->utf8started = 0; /* can't be valid UTF-8 */ + input_stop_utf8(ictx); /* can't be valid UTF-8 */ set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set; if (set == 1) @@ -1224,7 +1238,7 @@ input_c0_dispatch(struct input_ctx *ictx) u_int width; int has_content = 0; - ictx->utf8started = 0; /* can't be valid UTF-8 */ + input_stop_utf8(ictx); /* can't be valid UTF-8 */ log_debug("%s: '%c'", __func__, ictx->ch); @@ -2588,9 +2602,9 @@ input_top_bit_set(struct input_ctx *ictx) ictx->flags &= ~INPUT_LAST; if (!ictx->utf8started) { - if (utf8_open(ud, ictx->ch) != UTF8_MORE) - return (0); ictx->utf8started = 1; + if (utf8_open(ud, ictx->ch) != UTF8_MORE) + input_stop_utf8(ictx); return (0); } @@ -2598,7 +2612,7 @@ input_top_bit_set(struct input_ctx *ictx) case UTF8_MORE: return (0); case UTF8_ERROR: - ictx->utf8started = 0; + input_stop_utf8(ictx); return (0); case UTF8_DONE: break; diff --git a/key-bindings.c b/key-bindings.c index d334fe70..fb766a02 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -437,7 +437,6 @@ key_bindings_init(void) "bind -N 'Display window menu' < { display-menu -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU " }", "bind -N 'Display pane menu' > { display-menu -xP -yP -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", - /* Mouse button 1 down on pane. */ "bind -n MouseDown1Pane { select-pane -t=; send -M }", @@ -460,7 +459,7 @@ key_bindings_init(void) "bind -n MouseDrag1Border { resize-pane -M }", /* Mouse button 1 down on status line. */ - "bind -n MouseDown1Status { select-window -t= }", + "bind -n MouseDown1Status { switch-client -t= }", /* Mouse wheel down on status line. */ "bind -n WheelDownStatus { next-window }", diff --git a/menu.c b/menu.c index 871a8eb9..fd3a9fe4 100644 --- a/menu.c +++ b/menu.c @@ -298,6 +298,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) } } switch (event->key & ~KEYC_MASK_FLAGS) { + case KEYC_BTAB: case KEYC_UP: case 'k': if (old == -1) @@ -363,7 +364,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) name = menu->items[md->choice].name; if (md->choice != count - 1 && (name != NULL && *name != '-')) - i++; + i--; else if (md->choice == count - 1) break; } diff --git a/options-table.c b/options-table.c index 5b8a4eb6..160cd7ac 100644 --- a/options-table.c +++ b/options-table.c @@ -76,7 +76,7 @@ static const char *options_table_pane_border_indicators_list[] = { "off", "colour", "arrows", "both", NULL }; static const char *options_table_pane_border_lines_list[] = { - "single", "double", "heavy", "simple", "number", NULL + "single", "double", "heavy", "simple", "number", "spaces", NULL }; static const char *options_table_popup_border_lines_list[] = { "single", "double", "heavy", "simple", "rounded", "padded", "none", NULL @@ -173,10 +173,60 @@ static const char *options_table_allow_passthrough_list[] = { "#[pop-default]" \ "#[norange default]" #define OPTIONS_TABLE_STATUS_FORMAT2 \ - "#[align=centre]#{P:#{?pane_active,#[reverse],}" \ - "#{pane_index}[#{pane_width}x#{pane_height}]#[default] }" + "#[align=left]#{R: ,#{n:#{session_name}}}P: " \ + "#[norange default]" \ + "#[list=on align=#{status-justify}]" \ + "#[list=left-marker]<#[list=right-marker]>#[list=on]" \ + "#{P:" \ + "#[range=pane|#{pane_id} " \ + "#{E:pane-status-style}" \ + "]" \ + "#[push-default]" \ + "#P[#{pane_width}x#{pane_height}]" \ + "#[pop-default]" \ + "#[norange list=on default] " \ + "," \ + "#[range=pane|#{pane_id} list=focus " \ + "#{?#{!=:#{E:pane-status-current-style},default}," \ + "#{E:pane-status-current-style}," \ + "#{E:pane-status-style}" \ + "}" \ + "]" \ + "#[push-default]" \ + "#P[#{pane_width}x#{pane_height}]*" \ + "#[pop-default]" \ + "#[norange list=on default] " \ + "}" +#define OPTIONS_TABLE_STATUS_FORMAT3 \ + "#[align=left]#{R: ,#{n:#{session_name}}}S: " \ + "#[norange default]" \ + "#[list=on align=#{status-justify}]" \ + "#[list=left-marker]<#[list=right-marker]>#[list=on]" \ + "#{S:" \ + "#[range=session|#{session_id} " \ + "#{E:session-status-style}" \ + "]" \ + "#[push-default]" \ + "#S#{session_alert}" \ + "#[pop-default]" \ + "#[norange list=on default] " \ + "," \ + "#[range=session|#{session_id} list=focus " \ + "#{?#{!=:#{E:session-status-current-style},default}," \ + "#{E:session-status-current-style}," \ + "#{E:session-status-style}" \ + "}" \ + "]" \ + "#[push-default]" \ + "#S*#{session_alert}" \ + "#[pop-default]" \ + "#[norange list=on default] " \ + "}" static const char *options_table_status_format_default[] = { - OPTIONS_TABLE_STATUS_FORMAT1, OPTIONS_TABLE_STATUS_FORMAT2, NULL + OPTIONS_TABLE_STATUS_FORMAT1, + OPTIONS_TABLE_STATUS_FORMAT2, + OPTIONS_TABLE_STATUS_FORMAT3, + NULL }; /* Helpers for hook options. */ @@ -871,6 +921,25 @@ const struct options_table_entry options_table[] = { .text = "Style of the status line." }, + { .name = "pane-status-current-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Style of the current pane in the status line." + }, + + { .name = "pane-status-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Style of panes in the status line, except the current " + "pane." + }, + { .name = "prompt-cursor-colour", .type = OPTIONS_TABLE_COLOUR, .scope = OPTIONS_TABLE_SESSION, @@ -886,6 +955,25 @@ const struct options_table_entry options_table[] = { .text = "Style of the cursor when in the command prompt." }, + { .name = "session-status-current-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Style of the current session in the status line." + }, + + { .name = "session-status-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Style of sessions in the status line, except the current " + "session." + }, + { .name = "update-environment", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, diff --git a/popup.c b/popup.c index c2eaa3cc..2f02dbe8 100644 --- a/popup.c +++ b/popup.c @@ -348,6 +348,8 @@ popup_make_pane(struct popup_data *pd, enum layout_type type) window_unzoom(w, 1); lc = layout_split_pane(wp, type, -1, 0); + if (lc == NULL) + return; hlimit = options_get_number(s->options, "history-limit"); new_wp = window_add_pane(wp->window, NULL, hlimit, 0); layout_assign_pane(lc, new_wp, 0); diff --git a/screen-redraw.c b/screen-redraw.c index f9bef59e..96081839 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -87,6 +87,10 @@ screen_redraw_border_set(struct window *w, struct window_pane *wp, gc->attr &= ~GRID_ATTR_CHARSET; utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); break; + case PANE_LINES_SPACES: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, ' '); + break; default: gc->attr |= GRID_ATTR_CHARSET; utf8_set(&gc->data, CELL_BORDERS[cell_type]); diff --git a/server-client.c b/server-client.c index ae2e54f9..e9ef1e3c 100644 --- a/server-client.c +++ b/server-client.c @@ -880,8 +880,7 @@ have_event: m->wp = wp->id; m->w = wp->window->id; } - } else - m->wp = -1; + } /* Stop dragging if needed. */ if (type != DRAG && diff --git a/server.c b/server.c index 097bc70b..49cac8bb 100644 --- a/server.c +++ b/server.c @@ -70,7 +70,8 @@ server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp) cmd_find_clear_state(&marked_pane, 0); marked_pane.s = s; marked_pane.wl = wl; - marked_pane.w = wl->window; + if (wl != NULL) + marked_pane.w = wl->window; marked_pane.wp = wp; } diff --git a/tmux.1 b/tmux.1 index fec196ec..f4749d09 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5080,6 +5080,8 @@ heavy lines using UTF-8 characters simple ASCII characters .It number the pane number +.It spaces +space characters .El .Pp .Ql double @@ -5188,6 +5190,38 @@ Other attributes are ignored. .Xc Sets which side of the pane to display pane scrollbars on. .Pp +.It Ic pane-status-current-style Ar style +Set status line style for the currently active pane. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp +.It Ic pane-status-style Ar style +Set status line style for a single pane. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp +.It Ic session-status-current-style Ar style +Set status line style for the currently active session. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp +.It Ic session-status-style Ar style +Set status line style for a single session. +For how to specify +.Ar style , +see the +.Sx STYLES +section. +.Pp .It Ic window-status-activity-style Ar style Set status line style for windows with an activity alert. For how to specify diff --git a/tmux.h b/tmux.h index c996d5b9..589affd0 100644 --- a/tmux.h +++ b/tmux.h @@ -1025,7 +1025,8 @@ enum pane_lines { PANE_LINES_DOUBLE, PANE_LINES_HEAVY, PANE_LINES_SIMPLE, - PANE_LINES_NUMBER + PANE_LINES_NUMBER, + PANE_LINES_SPACES }; /* Pane border indicator option. */ diff --git a/window-tree.c b/window-tree.c index 0aca9b4f..89b5e648 100644 --- a/window-tree.c +++ b/window-tree.c @@ -859,9 +859,11 @@ window_tree_search(__unused void *modedata, void *itemdata, const char *ss) case WINDOW_TREE_PANE: if (s == NULL || wl == NULL || wp == NULL) break; - cmd = osdep_get_name(wp->fd, wp->tty); - if (cmd == NULL || *cmd == '\0') + cmd = get_proc_name(wp->fd, wp->tty); + if (cmd == NULL || *cmd == '\0') { + free(cmd); return (0); + } retval = (strstr(cmd, ss) != NULL); free(cmd); return (retval);