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