[BACK]Return to cmd-set-option.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/cmd-set-option.c, Revision 1.41

1.41    ! nicm        1: /* $OpenBSD: cmd-set-option.c,v 1.40 2010/12/06 22:51:02 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
                      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 <stdlib.h>
                     22: #include <string.h>
                     23:
                     24: #include "tmux.h"
                     25:
                     26: /*
                     27:  * Set an option.
                     28:  */
                     29:
                     30: int    cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
                     31:
1.27      nicm       32: const char *cmd_set_option_print(
                     33:            const struct set_option_entry *, struct options_entry *);
                     34: void   cmd_set_option_string(struct cmd_ctx *,
                     35:            struct options *, const struct set_option_entry *, char *, int);
                     36: void   cmd_set_option_number(struct cmd_ctx *,
1.28      nicm       37:            struct options *, const struct set_option_entry *, char *);
1.27      nicm       38: void   cmd_set_option_keys(struct cmd_ctx *,
1.28      nicm       39:            struct options *, const struct set_option_entry *, char *);
1.27      nicm       40: void   cmd_set_option_colour(struct cmd_ctx *,
1.28      nicm       41:            struct options *, const struct set_option_entry *, char *);
1.27      nicm       42: void   cmd_set_option_attributes(struct cmd_ctx *,
1.28      nicm       43:            struct options *, const struct set_option_entry *, char *);
1.27      nicm       44: void   cmd_set_option_flag(struct cmd_ctx *,
1.28      nicm       45:            struct options *, const struct set_option_entry *, char *);
1.27      nicm       46: void   cmd_set_option_choice(struct cmd_ctx *,
1.28      nicm       47:            struct options *, const struct set_option_entry *, char *);
1.27      nicm       48:
1.1       nicm       49: const struct cmd_entry cmd_set_option_entry = {
                     50:        "set-option", "set",
1.29      nicm       51:        "[-agsuw] [-t target-session|target-window] option [value]",
                     52:        CMD_ARG12, "agsuw",
1.1       nicm       53:        NULL,
1.14      nicm       54:        cmd_target_parse,
1.1       nicm       55:        cmd_set_option_exec,
1.14      nicm       56:        cmd_target_free,
                     57:        cmd_target_print
1.1       nicm       58: };
                     59:
1.27      nicm       60: const char *set_option_mode_keys_list[] = {
                     61:        "emacs", "vi", NULL
                     62: };
                     63: const char *set_option_clock_mode_style_list[] = {
                     64:        "12", "24", NULL
                     65: };
1.1       nicm       66: const char *set_option_status_keys_list[] = {
                     67:        "emacs", "vi", NULL
                     68: };
1.8       nicm       69: const char *set_option_status_justify_list[] = {
                     70:        "left", "centre", "right", NULL
                     71: };
1.1       nicm       72: const char *set_option_bell_action_list[] = {
                     73:        "none", "any", "current", NULL
                     74: };
1.27      nicm       75:
1.29      nicm       76: const struct set_option_entry set_option_table[] = {
1.31      nicm       77:        { "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.39      nicm       78:        { "exit-unattached", SET_OPTION_FLAG, 0, 0, NULL },
1.29      nicm       79:        { "quiet", SET_OPTION_FLAG, 0, 0, NULL },
1.30      nicm       80:        { NULL, 0, 0, 0, NULL }
1.29      nicm       81: };
                     82:
1.27      nicm       83: const struct set_option_entry set_session_option_table[] = {
1.15      nicm       84:        { "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.1       nicm       85:        { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list },
                     86:        { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
                     87:        { "default-command", SET_OPTION_STRING, 0, 0, NULL },
                     88:        { "default-path", SET_OPTION_STRING, 0, 0, NULL },
1.17      nicm       89:        { "default-shell", SET_OPTION_STRING, 0, 0, NULL },
1.4       nicm       90:        { "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
1.39      nicm       91:        { "destroy-unattached", SET_OPTION_FLAG, 0, 0, NULL },
1.37      nicm       92:        { "detach-on-destroy", SET_OPTION_FLAG, 0, 0, NULL },
1.16      nicm       93:        { "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
1.33      nicm       94:        { "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
1.16      nicm       95:        { "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
1.1       nicm       96:        { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
                     97:        { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
                     98:        { "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.20      nicm       99:        { "lock-command", SET_OPTION_STRING, 0, 0, NULL },
1.21      nicm      100:        { "lock-server", SET_OPTION_FLAG, 0, 0, NULL },
1.1       nicm      101:        { "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    102:        { "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    103:        { "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.26      nicm      104:        { "message-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.22      nicm      105:        { "mouse-select-pane", SET_OPTION_FLAG, 0, 0, NULL },
1.32      nicm      106:        { "pane-active-border-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    107:        { "pane-active-border-fg", SET_OPTION_COLOUR, 0, 0, NULL },
                    108:        { "pane-border-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    109:        { "pane-border-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.19      nicm      110:        { "prefix", SET_OPTION_KEYS, 0, 0, NULL },
1.1       nicm      111:        { "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
                    112:        { "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
                    113:        { "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
1.18      nicm      114:        { "set-titles-string", SET_OPTION_STRING, 0, 0, NULL },
1.1       nicm      115:        { "status", SET_OPTION_FLAG, 0, 0, NULL },
                    116:        { "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    117:        { "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    118:        { "status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
                    119:        { "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.28      nicm      120:        { "status-justify",
1.8       nicm      121:          SET_OPTION_CHOICE, 0, 0, set_option_status_justify_list },
1.1       nicm      122:        { "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list },
                    123:        { "status-left", SET_OPTION_STRING, 0, 0, NULL },
1.12      nicm      124:        { "status-left-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    125:        { "status-left-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    126:        { "status-left-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.1       nicm      127:        { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
                    128:        { "status-right", SET_OPTION_STRING, 0, 0, NULL },
1.12      nicm      129:        { "status-right-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    130:        { "status-right-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    131:        { "status-right-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.1       nicm      132:        { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
1.28      nicm      133:        { "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
1.10      nicm      134:        { "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
1.13      nicm      135:        { "update-environment", SET_OPTION_STRING, 0, 0, NULL },
1.7       nicm      136:        { "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
1.28      nicm      137:        { "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
1.7       nicm      138:        { "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
1.40      nicm      139:        { "visual-silence", SET_OPTION_FLAG, 0, 0, NULL },
1.6       nicm      140:        { NULL, 0, 0, 0, NULL }
1.1       nicm      141: };
                    142:
1.27      nicm      143: const struct set_option_entry set_window_option_table[] = {
                    144:        { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL },
1.34      nicm      145:        { "alternate-screen", SET_OPTION_FLAG, 0, 0, NULL },
1.27      nicm      146:        { "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL },
                    147:        { "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL },
                    148:        { "clock-mode-style",
                    149:          SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list },
                    150:        { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
                    151:        { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
                    152:        { "main-pane-height", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
                    153:        { "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
                    154:        { "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    155:        { "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    156:        { "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL },
                    157:        { "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list },
                    158:        { "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL },
                    159:        { "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL },
                    160:        { "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
1.40      nicm      161:        { "monitor-silence",SET_OPTION_NUMBER, 0, INT_MAX, NULL},
1.41    ! nicm      162:        { "other-pane-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
        !           163:        { "other-pane-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.27      nicm      164:        { "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
                    165:        { "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL },
                    166:        { "utf8", SET_OPTION_FLAG, 0, 0, NULL },
1.36      nicm      167:        { "window-status-alert-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    168:        { "window-status-alert-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    169:        { "window-status-alert-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.27      nicm      170:        { "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    171:        { "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    172:        { "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
                    173:        { "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL },
                    174:        { "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL },
                    175:        { "window-status-current-format", SET_OPTION_STRING, 0, 0, NULL },
                    176:        { "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
                    177:        { "window-status-format", SET_OPTION_STRING, 0, 0, NULL },
1.35      nicm      178:        { "word-separators", SET_OPTION_STRING, 0, 0, NULL },
1.27      nicm      179:        { "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
                    180:        { NULL, 0, 0, 0, NULL }
                    181: };
                    182:
1.1       nicm      183: int
                    184: cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
                    185: {
1.14      nicm      186:        struct cmd_target_data          *data = self->data;
1.27      nicm      187:        const struct set_option_entry   *table;
1.1       nicm      188:        struct session                  *s;
1.27      nicm      189:        struct winlink                  *wl;
1.1       nicm      190:        struct client                   *c;
                    191:        struct options                  *oo;
1.6       nicm      192:        const struct set_option_entry   *entry, *opt;
1.24      nicm      193:        struct jobs                     *jobs;
                    194:        struct job                      *job, *nextjob;
1.1       nicm      195:        u_int                            i;
1.24      nicm      196:        int                              try_again;
1.1       nicm      197:
1.29      nicm      198:        if (cmd_check_flag(data->chflags, 's')) {
                    199:                oo = &global_options;
                    200:                table = set_option_table;
                    201:        } else if (cmd_check_flag(data->chflags, 'w')) {
1.27      nicm      202:                table = set_window_option_table;
                    203:                if (cmd_check_flag(data->chflags, 'g'))
                    204:                        oo = &global_w_options;
                    205:                else {
                    206:                        wl = cmd_find_window(ctx, data->target, NULL);
                    207:                        if (wl == NULL)
                    208:                                return (-1);
                    209:                        oo = &wl->window->options;
                    210:                }
                    211:        } else {
                    212:                table = set_session_option_table;
                    213:                if (cmd_check_flag(data->chflags, 'g'))
                    214:                        oo = &global_s_options;
                    215:                else {
                    216:                        s = cmd_find_session(ctx, data->target);
                    217:                        if (s == NULL)
                    218:                                return (-1);
                    219:                        oo = &s->options;
                    220:                }
1.1       nicm      221:        }
                    222:
1.14      nicm      223:        if (*data->arg == '\0') {
1.1       nicm      224:                ctx->error(ctx, "invalid option");
                    225:                return (-1);
                    226:        }
                    227:
                    228:        entry = NULL;
1.27      nicm      229:        for (opt = table; opt->name != NULL; opt++) {
1.14      nicm      230:                if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
1.1       nicm      231:                        continue;
                    232:                if (entry != NULL) {
1.14      nicm      233:                        ctx->error(ctx, "ambiguous option: %s", data->arg);
1.1       nicm      234:                        return (-1);
                    235:                }
1.6       nicm      236:                entry = opt;
1.1       nicm      237:
                    238:                /* Bail now if an exact match. */
1.14      nicm      239:                if (strcmp(entry->name, data->arg) == 0)
1.1       nicm      240:                        break;
                    241:        }
                    242:        if (entry == NULL) {
1.14      nicm      243:                ctx->error(ctx, "unknown option: %s", data->arg);
1.1       nicm      244:                return (-1);
                    245:        }
                    246:
1.25      nicm      247:        if (cmd_check_flag(data->chflags, 'u')) {
                    248:                if (cmd_check_flag(data->chflags, 'g')) {
1.1       nicm      249:                        ctx->error(ctx,
                    250:                            "can't unset global option: %s", entry->name);
                    251:                        return (-1);
                    252:                }
1.14      nicm      253:                if (data->arg2 != NULL) {
1.1       nicm      254:                        ctx->error(ctx,
                    255:                            "value passed to unset option: %s", entry->name);
                    256:                        return (-1);
                    257:                }
                    258:
                    259:                options_remove(oo, entry->name);
                    260:                ctx->info(ctx, "unset option: %s", entry->name);
                    261:        } else {
                    262:                switch (entry->type) {
                    263:                case SET_OPTION_STRING:
1.27      nicm      264:                        cmd_set_option_string(ctx, oo, entry,
1.25      nicm      265:                            data->arg2, cmd_check_flag(data->chflags, 'a'));
1.1       nicm      266:                        break;
                    267:                case SET_OPTION_NUMBER:
1.27      nicm      268:                        cmd_set_option_number(ctx, oo, entry, data->arg2);
1.1       nicm      269:                        break;
1.19      nicm      270:                case SET_OPTION_KEYS:
1.27      nicm      271:                        cmd_set_option_keys(ctx, oo, entry, data->arg2);
1.1       nicm      272:                        break;
                    273:                case SET_OPTION_COLOUR:
1.27      nicm      274:                        cmd_set_option_colour(ctx, oo, entry, data->arg2);
1.1       nicm      275:                        break;
                    276:                case SET_OPTION_ATTRIBUTES:
1.27      nicm      277:                        cmd_set_option_attributes(ctx, oo, entry, data->arg2);
1.1       nicm      278:                        break;
                    279:                case SET_OPTION_FLAG:
1.27      nicm      280:                        cmd_set_option_flag(ctx, oo, entry, data->arg2);
1.1       nicm      281:                        break;
                    282:                case SET_OPTION_CHOICE:
1.27      nicm      283:                        cmd_set_option_choice(ctx, oo, entry, data->arg2);
1.1       nicm      284:                        break;
                    285:                }
                    286:        }
                    287:
                    288:        recalculate_sizes();
1.27      nicm      289:        for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
                    290:                c = ARRAY_ITEM(&clients, i);
                    291:                if (c != NULL && c->session != NULL)
                    292:                        server_redraw_client(c);
                    293:        }
1.24      nicm      294:
1.28      nicm      295:        /*
1.24      nicm      296:         * Special-case: kill all persistent jobs if status-left, status-right
                    297:         * or set-titles-string have changed. Persistent jobs are only used by
                    298:         * the status line at the moment so this works XXX.
                    299:         */
                    300:        if (strcmp(entry->name, "status-left") == 0 ||
                    301:            strcmp(entry->name, "status-right") == 0 ||
1.38      nicm      302:            strcmp(entry->name, "status") == 0 ||
1.27      nicm      303:            strcmp(entry->name, "set-titles-string") == 0 ||
                    304:            strcmp(entry->name, "window-status-format") == 0) {
1.24      nicm      305:                for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
                    306:                        c = ARRAY_ITEM(&clients, i);
                    307:                        if (c == NULL || c->session == NULL)
                    308:                                continue;
                    309:
                    310:                        jobs = &c->status_jobs;
                    311:                        do {
1.28      nicm      312:                                try_again = 0;
1.24      nicm      313:                                job = RB_ROOT(jobs);
                    314:                                while (job != NULL) {
                    315:                                        nextjob = RB_NEXT(jobs, jobs, job);
                    316:                                        if (job->flags & JOB_PERSIST) {
                    317:                                                job_remove(jobs, job);
                    318:                                                try_again = 1;
                    319:                                                break;
                    320:                                        }
                    321:                                        job = nextjob;
                    322:                                }
                    323:                        } while (try_again);
1.1       nicm      324:                        server_redraw_client(c);
1.23      nicm      325:                }
1.1       nicm      326:        }
                    327:
                    328:        return (0);
1.27      nicm      329: }
                    330:
                    331: const char *
                    332: cmd_set_option_print(
                    333:     const struct set_option_entry *entry, struct options_entry *o)
                    334: {
                    335:        static char     out[BUFSIZ];
                    336:        const char     *s;
                    337:        struct keylist *keylist;
                    338:        u_int           i;
                    339:
                    340:        *out = '\0';
                    341:        switch (entry->type) {
                    342:                case SET_OPTION_STRING:
                    343:                        xsnprintf(out, sizeof out, "\"%s\"", o->str);
                    344:                        break;
                    345:                case SET_OPTION_NUMBER:
                    346:                        xsnprintf(out, sizeof out, "%lld", o->num);
                    347:                        break;
                    348:                case SET_OPTION_KEYS:
                    349:                        keylist = o->data;
                    350:                        for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
                    351:                                strlcat(out, key_string_lookup_key(
                    352:                                    ARRAY_ITEM(keylist, i)), sizeof out);
                    353:                                if (i != ARRAY_LENGTH(keylist) - 1)
                    354:                                        strlcat(out, ",", sizeof out);
                    355:                        }
                    356:                        break;
                    357:                case SET_OPTION_COLOUR:
                    358:                        s = colour_tostring(o->num);
                    359:                        xsnprintf(out, sizeof out, "%s", s);
                    360:                        break;
                    361:                case SET_OPTION_ATTRIBUTES:
                    362:                        s = attributes_tostring(o->num);
                    363:                        xsnprintf(out, sizeof out, "%s", s);
                    364:                        break;
                    365:                case SET_OPTION_FLAG:
                    366:                        if (o->num)
                    367:                                strlcpy(out, "on", sizeof out);
                    368:                        else
                    369:                                strlcpy(out, "off", sizeof out);
                    370:                        break;
                    371:                case SET_OPTION_CHOICE:
                    372:                        s = entry->choices[o->num];
                    373:                        xsnprintf(out, sizeof out, "%s", s);
                    374:                        break;
                    375:        }
                    376:        return (out);
                    377: }
                    378:
                    379: void
                    380: cmd_set_option_string(struct cmd_ctx *ctx, struct options *oo,
                    381:     const struct set_option_entry *entry, char *value, int append)
                    382: {
                    383:        struct options_entry    *o;
                    384:        char                    *oldvalue, *newvalue;
                    385:
                    386:        if (value == NULL) {
                    387:                ctx->error(ctx, "empty value");
                    388:                return;
                    389:        }
                    390:
                    391:        if (append) {
                    392:                oldvalue = options_get_string(oo, entry->name);
                    393:                xasprintf(&newvalue, "%s%s", oldvalue, value);
                    394:        } else
                    395:                newvalue = value;
1.28      nicm      396:
1.27      nicm      397:        o = options_set_string(oo, entry->name, "%s", newvalue);
                    398:        ctx->info(ctx,
                    399:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
                    400:
                    401:        if (newvalue != value)
                    402:                xfree(newvalue);
                    403: }
                    404:
                    405: void
                    406: cmd_set_option_number(struct cmd_ctx *ctx, struct options *oo,
                    407:     const struct set_option_entry *entry, char *value)
                    408: {
                    409:        struct options_entry    *o;
                    410:        long long                number;
                    411:        const char              *errstr;
                    412:
                    413:        if (value == NULL) {
                    414:                ctx->error(ctx, "empty value");
                    415:                return;
                    416:        }
                    417:
                    418:        number = strtonum(value, entry->minimum, entry->maximum, &errstr);
                    419:        if (errstr != NULL) {
                    420:                ctx->error(ctx, "value is %s: %s", errstr, value);
                    421:                return;
                    422:        }
                    423:
                    424:        o = options_set_number(oo, entry->name, number);
                    425:        ctx->info(ctx,
                    426:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
                    427: }
                    428:
                    429: void
                    430: cmd_set_option_keys(struct cmd_ctx *ctx, struct options *oo,
                    431:     const struct set_option_entry *entry, char *value)
                    432: {
                    433:        struct options_entry    *o;
                    434:        struct keylist          *keylist;
                    435:        char                    *copyvalue, *ptr, *str;
                    436:        int                      key;
                    437:
                    438:        if (value == NULL) {
                    439:                ctx->error(ctx, "empty value");
                    440:                return;
                    441:        }
                    442:
                    443:        keylist = xmalloc(sizeof *keylist);
                    444:        ARRAY_INIT(keylist);
                    445:
                    446:        ptr = copyvalue = xstrdup(value);
                    447:        while ((str = strsep(&ptr, ",")) != NULL) {
                    448:                if ((key = key_string_lookup_string(str)) == KEYC_NONE) {
                    449:                        xfree(keylist);
                    450:                        ctx->error(ctx, "unknown key: %s", str);
                    451:                        xfree(copyvalue);
                    452:                        return;
                    453:                }
                    454:                ARRAY_ADD(keylist, key);
                    455:        }
                    456:        xfree(copyvalue);
                    457:
                    458:        o = options_set_data(oo, entry->name, keylist, xfree);
                    459:        ctx->info(ctx,
                    460:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
                    461: }
                    462:
                    463: void
                    464: cmd_set_option_colour(struct cmd_ctx *ctx, struct options *oo,
                    465:     const struct set_option_entry *entry, char *value)
                    466: {
                    467:        struct options_entry    *o;
                    468:        int                      colour;
                    469:
                    470:        if (value == NULL) {
                    471:                ctx->error(ctx, "empty value");
                    472:                return;
                    473:        }
                    474:
                    475:        if ((colour = colour_fromstring(value)) == -1) {
                    476:                ctx->error(ctx, "bad colour: %s", value);
                    477:                return;
                    478:        }
                    479:
                    480:        o = options_set_number(oo, entry->name, colour);
                    481:        ctx->info(ctx,
                    482:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
                    483: }
                    484:
                    485: void
                    486: cmd_set_option_attributes(struct cmd_ctx *ctx, struct options *oo,
                    487:     const struct set_option_entry *entry, char *value)
                    488: {
                    489:        struct options_entry    *o;
                    490:        int                      attr;
                    491:
                    492:        if (value == NULL) {
                    493:                ctx->error(ctx, "empty value");
                    494:                return;
                    495:        }
                    496:
                    497:        if ((attr = attributes_fromstring(value)) == -1) {
                    498:                ctx->error(ctx, "bad attributes: %s", value);
                    499:                return;
                    500:        }
                    501:
                    502:        o = options_set_number(oo, entry->name, attr);
                    503:        ctx->info(ctx,
                    504:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
                    505: }
                    506:
                    507: void
                    508: cmd_set_option_flag(struct cmd_ctx *ctx, struct options *oo,
                    509:     const struct set_option_entry *entry, char *value)
                    510: {
                    511:        struct options_entry    *o;
                    512:        int                      flag;
                    513:
                    514:        if (value == NULL || *value == '\0')
                    515:                flag = !options_get_number(oo, entry->name);
                    516:        else {
                    517:                if ((value[0] == '1' && value[1] == '\0') ||
                    518:                    strcasecmp(value, "on") == 0 ||
                    519:                    strcasecmp(value, "yes") == 0)
                    520:                        flag = 1;
                    521:                else if ((value[0] == '0' && value[1] == '\0') ||
                    522:                    strcasecmp(value, "off") == 0 ||
                    523:                    strcasecmp(value, "no") == 0)
                    524:                        flag = 0;
                    525:                else {
                    526:                        ctx->error(ctx, "bad value: %s", value);
                    527:                        return;
                    528:                }
                    529:        }
                    530:
                    531:        o = options_set_number(oo, entry->name, flag);
                    532:        ctx->info(ctx,
                    533:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
                    534: }
                    535:
                    536: void
                    537: cmd_set_option_choice(struct cmd_ctx *ctx, struct options *oo,
                    538:     const struct set_option_entry *entry, char *value)
                    539: {
                    540:        struct options_entry    *o;
                    541:        const char             **choicep;
                    542:        int                      n, choice = -1;
                    543:
                    544:        if (value == NULL) {
                    545:                ctx->error(ctx, "empty value");
                    546:                return;
                    547:        }
                    548:
                    549:        n = 0;
                    550:        for (choicep = entry->choices; *choicep != NULL; choicep++) {
                    551:                n++;
                    552:                if (strncmp(*choicep, value, strlen(value)) != 0)
                    553:                        continue;
                    554:
                    555:                if (choice != -1) {
                    556:                        ctx->error(ctx, "ambiguous option value: %s", value);
                    557:                        return;
                    558:                }
                    559:                choice = n - 1;
                    560:        }
                    561:        if (choice == -1) {
                    562:                ctx->error(ctx, "unknown option value: %s", value);
                    563:                return;
                    564:        }
                    565:
                    566:        o = options_set_number(oo, entry->name, choice);
                    567:        ctx->info(ctx,
                    568:            "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
1.1       nicm      569: }