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 },
46 * Parse an embedded style of the form "fg=colour,bg=colour,bright,...". Note
47 * that this adds onto the given style, so it must have been initialized
51 style_parse(struct style
*sy
, const struct grid_cell
*base
, const char *in
)
54 const char delimiters
[] = " ,\n", *cp
;
55 char tmp
[256], *found
;
61 style_copy(&saved
, sy
);
63 log_debug("%s: %s", __func__
, in
);
65 while (*in
!= '\0' && strchr(delimiters
, *in
) != NULL
)
70 end
= strcspn(in
, delimiters
);
71 if (end
> (sizeof tmp
) - 1)
76 log_debug("%s: %s", __func__
, tmp
);
77 if (strcasecmp(tmp
, "default") == 0) {
80 sy
->gc
.attr
= base
->attr
;
81 sy
->gc
.flags
= base
->flags
;
82 } else if (strcasecmp(tmp
, "ignore") == 0)
84 else if (strcasecmp(tmp
, "noignore") == 0)
86 else if (strcasecmp(tmp
, "push-default") == 0)
87 sy
->default_type
= STYLE_DEFAULT_PUSH
;
88 else if (strcasecmp(tmp
, "pop-default") == 0)
89 sy
->default_type
= STYLE_DEFAULT_POP
;
90 else if (strcasecmp(tmp
, "nolist") == 0)
91 sy
->list
= STYLE_LIST_OFF
;
92 else if (strncasecmp(tmp
, "list=", 5) == 0) {
93 if (strcasecmp(tmp
+ 5, "on") == 0)
94 sy
->list
= STYLE_LIST_ON
;
95 else if (strcasecmp(tmp
+ 5, "focus") == 0)
96 sy
->list
= STYLE_LIST_FOCUS
;
97 else if (strcasecmp(tmp
+ 5, "left-marker") == 0)
98 sy
->list
= STYLE_LIST_LEFT_MARKER
;
99 else if (strcasecmp(tmp
+ 5, "right-marker") == 0)
100 sy
->list
= STYLE_LIST_RIGHT_MARKER
;
103 } else if (strcasecmp(tmp
, "norange") == 0) {
104 sy
->range_type
= style_default
.range_type
;
105 sy
->range_argument
= style_default
.range_type
;
106 } else if (end
> 6 && strncasecmp(tmp
, "range=", 6) == 0) {
107 found
= strchr(tmp
+ 6, '|');
112 for (cp
= found
; *cp
!= '\0'; cp
++) {
113 if (!isdigit((u_char
)*cp
))
117 if (strcasecmp(tmp
+ 6, "left") == 0) {
120 sy
->range_type
= STYLE_RANGE_LEFT
;
121 sy
->range_argument
= 0;
122 } else if (strcasecmp(tmp
+ 6, "right") == 0) {
125 sy
->range_type
= STYLE_RANGE_RIGHT
;
126 sy
->range_argument
= 0;
127 } else if (strcasecmp(tmp
+ 6, "window") == 0) {
130 sy
->range_type
= STYLE_RANGE_WINDOW
;
131 sy
->range_argument
= atoi(found
);
133 } else if (strcasecmp(tmp
, "noalign") == 0)
134 sy
->align
= style_default
.align
;
135 else if (end
> 6 && strncasecmp(tmp
, "align=", 6) == 0) {
136 if (strcasecmp(tmp
+ 6, "left") == 0)
137 sy
->align
= STYLE_ALIGN_LEFT
;
138 else if (strcasecmp(tmp
+ 6, "centre") == 0)
139 sy
->align
= STYLE_ALIGN_CENTRE
;
140 else if (strcasecmp(tmp
+ 6, "right") == 0)
141 sy
->align
= STYLE_ALIGN_RIGHT
;
142 else if (strcasecmp(tmp
+ 6, "absolute-centre") == 0)
143 sy
->align
= STYLE_ALIGN_ABSOLUTE_CENTRE
;
146 } else if (end
> 5 && strncasecmp(tmp
, "fill=", 5) == 0) {
147 if ((value
= colour_fromstring(tmp
+ 5)) == -1)
150 } else if (end
> 3 && strncasecmp(tmp
+ 1, "g=", 2) == 0) {
151 if ((value
= colour_fromstring(tmp
+ 3)) == -1)
153 if (*in
== 'f' || *in
== 'F') {
157 sy
->gc
.fg
= base
->fg
;
158 } else if (*in
== 'b' || *in
== 'B') {
162 sy
->gc
.bg
= base
->bg
;
165 } else if (strcasecmp(tmp
, "none") == 0)
167 else if (end
> 2 && strncasecmp(tmp
, "no", 2) == 0) {
168 if ((value
= attributes_fromstring(tmp
+ 2)) == -1)
170 sy
->gc
.attr
&= ~value
;
172 if ((value
= attributes_fromstring(tmp
)) == -1)
174 sy
->gc
.attr
|= value
;
177 in
+= end
+ strspn(in
+ end
, delimiters
);
178 } while (*in
!= '\0');
183 style_copy(sy
, &saved
);
187 /* Convert style to a string. */
189 style_tostring(struct style
*sy
)
191 struct grid_cell
*gc
= &sy
->gc
;
193 const char *comma
= "", *tmp
= "";
199 if (sy
->list
!= STYLE_LIST_OFF
) {
200 if (sy
->list
== STYLE_LIST_ON
)
202 else if (sy
->list
== STYLE_LIST_FOCUS
)
204 else if (sy
->list
== STYLE_LIST_LEFT_MARKER
)
206 else if (sy
->list
== STYLE_LIST_RIGHT_MARKER
)
207 tmp
= "right-marker";
208 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%slist=%s", comma
,
212 if (sy
->range_type
!= STYLE_RANGE_NONE
) {
213 if (sy
->range_type
== STYLE_RANGE_LEFT
)
215 else if (sy
->range_type
== STYLE_RANGE_RIGHT
)
217 else if (sy
->range_type
== STYLE_RANGE_WINDOW
) {
218 snprintf(b
, sizeof b
, "window|%u", sy
->range_argument
);
221 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%srange=%s", comma
,
225 if (sy
->align
!= STYLE_ALIGN_DEFAULT
) {
226 if (sy
->align
== STYLE_ALIGN_LEFT
)
228 else if (sy
->align
== STYLE_ALIGN_CENTRE
)
230 else if (sy
->align
== STYLE_ALIGN_RIGHT
)
232 else if (sy
->align
== STYLE_ALIGN_ABSOLUTE_CENTRE
)
233 tmp
= "absolute-centre";
234 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%salign=%s", comma
,
238 if (sy
->default_type
!= STYLE_DEFAULT_BASE
) {
239 if (sy
->default_type
== STYLE_DEFAULT_PUSH
)
240 tmp
= "push-default";
241 else if (sy
->default_type
== STYLE_DEFAULT_POP
)
243 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%s%s", comma
, tmp
);
247 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sfill=%s", comma
,
248 colour_tostring(sy
->fill
));
252 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sfg=%s", comma
,
253 colour_tostring(gc
->fg
));
257 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sbg=%s", comma
,
258 colour_tostring(gc
->bg
));
262 xsnprintf(s
+ off
, sizeof s
- off
, "%s%s", comma
,
263 attributes_tostring(gc
->attr
));
272 /* Apply a style on top of the given style. */
274 style_add(struct grid_cell
*gc
, struct options
*oo
, const char *name
,
275 struct format_tree
*ft
)
278 struct format_tree
*ft0
= NULL
;
281 ft
= ft0
= format_create(NULL
, NULL
, 0, FORMAT_NOJOBS
);
283 sy
= options_string_to_style(oo
, name
, ft
);
290 gc
->attr
|= sy
->gc
.attr
;
296 /* Apply a style on top of the default style. */
298 style_apply(struct grid_cell
*gc
, struct options
*oo
, const char *name
,
299 struct format_tree
*ft
)
301 memcpy(gc
, &grid_default_cell
, sizeof *gc
);
302 style_add(gc
, oo
, name
, ft
);
305 /* Initialize style from cell. */
307 style_set(struct style
*sy
, const struct grid_cell
*gc
)
309 memcpy(sy
, &style_default
, sizeof *sy
);
310 memcpy(&sy
->gc
, gc
, sizeof sy
->gc
);
315 style_copy(struct style
*dst
, struct style
*src
)
317 memcpy(dst
, src
, sizeof *dst
);