4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
30 int cmd_set_option_exec(struct cmd
*, struct cmd_ctx
*);
32 int cmd_set_option_unset(struct cmd
*, struct cmd_ctx
*,
33 const struct options_table_entry
*, struct options
*,
35 int cmd_set_option_set(struct cmd
*, struct cmd_ctx
*,
36 const struct options_table_entry
*, struct options
*,
39 struct options_entry
*cmd_set_option_string(struct cmd
*, struct cmd_ctx
*,
40 const struct options_table_entry
*, struct options
*,
42 struct options_entry
*cmd_set_option_number(struct cmd
*, struct cmd_ctx
*,
43 const struct options_table_entry
*, struct options
*,
45 struct options_entry
*cmd_set_option_keys(struct cmd
*, struct cmd_ctx
*,
46 const struct options_table_entry
*, struct options
*,
48 struct options_entry
*cmd_set_option_colour(struct cmd
*, struct cmd_ctx
*,
49 const struct options_table_entry
*, struct options
*,
51 struct options_entry
*cmd_set_option_attributes(struct cmd
*, struct cmd_ctx
*,
52 const struct options_table_entry
*, struct options
*,
54 struct options_entry
*cmd_set_option_flag(struct cmd
*, struct cmd_ctx
*,
55 const struct options_table_entry
*, struct options
*,
57 struct options_entry
*cmd_set_option_choice(struct cmd
*, struct cmd_ctx
*,
58 const struct options_table_entry
*, struct options
*,
61 const struct cmd_entry cmd_set_option_entry
= {
64 "[-agsuw] [-t target-session|target-window] option [value]",
71 const struct cmd_entry cmd_set_window_option_entry
= {
72 "set-window-option", "setw",
74 "[-agu] " CMD_TARGET_WINDOW_USAGE
" option [value]",
82 cmd_set_option_exec(struct cmd
*self
, struct cmd_ctx
*ctx
)
84 struct args
*args
= self
->args
;
85 const struct options_table_entry
*table
, *oe
, *oe_loop
;
91 struct job
*job
, *nextjob
;
92 const char *optstr
, *valstr
;
96 /* Work out the options tree and table to use. */
97 if (args_has(self
->args
, 's')) {
99 table
= server_options_table
;
100 } else if (args_has(self
->args
, 'w') ||
101 self
->entry
== &cmd_set_window_option_entry
) {
102 table
= window_options_table
;
103 if (args_has(self
->args
, 'g'))
104 oo
= &global_w_options
;
106 wl
= cmd_find_window(ctx
, args_get(args
, 't'), NULL
);
109 oo
= &wl
->window
->options
;
112 table
= session_options_table
;
113 if (args_has(self
->args
, 'g'))
114 oo
= &global_s_options
;
116 s
= cmd_find_session(ctx
, args_get(args
, 't'));
123 /* Get the option name and value. */
124 optstr
= args
->argv
[0];
125 if (*optstr
== '\0') {
126 ctx
->error(ctx
, "invalid option");
132 valstr
= args
->argv
[1];
134 /* Find the option table entry. */
136 for (oe_loop
= table
; oe_loop
->name
!= NULL
; oe_loop
++) {
137 if (strncmp(oe_loop
->name
, optstr
, strlen(optstr
)) != 0)
141 ctx
->error(ctx
, "ambiguous option: %s", optstr
);
146 /* Bail now if an exact match. */
147 if (strcmp(oe
->name
, optstr
) == 0)
151 ctx
->error(ctx
, "unknown option: %s", optstr
);
155 /* Unset or set the option. */
156 if (args_has(args
, 'u')) {
157 if (cmd_set_option_unset(self
, ctx
, oe
, oo
, valstr
) != 0)
160 if (cmd_set_option_set(self
, ctx
, oe
, oo
, valstr
) != 0)
164 /* Update sizes and redraw. May not need it but meh. */
166 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
167 c
= ARRAY_ITEM(&clients
, i
);
168 if (c
!= NULL
&& c
->session
!= NULL
)
169 server_redraw_client(c
);
173 * Special-case: kill all persistent jobs if status-left, status-right
174 * or set-titles-string have changed. Persistent jobs are only used by
175 * the status line at the moment so this works XXX.
177 if (strcmp(oe
->name
, "status-left") == 0 ||
178 strcmp(oe
->name
, "status-right") == 0 ||
179 strcmp(oe
->name
, "status") == 0 ||
180 strcmp(oe
->name
, "set-titles-string") == 0 ||
181 strcmp(oe
->name
, "window-status-format") == 0) {
182 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
183 c
= ARRAY_ITEM(&clients
, i
);
184 if (c
== NULL
|| c
->session
== NULL
)
187 jobs
= &c
->status_jobs
;
191 while (job
!= NULL
) {
192 nextjob
= RB_NEXT(jobs
, jobs
, job
);
193 if (job
->flags
& JOB_PERSIST
) {
194 job_remove(jobs
, job
);
201 server_redraw_client(c
);
208 /* Unset an option. */
210 cmd_set_option_unset(struct cmd
*self
, struct cmd_ctx
*ctx
,
211 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
213 struct args
*args
= self
->args
;
215 if (args_has(args
, 'g')) {
216 ctx
->error(ctx
, "can't unset global option: %s", oe
->name
);
220 ctx
->error(ctx
, "value passed to unset option: %s", oe
->name
);
224 options_remove(oo
, oe
->name
);
225 ctx
->info(ctx
, "unset option: %s", oe
->name
);
231 cmd_set_option_set(struct cmd
*self
, struct cmd_ctx
*ctx
,
232 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
234 struct options_entry
*o
;
237 if (oe
->type
!= OPTIONS_TABLE_FLAG
&& value
== NULL
) {
238 ctx
->error(ctx
, "empty value");
244 case OPTIONS_TABLE_STRING
:
245 o
= cmd_set_option_string(self
, ctx
, oe
, oo
, value
);
247 case OPTIONS_TABLE_NUMBER
:
248 o
= cmd_set_option_number(self
, ctx
, oe
, oo
, value
);
250 case OPTIONS_TABLE_KEYS
:
251 o
= cmd_set_option_keys(self
, ctx
, oe
, oo
, value
);
253 case OPTIONS_TABLE_COLOUR
:
254 o
= cmd_set_option_colour(self
, ctx
, oe
, oo
, value
);
256 case OPTIONS_TABLE_ATTRIBUTES
:
257 o
= cmd_set_option_attributes(self
, ctx
, oe
, oo
, value
);
259 case OPTIONS_TABLE_FLAG
:
260 o
= cmd_set_option_flag(self
, ctx
, oe
, oo
, value
);
262 case OPTIONS_TABLE_CHOICE
:
263 o
= cmd_set_option_choice(self
, ctx
, oe
, oo
, value
);
269 s
= options_table_print_entry(oe
, o
);
270 ctx
->info(ctx
, "set option: %s -> %s", oe
->name
, s
);
274 /* Set a string option. */
275 struct options_entry
*
276 cmd_set_option_string(struct cmd
*self
, unused
struct cmd_ctx
*ctx
,
277 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
279 struct args
*args
= self
->args
;
280 struct options_entry
*o
;
281 char *oldval
, *newval
;
283 if (args_has(args
, 'a')) {
284 oldval
= options_get_string(oo
, oe
->name
);
285 xasprintf(&newval
, "%s%s", oldval
, value
);
287 newval
= xstrdup(value
);
289 o
= options_set_string(oo
, oe
->name
, "%s", newval
);
295 /* Set a number option. */
296 struct options_entry
*
297 cmd_set_option_number(unused
struct cmd
*self
, struct cmd_ctx
*ctx
,
298 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
303 ll
= strtonum(value
, oe
->minimum
, oe
->maximum
, &errstr
);
304 if (errstr
!= NULL
) {
305 ctx
->error(ctx
, "value is %s: %s", errstr
, value
);
309 return (options_set_number(oo
, oe
->name
, ll
));
312 /* Set a keys option. */
313 struct options_entry
*
314 cmd_set_option_keys(unused
struct cmd
*self
, struct cmd_ctx
*ctx
,
315 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
317 struct keylist
*keylist
;
318 char *copy
, *ptr
, *s
;
321 keylist
= xmalloc(sizeof *keylist
);
324 ptr
= copy
= xstrdup(value
);
325 while ((s
= strsep(&ptr
, ",")) != NULL
) {
326 if ((key
= key_string_lookup_string(s
)) == KEYC_NONE
) {
327 ctx
->error(ctx
, "unknown key: %s", s
);
332 ARRAY_ADD(keylist
, key
);
336 return (options_set_data(oo
, oe
->name
, keylist
, xfree
));
339 /* Set a colour option. */
340 struct options_entry
*
341 cmd_set_option_colour(unused
struct cmd
*self
, struct cmd_ctx
*ctx
,
342 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
346 if ((colour
= colour_fromstring(value
)) == -1) {
347 ctx
->error(ctx
, "bad colour: %s", value
);
351 return (options_set_number(oo
, oe
->name
, colour
));
354 /* Set an attributes option. */
355 struct options_entry
*
356 cmd_set_option_attributes(unused
struct cmd
*self
, struct cmd_ctx
*ctx
,
357 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
361 if ((attr
= attributes_fromstring(value
)) == -1) {
362 ctx
->error(ctx
, "bad attributes: %s", value
);
366 return (options_set_number(oo
, oe
->name
, attr
));
369 /* Set a flag option. */
370 struct options_entry
*
371 cmd_set_option_flag(unused
struct cmd
*self
, struct cmd_ctx
*ctx
,
372 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
376 if (value
== NULL
|| *value
== '\0')
377 flag
= !options_get_number(oo
, oe
->name
);
379 if ((value
[0] == '1' && value
[1] == '\0') ||
380 strcasecmp(value
, "on") == 0 ||
381 strcasecmp(value
, "yes") == 0)
383 else if ((value
[0] == '0' && value
[1] == '\0') ||
384 strcasecmp(value
, "off") == 0 ||
385 strcasecmp(value
, "no") == 0)
388 ctx
->error(ctx
, "bad value: %s", value
);
393 return (options_set_number(oo
, oe
->name
, flag
));
396 /* Set a choice option. */
397 struct options_entry
*
398 cmd_set_option_choice(unused
struct cmd
*self
, struct cmd_ctx
*ctx
,
399 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
401 const char **choicep
;
405 for (choicep
= oe
->choices
; *choicep
!= NULL
; choicep
++) {
407 if (strncmp(*choicep
, value
, strlen(value
)) != 0)
411 ctx
->error(ctx
, "ambiguous value: %s", value
);
417 ctx
->error(ctx
, "unknown value: %s", value
);
421 return (options_set_number(oo
, oe
->name
, choice
));