Annotation of src/usr.bin/tmux/window-customize.c, Revision 1.3
1.3 ! nicm 1: /* $OpenBSD: window-customize.c,v 1.2 2020/05/16 16:16:07 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
5: *
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.
9: *
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.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <ctype.h>
22: #include <stdlib.h>
23: #include <string.h>
24:
25: #include "tmux.h"
26:
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 *);
35:
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: "}"
44:
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 },
54:
55: { NULL, KEYC_NONE, NULL }
56: };
57:
58: const struct window_mode window_customize_mode = {
59: .name = "options-mode",
60: .default_format = WINDOW_CUSTOMIZE_DEFAULT_FORMAT,
61:
62: .init = window_customize_init,
63: .free = window_customize_free,
64: .resize = window_customize_resize,
65: .key = window_customize_key,
66: };
67:
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
77: };
78:
79: struct window_customize_itemdata {
80: struct window_customize_modedata *data;
81: enum window_customize_scope scope;
82:
83: char *table;
84: key_code key;
85:
86: struct options *oo;
87: char *name;
88: int idx;
89: };
90:
91: struct window_customize_modedata {
92: struct window_pane *wp;
93: int dead;
94: int references;
95:
96: struct mode_tree_data *data;
97: char *format;
98: int hide_global;
99:
100: struct window_customize_itemdata **item_list;
101: u_int item_size;
102:
103: struct cmd_find_state fs;
104: };
105:
106: static uint64_t
107: window_customize_get_tag(struct options_entry *o, int idx,
108: const struct options_table_entry *oe)
109: {
110: uint64_t offset;
111:
112: if (oe == NULL)
113: return ((uint64_t)o);
114: offset = ((char *)oe - (char *)options_table) / sizeof *options_table;
115: return ((2ULL << 62)|(offset << 32)|((idx + 1) << 1)|1);
116: }
117:
118: static struct options *
119: window_customize_get_tree(enum window_customize_scope scope,
120: struct cmd_find_state *fs)
121: {
122: switch (scope) {
123: case WINDOW_CUSTOMIZE_NONE:
124: case WINDOW_CUSTOMIZE_KEY:
125: return (NULL);
126: case WINDOW_CUSTOMIZE_SERVER:
127: return (global_options);
128: case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
129: return (global_s_options);
130: case WINDOW_CUSTOMIZE_SESSION:
131: return (fs->s->options);
132: case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
133: return (global_w_options);
134: case WINDOW_CUSTOMIZE_WINDOW:
135: return (fs->w->options);
136: case WINDOW_CUSTOMIZE_PANE:
137: return (fs->wp->options);
138: }
139: return (NULL);
140: }
141:
142: static int
143: window_customize_check_item(struct window_customize_modedata *data,
144: struct window_customize_itemdata *item, struct cmd_find_state *fsp)
145: {
146: struct cmd_find_state fs;
147:
148: if (fsp == NULL)
149: fsp = &fs;
150:
151: if (cmd_find_valid_state(&data->fs))
152: cmd_find_copy_state(fsp, &data->fs);
153: else
154: cmd_find_from_pane(fsp, data->wp, 0);
155: return (item->oo == window_customize_get_tree(item->scope, fsp));
156: }
157:
158: static int
159: window_customize_get_key(struct window_customize_itemdata *item,
160: struct key_table **ktp, struct key_binding **bdp)
161: {
162: struct key_table *kt;
163: struct key_binding *bd;
164:
165: kt = key_bindings_get_table(item->table, 0);
166: if (kt == NULL)
167: return (0);
168: bd = key_bindings_get(kt, item->key);
169: if (bd == NULL)
170: return (0);
171:
172: if (ktp != NULL)
173: *ktp = kt;
174: if (bdp != NULL)
175: *bdp = bd;
176: return (1);
177: }
178:
179: static char *
180: window_customize_scope_text(enum window_customize_scope scope,
181: struct cmd_find_state *fs)
182: {
183: char *s;
184: u_int idx;
185:
186: switch (scope) {
187: case WINDOW_CUSTOMIZE_NONE:
188: case WINDOW_CUSTOMIZE_KEY:
189: case WINDOW_CUSTOMIZE_SERVER:
190: case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
191: case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
192: s = xstrdup("");
193: break;
194: case WINDOW_CUSTOMIZE_PANE:
195: window_pane_index(fs->wp, &idx);
196: xasprintf(&s, "pane %u", idx);
197: break;
198: case WINDOW_CUSTOMIZE_SESSION:
199: xasprintf(&s, "session %s", fs->s->name);
200: break;
201: case WINDOW_CUSTOMIZE_WINDOW:
202: xasprintf(&s, "window %u", fs->wl->idx);
203: break;
204: }
205: return (s);
206: }
207:
208: static struct window_customize_itemdata *
209: window_customize_add_item(struct window_customize_modedata *data)
210: {
211: struct window_customize_itemdata *item;
212:
213: data->item_list = xreallocarray(data->item_list, data->item_size + 1,
214: sizeof *data->item_list);
215: item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
216: return (item);
217: }
218:
219: static void
220: window_customize_free_item(struct window_customize_itemdata *item)
221: {
222: free(item->table);
223: free(item->name);
224: free(item);
225: }
226:
227: static void
228: window_customize_build_array(struct window_customize_modedata *data,
229: struct mode_tree_item *top, enum window_customize_scope scope,
230: struct options_entry *o, struct format_tree *ft)
231: {
232: const struct options_table_entry *oe = options_table_entry(o);
233: struct options *oo = options_owner(o);
234: struct window_customize_itemdata *item;
235: struct options_array_item *ai;
236: char *name, *value, *text;
237: u_int idx;
238: uint64_t tag;
239:
240: ai = options_array_first(o);
241: while (ai != NULL) {
242: idx = options_array_item_index(ai);
243:
244: xasprintf(&name, "%s[%u]", options_name(o), idx);
245: format_add(ft, "option_name", "%s", name);
246: value = options_to_string(o, idx, 0);
247: format_add(ft, "option_value", "%s", value);
248:
249: item = window_customize_add_item(data);
250: item->scope = scope;
251: item->oo = oo;
252: item->name = xstrdup(options_name(o));
253: item->idx = idx;
254:
255: text = format_expand(ft, data->format);
256: tag = window_customize_get_tag(o, idx, oe);
257: mode_tree_add(data->data, top, item, tag, name, text, -1);
258: free(text);
259:
260: free(name);
261: free(value);
262:
263: ai = options_array_next(ai);
264: }
265: }
266:
267: static void
268: window_customize_build_option(struct window_customize_modedata *data,
269: struct mode_tree_item *top, enum window_customize_scope scope,
270: struct options_entry *o, struct format_tree *ft,
271: const char *filter, struct cmd_find_state *fs)
272: {
273: const struct options_table_entry *oe = options_table_entry(o);
274: struct options *oo = options_owner(o);
275: const char *name = options_name(o);
276: struct window_customize_itemdata *item;
277: char *text, *expanded, *value;
278: int global = 0, array = 0;
279: uint64_t tag;
280:
281: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_HOOK))
282: return;
283: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY))
284: array = 1;
285:
286: if (scope == WINDOW_CUSTOMIZE_SERVER ||
287: scope == WINDOW_CUSTOMIZE_GLOBAL_SESSION ||
288: scope == WINDOW_CUSTOMIZE_GLOBAL_WINDOW)
289: global = 1;
290: if (data->hide_global && global)
291: return;
292:
293: format_add(ft, "option_name", "%s", name);
294: format_add(ft, "option_is_global", "%d", global);
295: format_add(ft, "option_is_array", "%d", array);
296:
297: text = window_customize_scope_text(scope, fs);
298: format_add(ft, "option_scope", "%s", text);
299: free(text);
300:
301: if (oe != NULL && oe->unit != NULL)
302: format_add(ft, "option_unit", "%s", oe->unit);
303: else
304: format_add(ft, "option_unit", "%s", "");
305:
306: if (!array) {
307: value = options_to_string(o, -1, 0);
308: format_add(ft, "option_value", "%s", value);
309: free(value);
310: }
311:
312: if (filter != NULL) {
313: expanded = format_expand(ft, filter);
314: if (!format_true(expanded)) {
315: free(expanded);
316: return;
317: }
318: free(expanded);
319: }
320: item = window_customize_add_item(data);
321: item->oo = oo;
322: item->scope = scope;
323: item->name = xstrdup(name);
324: item->idx = -1;
325:
326: if (array)
327: text = NULL;
328: else
329: text = format_expand(ft, data->format);
330: tag = window_customize_get_tag(o, -1, oe);
331: top = mode_tree_add(data->data, top, item, tag, name, text, 0);
332: free(text);
333:
334: if (array)
335: window_customize_build_array(data, top, scope, o, ft);
336: }
337:
338: static void
339: window_customize_find_user_options(struct options *oo, const char ***list,
340: u_int *size)
341: {
342: struct options_entry *o;
343: const char *name;
344: u_int i;
345:
346: o = options_first(oo);
347: while (o != NULL) {
348: name = options_name(o);
349: if (*name != '@') {
350: o = options_next(o);
351: continue;
352: }
353: for (i = 0; i < *size; i++) {
354: if (strcmp((*list)[i], name) == 0)
355: break;
356: }
357: if (i != *size) {
358: o = options_next(o);
359: continue;
360: }
361: *list = xreallocarray(*list, (*size) + 1, sizeof **list);
362: (*list)[(*size)++] = name;
363:
364: o = options_next(o);
365: }
366: }
367:
368: static void
369: window_customize_build_options(struct window_customize_modedata *data,
370: const char *title, uint64_t tag,
371: enum window_customize_scope scope0, struct options *oo0,
372: enum window_customize_scope scope1, struct options *oo1,
373: enum window_customize_scope scope2, struct options *oo2,
374: struct format_tree *ft, const char *filter, struct cmd_find_state *fs)
375: {
376: struct mode_tree_item *top;
377: struct options_entry *o, *loop;
378: const char **list = NULL, *name;
379: u_int size = 0, i;
380: enum window_customize_scope scope;
381:
382: top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
383:
384: /*
385: * We get the options from the first tree, but build it using the
386: * values from the other two. Any tree can have user options so we need
387: * to build a separate list of them.
388: */
389:
390: window_customize_find_user_options(oo0, &list, &size);
391: if (oo1 != NULL)
392: window_customize_find_user_options(oo1, &list, &size);
393: if (oo2 != NULL)
394: window_customize_find_user_options(oo2, &list, &size);
395:
396: for (i = 0; i < size; i++) {
397: if (oo2 != NULL)
398: o = options_get(oo0, list[i]);
399: else if (oo1 != NULL)
400: o = options_get(oo1, list[i]);
401: else
402: o = options_get(oo2, list[i]);
403: if (options_owner(o) == oo2)
404: scope = scope2;
405: else if (options_owner(o) == oo1)
406: scope = scope1;
407: else
408: scope = scope0;
409: window_customize_build_option(data, top, scope, o, ft, filter,
410: fs);
411: }
412: free(list);
413:
414: loop = options_first(oo0);
415: while (loop != NULL) {
416: name = options_name(loop);
417: if (*name == '@') {
418: loop = options_next(loop);
419: continue;
420: }
421: if (oo2 != NULL)
422: o = options_get(oo2, name);
423: else if (oo1 != NULL)
424: o = options_get(oo1, name);
425: else
426: o = loop;
427: if (options_owner(o) == oo2)
428: scope = scope2;
429: else if (options_owner(o) == oo1)
430: scope = scope1;
431: else
432: scope = scope0;
433: window_customize_build_option(data, top, scope, o, ft, filter,
434: fs);
435: loop = options_next(loop);
436: }
437: }
438:
439: static void
440: window_customize_build_keys(struct window_customize_modedata *data,
441: struct key_table *kt, struct format_tree *ft, const char *filter,
442: struct cmd_find_state *fs, u_int number)
443: {
444: struct mode_tree_item *top, *child, *mti;
445: struct window_customize_itemdata *item;
446: struct key_binding *bd;
447: char *title, *text, *tmp, *expanded;
448: const char *flag;
449: uint64_t tag;
450:
451: tag = (1ULL << 62)|((uint64_t)number << 54)|1;
452:
453: xasprintf(&title, "Key Table - %s", kt->name);
454: top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
455: free(title);
456:
457: ft = format_create_from_state(NULL, NULL, fs);
458: format_add(ft, "is_option", "0");
459: format_add(ft, "is_key", "1");
460:
461: bd = key_bindings_first(kt);
462: while (bd != NULL) {
1.3 ! nicm 463: format_add(ft, "key", "%s", key_string_lookup_key(bd->key, 0));
1.1 nicm 464: if (bd->note != NULL)
465: format_add(ft, "key_note", "%s", bd->note);
466: if (filter != NULL) {
467: expanded = format_expand(ft, filter);
468: if (!format_true(expanded)) {
469: free(expanded);
470: continue;
471: }
472: free(expanded);
473: }
474:
475: item = window_customize_add_item(data);
476: item->scope = WINDOW_CUSTOMIZE_KEY;
477: item->table = xstrdup(kt->name);
478: item->key = bd->key;
479:
480: expanded = format_expand(ft, data->format);
481: child = mode_tree_add(data->data, top, item, (uint64_t)bd,
482: expanded, NULL, 0);
483: free(expanded);
484:
485: tmp = cmd_list_print(bd->cmdlist, 0);
486: xasprintf(&text, "#[ignore]%s", tmp);
487: free(tmp);
488: mti = mode_tree_add(data->data, child, item,
489: tag|(bd->key << 3)|(0 << 1)|1, "Command", text, -1);
490: mode_tree_draw_as_parent(mti);
491: free(text);
492:
493: if (bd->note != NULL)
494: xasprintf(&text, "#[ignore]%s", bd->note);
495: else
496: text = xstrdup("");
497: mti = mode_tree_add(data->data, child, item,
498: tag|(bd->key << 3)|(1 << 1)|1, "Note", text, -1);
499: mode_tree_draw_as_parent(mti);
500: free(text);
501:
502: if (bd->flags & KEY_BINDING_REPEAT)
503: flag = "on";
504: else
505: flag = "off";
506: mti = mode_tree_add(data->data, child, item,
507: tag|(bd->key << 3)|(2 << 1)|1, "Repeat", flag, -1);
508: mode_tree_draw_as_parent(mti);
509:
510: bd = key_bindings_next(kt, bd);
511: }
512:
513: format_free(ft);
514: }
515:
516: static void
517: window_customize_build(void *modedata,
518: __unused struct mode_tree_sort_criteria *sort_crit, __unused uint64_t *tag,
519: const char *filter)
520: {
521: struct window_customize_modedata *data = modedata;
522: struct cmd_find_state fs;
523: struct format_tree *ft;
524: u_int i;
525: struct key_table *kt;
526:
527: for (i = 0; i < data->item_size; i++)
528: window_customize_free_item(data->item_list[i]);
529: free(data->item_list);
530: data->item_list = NULL;
531: data->item_size = 0;
532:
533: if (cmd_find_valid_state(&data->fs))
534: cmd_find_copy_state(&fs, &data->fs);
535: else
536: cmd_find_from_pane(&fs, data->wp, 0);
537:
538: ft = format_create_from_state(NULL, NULL, &fs);
539: format_add(ft, "is_option", "1");
540: format_add(ft, "is_key", "0");
541:
542: window_customize_build_options(data, "Server Options",
543: (3ULL << 62)|(OPTIONS_TABLE_SERVER << 1)|1,
544: WINDOW_CUSTOMIZE_SERVER, global_options,
545: WINDOW_CUSTOMIZE_NONE, NULL,
546: WINDOW_CUSTOMIZE_NONE, NULL,
547: ft, filter, &fs);
548: window_customize_build_options(data, "Session Options",
549: (3ULL << 62)|(OPTIONS_TABLE_SESSION << 1)|1,
550: WINDOW_CUSTOMIZE_GLOBAL_SESSION, global_s_options,
551: WINDOW_CUSTOMIZE_SESSION, fs.s->options,
552: WINDOW_CUSTOMIZE_NONE, NULL,
553: ft, filter, &fs);
554: window_customize_build_options(data, "Window & Pane Options",
555: (3ULL << 62)|(OPTIONS_TABLE_WINDOW << 1)|1,
556: WINDOW_CUSTOMIZE_GLOBAL_WINDOW, global_w_options,
557: WINDOW_CUSTOMIZE_WINDOW, fs.w->options,
558: WINDOW_CUSTOMIZE_PANE, fs.wp->options,
559: ft, filter, &fs);
560:
561: format_free(ft);
562: ft = format_create_from_state(NULL, NULL, &fs);
563:
564: i = 0;
565: kt = key_bindings_first_table();
566: while (kt != NULL) {
567: if (!RB_EMPTY(&kt->key_bindings)) {
568: window_customize_build_keys(data, kt, ft, filter, &fs,
569: i);
570: if (++i == 256)
571: break;
572: }
573: kt = key_bindings_next_table(kt);
574: }
575:
576: format_free(ft);
577: }
578:
579: static void
580: window_customize_draw_key(__unused struct window_customize_modedata *data,
581: struct window_customize_itemdata *item, struct screen_write_ctx *ctx,
582: u_int sx, u_int sy)
583: {
584: struct screen *s = ctx->s;
585: u_int cx = s->cx, cy = s->cy;
586: struct key_table *kt;
587: struct key_binding *bd, *default_bd;
588: const char *note, *period = "";
589: char *cmd, *default_cmd;
590:
591: if (item == NULL || !window_customize_get_key(item, &kt, &bd))
592: return;
593:
594: note = bd->note;
595: if (note == NULL)
596: note = "There is no note for this key.";
597: if (*note != '\0' && note[strlen (note) - 1] != '.')
598: period = ".";
599: if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s%s",
600: note, period))
601: return;
602: screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
603: if (s->cy >= cy + sy - 1)
604: return;
605:
606: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
607: &grid_default_cell, "This key is in the %s table.", kt->name))
608: return;
609: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
610: &grid_default_cell, "This key %s repeat.",
611: (bd->flags & KEY_BINDING_REPEAT) ? "does" : "does not"))
612: return;
613: screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
614: if (s->cy >= cy + sy - 1)
615: return;
616:
617: cmd = cmd_list_print(bd->cmdlist, 0);
618: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
619: &grid_default_cell, "Command: %s", cmd)) {
620: free(cmd);
621: return;
622: }
623: default_bd = key_bindings_get_default(kt, bd->key);
624: if (default_bd != NULL) {
625: default_cmd = cmd_list_print(default_bd->cmdlist, 0);
626: if (strcmp(cmd, default_cmd) != 0 &&
627: !screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
628: &grid_default_cell, "The default is: %s", default_cmd)) {
629: free(default_cmd);
630: free(cmd);
631: return;
632: }
633: free(default_cmd);
634: }
635: free(cmd);
636: }
637:
638: static void
639: window_customize_draw_option(struct window_customize_modedata *data,
640: struct window_customize_itemdata *item, struct screen_write_ctx *ctx,
641: u_int sx, u_int sy)
642: {
643: struct screen *s = ctx->s;
644: u_int cx = s->cx, cy = s->cy;
645: int idx;
646: struct options_entry *o, *parent;
647: struct options *go, *wo;
648: const struct options_table_entry *oe;
649: struct grid_cell gc;
650: const char **choice, *text, *name;
651: const char *space = "", *unit = "";
652: char *value = NULL, *expanded;
653: char *default_value = NULL;
654: char choices[256] = "";
655: struct cmd_find_state fs;
656: struct format_tree *ft;
657:
658: if (!window_customize_check_item(data, item, &fs))
659: return;
660: name = item->name;
661: idx = item->idx;
662:
663: o = options_get(item->oo, name);
664: if (o == NULL)
665: return;
666: oe = options_table_entry(o);
667:
668: if (oe != NULL && oe->unit != NULL) {
669: space = " ";
670: unit = oe->unit;
671: }
672: ft = format_create_from_state(NULL, NULL, &fs);
673:
674: if (oe == NULL)
675: text = "This is a user option.";
676: else if (oe->text == NULL)
677: text = "This option doesn't have a description.";
678: else
679: text = oe->text;
680: if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s",
681: text))
682: goto out;
683: screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
684: if (s->cy >= cy + sy - 1)
685: goto out;
686:
687: if (oe == NULL)
688: text = "user";
689: else if ((oe->scope & (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE)) ==
690: (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE))
691: text = "window and pane";
692: else if (oe->scope & OPTIONS_TABLE_WINDOW)
693: text = "window";
694: else if (oe->scope & OPTIONS_TABLE_SESSION)
695: text = "session";
696: else
697: text = "server";
698: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
699: &grid_default_cell, "This is a %s option.", text))
700: goto out;
701: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
702: if (idx != -1) {
703: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
704: 0, &grid_default_cell,
705: "This is an array option, index %u.", idx))
706: goto out;
707: } else {
708: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
709: 0, &grid_default_cell, "This is an array option."))
710: goto out;
711: }
712: if (idx == -1)
713: goto out;
714: }
715: screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
716: if (s->cy >= cy + sy - 1)
717: goto out;
718:
719: value = options_to_string(o, idx, 0);
720: if (oe != NULL && idx == -1) {
721: default_value = options_default_to_string(oe);
722: if (strcmp(default_value, value) == 0) {
723: free(default_value);
724: default_value = NULL;
725: }
726: }
727: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
728: &grid_default_cell, "Option value: %s%s%s", value, space, unit))
729: goto out;
730: if (oe == NULL || oe->type == OPTIONS_TABLE_STRING) {
731: expanded = format_expand(ft, value);
732: if (strcmp(expanded, value) != 0) {
733: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy),
734: 0, &grid_default_cell, "This expands to: %s",
735: expanded))
736: goto out;
737: }
738: free(expanded);
739: }
740: if (oe != NULL && oe->type == OPTIONS_TABLE_CHOICE) {
741: for (choice = oe->choices; *choice != NULL; choice++) {
742: strlcat(choices, *choice, sizeof choices);
743: strlcat(choices, ", ", sizeof choices);
744: }
745: choices[strlen(choices) - 2] = '\0';
746: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
747: &grid_default_cell, "Available values are: %s",
748: choices))
749: goto out;
750: }
751: if (oe != NULL && oe->type == OPTIONS_TABLE_COLOUR) {
752: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 1,
753: &grid_default_cell, "This is a colour option: "))
754: goto out;
755: memcpy(&gc, &grid_default_cell, sizeof gc);
756: gc.fg = options_get_number(item->oo, name);
757: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &gc,
758: "EXAMPLE"))
759: goto out;
760: }
761: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_STYLE)) {
762: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 1,
763: &grid_default_cell, "This is a style option: "))
764: goto out;
765: style_apply(&gc, item->oo, name, ft);
766: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &gc,
767: "EXAMPLE"))
768: goto out;
769: }
770: if (default_value != NULL) {
771: if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0,
772: &grid_default_cell, "The default is: %s%s%s", default_value,
773: space, unit))
774: goto out;
775: }
776:
777: screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
778: if (s->cy > cy + sy - 1)
779: goto out;
780: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
781: wo = NULL;
782: go = NULL;
783: } else {
784: switch (item->scope) {
785: case WINDOW_CUSTOMIZE_PANE:
786: wo = options_get_parent(item->oo);
787: go = options_get_parent(wo);
788: break;
789: case WINDOW_CUSTOMIZE_WINDOW:
790: case WINDOW_CUSTOMIZE_SESSION:
791: wo = NULL;
792: go = options_get_parent(item->oo);
793: break;
794: default:
795: wo = NULL;
796: go = NULL;
797: break;
798: }
799: }
800: if (wo != NULL && options_owner(o) != wo) {
801: parent = options_get_only(wo, name);
802: if (parent != NULL) {
803: value = options_to_string(parent, -1 , 0);
804: if (!screen_write_text(ctx, s->cx, sx,
805: sy - (s->cy - cy), 0, &grid_default_cell,
806: "Window value (from window %u): %s%s%s", fs.wl->idx,
807: value, space, unit))
808: goto out;
809: }
810: }
811: if (go != NULL && options_owner(o) != go) {
812: parent = options_get_only(go, name);
813: if (parent != NULL) {
814: value = options_to_string(parent, -1 , 0);
815: if (!screen_write_text(ctx, s->cx, sx,
816: sy - (s->cy - cy), 0, &grid_default_cell,
817: "Global value: %s%s%s", value, space, unit))
818: goto out;
819: }
820: }
821:
822: out:
823: free(value);
824: free(default_value);
825: format_free(ft);
826: }
827:
828: static void
829: window_customize_draw(void *modedata, void *itemdata,
830: struct screen_write_ctx *ctx, u_int sx, u_int sy)
831: {
832: struct window_customize_modedata *data = modedata;
833: struct window_customize_itemdata *item = itemdata;
834:
835: if (item == NULL)
836: return;
837:
838: if (item->scope == WINDOW_CUSTOMIZE_KEY)
839: window_customize_draw_key(data, item, ctx, sx, sy);
840: else
841: window_customize_draw_option(data, item, ctx, sx, sy);
842: }
843:
844: static void
845: window_customize_menu(void *modedata, struct client *c, key_code key)
846: {
847: struct window_customize_modedata *data = modedata;
848: struct window_pane *wp = data->wp;
849: struct window_mode_entry *wme;
850:
851: wme = TAILQ_FIRST(&wp->modes);
852: if (wme == NULL || wme->data != modedata)
853: return;
854: window_customize_key(wme, c, NULL, NULL, key, NULL);
855: }
856:
857: static u_int
858: window_customize_height(__unused void *modedata, __unused u_int height)
859: {
860: return (12);
861: }
862:
863: static struct screen *
864: window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
865: struct args *args)
866: {
867: struct window_pane *wp = wme->wp;
868: struct window_customize_modedata *data;
869: struct screen *s;
870:
871: wme->data = data = xcalloc(1, sizeof *data);
872: data->wp = wp;
873: data->references = 1;
874:
875: memcpy(&data->fs, fs, sizeof data->fs);
876:
877: if (args == NULL || !args_has(args, 'F'))
878: data->format = xstrdup(WINDOW_CUSTOMIZE_DEFAULT_FORMAT);
879: else
880: data->format = xstrdup(args_get(args, 'F'));
881:
882: data->data = mode_tree_start(wp, args, window_customize_build,
883: window_customize_draw, NULL, window_customize_menu,
884: window_customize_height, data, window_customize_menu_items, NULL, 0,
885: &s);
886: mode_tree_zoom(data->data, args);
887:
888: mode_tree_build(data->data);
889: mode_tree_draw(data->data);
890:
891: return (s);
892: }
893:
894: static void
895: window_customize_destroy(struct window_customize_modedata *data)
896: {
897: u_int i;
898:
899: if (--data->references != 0)
900: return;
901:
902: for (i = 0; i < data->item_size; i++)
903: window_customize_free_item(data->item_list[i]);
904: free(data->item_list);
905:
906: free(data->format);
907:
908: free(data);
909: }
910:
911: static void
912: window_customize_free(struct window_mode_entry *wme)
913: {
914: struct window_customize_modedata *data = wme->data;
915:
916: if (data == NULL)
917: return;
918:
919: data->dead = 1;
920: mode_tree_free(data->data);
921: window_customize_destroy(data);
922: }
923:
924: static void
925: window_customize_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
926: {
927: struct window_customize_modedata *data = wme->data;
928:
929: mode_tree_resize(data->data, sx, sy);
930: }
931:
932: static void
933: window_customize_free_callback(void *modedata)
934: {
935: window_customize_destroy(modedata);
936: }
937:
938: static void
939: window_customize_free_item_callback(void *itemdata)
940: {
941: struct window_customize_itemdata *item = itemdata;
942: struct window_customize_modedata *data = item->data;
943:
944: window_customize_free_item(item);
945: window_customize_destroy(data);
946: }
947:
948: static int
949: window_customize_set_option_callback(struct client *c, void *itemdata,
950: const char *s, __unused int done)
951: {
952: struct window_customize_itemdata *item = itemdata;
953: struct window_customize_modedata *data = item->data;
954: struct options_entry *o;
955: const struct options_table_entry *oe;
956: struct options *oo = item->oo;
957: const char *name = item->name;
958: char *cause;
959: int idx = item->idx;
960:
961: if (s == NULL || *s == '\0' || data->dead)
962: return (0);
963: if (item == NULL || !window_customize_check_item(data, item, NULL))
964: return (0);
965: o = options_get(oo, name);
966: if (o == NULL)
967: return (0);
968: oe = options_table_entry(o);
969:
970: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
971: if (idx == -1) {
972: for (idx = 0; idx < INT_MAX; idx++) {
973: if (options_array_get(o, idx) == NULL)
974: break;
975: }
976: }
977: if (options_array_set(o, idx, s, 0, &cause) != 0)
978: goto fail;
979: } else {
980: if (options_from_string(oo, oe, name, s, 0, &cause) != 0)
981: goto fail;
982: }
983:
984: options_push_changes(item->name);
985: mode_tree_build(data->data);
986: mode_tree_draw(data->data);
987: data->wp->flags |= PANE_REDRAW;
988:
989: return (0);
990:
991: fail:
992: *cause = toupper((u_char)*cause);
993: status_message_set(c, 1, "%s", cause);
994: free(cause);
995: return (0);
996: }
997:
998: static void
999: window_customize_set_option(struct client *c,
1000: struct window_customize_modedata *data,
1001: struct window_customize_itemdata *item, int global, int pane)
1002: {
1003: struct options_entry *o;
1004: const struct options_table_entry *oe;
1005: struct options *oo;
1006: struct window_customize_itemdata *new_item;
1007: int flag, idx = item->idx;
1008: enum window_customize_scope scope;
1009: u_int choice;
1010: const char *name = item->name, *space = "";
1011: char *prompt, *value, *text;
1012: struct cmd_find_state fs;
1013:
1014: if (item == NULL || !window_customize_check_item(data, item, &fs))
1015: return;
1016: o = options_get(item->oo, name);
1017: if (o == NULL)
1018: return;
1019:
1020: oe = options_table_entry(o);
1021: if (~oe->scope & OPTIONS_TABLE_PANE)
1022: pane = 0;
1023: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
1024: scope = item->scope;
1025: oo = item->oo;
1026: } else {
1027: if (global) {
1028: switch (item->scope) {
1029: case WINDOW_CUSTOMIZE_NONE:
1030: case WINDOW_CUSTOMIZE_KEY:
1031: case WINDOW_CUSTOMIZE_SERVER:
1032: case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
1033: case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
1034: scope = item->scope;
1035: break;
1036: case WINDOW_CUSTOMIZE_SESSION:
1037: scope = WINDOW_CUSTOMIZE_GLOBAL_SESSION;
1038: break;
1039: case WINDOW_CUSTOMIZE_WINDOW:
1040: case WINDOW_CUSTOMIZE_PANE:
1041: scope = WINDOW_CUSTOMIZE_GLOBAL_WINDOW;
1042: break;
1043: }
1044: } else {
1045: switch (item->scope) {
1046: case WINDOW_CUSTOMIZE_NONE:
1047: case WINDOW_CUSTOMIZE_KEY:
1048: case WINDOW_CUSTOMIZE_SERVER:
1049: case WINDOW_CUSTOMIZE_SESSION:
1050: scope = item->scope;
1051: break;
1052: case WINDOW_CUSTOMIZE_WINDOW:
1053: case WINDOW_CUSTOMIZE_PANE:
1054: if (pane)
1055: scope = WINDOW_CUSTOMIZE_PANE;
1056: else
1057: scope = WINDOW_CUSTOMIZE_WINDOW;
1058: break;
1059: case WINDOW_CUSTOMIZE_GLOBAL_SESSION:
1060: scope = WINDOW_CUSTOMIZE_SESSION;
1061: break;
1062: case WINDOW_CUSTOMIZE_GLOBAL_WINDOW:
1063: if (pane)
1064: scope = WINDOW_CUSTOMIZE_PANE;
1065: else
1066: scope = WINDOW_CUSTOMIZE_WINDOW;
1067: break;
1068: }
1069: }
1070: if (scope == item->scope)
1071: oo = item->oo;
1072: else
1073: oo = window_customize_get_tree(scope, &fs);
1074: }
1075:
1076: if (oe != NULL && oe->type == OPTIONS_TABLE_FLAG) {
1077: flag = options_get_number(oo, name);
1078: options_set_number(oo, name, !flag);
1079: } else if (oe != NULL && oe->type == OPTIONS_TABLE_CHOICE) {
1080: choice = options_get_number(oo, name);
1081: if (oe->choices[choice + 1] == NULL)
1082: choice = 0;
1083: else
1084: choice++;
1085: options_set_number(oo, name, choice);
1086: } else {
1087: text = window_customize_scope_text(scope, &fs);
1088: if (*text != '\0')
1089: space = ", for ";
1090: else if (scope != WINDOW_CUSTOMIZE_SERVER)
1091: space = ", global";
1092: if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
1093: if (idx == -1) {
1094: xasprintf(&prompt, "(%s[+]%s%s) ", name, space,
1095: text);
1096: } else {
1097: xasprintf(&prompt, "(%s[%d]%s%s) ", name, idx,
1098: space, text);
1099: }
1100: } else
1101: xasprintf(&prompt, "(%s%s%s) ", name, space, text);
1102: free(text);
1103:
1104: value = options_to_string(o, idx, 0);
1105:
1106: new_item = xcalloc(1, sizeof *new_item);
1107: new_item->data = data;
1108: new_item->scope = scope;
1109: new_item->oo = oo;
1110: new_item->name = xstrdup(name);
1111: new_item->idx = idx;
1112:
1113: data->references++;
1.2 nicm 1114: status_prompt_set(c, NULL, prompt, value,
1.1 nicm 1115: window_customize_set_option_callback,
1116: window_customize_free_item_callback, new_item,
1117: PROMPT_NOFORMAT);
1118:
1119: free(prompt);
1120: free(value);
1121: }
1122: }
1123:
1124: static void
1125: window_customize_unset_option(struct window_customize_modedata *data,
1126: struct window_customize_itemdata *item)
1127: {
1128: struct options_entry *o;
1129: const struct options_table_entry *oe;
1130:
1131: if (item == NULL || !window_customize_check_item(data, item, NULL))
1132: return;
1133:
1134: o = options_get(item->oo, item->name);
1135: if (o == NULL)
1136: return;
1137: if (item->idx != -1) {
1138: if (item == mode_tree_get_current(data->data))
1139: mode_tree_up(data->data, 0);
1140: options_array_set(o, item->idx, NULL, 0, NULL);
1141: return;
1142: }
1143: oe = options_table_entry(o);
1144: if (oe != NULL &&
1145: options_owner(o) != global_options &&
1146: options_owner(o) != global_s_options &&
1147: options_owner(o) != global_w_options)
1148: options_remove(o);
1149: else
1150: options_default(options_owner(o), oe);
1151: }
1152:
1153: static int
1154: window_customize_set_command_callback(struct client *c, void *itemdata,
1155: const char *s, __unused int done)
1156: {
1157: struct window_customize_itemdata *item = itemdata;
1158: struct window_customize_modedata *data = item->data;
1159: struct key_binding *bd;
1160: struct cmd_parse_result *pr;
1161: char *error;
1162:
1163: if (s == NULL || *s == '\0' || data->dead)
1164: return (0);
1165: if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1166: return (0);
1167:
1168: pr = cmd_parse_from_string(s, NULL);
1169: switch (pr->status) {
1170: case CMD_PARSE_EMPTY:
1171: error = xstrdup("empty command");
1172: goto fail;
1173: case CMD_PARSE_ERROR:
1174: error = pr->error;
1175: goto fail;
1176: case CMD_PARSE_SUCCESS:
1177: break;
1178: }
1179: cmd_list_free(bd->cmdlist);
1180: bd->cmdlist = pr->cmdlist;
1181:
1182: mode_tree_build(data->data);
1183: mode_tree_draw(data->data);
1184: data->wp->flags |= PANE_REDRAW;
1185:
1186: return (0);
1187:
1188: fail:
1189: *error = toupper((u_char)*error);
1190: status_message_set(c, 1, "%s", error);
1191: free(error);
1192: return (0);
1193: }
1194:
1195: static int
1196: window_customize_set_note_callback(__unused struct client *c, void *itemdata,
1197: const char *s, __unused int done)
1198: {
1199: struct window_customize_itemdata *item = itemdata;
1200: struct window_customize_modedata *data = item->data;
1201: struct key_binding *bd;
1202:
1203: if (s == NULL || *s == '\0' || data->dead)
1204: return (0);
1205: if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1206: return (0);
1207:
1208: free((void *)bd->note);
1209: bd->note = xstrdup(s);
1210:
1211: mode_tree_build(data->data);
1212: mode_tree_draw(data->data);
1213: data->wp->flags |= PANE_REDRAW;
1214:
1215: return (0);
1216: }
1217:
1218: static void
1219: window_customize_set_key(struct client *c,
1220: struct window_customize_modedata *data,
1221: struct window_customize_itemdata *item)
1222: {
1223: key_code key = item->key;
1224: struct key_binding *bd;
1225: const char *s;
1226: char *prompt, *value;
1227: struct window_customize_itemdata *new_item;
1228:
1229: if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1230: return;
1231:
1232: s = mode_tree_get_current_name(data->data);
1233: if (strcmp(s, "Repeat") == 0)
1234: bd->flags ^= KEY_BINDING_REPEAT;
1235: else if (strcmp(s, "Command") == 0) {
1.3 ! nicm 1236: xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
1.1 nicm 1237: value = cmd_list_print(bd->cmdlist, 0);
1238:
1239: new_item = xcalloc(1, sizeof *new_item);
1240: new_item->data = data;
1241: new_item->scope = item->scope;
1242: new_item->table = xstrdup(item->table);
1243: new_item->key = key;
1244:
1245: data->references++;
1.2 nicm 1246: status_prompt_set(c, NULL, prompt, value,
1.1 nicm 1247: window_customize_set_command_callback,
1248: window_customize_free_item_callback, new_item,
1249: PROMPT_NOFORMAT);
1250: free(prompt);
1251: free(value);
1252: } else if (strcmp(s, "Note") == 0) {
1.3 ! nicm 1253: xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
1.1 nicm 1254:
1255: new_item = xcalloc(1, sizeof *new_item);
1256: new_item->data = data;
1257: new_item->scope = item->scope;
1258: new_item->table = xstrdup(item->table);
1259: new_item->key = key;
1260:
1261: data->references++;
1.2 nicm 1262: status_prompt_set(c, NULL, prompt,
1263: (bd->note == NULL ? "" : bd->note),
1.1 nicm 1264: window_customize_set_note_callback,
1265: window_customize_free_item_callback, new_item,
1266: PROMPT_NOFORMAT);
1267: free(prompt);
1268: }
1269: }
1270:
1271: static void
1272: window_customize_unset_key(struct window_customize_modedata *data,
1273: struct window_customize_itemdata *item)
1274: {
1275: struct key_table *kt;
1276: struct key_binding *bd;
1277:
1278: if (item == NULL || !window_customize_get_key(item, &kt, &bd))
1279: return;
1280:
1281: if (item == mode_tree_get_current(data->data)) {
1282: mode_tree_collapse_current(data->data);
1283: mode_tree_up(data->data, 0);
1284: }
1285: key_bindings_remove(kt->name, bd->key);
1286: }
1287:
1288: static void
1289: window_customize_unset_each(void *modedata, void *itemdata,
1290: __unused struct client *c, __unused key_code key)
1291: {
1292: struct window_customize_itemdata *item = itemdata;
1293:
1294: if (item->scope == WINDOW_CUSTOMIZE_KEY)
1295: window_customize_unset_key(modedata, item);
1296: else {
1297: window_customize_unset_option(modedata, item);
1298: options_push_changes(item->name);
1299: }
1300: }
1301:
1302: static int
1303: window_customize_unset_current_callback(__unused struct client *c,
1304: void *modedata, const char *s, __unused int done)
1305: {
1306: struct window_customize_modedata *data = modedata;
1307: struct window_customize_itemdata *item;
1308:
1309: if (s == NULL || *s == '\0' || data->dead)
1310: return (0);
1311: if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
1312: return (0);
1313:
1314: item = mode_tree_get_current(data->data);
1315: if (item->scope == WINDOW_CUSTOMIZE_KEY)
1316: window_customize_unset_key(data, item);
1317: else {
1318: window_customize_unset_option(data, item);
1319: options_push_changes(item->name);
1320: }
1321: mode_tree_build(data->data);
1322: mode_tree_draw(data->data);
1323: data->wp->flags |= PANE_REDRAW;
1324:
1325: return (0);
1326: }
1327:
1328: static int
1329: window_customize_unset_tagged_callback(struct client *c, void *modedata,
1330: const char *s, __unused int done)
1331: {
1332: struct window_customize_modedata *data = modedata;
1333:
1334: if (s == NULL || *s == '\0' || data->dead)
1335: return (0);
1336: if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
1337: return (0);
1338:
1339: mode_tree_each_tagged(data->data, window_customize_unset_each, c,
1340: KEYC_NONE, 0);
1341: mode_tree_build(data->data);
1342: mode_tree_draw(data->data);
1343: data->wp->flags |= PANE_REDRAW;
1344:
1345: return (0);
1346: }
1347:
1348: static void
1349: window_customize_key(struct window_mode_entry *wme, struct client *c,
1350: __unused struct session *s, __unused struct winlink *wl, key_code key,
1351: struct mouse_event *m)
1352: {
1353: struct window_pane *wp = wme->wp;
1354: struct window_customize_modedata *data = wme->data;
1355: struct window_customize_itemdata *item, *new_item;
1356: int finished;
1357: char *prompt;
1358: u_int tagged;
1359:
1360: item = mode_tree_get_current(data->data);
1361: finished = mode_tree_key(data->data, c, &key, m, NULL, NULL);
1362: if (item != (new_item = mode_tree_get_current(data->data)))
1363: item = new_item;
1364:
1365: switch (key) {
1366: case '\r':
1367: case 's':
1368: if (item == NULL)
1369: break;
1370: if (item->scope == WINDOW_CUSTOMIZE_KEY)
1371: window_customize_set_key(c, data, item);
1372: else {
1373: window_customize_set_option(c, data, item, 0, 1);
1374: options_push_changes(item->name);
1375: }
1376: mode_tree_build(data->data);
1377: break;
1378: case 'w':
1379: if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
1380: break;
1381: window_customize_set_option(c, data, item, 0, 0);
1382: options_push_changes(item->name);
1383: mode_tree_build(data->data);
1384: break;
1385: case 'S':
1386: case 'W':
1387: if (item == NULL || item->scope == WINDOW_CUSTOMIZE_KEY)
1388: break;
1389: window_customize_set_option(c, data, item, 1, 0);
1390: options_push_changes(item->name);
1391: mode_tree_build(data->data);
1392: break;
1393: case 'u':
1394: if (item == NULL)
1395: break;
1396: if (item->scope == WINDOW_CUSTOMIZE_KEY) {
1397: xasprintf(&prompt, "Unbind key %s? ",
1.3 ! nicm 1398: key_string_lookup_key(item->key, 0));
1.1 nicm 1399: } else
1400: xasprintf(&prompt, "Unset option %s? ", item->name);
1401: data->references++;
1.2 nicm 1402: status_prompt_set(c, NULL, prompt, "",
1.1 nicm 1403: window_customize_unset_current_callback,
1404: window_customize_free_callback, data,
1405: PROMPT_SINGLE|PROMPT_NOFORMAT);
1406: free(prompt);
1407: break;
1408: case 'U':
1409: tagged = mode_tree_count_tagged(data->data);
1410: if (tagged == 0)
1411: break;
1412: xasprintf(&prompt, "Unset or unbind %u tagged? ", tagged);
1413: data->references++;
1.2 nicm 1414: status_prompt_set(c, NULL, prompt, "",
1.1 nicm 1415: window_customize_unset_tagged_callback,
1416: window_customize_free_callback, data,
1417: PROMPT_SINGLE|PROMPT_NOFORMAT);
1418: free(prompt);
1419: break;
1420: case 'H':
1421: data->hide_global = !data->hide_global;
1422: mode_tree_build(data->data);
1423: break;
1424: }
1425: if (finished)
1426: window_pane_reset_mode(wp);
1427: else {
1428: mode_tree_draw(data->data);
1429: wp->flags |= PANE_REDRAW;
1430: }
1431: }