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