File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / tmux / options.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:22:44 2017 UTC (7 years ago) by misho
Branches: tmux, MAIN
CVS tags: v2_4p0, v2_4, HEAD
tmux 2.4

    1: /* $OpenBSD$ */
    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 <stdarg.h>
   23: #include <stdlib.h>
   24: #include <string.h>
   25: 
   26: #include "tmux.h"
   27: 
   28: /*
   29:  * Option handling; each option has a name, type and value and is stored in
   30:  * a red-black tree.
   31:  */
   32: 
   33: struct options_entry {
   34: 	struct options				 *owner;
   35: 
   36: 	const char				 *name;
   37: 	const struct options_table_entry	 *tableentry;
   38: 
   39: 	union {
   40: 		char				 *string;
   41: 		long long			  number;
   42: 		struct grid_cell		  style;
   43: 		struct {
   44: 			const char		**array;
   45: 			u_int			  arraysize;
   46: 		};
   47: 	};
   48: 
   49: 	RB_ENTRY(options_entry)			  entry;
   50: };
   51: 
   52: struct options {
   53: 	RB_HEAD(options_tree, options_entry)	 tree;
   54: 	struct options				*parent;
   55: };
   56: 
   57: static struct options_entry	*options_add(struct options *, const char *);
   58: 
   59: #define OPTIONS_ARRAY_LIMIT 1000
   60: 
   61: #define OPTIONS_IS_STRING(o)						\
   62: 	((o)->tableentry == NULL ||					\
   63: 	    (o)->tableentry->type == OPTIONS_TABLE_STRING)
   64: #define OPTIONS_IS_NUMBER(o) \
   65: 	((o)->tableentry != NULL &&					\
   66: 	    ((o)->tableentry->type == OPTIONS_TABLE_NUMBER ||		\
   67: 	    (o)->tableentry->type == OPTIONS_TABLE_KEY ||		\
   68: 	    (o)->tableentry->type == OPTIONS_TABLE_COLOUR ||		\
   69: 	    (o)->tableentry->type == OPTIONS_TABLE_ATTRIBUTES ||	\
   70: 	    (o)->tableentry->type == OPTIONS_TABLE_FLAG ||		\
   71: 	    (o)->tableentry->type == OPTIONS_TABLE_CHOICE))
   72: #define OPTIONS_IS_STYLE(o) \
   73: 	((o)->tableentry != NULL &&					\
   74: 	    (o)->tableentry->type == OPTIONS_TABLE_STYLE)
   75: #define OPTIONS_IS_ARRAY(o) \
   76: 	((o)->tableentry != NULL &&					\
   77: 	    (o)->tableentry->type == OPTIONS_TABLE_ARRAY)
   78: 
   79: static int	options_cmp(struct options_entry *, struct options_entry *);
   80: RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp);
   81: 
   82: static int
   83: options_cmp(struct options_entry *lhs, struct options_entry *rhs)
   84: {
   85: 	return (strcmp(lhs->name, rhs->name));
   86: }
   87: 
   88: static const struct options_table_entry *
   89: options_parent_table_entry(struct options *oo, const char *s)
   90: {
   91: 	struct options_entry	*o;
   92: 
   93: 	if (oo->parent == NULL)
   94: 		fatalx("no parent options for %s", s);
   95: 	o = options_get_only(oo->parent, s);
   96: 	if (o == NULL)
   97: 		fatalx("%s not in parent options", s);
   98: 	return (o->tableentry);
   99: }
  100: 
  101: struct options *
  102: options_create(struct options *parent)
  103: {
  104: 	struct options	*oo;
  105: 
  106: 	oo = xcalloc(1, sizeof *oo);
  107: 	RB_INIT(&oo->tree);
  108: 	oo->parent = parent;
  109: 	return (oo);
  110: }
  111: 
  112: void
  113: options_free(struct options *oo)
  114: {
  115: 	struct options_entry	*o, *tmp;
  116: 
  117: 	RB_FOREACH_SAFE (o, options_tree, &oo->tree, tmp)
  118: 		options_remove(o);
  119: 	free(oo);
  120: }
  121: 
  122: struct options_entry *
  123: options_first(struct options *oo)
  124: {
  125: 	return (RB_MIN(options_tree, &oo->tree));
  126: }
  127: 
  128: struct options_entry *
  129: options_next(struct options_entry *o)
  130: {
  131: 	return (RB_NEXT(options_tree, &oo->tree, o));
  132: }
  133: 
  134: struct options_entry *
  135: options_get_only(struct options *oo, const char *name)
  136: {
  137: 	struct options_entry	o;
  138: 
  139: 	o.name = name;
  140: 	return (RB_FIND(options_tree, &oo->tree, &o));
  141: }
  142: 
  143: struct options_entry *
  144: options_get(struct options *oo, const char *name)
  145: {
  146: 	struct options_entry	*o;
  147: 
  148: 	o = options_get_only(oo, name);
  149: 	while (o == NULL) {
  150: 		oo = oo->parent;
  151: 		if (oo == NULL)
  152: 			break;
  153: 		o = options_get_only(oo, name);
  154: 	}
  155: 	return (o);
  156: }
  157: 
  158: struct options_entry *
  159: options_empty(struct options *oo, const struct options_table_entry *oe)
  160: {
  161: 	struct options_entry	*o;
  162: 
  163: 	o = options_add(oo, oe->name);
  164: 	o->tableentry = oe;
  165: 
  166: 	return (o);
  167: }
  168: 
  169: struct options_entry *
  170: options_default(struct options *oo, const struct options_table_entry *oe)
  171: {
  172: 	struct options_entry	*o;
  173: 
  174: 	o = options_empty(oo, oe);
  175: 	if (oe->type == OPTIONS_TABLE_ARRAY)
  176: 		options_array_assign(o, oe->default_str);
  177: 	else if (oe->type == OPTIONS_TABLE_STRING)
  178: 		o->string = xstrdup(oe->default_str);
  179: 	else if (oe->type == OPTIONS_TABLE_STYLE) {
  180: 		memcpy(&o->style, &grid_default_cell, sizeof o->style);
  181: 		style_parse(&grid_default_cell, &o->style, oe->default_str);
  182: 	} else
  183: 		o->number = oe->default_num;
  184: 	return (o);
  185: }
  186: 
  187: static struct options_entry *
  188: options_add(struct options *oo, const char *name)
  189: {
  190: 	struct options_entry	*o;
  191: 
  192: 	o = options_get_only(oo, name);
  193: 	if (o != NULL)
  194: 		options_remove(o);
  195: 
  196: 	o = xcalloc(1, sizeof *o);
  197: 	o->owner = oo;
  198: 	o->name = xstrdup(name);
  199: 
  200: 	RB_INSERT(options_tree, &oo->tree, o);
  201: 	return (o);
  202: }
  203: 
  204: void
  205: options_remove(struct options_entry *o)
  206: {
  207: 	struct options	*oo = o->owner;
  208: 	u_int		 i;
  209: 
  210: 	if (OPTIONS_IS_STRING(o))
  211: 		free((void *)o->string);
  212: 	else if (OPTIONS_IS_ARRAY(o)) {
  213: 		for (i = 0; i < o->arraysize; i++)
  214: 			free((void *)o->array[i]);
  215: 		free(o->array);
  216: 	}
  217: 
  218: 	RB_REMOVE(options_tree, &oo->tree, o);
  219: 	free(o);
  220: }
  221: 
  222: const char *
  223: options_name(struct options_entry *o)
  224: {
  225: 	return (o->name);
  226: }
  227: 
  228: const struct options_table_entry *
  229: options_table_entry(struct options_entry *o)
  230: {
  231: 	return (o->tableentry);
  232: }
  233: 
  234: void
  235: options_array_clear(struct options_entry *o)
  236: {
  237: 	if (OPTIONS_IS_ARRAY(o))
  238: 		o->arraysize = 0;
  239: }
  240: 
  241: const char *
  242: options_array_get(struct options_entry *o, u_int idx)
  243: {
  244: 	if (!OPTIONS_IS_ARRAY(o))
  245: 		return (NULL);
  246: 	if (idx >= o->arraysize)
  247: 		return (NULL);
  248: 	return (o->array[idx]);
  249: }
  250: 
  251: int
  252: options_array_set(struct options_entry *o, u_int idx, const char *value,
  253:     int append)
  254: {
  255: 	char	*new;
  256: 	u_int	 i;
  257: 
  258: 	if (!OPTIONS_IS_ARRAY(o))
  259: 		return (-1);
  260: 
  261: 	if (idx >= OPTIONS_ARRAY_LIMIT)
  262: 		return (-1);
  263: 	if (idx >= o->arraysize) {
  264: 		o->array = xreallocarray(o->array, idx + 1, sizeof *o->array);
  265: 		for (i = o->arraysize; i < idx + 1; i++)
  266: 			o->array[i] = NULL;
  267: 		o->arraysize = idx + 1;
  268: 	}
  269: 
  270: 	new = NULL;
  271: 	if (value != NULL) {
  272: 		if (o->array[idx] != NULL && append)
  273: 			xasprintf(&new, "%s%s", o->array[idx], value);
  274: 		else
  275: 			new = xstrdup(value);
  276: 	}
  277: 
  278: 	free((void *)o->array[idx]);
  279: 	o->array[idx] = new;
  280: 	return (0);
  281: }
  282: 
  283: int
  284: options_array_size(struct options_entry *o, u_int *size)
  285: {
  286: 	if (!OPTIONS_IS_ARRAY(o))
  287: 		return (-1);
  288: 	if (size != NULL)
  289: 		*size = o->arraysize;
  290: 	return (0);
  291: }
  292: 
  293: void
  294: options_array_assign(struct options_entry *o, const char *s)
  295: {
  296: 	const char	*separator;
  297: 	char		*copy, *next, *string;
  298: 	u_int		 i;
  299: 
  300: 	separator = o->tableentry->separator;
  301: 	if (separator == NULL)
  302: 		separator = " ,";
  303: 
  304: 	copy = string = xstrdup(s);
  305: 	while ((next = strsep(&string, separator)) != NULL) {
  306: 		if (*next == '\0')
  307: 			continue;
  308: 		for (i = 0; i < OPTIONS_ARRAY_LIMIT; i++) {
  309: 			if (i >= o->arraysize || o->array[i] == NULL)
  310: 				break;
  311: 		}
  312: 		if (i == OPTIONS_ARRAY_LIMIT)
  313: 			break;
  314: 		options_array_set(o, i, next, 0);
  315: 	}
  316: 	free(copy);
  317: }
  318: 
  319: int
  320: options_isstring(struct options_entry *o)
  321: {
  322: 	if (o->tableentry == NULL)
  323: 		return (1);
  324: 	return (OPTIONS_IS_STRING(o) || OPTIONS_IS_ARRAY(o));
  325: }
  326: 
  327: const char *
  328: options_tostring(struct options_entry *o, int idx, int numeric)
  329: {
  330: 	static char	 s[1024];
  331: 	const char	*tmp;
  332: 
  333: 	if (OPTIONS_IS_ARRAY(o)) {
  334: 		if (idx == -1)
  335: 			return (NULL);
  336: 		if ((u_int)idx >= o->arraysize || o->array[idx] == NULL)
  337: 			return ("");
  338: 		return (o->array[idx]);
  339: 	}
  340: 	if (OPTIONS_IS_STYLE(o))
  341: 		return (style_tostring(&o->style));
  342: 	if (OPTIONS_IS_NUMBER(o)) {
  343: 		tmp = NULL;
  344: 		switch (o->tableentry->type) {
  345: 		case OPTIONS_TABLE_NUMBER:
  346: 			xsnprintf(s, sizeof s, "%lld", o->number);
  347: 			break;
  348: 		case OPTIONS_TABLE_KEY:
  349: 			tmp = key_string_lookup_key(o->number);
  350: 			break;
  351: 		case OPTIONS_TABLE_COLOUR:
  352: 			tmp = colour_tostring(o->number);
  353: 			break;
  354: 		case OPTIONS_TABLE_ATTRIBUTES:
  355: 			tmp = attributes_tostring(o->number);
  356: 			break;
  357: 		case OPTIONS_TABLE_FLAG:
  358: 			if (numeric)
  359: 				xsnprintf(s, sizeof s, "%lld", o->number);
  360: 			else
  361: 				tmp = (o->number ? "on" : "off");
  362: 			break;
  363: 		case OPTIONS_TABLE_CHOICE:
  364: 			tmp = o->tableentry->choices[o->number];
  365: 			break;
  366: 		case OPTIONS_TABLE_STRING:
  367: 		case OPTIONS_TABLE_STYLE:
  368: 		case OPTIONS_TABLE_ARRAY:
  369: 			break;
  370: 		}
  371: 		if (tmp != NULL)
  372: 			xsnprintf(s, sizeof s, "%s", tmp);
  373: 		return (s);
  374: 	}
  375: 	if (OPTIONS_IS_STRING(o))
  376: 		return (o->string);
  377: 	return (NULL);
  378: }
  379: 
  380: char *
  381: options_parse(const char *name, int *idx)
  382: {
  383: 	char	*copy, *cp, *end;
  384: 
  385: 	if (*name == '\0')
  386: 		return (NULL);
  387: 	copy = xstrdup(name);
  388: 	if ((cp = strchr(copy, '[')) == NULL) {
  389: 		*idx = -1;
  390: 		return (copy);
  391: 	}
  392: 	end = strchr(cp + 1, ']');
  393: 	if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) {
  394: 		free(copy);
  395: 		return (NULL);
  396: 	}
  397: 	if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) {
  398: 		free(copy);
  399: 		return (NULL);
  400: 	}
  401: 	*cp = '\0';
  402: 	return (copy);
  403: }
  404: 
  405: struct options_entry *
  406: options_parse_get(struct options *oo, const char *s, int *idx, int only)
  407: {
  408: 	struct options_entry	*o;
  409: 	char			*name;
  410: 
  411: 	name = options_parse(s, idx);
  412: 	if (name == NULL)
  413: 		return (NULL);
  414: 	if (only)
  415: 		o = options_get_only(oo, name);
  416: 	else
  417: 		o = options_get(oo, name);
  418: 	free(name);
  419: 	return (o);
  420: }
  421: 
  422: char *
  423: options_match(const char *s, int *idx, int* ambiguous)
  424: {
  425: 	const struct options_table_entry	*oe, *found;
  426: 	char					*name;
  427: 	size_t					 namelen;
  428: 
  429: 	name = options_parse(s, idx);
  430: 	if (name == NULL)
  431: 		return (NULL);
  432: 	namelen = strlen(name);
  433: 
  434: 	if (*name == '@') {
  435: 		*ambiguous = 0;
  436: 		return (xstrdup(name));
  437: 	}
  438: 
  439: 	found = NULL;
  440: 	for (oe = options_table; oe->name != NULL; oe++) {
  441: 		if (strcmp(oe->name, name) == 0) {
  442: 			found = oe;
  443: 			break;
  444: 		}
  445: 		if (strncmp(oe->name, name, namelen) == 0) {
  446: 			if (found != NULL) {
  447: 				*ambiguous = 1;
  448: 				free(name);
  449: 				return (NULL);
  450: 			}
  451: 			found = oe;
  452: 		}
  453: 	}
  454: 	free(name);
  455: 	if (found == NULL) {
  456: 		*ambiguous = 0;
  457: 		return (NULL);
  458: 	}
  459: 	return (xstrdup(found->name));
  460: }
  461: 
  462: struct options_entry *
  463: options_match_get(struct options *oo, const char *s, int *idx, int only,
  464:     int* ambiguous)
  465: {
  466: 	char			*name;
  467: 	struct options_entry	*o;
  468: 
  469: 	name = options_match(s, idx, ambiguous);
  470: 	if (name == NULL)
  471: 		return (NULL);
  472: 	*ambiguous = 0;
  473: 	if (only)
  474: 		o = options_get_only(oo, name);
  475: 	else
  476: 		o = options_get(oo, name);
  477: 	free(name);
  478: 	return (o);
  479: }
  480: 
  481: 
  482: const char *
  483: options_get_string(struct options *oo, const char *name)
  484: {
  485: 	struct options_entry	*o;
  486: 
  487: 	o = options_get(oo, name);
  488: 	if (o == NULL)
  489: 		fatalx("missing option %s", name);
  490: 	if (!OPTIONS_IS_STRING(o))
  491: 		fatalx("option %s is not a string", name);
  492: 	return (o->string);
  493: }
  494: 
  495: long long
  496: options_get_number(struct options *oo, const char *name)
  497: {
  498: 	struct options_entry	*o;
  499: 
  500: 	o = options_get(oo, name);
  501: 	if (o == NULL)
  502: 		fatalx("missing option %s", name);
  503: 	if (!OPTIONS_IS_NUMBER(o))
  504: 	    fatalx("option %s is not a number", name);
  505: 	return (o->number);
  506: }
  507: 
  508: const struct grid_cell *
  509: options_get_style(struct options *oo, const char *name)
  510: {
  511: 	struct options_entry	*o;
  512: 
  513: 	o = options_get(oo, name);
  514: 	if (o == NULL)
  515: 		fatalx("missing option %s", name);
  516: 	if (!OPTIONS_IS_STYLE(o))
  517: 		fatalx("option %s is not a style", name);
  518: 	return (&o->style);
  519: }
  520: 
  521: struct options_entry *
  522: options_set_string(struct options *oo, const char *name, int append,
  523:     const char *fmt, ...)
  524: {
  525: 	struct options_entry	*o;
  526: 	va_list			 ap;
  527: 	char			*s, *value;
  528: 
  529: 	va_start(ap, fmt);
  530: 	xvasprintf(&s, fmt, ap);
  531: 	va_end(ap);
  532: 
  533: 	o = options_get_only(oo, name);
  534: 	if (o != NULL && append && OPTIONS_IS_STRING(o)) {
  535: 		xasprintf(&value, "%s%s", o->string, s);
  536: 		free(s);
  537: 	} else
  538: 		value = s;
  539: 	if (o == NULL && *name == '@')
  540: 		o = options_add(oo, name);
  541: 	else if (o == NULL) {
  542: 		o = options_default(oo, options_parent_table_entry(oo, name));
  543: 		if (o == NULL)
  544: 			return (NULL);
  545: 	}
  546: 
  547: 	if (!OPTIONS_IS_STRING(o))
  548: 		fatalx("option %s is not a string", name);
  549: 	free(o->string);
  550: 	o->string = value;
  551: 	return (o);
  552: }
  553: 
  554: struct options_entry *
  555: options_set_number(struct options *oo, const char *name, long long value)
  556: {
  557: 	struct options_entry	*o;
  558: 
  559: 	if (*name == '@')
  560: 		fatalx("user option %s must be a string", name);
  561: 
  562: 	o = options_get_only(oo, name);
  563: 	if (o == NULL) {
  564: 		o = options_default(oo, options_parent_table_entry(oo, name));
  565: 		if (o == NULL)
  566: 			return (NULL);
  567: 	}
  568: 
  569: 	if (!OPTIONS_IS_NUMBER(o))
  570: 		fatalx("option %s is not a number", name);
  571: 	o->number = value;
  572: 	return (o);
  573: }
  574: 
  575: struct options_entry *
  576: options_set_style(struct options *oo, const char *name, int append,
  577:     const char *value)
  578: {
  579: 	struct options_entry	*o;
  580: 	struct grid_cell	 gc;
  581: 
  582: 	if (*name == '@')
  583: 		fatalx("user option %s must be a string", name);
  584: 
  585: 	o = options_get_only(oo, name);
  586: 	if (o != NULL && append && OPTIONS_IS_STYLE(o))
  587: 		memcpy(&gc, &o->style, sizeof gc);
  588: 	else
  589: 		memcpy(&gc, &grid_default_cell, sizeof gc);
  590: 	if (style_parse(&grid_default_cell, &gc, value) == -1)
  591: 		return (NULL);
  592: 	if (o == NULL) {
  593: 		o = options_default(oo, options_parent_table_entry(oo, name));
  594: 		if (o == NULL)
  595: 			return (NULL);
  596: 	}
  597: 
  598: 	if (!OPTIONS_IS_STYLE(o))
  599: 		fatalx("option %s is not a style", name);
  600: 	memcpy(&o->style, &gc, sizeof o->style);
  601: 	return (o);
  602: }
  603: 
  604: enum options_table_scope
  605: options_scope_from_flags(struct args *args, int window,
  606:     struct cmd_find_state *fs, struct options **oo, char **cause)
  607: {
  608: 	struct session	*s = fs->s;
  609: 	struct winlink	*wl = fs->wl;
  610: 	const char	*target= args_get(args, 't');
  611: 
  612: 	if (args_has(args, 's')) {
  613: 		*oo = global_options;
  614: 		return (OPTIONS_TABLE_SERVER);
  615: 	}
  616: 
  617: 	if (window || args_has(args, 'w')) {
  618: 		if (args_has(args, 'g')) {
  619: 			*oo = global_w_options;
  620: 			return (OPTIONS_TABLE_WINDOW);
  621: 		}
  622: 		if (wl == NULL) {
  623: 			if (target != NULL)
  624: 				xasprintf(cause, "no such window: %s", target);
  625: 			else
  626: 				xasprintf(cause, "no current window");
  627: 			return (OPTIONS_TABLE_NONE);
  628: 		}
  629: 		*oo = wl->window->options;
  630: 		return (OPTIONS_TABLE_WINDOW);
  631: 	} else {
  632: 		if (args_has(args, 'g')) {
  633: 			*oo = global_s_options;
  634: 			return (OPTIONS_TABLE_SESSION);
  635: 		}
  636: 		if (s == NULL) {
  637: 			if (target != NULL)
  638: 				xasprintf(cause, "no such session: %s", target);
  639: 			else
  640: 				xasprintf(cause, "no current session");
  641: 			return (OPTIONS_TABLE_NONE);
  642: 		}
  643: 		*oo = s->options;
  644: 		return (OPTIONS_TABLE_SESSION);
  645: 	}
  646: }
  647: 
  648: void
  649: options_style_update_new(struct options *oo, struct options_entry *o)
  650: {
  651: 	const char		*newname = o->tableentry->style;
  652: 	struct options_entry	*new;
  653: 
  654: 	if (newname == NULL)
  655: 		return;
  656: 	new = options_get_only(oo, newname);
  657: 	if (new == NULL)
  658: 		new = options_set_style(oo, newname, 0, "default");
  659: 
  660: 	if (strstr(o->name, "-bg") != NULL)
  661: 		new->style.bg = o->number;
  662: 	else if (strstr(o->name, "-fg") != NULL)
  663: 		new->style.fg = o->number;
  664: 	else if (strstr(o->name, "-attr") != NULL)
  665: 		new->style.attr = o->number;
  666: }
  667: 
  668: void
  669: options_style_update_old(struct options *oo, struct options_entry *o)
  670: {
  671: 	char	newname[128];
  672: 	int	size;
  673: 
  674: 	size = strrchr(o->name, '-') - o->name;
  675: 
  676: 	xsnprintf(newname, sizeof newname, "%.*s-bg", size, o->name);
  677: 	if (options_get(oo, newname) != NULL)
  678: 		options_set_number(oo, newname, o->style.bg);
  679: 
  680: 	xsnprintf(newname, sizeof newname, "%.*s-fg", size, o->name);
  681: 	if (options_get(oo, newname) != NULL)
  682: 		options_set_number(oo, newname, o->style.fg);
  683: 
  684: 	xsnprintf(newname, sizeof newname, "%.*s-attr", size, o->name);
  685: 	if (options_get(oo, newname) != NULL)
  686: 		options_set_number(oo, newname, o->style.attr);
  687: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>