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) {
81 sy
->gc
.attr
= base
->attr
;
82 sy
->gc
.flags
= base
->flags
;
83 } else if (strcasecmp(tmp
, "ignore") == 0)
85 else if (strcasecmp(tmp
, "noignore") == 0)
87 else if (strcasecmp(tmp
, "push-default") == 0)
88 sy
->default_type
= STYLE_DEFAULT_PUSH
;
89 else if (strcasecmp(tmp
, "pop-default") == 0)
90 sy
->default_type
= STYLE_DEFAULT_POP
;
91 else if (strcasecmp(tmp
, "nolist") == 0)
92 sy
->list
= STYLE_LIST_OFF
;
93 else if (strncasecmp(tmp
, "list=", 5) == 0) {
94 if (strcasecmp(tmp
+ 5, "on") == 0)
95 sy
->list
= STYLE_LIST_ON
;
96 else if (strcasecmp(tmp
+ 5, "focus") == 0)
97 sy
->list
= STYLE_LIST_FOCUS
;
98 else if (strcasecmp(tmp
+ 5, "left-marker") == 0)
99 sy
->list
= STYLE_LIST_LEFT_MARKER
;
100 else if (strcasecmp(tmp
+ 5, "right-marker") == 0)
101 sy
->list
= STYLE_LIST_RIGHT_MARKER
;
104 } else if (strcasecmp(tmp
, "norange") == 0) {
105 sy
->range_type
= style_default
.range_type
;
106 sy
->range_argument
= style_default
.range_type
;
107 } else if (end
> 6 && strncasecmp(tmp
, "range=", 6) == 0) {
108 found
= strchr(tmp
+ 6, '|');
113 for (cp
= found
; *cp
!= '\0'; cp
++) {
114 if (!isdigit((u_char
)*cp
))
118 if (strcasecmp(tmp
+ 6, "left") == 0) {
121 sy
->range_type
= STYLE_RANGE_LEFT
;
122 sy
->range_argument
= 0;
123 } else if (strcasecmp(tmp
+ 6, "right") == 0) {
126 sy
->range_type
= STYLE_RANGE_RIGHT
;
127 sy
->range_argument
= 0;
128 } else if (strcasecmp(tmp
+ 6, "window") == 0) {
131 sy
->range_type
= STYLE_RANGE_WINDOW
;
132 sy
->range_argument
= atoi(found
);
134 } else if (strcasecmp(tmp
, "noalign") == 0)
135 sy
->align
= style_default
.align
;
136 else if (end
> 6 && strncasecmp(tmp
, "align=", 6) == 0) {
137 if (strcasecmp(tmp
+ 6, "left") == 0)
138 sy
->align
= STYLE_ALIGN_LEFT
;
139 else if (strcasecmp(tmp
+ 6, "centre") == 0)
140 sy
->align
= STYLE_ALIGN_CENTRE
;
141 else if (strcasecmp(tmp
+ 6, "right") == 0)
142 sy
->align
= STYLE_ALIGN_RIGHT
;
143 else if (strcasecmp(tmp
+ 6, "absolute-centre") == 0)
144 sy
->align
= STYLE_ALIGN_ABSOLUTE_CENTRE
;
147 } else if (end
> 5 && strncasecmp(tmp
, "fill=", 5) == 0) {
148 if ((value
= colour_fromstring(tmp
+ 5)) == -1)
151 } else if (end
> 3 && strncasecmp(tmp
+ 1, "g=", 2) == 0) {
152 if ((value
= colour_fromstring(tmp
+ 3)) == -1)
154 if (*in
== 'f' || *in
== 'F') {
158 sy
->gc
.fg
= base
->fg
;
159 } else if (*in
== 'b' || *in
== 'B') {
163 sy
->gc
.bg
= base
->bg
;
166 } else if (end
> 3 && strncasecmp(tmp
, "us=", 3) == 0) {
167 if ((value
= colour_fromstring(tmp
+ 3)) == -1)
172 sy
->gc
.us
= base
->us
;
173 } else if (strcasecmp(tmp
, "none") == 0)
175 else if (end
> 2 && strncasecmp(tmp
, "no", 2) == 0) {
176 if ((value
= attributes_fromstring(tmp
+ 2)) == -1)
178 sy
->gc
.attr
&= ~value
;
180 if ((value
= attributes_fromstring(tmp
)) == -1)
182 sy
->gc
.attr
|= value
;
185 in
+= end
+ strspn(in
+ end
, delimiters
);
186 } while (*in
!= '\0');
191 style_copy(sy
, &saved
);
195 /* Convert style to a string. */
197 style_tostring(struct style
*sy
)
199 struct grid_cell
*gc
= &sy
->gc
;
201 const char *comma
= "", *tmp
= "";
207 if (sy
->list
!= STYLE_LIST_OFF
) {
208 if (sy
->list
== STYLE_LIST_ON
)
210 else if (sy
->list
== STYLE_LIST_FOCUS
)
212 else if (sy
->list
== STYLE_LIST_LEFT_MARKER
)
214 else if (sy
->list
== STYLE_LIST_RIGHT_MARKER
)
215 tmp
= "right-marker";
216 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%slist=%s", comma
,
220 if (sy
->range_type
!= STYLE_RANGE_NONE
) {
221 if (sy
->range_type
== STYLE_RANGE_LEFT
)
223 else if (sy
->range_type
== STYLE_RANGE_RIGHT
)
225 else if (sy
->range_type
== STYLE_RANGE_WINDOW
) {
226 snprintf(b
, sizeof b
, "window|%u", sy
->range_argument
);
229 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%srange=%s", comma
,
233 if (sy
->align
!= STYLE_ALIGN_DEFAULT
) {
234 if (sy
->align
== STYLE_ALIGN_LEFT
)
236 else if (sy
->align
== STYLE_ALIGN_CENTRE
)
238 else if (sy
->align
== STYLE_ALIGN_RIGHT
)
240 else if (sy
->align
== STYLE_ALIGN_ABSOLUTE_CENTRE
)
241 tmp
= "absolute-centre";
242 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%salign=%s", comma
,
246 if (sy
->default_type
!= STYLE_DEFAULT_BASE
) {
247 if (sy
->default_type
== STYLE_DEFAULT_PUSH
)
248 tmp
= "push-default";
249 else if (sy
->default_type
== STYLE_DEFAULT_POP
)
251 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%s%s", comma
, tmp
);
255 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sfill=%s", comma
,
256 colour_tostring(sy
->fill
));
260 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sfg=%s", comma
,
261 colour_tostring(gc
->fg
));
265 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sbg=%s", comma
,
266 colour_tostring(gc
->bg
));
270 off
+= xsnprintf(s
+ off
, sizeof s
- off
, "%sus=%s", comma
,
271 colour_tostring(gc
->us
));
275 xsnprintf(s
+ off
, sizeof s
- off
, "%s%s", comma
,
276 attributes_tostring(gc
->attr
));
285 /* Apply a style on top of the given style. */
287 style_add(struct grid_cell
*gc
, struct options
*oo
, const char *name
,
288 struct format_tree
*ft
)
291 struct format_tree
*ft0
= NULL
;
294 ft
= ft0
= format_create(NULL
, NULL
, 0, FORMAT_NOJOBS
);
296 sy
= options_string_to_style(oo
, name
, ft
);
305 gc
->attr
|= sy
->gc
.attr
;
311 /* Apply a style on top of the default style. */
313 style_apply(struct grid_cell
*gc
, struct options
*oo
, const char *name
,
314 struct format_tree
*ft
)
316 memcpy(gc
, &grid_default_cell
, sizeof *gc
);
317 style_add(gc
, oo
, name
, ft
);
320 /* Initialize style from cell. */
322 style_set(struct style
*sy
, const struct grid_cell
*gc
)
324 memcpy(sy
, &style_default
, sizeof *sy
);
325 memcpy(&sy
->gc
, gc
, sizeof sy
->gc
);
330 style_copy(struct style
*dst
, struct style
*src
)
332 memcpy(dst
, src
, sizeof *dst
);