Annotation of src/usr.bin/tmux/window-customize.c, Revision 1.13
1.13 ! nicm 1: /* $OpenBSD: window-customize.c,v 1.12 2021/08/21 17:25:32 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_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);
1.8 nicm 202: break;
203: default:
204: s = xstrdup("");
1.1 nicm 205: break;
206: }
207: return (s);
208: }
209:
210: static struct window_customize_itemdata *
211: window_customize_add_item(struct window_customize_modedata *data)
212: {
213: struct window_customize_itemdata *item;
214:
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);
219: }
220:
221: static void
222: window_customize_free_item(struct window_customize_itemdata *item)
223: {
224: free(item->table);
225: free(item->name);
226: free(item);
227: }
228:
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)
233: {
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;
241:
242: ai = options_array_first(o);
243: while (ai != NULL) {
244: idx = options_array_item_index(ai);
245:
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);
250:
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;
256:
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);
261:
262: free(name);
263: free(value);
264:
265: ai = options_array_next(ai);
266: }
267: }
268:
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)
274: {
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;
282:
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;
287:
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;
294:
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);
298:
299: text = window_customize_scope_text(scope, fs);
300: format_add(ft, "option_scope", "%s", text);
301: free(text);
302:
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", "");
307:
308: if (!array) {
309: value = options_to_string(o, -1, 0);
310: format_add(ft, "option_value", "%s", value);
311: free(value);
312: }
313:
314: if (filter != NULL) {
315: expanded = format_expand(ft, filter);
316: if (!format_true(expanded)) {
317: free(expanded);
318: return;
319: }
320: free(expanded);
321: }
322: item = window_customize_add_item(data);
323: item->oo = oo;
324: item->scope = scope;
325: item->name = xstrdup(name);
326: item->idx = -1;
327:
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);
335:
336: if (array)
337: window_customize_build_array(data, top, scope, o, ft);
338: }
339:
340: static void
341: window_customize_find_user_options(struct options *oo, const char ***list,
342: u_int *size)
343: {
344: struct options_entry *o;
345: const char *name;
346: u_int i;
347:
348: o = options_first(oo);
349: while (o != NULL) {
350: name = options_name(o);
351: if (*name != '@') {
352: o = options_next(o);
353: continue;
354: }
355: for (i = 0; i < *size; i++) {
356: if (strcmp((*list)[i], name) == 0)
357: break;
358: }
359: if (i != *size) {
360: o = options_next(o);
361: continue;
362: }
363: *list = xreallocarray(*list, (*size) + 1, sizeof **list);
364: (*list)[(*size)++] = name;
365:
366: o = options_next(o);
367: }
368: }
369:
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)
377: {
378: struct mode_tree_item *top;
1.7 nicm 379: struct options_entry *o = NULL, *loop;
1.1 nicm 380: const char **list = NULL, *name;
381: u_int size = 0, i;
382: enum window_customize_scope scope;
383:
384: top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
1.4 nicm 385: mode_tree_no_tag(top);
1.1 nicm 386:
387: /*
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.
391: */
392:
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);
398:
399: for (i = 0; i < size; i++) {
400: if (oo2 != NULL)
1.13 ! nicm 401: o = options_get(oo2, list[i]);
1.5 nicm 402: if (o == NULL && oo1 != NULL)
1.1 nicm 403: o = options_get(oo1, list[i]);
1.5 nicm 404: if (o == NULL)
1.13 ! nicm 405: o = options_get(oo0, list[i]);
1.1 nicm 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);
414: }
415: free(list);
416:
417: loop = options_first(oo0);
418: while (loop != NULL) {
419: name = options_name(loop);
420: if (*name == '@') {
421: loop = options_next(loop);
422: continue;
423: }
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);
439: }
440: }
441:
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)
446: {
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;
453:
454: tag = (1ULL << 62)|((uint64_t)number << 54)|1;
455:
456: xasprintf(&title, "Key Table - %s", kt->name);
457: top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0);
1.4 nicm 458: mode_tree_no_tag(top);
1.1 nicm 459: free(title);
460:
461: ft = format_create_from_state(NULL, NULL, fs);
462: format_add(ft, "is_option", "0");
463: format_add(ft, "is_key", "1");
464:
465: bd = key_bindings_first(kt);
466: while (bd != NULL) {
1.3 nicm 467: format_add(ft, "key", "%s", key_string_lookup_key(bd->key, 0));
1.1 nicm 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;
475: }
476: free(expanded);
477: }
478:
479: item = window_customize_add_item(data);
480: item->scope = WINDOW_CUSTOMIZE_KEY;
481: item->table = xstrdup(kt->name);
482: item->key = bd->key;
1.4 nicm 483: item->name = xstrdup(key_string_lookup_key(item->key, 0));
484: item->idx = -1;
1.1 nicm 485:
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);
490:
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);
1.4 nicm 497: mode_tree_no_tag(mti);
1.1 nicm 498: free(text);
499:
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);
1.4 nicm 507: mode_tree_no_tag(mti);
1.1 nicm 508: free(text);
509:
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);
1.4 nicm 517: mode_tree_no_tag(mti);
1.1 nicm 518:
519: bd = key_bindings_next(kt, bd);
520: }
521:
522: format_free(ft);
523: }
524:
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)
529: {
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;
535:
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;
541:
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);
546:
547: ft = format_create_from_state(NULL, NULL, &fs);
548: format_add(ft, "is_option", "1");
549: format_add(ft, "is_key", "0");
550:
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);
569:
570: format_free(ft);
571: ft = format_create_from_state(NULL, NULL, &fs);
572:
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,
578: i);
579: if (++i == 256)
580: break;
581: }
582: kt = key_bindings_next_table(kt);
583: }
584:
585: format_free(ft);
586: }
587:
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)
592: {
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;
599:
600: if (item == NULL || !window_customize_get_key(item, &kt, &bd))
601: return;
602:
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;
614:
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;
625:
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;
631: }
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;
641: }
642: free(default_cmd);
643: }
644: free(cmd);
645: }
646:
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)
651: {
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;
666:
667: if (!window_customize_check_item(data, item, &fs))
668: return;
669: name = item->name;
670: idx = item->idx;
671:
672: o = options_get(item->oo, name);
673: if (o == NULL)
674: return;
675: oe = options_table_entry(o);
676:
677: if (oe != NULL && oe->unit != NULL) {
678: space = " ";
679: unit = oe->unit;
680: }
681: ft = format_create_from_state(NULL, NULL, &fs);
682:
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;
695:
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;
720: }
721: if (idx == -1)
722: goto out;
723: }
724: screen_write_cursormove(ctx, cx, s->cy + 1, 0); /* skip line */
725: if (s->cy >= cy + sy - 1)
726: goto out;
727:
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;
734: }
735: }
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;
746: }
747: free(expanded);
748: }
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);
753: }
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;
759: }
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;
769: }
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;
778: }
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;
784: }
785:
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;
807: }
808: }
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;
818: }
819: }
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;
828: }
829: }
830:
831: out:
832: free(value);
833: free(default_value);
834: format_free(ft);
835: }
836:
837: static void
838: window_customize_draw(void *modedata, void *itemdata,
839: struct screen_write_ctx *ctx, u_int sx, u_int sy)
840: {
841: struct window_customize_modedata *data = modedata;
842: struct window_customize_itemdata *item = itemdata;
843:
844: if (item == NULL)
845: return;
846:
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);
851: }
852:
853: static void
854: window_customize_menu(void *modedata, struct client *c, key_code key)
855: {
856: struct window_customize_modedata *data = modedata;
857: struct window_pane *wp = data->wp;
858: struct window_mode_entry *wme;
859:
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);
864: }
865:
866: static u_int
867: window_customize_height(__unused void *modedata, __unused u_int height)
868: {
869: return (12);
870: }
871:
872: static struct screen *
873: window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
874: struct args *args)
875: {
876: struct window_pane *wp = wme->wp;
877: struct window_customize_modedata *data;
878: struct screen *s;
879:
880: wme->data = data = xcalloc(1, sizeof *data);
881: data->wp = wp;
882: data->references = 1;
883:
884: memcpy(&data->fs, fs, sizeof data->fs);
885:
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'));
890:
891: data->data = mode_tree_start(wp, args, window_customize_build,
892: window_customize_draw, NULL, window_customize_menu,
1.9 nicm 893: window_customize_height, NULL, data, window_customize_menu_items,
894: NULL, 0, &s);
1.1 nicm 895: mode_tree_zoom(data->data, args);
896:
897: mode_tree_build(data->data);
898: mode_tree_draw(data->data);
899:
900: return (s);
901: }
902:
903: static void
904: window_customize_destroy(struct window_customize_modedata *data)
905: {
906: u_int i;
907:
908: if (--data->references != 0)
909: return;
910:
911: for (i = 0; i < data->item_size; i++)
912: window_customize_free_item(data->item_list[i]);
913: free(data->item_list);
914:
915: free(data->format);
916:
917: free(data);
918: }
919:
920: static void
921: window_customize_free(struct window_mode_entry *wme)
922: {
923: struct window_customize_modedata *data = wme->data;
924:
925: if (data == NULL)
926: return;
927:
928: data->dead = 1;
929: mode_tree_free(data->data);
930: window_customize_destroy(data);
931: }
932:
933: static void
934: window_customize_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
935: {
936: struct window_customize_modedata *data = wme->data;
937:
938: mode_tree_resize(data->data, sx, sy);
939: }
940:
941: static void
942: window_customize_free_callback(void *modedata)
943: {
944: window_customize_destroy(modedata);
945: }
946:
947: static void
948: window_customize_free_item_callback(void *itemdata)
949: {
950: struct window_customize_itemdata *item = itemdata;
951: struct window_customize_modedata *data = item->data;
952:
953: window_customize_free_item(item);
954: window_customize_destroy(data);
955: }
956:
957: static int
958: window_customize_set_option_callback(struct client *c, void *itemdata,
959: const char *s, __unused int done)
960: {
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;
969:
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);
978:
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;
984: }
985: }
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;
991: }
992:
993: options_push_changes(item->name);
994: mode_tree_build(data->data);
995: mode_tree_draw(data->data);
996: data->wp->flags |= PANE_REDRAW;
997:
998: return (0);
999:
1000: fail:
1001: *cause = toupper((u_char)*cause);
1.10 nicm 1002: status_message_set(c, -1, 1, 0, "%s", cause);
1.1 nicm 1003: free(cause);
1004: return (0);
1005: }
1006:
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)
1011: {
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;
1.7 nicm 1017: enum window_customize_scope scope = WINDOW_CUSTOMIZE_NONE;
1.1 nicm 1018: u_int choice;
1019: const char *name = item->name, *space = "";
1020: char *prompt, *value, *text;
1021: struct cmd_find_state fs;
1022:
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;
1028:
1029: oe = options_table_entry(o);
1.7 nicm 1030: if (oe != NULL && ~oe->scope & OPTIONS_TABLE_PANE)
1.1 nicm 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;
1052: }
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;
1077: }
1078: }
1079: if (scope == item->scope)
1080: oo = item->oo;
1081: else
1082: oo = window_customize_get_tree(scope, &fs);
1083: }
1084:
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);
1108: }
1109: } else
1110: xasprintf(&prompt, "(%s%s%s) ", name, space, text);
1111: free(text);
1112:
1113: value = options_to_string(o, idx, 0);
1114:
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;
1121:
1122: data->references++;
1.2 nicm 1123: status_prompt_set(c, NULL, prompt, value,
1.1 nicm 1124: window_customize_set_option_callback,
1125: window_customize_free_item_callback, new_item,
1.11 nicm 1126: PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.1 nicm 1127:
1128: free(prompt);
1129: free(value);
1130: }
1131: }
1132:
1133: static void
1134: window_customize_unset_option(struct window_customize_modedata *data,
1135: struct window_customize_itemdata *item)
1136: {
1.4 nicm 1137: struct options_entry *o;
1.1 nicm 1138:
1139: if (item == NULL || !window_customize_check_item(data, item, NULL))
1140: return;
1141:
1142: o = options_get(item->oo, item->name);
1143: if (o == NULL)
1144: return;
1.4 nicm 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);
1148: }
1149:
1150: static void
1151: window_customize_reset_option(struct window_customize_modedata *data,
1152: struct window_customize_itemdata *item)
1153: {
1154: struct options *oo;
1155: struct options_entry *o;
1156:
1157: if (item == NULL || !window_customize_check_item(data, item, NULL))
1158: return;
1159: if (item->idx != -1)
1.1 nicm 1160: return;
1.4 nicm 1161:
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);
1.1 nicm 1168: }
1169: }
1170:
1171: static int
1172: window_customize_set_command_callback(struct client *c, void *itemdata,
1173: const char *s, __unused int done)
1174: {
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;
1180:
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);
1185:
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;
1193: }
1194: cmd_list_free(bd->cmdlist);
1195: bd->cmdlist = pr->cmdlist;
1196:
1197: mode_tree_build(data->data);
1198: mode_tree_draw(data->data);
1199: data->wp->flags |= PANE_REDRAW;
1200:
1201: return (0);
1202:
1203: fail:
1204: *error = toupper((u_char)*error);
1.10 nicm 1205: status_message_set(c, -1, 1, 0, "%s", error);
1.1 nicm 1206: free(error);
1207: return (0);
1208: }
1209:
1210: static int
1211: window_customize_set_note_callback(__unused struct client *c, void *itemdata,
1212: const char *s, __unused int done)
1213: {
1214: struct window_customize_itemdata *item = itemdata;
1215: struct window_customize_modedata *data = item->data;
1216: struct key_binding *bd;
1217:
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);
1222:
1223: free((void *)bd->note);
1224: bd->note = xstrdup(s);
1225:
1226: mode_tree_build(data->data);
1227: mode_tree_draw(data->data);
1228: data->wp->flags |= PANE_REDRAW;
1229:
1230: return (0);
1231: }
1232:
1233: static void
1234: window_customize_set_key(struct client *c,
1235: struct window_customize_modedata *data,
1236: struct window_customize_itemdata *item)
1237: {
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;
1243:
1244: if (item == NULL || !window_customize_get_key(item, NULL, &bd))
1245: return;
1246:
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) {
1.3 nicm 1251: xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
1.1 nicm 1252: value = cmd_list_print(bd->cmdlist, 0);
1253:
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;
1259:
1260: data->references++;
1.2 nicm 1261: status_prompt_set(c, NULL, prompt, value,
1.1 nicm 1262: window_customize_set_command_callback,
1263: window_customize_free_item_callback, new_item,
1.11 nicm 1264: PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.1 nicm 1265: free(prompt);
1266: free(value);
1267: } else if (strcmp(s, "Note") == 0) {
1.3 nicm 1268: xasprintf(&prompt, "(%s) ", key_string_lookup_key(key, 0));
1.1 nicm 1269:
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;
1275:
1276: data->references++;
1.2 nicm 1277: status_prompt_set(c, NULL, prompt,
1278: (bd->note == NULL ? "" : bd->note),
1.1 nicm 1279: window_customize_set_note_callback,
1280: window_customize_free_item_callback, new_item,
1.11 nicm 1281: PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.1 nicm 1282: free(prompt);
1283: }
1284: }
1285:
1286: static void
1287: window_customize_unset_key(struct window_customize_modedata *data,
1288: struct window_customize_itemdata *item)
1289: {
1290: struct key_table *kt;
1291: struct key_binding *bd;
1292:
1293: if (item == NULL || !window_customize_get_key(item, &kt, &bd))
1294: return;
1295:
1296: if (item == mode_tree_get_current(data->data)) {
1297: mode_tree_collapse_current(data->data);
1298: mode_tree_up(data->data, 0);
1299: }
1300: key_bindings_remove(kt->name, bd->key);
1301: }
1302:
1303: static void
1.4 nicm 1304: window_customize_reset_key(struct window_customize_modedata *data,
1305: struct window_customize_itemdata *item)
1306: {
1307: struct key_table *kt;
1308: struct key_binding *dd, *bd;
1309:
1310: if (item == NULL || !window_customize_get_key(item, &kt, &bd))
1311: return;
1312:
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);
1319: }
1320: key_bindings_reset(kt->name, bd->key);
1321: }
1322:
1323: static void
1324: window_customize_change_each(void *modedata, void *itemdata,
1.1 nicm 1325: __unused struct client *c, __unused key_code key)
1326: {
1.4 nicm 1327: struct window_customize_modedata *data = modedata;
1.1 nicm 1328: struct window_customize_itemdata *item = itemdata;
1329:
1.4 nicm 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;
1343: }
1344: if (item->scope != WINDOW_CUSTOMIZE_KEY)
1.1 nicm 1345: options_push_changes(item->name);
1346: }
1347:
1348: static int
1.4 nicm 1349: window_customize_change_current_callback(__unused struct client *c,
1.1 nicm 1350: void *modedata, const char *s, __unused int done)
1351: {
1352: struct window_customize_modedata *data = modedata;
1353: struct window_customize_itemdata *item;
1354:
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);
1359:
1360: item = mode_tree_get_current(data->data);
1.4 nicm 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;
1374: }
1375: if (item->scope != WINDOW_CUSTOMIZE_KEY)
1.1 nicm 1376: options_push_changes(item->name);
1377: mode_tree_build(data->data);
1378: mode_tree_draw(data->data);
1379: data->wp->flags |= PANE_REDRAW;
1380:
1381: return (0);
1382: }
1383:
1384: static int
1.4 nicm 1385: window_customize_change_tagged_callback(struct client *c, void *modedata,
1.1 nicm 1386: const char *s, __unused int done)
1387: {
1388: struct window_customize_modedata *data = modedata;
1389:
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);
1394:
1.4 nicm 1395: mode_tree_each_tagged(data->data, window_customize_change_each, c,
1.1 nicm 1396: KEYC_NONE, 0);
1397: mode_tree_build(data->data);
1398: mode_tree_draw(data->data);
1399: data->wp->flags |= PANE_REDRAW;
1400:
1401: return (0);
1402: }
1403:
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)
1408: {
1409: struct window_pane *wp = wme->wp;
1410: struct window_customize_modedata *data = wme->data;
1411: struct window_customize_itemdata *item, *new_item;
1.4 nicm 1412: int finished, idx;
1.1 nicm 1413: char *prompt;
1414: u_int tagged;
1415:
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;
1420:
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);
1431: }
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;
1.4 nicm 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,
1.11 nicm 1458: PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.4 nicm 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,
1.11 nicm 1471: PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.4 nicm 1472: free(prompt);
1473: break;
1.1 nicm 1474: case 'u':
1475: if (item == NULL)
1476: break;
1.4 nicm 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);
1.1 nicm 1482: data->references++;
1.4 nicm 1483: data->change = WINDOW_CUSTOMIZE_UNSET;
1.2 nicm 1484: status_prompt_set(c, NULL, prompt, "",
1.4 nicm 1485: window_customize_change_current_callback,
1.1 nicm 1486: window_customize_free_callback, data,
1.11 nicm 1487: PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.1 nicm 1488: free(prompt);
1489: break;
1490: case 'U':
1491: tagged = mode_tree_count_tagged(data->data);
1492: if (tagged == 0)
1493: break;
1.4 nicm 1494: xasprintf(&prompt, "Unset %u tagged? ", tagged);
1.1 nicm 1495: data->references++;
1.4 nicm 1496: data->change = WINDOW_CUSTOMIZE_UNSET;
1.2 nicm 1497: status_prompt_set(c, NULL, prompt, "",
1.4 nicm 1498: window_customize_change_tagged_callback,
1.1 nicm 1499: window_customize_free_callback, data,
1.11 nicm 1500: PROMPT_SINGLE|PROMPT_NOFORMAT, PROMPT_TYPE_COMMAND);
1.1 nicm 1501: free(prompt);
1502: break;
1503: case 'H':
1504: data->hide_global = !data->hide_global;
1505: mode_tree_build(data->data);
1506: break;
1507: }
1508: if (finished)
1509: window_pane_reset_mode(wp);
1510: else {
1511: mode_tree_draw(data->data);
1512: wp->flags |= PANE_REDRAW;
1513: }
1514: }