1 /* Id */
2
3 /*
4 * Copyright (c) 2008 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 <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "tmux.h"
26
27 /*
28 * Option handling; each option has a name, type and value and is stored in
29 * a red-black tree.
30 */
31
32 RB_GENERATE(options_tree, options_entry, entry, options_cmp);
33
34 int
options_cmp(struct options_entry * o1,struct options_entry * o2)35 options_cmp(struct options_entry *o1, struct options_entry *o2)
36 {
37 return (strcmp(o1->name, o2->name));
38 }
39
40 void
options_init(struct options * oo,struct options * parent)41 options_init(struct options *oo, struct options *parent)
42 {
43 RB_INIT(&oo->tree);
44 oo->parent = parent;
45 }
46
47 void
options_free(struct options * oo)48 options_free(struct options *oo)
49 {
50 struct options_entry *o;
51
52 while (!RB_EMPTY(&oo->tree)) {
53 o = RB_ROOT(&oo->tree);
54 RB_REMOVE(options_tree, &oo->tree, o);
55 free(o->name);
56 if (o->type == OPTIONS_STRING)
57 free(o->str);
58 free(o);
59 }
60 }
61
62 struct options_entry *
options_find1(struct options * oo,const char * name)63 options_find1(struct options *oo, const char *name)
64 {
65 struct options_entry p;
66
67 p.name = __UNCONST(name);
68 return (RB_FIND(options_tree, &oo->tree, &p));
69 }
70
71 struct options_entry *
options_find(struct options * oo,const char * name)72 options_find(struct options *oo, const char *name)
73 {
74 struct options_entry *o, p;
75
76 p.name = __UNCONST(name);
77 o = RB_FIND(options_tree, &oo->tree, &p);
78 while (o == NULL) {
79 oo = oo->parent;
80 if (oo == NULL)
81 break;
82 o = RB_FIND(options_tree, &oo->tree, &p);
83 }
84 return (o);
85 }
86
87 void
options_remove(struct options * oo,const char * name)88 options_remove(struct options *oo, const char *name)
89 {
90 struct options_entry *o;
91
92 if ((o = options_find1(oo, name)) == NULL)
93 return;
94
95 RB_REMOVE(options_tree, &oo->tree, o);
96 free(o->name);
97 if (o->type == OPTIONS_STRING)
98 free(o->str);
99 free(o);
100 }
101
102 struct options_entry *printflike3
options_set_string(struct options * oo,const char * name,const char * fmt,...)103 options_set_string(struct options *oo, const char *name, const char *fmt, ...)
104 {
105 struct options_entry *o;
106 va_list ap;
107
108 if ((o = options_find1(oo, name)) == NULL) {
109 o = xmalloc(sizeof *o);
110 o->name = xstrdup(name);
111 RB_INSERT(options_tree, &oo->tree, o);
112 memcpy(&o->style, &grid_default_cell, sizeof o->style);
113 } else if (o->type == OPTIONS_STRING)
114 free(o->str);
115
116 va_start(ap, fmt);
117 o->type = OPTIONS_STRING;
118 xvasprintf(&o->str, fmt, ap);
119 va_end(ap);
120 return (o);
121 }
122
123 char *
options_get_string(struct options * oo,const char * name)124 options_get_string(struct options *oo, const char *name)
125 {
126 struct options_entry *o;
127
128 if ((o = options_find(oo, name)) == NULL)
129 fatalx("missing option");
130 if (o->type != OPTIONS_STRING)
131 fatalx("option not a string");
132 return (o->str);
133 }
134
135 struct options_entry *
options_set_number(struct options * oo,const char * name,long long value)136 options_set_number(struct options *oo, const char *name, long long value)
137 {
138 struct options_entry *o;
139
140 if ((o = options_find1(oo, name)) == NULL) {
141 o = xmalloc(sizeof *o);
142 o->name = xstrdup(name);
143 RB_INSERT(options_tree, &oo->tree, o);
144 memcpy(&o->style, &grid_default_cell, sizeof o->style);
145 } else if (o->type == OPTIONS_STRING)
146 free(o->str);
147
148 o->type = OPTIONS_NUMBER;
149 o->num = value;
150 return (o);
151 }
152
153 long long
options_get_number(struct options * oo,const char * name)154 options_get_number(struct options *oo, const char *name)
155 {
156 struct options_entry *o;
157
158 if ((o = options_find(oo, name)) == NULL)
159 fatalx("missing option");
160 if (o->type != OPTIONS_NUMBER)
161 fatalx("option not a number");
162 return (o->num);
163 }
164
165 struct options_entry *
options_set_style(struct options * oo,const char * name,const char * value,int append)166 options_set_style(struct options *oo, const char *name, const char *value,
167 int append)
168 {
169 struct options_entry *o;
170
171 if ((o = options_find1(oo, name)) == NULL) {
172 o = xmalloc(sizeof *o);
173 o->name = xstrdup(name);
174 RB_INSERT(options_tree, &oo->tree, o);
175 } else if (o->type == OPTIONS_STRING)
176 free(o->str);
177
178 if (!append)
179 memcpy(&o->style, &grid_default_cell, sizeof o->style);
180
181 o->type = OPTIONS_STYLE;
182 if (style_parse(&grid_default_cell, &o->style, value) == -1)
183 return (NULL);
184 return (o);
185 }
186
187 struct grid_cell *
options_get_style(struct options * oo,const char * name)188 options_get_style(struct options *oo, const char *name)
189 {
190 struct options_entry *o;
191
192 if ((o = options_find(oo, name)) == NULL)
193 fatalx("missing option");
194 if (o->type != OPTIONS_STYLE)
195 fatalx("option not a style");
196 return (&o->style);
197 }
198