19fb66d81Schristos /* $OpenBSD$ */
29fb66d81Schristos
39fb66d81Schristos /*
49fb66d81Schristos * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
59fb66d81Schristos *
69fb66d81Schristos * Permission to use, copy, modify, and distribute this software for any
79fb66d81Schristos * purpose with or without fee is hereby granted, provided that the above
89fb66d81Schristos * copyright notice and this permission notice appear in all copies.
99fb66d81Schristos *
109fb66d81Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
119fb66d81Schristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
129fb66d81Schristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
139fb66d81Schristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
149fb66d81Schristos * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
159fb66d81Schristos * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
169fb66d81Schristos * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
179fb66d81Schristos */
189fb66d81Schristos
199fb66d81Schristos #include <sys/types.h>
209fb66d81Schristos
219fb66d81Schristos #include <ctype.h>
229fb66d81Schristos #include <stdlib.h>
239fb66d81Schristos #include <string.h>
249fb66d81Schristos
259fb66d81Schristos #include "tmux.h"
269fb66d81Schristos
279fb66d81Schristos static struct screen *window_customize_init(struct window_mode_entry *,
289fb66d81Schristos struct cmd_find_state *, struct args *);
299fb66d81Schristos static void window_customize_free(struct window_mode_entry *);
309fb66d81Schristos static void window_customize_resize(struct window_mode_entry *,
319fb66d81Schristos u_int, u_int);
329fb66d81Schristos static void window_customize_key(struct window_mode_entry *,
339fb66d81Schristos struct client *, struct session *,
349fb66d81Schristos struct winlink *, key_code, struct mouse_event *);
359fb66d81Schristos
369fb66d81Schristos #define WINDOW_CUSTOMIZE_DEFAULT_FORMAT \
379fb66d81Schristos "#{?is_option," \
389fb66d81Schristos "#{?option_is_global,,#[reverse](#{option_scope})#[default] }" \
399fb66d81Schristos "#[ignore]" \
409fb66d81Schristos "#{option_value}#{?option_unit, #{option_unit},}" \
419fb66d81Schristos "," \
429fb66d81Schristos "#{key}" \
439fb66d81Schristos "}"
449fb66d81Schristos
459fb66d81Schristos static const struct menu_item window_customize_menu_items[] = {
469fb66d81Schristos { "Select", '\r', NULL },
479fb66d81Schristos { "Expand", KEYC_RIGHT, NULL },
489fb66d81Schristos { "", KEYC_NONE, NULL },
499fb66d81Schristos { "Tag", 't', NULL },
509fb66d81Schristos { "Tag All", '\024', NULL },
519fb66d81Schristos { "Tag None", 'T', NULL },
529fb66d81Schristos { "", KEYC_NONE, NULL },
539fb66d81Schristos { "Cancel", 'q', NULL },
549fb66d81Schristos
559fb66d81Schristos { NULL, KEYC_NONE, NULL }
569fb66d81Schristos };
579fb66d81Schristos
589fb66d81Schristos const struct window_mode window_customize_mode = {
599fb66d81Schristos .name = "options-mode",
609fb66d81Schristos .default_format = WINDOW_CUSTOMIZE_DEFAULT_FORMAT,
619fb66d81Schristos
629fb66d81Schristos .init = window_customize_init,
639fb66d81Schristos .free = window_customize_free,
649fb66d81Schristos .resize = window_customize_resize,
659fb66d81Schristos .key = window_customize_key,
669fb66d81Schristos };
679fb66d81Schristos
689fb66d81Schristos enum window_customize_scope {
699fb66d81Schristos WINDOW_CUSTOMIZE_NONE,
709fb66d81Schristos WINDOW_CUSTOMIZE_KEY,
719fb66d81Schristos WINDOW_CUSTOMIZE_SERVER,
729fb66d81Schristos WINDOW_CUSTOMIZE_GLOBAL_SESSION,
739fb66d81Schristos WINDOW_CUSTOMIZE_SESSION,
749fb66d81Schristos WINDOW_CUSTOMIZE_GLOBAL_WINDOW,
759fb66d81Schristos WINDOW_CUSTOMIZE_WINDOW,
769fb66d81Schristos WINDOW_CUSTOMIZE_PANE
779fb66d81Schristos };
789fb66d81Schristos
799fb66d81Schristos enum window_customize_change {
809fb66d81Schristos WINDOW_CUSTOMIZE_UNSET,
819fb66d81Schristos WINDOW_CUSTOMIZE_RESET,
829fb66d81Schristos };
839fb66d81Schristos
849fb66d81Schristos struct window_customize_itemdata {
859fb66d81Schristos struct window_customize_modedata *data;
869fb66d81Schristos enum window_customize_scope scope;
879fb66d81Schristos
889fb66d81Schristos char *table;
899fb66d81Schristos key_code key;
909fb66d81Schristos
919fb66d81Schristos struct options *oo;
929fb66d81Schristos char *name;
939fb66d81Schristos int idx;
949fb66d81Schristos };
959fb66d81Schristos
969fb66d81Schristos struct window_customize_modedata {
979fb66d81Schristos struct window_pane *wp;
989fb66d81Schristos int dead;
999fb66d81Schristos int references;
1009fb66d81Schristos
1019fb66d81Schristos struct mode_tree_data *data;
1029fb66d81Schristos char *format;
1039fb66d81Schristos int hide_global;
1049fb66d81Schristos
1059fb66d81Schristos struct window_customize_itemdata **item_list;
1069fb66d81Schristos u_int item_size;
1079fb66d81Schristos
1089fb66d81Schristos struct cmd_find_state fs;
1099fb66d81Schristos enum window_customize_change change;
1109fb66d81Schristos };
1119fb66d81Schristos
1129fb66d81Schristos static uint64_t
window_customize_get_tag(struct options_entry * o,int idx,const struct options_table_entry * oe)1139fb66d81Schristos window_customize_get_tag(struct options_entry *o, int idx,
1149fb66d81Schristos const struct options_table_entry *oe)
1159fb66d81Schristos {
1169fb66d81Schristos uint64_t offset;
1179fb66d81Schristos
1189fb66d81Schristos if (oe == NULL)
119c745c111Schristos return ((uintptr_t)o);
120e271dbb8Schristos offset = ((const char *)oe - (const char *)options_table) / sizeof *options_table;
1219fb66d81Schristos return ((2ULL << 62)|(offset << 32)|((idx + 1) << 1)|1);
1229fb66d81Schristos }
1239fb66d81Schristos
1249fb66d81Schristos static struct options *
window_customize_get_tree(enum window_customize_scope scope,struct cmd_find_state * fs)1259fb66d81Schristos window_customize_get_tree(enum window_customize_scope scope,
1269fb66d81Schristos struct cmd_find_state *fs)
1279fb66d81Schristos {
1289fb66d81Schristos switch (scope) {
1299fb66d81Schristos case WINDOW_CUSTOMIZE_NONE:
1309fb66d81Schristos case WINDOW_CUSTOMIZE_KEY:
1319fb66d81Schristos return (NULL);
1329fb66d81Schristos case WINDOW_CUSTOMIZE_SERVER:
1339fb66d81Schristos return (global_options);
1349fb66d81Schristos case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
1359fb66d81Schristos return (global_s_options);
1369fb66d81Schristos case WINDOW_CUSTOMIZE_SESSION:
1379fb66d81Schristos return (fs->s->options);
1389fb66d81Schristos case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
1399fb66d81Schristos return (global_w_options);
1409fb66d81Schristos case WINDOW_CUSTOMIZE_WINDOW:
1419fb66d81Schristos return (fs->w->options);
1429fb66d81Schristos case WINDOW_CUSTOMIZE_PANE:
1439fb66d81Schristos return (fs->wp->options);
1449fb66d81Schristos }
1459fb66d81Schristos return (NULL);
1469fb66d81Schristos }
1479fb66d81Schristos
1489fb66d81Schristos static int
window_customize_check_item(struct window_customize_modedata * data,struct window_customize_itemdata * item,struct cmd_find_state * fsp)1499fb66d81Schristos window_customize_check_item(struct window_customize_modedata *data,
1509fb66d81Schristos struct window_customize_itemdata *item, struct cmd_find_state *fsp)
1519fb66d81Schristos {
1529fb66d81Schristos struct cmd_find_state fs;
1539fb66d81Schristos
1549fb66d81Schristos if (fsp == NULL)
1559fb66d81Schristos fsp = &fs;
1569fb66d81Schristos
1579fb66d81Schristos if (cmd_find_valid_state(&data->fs))
1589fb66d81Schristos cmd_find_copy_state(fsp, &data->fs);
1599fb66d81Schristos else
1609fb66d81Schristos cmd_find_from_pane(fsp, data->wp, 0);
1619fb66d81Schristos return (item->oo == window_customize_get_tree(item->scope, fsp));
1629fb66d81Schristos }
1639fb66d81Schristos
1649fb66d81Schristos static int
window_customize_get_key(struct window_customize_itemdata * item,struct key_table ** ktp,struct key_binding ** bdp)1659fb66d81Schristos window_customize_get_key(struct window_customize_itemdata *item,
1669fb66d81Schristos struct key_table **ktp, struct key_binding **bdp)
1679fb66d81Schristos {
1689fb66d81Schristos struct key_table *kt;
1699fb66d81Schristos struct key_binding *bd;
1709fb66d81Schristos
1719fb66d81Schristos kt = key_bindings_get_table(item->table, 0);
1729fb66d81Schristos if (kt == NULL)
1739fb66d81Schristos return (0);
1749fb66d81Schristos bd = key_bindings_get(kt, item->key);
1759fb66d81Schristos if (bd == NULL)
1769fb66d81Schristos return (0);
1779fb66d81Schristos
1789fb66d81Schristos if (ktp != NULL)
1799fb66d81Schristos *ktp = kt;
1809fb66d81Schristos if (bdp != NULL)
1819fb66d81Schristos *bdp = bd;
1829fb66d81Schristos return (1);
1839fb66d81Schristos }
1849fb66d81Schristos
1859fb66d81Schristos static char *
window_customize_scope_text(enum window_customize_scope scope,struct cmd_find_state * fs)1869fb66d81Schristos window_customize_scope_text(enum window_customize_scope scope,
1879fb66d81Schristos struct cmd_find_state *fs)
1889fb66d81Schristos {
1899fb66d81Schristos char *s;
1909fb66d81Schristos u_int idx;
1919fb66d81Schristos
1929fb66d81Schristos switch (scope) {
1939fb66d81Schristos case WINDOW_CUSTOMIZE_PANE:
1949fb66d81Schristos window_pane_index(fs->wp, &idx);
1959fb66d81Schristos xasprintf(&s, "pane %u", idx);
1969fb66d81Schristos break;
1979fb66d81Schristos case WINDOW_CUSTOMIZE_SESSION:
1989fb66d81Schristos xasprintf(&s, "session %s", fs->s->name);
1999fb66d81Schristos break;
2009fb66d81Schristos case WINDOW_CUSTOMIZE_WINDOW:
2019fb66d81Schristos xasprintf(&s, "window %u", fs->wl->idx);
2029fb66d81Schristos break;
2039fb66d81Schristos default:
2049fb66d81Schristos s = xstrdup("");
2059fb66d81Schristos break;
2069fb66d81Schristos }
2079fb66d81Schristos return (s);
2089fb66d81Schristos }
2099fb66d81Schristos
2109fb66d81Schristos static struct window_customize_itemdata *
window_customize_add_item(struct window_customize_modedata * data)2119fb66d81Schristos window_customize_add_item(struct window_customize_modedata *data)
2129fb66d81Schristos {
2139fb66d81Schristos struct window_customize_itemdata *item;
2149fb66d81Schristos
2159fb66d81Schristos data->item_list = xreallocarray(data->item_list, data->item_size + 1,
2169fb66d81Schristos sizeof *data->item_list);
2179fb66d81Schristos item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
2189fb66d81Schristos return (item);
2199fb66d81Schristos }
2209fb66d81Schristos
2219fb66d81Schristos static void
window_customize_free_item(struct window_customize_itemdata * item)2229fb66d81Schristos window_customize_free_item(struct window_customize_itemdata *item)
2239fb66d81Schristos {
2249fb66d81Schristos free(item->table);
2259fb66d81Schristos free(item->name);
2269fb66d81Schristos free(item);
2279fb66d81Schristos }
2289fb66d81Schristos
2299fb66d81Schristos static void
window_customize_build_array(struct window_customize_modedata * data,struct mode_tree_item * top,enum window_customize_scope scope,struct options_entry * o,struct format_tree * ft)2309fb66d81Schristos window_customize_build_array(struct window_customize_modedata *data,
2319fb66d81Schristos struct mode_tree_item *top, enum window_customize_scope scope,
2329fb66d81Schristos struct options_entry *o, struct format_tree *ft)
2339fb66d81Schristos {
2349fb66d81Schristos const struct options_table_entry *oe = options_table_entry(o);
2359fb66d81Schristos struct options *oo = options_owner(o);
2369fb66d81Schristos struct window_customize_itemdata *item;
2379fb66d81Schristos struct options_array_item *ai;
2389fb66d81Schristos char *name, *value, *text;
2399fb66d81Schristos u_int idx;
2409fb66d81Schristos uint64_t tag;
2419fb66d81Schristos
2429fb66d81Schristos ai = options_array_first(o);
2439fb66d81Schristos while (ai != NULL) {
2449fb66d81Schristos idx = options_array_item_index(ai);
2459fb66d81Schristos
2469fb66d81Schristos xasprintf(&name, "%s[%u]", options_name(o), idx);
2479fb66d81Schristos format_add(ft, "option_name", "%s", name);
2489fb66d81Schristos value = options_to_string(o, idx, 0);
2499fb66d81Schristos format_add(ft, "option_value", "%s", value);
2509fb66d81Schristos
2519fb66d81Schristos item = window_customize_add_item(data);
2529fb66d81Schristos item->scope = scope;
2539fb66d81Schristos item->oo = oo;
2549fb66d81Schristos item->name = xstrdup(options_name(o));
2559fb66d81Schristos item->idx = idx;
2569fb66d81Schristos
2579fb66d81Schristos text = format_expand(ft, data->format);
2589fb66d81Schristos tag = window_customize_get_tag(o, idx, oe);
2599fb66d81Schristos mode_tree_add(data->data, top, item, tag, name, text, -1);
2609fb66d81Schristos free(text);
2619fb66d81Schristos
2629fb66d81Schristos free(name);
2639fb66d81Schristos free(value);
2649fb66d81Schristos
2659fb66d81Schristos ai = options_array_next(ai);
2669fb66d81Schristos }
2679fb66d81Schristos }
2689fb66d81Schristos
2699fb66d81Schristos static void
window_customize_build_option(struct window_customize_modedata * data,struct mode_tree_item * top,enum window_customize_scope scope,struct options_entry * o,struct format_tree * ft,const char * filter,struct cmd_find_state * fs)2709fb66d81Schristos window_customize_build_option(struct window_customize_modedata *data,
2719fb66d81Schristos struct mode_tree_item *top, enum window_customize_scope scope,
2729fb66d81Schristos struct options_entry *o, struct format_tree *ft,
2739fb66d81Schristos const char *filter, struct cmd_find_state *fs)
2749fb66d81Schristos {
2759fb66d81Schristos const struct options_table_entry *oe = options_table_entry(o);
2769fb66d81Schristos struct options *oo = options_owner(o);
2779fb66d81Schristos const char *name = options_name(o);
2789fb66d81Schristos struct window_customize_itemdata *item;
2799fb66d81Schristos char *text, *expanded, *value;
2809fb66d81Schristos int global = 0, array = 0;
2819fb66d81Schristos uint64_t tag;
2829fb66d81Schristos
2839fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_HOOK))
2849fb66d81Schristos return;
2859fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY))
2869fb66d81Schristos array = 1;
2879fb66d81Schristos
2889fb66d81Schristos if (scope == WINDOW_CUSTOMIZE_SERVER ||
2899fb66d81Schristos scope == WINDOW_CUSTOMIZE_GLOBAL_SESSION ||
2909fb66d81Schristos scope == WINDOW_CUSTOMIZE_GLOBAL_WINDOW)
2919fb66d81Schristos global = 1;
2929fb66d81Schristos if (data->hide_global && global)
2939fb66d81Schristos return;
2949fb66d81Schristos
2959fb66d81Schristos format_add(ft, "option_name", "%s", name);
2969fb66d81Schristos format_add(ft, "option_is_global", "%d", global);
2979fb66d81Schristos format_add(ft, "option_is_array", "%d", array);
2989fb66d81Schristos
2999fb66d81Schristos text = window_customize_scope_text(scope, fs);
3009fb66d81Schristos format_add(ft, "option_scope", "%s", text);
3019fb66d81Schristos free(text);
3029fb66d81Schristos
3039fb66d81Schristos if (oe != NULL && oe->unit != NULL)
3049fb66d81Schristos format_add(ft, "option_unit", "%s", oe->unit);
3059fb66d81Schristos else
3069fb66d81Schristos format_add(ft, "option_unit", "%s", "");
3079fb66d81Schristos
3089fb66d81Schristos if (!array) {
3099fb66d81Schristos value = options_to_string(o, -1, 0);
3109fb66d81Schristos format_add(ft, "option_value", "%s", value);
3119fb66d81Schristos free(value);
3129fb66d81Schristos }
3139fb66d81Schristos
3149fb66d81Schristos if (filter != NULL) {
3159fb66d81Schristos expanded = format_expand(ft, filter);
3169fb66d81Schristos if (!format_true(expanded)) {
3179fb66d81Schristos free(expanded);
3189fb66d81Schristos return;
3199fb66d81Schristos }
3209fb66d81Schristos free(expanded);
3219fb66d81Schristos }
3229fb66d81Schristos item = window_customize_add_item(data);
3239fb66d81Schristos item->oo = oo;
3249fb66d81Schristos item->scope = scope;
3259fb66d81Schristos item->name = xstrdup(name);
3269fb66d81Schristos item->idx = -1;
3279fb66d81Schristos
3289fb66d81Schristos if (array)
3299fb66d81Schristos text = NULL;
3309fb66d81Schristos else
3319fb66d81Schristos text = format_expand(ft, data->format);
3329fb66d81Schristos tag = window_customize_get_tag(o, -1, oe);
3339fb66d81Schristos top = mode_tree_add(data->data, top, item, tag, name, text, 0);
3349fb66d81Schristos free(text);
3359fb66d81Schristos
3369fb66d81Schristos if (array)
3379fb66d81Schristos window_customize_build_array(data, top, scope, o, ft);
3389fb66d81Schristos }
3399fb66d81Schristos
3409fb66d81Schristos static void
window_customize_find_user_options(struct options * oo,const char *** list,u_int * size)3419fb66d81Schristos window_customize_find_user_options(struct options *oo, const char ***list,
3429fb66d81Schristos u_int *size)
3439fb66d81Schristos {
3449fb66d81Schristos struct options_entry *o;
3459fb66d81Schristos const char *name;
3469fb66d81Schristos u_int i;
3479fb66d81Schristos
3489fb66d81Schristos o = options_first(oo);
3499fb66d81Schristos while (o != NULL) {
3509fb66d81Schristos name = options_name(o);
3519fb66d81Schristos if (*name != '@') {
3529fb66d81Schristos o = options_next(o);
3539fb66d81Schristos continue;
3549fb66d81Schristos }
3559fb66d81Schristos for (i = 0; i < *size; i++) {
3569fb66d81Schristos if (strcmp((*list)[i], name) == 0)
3579fb66d81Schristos break;
3589fb66d81Schristos }
3599fb66d81Schristos if (i != *size) {
3609fb66d81Schristos o = options_next(o);
3619fb66d81Schristos continue;
3629fb66d81Schristos }
3639fb66d81Schristos *list = xreallocarray(*list, (*size) + 1, sizeof **list);
3649fb66d81Schristos (*list)[(*size)++] = name;
3659fb66d81Schristos
3669fb66d81Schristos o = options_next(o);
3679fb66d81Schristos }
3689fb66d81Schristos }
3699fb66d81Schristos
3709fb66d81Schristos static void
window_customize_build_options(struct window_customize_modedata * data,const char * title,uint64_t tag,enum window_customize_scope scope0,struct options * oo0,enum window_customize_scope scope1,struct options * oo1,enum window_customize_scope scope2,struct options * oo2,struct format_tree * ft,const char * filter,struct cmd_find_state * fs)3719fb66d81Schristos window_customize_build_options(struct window_customize_modedata *data,
3729fb66d81Schristos const char *title, uint64_t tag,
3739fb66d81Schristos enum window_customize_scope scope0, struct options *oo0,
3749fb66d81Schristos enum window_customize_scope scope1, struct options *oo1,
3759fb66d81Schristos enum window_customize_scope scope2, struct options *oo2,
3769fb66d81Schristos struct format_tree *ft, const char *filter, struct cmd_find_state *fs)
3779fb66d81Schristos {
3789fb66d81Schristos struct mode_tree_item *top;
3799fb66d81Schristos struct options_entry *o = NULL, *loop;
3809fb66d81Schristos const char **list = NULL, *name;
3819fb66d81Schristos u_int size = 0, i;
3829fb66d81Schristos enum window_customize_scope scope;
3839fb66d81Schristos
3849fb66d81Schristos top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
3859fb66d81Schristos mode_tree_no_tag(top);
3869fb66d81Schristos
3879fb66d81Schristos /*
3889fb66d81Schristos * We get the options from the first tree, but build it using the
3899fb66d81Schristos * values from the other two. Any tree can have user options so we need
3909fb66d81Schristos * to build a separate list of them.
3919fb66d81Schristos */
3929fb66d81Schristos
3939fb66d81Schristos window_customize_find_user_options(oo0, &list, &size);
3949fb66d81Schristos if (oo1 != NULL)
3959fb66d81Schristos window_customize_find_user_options(oo1, &list, &size);
3969fb66d81Schristos if (oo2 != NULL)
3979fb66d81Schristos window_customize_find_user_options(oo2, &list, &size);
3989fb66d81Schristos
3999fb66d81Schristos for (i = 0; i < size; i++) {
4009fb66d81Schristos if (oo2 != NULL)
401*46548964Swiz o = options_get(oo2, list[i]);
4029fb66d81Schristos if (o == NULL && oo1 != NULL)
4039fb66d81Schristos o = options_get(oo1, list[i]);
4049fb66d81Schristos if (o == NULL)
405*46548964Swiz o = options_get(oo0, list[i]);
4069fb66d81Schristos if (options_owner(o) == oo2)
4079fb66d81Schristos scope = scope2;
4089fb66d81Schristos else if (options_owner(o) == oo1)
4099fb66d81Schristos scope = scope1;
4109fb66d81Schristos else
4119fb66d81Schristos scope = scope0;
4129fb66d81Schristos window_customize_build_option(data, top, scope, o, ft, filter,
4139fb66d81Schristos fs);
4149fb66d81Schristos }
4159fb66d81Schristos free(list);
4169fb66d81Schristos
4179fb66d81Schristos loop = options_first(oo0);
4189fb66d81Schristos while (loop != NULL) {
4199fb66d81Schristos name = options_name(loop);
4209fb66d81Schristos if (*name == '@') {
4219fb66d81Schristos loop = options_next(loop);
4229fb66d81Schristos continue;
4239fb66d81Schristos }
4249fb66d81Schristos if (oo2 != NULL)
4259fb66d81Schristos o = options_get(oo2, name);
4269fb66d81Schristos else if (oo1 != NULL)
4279fb66d81Schristos o = options_get(oo1, name);
4289fb66d81Schristos else
4299fb66d81Schristos o = loop;
4309fb66d81Schristos if (options_owner(o) == oo2)
4319fb66d81Schristos scope = scope2;
4329fb66d81Schristos else if (options_owner(o) == oo1)
4339fb66d81Schristos scope = scope1;
4349fb66d81Schristos else
4359fb66d81Schristos scope = scope0;
4369fb66d81Schristos window_customize_build_option(data, top, scope, o, ft, filter,
4379fb66d81Schristos fs);
4389fb66d81Schristos loop = options_next(loop);
4399fb66d81Schristos }
4409fb66d81Schristos }
4419fb66d81Schristos
4429fb66d81Schristos static void
window_customize_build_keys(struct window_customize_modedata * data,struct key_table * kt,struct format_tree * ft,const char * filter,struct cmd_find_state * fs,u_int number)4439fb66d81Schristos window_customize_build_keys(struct window_customize_modedata *data,
4449fb66d81Schristos struct key_table *kt, struct format_tree *ft, const char *filter,
4459fb66d81Schristos struct cmd_find_state *fs, u_int number)
4469fb66d81Schristos {
4479fb66d81Schristos struct mode_tree_item *top, *child, *mti;
4489fb66d81Schristos struct window_customize_itemdata *item;
4499fb66d81Schristos struct key_binding *bd;
4509fb66d81Schristos char *title, *text, *tmp, *expanded;
4519fb66d81Schristos const char *flag;
4529fb66d81Schristos uint64_t tag;
4539fb66d81Schristos
4549fb66d81Schristos tag = (1ULL << 62)|((uint64_t)number << 54)|1;
4559fb66d81Schristos
4569fb66d81Schristos xasprintf(&title, "Key Table - %s", kt->name);
4579fb66d81Schristos top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
4589fb66d81Schristos mode_tree_no_tag(top);
4599fb66d81Schristos free(title);
4609fb66d81Schristos
4619fb66d81Schristos ft = format_create_from_state(NULL, NULL, fs);
4629fb66d81Schristos format_add(ft, "is_option", "0");
4639fb66d81Schristos format_add(ft, "is_key", "1");
4649fb66d81Schristos
4659fb66d81Schristos bd = key_bindings_first(kt);
4669fb66d81Schristos while (bd != NULL) {
4679fb66d81Schristos format_add(ft, "key", "%s", key_string_lookup_key(bd->key, 0));
4689fb66d81Schristos if (bd->note != NULL)
4699fb66d81Schristos format_add(ft, "key_note", "%s", bd->note);
4709fb66d81Schristos if (filter != NULL) {
4719fb66d81Schristos expanded = format_expand(ft, filter);
4729fb66d81Schristos if (!format_true(expanded)) {
4739fb66d81Schristos free(expanded);
4749fb66d81Schristos continue;
4759fb66d81Schristos }
4769fb66d81Schristos free(expanded);
4779fb66d81Schristos }
4789fb66d81Schristos
4799fb66d81Schristos item = window_customize_add_item(data);
4809fb66d81Schristos item->scope = WINDOW_CUSTOMIZE_KEY;
4819fb66d81Schristos item->table = xstrdup(kt->name);
4829fb66d81Schristos item->key = bd->key;
4839fb66d81Schristos item->name = xstrdup(key_string_lookup_key(item->key, 0));
4849fb66d81Schristos item->idx = -1;
4859fb66d81Schristos
4869fb66d81Schristos expanded = format_expand(ft, data->format);
487c745c111Schristos child = mode_tree_add(data->data, top, item, (uintptr_t)bd,
4889fb66d81Schristos expanded, NULL, 0);
4899fb66d81Schristos free(expanded);
4909fb66d81Schristos
4919fb66d81Schristos tmp = cmd_list_print(bd->cmdlist, 0);
4929fb66d81Schristos xasprintf(&text, "#[ignore]%s", tmp);
4939fb66d81Schristos free(tmp);
4949fb66d81Schristos mti = mode_tree_add(data->data, child, item,
4959fb66d81Schristos tag|(bd->key << 3)|(0 << 1)|1, "Command", text, -1);
4969fb66d81Schristos mode_tree_draw_as_parent(mti);
4979fb66d81Schristos mode_tree_no_tag(mti);
4989fb66d81Schristos free(text);
4999fb66d81Schristos
5009fb66d81Schristos if (bd->note != NULL)
5019fb66d81Schristos xasprintf(&text, "#[ignore]%s", bd->note);
5029fb66d81Schristos else
5039fb66d81Schristos text = xstrdup("");
5049fb66d81Schristos mti = mode_tree_add(data->data, child, item,
5059fb66d81Schristos tag|(bd->key << 3)|(1 << 1)|1, "Note", text, -1);
5069fb66d81Schristos mode_tree_draw_as_parent(mti);
5079fb66d81Schristos mode_tree_no_tag(mti);
5089fb66d81Schristos free(text);
5099fb66d81Schristos
5109fb66d81Schristos if (bd->flags & KEY_BINDING_REPEAT)
5119fb66d81Schristos flag = "on";
5129fb66d81Schristos else
5139fb66d81Schristos flag = "off";
5149fb66d81Schristos mti = mode_tree_add(data->data, child, item,
5159fb66d81Schristos tag|(bd->key << 3)|(2 << 1)|1, "Repeat", flag, -1);
5169fb66d81Schristos mode_tree_draw_as_parent(mti);
5179fb66d81Schristos mode_tree_no_tag(mti);
5189fb66d81Schristos
5199fb66d81Schristos bd = key_bindings_next(kt, bd);
5209fb66d81Schristos }
5219fb66d81Schristos
5229fb66d81Schristos format_free(ft);
5239fb66d81Schristos }
5249fb66d81Schristos
5259fb66d81Schristos static void
window_customize_build(void * modedata,__unused struct mode_tree_sort_criteria * sort_crit,__unused uint64_t * tag,const char * filter)5269fb66d81Schristos window_customize_build(void *modedata,
5279fb66d81Schristos __unused struct mode_tree_sort_criteria *sort_crit, __unused uint64_t *tag,
5289fb66d81Schristos const char *filter)
5299fb66d81Schristos {
5309fb66d81Schristos struct window_customize_modedata *data = modedata;
5319fb66d81Schristos struct cmd_find_state fs;
5329fb66d81Schristos struct format_tree *ft;
5339fb66d81Schristos u_int i;
5349fb66d81Schristos struct key_table *kt;
5359fb66d81Schristos
5369fb66d81Schristos for (i = 0; i < data->item_size; i++)
5379fb66d81Schristos window_customize_free_item(data->item_list[i]);
5389fb66d81Schristos free(data->item_list);
5399fb66d81Schristos data->item_list = NULL;
5409fb66d81Schristos data->item_size = 0;
5419fb66d81Schristos
5429fb66d81Schristos if (cmd_find_valid_state(&data->fs))
5439fb66d81Schristos cmd_find_copy_state(&fs, &data->fs);
5449fb66d81Schristos else
5459fb66d81Schristos cmd_find_from_pane(&fs, data->wp, 0);
5469fb66d81Schristos
5479fb66d81Schristos ft = format_create_from_state(NULL, NULL, &fs);
5489fb66d81Schristos format_add(ft, "is_option", "1");
5499fb66d81Schristos format_add(ft, "is_key", "0");
5509fb66d81Schristos
5519fb66d81Schristos window_customize_build_options(data, "Server Options",
5529fb66d81Schristos (3ULL << 62)|(OPTIONS_TABLE_SERVER << 1)|1,
5539fb66d81Schristos WINDOW_CUSTOMIZE_SERVER, global_options,
5549fb66d81Schristos WINDOW_CUSTOMIZE_NONE, NULL,
5559fb66d81Schristos WINDOW_CUSTOMIZE_NONE, NULL,
5569fb66d81Schristos ft, filter, &fs);
5579fb66d81Schristos window_customize_build_options(data, "Session Options",
5589fb66d81Schristos (3ULL << 62)|(OPTIONS_TABLE_SESSION << 1)|1,
5599fb66d81Schristos WINDOW_CUSTOMIZE_GLOBAL_SESSION, global_s_options,
5609fb66d81Schristos WINDOW_CUSTOMIZE_SESSION, fs.s->options,
5619fb66d81Schristos WINDOW_CUSTOMIZE_NONE, NULL,
5629fb66d81Schristos ft, filter, &fs);
5639fb66d81Schristos window_customize_build_options(data, "Window & Pane Options",
5649fb66d81Schristos (3ULL << 62)|(OPTIONS_TABLE_WINDOW << 1)|1,
5659fb66d81Schristos WINDOW_CUSTOMIZE_GLOBAL_WINDOW, global_w_options,
5669fb66d81Schristos WINDOW_CUSTOMIZE_WINDOW, fs.w->options,
5679fb66d81Schristos WINDOW_CUSTOMIZE_PANE, fs.wp->options,
5689fb66d81Schristos ft, filter, &fs);
5699fb66d81Schristos
5709fb66d81Schristos format_free(ft);
5719fb66d81Schristos ft = format_create_from_state(NULL, NULL, &fs);
5729fb66d81Schristos
5739fb66d81Schristos i = 0;
5749fb66d81Schristos kt = key_bindings_first_table();
5759fb66d81Schristos while (kt != NULL) {
5769fb66d81Schristos if (!RB_EMPTY(&kt->key_bindings)) {
5779fb66d81Schristos window_customize_build_keys(data, kt, ft, filter, &fs,
5789fb66d81Schristos i);
5799fb66d81Schristos if (++i == 256)
5809fb66d81Schristos break;
5819fb66d81Schristos }
5829fb66d81Schristos kt = key_bindings_next_table(kt);
5839fb66d81Schristos }
5849fb66d81Schristos
5859fb66d81Schristos format_free(ft);
5869fb66d81Schristos }
5879fb66d81Schristos
5889fb66d81Schristos static void
window_customize_draw_key(__unused struct window_customize_modedata * data,struct window_customize_itemdata * item,struct screen_write_ctx * ctx,u_int sx,u_int sy)5899fb66d81Schristos window_customize_draw_key(__unused struct window_customize_modedata *data,
5909fb66d81Schristos struct window_customize_itemdata *item, struct screen_write_ctx *ctx,
5919fb66d81Schristos u_int sx, u_int sy)
5929fb66d81Schristos {
5939fb66d81Schristos struct screen *s = ctx->s;
5949fb66d81Schristos u_int cx = s->cx, cy = s->cy;
5959fb66d81Schristos struct key_table *kt;
5969fb66d81Schristos struct key_binding *bd, *default_bd;
5979fb66d81Schristos const char *note, *period = "";
5989fb66d81Schristos char *cmd, *default_cmd;
5999fb66d81Schristos
6009fb66d81Schristos if (item == NULL || !window_customize_get_key(item, &kt, &bd))
6019fb66d81Schristos return;
6029fb66d81Schristos
6039fb66d81Schristos note = bd->note;
6049fb66d81Schristos if (note == NULL)
6059fb66d81Schristos note = "There is no note for this key.";
6069fb66d81Schristos if (*note != '\0' && note[strlen (note) - 1] != '.')
6079fb66d81Schristos period = ".";
6089fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s%s",
6099fb66d81Schristos note, period))
6109fb66d81Schristos return;
6119fb66d81Schristos screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
6129fb66d81Schristos if (s->cy >= cy + sy - 1)
6139fb66d81Schristos return;
6149fb66d81Schristos
6159fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
6169fb66d81Schristos &grid_default_cell, "This key is in the %s table.", kt->name))
6179fb66d81Schristos return;
6189fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
6199fb66d81Schristos &grid_default_cell, "This key %s repeat.",
6209fb66d81Schristos (bd->flags & KEY_BINDING_REPEAT) ? "does" : "does not"))
6219fb66d81Schristos return;
6229fb66d81Schristos screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
6239fb66d81Schristos if (s->cy >= cy + sy - 1)
6249fb66d81Schristos return;
6259fb66d81Schristos
6269fb66d81Schristos cmd = cmd_list_print(bd->cmdlist, 0);
6279fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
6289fb66d81Schristos &grid_default_cell, "Command: %s", cmd)) {
6299fb66d81Schristos free(cmd);
6309fb66d81Schristos return;
6319fb66d81Schristos }
6329fb66d81Schristos default_bd = key_bindings_get_default(kt, bd->key);
6339fb66d81Schristos if (default_bd != NULL) {
6349fb66d81Schristos default_cmd = cmd_list_print(default_bd->cmdlist, 0);
6359fb66d81Schristos if (strcmp(cmd, default_cmd) != 0 &&
6369fb66d81Schristos !screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
6379fb66d81Schristos &grid_default_cell, "The default is: %s", default_cmd)) {
6389fb66d81Schristos free(default_cmd);
6399fb66d81Schristos free(cmd);
6409fb66d81Schristos return;
6419fb66d81Schristos }
6429fb66d81Schristos free(default_cmd);
6439fb66d81Schristos }
6449fb66d81Schristos free(cmd);
6459fb66d81Schristos }
6469fb66d81Schristos
6479fb66d81Schristos static void
window_customize_draw_option(struct window_customize_modedata * data,struct window_customize_itemdata * item,struct screen_write_ctx * ctx,u_int sx,u_int sy)6489fb66d81Schristos window_customize_draw_option(struct window_customize_modedata *data,
6499fb66d81Schristos struct window_customize_itemdata *item, struct screen_write_ctx *ctx,
6509fb66d81Schristos u_int sx, u_int sy)
6519fb66d81Schristos {
6529fb66d81Schristos struct screen *s = ctx->s;
6539fb66d81Schristos u_int cx = s->cx, cy = s->cy;
6549fb66d81Schristos int idx;
6559fb66d81Schristos struct options_entry *o, *parent;
6569fb66d81Schristos struct options *go, *wo;
6579fb66d81Schristos const struct options_table_entry *oe;
6589fb66d81Schristos struct grid_cell gc;
6599fb66d81Schristos const char **choice, *text, *name;
6609fb66d81Schristos const char *space = "", *unit = "";
6619fb66d81Schristos char *value = NULL, *expanded;
6629fb66d81Schristos char *default_value = NULL;
6639fb66d81Schristos char choices[256] = "";
6649fb66d81Schristos struct cmd_find_state fs;
6659fb66d81Schristos struct format_tree *ft;
6669fb66d81Schristos
6679fb66d81Schristos if (!window_customize_check_item(data, item, &fs))
6689fb66d81Schristos return;
6699fb66d81Schristos name = item->name;
6709fb66d81Schristos idx = item->idx;
6719fb66d81Schristos
6729fb66d81Schristos o = options_get(item->oo, name);
6739fb66d81Schristos if (o == NULL)
6749fb66d81Schristos return;
6759fb66d81Schristos oe = options_table_entry(o);
6769fb66d81Schristos
6779fb66d81Schristos if (oe != NULL && oe->unit != NULL) {
6789fb66d81Schristos space = " ";
6799fb66d81Schristos unit = oe->unit;
6809fb66d81Schristos }
6819fb66d81Schristos ft = format_create_from_state(NULL, NULL, &fs);
6829fb66d81Schristos
683*46548964Swiz if (oe == NULL || oe->text == NULL)
6849fb66d81Schristos text = "This option doesn't have a description.";
6859fb66d81Schristos else
6869fb66d81Schristos text = oe->text;
6879fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s",
6889fb66d81Schristos text))
6899fb66d81Schristos goto out;
6909fb66d81Schristos screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
6919fb66d81Schristos if (s->cy >= cy + sy - 1)
6929fb66d81Schristos goto out;
6939fb66d81Schristos
6949fb66d81Schristos if (oe == NULL)
6959fb66d81Schristos text = "user";
6969fb66d81Schristos else if ((oe->scope & (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE)) ==
6979fb66d81Schristos (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE))
6989fb66d81Schristos text = "window and pane";
6999fb66d81Schristos else if (oe->scope & OPTIONS_TABLE_WINDOW)
7009fb66d81Schristos text = "window";
7019fb66d81Schristos else if (oe->scope & OPTIONS_TABLE_SESSION)
7029fb66d81Schristos text = "session";
7039fb66d81Schristos else
7049fb66d81Schristos text = "server";
7059fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
7069fb66d81Schristos &grid_default_cell, "This is a %s option.", text))
7079fb66d81Schristos goto out;
7089fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
7099fb66d81Schristos if (idx != -1) {
7109fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
7119fb66d81Schristos 0, &grid_default_cell,
7129fb66d81Schristos "This is an array option, index %u.", idx))
7139fb66d81Schristos goto out;
7149fb66d81Schristos } else {
7159fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
7169fb66d81Schristos 0, &grid_default_cell, "This is an array option."))
7179fb66d81Schristos goto out;
7189fb66d81Schristos }
7199fb66d81Schristos if (idx == -1)
7209fb66d81Schristos goto out;
7219fb66d81Schristos }
7229fb66d81Schristos screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
7239fb66d81Schristos if (s->cy >= cy + sy - 1)
7249fb66d81Schristos goto out;
7259fb66d81Schristos
7269fb66d81Schristos value = options_to_string(o, idx, 0);
7279fb66d81Schristos if (oe != NULL && idx == -1) {
7289fb66d81Schristos default_value = options_default_to_string(oe);
7299fb66d81Schristos if (strcmp(default_value, value) == 0) {
7309fb66d81Schristos free(default_value);
7319fb66d81Schristos default_value = NULL;
7329fb66d81Schristos }
7339fb66d81Schristos }
7349fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
7359fb66d81Schristos &grid_default_cell, "Option value: %s%s%s", value, space, unit))
7369fb66d81Schristos goto out;
7379fb66d81Schristos if (oe == NULL || oe->type == OPTIONS_TABLE_STRING) {
7389fb66d81Schristos expanded = format_expand(ft, value);
7399fb66d81Schristos if (strcmp(expanded, value) != 0) {
7409fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
7419fb66d81Schristos 0, &grid_default_cell, "This expands to: %s",
7429fb66d81Schristos expanded))
7439fb66d81Schristos goto out;
7449fb66d81Schristos }
7459fb66d81Schristos free(expanded);
7469fb66d81Schristos }
7479fb66d81Schristos if (oe != NULL && oe->type == OPTIONS_TABLE_CHOICE) {
7489fb66d81Schristos for (choice = oe->choices; *choice != NULL; choice++) {
7499fb66d81Schristos strlcat(choices, *choice, sizeof choices);
7509fb66d81Schristos strlcat(choices, ", ", sizeof choices);
7519fb66d81Schristos }
7529fb66d81Schristos choices[strlen(choices) - 2] = '\0';
7539fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
7549fb66d81Schristos &grid_default_cell, "Available values are: %s",
7559fb66d81Schristos choices))
7569fb66d81Schristos goto out;
7579fb66d81Schristos }
7589fb66d81Schristos if (oe != NULL && oe->type == OPTIONS_TABLE_COLOUR) {
7599fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 1,
7609fb66d81Schristos &grid_default_cell, "This is a colour option: "))
7619fb66d81Schristos goto out;
7629fb66d81Schristos memcpy(&gc, &grid_default_cell, sizeof gc);
7639fb66d81Schristos gc.fg = options_get_number(item->oo, name);
7649fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &gc,
7659fb66d81Schristos "EXAMPLE"))
7669fb66d81Schristos goto out;
7679fb66d81Schristos }
7689fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_STYLE)) {
7699fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 1,
7709fb66d81Schristos &grid_default_cell, "This is a style option: "))
7719fb66d81Schristos goto out;
7729fb66d81Schristos style_apply(&gc, item->oo, name, ft);
7739fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &gc,
7749fb66d81Schristos "EXAMPLE"))
7759fb66d81Schristos goto out;
7769fb66d81Schristos }
7779fb66d81Schristos if (default_value != NULL) {
7789fb66d81Schristos if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
7799fb66d81Schristos &grid_default_cell, "The default is: %s%s%s", default_value,
7809fb66d81Schristos space, unit))
7819fb66d81Schristos goto out;
7829fb66d81Schristos }
7839fb66d81Schristos
7849fb66d81Schristos screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
7859fb66d81Schristos if (s->cy > cy + sy - 1)
7869fb66d81Schristos goto out;
7879fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
7889fb66d81Schristos wo = NULL;
7899fb66d81Schristos go = NULL;
7909fb66d81Schristos } else {
7919fb66d81Schristos switch (item->scope) {
7929fb66d81Schristos case WINDOW_CUSTOMIZE_PANE:
7939fb66d81Schristos wo = options_get_parent(item->oo);
7949fb66d81Schristos go = options_get_parent(wo);
7959fb66d81Schristos break;
7969fb66d81Schristos case WINDOW_CUSTOMIZE_WINDOW:
7979fb66d81Schristos case WINDOW_CUSTOMIZE_SESSION:
7989fb66d81Schristos wo = NULL;
7999fb66d81Schristos go = options_get_parent(item->oo);
8009fb66d81Schristos break;
8019fb66d81Schristos default:
8029fb66d81Schristos wo = NULL;
8039fb66d81Schristos go = NULL;
8049fb66d81Schristos break;
8059fb66d81Schristos }
8069fb66d81Schristos }
8079fb66d81Schristos if (wo != NULL && options_owner(o) != wo) {
8089fb66d81Schristos parent = options_get_only(wo, name);
8099fb66d81Schristos if (parent != NULL) {
8109fb66d81Schristos value = options_to_string(parent, -1 , 0);
8119fb66d81Schristos if (!screen_write_text(ctx, s->cx, sx,
8129fb66d81Schristos sy - (s->cy - cy), 0, &grid_default_cell,
8139fb66d81Schristos "Window value (from window %u): %s%s%s", fs.wl->idx,
8149fb66d81Schristos value, space, unit))
8159fb66d81Schristos goto out;
8169fb66d81Schristos }
8179fb66d81Schristos }
8189fb66d81Schristos if (go != NULL && options_owner(o) != go) {
8199fb66d81Schristos parent = options_get_only(go, name);
8209fb66d81Schristos if (parent != NULL) {
8219fb66d81Schristos value = options_to_string(parent, -1 , 0);
8229fb66d81Schristos if (!screen_write_text(ctx, s->cx, sx,
8239fb66d81Schristos sy - (s->cy - cy), 0, &grid_default_cell,
8249fb66d81Schristos "Global value: %s%s%s", value, space, unit))
8259fb66d81Schristos goto out;
8269fb66d81Schristos }
8279fb66d81Schristos }
8289fb66d81Schristos
8299fb66d81Schristos out:
8309fb66d81Schristos free(value);
8319fb66d81Schristos free(default_value);
8329fb66d81Schristos format_free(ft);
8339fb66d81Schristos }
8349fb66d81Schristos
8359fb66d81Schristos static void
window_customize_draw(void * modedata,void * itemdata,struct screen_write_ctx * ctx,u_int sx,u_int sy)8369fb66d81Schristos window_customize_draw(void *modedata, void *itemdata,
8379fb66d81Schristos struct screen_write_ctx *ctx, u_int sx, u_int sy)
8389fb66d81Schristos {
8399fb66d81Schristos struct window_customize_modedata *data = modedata;
8409fb66d81Schristos struct window_customize_itemdata *item = itemdata;
8419fb66d81Schristos
8429fb66d81Schristos if (item == NULL)
8439fb66d81Schristos return;
8449fb66d81Schristos
8459fb66d81Schristos if (item->scope == WINDOW_CUSTOMIZE_KEY)
8469fb66d81Schristos window_customize_draw_key(data, item, ctx, sx, sy);
8479fb66d81Schristos else
8489fb66d81Schristos window_customize_draw_option(data, item, ctx, sx, sy);
8499fb66d81Schristos }
8509fb66d81Schristos
8519fb66d81Schristos static void
window_customize_menu(void * modedata,struct client * c,key_code key)8529fb66d81Schristos window_customize_menu(void *modedata, struct client *c, key_code key)
8539fb66d81Schristos {
8549fb66d81Schristos struct window_customize_modedata *data = modedata;
8559fb66d81Schristos struct window_pane *wp = data->wp;
8569fb66d81Schristos struct window_mode_entry *wme;
8579fb66d81Schristos
8589fb66d81Schristos wme = TAILQ_FIRST(&wp->modes);
8599fb66d81Schristos if (wme == NULL || wme->data != modedata)
8609fb66d81Schristos return;
8619fb66d81Schristos window_customize_key(wme, c, NULL, NULL, key, NULL);
8629fb66d81Schristos }
8639fb66d81Schristos
8649fb66d81Schristos static u_int
window_customize_height(__unused void * modedata,__unused u_int height)8659fb66d81Schristos window_customize_height(__unused void *modedata, __unused u_int height)
8669fb66d81Schristos {
8679fb66d81Schristos return (12);
8689fb66d81Schristos }
8699fb66d81Schristos
8709fb66d81Schristos static struct screen *
window_customize_init(struct window_mode_entry * wme,struct cmd_find_state * fs,struct args * args)8719fb66d81Schristos window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
8729fb66d81Schristos struct args *args)
8739fb66d81Schristos {
8749fb66d81Schristos struct window_pane *wp = wme->wp;
8759fb66d81Schristos struct window_customize_modedata *data;
8769fb66d81Schristos struct screen *s;
8779fb66d81Schristos
8789fb66d81Schristos wme->data = data = xcalloc(1, sizeof *data);
8799fb66d81Schristos data->wp = wp;
8809fb66d81Schristos data->references = 1;
8819fb66d81Schristos
8829fb66d81Schristos memcpy(&data->fs, fs, sizeof data->fs);
8839fb66d81Schristos
8849fb66d81Schristos if (args == NULL || !args_has(args, 'F'))
8859fb66d81Schristos data->format = xstrdup(WINDOW_CUSTOMIZE_DEFAULT_FORMAT);
8869fb66d81Schristos else
8879fb66d81Schristos data->format = xstrdup(args_get(args, 'F'));
8889fb66d81Schristos
8899fb66d81Schristos data->data = mode_tree_start(wp, args, window_customize_build,
8909fb66d81Schristos window_customize_draw, NULL, window_customize_menu,
8919fb66d81Schristos window_customize_height, NULL, data, window_customize_menu_items,
8929fb66d81Schristos NULL, 0, &s);
8939fb66d81Schristos mode_tree_zoom(data->data, args);
8949fb66d81Schristos
8959fb66d81Schristos mode_tree_build(data->data);
8969fb66d81Schristos mode_tree_draw(data->data);
8979fb66d81Schristos
8989fb66d81Schristos return (s);
8999fb66d81Schristos }
9009fb66d81Schristos
9019fb66d81Schristos static void
window_customize_destroy(struct window_customize_modedata * data)9029fb66d81Schristos window_customize_destroy(struct window_customize_modedata *data)
9039fb66d81Schristos {
9049fb66d81Schristos u_int i;
9059fb66d81Schristos
9069fb66d81Schristos if (--data->references != 0)
9079fb66d81Schristos return;
9089fb66d81Schristos
9099fb66d81Schristos for (i = 0; i < data->item_size; i++)
9109fb66d81Schristos window_customize_free_item(data->item_list[i]);
9119fb66d81Schristos free(data->item_list);
9129fb66d81Schristos
9139fb66d81Schristos free(data->format);
9149fb66d81Schristos
9159fb66d81Schristos free(data);
9169fb66d81Schristos }
9179fb66d81Schristos
9189fb66d81Schristos static void
window_customize_free(struct window_mode_entry * wme)9199fb66d81Schristos window_customize_free(struct window_mode_entry *wme)
9209fb66d81Schristos {
9219fb66d81Schristos struct window_customize_modedata *data = wme->data;
9229fb66d81Schristos
9239fb66d81Schristos if (data == NULL)
9249fb66d81Schristos return;
9259fb66d81Schristos
9269fb66d81Schristos data->dead = 1;
9279fb66d81Schristos mode_tree_free(data->data);
9289fb66d81Schristos window_customize_destroy(data);
9299fb66d81Schristos }
9309fb66d81Schristos
9319fb66d81Schristos static void
window_customize_resize(struct window_mode_entry * wme,u_int sx,u_int sy)9329fb66d81Schristos window_customize_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
9339fb66d81Schristos {
9349fb66d81Schristos struct window_customize_modedata *data = wme->data;
9359fb66d81Schristos
9369fb66d81Schristos mode_tree_resize(data->data, sx, sy);
9379fb66d81Schristos }
9389fb66d81Schristos
9399fb66d81Schristos static void
window_customize_free_callback(void * modedata)9409fb66d81Schristos window_customize_free_callback(void *modedata)
9419fb66d81Schristos {
9429fb66d81Schristos window_customize_destroy(modedata);
9439fb66d81Schristos }
9449fb66d81Schristos
9459fb66d81Schristos static void
window_customize_free_item_callback(void * itemdata)9469fb66d81Schristos window_customize_free_item_callback(void *itemdata)
9479fb66d81Schristos {
9489fb66d81Schristos struct window_customize_itemdata *item = itemdata;
9499fb66d81Schristos struct window_customize_modedata *data = item->data;
9509fb66d81Schristos
9519fb66d81Schristos window_customize_free_item(item);
9529fb66d81Schristos window_customize_destroy(data);
9539fb66d81Schristos }
9549fb66d81Schristos
9559fb66d81Schristos static int
window_customize_set_option_callback(struct client * c,void * itemdata,const char * s,__unused int done)9569fb66d81Schristos window_customize_set_option_callback(struct client *c, void *itemdata,
9579fb66d81Schristos const char *s, __unused int done)
9589fb66d81Schristos {
9599fb66d81Schristos struct window_customize_itemdata *item = itemdata;
9609fb66d81Schristos struct window_customize_modedata *data = item->data;
9619fb66d81Schristos struct options_entry *o;
9629fb66d81Schristos const struct options_table_entry *oe;
9639fb66d81Schristos struct options *oo = item->oo;
9649fb66d81Schristos const char *name = item->name;
9659fb66d81Schristos char *cause;
9669fb66d81Schristos int idx = item->idx;
9679fb66d81Schristos
9689fb66d81Schristos if (s == NULL || *s == '\0' || data->dead)
9699fb66d81Schristos return (0);
9709fb66d81Schristos if (item == NULL || !window_customize_check_item(data, item, NULL))
9719fb66d81Schristos return (0);
9729fb66d81Schristos o = options_get(oo, name);
9739fb66d81Schristos if (o == NULL)
9749fb66d81Schristos return (0);
9759fb66d81Schristos oe = options_table_entry(o);
9769fb66d81Schristos
9779fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
9789fb66d81Schristos if (idx == -1) {
9799fb66d81Schristos for (idx = 0; idx < INT_MAX; idx++) {
9809fb66d81Schristos if (options_array_get(o, idx) == NULL)
9819fb66d81Schristos break;
9829fb66d81Schristos }
9839fb66d81Schristos }
9849fb66d81Schristos if (options_array_set(o, idx, s, 0, &cause) != 0)
9859fb66d81Schristos goto fail;
9869fb66d81Schristos } else {
9879fb66d81Schristos if (options_from_string(oo, oe, name, s, 0, &cause) != 0)
9889fb66d81Schristos goto fail;
9899fb66d81Schristos }
9909fb66d81Schristos
9919fb66d81Schristos options_push_changes(item->name);
9929fb66d81Schristos mode_tree_build(data->data);
9939fb66d81Schristos mode_tree_draw(data->data);
9949fb66d81Schristos data->wp->flags |= PANE_REDRAW;
9959fb66d81Schristos
9969fb66d81Schristos return (0);
9979fb66d81Schristos
9989fb66d81Schristos fail:
9999fb66d81Schristos *cause = toupper((u_char)*cause);
10009fb66d81Schristos status_message_set(c, -1, 1, 0, "%s", cause);
10019fb66d81Schristos free(cause);
10029fb66d81Schristos return (0);
10039fb66d81Schristos }
10049fb66d81Schristos
10059fb66d81Schristos static void
window_customize_set_option(struct client * c,struct window_customize_modedata * data,struct window_customize_itemdata * item,int global,int pane)10069fb66d81Schristos window_customize_set_option(struct client *c,
10079fb66d81Schristos struct window_customize_modedata *data,
10089fb66d81Schristos struct window_customize_itemdata *item, int global, int pane)
10099fb66d81Schristos {
10109fb66d81Schristos struct options_entry *o;
10119fb66d81Schristos const struct options_table_entry *oe;
10129fb66d81Schristos struct options *oo;
10139fb66d81Schristos struct window_customize_itemdata *new_item;
10149fb66d81Schristos int flag, idx = item->idx;
10159fb66d81Schristos enum window_customize_scope scope = WINDOW_CUSTOMIZE_NONE;
10169fb66d81Schristos u_int choice;
10179fb66d81Schristos const char *name = item->name, *space = "";
10189fb66d81Schristos char *prompt, *value, *text;
10199fb66d81Schristos struct cmd_find_state fs;
10209fb66d81Schristos
10219fb66d81Schristos if (item == NULL || !window_customize_check_item(data, item, &fs))
10229fb66d81Schristos return;
10239fb66d81Schristos o = options_get(item->oo, name);
10249fb66d81Schristos if (o == NULL)
10259fb66d81Schristos return;
10269fb66d81Schristos
10279fb66d81Schristos oe = options_table_entry(o);
10289fb66d81Schristos if (oe != NULL && ~oe->scope & OPTIONS_TABLE_PANE)
10299fb66d81Schristos pane = 0;
10309fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
10319fb66d81Schristos scope = item->scope;
10329fb66d81Schristos oo = item->oo;
10339fb66d81Schristos } else {
10349fb66d81Schristos if (global) {
10359fb66d81Schristos switch (item->scope) {
10369fb66d81Schristos case WINDOW_CUSTOMIZE_NONE:
10379fb66d81Schristos case WINDOW_CUSTOMIZE_KEY:
10389fb66d81Schristos case WINDOW_CUSTOMIZE_SERVER:
10399fb66d81Schristos case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
10409fb66d81Schristos case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
10419fb66d81Schristos scope = item->scope;
10429fb66d81Schristos break;
10439fb66d81Schristos case WINDOW_CUSTOMIZE_SESSION:
10449fb66d81Schristos scope = WINDOW_CUSTOMIZE_GLOBAL_SESSION;
10459fb66d81Schristos break;
10469fb66d81Schristos case WINDOW_CUSTOMIZE_WINDOW:
10479fb66d81Schristos case WINDOW_CUSTOMIZE_PANE:
10489fb66d81Schristos scope = WINDOW_CUSTOMIZE_GLOBAL_WINDOW;
10499fb66d81Schristos break;
10509fb66d81Schristos }
10519fb66d81Schristos } else {
10529fb66d81Schristos switch (item->scope) {
10539fb66d81Schristos case WINDOW_CUSTOMIZE_NONE:
10549fb66d81Schristos case WINDOW_CUSTOMIZE_KEY:
10559fb66d81Schristos case WINDOW_CUSTOMIZE_SERVER:
10569fb66d81Schristos case WINDOW_CUSTOMIZE_SESSION:
10579fb66d81Schristos scope = item->scope;
10589fb66d81Schristos break;
10599fb66d81Schristos case WINDOW_CUSTOMIZE_WINDOW:
10609fb66d81Schristos case WINDOW_CUSTOMIZE_PANE:
10619fb66d81Schristos if (pane)
10629fb66d81Schristos scope = WINDOW_CUSTOMIZE_PANE;
10639fb66d81Schristos else
10649fb66d81Schristos scope = WINDOW_CUSTOMIZE_WINDOW;
10659fb66d81Schristos break;
10669fb66d81Schristos case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
10679fb66d81Schristos scope = WINDOW_CUSTOMIZE_SESSION;
10689fb66d81Schristos break;
10699fb66d81Schristos case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
10709fb66d81Schristos if (pane)
10719fb66d81Schristos scope = WINDOW_CUSTOMIZE_PANE;
10729fb66d81Schristos else
10739fb66d81Schristos scope = WINDOW_CUSTOMIZE_WINDOW;
10749fb66d81Schristos break;
10759fb66d81Schristos }
10769fb66d81Schristos }
10779fb66d81Schristos if (scope == item->scope)
10789fb66d81Schristos oo = item->oo;
10799fb66d81Schristos else
10809fb66d81Schristos oo = window_customize_get_tree(scope, &fs);
10819fb66d81Schristos }
10829fb66d81Schristos
10839fb66d81Schristos if (oe != NULL && oe->type == OPTIONS_TABLE_FLAG) {
10849fb66d81Schristos flag = options_get_number(oo, name);
10859fb66d81Schristos options_set_number(oo, name, !flag);
10869fb66d81Schristos } else if (oe != NULL && oe->type == OPTIONS_TABLE_CHOICE) {
10879fb66d81Schristos choice = options_get_number(oo, name);
10889fb66d81Schristos if (oe->choices[choice + 1] == NULL)
10899fb66d81Schristos choice = 0;
10909fb66d81Schristos else
10919fb66d81Schristos choice++;
10929fb66d81Schristos options_set_number(oo, name, choice);
10939fb66d81Schristos } else {
10949fb66d81Schristos text = window_customize_scope_text(scope, &fs);
10959fb66d81Schristos if (*text != '\0')
10969fb66d81Schristos space = ", for ";
10979fb66d81Schristos else if (scope != WINDOW_CUSTOMIZE_SERVER)
10989fb66d81Schristos space = ", global";
10999fb66d81Schristos if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
11009fb66d81Schristos if (idx == -1) {
11019fb66d81Schristos xasprintf(&prompt, "(%s[+]%s%s) ", name, space,
11029fb66d81Schristos text);
11039fb66d81Schristos } else {
11049fb66d81Schristos xasprintf(&prompt, "(%s[%d]%s%s) ", name, idx,
11059fb66d81Schristos space, text);
11069fb66d81Schristos }
11079fb66d81Schristos } else
11089fb66d81Schristos xasprintf(&prompt, "(%s%s%s) ", name, space, text);
11099fb66d81Schristos free(text);
11109fb66d81Schristos
11119fb66d81Schristos value = options_to_string(o, idx, 0);
11129fb66d81Schristos
11139fb66d81Schristos new_item = xcalloc(1, sizeof *new_item);
11149fb66d81Schristos new_item->data = data;
11159fb66d81Schristos new_item->scope = scope;
11169fb66d81Schristos new_item->oo = oo;
11179fb66d81Schristos new_item->name = xstrdup(name);
11189fb66d81Schristos new_item->idx = idx;
11199fb66d81Schristos
11209fb66d81Schristos data->references++;
11219fb66d81Schristos status_prompt_set(c, NULL, prompt, value,
11229fb66d81Schristos window_customize_set_option_callback,
11239fb66d81Schristos window_customize_free_item_callback, new_item,
1124*46548964Swiz PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
11259fb66d81Schristos
11269fb66d81Schristos free(prompt);
11279fb66d81Schristos free(value);
11289fb66d81Schristos }
11299fb66d81Schristos }
11309fb66d81Schristos
11319fb66d81Schristos static void
window_customize_unset_option(struct window_customize_modedata * data,struct window_customize_itemdata * item)11329fb66d81Schristos window_customize_unset_option(struct window_customize_modedata *data,
11339fb66d81Schristos struct window_customize_itemdata *item)
11349fb66d81Schristos {
11359fb66d81Schristos struct options_entry *o;
11369fb66d81Schristos
11379fb66d81Schristos if (item == NULL || !window_customize_check_item(data, item, NULL))
11389fb66d81Schristos return;
11399fb66d81Schristos
11409fb66d81Schristos o = options_get(item->oo, item->name);
11419fb66d81Schristos if (o == NULL)
11429fb66d81Schristos return;
11439fb66d81Schristos if (item->idx != -1 && item == mode_tree_get_current(data->data))
11449fb66d81Schristos mode_tree_up(data->data, 0);
11459fb66d81Schristos options_remove_or_default(o, item->idx, NULL);
11469fb66d81Schristos }
11479fb66d81Schristos
11489fb66d81Schristos static void
window_customize_reset_option(struct window_customize_modedata * data,struct window_customize_itemdata * item)11499fb66d81Schristos window_customize_reset_option(struct window_customize_modedata *data,
11509fb66d81Schristos struct window_customize_itemdata *item)
11519fb66d81Schristos {
11529fb66d81Schristos struct options *oo;
11539fb66d81Schristos struct options_entry *o;
11549fb66d81Schristos
11559fb66d81Schristos if (item == NULL || !window_customize_check_item(data, item, NULL))
11569fb66d81Schristos return;
11579fb66d81Schristos if (item->idx != -1)
11589fb66d81Schristos return;
11599fb66d81Schristos
11609fb66d81Schristos oo = item->oo;
11619fb66d81Schristos while (oo != NULL) {
11629fb66d81Schristos o = options_get_only(item->oo, item->name);
11639fb66d81Schristos if (o != NULL)
11649fb66d81Schristos options_remove_or_default(o, -1, NULL);
11659fb66d81Schristos oo = options_get_parent(oo);
11669fb66d81Schristos }
11679fb66d81Schristos }
11689fb66d81Schristos
11699fb66d81Schristos static int
window_customize_set_command_callback(struct client * c,void * itemdata,const char * s,__unused int done)11709fb66d81Schristos window_customize_set_command_callback(struct client *c, void *itemdata,
11719fb66d81Schristos const char *s, __unused int done)
11729fb66d81Schristos {
11739fb66d81Schristos struct window_customize_itemdata *item = itemdata;
11749fb66d81Schristos struct window_customize_modedata *data = item->data;
11759fb66d81Schristos struct key_binding *bd;
11769fb66d81Schristos struct cmd_parse_result *pr;
11779fb66d81Schristos char *error;
11789fb66d81Schristos
11799fb66d81Schristos if (s == NULL || *s == '\0' || data->dead)
11809fb66d81Schristos return (0);
11819fb66d81Schristos if (item == NULL || !window_customize_get_key(item, NULL, &bd))
11829fb66d81Schristos return (0);
11839fb66d81Schristos
11849fb66d81Schristos pr = cmd_parse_from_string(s, NULL);
11859fb66d81Schristos switch (pr->status) {
11869fb66d81Schristos case CMD_PARSE_ERROR:
11879fb66d81Schristos error = pr->error;
11889fb66d81Schristos goto fail;
11899fb66d81Schristos case CMD_PARSE_SUCCESS:
11909fb66d81Schristos break;
11919fb66d81Schristos }
11929fb66d81Schristos cmd_list_free(bd->cmdlist);
11939fb66d81Schristos bd->cmdlist = pr->cmdlist;
11949fb66d81Schristos
11959fb66d81Schristos mode_tree_build(data->data);
11969fb66d81Schristos mode_tree_draw(data->data);
11979fb66d81Schristos data->wp->flags |= PANE_REDRAW;
11989fb66d81Schristos
11999fb66d81Schristos return (0);
12009fb66d81Schristos
12019fb66d81Schristos fail:
12029fb66d81Schristos *error = toupper((u_char)*error);
12039fb66d81Schristos status_message_set(c, -1, 1, 0, "%s", error);
12049fb66d81Schristos free(error);
12059fb66d81Schristos return (0);
12069fb66d81Schristos }
12079fb66d81Schristos
12089fb66d81Schristos static int
window_customize_set_note_callback(__unused struct client * c,void * itemdata,const char * s,__unused int done)12099fb66d81Schristos window_customize_set_note_callback(__unused struct client *c, void *itemdata,
12109fb66d81Schristos const char *s, __unused int done)
12119fb66d81Schristos {
12129fb66d81Schristos struct window_customize_itemdata *item = itemdata;
12139fb66d81Schristos struct window_customize_modedata *data = item->data;
12149fb66d81Schristos struct key_binding *bd;
12159fb66d81Schristos
12169fb66d81Schristos if (s == NULL || *s == '\0' || data->dead)
12179fb66d81Schristos return (0);
12189fb66d81Schristos if (item == NULL || !window_customize_get_key(item, NULL, &bd))
12199fb66d81Schristos return (0);
12209fb66d81Schristos
1221e271dbb8Schristos free(__UNCONST(bd->note));
12229fb66d81Schristos bd->note = xstrdup(s);
12239fb66d81Schristos
12249fb66d81Schristos mode_tree_build(data->data);
12259fb66d81Schristos mode_tree_draw(data->data);
12269fb66d81Schristos data->wp->flags |= PANE_REDRAW;
12279fb66d81Schristos
12289fb66d81Schristos return (0);
12299fb66d81Schristos }
12309fb66d81Schristos
12319fb66d81Schristos static void
window_customize_set_key(struct client * c,struct window_customize_modedata * data,struct window_customize_itemdata * item)12329fb66d81Schristos window_customize_set_key(struct client *c,
12339fb66d81Schristos struct window_customize_modedata *data,
12349fb66d81Schristos struct window_customize_itemdata *item)
12359fb66d81Schristos {
12369fb66d81Schristos key_code key = item->key;
12379fb66d81Schristos struct key_binding *bd;
12389fb66d81Schristos const char *s;
12399fb66d81Schristos char *prompt, *value;
12409fb66d81Schristos struct window_customize_itemdata *new_item;
12419fb66d81Schristos
12429fb66d81Schristos if (item == NULL || !window_customize_get_key(item, NULL, &bd))
12439fb66d81Schristos return;
12449fb66d81Schristos
12459fb66d81Schristos s = mode_tree_get_current_name(data->data);
12469fb66d81Schristos if (strcmp(s, "Repeat") == 0)
12479fb66d81Schristos bd->flags ^= KEY_BINDING_REPEAT;
12489fb66d81Schristos else if (strcmp(s, "Command") == 0) {
12499fb66d81Schristos xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
12509fb66d81Schristos value = cmd_list_print(bd->cmdlist, 0);
12519fb66d81Schristos
12529fb66d81Schristos new_item = xcalloc(1, sizeof *new_item);
12539fb66d81Schristos new_item->data = data;
12549fb66d81Schristos new_item->scope = item->scope;
12559fb66d81Schristos new_item->table = xstrdup(item->table);
12569fb66d81Schristos new_item->key = key;
12579fb66d81Schristos
12589fb66d81Schristos data->references++;
12599fb66d81Schristos status_prompt_set(c, NULL, prompt, value,
12609fb66d81Schristos window_customize_set_command_callback,
12619fb66d81Schristos window_customize_free_item_callback, new_item,
1262*46548964Swiz PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
12639fb66d81Schristos free(prompt);
12649fb66d81Schristos free(value);
12659fb66d81Schristos } else if (strcmp(s, "Note") == 0) {
12669fb66d81Schristos xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
12679fb66d81Schristos
12689fb66d81Schristos new_item = xcalloc(1, sizeof *new_item);
12699fb66d81Schristos new_item->data = data;
12709fb66d81Schristos new_item->scope = item->scope;
12719fb66d81Schristos new_item->table = xstrdup(item->table);
12729fb66d81Schristos new_item->key = key;
12739fb66d81Schristos
12749fb66d81Schristos data->references++;
12759fb66d81Schristos status_prompt_set(c, NULL, prompt,
12769fb66d81Schristos (bd->note == NULL ? "" : bd->note),
12779fb66d81Schristos window_customize_set_note_callback,
12789fb66d81Schristos window_customize_free_item_callback, new_item,
1279*46548964Swiz PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
12809fb66d81Schristos free(prompt);
12819fb66d81Schristos }
12829fb66d81Schristos }
12839fb66d81Schristos
12849fb66d81Schristos static void
window_customize_unset_key(struct window_customize_modedata * data,struct window_customize_itemdata * item)12859fb66d81Schristos window_customize_unset_key(struct window_customize_modedata *data,
12869fb66d81Schristos struct window_customize_itemdata *item)
12879fb66d81Schristos {
12889fb66d81Schristos struct key_table *kt;
12899fb66d81Schristos struct key_binding *bd;
12909fb66d81Schristos
12919fb66d81Schristos if (item == NULL || !window_customize_get_key(item, &kt, &bd))
12929fb66d81Schristos return;
12939fb66d81Schristos
12949fb66d81Schristos if (item == mode_tree_get_current(data->data)) {
12959fb66d81Schristos mode_tree_collapse_current(data->data);
12969fb66d81Schristos mode_tree_up(data->data, 0);
12979fb66d81Schristos }
12989fb66d81Schristos key_bindings_remove(kt->name, bd->key);
12999fb66d81Schristos }
13009fb66d81Schristos
13019fb66d81Schristos static void
window_customize_reset_key(struct window_customize_modedata * data,struct window_customize_itemdata * item)13029fb66d81Schristos window_customize_reset_key(struct window_customize_modedata *data,
13039fb66d81Schristos struct window_customize_itemdata *item)
13049fb66d81Schristos {
13059fb66d81Schristos struct key_table *kt;
13069fb66d81Schristos struct key_binding *dd, *bd;
13079fb66d81Schristos
13089fb66d81Schristos if (item == NULL || !window_customize_get_key(item, &kt, &bd))
13099fb66d81Schristos return;
13109fb66d81Schristos
13119fb66d81Schristos dd = key_bindings_get_default(kt, bd->key);
13129fb66d81Schristos if (dd != NULL && bd->cmdlist == dd->cmdlist)
13139fb66d81Schristos return;
13149fb66d81Schristos if (dd == NULL && item == mode_tree_get_current(data->data)) {
13159fb66d81Schristos mode_tree_collapse_current(data->data);
13169fb66d81Schristos mode_tree_up(data->data, 0);
13179fb66d81Schristos }
13189fb66d81Schristos key_bindings_reset(kt->name, bd->key);
13199fb66d81Schristos }
13209fb66d81Schristos
13219fb66d81Schristos static void
window_customize_change_each(void * modedata,void * itemdata,__unused struct client * c,__unused key_code key)13229fb66d81Schristos window_customize_change_each(void *modedata, void *itemdata,
13239fb66d81Schristos __unused struct client *c, __unused key_code key)
13249fb66d81Schristos {
13259fb66d81Schristos struct window_customize_modedata *data = modedata;
13269fb66d81Schristos struct window_customize_itemdata *item = itemdata;
13279fb66d81Schristos
13289fb66d81Schristos switch (data->change) {
13299fb66d81Schristos case WINDOW_CUSTOMIZE_UNSET:
13309fb66d81Schristos if (item->scope == WINDOW_CUSTOMIZE_KEY)
13319fb66d81Schristos window_customize_unset_key(data, item);
13329fb66d81Schristos else
13339fb66d81Schristos window_customize_unset_option(data, item);
13349fb66d81Schristos break;
13359fb66d81Schristos case WINDOW_CUSTOMIZE_RESET:
13369fb66d81Schristos if (item->scope == WINDOW_CUSTOMIZE_KEY)
13379fb66d81Schristos window_customize_reset_key(data, item);
13389fb66d81Schristos else
13399fb66d81Schristos window_customize_reset_option(data, item);
13409fb66d81Schristos break;
13419fb66d81Schristos }
13429fb66d81Schristos if (item->scope != WINDOW_CUSTOMIZE_KEY)
13439fb66d81Schristos options_push_changes(item->name);
13449fb66d81Schristos }
13459fb66d81Schristos
13469fb66d81Schristos static int
window_customize_change_current_callback(__unused struct client * c,void * modedata,const char * s,__unused int done)13479fb66d81Schristos window_customize_change_current_callback(__unused struct client *c,
13489fb66d81Schristos void *modedata, const char *s, __unused int done)
13499fb66d81Schristos {
13509fb66d81Schristos struct window_customize_modedata *data = modedata;
13519fb66d81Schristos struct window_customize_itemdata *item;
13529fb66d81Schristos
13539fb66d81Schristos if (s == NULL || *s == '\0' || data->dead)
13549fb66d81Schristos return (0);
13559fb66d81Schristos if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
13569fb66d81Schristos return (0);
13579fb66d81Schristos
13589fb66d81Schristos item = mode_tree_get_current(data->data);
13599fb66d81Schristos switch (data->change) {
13609fb66d81Schristos case WINDOW_CUSTOMIZE_UNSET:
13619fb66d81Schristos if (item->scope == WINDOW_CUSTOMIZE_KEY)
13629fb66d81Schristos window_customize_unset_key(data, item);
13639fb66d81Schristos else
13649fb66d81Schristos window_customize_unset_option(data, item);
13659fb66d81Schristos break;
13669fb66d81Schristos case WINDOW_CUSTOMIZE_RESET:
13679fb66d81Schristos if (item->scope == WINDOW_CUSTOMIZE_KEY)
13689fb66d81Schristos window_customize_reset_key(data, item);
13699fb66d81Schristos else
13709fb66d81Schristos window_customize_reset_option(data, item);
13719fb66d81Schristos break;
13729fb66d81Schristos }
13739fb66d81Schristos if (item->scope != WINDOW_CUSTOMIZE_KEY)
13749fb66d81Schristos options_push_changes(item->name);
13759fb66d81Schristos mode_tree_build(data->data);
13769fb66d81Schristos mode_tree_draw(data->data);
13779fb66d81Schristos data->wp->flags |= PANE_REDRAW;
13789fb66d81Schristos
13799fb66d81Schristos return (0);
13809fb66d81Schristos }
13819fb66d81Schristos
13829fb66d81Schristos static int
window_customize_change_tagged_callback(struct client * c,void * modedata,const char * s,__unused int done)13839fb66d81Schristos window_customize_change_tagged_callback(struct client *c, void *modedata,
13849fb66d81Schristos const char *s, __unused int done)
13859fb66d81Schristos {
13869fb66d81Schristos struct window_customize_modedata *data = modedata;
13879fb66d81Schristos
13889fb66d81Schristos if (s == NULL || *s == '\0' || data->dead)
13899fb66d81Schristos return (0);
13909fb66d81Schristos if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
13919fb66d81Schristos return (0);
13929fb66d81Schristos
13939fb66d81Schristos mode_tree_each_tagged(data->data, window_customize_change_each, c,
13949fb66d81Schristos KEYC_NONE, 0);
13959fb66d81Schristos mode_tree_build(data->data);
13969fb66d81Schristos mode_tree_draw(data->data);
13979fb66d81Schristos data->wp->flags |= PANE_REDRAW;
13989fb66d81Schristos
13999fb66d81Schristos return (0);
14009fb66d81Schristos }
14019fb66d81Schristos
14029fb66d81Schristos static void
window_customize_key(struct window_mode_entry * wme,struct client * c,__unused struct session * s,__unused struct winlink * wl,key_code key,struct mouse_event * m)14039fb66d81Schristos window_customize_key(struct window_mode_entry *wme, struct client *c,
14049fb66d81Schristos __unused struct session *s, __unused struct winlink *wl, key_code key,
14059fb66d81Schristos struct mouse_event *m)
14069fb66d81Schristos {
14079fb66d81Schristos struct window_pane *wp = wme->wp;
14089fb66d81Schristos struct window_customize_modedata *data = wme->data;
14099fb66d81Schristos struct window_customize_itemdata *item, *new_item;
14109fb66d81Schristos int finished, idx;
14119fb66d81Schristos char *prompt;
14129fb66d81Schristos u_int tagged;
14139fb66d81Schristos
14149fb66d81Schristos item = mode_tree_get_current(data->data);
14159fb66d81Schristos finished = mode_tree_key(data->data, c, &key, m, NULL, NULL);
14169fb66d81Schristos if (item != (new_item = mode_tree_get_current(data->data)))
14179fb66d81Schristos item = new_item;
14189fb66d81Schristos
14199fb66d81Schristos switch (key) {
14209fb66d81Schristos case '\r':
14219fb66d81Schristos case 's':
14229fb66d81Schristos if (item == NULL)
14239fb66d81Schristos break;
14249fb66d81Schristos if (item->scope == WINDOW_CUSTOMIZE_KEY)
14259fb66d81Schristos window_customize_set_key(c, data, item);
14269fb66d81Schristos else {
14279fb66d81Schristos window_customize_set_option(c, data, item, 0, 1);
14289fb66d81Schristos options_push_changes(item->name);
14299fb66d81Schristos }
14309fb66d81Schristos mode_tree_build(data->data);
14319fb66d81Schristos break;
14329fb66d81Schristos case 'w':
14339fb66d81Schristos if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
14349fb66d81Schristos break;
14359fb66d81Schristos window_customize_set_option(c, data, item, 0, 0);
14369fb66d81Schristos options_push_changes(item->name);
14379fb66d81Schristos mode_tree_build(data->data);
14389fb66d81Schristos break;
14399fb66d81Schristos case 'S':
14409fb66d81Schristos case 'W':
14419fb66d81Schristos if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
14429fb66d81Schristos break;
14439fb66d81Schristos window_customize_set_option(c, data, item, 1, 0);
14449fb66d81Schristos options_push_changes(item->name);
14459fb66d81Schristos mode_tree_build(data->data);
14469fb66d81Schristos break;
14479fb66d81Schristos case 'd':
14489fb66d81Schristos if (item == NULL || item->idx != -1)
14499fb66d81Schristos break;
14509fb66d81Schristos xasprintf(&prompt, "Reset %s to default? ", item->name);
14519fb66d81Schristos data->references++;
14529fb66d81Schristos data->change = WINDOW_CUSTOMIZE_RESET;
14539fb66d81Schristos status_prompt_set(c, NULL, prompt, "",
14549fb66d81Schristos window_customize_change_current_callback,
14559fb66d81Schristos window_customize_free_callback, data,
1456*46548964Swiz PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
14579fb66d81Schristos free(prompt);
14589fb66d81Schristos break;
14599fb66d81Schristos case 'D':
14609fb66d81Schristos tagged = mode_tree_count_tagged(data->data);
14619fb66d81Schristos if (tagged == 0)
14629fb66d81Schristos break;
14639fb66d81Schristos xasprintf(&prompt, "Reset %u tagged to default? ", tagged);
14649fb66d81Schristos data->references++;
14659fb66d81Schristos data->change = WINDOW_CUSTOMIZE_RESET;
14669fb66d81Schristos status_prompt_set(c, NULL, prompt, "",
14679fb66d81Schristos window_customize_change_tagged_callback,
14689fb66d81Schristos window_customize_free_callback, data,
1469*46548964Swiz PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
14709fb66d81Schristos free(prompt);
14719fb66d81Schristos break;
14729fb66d81Schristos case 'u':
14739fb66d81Schristos if (item == NULL)
14749fb66d81Schristos break;
14759fb66d81Schristos idx = item->idx;
14769fb66d81Schristos if (idx != -1)
14779fb66d81Schristos xasprintf(&prompt, "Unset %s[%d]? ", item->name, idx);
14789fb66d81Schristos else
14799fb66d81Schristos xasprintf(&prompt, "Unset %s? ", item->name);
14809fb66d81Schristos data->references++;
14819fb66d81Schristos data->change = WINDOW_CUSTOMIZE_UNSET;
14829fb66d81Schristos status_prompt_set(c, NULL, prompt, "",
14839fb66d81Schristos window_customize_change_current_callback,
14849fb66d81Schristos window_customize_free_callback, data,
1485*46548964Swiz PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
14869fb66d81Schristos free(prompt);
14879fb66d81Schristos break;
14889fb66d81Schristos case 'U':
14899fb66d81Schristos tagged = mode_tree_count_tagged(data->data);
14909fb66d81Schristos if (tagged == 0)
14919fb66d81Schristos break;
14929fb66d81Schristos xasprintf(&prompt, "Unset %u tagged? ", tagged);
14939fb66d81Schristos data->references++;
14949fb66d81Schristos data->change = WINDOW_CUSTOMIZE_UNSET;
14959fb66d81Schristos status_prompt_set(c, NULL, prompt, "",
14969fb66d81Schristos window_customize_change_tagged_callback,
14979fb66d81Schristos window_customize_free_callback, data,
1498*46548964Swiz PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
14999fb66d81Schristos free(prompt);
15009fb66d81Schristos break;
15019fb66d81Schristos case 'H':
15029fb66d81Schristos data->hide_global = !data->hide_global;
15039fb66d81Schristos mode_tree_build(data->data);
15049fb66d81Schristos break;
15059fb66d81Schristos }
15069fb66d81Schristos if (finished)
15079fb66d81Schristos window_pane_reset_mode(wp);
15089fb66d81Schristos else {
15099fb66d81Schristos mode_tree_draw(data->data);
15109fb66d81Schristos wp->flags |= PANE_REDRAW;
15119fb66d81Schristos }
15129fb66d81Schristos }
1513