Use correct size for screen when popup is created without borders.
[tmux-openbsd.git] / window-customize.c
blob98387e509748f64be162508403304fc73ee7de73
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "tmux.h"
27 static struct screen *window_customize_init(struct window_mode_entry *,
28 struct cmd_find_state *, struct args *);
29 static void window_customize_free(struct window_mode_entry *);
30 static void window_customize_resize(struct window_mode_entry *,
31 u_int, u_int);
32 static void window_customize_key(struct window_mode_entry *,
33 struct client *, struct session *,
34 struct winlink *, key_code, struct mouse_event *);
36 #define WINDOW_CUSTOMIZE_DEFAULT_FORMAT \
37 "#{?is_option," \
38 "#{?option_is_global,,#[reverse](#{option_scope})#[default] }" \
39 "#[ignore]" \
40 "#{option_value}#{?option_unit, #{option_unit},}" \
41 "," \
42 "#{key}" \
43 "}"
45 static const struct menu_item window_customize_menu_items[] = {
46 { "Select", '\r', NULL },
47 { "Expand", KEYC_RIGHT, NULL },
48 { "", KEYC_NONE, NULL },
49 { "Tag", 't', NULL },
50 { "Tag All", '\024', NULL },
51 { "Tag None", 'T', NULL },
52 { "", KEYC_NONE, NULL },
53 { "Cancel", 'q', NULL },
55 { NULL, KEYC_NONE, NULL }
58 const struct window_mode window_customize_mode = {
59 .name = "options-mode",
60 .default_format = WINDOW_CUSTOMIZE_DEFAULT_FORMAT,
62 .init = window_customize_init,
63 .free = window_customize_free,
64 .resize = window_customize_resize,
65 .key = window_customize_key,
68 enum window_customize_scope {
69 WINDOW_CUSTOMIZE_NONE,
70 WINDOW_CUSTOMIZE_KEY,
71 WINDOW_CUSTOMIZE_SERVER,
72 WINDOW_CUSTOMIZE_GLOBAL_SESSION,
73 WINDOW_CUSTOMIZE_SESSION,
74 WINDOW_CUSTOMIZE_GLOBAL_WINDOW,
75 WINDOW_CUSTOMIZE_WINDOW,
76 WINDOW_CUSTOMIZE_PANE
79 enum window_customize_change {
80 WINDOW_CUSTOMIZE_UNSET,
81 WINDOW_CUSTOMIZE_RESET,
84 struct window_customize_itemdata {
85 struct window_customize_modedata *data;
86 enum window_customize_scope scope;
88 char *table;
89 key_code key;
91 struct options *oo;
92 char *name;
93 int idx;
96 struct window_customize_modedata {
97 struct window_pane *wp;
98 int dead;
99 int references;
101 struct mode_tree_data *data;
102 char *format;
103 int hide_global;
105 struct window_customize_itemdata **item_list;
106 u_int item_size;
108 struct cmd_find_state fs;
109 enum window_customize_change change;
112 static uint64_t
113 window_customize_get_tag(struct options_entry *o, int idx,
114 const struct options_table_entry *oe)
116 uint64_t offset;
118 if (oe == NULL)
119 return ((uint64_t)o);
120 offset = ((char *)oe - (char *)options_table) / sizeof *options_table;
121 return ((2ULL << 62)|(offset << 32)|((idx + 1) << 1)|1);
124 static struct options *
125 window_customize_get_tree(enum window_customize_scope scope,
126 struct cmd_find_state *fs)
128 switch (scope) {
129 case WINDOW_CUSTOMIZE_NONE:
130 case WINDOW_CUSTOMIZE_KEY:
131 return (NULL);
132 case WINDOW_CUSTOMIZE_SERVER:
133 return (global_options);
134 case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
135 return (global_s_options);
136 case WINDOW_CUSTOMIZE_SESSION:
137 return (fs->s->options);
138 case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
139 return (global_w_options);
140 case WINDOW_CUSTOMIZE_WINDOW:
141 return (fs->w->options);
142 case WINDOW_CUSTOMIZE_PANE:
143 return (fs->wp->options);
145 return (NULL);
148 static int
149 window_customize_check_item(struct window_customize_modedata *data,
150 struct window_customize_itemdata *item, struct cmd_find_state *fsp)
152 struct cmd_find_state fs;
154 if (fsp == NULL)
155 fsp = &fs;
157 if (cmd_find_valid_state(&data->fs))
158 cmd_find_copy_state(fsp, &data->fs);
159 else
160 cmd_find_from_pane(fsp, data->wp, 0);
161 return (item->oo == window_customize_get_tree(item->scope, fsp));
164 static int
165 window_customize_get_key(struct window_customize_itemdata *item,
166 struct key_table **ktp, struct key_binding **bdp)
168 struct key_table *kt;
169 struct key_binding *bd;
171 kt = key_bindings_get_table(item->table, 0);
172 if (kt == NULL)
173 return (0);
174 bd = key_bindings_get(kt, item->key);
175 if (bd == NULL)
176 return (0);
178 if (ktp != NULL)
179 *ktp = kt;
180 if (bdp != NULL)
181 *bdp = bd;
182 return (1);
185 static char *
186 window_customize_scope_text(enum window_customize_scope scope,
187 struct cmd_find_state *fs)
189 char *s;
190 u_int idx;
192 switch (scope) {
193 case WINDOW_CUSTOMIZE_PANE:
194 window_pane_index(fs->wp, &idx);
195 xasprintf(&s, "pane %u", idx);
196 break;
197 case WINDOW_CUSTOMIZE_SESSION:
198 xasprintf(&s, "session %s", fs->s->name);
199 break;
200 case WINDOW_CUSTOMIZE_WINDOW:
201 xasprintf(&s, "window %u", fs->wl->idx);
202 break;
203 default:
204 s = xstrdup("");
205 break;
207 return (s);
210 static struct window_customize_itemdata *
211 window_customize_add_item(struct window_customize_modedata *data)
213 struct window_customize_itemdata *item;
215 data->item_list = xreallocarray(data->item_list, data->item_size + 1,
216 sizeof *data->item_list);
217 item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
218 return (item);
221 static void
222 window_customize_free_item(struct window_customize_itemdata *item)
224 free(item->table);
225 free(item->name);
226 free(item);
229 static void
230 window_customize_build_array(struct window_customize_modedata *data,
231 struct mode_tree_item *top, enum window_customize_scope scope,
232 struct options_entry *o, struct format_tree *ft)
234 const struct options_table_entry *oe = options_table_entry(o);
235 struct options *oo = options_owner(o);
236 struct window_customize_itemdata *item;
237 struct options_array_item *ai;
238 char *name, *value, *text;
239 u_int idx;
240 uint64_t tag;
242 ai = options_array_first(o);
243 while (ai != NULL) {
244 idx = options_array_item_index(ai);
246 xasprintf(&name, "%s[%u]", options_name(o), idx);
247 format_add(ft, "option_name", "%s", name);
248 value = options_to_string(o, idx, 0);
249 format_add(ft, "option_value", "%s", value);
251 item = window_customize_add_item(data);
252 item->scope = scope;
253 item->oo = oo;
254 item->name = xstrdup(options_name(o));
255 item->idx = idx;
257 text = format_expand(ft, data->format);
258 tag = window_customize_get_tag(o, idx, oe);
259 mode_tree_add(data->data, top, item, tag, name, text, -1);
260 free(text);
262 free(name);
263 free(value);
265 ai = options_array_next(ai);
269 static void
270 window_customize_build_option(struct window_customize_modedata *data,
271 struct mode_tree_item *top, enum window_customize_scope scope,
272 struct options_entry *o, struct format_tree *ft,
273 const char *filter, struct cmd_find_state *fs)
275 const struct options_table_entry *oe = options_table_entry(o);
276 struct options *oo = options_owner(o);
277 const char *name = options_name(o);
278 struct window_customize_itemdata *item;
279 char *text, *expanded, *value;
280 int global = 0, array = 0;
281 uint64_t tag;
283 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_HOOK))
284 return;
285 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY))
286 array = 1;
288 if (scope == WINDOW_CUSTOMIZE_SERVER ||
289 scope == WINDOW_CUSTOMIZE_GLOBAL_SESSION ||
290 scope == WINDOW_CUSTOMIZE_GLOBAL_WINDOW)
291 global = 1;
292 if (data->hide_global && global)
293 return;
295 format_add(ft, "option_name", "%s", name);
296 format_add(ft, "option_is_global", "%d", global);
297 format_add(ft, "option_is_array", "%d", array);
299 text = window_customize_scope_text(scope, fs);
300 format_add(ft, "option_scope", "%s", text);
301 free(text);
303 if (oe != NULL && oe->unit != NULL)
304 format_add(ft, "option_unit", "%s", oe->unit);
305 else
306 format_add(ft, "option_unit", "%s", "");
308 if (!array) {
309 value = options_to_string(o, -1, 0);
310 format_add(ft, "option_value", "%s", value);
311 free(value);
314 if (filter != NULL) {
315 expanded = format_expand(ft, filter);
316 if (!format_true(expanded)) {
317 free(expanded);
318 return;
320 free(expanded);
322 item = window_customize_add_item(data);
323 item->oo = oo;
324 item->scope = scope;
325 item->name = xstrdup(name);
326 item->idx = -1;
328 if (array)
329 text = NULL;
330 else
331 text = format_expand(ft, data->format);
332 tag = window_customize_get_tag(o, -1, oe);
333 top = mode_tree_add(data->data, top, item, tag, name, text, 0);
334 free(text);
336 if (array)
337 window_customize_build_array(data, top, scope, o, ft);
340 static void
341 window_customize_find_user_options(struct options *oo, const char ***list,
342 u_int *size)
344 struct options_entry *o;
345 const char *name;
346 u_int i;
348 o = options_first(oo);
349 while (o != NULL) {
350 name = options_name(o);
351 if (*name != '@') {
352 o = options_next(o);
353 continue;
355 for (i = 0; i < *size; i++) {
356 if (strcmp((*list)[i], name) == 0)
357 break;
359 if (i != *size) {
360 o = options_next(o);
361 continue;
363 *list = xreallocarray(*list, (*size) + 1, sizeof **list);
364 (*list)[(*size)++] = name;
366 o = options_next(o);
370 static void
371 window_customize_build_options(struct window_customize_modedata *data,
372 const char *title, uint64_t tag,
373 enum window_customize_scope scope0, struct options *oo0,
374 enum window_customize_scope scope1, struct options *oo1,
375 enum window_customize_scope scope2, struct options *oo2,
376 struct format_tree *ft, const char *filter, struct cmd_find_state *fs)
378 struct mode_tree_item *top;
379 struct options_entry *o = NULL, *loop;
380 const char **list = NULL, *name;
381 u_int size = 0, i;
382 enum window_customize_scope scope;
384 top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
385 mode_tree_no_tag(top);
388 * We get the options from the first tree, but build it using the
389 * values from the other two. Any tree can have user options so we need
390 * to build a separate list of them.
393 window_customize_find_user_options(oo0, &list, &size);
394 if (oo1 != NULL)
395 window_customize_find_user_options(oo1, &list, &size);
396 if (oo2 != NULL)
397 window_customize_find_user_options(oo2, &list, &size);
399 for (i = 0; i < size; i++) {
400 if (oo2 != NULL)
401 o = options_get(oo2, list[i]);
402 if (o == NULL && oo1 != NULL)
403 o = options_get(oo1, list[i]);
404 if (o == NULL)
405 o = options_get(oo0, list[i]);
406 if (options_owner(o) == oo2)
407 scope = scope2;
408 else if (options_owner(o) == oo1)
409 scope = scope1;
410 else
411 scope = scope0;
412 window_customize_build_option(data, top, scope, o, ft, filter,
413 fs);
415 free(list);
417 loop = options_first(oo0);
418 while (loop != NULL) {
419 name = options_name(loop);
420 if (*name == '@') {
421 loop = options_next(loop);
422 continue;
424 if (oo2 != NULL)
425 o = options_get(oo2, name);
426 else if (oo1 != NULL)
427 o = options_get(oo1, name);
428 else
429 o = loop;
430 if (options_owner(o) == oo2)
431 scope = scope2;
432 else if (options_owner(o) == oo1)
433 scope = scope1;
434 else
435 scope = scope0;
436 window_customize_build_option(data, top, scope, o, ft, filter,
437 fs);
438 loop = options_next(loop);
442 static void
443 window_customize_build_keys(struct window_customize_modedata *data,
444 struct key_table *kt, struct format_tree *ft, const char *filter,
445 struct cmd_find_state *fs, u_int number)
447 struct mode_tree_item *top, *child, *mti;
448 struct window_customize_itemdata *item;
449 struct key_binding *bd;
450 char *title, *text, *tmp, *expanded;
451 const char *flag;
452 uint64_t tag;
454 tag = (1ULL << 62)|((uint64_t)number << 54)|1;
456 xasprintf(&title, "Key Table - %s", kt->name);
457 top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
458 mode_tree_no_tag(top);
459 free(title);
461 ft = format_create_from_state(NULL, NULL, fs);
462 format_add(ft, "is_option", "0");
463 format_add(ft, "is_key", "1");
465 bd = key_bindings_first(kt);
466 while (bd != NULL) {
467 format_add(ft, "key", "%s", key_string_lookup_key(bd->key, 0));
468 if (bd->note != NULL)
469 format_add(ft, "key_note", "%s", bd->note);
470 if (filter != NULL) {
471 expanded = format_expand(ft, filter);
472 if (!format_true(expanded)) {
473 free(expanded);
474 continue;
476 free(expanded);
479 item = window_customize_add_item(data);
480 item->scope = WINDOW_CUSTOMIZE_KEY;
481 item->table = xstrdup(kt->name);
482 item->key = bd->key;
483 item->name = xstrdup(key_string_lookup_key(item->key, 0));
484 item->idx = -1;
486 expanded = format_expand(ft, data->format);
487 child = mode_tree_add(data->data, top, item, (uint64_t)bd,
488 expanded, NULL, 0);
489 free(expanded);
491 tmp = cmd_list_print(bd->cmdlist, 0);
492 xasprintf(&text, "#[ignore]%s", tmp);
493 free(tmp);
494 mti = mode_tree_add(data->data, child, item,
495 tag|(bd->key << 3)|(0 << 1)|1, "Command", text, -1);
496 mode_tree_draw_as_parent(mti);
497 mode_tree_no_tag(mti);
498 free(text);
500 if (bd->note != NULL)
501 xasprintf(&text, "#[ignore]%s", bd->note);
502 else
503 text = xstrdup("");
504 mti = mode_tree_add(data->data, child, item,
505 tag|(bd->key << 3)|(1 << 1)|1, "Note", text, -1);
506 mode_tree_draw_as_parent(mti);
507 mode_tree_no_tag(mti);
508 free(text);
510 if (bd->flags & KEY_BINDING_REPEAT)
511 flag = "on";
512 else
513 flag = "off";
514 mti = mode_tree_add(data->data, child, item,
515 tag|(bd->key << 3)|(2 << 1)|1, "Repeat", flag, -1);
516 mode_tree_draw_as_parent(mti);
517 mode_tree_no_tag(mti);
519 bd = key_bindings_next(kt, bd);
522 format_free(ft);
525 static void
526 window_customize_build(void *modedata,
527 __unused struct mode_tree_sort_criteria *sort_crit, __unused uint64_t *tag,
528 const char *filter)
530 struct window_customize_modedata *data = modedata;
531 struct cmd_find_state fs;
532 struct format_tree *ft;
533 u_int i;
534 struct key_table *kt;
536 for (i = 0; i < data->item_size; i++)
537 window_customize_free_item(data->item_list[i]);
538 free(data->item_list);
539 data->item_list = NULL;
540 data->item_size = 0;
542 if (cmd_find_valid_state(&data->fs))
543 cmd_find_copy_state(&fs, &data->fs);
544 else
545 cmd_find_from_pane(&fs, data->wp, 0);
547 ft = format_create_from_state(NULL, NULL, &fs);
548 format_add(ft, "is_option", "1");
549 format_add(ft, "is_key", "0");
551 window_customize_build_options(data, "Server Options",
552 (3ULL << 62)|(OPTIONS_TABLE_SERVER << 1)|1,
553 WINDOW_CUSTOMIZE_SERVER, global_options,
554 WINDOW_CUSTOMIZE_NONE, NULL,
555 WINDOW_CUSTOMIZE_NONE, NULL,
556 ft, filter, &fs);
557 window_customize_build_options(data, "Session Options",
558 (3ULL << 62)|(OPTIONS_TABLE_SESSION << 1)|1,
559 WINDOW_CUSTOMIZE_GLOBAL_SESSION, global_s_options,
560 WINDOW_CUSTOMIZE_SESSION, fs.s->options,
561 WINDOW_CUSTOMIZE_NONE, NULL,
562 ft, filter, &fs);
563 window_customize_build_options(data, "Window & Pane Options",
564 (3ULL << 62)|(OPTIONS_TABLE_WINDOW << 1)|1,
565 WINDOW_CUSTOMIZE_GLOBAL_WINDOW, global_w_options,
566 WINDOW_CUSTOMIZE_WINDOW, fs.w->options,
567 WINDOW_CUSTOMIZE_PANE, fs.wp->options,
568 ft, filter, &fs);
570 format_free(ft);
571 ft = format_create_from_state(NULL, NULL, &fs);
573 i = 0;
574 kt = key_bindings_first_table();
575 while (kt != NULL) {
576 if (!RB_EMPTY(&kt->key_bindings)) {
577 window_customize_build_keys(data, kt, ft, filter, &fs,
579 if (++i == 256)
580 break;
582 kt = key_bindings_next_table(kt);
585 format_free(ft);
588 static void
589 window_customize_draw_key(__unused struct window_customize_modedata *data,
590 struct window_customize_itemdata *item, struct screen_write_ctx *ctx,
591 u_int sx, u_int sy)
593 struct screen *s = ctx->s;
594 u_int cx = s->cx, cy = s->cy;
595 struct key_table *kt;
596 struct key_binding *bd, *default_bd;
597 const char *note, *period = "";
598 char *cmd, *default_cmd;
600 if (item == NULL || !window_customize_get_key(item, &kt, &bd))
601 return;
603 note = bd->note;
604 if (note == NULL)
605 note = "There is no note for this key.";
606 if (*note != '\0' && note[strlen (note) - 1] != '.')
607 period = ".";
608 if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s%s",
609 note, period))
610 return;
611 screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
612 if (s->cy >= cy + sy - 1)
613 return;
615 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
616 &grid_default_cell, "This key is in the %s table.", kt->name))
617 return;
618 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
619 &grid_default_cell, "This key %s repeat.",
620 (bd->flags & KEY_BINDING_REPEAT) ? "does" : "does not"))
621 return;
622 screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
623 if (s->cy >= cy + sy - 1)
624 return;
626 cmd = cmd_list_print(bd->cmdlist, 0);
627 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
628 &grid_default_cell, "Command: %s", cmd)) {
629 free(cmd);
630 return;
632 default_bd = key_bindings_get_default(kt, bd->key);
633 if (default_bd != NULL) {
634 default_cmd = cmd_list_print(default_bd->cmdlist, 0);
635 if (strcmp(cmd, default_cmd) != 0 &&
636 !screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
637 &grid_default_cell, "The default is: %s", default_cmd)) {
638 free(default_cmd);
639 free(cmd);
640 return;
642 free(default_cmd);
644 free(cmd);
647 static void
648 window_customize_draw_option(struct window_customize_modedata *data,
649 struct window_customize_itemdata *item, struct screen_write_ctx *ctx,
650 u_int sx, u_int sy)
652 struct screen *s = ctx->s;
653 u_int cx = s->cx, cy = s->cy;
654 int idx;
655 struct options_entry *o, *parent;
656 struct options *go, *wo;
657 const struct options_table_entry *oe;
658 struct grid_cell gc;
659 const char **choice, *text, *name;
660 const char *space = "", *unit = "";
661 char *value = NULL, *expanded;
662 char *default_value = NULL;
663 char choices[256] = "";
664 struct cmd_find_state fs;
665 struct format_tree *ft;
667 if (!window_customize_check_item(data, item, &fs))
668 return;
669 name = item->name;
670 idx = item->idx;
672 o = options_get(item->oo, name);
673 if (o == NULL)
674 return;
675 oe = options_table_entry(o);
677 if (oe != NULL && oe->unit != NULL) {
678 space = " ";
679 unit = oe->unit;
681 ft = format_create_from_state(NULL, NULL, &fs);
683 if (oe == NULL)
684 text = "This is a user option.";
685 else if (oe->text == NULL)
686 text = "This option doesn't have a description.";
687 else
688 text = oe->text;
689 if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s",
690 text))
691 goto out;
692 screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
693 if (s->cy >= cy + sy - 1)
694 goto out;
696 if (oe == NULL)
697 text = "user";
698 else if ((oe->scope & (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE)) ==
699 (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE))
700 text = "window and pane";
701 else if (oe->scope & OPTIONS_TABLE_WINDOW)
702 text = "window";
703 else if (oe->scope & OPTIONS_TABLE_SESSION)
704 text = "session";
705 else
706 text = "server";
707 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
708 &grid_default_cell, "This is a %s option.", text))
709 goto out;
710 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
711 if (idx != -1) {
712 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
713 0, &grid_default_cell,
714 "This is an array option, index %u.", idx))
715 goto out;
716 } else {
717 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
718 0, &grid_default_cell, "This is an array option."))
719 goto out;
721 if (idx == -1)
722 goto out;
724 screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
725 if (s->cy >= cy + sy - 1)
726 goto out;
728 value = options_to_string(o, idx, 0);
729 if (oe != NULL && idx == -1) {
730 default_value = options_default_to_string(oe);
731 if (strcmp(default_value, value) == 0) {
732 free(default_value);
733 default_value = NULL;
736 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
737 &grid_default_cell, "Option value: %s%s%s", value, space, unit))
738 goto out;
739 if (oe == NULL || oe->type == OPTIONS_TABLE_STRING) {
740 expanded = format_expand(ft, value);
741 if (strcmp(expanded, value) != 0) {
742 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
743 0, &grid_default_cell, "This expands to: %s",
744 expanded))
745 goto out;
747 free(expanded);
749 if (oe != NULL && oe->type == OPTIONS_TABLE_CHOICE) {
750 for (choice = oe->choices; *choice != NULL; choice++) {
751 strlcat(choices, *choice, sizeof choices);
752 strlcat(choices, ", ", sizeof choices);
754 choices[strlen(choices) - 2] = '\0';
755 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
756 &grid_default_cell, "Available values are: %s",
757 choices))
758 goto out;
760 if (oe != NULL && oe->type == OPTIONS_TABLE_COLOUR) {
761 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 1,
762 &grid_default_cell, "This is a colour option: "))
763 goto out;
764 memcpy(&gc, &grid_default_cell, sizeof gc);
765 gc.fg = options_get_number(item->oo, name);
766 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &gc,
767 "EXAMPLE"))
768 goto out;
770 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_STYLE)) {
771 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 1,
772 &grid_default_cell, "This is a style option: "))
773 goto out;
774 style_apply(&gc, item->oo, name, ft);
775 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &gc,
776 "EXAMPLE"))
777 goto out;
779 if (default_value != NULL) {
780 if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
781 &grid_default_cell, "The default is: %s%s%s", default_value,
782 space, unit))
783 goto out;
786 screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
787 if (s->cy > cy + sy - 1)
788 goto out;
789 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
790 wo = NULL;
791 go = NULL;
792 } else {
793 switch (item->scope) {
794 case WINDOW_CUSTOMIZE_PANE:
795 wo = options_get_parent(item->oo);
796 go = options_get_parent(wo);
797 break;
798 case WINDOW_CUSTOMIZE_WINDOW:
799 case WINDOW_CUSTOMIZE_SESSION:
800 wo = NULL;
801 go = options_get_parent(item->oo);
802 break;
803 default:
804 wo = NULL;
805 go = NULL;
806 break;
809 if (wo != NULL && options_owner(o) != wo) {
810 parent = options_get_only(wo, name);
811 if (parent != NULL) {
812 value = options_to_string(parent, -1 , 0);
813 if (!screen_write_text(ctx, s->cx, sx,
814 sy - (s->cy - cy), 0, &grid_default_cell,
815 "Window value (from window %u): %s%s%s", fs.wl->idx,
816 value, space, unit))
817 goto out;
820 if (go != NULL && options_owner(o) != go) {
821 parent = options_get_only(go, name);
822 if (parent != NULL) {
823 value = options_to_string(parent, -1 , 0);
824 if (!screen_write_text(ctx, s->cx, sx,
825 sy - (s->cy - cy), 0, &grid_default_cell,
826 "Global value: %s%s%s", value, space, unit))
827 goto out;
831 out:
832 free(value);
833 free(default_value);
834 format_free(ft);
837 static void
838 window_customize_draw(void *modedata, void *itemdata,
839 struct screen_write_ctx *ctx, u_int sx, u_int sy)
841 struct window_customize_modedata *data = modedata;
842 struct window_customize_itemdata *item = itemdata;
844 if (item == NULL)
845 return;
847 if (item->scope == WINDOW_CUSTOMIZE_KEY)
848 window_customize_draw_key(data, item, ctx, sx, sy);
849 else
850 window_customize_draw_option(data, item, ctx, sx, sy);
853 static void
854 window_customize_menu(void *modedata, struct client *c, key_code key)
856 struct window_customize_modedata *data = modedata;
857 struct window_pane *wp = data->wp;
858 struct window_mode_entry *wme;
860 wme = TAILQ_FIRST(&wp->modes);
861 if (wme == NULL || wme->data != modedata)
862 return;
863 window_customize_key(wme, c, NULL, NULL, key, NULL);
866 static u_int
867 window_customize_height(__unused void *modedata, __unused u_int height)
869 return (12);
872 static struct screen *
873 window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
874 struct args *args)
876 struct window_pane *wp = wme->wp;
877 struct window_customize_modedata *data;
878 struct screen *s;
880 wme->data = data = xcalloc(1, sizeof *data);
881 data->wp = wp;
882 data->references = 1;
884 memcpy(&data->fs, fs, sizeof data->fs);
886 if (args == NULL || !args_has(args, 'F'))
887 data->format = xstrdup(WINDOW_CUSTOMIZE_DEFAULT_FORMAT);
888 else
889 data->format = xstrdup(args_get(args, 'F'));
891 data->data = mode_tree_start(wp, args, window_customize_build,
892 window_customize_draw, NULL, window_customize_menu,
893 window_customize_height, NULL, data, window_customize_menu_items,
894 NULL, 0, &s);
895 mode_tree_zoom(data->data, args);
897 mode_tree_build(data->data);
898 mode_tree_draw(data->data);
900 return (s);
903 static void
904 window_customize_destroy(struct window_customize_modedata *data)
906 u_int i;
908 if (--data->references != 0)
909 return;
911 for (i = 0; i < data->item_size; i++)
912 window_customize_free_item(data->item_list[i]);
913 free(data->item_list);
915 free(data->format);
917 free(data);
920 static void
921 window_customize_free(struct window_mode_entry *wme)
923 struct window_customize_modedata *data = wme->data;
925 if (data == NULL)
926 return;
928 data->dead = 1;
929 mode_tree_free(data->data);
930 window_customize_destroy(data);
933 static void
934 window_customize_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
936 struct window_customize_modedata *data = wme->data;
938 mode_tree_resize(data->data, sx, sy);
941 static void
942 window_customize_free_callback(void *modedata)
944 window_customize_destroy(modedata);
947 static void
948 window_customize_free_item_callback(void *itemdata)
950 struct window_customize_itemdata *item = itemdata;
951 struct window_customize_modedata *data = item->data;
953 window_customize_free_item(item);
954 window_customize_destroy(data);
957 static int
958 window_customize_set_option_callback(struct client *c, void *itemdata,
959 const char *s, __unused int done)
961 struct window_customize_itemdata *item = itemdata;
962 struct window_customize_modedata *data = item->data;
963 struct options_entry *o;
964 const struct options_table_entry *oe;
965 struct options *oo = item->oo;
966 const char *name = item->name;
967 char *cause;
968 int idx = item->idx;
970 if (s == NULL || *s == '\0' || data->dead)
971 return (0);
972 if (item == NULL || !window_customize_check_item(data, item, NULL))
973 return (0);
974 o = options_get(oo, name);
975 if (o == NULL)
976 return (0);
977 oe = options_table_entry(o);
979 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
980 if (idx == -1) {
981 for (idx = 0; idx < INT_MAX; idx++) {
982 if (options_array_get(o, idx) == NULL)
983 break;
986 if (options_array_set(o, idx, s, 0, &cause) != 0)
987 goto fail;
988 } else {
989 if (options_from_string(oo, oe, name, s, 0, &cause) != 0)
990 goto fail;
993 options_push_changes(item->name);
994 mode_tree_build(data->data);
995 mode_tree_draw(data->data);
996 data->wp->flags |= PANE_REDRAW;
998 return (0);
1000 fail:
1001 *cause = toupper((u_char)*cause);
1002 status_message_set(c, -1, 1, 0, "%s", cause);
1003 free(cause);
1004 return (0);
1007 static void
1008 window_customize_set_option(struct client *c,
1009 struct window_customize_modedata *data,
1010 struct window_customize_itemdata *item, int global, int pane)
1012 struct options_entry *o;
1013 const struct options_table_entry *oe;
1014 struct options *oo;
1015 struct window_customize_itemdata *new_item;
1016 int flag, idx = item->idx;
1017 enum window_customize_scope scope = WINDOW_CUSTOMIZE_NONE;
1018 u_int choice;
1019 const char *name = item->name, *space = "";
1020 char *prompt, *value, *text;
1021 struct cmd_find_state fs;
1023 if (item == NULL || !window_customize_check_item(data, item, &fs))
1024 return;
1025 o = options_get(item->oo, name);
1026 if (o == NULL)
1027 return;
1029 oe = options_table_entry(o);
1030 if (oe != NULL && ~oe->scope & OPTIONS_TABLE_PANE)
1031 pane = 0;
1032 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
1033 scope = item->scope;
1034 oo = item->oo;
1035 } else {
1036 if (global) {
1037 switch (item->scope) {
1038 case WINDOW_CUSTOMIZE_NONE:
1039 case WINDOW_CUSTOMIZE_KEY:
1040 case WINDOW_CUSTOMIZE_SERVER:
1041 case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
1042 case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
1043 scope = item->scope;
1044 break;
1045 case WINDOW_CUSTOMIZE_SESSION:
1046 scope = WINDOW_CUSTOMIZE_GLOBAL_SESSION;
1047 break;
1048 case WINDOW_CUSTOMIZE_WINDOW:
1049 case WINDOW_CUSTOMIZE_PANE:
1050 scope = WINDOW_CUSTOMIZE_GLOBAL_WINDOW;
1051 break;
1053 } else {
1054 switch (item->scope) {
1055 case WINDOW_CUSTOMIZE_NONE:
1056 case WINDOW_CUSTOMIZE_KEY:
1057 case WINDOW_CUSTOMIZE_SERVER:
1058 case WINDOW_CUSTOMIZE_SESSION:
1059 scope = item->scope;
1060 break;
1061 case WINDOW_CUSTOMIZE_WINDOW:
1062 case WINDOW_CUSTOMIZE_PANE:
1063 if (pane)
1064 scope = WINDOW_CUSTOMIZE_PANE;
1065 else
1066 scope = WINDOW_CUSTOMIZE_WINDOW;
1067 break;
1068 case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
1069 scope = WINDOW_CUSTOMIZE_SESSION;
1070 break;
1071 case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
1072 if (pane)
1073 scope = WINDOW_CUSTOMIZE_PANE;
1074 else
1075 scope = WINDOW_CUSTOMIZE_WINDOW;
1076 break;
1079 if (scope == item->scope)
1080 oo = item->oo;
1081 else
1082 oo = window_customize_get_tree(scope, &fs);
1085 if (oe != NULL && oe->type == OPTIONS_TABLE_FLAG) {
1086 flag = options_get_number(oo, name);
1087 options_set_number(oo, name, !flag);
1088 } else if (oe != NULL && oe->type == OPTIONS_TABLE_CHOICE) {
1089 choice = options_get_number(oo, name);
1090 if (oe->choices[choice + 1] == NULL)
1091 choice = 0;
1092 else
1093 choice++;
1094 options_set_number(oo, name, choice);
1095 } else {
1096 text = window_customize_scope_text(scope, &fs);
1097 if (*text != '\0')
1098 space = ", for ";
1099 else if (scope != WINDOW_CUSTOMIZE_SERVER)
1100 space = ", global";
1101 if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
1102 if (idx == -1) {
1103 xasprintf(&prompt, "(%s[+]%s%s) ", name, space,
1104 text);
1105 } else {
1106 xasprintf(&prompt, "(%s[%d]%s%s) ", name, idx,
1107 space, text);
1109 } else
1110 xasprintf(&prompt, "(%s%s%s) ", name, space, text);
1111 free(text);
1113 value = options_to_string(o, idx, 0);
1115 new_item = xcalloc(1, sizeof *new_item);
1116 new_item->data = data;
1117 new_item->scope = scope;
1118 new_item->oo = oo;
1119 new_item->name = xstrdup(name);
1120 new_item->idx = idx;
1122 data->references++;
1123 status_prompt_set(c, NULL, prompt, value,
1124 window_customize_set_option_callback,
1125 window_customize_free_item_callback, new_item,
1126 PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1128 free(prompt);
1129 free(value);
1133 static void
1134 window_customize_unset_option(struct window_customize_modedata *data,
1135 struct window_customize_itemdata *item)
1137 struct options_entry *o;
1139 if (item == NULL || !window_customize_check_item(data, item, NULL))
1140 return;
1142 o = options_get(item->oo, item->name);
1143 if (o == NULL)
1144 return;
1145 if (item->idx != -1 && item == mode_tree_get_current(data->data))
1146 mode_tree_up(data->data, 0);
1147 options_remove_or_default(o, item->idx, NULL);
1150 static void
1151 window_customize_reset_option(struct window_customize_modedata *data,
1152 struct window_customize_itemdata *item)
1154 struct options *oo;
1155 struct options_entry *o;
1157 if (item == NULL || !window_customize_check_item(data, item, NULL))
1158 return;
1159 if (item->idx != -1)
1160 return;
1162 oo = item->oo;
1163 while (oo != NULL) {
1164 o = options_get_only(item->oo, item->name);
1165 if (o != NULL)
1166 options_remove_or_default(o, -1, NULL);
1167 oo = options_get_parent(oo);
1171 static int
1172 window_customize_set_command_callback(struct client *c, void *itemdata,
1173 const char *s, __unused int done)
1175 struct window_customize_itemdata *item = itemdata;
1176 struct window_customize_modedata *data = item->data;
1177 struct key_binding *bd;
1178 struct cmd_parse_result *pr;
1179 char *error;
1181 if (s == NULL || *s == '\0' || data->dead)
1182 return (0);
1183 if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1184 return (0);
1186 pr = cmd_parse_from_string(s, NULL);
1187 switch (pr->status) {
1188 case CMD_PARSE_ERROR:
1189 error = pr->error;
1190 goto fail;
1191 case CMD_PARSE_SUCCESS:
1192 break;
1194 cmd_list_free(bd->cmdlist);
1195 bd->cmdlist = pr->cmdlist;
1197 mode_tree_build(data->data);
1198 mode_tree_draw(data->data);
1199 data->wp->flags |= PANE_REDRAW;
1201 return (0);
1203 fail:
1204 *error = toupper((u_char)*error);
1205 status_message_set(c, -1, 1, 0, "%s", error);
1206 free(error);
1207 return (0);
1210 static int
1211 window_customize_set_note_callback(__unused struct client *c, void *itemdata,
1212 const char *s, __unused int done)
1214 struct window_customize_itemdata *item = itemdata;
1215 struct window_customize_modedata *data = item->data;
1216 struct key_binding *bd;
1218 if (s == NULL || *s == '\0' || data->dead)
1219 return (0);
1220 if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1221 return (0);
1223 free((void *)bd->note);
1224 bd->note = xstrdup(s);
1226 mode_tree_build(data->data);
1227 mode_tree_draw(data->data);
1228 data->wp->flags |= PANE_REDRAW;
1230 return (0);
1233 static void
1234 window_customize_set_key(struct client *c,
1235 struct window_customize_modedata *data,
1236 struct window_customize_itemdata *item)
1238 key_code key = item->key;
1239 struct key_binding *bd;
1240 const char *s;
1241 char *prompt, *value;
1242 struct window_customize_itemdata *new_item;
1244 if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1245 return;
1247 s = mode_tree_get_current_name(data->data);
1248 if (strcmp(s, "Repeat") == 0)
1249 bd->flags ^= KEY_BINDING_REPEAT;
1250 else if (strcmp(s, "Command") == 0) {
1251 xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
1252 value = cmd_list_print(bd->cmdlist, 0);
1254 new_item = xcalloc(1, sizeof *new_item);
1255 new_item->data = data;
1256 new_item->scope = item->scope;
1257 new_item->table = xstrdup(item->table);
1258 new_item->key = key;
1260 data->references++;
1261 status_prompt_set(c, NULL, prompt, value,
1262 window_customize_set_command_callback,
1263 window_customize_free_item_callback, new_item,
1264 PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1265 free(prompt);
1266 free(value);
1267 } else if (strcmp(s, "Note") == 0) {
1268 xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
1270 new_item = xcalloc(1, sizeof *new_item);
1271 new_item->data = data;
1272 new_item->scope = item->scope;
1273 new_item->table = xstrdup(item->table);
1274 new_item->key = key;
1276 data->references++;
1277 status_prompt_set(c, NULL, prompt,
1278 (bd->note == NULL ? "" : bd->note),
1279 window_customize_set_note_callback,
1280 window_customize_free_item_callback, new_item,
1281 PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1282 free(prompt);
1286 static void
1287 window_customize_unset_key(struct window_customize_modedata *data,
1288 struct window_customize_itemdata *item)
1290 struct key_table *kt;
1291 struct key_binding *bd;
1293 if (item == NULL || !window_customize_get_key(item, &kt, &bd))
1294 return;
1296 if (item == mode_tree_get_current(data->data)) {
1297 mode_tree_collapse_current(data->data);
1298 mode_tree_up(data->data, 0);
1300 key_bindings_remove(kt->name, bd->key);
1303 static void
1304 window_customize_reset_key(struct window_customize_modedata *data,
1305 struct window_customize_itemdata *item)
1307 struct key_table *kt;
1308 struct key_binding *dd, *bd;
1310 if (item == NULL || !window_customize_get_key(item, &kt, &bd))
1311 return;
1313 dd = key_bindings_get_default(kt, bd->key);
1314 if (dd != NULL && bd->cmdlist == dd->cmdlist)
1315 return;
1316 if (dd == NULL && item == mode_tree_get_current(data->data)) {
1317 mode_tree_collapse_current(data->data);
1318 mode_tree_up(data->data, 0);
1320 key_bindings_reset(kt->name, bd->key);
1323 static void
1324 window_customize_change_each(void *modedata, void *itemdata,
1325 __unused struct client *c, __unused key_code key)
1327 struct window_customize_modedata *data = modedata;
1328 struct window_customize_itemdata *item = itemdata;
1330 switch (data->change) {
1331 case WINDOW_CUSTOMIZE_UNSET:
1332 if (item->scope == WINDOW_CUSTOMIZE_KEY)
1333 window_customize_unset_key(data, item);
1334 else
1335 window_customize_unset_option(data, item);
1336 break;
1337 case WINDOW_CUSTOMIZE_RESET:
1338 if (item->scope == WINDOW_CUSTOMIZE_KEY)
1339 window_customize_reset_key(data, item);
1340 else
1341 window_customize_reset_option(data, item);
1342 break;
1344 if (item->scope != WINDOW_CUSTOMIZE_KEY)
1345 options_push_changes(item->name);
1348 static int
1349 window_customize_change_current_callback(__unused struct client *c,
1350 void *modedata, const char *s, __unused int done)
1352 struct window_customize_modedata *data = modedata;
1353 struct window_customize_itemdata *item;
1355 if (s == NULL || *s == '\0' || data->dead)
1356 return (0);
1357 if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
1358 return (0);
1360 item = mode_tree_get_current(data->data);
1361 switch (data->change) {
1362 case WINDOW_CUSTOMIZE_UNSET:
1363 if (item->scope == WINDOW_CUSTOMIZE_KEY)
1364 window_customize_unset_key(data, item);
1365 else
1366 window_customize_unset_option(data, item);
1367 break;
1368 case WINDOW_CUSTOMIZE_RESET:
1369 if (item->scope == WINDOW_CUSTOMIZE_KEY)
1370 window_customize_reset_key(data, item);
1371 else
1372 window_customize_reset_option(data, item);
1373 break;
1375 if (item->scope != WINDOW_CUSTOMIZE_KEY)
1376 options_push_changes(item->name);
1377 mode_tree_build(data->data);
1378 mode_tree_draw(data->data);
1379 data->wp->flags |= PANE_REDRAW;
1381 return (0);
1384 static int
1385 window_customize_change_tagged_callback(struct client *c, void *modedata,
1386 const char *s, __unused int done)
1388 struct window_customize_modedata *data = modedata;
1390 if (s == NULL || *s == '\0' || data->dead)
1391 return (0);
1392 if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
1393 return (0);
1395 mode_tree_each_tagged(data->data, window_customize_change_each, c,
1396 KEYC_NONE, 0);
1397 mode_tree_build(data->data);
1398 mode_tree_draw(data->data);
1399 data->wp->flags |= PANE_REDRAW;
1401 return (0);
1404 static void
1405 window_customize_key(struct window_mode_entry *wme, struct client *c,
1406 __unused struct session *s, __unused struct winlink *wl, key_code key,
1407 struct mouse_event *m)
1409 struct window_pane *wp = wme->wp;
1410 struct window_customize_modedata *data = wme->data;
1411 struct window_customize_itemdata *item, *new_item;
1412 int finished, idx;
1413 char *prompt;
1414 u_int tagged;
1416 item = mode_tree_get_current(data->data);
1417 finished = mode_tree_key(data->data, c, &key, m, NULL, NULL);
1418 if (item != (new_item = mode_tree_get_current(data->data)))
1419 item = new_item;
1421 switch (key) {
1422 case '\r':
1423 case 's':
1424 if (item == NULL)
1425 break;
1426 if (item->scope == WINDOW_CUSTOMIZE_KEY)
1427 window_customize_set_key(c, data, item);
1428 else {
1429 window_customize_set_option(c, data, item, 0, 1);
1430 options_push_changes(item->name);
1432 mode_tree_build(data->data);
1433 break;
1434 case 'w':
1435 if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
1436 break;
1437 window_customize_set_option(c, data, item, 0, 0);
1438 options_push_changes(item->name);
1439 mode_tree_build(data->data);
1440 break;
1441 case 'S':
1442 case 'W':
1443 if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
1444 break;
1445 window_customize_set_option(c, data, item, 1, 0);
1446 options_push_changes(item->name);
1447 mode_tree_build(data->data);
1448 break;
1449 case 'd':
1450 if (item == NULL || item->idx != -1)
1451 break;
1452 xasprintf(&prompt, "Reset %s to default? ", item->name);
1453 data->references++;
1454 data->change = WINDOW_CUSTOMIZE_RESET;
1455 status_prompt_set(c, NULL, prompt, "",
1456 window_customize_change_current_callback,
1457 window_customize_free_callback, data,
1458 PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1459 free(prompt);
1460 break;
1461 case 'D':
1462 tagged = mode_tree_count_tagged(data->data);
1463 if (tagged == 0)
1464 break;
1465 xasprintf(&prompt, "Reset %u tagged to default? ", tagged);
1466 data->references++;
1467 data->change = WINDOW_CUSTOMIZE_RESET;
1468 status_prompt_set(c, NULL, prompt, "",
1469 window_customize_change_tagged_callback,
1470 window_customize_free_callback, data,
1471 PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1472 free(prompt);
1473 break;
1474 case 'u':
1475 if (item == NULL)
1476 break;
1477 idx = item->idx;
1478 if (idx != -1)
1479 xasprintf(&prompt, "Unset %s[%d]? ", item->name, idx);
1480 else
1481 xasprintf(&prompt, "Unset %s? ", item->name);
1482 data->references++;
1483 data->change = WINDOW_CUSTOMIZE_UNSET;
1484 status_prompt_set(c, NULL, prompt, "",
1485 window_customize_change_current_callback,
1486 window_customize_free_callback, data,
1487 PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1488 free(prompt);
1489 break;
1490 case 'U':
1491 tagged = mode_tree_count_tagged(data->data);
1492 if (tagged == 0)
1493 break;
1494 xasprintf(&prompt, "Unset %u tagged? ", tagged);
1495 data->references++;
1496 data->change = WINDOW_CUSTOMIZE_UNSET;
1497 status_prompt_set(c, NULL, prompt, "",
1498 window_customize_change_tagged_callback,
1499 window_customize_free_callback, data,
1500 PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1501 free(prompt);
1502 break;
1503 case 'H':
1504 data->hide_global = !data->hide_global;
1505 mode_tree_build(data->data);
1506 break;
1508 if (finished)
1509 window_pane_reset_mode(wp);
1510 else {
1511 mode_tree_draw(data->data);
1512 wp->flags |= PANE_REDRAW;