[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.43

1.43    ! nicm        1: /* $OpenBSD: cmd-set-option.c,v 1.42 2010/12/30 23:16:18 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.43    ! nicm       32: int    cmd_set_option_unset(struct cmd *, struct cmd_ctx *,
        !            33:            const struct options_table_entry *, struct options *);
        !            34: int    cmd_set_option_set(struct cmd *, struct cmd_ctx *,
        !            35:            const struct options_table_entry *, struct options *);
        !            36:
        !            37: struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *,
        !            38:            const struct options_table_entry *, struct options *);
        !            39: struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *,
        !            40:            const struct options_table_entry *, struct options *);
        !            41: struct options_entry *cmd_set_option_keys(struct cmd *, struct cmd_ctx *,
        !            42:            const struct options_table_entry *, struct options *);
        !            43: struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *,
        !            44:            const struct options_table_entry *, struct options *);
        !            45: struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_ctx *,
        !            46:            const struct options_table_entry *, struct options *);
        !            47: struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_ctx *,
        !            48:            const struct options_table_entry *, struct options *);
        !            49: struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *,
        !            50:            const struct options_table_entry *, struct options *);
1.27      nicm       51:
1.1       nicm       52: const struct cmd_entry cmd_set_option_entry = {
                     53:        "set-option", "set",
1.29      nicm       54:        "[-agsuw] [-t target-session|target-window] option [value]",
                     55:        CMD_ARG12, "agsuw",
1.1       nicm       56:        NULL,
1.14      nicm       57:        cmd_target_parse,
1.1       nicm       58:        cmd_set_option_exec,
1.14      nicm       59:        cmd_target_free,
                     60:        cmd_target_print
1.1       nicm       61: };
                     62:
                     63: int
                     64: cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
                     65: {
1.43    ! nicm       66:        struct cmd_target_data                  *data = self->data;
        !            67:        const struct options_table_entry        *table, *oe, *oe_loop;
        !            68:        struct session                          *s;
        !            69:        struct winlink                          *wl;
        !            70:        struct client                           *c;
        !            71:        struct options                          *oo;
        !            72:        struct jobs                             *jobs;
        !            73:        struct job                              *job, *nextjob;
        !            74:        u_int                                    i;
        !            75:        int                                      try_again;
1.1       nicm       76:
1.43    ! nicm       77:        /* Work out the options tree and table to use. */
1.29      nicm       78:        if (cmd_check_flag(data->chflags, 's')) {
                     79:                oo = &global_options;
1.43    ! nicm       80:                table = server_options_table;
1.29      nicm       81:        } else if (cmd_check_flag(data->chflags, 'w')) {
1.43    ! nicm       82:                table = window_options_table;
1.27      nicm       83:                if (cmd_check_flag(data->chflags, 'g'))
                     84:                        oo = &global_w_options;
                     85:                else {
                     86:                        wl = cmd_find_window(ctx, data->target, NULL);
                     87:                        if (wl == NULL)
                     88:                                return (-1);
                     89:                        oo = &wl->window->options;
                     90:                }
                     91:        } else {
1.43    ! nicm       92:                table = session_options_table;
1.27      nicm       93:                if (cmd_check_flag(data->chflags, 'g'))
                     94:                        oo = &global_s_options;
                     95:                else {
                     96:                        s = cmd_find_session(ctx, data->target);
                     97:                        if (s == NULL)
                     98:                                return (-1);
                     99:                        oo = &s->options;
                    100:                }
1.1       nicm      101:        }
                    102:
1.43    ! nicm      103:        /* Find the option table entry. */
        !           104:        oe = NULL;
        !           105:        for (oe_loop = table; oe_loop->name != NULL; oe_loop++) {
        !           106:                if (strncmp(oe_loop->name, data->arg, strlen(data->arg)) != 0)
1.1       nicm      107:                        continue;
1.43    ! nicm      108:                if (oe != NULL) {
1.14      nicm      109:                        ctx->error(ctx, "ambiguous option: %s", data->arg);
1.1       nicm      110:                        return (-1);
                    111:                }
1.43    ! nicm      112:                oe = oe_loop;
1.1       nicm      113:
                    114:                /* Bail now if an exact match. */
1.43    ! nicm      115:                if (strcmp(oe->name, data->arg) == 0)
1.1       nicm      116:                        break;
                    117:        }
1.43    ! nicm      118:        if (oe == NULL) {
1.14      nicm      119:                ctx->error(ctx, "unknown option: %s", data->arg);
1.1       nicm      120:                return (-1);
                    121:        }
                    122:
1.43    ! nicm      123:        /* Unset or set the option. */
1.25      nicm      124:        if (cmd_check_flag(data->chflags, 'u')) {
1.43    ! nicm      125:                if (cmd_set_option_unset(self, ctx, oe, oo) != 0)
1.1       nicm      126:                        return (-1);
1.43    ! nicm      127:        } else {
        !           128:                if (cmd_set_option_set(self, ctx, oe, oo) != 0)
1.1       nicm      129:                        return (-1);
                    130:        }
                    131:
1.43    ! nicm      132:        /* Update sizes and redraw. May not need it but meh. */
1.1       nicm      133:        recalculate_sizes();
1.27      nicm      134:        for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
                    135:                c = ARRAY_ITEM(&clients, i);
                    136:                if (c != NULL && c->session != NULL)
                    137:                        server_redraw_client(c);
                    138:        }
1.24      nicm      139:
1.28      nicm      140:        /*
1.24      nicm      141:         * Special-case: kill all persistent jobs if status-left, status-right
                    142:         * or set-titles-string have changed. Persistent jobs are only used by
                    143:         * the status line at the moment so this works XXX.
                    144:         */
1.43    ! nicm      145:        if (strcmp(oe->name, "status-left") == 0 ||
        !           146:            strcmp(oe->name, "status-right") == 0 ||
        !           147:            strcmp(oe->name, "status") == 0 ||
        !           148:            strcmp(oe->name, "set-titles-string") == 0 ||
        !           149:            strcmp(oe->name, "window-status-format") == 0) {
1.24      nicm      150:                for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
                    151:                        c = ARRAY_ITEM(&clients, i);
                    152:                        if (c == NULL || c->session == NULL)
                    153:                                continue;
                    154:
                    155:                        jobs = &c->status_jobs;
                    156:                        do {
1.28      nicm      157:                                try_again = 0;
1.24      nicm      158:                                job = RB_ROOT(jobs);
                    159:                                while (job != NULL) {
                    160:                                        nextjob = RB_NEXT(jobs, jobs, job);
                    161:                                        if (job->flags & JOB_PERSIST) {
                    162:                                                job_remove(jobs, job);
                    163:                                                try_again = 1;
                    164:                                                break;
                    165:                                        }
                    166:                                        job = nextjob;
                    167:                                }
                    168:                        } while (try_again);
1.1       nicm      169:                        server_redraw_client(c);
1.23      nicm      170:                }
1.1       nicm      171:        }
                    172:
                    173:        return (0);
1.27      nicm      174: }
                    175:
1.43    ! nicm      176: /* Unset an option. */
        !           177: int
        !           178: cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx,
        !           179:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      180: {
1.43    ! nicm      181:        struct cmd_target_data  *data = self->data;
        !           182:
        !           183:        if (cmd_check_flag(data->chflags, 'g')) {
        !           184:                ctx->error(ctx, "can't unset global option: %s", oe->name);
        !           185:                return (-1);
        !           186:        }
        !           187:        if (data->arg2 != NULL) {
        !           188:                ctx->error(ctx, "value passed to unset option: %s", oe->name);
        !           189:                return (-1);
1.27      nicm      190:        }
1.43    ! nicm      191:
        !           192:        options_remove(oo, oe->name);
        !           193:        ctx->info(ctx, "unset option: %s", oe->name);
        !           194:        return (0);
1.27      nicm      195: }
                    196:
1.43    ! nicm      197: /* Set an option. */
        !           198: int
        !           199: cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
        !           200:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      201: {
1.43    ! nicm      202:        struct cmd_target_data  *data = self->data;
1.27      nicm      203:        struct options_entry    *o;
1.43    ! nicm      204:        const char              *s;
1.27      nicm      205:
1.43    ! nicm      206:        if (oe->type != OPTIONS_TABLE_FLAG && data->arg2 == NULL) {
        !           207:                ctx->error(ctx, "empty data->arg2");
        !           208:                return (-1);
1.27      nicm      209:        }
                    210:
1.43    ! nicm      211:        o = NULL;
        !           212:        switch (oe->type) {
        !           213:        case OPTIONS_TABLE_STRING:
        !           214:                o = cmd_set_option_string(self, ctx, oe, oo);
        !           215:                break;
        !           216:        case OPTIONS_TABLE_NUMBER:
        !           217:                o = cmd_set_option_number(self, ctx, oe, oo);
        !           218:                break;
        !           219:        case OPTIONS_TABLE_KEYS:
        !           220:                o = cmd_set_option_keys(self, ctx, oe, oo);
        !           221:                break;
        !           222:        case OPTIONS_TABLE_COLOUR:
        !           223:                o = cmd_set_option_colour(self, ctx, oe, oo);
        !           224:                break;
        !           225:        case OPTIONS_TABLE_ATTRIBUTES:
        !           226:                o = cmd_set_option_attributes(self, ctx, oe, oo);
        !           227:                break;
        !           228:        case OPTIONS_TABLE_FLAG:
        !           229:                o = cmd_set_option_flag(self, ctx, oe, oo);
        !           230:                break;
        !           231:        case OPTIONS_TABLE_CHOICE:
        !           232:                o = cmd_set_option_choice(self, ctx, oe, oo);
        !           233:                break;
        !           234:        }
        !           235:        if (o == NULL)
        !           236:                return (-1);
        !           237:
        !           238:        s = options_table_print_entry(oe, o);
        !           239:        ctx->info(ctx, "set option: %s -> %s", oe->name, s);
        !           240:        return (0);
        !           241: }
        !           242:
        !           243: /* Set a string option. */
        !           244: struct options_entry *
        !           245: cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
        !           246:     const struct options_table_entry *oe, struct options *oo)
        !           247: {
        !           248:        struct cmd_target_data  *data = self->data;
        !           249:        struct options_entry    *o;
        !           250:        char                    *oldval, *newval;
        !           251:
        !           252:        if (cmd_check_flag(data->chflags, 'a')) {
        !           253:                oldval = options_get_string(oo, oe->name);
        !           254:                xasprintf(&newval, "%s%s", oldval, data->arg2);
1.27      nicm      255:        } else
1.43    ! nicm      256:                newval = data->arg2;
1.28      nicm      257:
1.43    ! nicm      258:        o = options_set_string(oo, oe->name, "%s", newval);
1.27      nicm      259:
1.43    ! nicm      260:        if (newval != data->arg2)
        !           261:                xfree(newval);
        !           262:        return (o);
1.27      nicm      263: }
                    264:
1.43    ! nicm      265: /* Set a number option. */
        !           266: struct options_entry *
        !           267: cmd_set_option_number(struct cmd *self, struct cmd_ctx *ctx,
        !           268:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      269: {
1.43    ! nicm      270:        struct cmd_target_data  *data = self->data;
        !           271:        long long                ll;
1.27      nicm      272:        const char              *errstr;
                    273:
1.43    ! nicm      274:        ll = strtonum(data->arg2, oe->minimum, oe->maximum, &errstr);
1.27      nicm      275:        if (errstr != NULL) {
1.43    ! nicm      276:                ctx->error(ctx, "value is %s: %s", errstr, data->arg2);
        !           277:                return (NULL);
1.27      nicm      278:        }
                    279:
1.43    ! nicm      280:        return (options_set_number(oo, oe->name, ll));
1.27      nicm      281: }
                    282:
1.43    ! nicm      283: /* Set a keys option. */
        !           284: struct options_entry *
        !           285: cmd_set_option_keys(struct cmd *self, struct cmd_ctx *ctx,
        !           286:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      287: {
1.43    ! nicm      288:        struct cmd_target_data  *data = self->data;
1.27      nicm      289:        struct keylist          *keylist;
1.43    ! nicm      290:        char                    *copy, *ptr, *s;
1.27      nicm      291:        int                      key;
                    292:
                    293:        keylist = xmalloc(sizeof *keylist);
                    294:        ARRAY_INIT(keylist);
                    295:
1.43    ! nicm      296:        ptr = copy = xstrdup(data->arg2);
        !           297:        while ((s = strsep(&ptr, ",")) != NULL) {
        !           298:                if ((key = key_string_lookup_string(s)) == KEYC_NONE) {
        !           299:                        ctx->error(ctx, "unknown key: %s", s);
        !           300:                        xfree(copy);
1.27      nicm      301:                        xfree(keylist);
1.43    ! nicm      302:                        return (NULL);
1.27      nicm      303:                }
                    304:                ARRAY_ADD(keylist, key);
                    305:        }
1.43    ! nicm      306:        xfree(copy);
1.27      nicm      307:
1.43    ! nicm      308:        return (options_set_data(oo, oe->name, keylist, xfree));
1.27      nicm      309: }
                    310:
1.43    ! nicm      311: /* Set a colour option. */
        !           312: struct options_entry *
        !           313: cmd_set_option_colour(struct cmd *self, struct cmd_ctx *ctx,
        !           314:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      315: {
1.43    ! nicm      316:        struct cmd_target_data  *data = self->data;
1.27      nicm      317:        int                      colour;
                    318:
1.43    ! nicm      319:        if ((colour = colour_fromstring(data->arg2)) == -1) {
        !           320:                ctx->error(ctx, "bad colour: %s", data->arg2);
        !           321:                return (NULL);
1.27      nicm      322:        }
                    323:
1.43    ! nicm      324:        return (options_set_number(oo, oe->name, colour));
1.27      nicm      325: }
                    326:
1.43    ! nicm      327: /* Set an attributes option. */
        !           328: struct options_entry *
        !           329: cmd_set_option_attributes(struct cmd *self, struct cmd_ctx *ctx,
        !           330:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      331: {
1.43    ! nicm      332:        struct cmd_target_data  *data = self->data;
1.27      nicm      333:        int                      attr;
                    334:
1.43    ! nicm      335:        if ((attr = attributes_fromstring(data->arg2)) == -1) {
        !           336:                ctx->error(ctx, "bad attributes: %s", data->arg2);
        !           337:                return (NULL);
1.27      nicm      338:        }
                    339:
1.43    ! nicm      340:        return (options_set_number(oo, oe->name, attr));
1.27      nicm      341: }
                    342:
1.43    ! nicm      343: /* Set a flag option. */
        !           344: struct options_entry *
        !           345: cmd_set_option_flag(struct cmd *self, struct cmd_ctx *ctx,
        !           346:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      347: {
1.43    ! nicm      348:        struct cmd_target_data  *data = self->data;
1.27      nicm      349:        int                      flag;
                    350:
1.43    ! nicm      351:        if (data->arg2 == NULL || *data->arg2 == '\0')
        !           352:                flag = !options_get_number(oo, oe->name);
1.27      nicm      353:        else {
1.43    ! nicm      354:                if ((data->arg2[0] == '1' && data->arg2[1] == '\0') ||
        !           355:                    strcasecmp(data->arg2, "on") == 0 ||
        !           356:                    strcasecmp(data->arg2, "yes") == 0)
1.27      nicm      357:                        flag = 1;
1.43    ! nicm      358:                else if ((data->arg2[0] == '0' && data->arg2[1] == '\0') ||
        !           359:                    strcasecmp(data->arg2, "off") == 0 ||
        !           360:                    strcasecmp(data->arg2, "no") == 0)
1.27      nicm      361:                        flag = 0;
                    362:                else {
1.43    ! nicm      363:                        ctx->error(ctx, "bad value: %s", data->arg2);
        !           364:                        return (NULL);
1.27      nicm      365:                }
                    366:        }
                    367:
1.43    ! nicm      368:        return (options_set_number(oo, oe->name, flag));
1.27      nicm      369: }
                    370:
1.43    ! nicm      371: /* Set a choice option. */
        !           372: struct options_entry *
        !           373: cmd_set_option_choice(struct cmd *self, struct cmd_ctx *ctx,
        !           374:     const struct options_table_entry *oe, struct options *oo)
1.27      nicm      375: {
1.43    ! nicm      376:        struct cmd_target_data  *data = self->data;
1.27      nicm      377:        const char             **choicep;
                    378:        int                      n, choice = -1;
                    379:
                    380:        n = 0;
1.43    ! nicm      381:        for (choicep = oe->choices; *choicep != NULL; choicep++) {
1.27      nicm      382:                n++;
1.43    ! nicm      383:                if (strncmp(*choicep, data->arg2, strlen(data->arg2)) != 0)
1.27      nicm      384:                        continue;
                    385:
                    386:                if (choice != -1) {
1.43    ! nicm      387:                        ctx->error(ctx, "ambiguous value: %s", data->arg2);
        !           388:                        return (NULL);
1.27      nicm      389:                }
                    390:                choice = n - 1;
                    391:        }
                    392:        if (choice == -1) {
1.43    ! nicm      393:                ctx->error(ctx, "unknown value: %s", data->arg2);
        !           394:                return (NULL);
1.27      nicm      395:        }
                    396:
1.43    ! nicm      397:        return (options_set_number(oo, oe->name, choice));
1.1       nicm      398: }