Line | Count | Source |
1 | | /* $OpenBSD: style.c,v 1.47 2026/06/29 17:08:52 nicm Exp $ */ |
2 | | |
3 | | /* |
4 | | * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> |
5 | | * Copyright (c) 2014 Tiago Cunha <tcunha@users.sourceforge.net> |
6 | | * |
7 | | * Permission to use, copy, modify, and distribute this software for any |
8 | | * purpose with or without fee is hereby granted, provided that the above |
9 | | * copyright notice and this permission notice appear in all copies. |
10 | | * |
11 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | | * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER |
16 | | * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
17 | | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | | */ |
19 | | |
20 | | #include <sys/types.h> |
21 | | |
22 | | #include <ctype.h> |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | |
26 | | #include "tmux.h" |
27 | | |
28 | | /* Mask for bits not included in style. */ |
29 | | #define STYLE_ATTR_MASK (~0) |
30 | | |
31 | | /* Default style. */ |
32 | | static struct style style_default = { |
33 | | { { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0 }, |
34 | | 0, |
35 | | 0, |
36 | | |
37 | | 8, |
38 | | STYLE_ALIGN_DEFAULT, |
39 | | STYLE_LIST_OFF, |
40 | | |
41 | | STYLE_RANGE_NONE, 0, "", |
42 | | |
43 | | STYLE_WIDTH_DEFAULT, 0, STYLE_PAD_DEFAULT, |
44 | | |
45 | | STYLE_DEFAULT_BASE, |
46 | | |
47 | | 0 |
48 | | }; |
49 | | |
50 | | /* |
51 | | * Global hyperlink set holding the URIs for #[link=...] styles, so a style |
52 | | * only needs to store a small ID rather than the URI itself. |
53 | | */ |
54 | | static struct hyperlinks *style_hyperlinks; |
55 | | |
56 | | /* Set range string. */ |
57 | | static void |
58 | | style_set_range_string(struct style *sy, const char *s) |
59 | 0 | { |
60 | 0 | strlcpy(sy->range_string, s, sizeof sy->range_string); |
61 | 0 | } |
62 | | |
63 | | /* |
64 | | * Parse an embedded style of the form "fg=colour,bg=colour,bright,...". Note |
65 | | * that this adds onto the given style, so it must have been initialized |
66 | | * already. |
67 | | */ |
68 | | int |
69 | | style_parse(struct style *sy, const struct grid_cell *base, const char *in) |
70 | 1.53k | { |
71 | 1.53k | struct style saved; |
72 | 1.53k | const char delimiters[] = " ,\n", *errstr; |
73 | 1.53k | char tmp[256], *found; |
74 | 1.53k | int value; |
75 | 1.53k | size_t end; |
76 | 1.53k | u_int n; |
77 | | |
78 | 1.53k | if (*in == '\0') |
79 | 64 | return (0); |
80 | 1.46k | style_copy(&saved, sy); |
81 | | |
82 | 1.46k | log_debug("%s: %s", __func__, in); |
83 | 1.59k | do { |
84 | 2.33k | while (*in != '\0' && strchr(delimiters, *in) != NULL) |
85 | 742 | in++; |
86 | 1.59k | if (*in == '\0') |
87 | 0 | break; |
88 | | |
89 | 1.59k | end = strcspn(in, delimiters); |
90 | 1.59k | if (end > (sizeof tmp) - 1) |
91 | 0 | goto error; |
92 | 1.59k | memcpy(tmp, in, end); |
93 | 1.59k | tmp[end] = '\0'; |
94 | | |
95 | 1.59k | log_debug("%s: %s", __func__, tmp); |
96 | 1.59k | if (strcasecmp(tmp, "default") == 0) { |
97 | 0 | sy->gc.fg = base->fg; |
98 | 0 | sy->gc.bg = base->bg; |
99 | 0 | sy->gc.us = base->us; |
100 | 0 | sy->gc.attr = base->attr; |
101 | 0 | sy->gc.flags = base->flags; |
102 | 0 | sy->link = 0; |
103 | 1.59k | } else if (strcasecmp(tmp, "ignore") == 0) |
104 | 0 | sy->ignore = 1; |
105 | 1.59k | else if (strcasecmp(tmp, "noignore") == 0) |
106 | 0 | sy->ignore = 0; |
107 | 1.59k | else if (strcasecmp(tmp, "push-default") == 0) |
108 | 0 | sy->default_type = STYLE_DEFAULT_PUSH; |
109 | 1.59k | else if (strcasecmp(tmp, "pop-default") == 0) |
110 | 0 | sy->default_type = STYLE_DEFAULT_POP; |
111 | 1.59k | else if (strcasecmp(tmp, "set-default") == 0) |
112 | 0 | sy->default_type = STYLE_DEFAULT_SET; |
113 | 1.59k | else if (strcasecmp(tmp, "nolist") == 0) |
114 | 0 | sy->list = STYLE_LIST_OFF; |
115 | 1.59k | else if (strncasecmp(tmp, "list=", 5) == 0) { |
116 | 0 | if (strcasecmp(tmp + 5, "on") == 0) |
117 | 0 | sy->list = STYLE_LIST_ON; |
118 | 0 | else if (strcasecmp(tmp + 5, "focus") == 0) |
119 | 0 | sy->list = STYLE_LIST_FOCUS; |
120 | 0 | else if (strcasecmp(tmp + 5, "left-marker") == 0) |
121 | 0 | sy->list = STYLE_LIST_LEFT_MARKER; |
122 | 0 | else if (strcasecmp(tmp + 5, "right-marker") == 0) |
123 | 0 | sy->list = STYLE_LIST_RIGHT_MARKER; |
124 | 0 | else |
125 | 0 | goto error; |
126 | 1.59k | } else if (strcasecmp(tmp, "norange") == 0) { |
127 | 0 | sy->range_type = style_default.range_type; |
128 | 0 | sy->range_argument = style_default.range_type; |
129 | 0 | strlcpy(sy->range_string, style_default.range_string, |
130 | 0 | sizeof sy->range_string); |
131 | 1.59k | } else if (end > 6 && strncasecmp(tmp, "range=", 6) == 0) { |
132 | 406 | found = strchr(tmp + 6, '|'); |
133 | 406 | if (found != NULL) { |
134 | 22 | *found++ = '\0'; |
135 | 22 | if (*found == '\0') |
136 | 16 | goto error; |
137 | 22 | } |
138 | 390 | if (strcasecmp(tmp + 6, "left") == 0) { |
139 | 0 | if (found != NULL) |
140 | 0 | goto error; |
141 | 0 | sy->range_type = STYLE_RANGE_LEFT; |
142 | 0 | sy->range_argument = 0; |
143 | 0 | style_set_range_string(sy, ""); |
144 | 390 | } else if (strcasecmp(tmp + 6, "right") == 0) { |
145 | 0 | if (found != NULL) |
146 | 0 | goto error; |
147 | 0 | sy->range_type = STYLE_RANGE_RIGHT; |
148 | 0 | sy->range_argument = 0; |
149 | 0 | style_set_range_string(sy, ""); |
150 | 390 | } else if (strcasecmp(tmp + 6, "control") == 0) { |
151 | 0 | if (found == NULL) |
152 | 0 | goto error; |
153 | 0 | n = strtonum(found, 0, 9, &errstr); |
154 | 0 | if (errstr != NULL) |
155 | 0 | goto error; |
156 | 0 | sy->range_type = STYLE_RANGE_CONTROL; |
157 | 0 | sy->range_argument = n; |
158 | 0 | style_set_range_string(sy, ""); |
159 | 390 | } else if (strcasecmp(tmp + 6, "pane") == 0) { |
160 | 390 | if (found == NULL) |
161 | 384 | goto error; |
162 | 6 | if (*found != '%' || found[1] == '\0') |
163 | 6 | goto error; |
164 | 0 | n = strtonum(found + 1, 0, UINT_MAX, &errstr); |
165 | 0 | if (errstr != NULL) |
166 | 0 | goto error; |
167 | 0 | sy->range_type = STYLE_RANGE_PANE; |
168 | 0 | sy->range_argument = n; |
169 | 0 | style_set_range_string(sy, ""); |
170 | 0 | } else if (strcasecmp(tmp + 6, "window") == 0) { |
171 | 0 | if (found == NULL) |
172 | 0 | goto error; |
173 | 0 | n = strtonum(found, 0, UINT_MAX, &errstr); |
174 | 0 | if (errstr != NULL) |
175 | 0 | goto error; |
176 | 0 | sy->range_type = STYLE_RANGE_WINDOW; |
177 | 0 | sy->range_argument = n; |
178 | 0 | style_set_range_string(sy, ""); |
179 | 0 | } else if (strcasecmp(tmp + 6, "session") == 0) { |
180 | 0 | if (found == NULL) |
181 | 0 | goto error; |
182 | 0 | if (*found != '$' || found[1] == '\0') |
183 | 0 | goto error; |
184 | 0 | n = strtonum(found + 1, 0, UINT_MAX, &errstr); |
185 | 0 | if (errstr != NULL) |
186 | 0 | goto error; |
187 | 0 | sy->range_type = STYLE_RANGE_SESSION; |
188 | 0 | sy->range_argument = n; |
189 | 0 | style_set_range_string(sy, ""); |
190 | 0 | } else if (strcasecmp(tmp + 6, "user") == 0) { |
191 | 0 | if (found == NULL) |
192 | 0 | goto error; |
193 | 0 | sy->range_type = STYLE_RANGE_USER; |
194 | 0 | sy->range_argument = 0; |
195 | 0 | style_set_range_string(sy, found); |
196 | 0 | } |
197 | 1.19k | } else if (strcasecmp(tmp, "noalign") == 0) |
198 | 0 | sy->align = style_default.align; |
199 | 1.19k | else if (end > 6 && strncasecmp(tmp, "align=", 6) == 0) { |
200 | 0 | if (strcasecmp(tmp + 6, "left") == 0) |
201 | 0 | sy->align = STYLE_ALIGN_LEFT; |
202 | 0 | else if (strcasecmp(tmp + 6, "centre") == 0) |
203 | 0 | sy->align = STYLE_ALIGN_CENTRE; |
204 | 0 | else if (strcasecmp(tmp + 6, "right") == 0) |
205 | 0 | sy->align = STYLE_ALIGN_RIGHT; |
206 | 0 | else if (strcasecmp(tmp + 6, "absolute-centre") == 0) |
207 | 0 | sy->align = STYLE_ALIGN_ABSOLUTE_CENTRE; |
208 | 0 | else |
209 | 0 | goto error; |
210 | 1.19k | } else if (end > 5 && strncasecmp(tmp, "fill=", 5) == 0) { |
211 | 0 | if ((value = colour_fromstring(tmp + 5)) == -1) |
212 | 0 | goto error; |
213 | 0 | sy->fill = value; |
214 | 1.19k | } else if (end > 4 && strncasecmp(tmp, "dim=", 4) == 0) { |
215 | 64 | if (tmp[end - 1] == '%') |
216 | 64 | tmp[end - 1] = '\0'; |
217 | 64 | n = strtonum(tmp + 4, 0, 100, &errstr); |
218 | 64 | if (errstr != NULL) |
219 | 64 | goto error; |
220 | 0 | sy->dim = n; |
221 | 1.12k | } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) { |
222 | 271 | if ((value = colour_fromstring(tmp + 3)) == -1) |
223 | 64 | goto error; |
224 | 207 | if (*in == 'f' || *in == 'F') { |
225 | 15 | if (value != 8) |
226 | 15 | sy->gc.fg = value; |
227 | 0 | else |
228 | 0 | sy->gc.fg = base->fg; |
229 | 192 | } else if (*in == 'b' || *in == 'B') { |
230 | 192 | if (value != 8) |
231 | 128 | sy->gc.bg = value; |
232 | 64 | else |
233 | 64 | sy->gc.bg = base->bg; |
234 | 192 | } else |
235 | 0 | goto error; |
236 | 855 | } else if (end > 3 && strncasecmp(tmp, "us=", 3) == 0) { |
237 | 8 | if ((value = colour_fromstring(tmp + 3)) == -1) |
238 | 8 | goto error; |
239 | 0 | if (value != 8) |
240 | 0 | sy->gc.us = value; |
241 | 0 | else |
242 | 0 | sy->gc.us = base->us; |
243 | 847 | } else if (strcasecmp(tmp, "none") == 0) |
244 | 0 | sy->gc.attr = 0; |
245 | 847 | else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) { |
246 | 128 | if (strcmp(tmp + 2, "link") == 0) |
247 | 64 | sy->link = 0; |
248 | 64 | else if (strcmp(tmp + 2, "attr") == 0) |
249 | 0 | sy->gc.attr |= GRID_ATTR_NOATTR; |
250 | 64 | else { |
251 | 64 | value = attributes_fromstring(tmp + 2); |
252 | 64 | if (value == -1) |
253 | 64 | goto error; |
254 | 0 | sy->gc.attr &= ~value; |
255 | 0 | } |
256 | 719 | } else if (end > 6 && strncasecmp(tmp, "width=", 6) == 0) { |
257 | 32 | if (end > 7 && tmp[end - 1] == '%') { |
258 | 16 | tmp[end - 1] = '\0'; |
259 | 16 | n = strtonum(tmp + 6, 0, 100, &errstr); |
260 | 16 | if (errstr != NULL) |
261 | 16 | goto error; |
262 | 0 | sy->width = (int)n; |
263 | 0 | sy->width_percentage = 1; |
264 | 16 | } else { |
265 | 16 | n = strtonum(tmp + 6, 0, UINT_MAX, &errstr); |
266 | 16 | if (errstr != NULL) |
267 | 0 | goto error; |
268 | 16 | sy->width = (int)n; |
269 | 16 | sy->width_percentage = 0; |
270 | 16 | } |
271 | 687 | } else if (end > 4 && strncasecmp(tmp, "pad=", 4) == 0) { |
272 | 12 | n = strtonum(tmp + 4, 0, UINT_MAX, &errstr); |
273 | 12 | if (errstr != NULL) |
274 | 12 | goto error; |
275 | 0 | sy->pad = (int)n; |
276 | 675 | } else if (strncasecmp(tmp, "link=", 5) == 0) { |
277 | 128 | if (tmp[5] == '\0') |
278 | 128 | sy->link = 0; |
279 | 0 | else { |
280 | 0 | if (style_hyperlinks == NULL) |
281 | 0 | style_hyperlinks = hyperlinks_init(); |
282 | 0 | sy->link = hyperlinks_put(style_hyperlinks, |
283 | 0 | tmp + 5, tmp + 5); |
284 | 0 | } |
285 | 547 | } else { |
286 | 547 | if ((value = attributes_fromstring(tmp)) == -1) |
287 | 544 | goto error; |
288 | 3 | sy->gc.attr |= value; |
289 | 3 | } |
290 | | |
291 | 418 | in += end + strspn(in + end, delimiters); |
292 | 418 | } while (*in != '\0'); |
293 | | |
294 | 290 | return (0); |
295 | | |
296 | 1.17k | error: |
297 | 1.17k | style_copy(sy, &saved); |
298 | 1.17k | return (-1); |
299 | 1.46k | } |
300 | | |
301 | | /* Convert style to a string. */ |
302 | | const char * |
303 | | style_tostring(struct style *sy) |
304 | 0 | { |
305 | 0 | struct grid_cell *gc = &sy->gc; |
306 | 0 | int off = 0; |
307 | 0 | const char *comma = "", *tmp = "", *uri; |
308 | 0 | static char s[2048]; |
309 | 0 | char b[21]; |
310 | |
|
311 | 0 | *s = '\0'; |
312 | |
|
313 | 0 | if (sy->list != STYLE_LIST_OFF) { |
314 | 0 | if (sy->list == STYLE_LIST_ON) |
315 | 0 | tmp = "on"; |
316 | 0 | else if (sy->list == STYLE_LIST_FOCUS) |
317 | 0 | tmp = "focus"; |
318 | 0 | else if (sy->list == STYLE_LIST_LEFT_MARKER) |
319 | 0 | tmp = "left-marker"; |
320 | 0 | else if (sy->list == STYLE_LIST_RIGHT_MARKER) |
321 | 0 | tmp = "right-marker"; |
322 | 0 | off += xsnprintf(s + off, sizeof s - off, "%slist=%s", comma, |
323 | 0 | tmp); |
324 | 0 | comma = ","; |
325 | 0 | } |
326 | 0 | if (sy->range_type != STYLE_RANGE_NONE) { |
327 | 0 | if (sy->range_type == STYLE_RANGE_LEFT) |
328 | 0 | tmp = "left"; |
329 | 0 | else if (sy->range_type == STYLE_RANGE_RIGHT) |
330 | 0 | tmp = "right"; |
331 | 0 | else if (sy->range_type == STYLE_RANGE_PANE) { |
332 | 0 | snprintf(b, sizeof b, "pane|%%%u", sy->range_argument); |
333 | 0 | tmp = b; |
334 | 0 | } else if (sy->range_type == STYLE_RANGE_WINDOW) { |
335 | 0 | snprintf(b, sizeof b, "window|%u", sy->range_argument); |
336 | 0 | tmp = b; |
337 | 0 | } else if (sy->range_type == STYLE_RANGE_SESSION) { |
338 | 0 | snprintf(b, sizeof b, "session|$%u", |
339 | 0 | sy->range_argument); |
340 | 0 | tmp = b; |
341 | 0 | } else if (sy->range_type == STYLE_RANGE_USER) { |
342 | 0 | snprintf(b, sizeof b, "user|%s", sy->range_string); |
343 | 0 | tmp = b; |
344 | 0 | } |
345 | 0 | off += xsnprintf(s + off, sizeof s - off, "%srange=%s", comma, |
346 | 0 | tmp); |
347 | 0 | comma = ","; |
348 | 0 | } |
349 | 0 | if (sy->align != STYLE_ALIGN_DEFAULT) { |
350 | 0 | if (sy->align == STYLE_ALIGN_LEFT) |
351 | 0 | tmp = "left"; |
352 | 0 | else if (sy->align == STYLE_ALIGN_CENTRE) |
353 | 0 | tmp = "centre"; |
354 | 0 | else if (sy->align == STYLE_ALIGN_RIGHT) |
355 | 0 | tmp = "right"; |
356 | 0 | else if (sy->align == STYLE_ALIGN_ABSOLUTE_CENTRE) |
357 | 0 | tmp = "absolute-centre"; |
358 | 0 | off += xsnprintf(s + off, sizeof s - off, "%salign=%s", comma, |
359 | 0 | tmp); |
360 | 0 | comma = ","; |
361 | 0 | } |
362 | 0 | if (sy->default_type != STYLE_DEFAULT_BASE) { |
363 | 0 | if (sy->default_type == STYLE_DEFAULT_PUSH) |
364 | 0 | tmp = "push-default"; |
365 | 0 | else if (sy->default_type == STYLE_DEFAULT_POP) |
366 | 0 | tmp = "pop-default"; |
367 | 0 | else if (sy->default_type == STYLE_DEFAULT_SET) |
368 | 0 | tmp = "set-default"; |
369 | 0 | off += xsnprintf(s + off, sizeof s - off, "%s%s", comma, tmp); |
370 | 0 | comma = ","; |
371 | 0 | } |
372 | 0 | if (sy->fill != 8) { |
373 | 0 | off += xsnprintf(s + off, sizeof s - off, "%sfill=%s", comma, |
374 | 0 | colour_tostring(sy->fill)); |
375 | 0 | comma = ","; |
376 | 0 | } |
377 | 0 | if (sy->dim != 0) { |
378 | 0 | off += xsnprintf(s + off, sizeof s - off, "%sdim=%d%%", comma, |
379 | 0 | sy->dim); |
380 | 0 | comma = ","; |
381 | 0 | } |
382 | 0 | if (gc->fg != 8) { |
383 | 0 | off += xsnprintf(s + off, sizeof s - off, "%sfg=%s", comma, |
384 | 0 | colour_tostring(gc->fg)); |
385 | 0 | comma = ","; |
386 | 0 | } |
387 | 0 | if (gc->bg != 8) { |
388 | 0 | off += xsnprintf(s + off, sizeof s - off, "%sbg=%s", comma, |
389 | 0 | colour_tostring(gc->bg)); |
390 | 0 | comma = ","; |
391 | 0 | } |
392 | 0 | if (gc->us != 8) { |
393 | 0 | off += xsnprintf(s + off, sizeof s - off, "%sus=%s", comma, |
394 | 0 | colour_tostring(gc->us)); |
395 | 0 | comma = ","; |
396 | 0 | } |
397 | 0 | if (gc->attr != 0) { |
398 | 0 | off += xsnprintf(s + off, sizeof s - off, "%s%s", comma, |
399 | 0 | attributes_tostring(gc->attr)); |
400 | 0 | comma = ","; |
401 | 0 | } |
402 | 0 | if (sy->width >= 0) { |
403 | 0 | if (sy->width_percentage) |
404 | 0 | off += xsnprintf(s + off, sizeof s - off, |
405 | 0 | "%swidth=%u%%", comma, sy->width); |
406 | 0 | else |
407 | 0 | off += xsnprintf(s + off, sizeof s - off, |
408 | 0 | "%swidth=%u", comma, sy->width); |
409 | 0 | comma = ","; |
410 | 0 | } |
411 | 0 | if (sy->pad >= 0) { |
412 | 0 | off += xsnprintf(s + off, sizeof s - off, "%spad=%u", comma, |
413 | 0 | sy->pad); |
414 | 0 | comma = ","; |
415 | 0 | } |
416 | 0 | uri = style_link(sy); |
417 | 0 | if (uri != NULL) { |
418 | 0 | xsnprintf(s + off, sizeof s - off, "%slink=%s", comma, uri); |
419 | 0 | comma = ","; |
420 | 0 | } |
421 | 0 | if (*s == '\0') |
422 | 0 | return ("default"); |
423 | 0 | return (s); |
424 | 0 | } |
425 | | |
426 | | /* Get the hyperlink URI for a style, or NULL if it has none. */ |
427 | | const char * |
428 | | style_link(struct style *sy) |
429 | 0 | { |
430 | 0 | const char *uri; |
431 | |
|
432 | 0 | if (sy->link == 0 || style_hyperlinks == NULL) |
433 | 0 | return (NULL); |
434 | 0 | if (!hyperlinks_get(style_hyperlinks, sy->link, &uri, NULL, NULL)) |
435 | 0 | return (NULL); |
436 | 0 | return (uri); |
437 | 0 | } |
438 | | |
439 | | /* Apply a style on top of the given style. */ |
440 | | struct style * |
441 | | style_add(struct grid_cell *gc, struct options *oo, const char *name, |
442 | | struct format_tree *ft) |
443 | 0 | { |
444 | 0 | struct style *sy; |
445 | 0 | struct format_tree *ft0 = NULL; |
446 | |
|
447 | 0 | if (ft == NULL) |
448 | 0 | ft = ft0 = format_create(NULL, NULL, 0, FORMAT_NOJOBS); |
449 | |
|
450 | 0 | sy = options_string_to_style(oo, name, ft); |
451 | 0 | if (sy == NULL) |
452 | 0 | sy = &style_default; |
453 | 0 | if (sy->gc.fg != 8) |
454 | 0 | gc->fg = sy->gc.fg; |
455 | 0 | if (sy->gc.bg != 8) |
456 | 0 | gc->bg = sy->gc.bg; |
457 | 0 | if (sy->gc.us != 8) |
458 | 0 | gc->us = sy->gc.us; |
459 | 0 | gc->attr |= sy->gc.attr; |
460 | |
|
461 | 0 | if (ft0 != NULL) |
462 | 0 | format_free(ft0); |
463 | 0 | return (sy); |
464 | 0 | } |
465 | | |
466 | | /* Apply a style on top of the default style. */ |
467 | | void |
468 | | style_apply(struct grid_cell *gc, struct options *oo, const char *name, |
469 | | struct format_tree *ft) |
470 | 0 | { |
471 | 0 | memcpy(gc, &grid_default_cell, sizeof *gc); |
472 | 0 | style_add(gc, oo, name, ft); |
473 | 0 | } |
474 | | |
475 | | /* Parse a single colour into a style */ |
476 | | int |
477 | | style_parse_colour(struct style *sy, const struct grid_cell *base, |
478 | | const char *s) |
479 | 0 | { |
480 | 0 | int c; |
481 | |
|
482 | 0 | style_set(sy, base); |
483 | |
|
484 | 0 | if (*s == '\0') { |
485 | 0 | sy->gc.fg = -1; |
486 | 0 | return (0); |
487 | 0 | } |
488 | | |
489 | 0 | if ((c = colour_fromstring(s)) == -1) |
490 | 0 | return (-1); |
491 | 0 | if (c == 8) |
492 | 0 | sy->gc.fg = base->fg; |
493 | 0 | else |
494 | 0 | sy->gc.fg = c; |
495 | 0 | return (0); |
496 | 0 | } |
497 | | |
498 | | /* Initialize style from cell. */ |
499 | | void |
500 | | style_set(struct style *sy, const struct grid_cell *gc) |
501 | 908 | { |
502 | 908 | memcpy(sy, &style_default, sizeof *sy); |
503 | 908 | memcpy(&sy->gc, gc, sizeof sy->gc); |
504 | 908 | } |
505 | | |
506 | | /* Copy style. */ |
507 | | void |
508 | | style_copy(struct style *dst, struct style *src) |
509 | 2.64k | { |
510 | 2.64k | memcpy(dst, src, sizeof *dst); |
511 | 2.64k | } |
512 | | |
513 | | /* Set scrollbar style from an option. */ |
514 | | void |
515 | | style_set_scrollbar_style_from_option(struct style *sb_style, |
516 | | struct options *oo) |
517 | 0 | { |
518 | 0 | const struct options_table_entry *oe; |
519 | 0 | struct options_entry *o; |
520 | 0 | const char *s; |
521 | 0 | char *style, *expanded; |
522 | |
|
523 | 0 | style_set(sb_style, &grid_default_cell); |
524 | 0 | o = options_get(oo, "pane-scrollbars-style"); |
525 | 0 | if (o == NULL) |
526 | 0 | fatalx("missing pane-scrollbars-style"); |
527 | 0 | oe = options_table_entry(o); |
528 | 0 | style = format_single(NULL, oe->default_str, NULL, NULL, NULL, NULL); |
529 | 0 | if (style_parse(sb_style, &grid_default_cell, style) != 0) |
530 | 0 | fatalx("bad pane-scrollbars-style default"); |
531 | | |
532 | 0 | s = options_get_string(oo, "pane-scrollbars-style"); |
533 | 0 | if (s != NULL) { |
534 | 0 | expanded = format_single(NULL, s, NULL, NULL, NULL, NULL); |
535 | 0 | if (style_parse(sb_style, &grid_default_cell, expanded) != 0) |
536 | 0 | style_parse(sb_style, &grid_default_cell, style); |
537 | 0 | free(expanded); |
538 | 0 | } |
539 | 0 | free(style); |
540 | 0 | if (sb_style->width < 1) |
541 | 0 | sb_style->width = PANE_SCROLLBARS_DEFAULT_WIDTH; |
542 | 0 | if (sb_style->pad < 0) |
543 | 0 | sb_style->pad = PANE_SCROLLBARS_DEFAULT_PADDING; |
544 | 0 | utf8_set(&sb_style->gc.data, PANE_SCROLLBARS_CHARACTER); |
545 | 0 | } |
546 | | |
547 | | /* Initialize style ranges. */ |
548 | | void |
549 | | style_ranges_init(struct style_ranges *srs) |
550 | 0 | { |
551 | 0 | TAILQ_INIT(srs); |
552 | 0 | } |
553 | | |
554 | | /* Free style ranges. */ |
555 | | void |
556 | | style_ranges_free(struct style_ranges *srs) |
557 | 0 | { |
558 | 0 | struct style_range *sr, *sr1; |
559 | |
|
560 | 0 | TAILQ_FOREACH_SAFE(sr, srs, entry, sr1) { |
561 | 0 | TAILQ_REMOVE(srs, sr, entry); |
562 | 0 | free(sr); |
563 | 0 | } |
564 | 0 | } |
565 | | |
566 | | /* Get range for position from style ranges. */ |
567 | | struct style_range * |
568 | | style_ranges_get_range(struct style_ranges *srs, u_int x) |
569 | 0 | { |
570 | 0 | struct style_range *sr; |
571 | |
|
572 | 0 | if (srs == NULL) |
573 | 0 | return (NULL); |
574 | 0 | TAILQ_FOREACH(sr, srs, entry) { |
575 | 0 | if (x >= sr->start && x < sr->end) |
576 | 0 | return (sr); |
577 | 0 | } |
578 | 0 | return (NULL); |
579 | 0 | } |