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 enum cmd_retval
cmd_set_option_exec(struct cmd
*, struct cmd_q
*);
32 enum cmd_retval
cmd_set_option_user(struct cmd
*, struct cmd_q
*,
33 const char *, const char *);
35 int cmd_set_option_unset(struct cmd
*, struct cmd_q
*,
36 const struct options_table_entry
*, struct options
*,
38 int cmd_set_option_set(struct cmd
*, struct cmd_q
*,
39 const struct options_table_entry
*, struct options
*,
42 struct options_entry
*cmd_set_option_string(struct cmd
*, struct cmd_q
*,
43 const struct options_table_entry
*, struct options
*,
45 struct options_entry
*cmd_set_option_number(struct cmd
*, struct cmd_q
*,
46 const struct options_table_entry
*, struct options
*,
48 struct options_entry
*cmd_set_option_key(struct cmd
*, struct cmd_q
*,
49 const struct options_table_entry
*, struct options
*,
51 struct options_entry
*cmd_set_option_colour(struct cmd
*, struct cmd_q
*,
52 const struct options_table_entry
*, struct options
*,
54 struct options_entry
*cmd_set_option_attributes(struct cmd
*, struct cmd_q
*,
55 const struct options_table_entry
*, struct options
*,
57 struct options_entry
*cmd_set_option_flag(struct cmd
*, struct cmd_q
*,
58 const struct options_table_entry
*, struct options
*,
60 struct options_entry
*cmd_set_option_choice(struct cmd
*, struct cmd_q
*,
61 const struct options_table_entry
*, struct options
*,
63 struct options_entry
*cmd_set_option_style(struct cmd
*, struct cmd_q
*,
64 const struct options_table_entry
*, struct options
*,
67 const struct cmd_entry cmd_set_option_entry
= {
70 "[-agosquw] [-t target-session|target-window] option [value]",
76 const struct cmd_entry cmd_set_window_option_entry
= {
77 "set-window-option", "setw",
79 "[-agoqu] " CMD_TARGET_WINDOW_USAGE
" option [value]",
86 cmd_set_option_exec(struct cmd
*self
, struct cmd_q
*cmdq
)
88 struct args
*args
= self
->args
;
89 const struct options_table_entry
*table
, *oe
;
95 const char *optstr
, *valstr
;
98 /* Get the option name and value. */
99 optstr
= args
->argv
[0];
100 if (*optstr
== '\0') {
101 cmdq_error(cmdq
, "invalid option");
102 return (CMD_RETURN_ERROR
);
107 valstr
= args
->argv
[1];
109 /* Is this a user option? */
111 return (cmd_set_option_user(self
, cmdq
, optstr
, valstr
));
113 /* Find the option entry, try each table. */
115 if (options_table_find(optstr
, &table
, &oe
) != 0) {
116 cmdq_error(cmdq
, "ambiguous option: %s", optstr
);
117 return (CMD_RETURN_ERROR
);
120 cmdq_error(cmdq
, "unknown option: %s", optstr
);
121 return (CMD_RETURN_ERROR
);
124 /* Work out the tree from the table. */
125 if (table
== server_options_table
)
126 oo
= &global_options
;
127 else if (table
== window_options_table
) {
128 if (args_has(self
->args
, 'g'))
129 oo
= &global_w_options
;
131 wl
= cmd_find_window(cmdq
, args_get(args
, 't'), NULL
);
134 "couldn't set '%s'%s", optstr
,
135 (!args_has(args
, 't') && !args_has(args
,
136 'g')) ? " need target window or -g" : "");
137 return (CMD_RETURN_ERROR
);
139 oo
= &wl
->window
->options
;
141 } else if (table
== session_options_table
) {
142 if (args_has(self
->args
, 'g'))
143 oo
= &global_s_options
;
145 s
= cmd_find_session(cmdq
, args_get(args
, 't'), 0);
148 "couldn't set '%s'%s", optstr
,
149 (!args_has(args
, 't') && !args_has(args
,
150 'g')) ? " need target session or -g" : "");
151 return (CMD_RETURN_ERROR
);
156 cmdq_error(cmdq
, "unknown table");
157 return (CMD_RETURN_ERROR
);
160 /* Unset or set the option. */
161 if (args_has(args
, 'u')) {
162 if (cmd_set_option_unset(self
, cmdq
, oe
, oo
, valstr
) != 0)
163 return (CMD_RETURN_ERROR
);
165 if (args_has(args
, 'o') && options_find1(oo
, optstr
) != NULL
) {
166 if (!args_has(args
, 'q'))
167 cmdq_print(cmdq
, "already set: %s", optstr
);
168 return (CMD_RETURN_NORMAL
);
170 if (cmd_set_option_set(self
, cmdq
, oe
, oo
, valstr
) != 0)
171 return (CMD_RETURN_ERROR
);
174 /* Start or stop timers when automatic-rename changed. */
175 if (strcmp(oe
->name
, "automatic-rename") == 0) {
176 for (i
= 0; i
< ARRAY_LENGTH(&windows
); i
++) {
177 if ((w
= ARRAY_ITEM(&windows
, i
)) == NULL
)
179 if (options_get_number(&w
->options
, "automatic-rename"))
180 queue_window_name(w
);
181 else if (event_initialized(&w
->name_timer
))
182 evtimer_del(&w
->name_timer
);
186 /* Update sizes and redraw. May not need it but meh. */
188 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
189 c
= ARRAY_ITEM(&clients
, i
);
190 if (c
!= NULL
&& c
->session
!= NULL
)
191 server_redraw_client(c
);
194 return (CMD_RETURN_NORMAL
);
197 /* Set user option. */
199 cmd_set_option_user(struct cmd
*self
, struct cmd_q
*cmdq
, const char* optstr
,
202 struct args
*args
= self
->args
;
207 if (args_has(args
, 's'))
208 oo
= &global_options
;
209 else if (args_has(self
->args
, 'w') ||
210 self
->entry
== &cmd_set_window_option_entry
) {
211 if (args_has(self
->args
, 'g'))
212 oo
= &global_w_options
;
214 wl
= cmd_find_window(cmdq
, args_get(args
, 't'), NULL
);
216 return (CMD_RETURN_ERROR
);
217 oo
= &wl
->window
->options
;
220 if (args_has(self
->args
, 'g'))
221 oo
= &global_s_options
;
223 s
= cmd_find_session(cmdq
, args_get(args
, 't'), 0);
225 return (CMD_RETURN_ERROR
);
230 if (args_has(args
, 'u')) {
231 if (options_find1(oo
, optstr
) == NULL
) {
232 cmdq_error(cmdq
, "unknown option: %s", optstr
);
233 return (CMD_RETURN_ERROR
);
235 if (valstr
!= NULL
) {
236 cmdq_error(cmdq
, "value passed to unset option: %s",
238 return (CMD_RETURN_ERROR
);
240 options_remove(oo
, optstr
);
242 if (valstr
== NULL
) {
243 cmdq_error(cmdq
, "empty value");
244 return (CMD_RETURN_ERROR
);
246 if (args_has(args
, 'o') && options_find1(oo
, optstr
) != NULL
) {
247 if (!args_has(args
, 'q'))
248 cmdq_print(cmdq
, "already set: %s", optstr
);
249 return (CMD_RETURN_NORMAL
);
251 options_set_string(oo
, optstr
, "%s", valstr
);
252 if (!args_has(args
, 'q')) {
253 cmdq_info(cmdq
, "set option: %s -> %s", optstr
,
257 return (CMD_RETURN_NORMAL
);
261 /* Unset an option. */
263 cmd_set_option_unset(struct cmd
*self
, struct cmd_q
*cmdq
,
264 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
266 struct args
*args
= self
->args
;
268 if (args_has(args
, 'g')) {
269 cmdq_error(cmdq
, "can't unset global option: %s", oe
->name
);
273 cmdq_error(cmdq
, "value passed to unset option: %s", oe
->name
);
277 options_remove(oo
, oe
->name
);
278 if (!args_has(args
, 'q'))
279 cmdq_info(cmdq
, "unset option: %s", oe
->name
);
285 cmd_set_option_set(struct cmd
*self
, struct cmd_q
*cmdq
,
286 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
288 struct args
*args
= self
->args
;
289 struct options_entry
*o
;
292 if (oe
->type
!= OPTIONS_TABLE_FLAG
&& value
== NULL
) {
293 cmdq_error(cmdq
, "empty value");
299 case OPTIONS_TABLE_STRING
:
300 o
= cmd_set_option_string(self
, cmdq
, oe
, oo
, value
);
302 case OPTIONS_TABLE_NUMBER
:
303 o
= cmd_set_option_number(self
, cmdq
, oe
, oo
, value
);
305 case OPTIONS_TABLE_KEY
:
306 o
= cmd_set_option_key(self
, cmdq
, oe
, oo
, value
);
308 case OPTIONS_TABLE_COLOUR
:
309 o
= cmd_set_option_colour(self
, cmdq
, oe
, oo
, value
);
311 style_update_new(oo
, o
->name
, oe
->style
);
313 case OPTIONS_TABLE_ATTRIBUTES
:
314 o
= cmd_set_option_attributes(self
, cmdq
, oe
, oo
, value
);
316 style_update_new(oo
, o
->name
, oe
->style
);
318 case OPTIONS_TABLE_FLAG
:
319 o
= cmd_set_option_flag(self
, cmdq
, oe
, oo
, value
);
321 case OPTIONS_TABLE_CHOICE
:
322 o
= cmd_set_option_choice(self
, cmdq
, oe
, oo
, value
);
324 case OPTIONS_TABLE_STYLE
:
325 o
= cmd_set_option_style(self
, cmdq
, oe
, oo
, value
);
331 s
= options_table_print_entry(oe
, o
, 0);
332 if (!args_has(args
, 'q'))
333 cmdq_info(cmdq
, "set option: %s -> %s", oe
->name
, s
);
337 /* Set a string option. */
338 struct options_entry
*
339 cmd_set_option_string(struct cmd
*self
, unused
struct cmd_q
*cmdq
,
340 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
342 struct args
*args
= self
->args
;
343 struct options_entry
*o
;
344 char *oldval
, *newval
;
346 if (args_has(args
, 'a')) {
347 oldval
= options_get_string(oo
, oe
->name
);
348 xasprintf(&newval
, "%s%s", oldval
, value
);
350 newval
= xstrdup(value
);
352 o
= options_set_string(oo
, oe
->name
, "%s", newval
);
358 /* Set a number option. */
359 struct options_entry
*
360 cmd_set_option_number(unused
struct cmd
*self
, struct cmd_q
*cmdq
,
361 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
366 ll
= strtonum(value
, oe
->minimum
, oe
->maximum
, &errstr
);
367 if (errstr
!= NULL
) {
368 cmdq_error(cmdq
, "value is %s: %s", errstr
, value
);
372 return (options_set_number(oo
, oe
->name
, ll
));
375 /* Set a key option. */
376 struct options_entry
*
377 cmd_set_option_key(unused
struct cmd
*self
, struct cmd_q
*cmdq
,
378 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
382 if ((key
= key_string_lookup_string(value
)) == KEYC_NONE
) {
383 cmdq_error(cmdq
, "bad key: %s", value
);
387 return (options_set_number(oo
, oe
->name
, key
));
390 /* Set a colour option. */
391 struct options_entry
*
392 cmd_set_option_colour(unused
struct cmd
*self
, struct cmd_q
*cmdq
,
393 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
397 if ((colour
= colour_fromstring(value
)) == -1) {
398 cmdq_error(cmdq
, "bad colour: %s", value
);
402 return (options_set_number(oo
, oe
->name
, colour
));
405 /* Set an attributes option. */
406 struct options_entry
*
407 cmd_set_option_attributes(unused
struct cmd
*self
, struct cmd_q
*cmdq
,
408 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
412 if ((attr
= attributes_fromstring(value
)) == -1) {
413 cmdq_error(cmdq
, "bad attributes: %s", value
);
417 return (options_set_number(oo
, oe
->name
, attr
));
420 /* Set a flag option. */
421 struct options_entry
*
422 cmd_set_option_flag(unused
struct cmd
*self
, struct cmd_q
*cmdq
,
423 const struct options_table_entry
*oe
, struct options
*oo
, const char *value
)
427 if (value
== NULL
|| *value
== '\0')
428 flag
= !options_get_number(oo
, oe
->name
);
430 if ((value
[0] == '1' && value
[1] == '\0') ||
431 strcasecmp(value
, "on") == 0 ||
432 strcasecmp(value
, "yes") == 0)
434 else if ((value
[0] == '0' && value
[1] == '\0') ||
435 strcasecmp(value
, "off") == 0 ||
436 strcasecmp(value
, "no") == 0)
439 cmdq_error(cmdq
, "bad value: %s", value
);
444 return (options_set_number(oo
, oe
->name
, flag
));
447 /* Set a choice option. */
448 struct options_entry
*
449 cmd_set_option_choice(unused
struct cmd
*self
, struct cmd_q
*cmdq
,
450 const struct options_table_entry
*oe
, struct options
*oo
,
453 const char **choicep
;
457 for (choicep
= oe
->choices
; *choicep
!= NULL
; choicep
++) {
459 if (strncmp(*choicep
, value
, strlen(value
)) != 0)
463 cmdq_error(cmdq
, "ambiguous value: %s", value
);
469 cmdq_error(cmdq
, "unknown value: %s", value
);
473 return (options_set_number(oo
, oe
->name
, choice
));
476 /* Set a style option. */
477 struct options_entry
*
478 cmd_set_option_style(struct cmd
*self
, struct cmd_q
*cmdq
,
479 const struct options_table_entry
*oe
, struct options
*oo
,
482 struct args
*args
= self
->args
;
483 struct options_entry
*o
;
486 append
= args_has(args
, 'a');
487 if ((o
= options_set_style(oo
, oe
->name
, value
, append
)) == NULL
) {
488 cmdq_error(cmdq
, "bad style: %s", value
);
492 style_update_old(oo
, oe
->name
, &o
->style
);