Coverage Report

Created: 2026-09-01 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tmux/options.c
Line
Count
Source
1
/* $OpenBSD: options.c,v 1.92 2026/07/27 19:15:58 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2008 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 <fnmatch.h>
23
#include <stdarg.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "tmux.h"
28
29
/*
30
 * Option handling; each option has a name, type and value and is stored in
31
 * a red-black tree.
32
 */
33
34
struct options_array_item {
35
  char        *key;
36
  union options_value    value;
37
  RB_ENTRY(options_array_item)   entry;
38
};
39
40
static int
41
options_array_key_to_number(const char *key, u_int *idx)
42
1.95k
{
43
1.95k
  const char  *errstr;
44
1.95k
  long long  n;
45
46
1.95k
  if (*key == '\0')
47
0
    return (-1);
48
4.07k
  for (const char *cp = key; *cp != '\0'; cp++) {
49
2.12k
    if (!isdigit((u_char)*cp))
50
0
      return (0);
51
2.12k
  }
52
53
1.95k
  n = strtonum(key, 0, UINT_MAX, &errstr);
54
1.95k
  if (errstr != NULL)
55
0
    return (-1);
56
1.95k
  if (idx != NULL)
57
1.95k
    *idx = n;
58
1.95k
  return (1);
59
1.95k
}
60
61
static char *
62
options_array_correct_key(const char *key)
63
290
{
64
290
  u_int  idx;
65
290
  int  numeric;
66
290
  char  *out;
67
68
290
  numeric = options_array_key_to_number(key, &idx);
69
290
  if (numeric == -1)
70
0
    return (NULL);
71
290
  if (numeric == 1) {
72
290
    xasprintf(&out, "%u", idx);
73
290
    return (out);
74
290
  }
75
0
  return (xstrdup(key));
76
290
}
77
78
static int
79
options_array_cmp(struct options_array_item *a1, struct options_array_item *a2)
80
834
{
81
834
  u_int i1, i2;
82
834
  int n1, n2;
83
84
834
  n1 = options_array_key_to_number(a1->key, &i1);
85
834
  n2 = options_array_key_to_number(a2->key, &i2);
86
834
  if (n1 && n2) {
87
834
    if (i1 < i2)
88
92
      return (-1);
89
742
    if (i1 > i2)
90
550
      return (1);
91
192
    return (0);
92
742
  }
93
0
  if (n1)
94
0
    return (-1);
95
0
  if (n2)
96
0
    return (1);
97
0
  return (strcmp(a1->key, a2->key));
98
0
}
99
308
RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
options.c:options_array_RB_MINMAX
Line
Count
Source
99
RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
Unexecuted instantiation: options.c:options_array_RB_REMOVE
Unexecuted instantiation: options.c:options_array_RB_REMOVE_COLOR
options.c:options_array_RB_FIND
Line
Count
Source
99
RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
options.c:options_array_RB_INSERT
Line
Count
Source
99
RB_GENERATE_STATIC(options_array, options_array_item, entry, options_array_cmp);
100
308
101
308
struct options_entry {
102
308
  struct options        *owner;
103
308
104
308
  const char        *name;
105
308
  const struct options_table_entry  *tableentry;
106
308
  union options_value      value;
107
308
108
308
  int          cached;
109
308
  struct style         style;
110
308
111
308
  void          *monitor_data;
112
308
  u_int          fire_count;
113
308
  time_t           fire_time;
114
308
115
308
  RB_ENTRY(options_entry)      entry;
116
308
};
117
308
118
308
struct options {
119
308
  RB_HEAD(options_tree, options_entry)   tree;
120
308
  struct options        *parent;
121
308
};
122
308
123
308
static struct options_entry *options_add(struct options *, const char *);
124
308
static void      options_remove(struct options_entry *);
125
308
126
308
#define OPTIONS_IS_STRING(o)            \
127
308
  ((o)->tableentry == NULL ||         \
128
52
      (o)->tableentry->type == OPTIONS_TABLE_STRING)
129
#define OPTIONS_IS_NUMBER(o) \
130
0
  ((o)->tableentry != NULL &&         \
131
0
      ((o)->tableentry->type == OPTIONS_TABLE_NUMBER ||   \
132
0
      (o)->tableentry->type == OPTIONS_TABLE_KEY ||   \
133
0
      (o)->tableentry->type == OPTIONS_TABLE_COLOUR ||   \
134
0
      (o)->tableentry->type == OPTIONS_TABLE_FLAG ||   \
135
0
      (o)->tableentry->type == OPTIONS_TABLE_CHOICE))
136
#define OPTIONS_IS_COMMAND(o) \
137
52
  ((o)->tableentry != NULL &&         \
138
52
      (o)->tableentry->type == OPTIONS_TABLE_COMMAND)
139
140
#define OPTIONS_IS_ARRAY(o)           \
141
292
  ((o)->tableentry != NULL &&         \
142
292
      ((o)->tableentry->flags & OPTIONS_TABLE_IS_ARRAY))
143
144
static int  options_cmp(struct options_entry *, struct options_entry *);
145
3.26k
RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
Unexecuted instantiation: options.c:options_tree_RB_MINMAX
options.c:options_tree_RB_FIND
Line
Count
Source
145
RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
options.c:options_tree_RB_INSERT
Line
Count
Source
145
RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
Unexecuted instantiation: options.c:options_tree_RB_REMOVE
Unexecuted instantiation: options.c:options_tree_RB_REMOVE_COLOR
146
3.26k
147
3.26k
static int
148
3.26k
options_cmp(struct options_entry *lhs, struct options_entry *rhs)
149
11.3k
{
150
11.3k
  return (strcmp(lhs->name, rhs->name));
151
11.3k
}
152
153
static const char *
154
options_map_name(const char *name)
155
544
{
156
544
  const struct options_name_map *map;
157
158
4.35k
  for (map = options_other_names; map->from != NULL; map++) {
159
3.80k
    if (strcmp(map->from, name) == 0)
160
0
      return (map->to);
161
3.80k
  }
162
544
  return (name);
163
544
}
164
165
static const struct options_table_entry *
166
options_parent_table_entry(struct options *oo, const char *s)
167
0
{
168
0
  struct options_entry  *o;
169
170
0
  if (oo->parent == NULL)
171
0
    fatalx("no parent options for %s", s);
172
0
  o = options_get(oo->parent, s);
173
0
  if (o == NULL)
174
0
    fatalx("%s not in parent options", s);
175
0
  return (o->tableentry);
176
0
}
177
178
static void
179
options_value_free(struct options_entry *o, union options_value *ov)
180
0
{
181
0
  if (OPTIONS_IS_STRING(o))
182
0
    free(ov->string);
183
0
  if (OPTIONS_IS_COMMAND(o) && ov->cmdlist != NULL)
184
0
    cmd_list_free(ov->cmdlist);
185
0
}
186
187
static char *
188
options_value_to_string(struct options_entry *o, union options_value *ov,
189
    int numeric)
190
0
{
191
0
  char  *s;
192
193
0
  if (OPTIONS_IS_COMMAND(o))
194
0
    return (cmd_list_print(ov->cmdlist, 0));
195
0
  if (OPTIONS_IS_NUMBER(o)) {
196
0
    switch (o->tableentry->type) {
197
0
    case OPTIONS_TABLE_NUMBER:
198
0
      xasprintf(&s, "%lld", ov->number);
199
0
      break;
200
0
    case OPTIONS_TABLE_KEY:
201
0
      s = xstrdup(key_string_lookup_key(ov->number, 0));
202
0
      break;
203
0
    case OPTIONS_TABLE_COLOUR:
204
0
      s = xstrdup(colour_tostring(ov->number));
205
0
      break;
206
0
    case OPTIONS_TABLE_FLAG:
207
0
      if (numeric)
208
0
        xasprintf(&s, "%lld", ov->number);
209
0
      else
210
0
        s = xstrdup(ov->number ? "on" : "off");
211
0
      break;
212
0
    case OPTIONS_TABLE_CHOICE:
213
0
      s = xstrdup(o->tableentry->choices[ov->number]);
214
0
      break;
215
0
    default:
216
0
      fatalx("not a number option type");
217
0
    }
218
0
    return (s);
219
0
  }
220
0
  if (OPTIONS_IS_STRING(o))
221
0
    return (xstrdup(ov->string));
222
0
  return (xstrdup(""));
223
0
}
224
225
struct options *
226
options_create(struct options *parent)
227
6
{
228
6
  struct options  *oo;
229
230
6
  oo = xcalloc(1, sizeof *oo);
231
6
  RB_INIT(&oo->tree);
232
6
  oo->parent = parent;
233
6
  return (oo);
234
6
}
235
236
void
237
options_free(struct options *oo)
238
0
{
239
0
  struct options_entry  *o, *tmp;
240
241
0
  RB_FOREACH_SAFE(o, options_tree, &oo->tree, tmp)
242
0
    options_remove(o);
243
0
  free(oo);
244
0
}
245
246
struct options *
247
options_get_parent(struct options *oo)
248
0
{
249
0
  return (oo->parent);
250
0
}
251
252
void
253
options_set_parent(struct options *oo, struct options *parent)
254
0
{
255
0
  oo->parent = parent;
256
0
}
257
258
struct options_entry *
259
options_first(struct options *oo)
260
0
{
261
0
  return (RB_MIN(options_tree, &oo->tree));
262
0
}
263
264
struct options_entry *
265
options_next(struct options_entry *o)
266
0
{
267
0
  return (RB_NEXT(options_tree, &oo->tree, o));
268
0
}
269
270
struct options_entry *
271
options_get_only(struct options *oo, const char *name)
272
546
{
273
546
  struct options_entry  o = { .name = name }, *found;
274
275
546
  found = RB_FIND(options_tree, &oo->tree, &o);
276
546
  if (found == NULL) {
277
544
    o.name = options_map_name(name);
278
544
    return (RB_FIND(options_tree, &oo->tree, &o));
279
544
  }
280
2
  return (found);
281
546
}
282
283
struct options_entry *
284
options_get(struct options *oo, const char *name)
285
0
{
286
0
  struct options_entry  *o;
287
288
0
  o = options_get_only(oo, name);
289
0
  while (o == NULL) {
290
0
    oo = oo->parent;
291
0
    if (oo == NULL)
292
0
      break;
293
0
    o = options_get_only(oo, name);
294
0
  }
295
0
  return (o);
296
0
}
297
298
struct options_entry *
299
options_empty(struct options *oo, const struct options_table_entry *oe)
300
544
{
301
544
  struct options_entry  *o;
302
303
544
  o = options_add(oo, oe->name);
304
544
  o->tableentry = oe;
305
306
544
  if (oe->flags & OPTIONS_TABLE_IS_ARRAY)
307
194
    RB_INIT(&o->value.array);
308
309
544
  return (o);
310
544
}
311
312
struct options_entry *
313
options_default(struct options *oo, const struct options_table_entry *oe)
314
544
{
315
544
  struct options_entry  *o;
316
544
  union options_value *ov;
317
544
  char       key[32];
318
544
  u_int      i;
319
544
  struct cmd_parse_result *pr;
320
321
544
  o = options_empty(oo, oe);
322
544
  ov = &o->value;
323
324
544
  if (oe->flags & OPTIONS_TABLE_IS_ARRAY) {
325
194
    if (oe->default_arr == NULL) {
326
192
      options_array_assign(o, oe->default_str, NULL);
327
192
      return (o);
328
192
    }
329
8
    for (i = 0; oe->default_arr[i] != NULL; i++) {
330
6
      xsnprintf(key, sizeof key, "%u", i);
331
6
      options_array_set(o, key, oe->default_arr[i], 0, NULL);
332
6
    }
333
2
    return (o);
334
194
  }
335
336
350
  switch (oe->type) {
337
188
  case OPTIONS_TABLE_STRING:
338
188
    ov->string = xstrdup(oe->default_str);
339
188
    break;
340
2
  case OPTIONS_TABLE_COMMAND:
341
2
    pr = cmd_parse_from_string(oe->default_str, NULL);
342
2
    switch (pr->status) {
343
0
    case CMD_PARSE_ERROR:
344
0
      free(pr->error);
345
0
      break;
346
2
    case CMD_PARSE_SUCCESS:
347
2
      ov->cmdlist = pr->cmdlist;
348
2
      break;
349
2
    }
350
2
    break;
351
160
  default:
352
160
    ov->number = oe->default_num;
353
160
    break;
354
350
  }
355
350
  return (o);
356
350
}
357
358
char *
359
options_default_to_string(const struct options_table_entry *oe)
360
0
{
361
0
  char  *s;
362
363
0
  switch (oe->type) {
364
0
  case OPTIONS_TABLE_STRING:
365
0
  case OPTIONS_TABLE_COMMAND:
366
0
    s = xstrdup(oe->default_str);
367
0
    break;
368
0
  case OPTIONS_TABLE_NUMBER:
369
0
    xasprintf(&s, "%lld", oe->default_num);
370
0
    break;
371
0
  case OPTIONS_TABLE_KEY:
372
0
    s = xstrdup(key_string_lookup_key(oe->default_num, 0));
373
0
    break;
374
0
  case OPTIONS_TABLE_COLOUR:
375
0
    s = xstrdup(colour_tostring(oe->default_num));
376
0
    break;
377
0
  case OPTIONS_TABLE_FLAG:
378
0
    s = xstrdup(oe->default_num ? "on" : "off");
379
0
    break;
380
0
  case OPTIONS_TABLE_CHOICE:
381
0
    s = xstrdup(oe->choices[oe->default_num]);
382
0
    break;
383
0
  default:
384
0
    fatalx("unknown option type");
385
0
  }
386
0
  return (s);
387
0
}
388
389
static struct options_entry *
390
options_add(struct options *oo, const char *name)
391
544
{
392
544
  struct options_entry  *o;
393
394
544
  o = options_get_only(oo, name);
395
544
  if (o != NULL)
396
0
    options_remove(o);
397
398
544
  o = xcalloc(1, sizeof *o);
399
544
  o->owner = oo;
400
544
  o->name = xstrdup(name);
401
402
544
  RB_INSERT(options_tree, &oo->tree, o);
403
544
  return (o);
404
544
}
405
406
static void
407
options_remove(struct options_entry *o)
408
0
{
409
0
  struct options  *oo = o->owner;
410
411
0
  if (OPTIONS_IS_ARRAY(o))
412
0
    options_array_clear(o);
413
0
  else
414
0
    options_value_free(o, &o->value);
415
0
  if (o->monitor_data != NULL)
416
0
    hooks_monitor_free(o->monitor_data);
417
0
  RB_REMOVE(options_tree, &oo->tree, o);
418
0
  free((void *)o->name);
419
0
  free(o);
420
0
}
421
422
const char *
423
options_name(struct options_entry *o)
424
0
{
425
0
  return (o->name);
426
0
}
427
428
struct options *
429
options_owner(struct options_entry *o)
430
0
{
431
0
  return (o->owner);
432
0
}
433
434
void *
435
options_get_monitor_data(struct options_entry *o)
436
0
{
437
0
  return (o->monitor_data);
438
0
}
439
440
void
441
options_set_monitor_data(struct options_entry *o, void *data)
442
0
{
443
0
  o->monitor_data = data;
444
0
}
445
446
void
447
options_hook_fired(struct options_entry *o)
448
0
{
449
0
  o->fire_count++;
450
0
  o->fire_time = current_time;
451
0
}
452
453
u_int
454
options_get_fire_count(struct options_entry *o)
455
0
{
456
0
  return (o->fire_count);
457
0
}
458
459
time_t
460
options_get_fire_time(struct options_entry *o)
461
0
{
462
0
  return (o->fire_time);
463
0
}
464
465
const struct options_table_entry *
466
options_table_entry(struct options_entry *o)
467
0
{
468
0
  return (o->tableentry);
469
0
}
470
471
static struct options_array_item *
472
options_array_item(struct options_entry *o, const char *key)
473
290
{
474
290
  struct options_array_item a;
475
476
290
  a.key = (char *)key;
477
290
  return (RB_FIND(options_array, &o->value.array, &a));
478
290
}
479
480
static struct options_array_item *
481
options_array_new(struct options_entry *o, const char *key)
482
52
{
483
52
  struct options_array_item *a;
484
485
52
  a = xcalloc(1, sizeof *a);
486
52
  a->key = xstrdup(key);
487
52
  RB_INSERT(options_array, &o->value.array, a);
488
52
  return (a);
489
52
}
490
491
static void
492
options_array_free(struct options_entry *o, struct options_array_item *a)
493
0
{
494
0
  options_value_free(o, &a->value);
495
0
  RB_REMOVE(options_array, &o->value.array, a);
496
0
  free(a->key);
497
0
  free(a);
498
0
}
499
500
void
501
options_array_clear(struct options_entry *o)
502
0
{
503
0
  struct options_array_item *a, *a1;
504
505
0
  if (!OPTIONS_IS_ARRAY(o))
506
0
    return;
507
508
0
  RB_FOREACH_SAFE(a, options_array, &o->value.array, a1)
509
0
    options_array_free(o, a);
510
0
}
511
512
union options_value *
513
options_array_get(struct options_entry *o, const char *key)
514
238
{
515
238
  struct options_array_item *a;
516
238
  char        *new_key;
517
518
238
  if (!OPTIONS_IS_ARRAY(o))
519
0
    return (NULL);
520
238
  new_key = options_array_correct_key(key);
521
238
  if (new_key == NULL)
522
0
    return (NULL);
523
238
  a = options_array_item(o, new_key);
524
238
  free(new_key);
525
238
  if (a == NULL)
526
46
    return (NULL);
527
192
  return (&a->value);
528
238
}
529
530
union options_value *
531
options_array_getv(struct options_entry *o, const char *fmt, ...)
532
238
{
533
238
  union options_value *ov;
534
238
  va_list      ap;
535
238
  char      *key;
536
537
238
  va_start(ap, fmt);
538
238
  xvasprintf(&key, fmt, ap);
539
238
  va_end(ap);
540
541
238
  ov = options_array_get(o, key);
542
238
  free(key);
543
238
  return (ov);
544
238
}
545
546
int
547
options_array_set(struct options_entry *o, const char *key, const char *value,
548
    int append, char **cause)
549
52
{
550
52
  struct options_array_item *a;
551
52
  char        *new, *new_key;
552
52
  struct cmd_parse_result   *pr;
553
52
  long long      number;
554
555
52
  if (!OPTIONS_IS_ARRAY(o)) {
556
0
    if (cause != NULL)
557
0
      *cause = xstrdup("not an array");
558
0
    return (-1);
559
0
  }
560
561
52
  new_key = options_array_correct_key(key);
562
52
  if (new_key == NULL) {
563
0
    if (cause != NULL)
564
0
      xasprintf(cause, "bad array key: %s", key);
565
0
    return (-1);
566
0
  }
567
568
52
  if (value == NULL) {
569
0
    a = options_array_item(o, new_key);
570
0
    if (a != NULL)
571
0
      options_array_free(o, a);
572
0
    free(new_key);
573
0
    return (0);
574
0
  }
575
576
52
  if (OPTIONS_IS_COMMAND(o)) {
577
0
    pr = cmd_parse_from_string(value, NULL);
578
0
    switch (pr->status) {
579
0
    case CMD_PARSE_ERROR:
580
0
      if (cause != NULL)
581
0
        *cause = pr->error;
582
0
      else
583
0
        free(pr->error);
584
0
      free(new_key);
585
0
      return (-1);
586
0
    case CMD_PARSE_SUCCESS:
587
0
      break;
588
0
    }
589
590
0
    a = options_array_item(o, new_key);
591
0
    if (a == NULL)
592
0
      a = options_array_new(o, new_key);
593
0
    else
594
0
      options_value_free(o, &a->value);
595
0
    a->value.cmdlist = pr->cmdlist;
596
0
    free(new_key);
597
0
    return (0);
598
0
  }
599
600
52
  if (OPTIONS_IS_STRING(o)) {
601
52
    a = options_array_item(o, new_key);
602
52
    if (a != NULL && append)
603
0
      xasprintf(&new, "%s%s", a->value.string, value);
604
52
    else
605
52
      new = xstrdup(value);
606
52
    if (a == NULL)
607
52
      a = options_array_new(o, new_key);
608
0
    else
609
0
      options_value_free(o, &a->value);
610
52
    a->value.string = new;
611
52
    free(new_key);
612
52
    return (0);
613
52
  }
614
615
0
  if (o->tableentry->type == OPTIONS_TABLE_COLOUR) {
616
0
    if ((number = colour_fromstring(value)) == -1) {
617
0
      xasprintf(cause, "bad colour: %s", value);
618
0
      free(new_key);
619
0
      return (-1);
620
0
    }
621
0
    a = options_array_item(o, new_key);
622
0
    if (a == NULL)
623
0
      a = options_array_new(o, new_key);
624
0
    else
625
0
      options_value_free(o, &a->value);
626
0
    a->value.number = number;
627
0
    free(new_key);
628
0
    return (0);
629
0
  }
630
631
0
  if (cause != NULL)
632
0
    *cause = xstrdup("wrong array type");
633
0
  free(new_key);
634
0
  return (-1);
635
0
}
636
637
int
638
options_array_assign(struct options_entry *o, const char *s, char **cause)
639
192
{
640
192
  const char  *separator;
641
192
  char    *copy, *next, *string;
642
192
  char     key[32];
643
192
  u_int    i;
644
645
192
  separator = o->tableentry->separator;
646
192
  if (separator == NULL)
647
4
    separator = " ,";
648
192
  if (*separator == '\0') {
649
178
    if (*s == '\0')
650
178
      return (0);
651
0
    for (i = 0; i < UINT_MAX; i++) {
652
0
      if (options_array_getv(o, "%u", i) == NULL)
653
0
        break;
654
0
    }
655
0
    xsnprintf(key, sizeof key, "%u", i);
656
0
    return (options_array_set(o, key, s, 0, cause));
657
178
  }
658
659
14
  if (*s == '\0')
660
6
    return (0);
661
8
  copy = string = xstrdup(s);
662
54
  while ((next = strsep(&string, separator)) != NULL) {
663
46
    if (*next == '\0')
664
0
      continue;
665
238
    for (i = 0; i < UINT_MAX; i++) {
666
238
      if (options_array_getv(o, "%u", i) == NULL)
667
46
        break;
668
238
    }
669
46
    if (i == UINT_MAX)
670
0
      break;
671
46
    xsnprintf(key, sizeof key, "%u", i);
672
46
    if (options_array_set(o, key, next, 0, cause) != 0) {
673
0
      free(copy);
674
0
      return (-1);
675
0
    }
676
46
  }
677
8
  free(copy);
678
8
  return (0);
679
8
}
680
681
struct options_array_item *
682
options_array_first(struct options_entry *o)
683
2
{
684
2
  if (!OPTIONS_IS_ARRAY(o))
685
0
    return (NULL);
686
2
  return (RB_MIN(options_array, &o->value.array));
687
2
}
688
689
struct options_array_item *
690
options_array_next(struct options_array_item *a)
691
12
{
692
12
  return (RB_NEXT(options_array, , a));
693
12
}
694
695
const char *
696
options_array_item_key(struct options_array_item *a)
697
0
{
698
0
  return (a->key);
699
0
}
700
701
union options_value *
702
options_array_item_value(struct options_array_item *a)
703
12
{
704
12
  return (&a->value);
705
12
}
706
707
int
708
options_is_array(struct options_entry *o)
709
0
{
710
0
  return (OPTIONS_IS_ARRAY(o));
711
0
}
712
713
int
714
options_is_string(struct options_entry *o)
715
0
{
716
0
  return (OPTIONS_IS_STRING(o));
717
0
}
718
719
char *
720
options_to_string(struct options_entry *o, const char *key, int numeric)
721
0
{
722
0
  struct options_array_item *a;
723
0
  char        *result = NULL;
724
0
  char        *last = NULL;
725
0
  char        *next;
726
0
  char        *new_key;
727
728
0
  if (OPTIONS_IS_ARRAY(o)) {
729
0
    if (key == NULL) {
730
0
      RB_FOREACH(a, options_array, &o->value.array) {
731
0
        next = options_value_to_string(o, &a->value,
732
0
            numeric);
733
0
        if (last == NULL)
734
0
          result = next;
735
0
        else {
736
0
          xasprintf(&result, "%s %s", last, next);
737
0
          free(last);
738
0
          free(next);
739
0
        }
740
0
        last = result;
741
0
      }
742
0
      if (result == NULL)
743
0
        return (xstrdup(""));
744
0
      return (result);
745
0
    }
746
0
    new_key = options_array_correct_key(key);
747
0
    if (new_key == NULL)
748
0
      return (xstrdup(""));
749
0
    a = options_array_item(o, new_key);
750
0
    free(new_key);
751
0
    if (a == NULL)
752
0
      return (xstrdup(""));
753
0
    return (options_value_to_string(o, &a->value, numeric));
754
0
  }
755
0
  return (options_value_to_string(o, &o->value, numeric));
756
0
}
757
758
char *
759
options_parse(const char *name, char **key)
760
0
{
761
0
  char  *copy, *cp, *end, *raw, *new_key;
762
763
0
  if (*name == '\0')
764
0
    return (NULL);
765
0
  *key = NULL;
766
0
  copy = xstrdup(name);
767
0
  if ((cp = strchr(copy, '[')) == NULL) {
768
0
    return (copy);
769
0
  }
770
0
  end = strchr(cp + 1, ']');
771
0
  if (end == NULL || end[1] != '\0' || end == cp + 1) {
772
0
    free(copy);
773
0
    return (NULL);
774
0
  }
775
0
  raw = xstrndup(cp + 1, end - (cp + 1));
776
0
  new_key = options_array_correct_key(raw);
777
0
  free(raw);
778
0
  if (new_key == NULL) {
779
0
    free(copy);
780
0
    return (NULL);
781
0
  }
782
0
  *key = new_key;
783
0
  *cp = '\0';
784
0
  return (copy);
785
0
}
786
787
struct options_entry *
788
options_parse_get(struct options *oo, const char *s, char **key, int only)
789
0
{
790
0
  struct options_entry  *o;
791
0
  char      *name;
792
793
0
  name = options_parse(s, key);
794
0
  if (name == NULL)
795
0
    return (NULL);
796
0
  if (only)
797
0
    o = options_get_only(oo, name);
798
0
  else
799
0
    o = options_get(oo, name);
800
0
  free(name);
801
0
  if (o == NULL) {
802
0
    free(*key);
803
0
    *key = NULL;
804
0
  }
805
0
  return (o);
806
0
}
807
808
const struct options_table_entry *
809
options_search(const char *name)
810
0
{
811
0
  const struct options_table_entry  *oe;
812
813
0
  for (oe = options_table; oe->name != NULL; oe++) {
814
0
    if (strcmp(oe->name, name) == 0)
815
0
      return (oe);
816
0
  }
817
0
  return (NULL);
818
0
}
819
820
char *
821
options_match(const char *s, char **key, int *ambiguous)
822
0
{
823
0
  const struct options_table_entry  *oe, *found;
824
0
  char          *parsed;
825
0
  const char        *name;
826
0
  size_t           namelen;
827
828
0
  parsed = options_parse(s, key);
829
0
  if (parsed == NULL)
830
0
    return (NULL);
831
0
  if (*parsed == '@') {
832
0
    *ambiguous = 0;
833
0
    return (parsed);
834
0
  }
835
836
0
  name = options_map_name(parsed);
837
0
  namelen = strlen(name);
838
839
0
  found = NULL;
840
0
  for (oe = options_table; oe->name != NULL; oe++) {
841
0
    if (strcmp(oe->name, name) == 0) {
842
0
      found = oe;
843
0
      break;
844
0
    }
845
0
    if (strncmp(oe->name, name, namelen) == 0) {
846
0
      if (found != NULL) {
847
0
        *ambiguous = 1;
848
0
        free(parsed);
849
0
        free(*key);
850
0
        *key = NULL;
851
0
        return (NULL);
852
0
      }
853
0
      found = oe;
854
0
    }
855
0
  }
856
0
  free(parsed);
857
0
  if (found == NULL) {
858
0
    *ambiguous = 0;
859
0
    free(*key);
860
0
    *key = NULL;
861
0
    return (NULL);
862
0
  }
863
0
  return (xstrdup(found->name));
864
0
}
865
866
struct options_entry *
867
options_match_get(struct options *oo, const char *s, char **key, int only,
868
    int *ambiguous)
869
0
{
870
0
  char      *name;
871
0
  struct options_entry  *o;
872
873
0
  name = options_match(s, key, ambiguous);
874
0
  if (name == NULL)
875
0
    return (NULL);
876
0
  *ambiguous = 0;
877
0
  if (only)
878
0
    o = options_get_only(oo, name);
879
0
  else
880
0
    o = options_get(oo, name);
881
0
  free(name);
882
0
  if (o == NULL) {
883
0
    free(*key);
884
0
    *key = NULL;
885
0
  }
886
0
  return (o);
887
0
}
888
889
const char *
890
options_get_string(struct options *oo, const char *name)
891
0
{
892
0
  struct options_entry  *o;
893
894
0
  o = options_get(oo, name);
895
0
  if (o == NULL)
896
0
    fatalx("missing option %s", name);
897
0
  if (!OPTIONS_IS_STRING(o))
898
0
    fatalx("option %s is not a string", name);
899
0
  return (o->value.string);
900
0
}
901
902
long long
903
options_get_number(struct options *oo, const char *name)
904
0
{
905
0
  struct options_entry  *o;
906
907
0
  o = options_get(oo, name);
908
0
  if (o == NULL)
909
0
    fatalx("missing option %s", name);
910
0
  if (!OPTIONS_IS_NUMBER(o))
911
0
    fatalx("option %s is not a number", name);
912
0
  return (o->value.number);
913
0
}
914
915
struct cmd_list *
916
options_get_command(struct options *oo, const char *name)
917
0
{
918
0
  struct options_entry  *o;
919
920
0
  o = options_get(oo, name);
921
0
  if (o == NULL)
922
0
    fatalx("missing option %s", name);
923
0
  if (!OPTIONS_IS_COMMAND(o))
924
0
    fatalx("option %s is not a command", name);
925
0
  return (o->value.cmdlist);
926
0
}
927
928
struct options_entry *
929
options_set_string(struct options *oo, const char *name, int append,
930
    const char *fmt, ...)
931
0
{
932
0
  struct options_entry  *o;
933
0
  va_list      ap;
934
0
  const char    *separator = "";
935
0
  char      *s, *value;
936
937
0
  va_start(ap, fmt);
938
0
  xvasprintf(&s, fmt, ap);
939
0
  va_end(ap);
940
941
0
  o = options_get_only(oo, name);
942
0
  if (o != NULL && append && OPTIONS_IS_STRING(o)) {
943
0
    if (*name != '@') {
944
0
      separator = o->tableentry->separator;
945
0
      if (separator == NULL)
946
0
        separator = "";
947
0
    }
948
0
    xasprintf(&value, "%s%s%s", o->value.string, separator, s);
949
0
    free(s);
950
0
  } else
951
0
    value = s;
952
0
  if (o == NULL && *name == '@')
953
0
    o = options_add(oo, name);
954
0
  else if (o == NULL) {
955
0
    o = options_default(oo, options_parent_table_entry(oo, name));
956
0
    if (o == NULL)
957
0
      return (NULL);
958
0
  }
959
960
0
  if (!OPTIONS_IS_STRING(o))
961
0
    fatalx("option %s is not a string", name);
962
0
  free(o->value.string);
963
0
  o->value.string = value;
964
0
  o->cached = 0;
965
0
  return (o);
966
0
}
967
968
struct options_entry *
969
options_set_number(struct options *oo, const char *name, long long value)
970
0
{
971
0
  struct options_entry  *o;
972
973
0
  if (*name == '@')
974
0
    fatalx("user option %s must be a string", name);
975
976
0
  o = options_get_only(oo, name);
977
0
  if (o == NULL) {
978
0
    o = options_default(oo, options_parent_table_entry(oo, name));
979
0
    if (o == NULL)
980
0
      return (NULL);
981
0
  }
982
983
0
  if (!OPTIONS_IS_NUMBER(o))
984
0
    fatalx("option %s is not a number", name);
985
0
  o->value.number = value;
986
0
  return (o);
987
0
}
988
989
struct options_entry *
990
options_set_command(struct options *oo, const char *name,
991
    struct cmd_list *value)
992
0
{
993
0
  struct options_entry  *o;
994
995
0
  if (*name == '@')
996
0
    fatalx("user option %s must be a string", name);
997
998
0
  o = options_get_only(oo, name);
999
0
  if (o == NULL) {
1000
0
    o = options_default(oo, options_parent_table_entry(oo, name));
1001
0
    if (o == NULL)
1002
0
      return (NULL);
1003
0
  }
1004
1005
0
  if (!OPTIONS_IS_COMMAND(o))
1006
0
    fatalx("option %s is not a command", name);
1007
0
  if (o->value.cmdlist != NULL)
1008
0
    cmd_list_free(o->value.cmdlist);
1009
0
  o->value.cmdlist = value;
1010
0
  return (o);
1011
0
}
1012
1013
int
1014
options_scope_from_name(struct args *args, int window,
1015
    const char *name, struct cmd_find_state *fs, struct options **oo,
1016
    char **cause)
1017
0
{
1018
0
  struct session        *s = fs->s;
1019
0
  struct winlink        *wl = fs->wl;
1020
0
  struct window_pane      *wp = fs->wp;
1021
0
  const char        *target = args_get(args, 't');
1022
0
  const struct options_table_entry  *oe;
1023
0
  int          scope = OPTIONS_TABLE_NONE;
1024
1025
0
  if (*name == '@')
1026
0
    return (options_scope_from_flags(args, window, fs, oo, cause));
1027
1028
0
  for (oe = options_table; oe->name != NULL; oe++) {
1029
0
    if (strcmp(oe->name, name) == 0)
1030
0
      break;
1031
0
  }
1032
0
  if (oe->name == NULL) {
1033
0
    xasprintf(cause, "unknown option: %s", name);
1034
0
    return (OPTIONS_TABLE_NONE);
1035
0
  }
1036
0
  switch (oe->scope) {
1037
0
  case OPTIONS_TABLE_SERVER:
1038
0
    *oo = global_options;
1039
0
    scope = OPTIONS_TABLE_SERVER;
1040
0
    break;
1041
0
  case OPTIONS_TABLE_SESSION:
1042
0
    if (args_has(args, 'g')) {
1043
0
      *oo = global_s_options;
1044
0
      scope = OPTIONS_TABLE_SESSION;
1045
0
    } else if (s == NULL && target != NULL)
1046
0
      xasprintf(cause, "no such session: %s", target);
1047
0
    else if (s == NULL)
1048
0
      xasprintf(cause, "no current session");
1049
0
    else {
1050
0
      *oo = s->options;
1051
0
      scope = OPTIONS_TABLE_SESSION;
1052
0
    }
1053
0
    break;
1054
0
  case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE:
1055
0
    if (args_has(args, 'p')) {
1056
0
      if (wp == NULL && target != NULL)
1057
0
        xasprintf(cause, "no such pane: %s", target);
1058
0
      else if (wp == NULL)
1059
0
        xasprintf(cause, "no current pane");
1060
0
      else {
1061
0
        *oo = wp->options;
1062
0
        scope = OPTIONS_TABLE_PANE;
1063
0
      }
1064
0
      break;
1065
0
    }
1066
    /* FALLTHROUGH */
1067
0
  case OPTIONS_TABLE_WINDOW:
1068
0
    if (args_has(args, 'g')) {
1069
0
      *oo = global_w_options;
1070
0
      scope = OPTIONS_TABLE_WINDOW;
1071
0
    } else if (wl == NULL && target != NULL)
1072
0
      xasprintf(cause, "no such window: %s", target);
1073
0
    else if (wl == NULL)
1074
0
      xasprintf(cause, "no current window");
1075
0
    else {
1076
0
      *oo = wl->window->options;
1077
0
      scope = OPTIONS_TABLE_WINDOW;
1078
0
    }
1079
0
    break;
1080
0
  }
1081
0
  return (scope);
1082
0
}
1083
1084
int
1085
options_scope_from_flags(struct args *args, int window,
1086
    struct cmd_find_state *fs, struct options **oo, char **cause)
1087
0
{
1088
0
  struct session    *s = fs->s;
1089
0
  struct winlink    *wl = fs->wl;
1090
0
  struct window_pane  *wp = fs->wp;
1091
0
  const char    *target = args_get(args, 't');
1092
1093
0
  if (args_has(args, 's')) {
1094
0
    *oo = global_options;
1095
0
    return (OPTIONS_TABLE_SERVER);
1096
0
  }
1097
1098
0
  if (args_has(args, 'p')) {
1099
0
    if (wp == NULL) {
1100
0
      if (target != NULL)
1101
0
        xasprintf(cause, "no such pane: %s", target);
1102
0
      else
1103
0
        xasprintf(cause, "no current pane");
1104
0
      return (OPTIONS_TABLE_NONE);
1105
0
    }
1106
0
    *oo = wp->options;
1107
0
    return (OPTIONS_TABLE_PANE);
1108
0
  } else if (window || args_has(args, 'w')) {
1109
0
    if (args_has(args, 'g')) {
1110
0
      *oo = global_w_options;
1111
0
      return (OPTIONS_TABLE_WINDOW);
1112
0
    }
1113
0
    if (wl == NULL) {
1114
0
      if (target != NULL)
1115
0
        xasprintf(cause, "no such window: %s", target);
1116
0
      else
1117
0
        xasprintf(cause, "no current window");
1118
0
      return (OPTIONS_TABLE_NONE);
1119
0
    }
1120
0
    *oo = wl->window->options;
1121
0
    return (OPTIONS_TABLE_WINDOW);
1122
0
  } else {
1123
0
    if (args_has(args, 'g')) {
1124
0
      *oo = global_s_options;
1125
0
      return (OPTIONS_TABLE_SESSION);
1126
0
    }
1127
0
    if (s == NULL) {
1128
0
      if (target != NULL)
1129
0
        xasprintf(cause, "no such session: %s", target);
1130
0
      else
1131
0
        xasprintf(cause, "no current session");
1132
0
      return (OPTIONS_TABLE_NONE);
1133
0
    }
1134
0
    *oo = s->options;
1135
0
    return (OPTIONS_TABLE_SESSION);
1136
0
  }
1137
0
}
1138
1139
struct style *
1140
options_string_to_style(struct options *oo, const char *name,
1141
    struct format_tree *ft)
1142
0
{
1143
0
  struct options_entry      *o;
1144
0
  const struct options_table_entry  *oe;
1145
0
  const struct grid_cell      *dgc = &grid_default_cell;
1146
0
  const char        *s;
1147
0
  char          *expanded;
1148
0
  int          failed;
1149
1150
0
  o = options_get(oo, name);
1151
0
  if (o == NULL || !OPTIONS_IS_STRING(o))
1152
0
    return (NULL);
1153
1154
0
  if (o->cached)
1155
0
    return (&o->style);
1156
0
  s = o->value.string;
1157
0
  oe = o->tableentry;
1158
0
  log_debug("%s: %s is '%s'", __func__, name, s);
1159
1160
0
  style_set(&o->style, dgc);
1161
0
  o->cached = (strstr(s, "#{") == NULL);
1162
1163
0
  if (ft != NULL && !o->cached) {
1164
0
    expanded = format_expand(ft, s);
1165
0
    if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_COLOUR))
1166
0
      failed = style_parse_colour(&o->style, dgc, expanded);
1167
0
    else
1168
0
      failed = style_parse(&o->style, dgc, expanded);
1169
0
    free(expanded);
1170
0
    if (failed != 0)
1171
0
      return (NULL);
1172
0
  } else {
1173
0
    if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_COLOUR))
1174
0
      failed = style_parse_colour(&o->style, dgc, s);
1175
0
    else
1176
0
      failed = style_parse(&o->style, dgc, s);
1177
0
    if (failed != 0)
1178
0
      return (NULL);
1179
0
  }
1180
0
  return (&o->style);
1181
0
}
1182
1183
static int
1184
options_from_string_check(const struct options_table_entry *oe,
1185
    const char *value, char **cause)
1186
0
{
1187
0
  struct style  sy;
1188
1189
0
  if (oe == NULL)
1190
0
    return (0);
1191
0
  if (strcmp(oe->name, "default-shell") == 0 && !checkshell(value)) {
1192
0
    xasprintf(cause, "not a suitable shell: %s", value);
1193
0
    return (-1);
1194
0
  }
1195
0
  if (oe->pattern != NULL && fnmatch(oe->pattern, value, 0) != 0) {
1196
0
    xasprintf(cause, "value is invalid: %s", value);
1197
0
    return (-1);
1198
0
  }
1199
0
  if ((oe->flags & OPTIONS_TABLE_IS_STYLE) &&
1200
0
      strstr(value, "#{") == NULL &&
1201
0
      style_parse(&sy, &grid_default_cell, value) != 0) {
1202
0
    xasprintf(cause, "invalid style: %s", value);
1203
0
    return (-1);
1204
0
  }
1205
0
  if ((oe->flags & OPTIONS_TABLE_IS_COLOUR) &&
1206
0
      strstr(value, "#{") == NULL &&
1207
0
      style_parse_colour(&sy, &grid_default_cell, value) != 0) {
1208
0
    xasprintf(cause, "invalid colour: %s", value);
1209
0
    return (-1);
1210
0
  }
1211
0
  return (0);
1212
0
}
1213
1214
static int
1215
options_from_string_flag(struct options *oo, const char *name,
1216
    const char *value, char **cause)
1217
0
{
1218
0
  int flag;
1219
1220
0
  if (value == NULL || *value == '\0')
1221
0
    flag = !options_get_number(oo, name);
1222
0
  else if (strcmp(value, "1") == 0 ||
1223
0
      strcasecmp(value, "on") == 0 ||
1224
0
      strcasecmp(value, "yes") == 0)
1225
0
    flag = 1;
1226
0
  else if (strcmp(value, "0") == 0 ||
1227
0
      strcasecmp(value, "off") == 0 ||
1228
0
      strcasecmp(value, "no") == 0)
1229
0
    flag = 0;
1230
0
  else {
1231
0
    xasprintf(cause, "bad value: %s", value);
1232
0
    return (-1);
1233
0
  }
1234
0
  options_set_number(oo, name, flag);
1235
0
  return (0);
1236
0
}
1237
1238
int
1239
options_find_choice(const struct options_table_entry *oe, const char *value,
1240
    char **cause)
1241
0
{
1242
0
  const char  **cp;
1243
0
  int     n = 0, choice = -1;
1244
1245
0
  for (cp = oe->choices; *cp != NULL; cp++) {
1246
0
    if (strcmp(*cp, value) == 0)
1247
0
      choice = n;
1248
0
    n++;
1249
0
  }
1250
0
  if (choice == -1) {
1251
0
    xasprintf(cause, "unknown value: %s", value);
1252
0
    return (-1);
1253
0
  }
1254
0
  return (choice);
1255
0
}
1256
1257
static int
1258
options_from_string_choice(const struct options_table_entry *oe,
1259
    struct options *oo, const char *name, const char *value, char **cause)
1260
0
{
1261
0
  int choice = -1;
1262
1263
0
  if (value == NULL) {
1264
0
    choice = options_get_number(oo, name);
1265
0
    if (choice < 2)
1266
0
      choice = !choice;
1267
0
  } else {
1268
0
    choice = options_find_choice(oe, value, cause);
1269
0
    if (choice < 0)
1270
0
      return (-1);
1271
0
  }
1272
0
  options_set_number(oo, name, choice);
1273
0
  return (0);
1274
0
}
1275
1276
int
1277
options_from_string(struct options *oo, const struct options_table_entry *oe,
1278
    const char *name, const char *value, int append, char **cause)
1279
0
{
1280
0
  enum options_table_type  type;
1281
0
  long long    number;
1282
0
  const char    *errstr, *new;
1283
0
  char      *old;
1284
0
  key_code     key;
1285
0
  struct cmd_parse_result *pr;
1286
1287
0
  if (oe != NULL) {
1288
0
    if (value == NULL &&
1289
0
        oe->type != OPTIONS_TABLE_FLAG &&
1290
0
        oe->type != OPTIONS_TABLE_CHOICE) {
1291
0
      xasprintf(cause, "empty value");
1292
0
      return (-1);
1293
0
    }
1294
0
    type = oe->type;
1295
0
  } else {
1296
0
    if (*name != '@') {
1297
0
      xasprintf(cause, "bad option name");
1298
0
      return (-1);
1299
0
    }
1300
0
    type = OPTIONS_TABLE_STRING;
1301
0
  }
1302
1303
0
  switch (type) {
1304
0
  case OPTIONS_TABLE_STRING:
1305
0
    old = xstrdup(options_get_string(oo, name));
1306
0
    options_set_string(oo, name, append, "%s", value);
1307
1308
0
    new = options_get_string(oo, name);
1309
0
    if (options_from_string_check(oe, new, cause) != 0) {
1310
0
      options_set_string(oo, name, 0, "%s", old);
1311
0
      free(old);
1312
0
      return (-1);
1313
0
    }
1314
0
    free(old);
1315
0
    return (0);
1316
0
  case OPTIONS_TABLE_NUMBER:
1317
0
    number = strtonum(value, oe->minimum, oe->maximum, &errstr);
1318
0
    if (errstr != NULL) {
1319
0
      xasprintf(cause, "value is %s: %s", errstr, value);
1320
0
      return (-1);
1321
0
    }
1322
0
    options_set_number(oo, name, number);
1323
0
    return (0);
1324
0
  case OPTIONS_TABLE_KEY:
1325
0
    key = key_string_lookup_string(value);
1326
0
    if (key == KEYC_UNKNOWN) {
1327
0
      xasprintf(cause, "bad key: %s", value);
1328
0
      return (-1);
1329
0
    }
1330
0
    options_set_number(oo, name, key);
1331
0
    return (0);
1332
0
  case OPTIONS_TABLE_COLOUR:
1333
0
    if ((number = colour_fromstring(value)) == -1) {
1334
0
      xasprintf(cause, "bad colour: %s", value);
1335
0
      return (-1);
1336
0
    }
1337
0
    options_set_number(oo, name, number);
1338
0
    return (0);
1339
0
  case OPTIONS_TABLE_FLAG:
1340
0
    return (options_from_string_flag(oo, name, value, cause));
1341
0
  case OPTIONS_TABLE_CHOICE:
1342
0
    return (options_from_string_choice(oe, oo, name, value, cause));
1343
0
  case OPTIONS_TABLE_COMMAND:
1344
0
    pr = cmd_parse_from_string(value, NULL);
1345
0
    switch (pr->status) {
1346
0
    case CMD_PARSE_ERROR:
1347
0
      *cause = pr->error;
1348
0
      return (-1);
1349
0
    case CMD_PARSE_SUCCESS:
1350
0
      options_set_command(oo, name, pr->cmdlist);
1351
0
      return (0);
1352
0
    }
1353
0
    break;
1354
0
  }
1355
0
  return (-1);
1356
0
}
1357
1358
void
1359
options_push_changes(const char *name)
1360
0
{
1361
0
  struct client   *loop;
1362
0
  struct session    *s;
1363
0
  struct window   *w;
1364
0
  struct window_pane  *wp;
1365
1366
0
  log_debug("%s: %s", __func__, name);
1367
1368
0
  if (strcmp(name, "theme") == 0 ||
1369
0
      strncmp(name, "dark-theme-", 11) == 0 ||
1370
0
      strncmp(name, "light-theme-", 12) == 0) {
1371
0
    TAILQ_FOREACH(loop, &clients, entry) {
1372
0
      server_client_update_theme_colours(loop);
1373
0
      if (loop->tty.flags & TTY_OPENED)
1374
0
        tty_invalidate(&loop->tty);
1375
0
      server_redraw_client(loop);
1376
0
    }
1377
0
  }
1378
1379
0
  if (strcmp(name, "automatic-rename") == 0) {
1380
0
    RB_FOREACH(w, windows, &windows) {
1381
0
      if (w->active == NULL)
1382
0
        continue;
1383
0
      if (options_get_number(w->options, name))
1384
0
        w->active->flags |= PANE_CHANGED;
1385
0
    }
1386
0
  }
1387
0
  if (strcmp(name, "cursor-colour") == 0) {
1388
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1389
0
      window_pane_default_cursor(wp);
1390
0
  }
1391
0
  if (strcmp(name, "cursor-style") == 0) {
1392
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1393
0
      window_pane_default_cursor(wp);
1394
0
  }
1395
0
  if (strcmp(name, "fill-character") == 0) {
1396
0
    RB_FOREACH(w, windows, &windows)
1397
0
      window_set_fill_cells(w);
1398
0
  }
1399
0
  if (strcmp(name, "key-table") == 0) {
1400
0
    TAILQ_FOREACH(loop, &clients, entry)
1401
0
      server_client_set_key_table(loop, NULL);
1402
0
  }
1403
0
  if (strcmp(name, "user-keys") == 0) {
1404
0
    TAILQ_FOREACH(loop, &clients, entry) {
1405
0
      if (loop->tty.flags & TTY_OPENED)
1406
0
        tty_keys_build(&loop->tty);
1407
0
    }
1408
0
  }
1409
0
  if (strcmp(name, "status") == 0 ||
1410
0
      strcmp(name, "status-interval") == 0)
1411
0
    status_timer_start_all();
1412
0
  if (strcmp(name, "status") == 0 ||
1413
0
      strcmp(name, "status-position") == 0 ||
1414
0
      strcmp(name, "pane-border-indicators") == 0 ||
1415
0
      strcmp(name, "pane-border-lines") == 0 ||
1416
0
      strcmp(name, "pane-border-status") == 0 ||
1417
0
      strcmp(name, "pane-scrollbars") == 0 ||
1418
0
      strcmp(name, "pane-scrollbars-timeout") == 0 ||
1419
0
      strcmp(name, "pane-scrollbars-position") == 0 ||
1420
0
      strcmp(name, "pane-scrollbars-style") == 0)
1421
0
    redraw_invalidate_all_scenes();
1422
0
  if (strcmp(name, "monitor-silence") == 0)
1423
0
    alerts_reset_all();
1424
0
  if (strcmp(name, "window-style") == 0 ||
1425
0
      strcmp(name, "window-active-style") == 0) {
1426
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1427
0
      wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
1428
0
  }
1429
0
  if (*name == '@') {
1430
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1431
0
      wp->flags |= PANE_STYLECHANGED;
1432
0
  }
1433
0
  if (strcmp(name, "pane-colours") == 0) {
1434
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1435
0
      colour_palette_from_option(&wp->palette, wp->options);
1436
0
  }
1437
0
  if (strcmp(name, "pane-border-status") == 0 ||
1438
0
      strcmp(name, "pane-scrollbars") == 0 ||
1439
0
      strcmp(name, "pane-scrollbars-position") == 0) {
1440
0
    RB_FOREACH(w, windows, &windows) {
1441
0
      w->sb = options_get_number(w->options,
1442
0
          "pane-scrollbars");
1443
0
      w->sb_pos = options_get_number(w->options,
1444
0
          "pane-scrollbars-position");
1445
0
      layout_fix_panes(w, NULL);
1446
0
    }
1447
0
  }
1448
0
  if (strcmp(name, "pane-scrollbars") == 0) {
1449
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes)
1450
0
      window_pane_scrollbar_hide(wp);
1451
0
  }
1452
0
  if (strcmp(name, "pane-scrollbars-style") == 0) {
1453
0
    RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
1454
0
      style_set_scrollbar_style_from_option(
1455
0
          &wp->scrollbar_style, wp->options);
1456
0
    }
1457
0
    RB_FOREACH(w, windows, &windows)
1458
0
      layout_fix_panes(w, NULL);
1459
0
  }
1460
0
  if (strcmp(name, "codepoint-widths") == 0)
1461
0
    utf8_update_width_cache();
1462
0
  if (strcmp(name, "input-buffer-size") == 0)
1463
0
    input_set_buffer_size(options_get_number(global_options, name));
1464
0
  if (strcmp(name, "history-limit") == 0) {
1465
0
    RB_FOREACH(s, sessions, &sessions)
1466
0
      session_update_history(s);
1467
0
  }
1468
0
  RB_FOREACH(s, sessions, &sessions)
1469
0
    status_update_cache(s);
1470
1471
0
  recalculate_sizes();
1472
0
  TAILQ_FOREACH(loop, &clients, entry) {
1473
0
    if (loop->session != NULL)
1474
0
      server_redraw_client(loop);
1475
0
  }
1476
0
}
1477
1478
int
1479
options_remove_or_default(struct options_entry *o, const char *key,
1480
    char **cause)
1481
0
{
1482
0
  struct options  *oo = o->owner;
1483
1484
0
  if (key == NULL) {
1485
0
    if (o->tableentry != NULL &&
1486
0
        (oo == global_options ||
1487
0
        oo == global_s_options ||
1488
0
        oo == global_w_options))
1489
0
      options_default(oo, o->tableentry);
1490
0
    else
1491
0
      options_remove(o);
1492
0
  } else if (options_array_set(o, key, NULL, 0, cause) != 0)
1493
0
    return (-1);
1494
0
  return (0);
1495
0
}