4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5 * Copyright (c) 2014 Tiago Cunha <tcunha@users.sourceforge.net>
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.
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.
20 #include <sys/types.h>
28 /* Mask for bits not included in style. */
29 #define STYLE_ATTR_MASK (~0)
32 static struct style style_default
= {
33 { { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0 },
40 STYLE_RANGE_NONE
, 0, "",
45 /* Set range string. */
47 style_set_range_string(struct style
*sy
, const char *s
)
49 strlcpy(sy
->range_string
, s
, sizeof sy
->range_string
);
53 * Parse an embedded style of the form "fg=colour,bg=colour,bright,...". Note
54 * that this adds onto the given style, so it must have been initialized
58 style_parse(struct style
*sy
, const struct grid_cell
*base
, const char *in
)
61 const char delimiters
[] = " ,\n", *cp
;
62 char tmp
[256], *found
;
68 style_copy(&saved
, sy
);
70 log_debug("%s: %s", __func__
, in
);
72 while (*in
!= '\0' && strchr(delimiters
, *in
) != NULL
)
77 end
= strcspn(in
, delimiters
);
78 if (end
> (sizeof tmp
) - 1)
83 log_debug("%s: %s", __func__
, tmp
);
84 if (strcasecmp(tmp
, "default") == 0) {
88 sy
->gc
.attr
= base
->attr
;
89 sy
->gc
.flags
= base
->flags
;
90 } else if (strcasecmp(tmp
, "ignore") == 0)
92 else if (strcasecmp(tmp
, "noignore") == 0)
94 else if (strcasecmp(tmp
, "push-default") == 0)
95 sy
->default_type
= STYLE_DEFAULT_PUSH
;
96 else if (strcasecmp(tmp
, "pop-default") == 0)
97 sy
->default_type
= STYLE_DEFAULT_POP
;
98 else if (strcasecmp(tmp
, "nolist") == 0)
99 sy
->list
= STYLE_LIST_OFF
;
100 else if (strncasecmp(tmp
, "list=", 5) == 0) {
101 if (strcasecmp(tmp
+ 5, "on") == 0)
102 sy
->list
= STYLE_LIST_ON
;
103 else if (strcasecmp(tmp
+ 5, "focus") == 0)
104 sy
->list
= STYLE_LIST_FOCUS
;
105 else if (strcasecmp(tmp
+ 5, "left-marker") == 0)
106 sy
->list
= STYLE_LIST_LEFT_MARKER
;
107 else if (strcasecmp(tmp
+ 5, "right-marker") == 0)
108 sy
->list
= STYLE_LIST_RIGHT_MARKER
;
111 } else if (strcasecmp(tmp
, "norange") == 0) {
112 sy
->range_type
= style_default
.range_type
;
113 sy
->range_argument
= style_default
.range_type
;
114 strlcpy(sy
->range_string
, style_default
.range_string
,
115 sizeof sy
->range_string
);
116 } else if (end
> 6 && strncasecmp(tmp
, "range=", 6) == 0) {
117 found
= strchr(tmp
+ 6, '|');
123 if (strcasecmp(tmp
+ 6, "left") == 0) {
126 sy
->range_type
= STYLE_RANGE_LEFT
;
127 sy
->range_argument
= 0;
128 style_set_range_string(sy
, "");
129 } else if (strcasecmp(tmp
+ 6, "right") == 0) {
132 sy
->range_type
= STYLE_RANGE_RIGHT
;
133 sy
->range_argument
= 0;
134 style_set_range_string(sy
, "");
135 } else if (strcasecmp(tmp
+ 6, "pane") == 0) {
138 if (*found
!= '%' || found
[1] == '\0')
140 for (cp
= found
+ 1; *cp
!= '\0'; cp
++) {
141 if (!isdigit((u_char
)*cp
))
144 sy
->range_type
= STYLE_RANGE_PANE
;
145 sy
->range_argument
= atoi(found
+ 1);
146 style_set_range_string(sy
, "");
147 } else if (strcasecmp(tmp
+ 6, "window") == 0) {
150 for (cp
= found
; *cp
!= '\0'; cp
++) {
151 if (!isdigit((u_char
)*cp
))
154 sy
->range_type
= STYLE_RANGE_WINDOW
;
155 sy
->range_argument
= atoi(found
);
156 style_set_range_string(sy
, "");
157 } else if (strcasecmp(tmp
+ 6, "session") == 0) {
160 if (*found
!= '$' || found
[1] == '\0')
162 for (cp
= found
+ 1; *cp
!= '\0'; cp
++) {
163 if (!isdigit((u_char
)*cp
))
166 sy
->range_type
= STYLE_RANGE_SESSION
;
167 sy
->range_argument
= atoi(found
+ 1);
168 style_set_range_string(sy
, "");
169 } else if (strcasecmp(tmp
+ 6, "user") == 0) {
172 sy
->range_type
= STYLE_RANGE_USER
;
173 sy
->range_argument
= 0;
174 style_set_range_string(sy
, found
);
176 } else if (strcasecmp(tmp
, "noalign") == 0)
177 sy
->align
= style_default
.align
;
178 else if (end
> 6 && strncasecmp(tmp
, "align=", 6) == 0) {
179 if (strcasecmp(tmp
+ 6, "left") == 0)
180 sy
->align
= STYLE_ALIGN_LEFT
;
181 else if (strcasecmp(tmp
+ 6, "centre") == 0)
182 sy
->align
= STYLE_ALIGN_CENTRE
;
183 else if (strcasecmp(tmp
+ 6, "right") == 0)
184 sy
->align
= STYLE_ALIGN_RIGHT
;
185 else if (strcasecmp(tmp
+ 6, "absolute-centre") == 0)
186 sy
->align
= STYLE_ALIGN_ABSOLUTE_CENTRE
;
189 } else if (end
> 5 && strncasecmp(tmp
, "fill=", 5) == 0) {
190 if ((value
= colour_fromstring(tmp
+ 5)) == -1)
193 } else if (end
> 3 && strncasecmp(tmp
+ 1, "g=", 2) == 0) {
194 if ((value
= colour_fromstring(tmp
+ 3)) == -1)
196 if (*in
== 'f' || *in
== 'F') {
200 sy
->gc
.fg
= base
->fg
;
201 } else if (*in
== 'b' || *in
== 'B') {
205 sy
->gc
.bg
= base
->bg
;
208 } else if (end
> 3 && strncasecmp(tmp
, "us=", 3) == 0) {
209 if ((value
= colour_fromstring(tmp
+ 3)) == -1)
214 sy
->gc
.us
= base
->us
;
215 } else if (strcasecmp(tmp
, "none") == 0)
217 else if (end
> 2 && strncasecmp(tmp
, "no", 2) == 0) {
218 if ((value
= attributes_fromstring(tmp
+ 2)) == -1)
220 sy
->gc
.attr
&= ~value
;
222 if ((value
= attributes_fromstring(tmp
)) == -1)
224 sy
->gc
.attr
|= value
;
227 in
+= end
+ strspn(in
+ end
, delimiters
);
228 } while (*in
!= '\0');
233 style_copy(sy
, &saved
);
237 /* Convert style to a string. */
239 style_tostring(struct style
*sy
)
241 struct grid_cell
*gc
= &sy
->gc
;
243 const char *comma
= "", *tmp
= "";
249 if (sy
->list
!= STYLE_LIST_OFF
) {
250 if (sy
->list
== STYLE_LIST_ON
)
252 else if (sy
->list
== STYLE_LIST_FOCUS
)
254 else if (sy
->list
== STYLE_LIST_LEFT_MARKER
)
256 else if (sy
->list
== STYLE_LIST_RIGHT_MARKER
)
257 tmp
= "right-marker";
258 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%slist=%s", comma
,
262 if (sy
->range_type
!= STYLE_RANGE_NONE
) {
263 if (sy
->range_type
== STYLE_RANGE_LEFT
)
265 else if (sy
->range_type
== STYLE_RANGE_RIGHT
)
267 else if (sy
->range_type
== STYLE_RANGE_PANE
) {
268 snprintf(b
, sizeof b
, "pane|%%%u", sy
->range_argument
);
270 } else if (sy
->range_type
== STYLE_RANGE_WINDOW
) {
271 snprintf(b
, sizeof b
, "window|%u", sy
->range_argument
);
273 } else if (sy
->range_type
== STYLE_RANGE_SESSION
) {
274 snprintf(b
, sizeof b
, "session|$%u",
277 } else if (sy
->range_type
== STYLE_RANGE_USER
) {
278 snprintf(b
, sizeof b
, "user|%s", sy
->range_string
);
281 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%srange=%s", comma
,
285 if (sy
->align
!= STYLE_ALIGN_DEFAULT
) {
286 if (sy
->align
== STYLE_ALIGN_LEFT
)
288 else if (sy
->align
== STYLE_ALIGN_CENTRE
)
290 else if (sy
->align
== STYLE_ALIGN_RIGHT
)
292 else if (sy
->align
== STYLE_ALIGN_ABSOLUTE_CENTRE
)
293 tmp
= "absolute-centre";
294 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%salign=%s", comma
,
298 if (sy
->default_type
!= STYLE_DEFAULT_BASE
) {
299 if (sy
->default_type
== STYLE_DEFAULT_PUSH
)
300 tmp
= "push-default";
301 else if (sy
->default_type
== STYLE_DEFAULT_POP
)
303 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%s%s", comma
, tmp
);
307 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sfill=%s", comma
,
308 colour_tostring(sy
->fill
));
312 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sfg=%s", comma
,
313 colour_tostring(gc
->fg
));
317 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sbg=%s", comma
,
318 colour_tostring(gc
->bg
));
322 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sus=%s", comma
,
323 colour_tostring(gc
->us
));
327 xsnprintf(s
+ off
, sizeof s
- off
, "%s%s", comma
,
328 attributes_tostring(gc
->attr
));
337 /* Apply a style on top of the given style. */
339 style_add(struct grid_cell
*gc
, struct options
*oo
, const char *name
,
340 struct format_tree
*ft
)
343 struct format_tree
*ft0
= NULL
;
346 ft
= ft0
= format_create(NULL
, NULL
, 0, FORMAT_NOJOBS
);
348 sy
= options_string_to_style(oo
, name
, ft
);
357 gc
->attr
|= sy
->gc
.attr
;
363 /* Apply a style on top of the default style. */
365 style_apply(struct grid_cell
*gc
, struct options
*oo
, const char *name
,
366 struct format_tree
*ft
)
368 memcpy(gc
, &grid_default_cell
, sizeof *gc
);
369 style_add(gc
, oo
, name
, ft
);
372 /* Initialize style from cell. */
374 style_set(struct style
*sy
, const struct grid_cell
*gc
)
376 memcpy(sy
, &style_default
, sizeof *sy
);
377 memcpy(&sy
->gc
, gc
, sizeof sy
->gc
);
382 style_copy(struct style
*dst
, struct style
*src
)
384 memcpy(dst
, src
, sizeof *dst
);