1*0a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek *
6eda6f593SDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek *
10eda6f593SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek */
18eda6f593SDavid van Moolenbroek
19eda6f593SDavid van Moolenbroek #include <sys/types.h>
20eda6f593SDavid van Moolenbroek
21eda6f593SDavid van Moolenbroek #include <stdarg.h>
22*0a6a1f1dSLionel Sambuc #include <stdlib.h>
23eda6f593SDavid van Moolenbroek #include <string.h>
24eda6f593SDavid van Moolenbroek
25eda6f593SDavid van Moolenbroek #include "tmux.h"
26eda6f593SDavid van Moolenbroek
27eda6f593SDavid van Moolenbroek /*
28eda6f593SDavid van Moolenbroek * Option handling; each option has a name, type and value and is stored in
29*0a6a1f1dSLionel Sambuc * a red-black tree.
30eda6f593SDavid van Moolenbroek */
31eda6f593SDavid van Moolenbroek
32*0a6a1f1dSLionel Sambuc RB_GENERATE(options_tree, options_entry, entry, options_cmp);
33eda6f593SDavid van Moolenbroek
34eda6f593SDavid van Moolenbroek int
options_cmp(struct options_entry * o1,struct options_entry * o2)35eda6f593SDavid van Moolenbroek options_cmp(struct options_entry *o1, struct options_entry *o2)
36eda6f593SDavid van Moolenbroek {
37eda6f593SDavid van Moolenbroek return (strcmp(o1->name, o2->name));
38eda6f593SDavid van Moolenbroek }
39eda6f593SDavid van Moolenbroek
40eda6f593SDavid van Moolenbroek void
options_init(struct options * oo,struct options * parent)41eda6f593SDavid van Moolenbroek options_init(struct options *oo, struct options *parent)
42eda6f593SDavid van Moolenbroek {
43*0a6a1f1dSLionel Sambuc RB_INIT(&oo->tree);
44eda6f593SDavid van Moolenbroek oo->parent = parent;
45eda6f593SDavid van Moolenbroek }
46eda6f593SDavid van Moolenbroek
47eda6f593SDavid van Moolenbroek void
options_free(struct options * oo)48eda6f593SDavid van Moolenbroek options_free(struct options *oo)
49eda6f593SDavid van Moolenbroek {
50eda6f593SDavid van Moolenbroek struct options_entry *o;
51eda6f593SDavid van Moolenbroek
52*0a6a1f1dSLionel Sambuc while (!RB_EMPTY(&oo->tree)) {
53*0a6a1f1dSLionel Sambuc o = RB_ROOT(&oo->tree);
54*0a6a1f1dSLionel Sambuc RB_REMOVE(options_tree, &oo->tree, o);
55*0a6a1f1dSLionel Sambuc free(o->name);
56eda6f593SDavid van Moolenbroek if (o->type == OPTIONS_STRING)
57*0a6a1f1dSLionel Sambuc free(o->str);
58*0a6a1f1dSLionel Sambuc free(o);
59eda6f593SDavid van Moolenbroek }
60eda6f593SDavid van Moolenbroek }
61eda6f593SDavid van Moolenbroek
62eda6f593SDavid van Moolenbroek struct options_entry *
options_find1(struct options * oo,const char * name)63eda6f593SDavid van Moolenbroek options_find1(struct options *oo, const char *name)
64eda6f593SDavid van Moolenbroek {
65eda6f593SDavid van Moolenbroek struct options_entry p;
66eda6f593SDavid van Moolenbroek
67eda6f593SDavid van Moolenbroek p.name = __UNCONST(name);
68*0a6a1f1dSLionel Sambuc return (RB_FIND(options_tree, &oo->tree, &p));
69eda6f593SDavid van Moolenbroek }
70eda6f593SDavid van Moolenbroek
71eda6f593SDavid van Moolenbroek struct options_entry *
options_find(struct options * oo,const char * name)72eda6f593SDavid van Moolenbroek options_find(struct options *oo, const char *name)
73eda6f593SDavid van Moolenbroek {
74eda6f593SDavid van Moolenbroek struct options_entry *o, p;
75eda6f593SDavid van Moolenbroek
76eda6f593SDavid van Moolenbroek p.name = __UNCONST(name);
77*0a6a1f1dSLionel Sambuc o = RB_FIND(options_tree, &oo->tree, &p);
78eda6f593SDavid van Moolenbroek while (o == NULL) {
79eda6f593SDavid van Moolenbroek oo = oo->parent;
80eda6f593SDavid van Moolenbroek if (oo == NULL)
81eda6f593SDavid van Moolenbroek break;
82*0a6a1f1dSLionel Sambuc o = RB_FIND(options_tree, &oo->tree, &p);
83eda6f593SDavid van Moolenbroek }
84eda6f593SDavid van Moolenbroek return (o);
85eda6f593SDavid van Moolenbroek }
86eda6f593SDavid van Moolenbroek
87eda6f593SDavid van Moolenbroek void
options_remove(struct options * oo,const char * name)88eda6f593SDavid van Moolenbroek options_remove(struct options *oo, const char *name)
89eda6f593SDavid van Moolenbroek {
90eda6f593SDavid van Moolenbroek struct options_entry *o;
91eda6f593SDavid van Moolenbroek
92eda6f593SDavid van Moolenbroek if ((o = options_find1(oo, name)) == NULL)
93eda6f593SDavid van Moolenbroek return;
94eda6f593SDavid van Moolenbroek
95*0a6a1f1dSLionel Sambuc RB_REMOVE(options_tree, &oo->tree, o);
96*0a6a1f1dSLionel Sambuc free(o->name);
97eda6f593SDavid van Moolenbroek if (o->type == OPTIONS_STRING)
98*0a6a1f1dSLionel Sambuc free(o->str);
99*0a6a1f1dSLionel Sambuc free(o);
100eda6f593SDavid van Moolenbroek }
101eda6f593SDavid van Moolenbroek
102eda6f593SDavid van Moolenbroek struct options_entry *printflike3
options_set_string(struct options * oo,const char * name,const char * fmt,...)103eda6f593SDavid van Moolenbroek options_set_string(struct options *oo, const char *name, const char *fmt, ...)
104eda6f593SDavid van Moolenbroek {
105eda6f593SDavid van Moolenbroek struct options_entry *o;
106eda6f593SDavid van Moolenbroek va_list ap;
107eda6f593SDavid van Moolenbroek
108eda6f593SDavid van Moolenbroek if ((o = options_find1(oo, name)) == NULL) {
109eda6f593SDavid van Moolenbroek o = xmalloc(sizeof *o);
110eda6f593SDavid van Moolenbroek o->name = xstrdup(name);
111*0a6a1f1dSLionel Sambuc RB_INSERT(options_tree, &oo->tree, o);
112*0a6a1f1dSLionel Sambuc memcpy(&o->style, &grid_default_cell, sizeof o->style);
113eda6f593SDavid van Moolenbroek } else if (o->type == OPTIONS_STRING)
114*0a6a1f1dSLionel Sambuc free(o->str);
115eda6f593SDavid van Moolenbroek
116eda6f593SDavid van Moolenbroek va_start(ap, fmt);
117eda6f593SDavid van Moolenbroek o->type = OPTIONS_STRING;
118eda6f593SDavid van Moolenbroek xvasprintf(&o->str, fmt, ap);
119eda6f593SDavid van Moolenbroek va_end(ap);
120eda6f593SDavid van Moolenbroek return (o);
121eda6f593SDavid van Moolenbroek }
122eda6f593SDavid van Moolenbroek
123eda6f593SDavid van Moolenbroek char *
options_get_string(struct options * oo,const char * name)124eda6f593SDavid van Moolenbroek options_get_string(struct options *oo, const char *name)
125eda6f593SDavid van Moolenbroek {
126eda6f593SDavid van Moolenbroek struct options_entry *o;
127eda6f593SDavid van Moolenbroek
128eda6f593SDavid van Moolenbroek if ((o = options_find(oo, name)) == NULL)
129eda6f593SDavid van Moolenbroek fatalx("missing option");
130eda6f593SDavid van Moolenbroek if (o->type != OPTIONS_STRING)
131eda6f593SDavid van Moolenbroek fatalx("option not a string");
132eda6f593SDavid van Moolenbroek return (o->str);
133eda6f593SDavid van Moolenbroek }
134eda6f593SDavid van Moolenbroek
135eda6f593SDavid van Moolenbroek struct options_entry *
options_set_number(struct options * oo,const char * name,long long value)136eda6f593SDavid van Moolenbroek options_set_number(struct options *oo, const char *name, long long value)
137eda6f593SDavid van Moolenbroek {
138eda6f593SDavid van Moolenbroek struct options_entry *o;
139eda6f593SDavid van Moolenbroek
140eda6f593SDavid van Moolenbroek if ((o = options_find1(oo, name)) == NULL) {
141eda6f593SDavid van Moolenbroek o = xmalloc(sizeof *o);
142eda6f593SDavid van Moolenbroek o->name = xstrdup(name);
143*0a6a1f1dSLionel Sambuc RB_INSERT(options_tree, &oo->tree, o);
144*0a6a1f1dSLionel Sambuc memcpy(&o->style, &grid_default_cell, sizeof o->style);
145eda6f593SDavid van Moolenbroek } else if (o->type == OPTIONS_STRING)
146*0a6a1f1dSLionel Sambuc free(o->str);
147eda6f593SDavid van Moolenbroek
148eda6f593SDavid van Moolenbroek o->type = OPTIONS_NUMBER;
149eda6f593SDavid van Moolenbroek o->num = value;
150eda6f593SDavid van Moolenbroek return (o);
151eda6f593SDavid van Moolenbroek }
152eda6f593SDavid van Moolenbroek
153eda6f593SDavid van Moolenbroek long long
options_get_number(struct options * oo,const char * name)154eda6f593SDavid van Moolenbroek options_get_number(struct options *oo, const char *name)
155eda6f593SDavid van Moolenbroek {
156eda6f593SDavid van Moolenbroek struct options_entry *o;
157eda6f593SDavid van Moolenbroek
158eda6f593SDavid van Moolenbroek if ((o = options_find(oo, name)) == NULL)
159eda6f593SDavid van Moolenbroek fatalx("missing option");
160eda6f593SDavid van Moolenbroek if (o->type != OPTIONS_NUMBER)
161eda6f593SDavid van Moolenbroek fatalx("option not a number");
162eda6f593SDavid van Moolenbroek return (o->num);
163eda6f593SDavid van Moolenbroek }
164eda6f593SDavid van Moolenbroek
165eda6f593SDavid van Moolenbroek struct options_entry *
options_set_style(struct options * oo,const char * name,const char * value,int append)166*0a6a1f1dSLionel Sambuc options_set_style(struct options *oo, const char *name, const char *value,
167*0a6a1f1dSLionel Sambuc int append)
168eda6f593SDavid van Moolenbroek {
169eda6f593SDavid van Moolenbroek struct options_entry *o;
170eda6f593SDavid van Moolenbroek
171eda6f593SDavid van Moolenbroek if ((o = options_find1(oo, name)) == NULL) {
172eda6f593SDavid van Moolenbroek o = xmalloc(sizeof *o);
173eda6f593SDavid van Moolenbroek o->name = xstrdup(name);
174*0a6a1f1dSLionel Sambuc RB_INSERT(options_tree, &oo->tree, o);
175eda6f593SDavid van Moolenbroek } else if (o->type == OPTIONS_STRING)
176*0a6a1f1dSLionel Sambuc free(o->str);
177eda6f593SDavid van Moolenbroek
178*0a6a1f1dSLionel Sambuc if (!append)
179*0a6a1f1dSLionel Sambuc memcpy(&o->style, &grid_default_cell, sizeof o->style);
180*0a6a1f1dSLionel Sambuc
181*0a6a1f1dSLionel Sambuc o->type = OPTIONS_STYLE;
182*0a6a1f1dSLionel Sambuc if (style_parse(&grid_default_cell, &o->style, value) == -1)
183*0a6a1f1dSLionel Sambuc return (NULL);
184eda6f593SDavid van Moolenbroek return (o);
185eda6f593SDavid van Moolenbroek }
186eda6f593SDavid van Moolenbroek
187*0a6a1f1dSLionel Sambuc struct grid_cell *
options_get_style(struct options * oo,const char * name)188*0a6a1f1dSLionel Sambuc options_get_style(struct options *oo, const char *name)
189eda6f593SDavid van Moolenbroek {
190eda6f593SDavid van Moolenbroek struct options_entry *o;
191eda6f593SDavid van Moolenbroek
192eda6f593SDavid van Moolenbroek if ((o = options_find(oo, name)) == NULL)
193eda6f593SDavid van Moolenbroek fatalx("missing option");
194*0a6a1f1dSLionel Sambuc if (o->type != OPTIONS_STYLE)
195*0a6a1f1dSLionel Sambuc fatalx("option not a style");
196*0a6a1f1dSLionel Sambuc return (&o->style);
197eda6f593SDavid van Moolenbroek }
198