xref: /minix3/external/bsd/tmux/dist/style.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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 <string.h>
21 
22 #include "tmux.h"
23 
24 /* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */
25 int
style_parse(const struct grid_cell * defgc,struct grid_cell * gc,const char * in)26 style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
27     const char *in)
28 {
29 	const char	delimiters[] = " ,";
30 	char		tmp[32];
31 	int		val;
32 	size_t		end;
33 	u_char		fg, bg, attr, flags;
34 
35 	if (*in == '\0')
36 		return (0);
37 	if (strchr(delimiters, in[strlen(in) - 1]) != NULL)
38 		return (-1);
39 
40 	fg = gc->fg;
41 	bg = gc->bg;
42 	attr = gc->attr;
43 	flags = gc->flags;
44 	do {
45 		end = strcspn(in, delimiters);
46 		if (end > (sizeof tmp) - 1)
47 			return (-1);
48 		memcpy(tmp, in, end);
49 		tmp[end] = '\0';
50 
51 		if (strcasecmp(tmp, "default") == 0) {
52 			fg = defgc->fg;
53 			bg = defgc->bg;
54 			attr = defgc->attr;
55 			flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
56 			flags |=
57 			    defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
58 		} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
59 			if ((val = colour_fromstring(tmp + 3)) == -1)
60 				return (-1);
61 			if (*in == 'f' || *in == 'F') {
62 				if (val != 8) {
63 					if (val & 0x100) {
64 						flags |= GRID_FLAG_FG256;
65 						val &= ~0x100;
66 					} else
67 						flags &= ~GRID_FLAG_FG256;
68 					fg = val;
69 				} else {
70 					fg = defgc->fg;
71 					flags &= ~GRID_FLAG_FG256;
72 					flags |= defgc->flags & GRID_FLAG_FG256;
73 				}
74 			} else if (*in == 'b' || *in == 'B') {
75 				if (val != 8) {
76 					if (val & 0x100) {
77 						flags |= GRID_FLAG_BG256;
78 						val &= ~0x100;
79 					} else
80 						flags &= ~GRID_FLAG_BG256;
81 					bg = val;
82 				} else {
83 					bg = defgc->bg;
84 					flags &= ~GRID_FLAG_BG256;
85 					flags |= defgc->flags & GRID_FLAG_BG256;
86 				}
87 			} else
88 				return (-1);
89 		} else if (strcasecmp(tmp, "none") == 0)
90 			attr = 0;
91 		else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
92 			if ((val = attributes_fromstring(tmp + 2)) == -1)
93 				return (-1);
94 			attr &= ~val;
95 		} else {
96 			if ((val = attributes_fromstring(tmp)) == -1)
97 				return (-1);
98 			attr |= val;
99 		}
100 
101 		in += end + strspn(in + end, delimiters);
102 	} while (*in != '\0');
103 	gc->fg = fg;
104 	gc->bg = bg;
105 	gc->attr = attr;
106 	gc->flags = flags;
107 
108 	return (0);
109 }
110 
111 /* Convert style to a string. */
112 const char *
style_tostring(struct grid_cell * gc)113 style_tostring(struct grid_cell *gc)
114 {
115 	int		 c, off = 0, comma = 0;
116 	static char	 s[256];
117 
118 	*s = '\0';
119 
120 	if (gc->fg != 8) {
121 		if (gc->flags & GRID_FLAG_FG256)
122 			c = gc->fg | 0x100;
123 		else
124 			c = gc->fg;
125 		off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
126 		comma = 1;
127 	}
128 
129 	if (gc->bg != 8) {
130 		if (gc->flags & GRID_FLAG_BG256)
131 			c = gc->bg | 0x100;
132 		else
133 			c = gc->bg;
134 		off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
135 		    comma ? "," : "", colour_tostring(c));
136 		comma = 1;
137 	}
138 
139 	if (gc->attr != 0 && gc->attr != GRID_ATTR_CHARSET) {
140 		xsnprintf(s + off, sizeof s - off, "%s%s",
141 		    comma ? "," : "", attributes_tostring(gc->attr));
142 	}
143 
144 	if (*s == '\0')
145 		return ("default");
146 	return (s);
147 }
148 
149 /* Synchronize new -style option with the old one. */
150 void
style_update_new(struct options * oo,const char * name,const char * newname)151 style_update_new(struct options *oo, const char *name, const char *newname)
152 {
153 	int			 value;
154 	struct grid_cell	*gc;
155 
156 	/* It's a colour or attribute, but with no -style equivalent. */
157 	if (newname == NULL)
158 		return;
159 
160 	gc = options_get_style(oo, newname);
161 	value = options_get_number(oo, name);
162 
163 	if (strstr(name, "-bg") != NULL)
164 		colour_set_bg(gc, value);
165 	else if (strstr(name, "-fg") != NULL)
166 		colour_set_fg(gc, value);
167 	else if (strstr(name, "-attr") != NULL)
168 		gc->attr = value;
169 }
170 
171 /* Synchronize all the old options with the new -style one. */
172 void
style_update_old(struct options * oo,const char * name,struct grid_cell * gc)173 style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
174 {
175 	char	newname[128];
176 	int	c, size;
177 
178 	size = strrchr(name, '-') - name;
179 
180 	if (gc->flags & GRID_FLAG_BG256)
181 		c = gc->bg | 0x100;
182 	else
183 		c = gc->bg;
184 	xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
185 	options_set_number(oo, newname, c);
186 
187 	if (gc->flags & GRID_FLAG_FG256)
188 		c = gc->fg | 0x100;
189 	else
190 		c = gc->fg;
191 	xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
192 	options_set_number(oo, newname, c);
193 
194 	xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
195 	options_set_number(oo, newname, gc->attr);
196 }
197 
198 /* Apply a style. */
199 void
style_apply(struct grid_cell * gc,struct options * oo,const char * name)200 style_apply(struct grid_cell *gc, struct options *oo, const char *name)
201 {
202 	struct grid_cell	*gcp;
203 
204 	memcpy(gc, &grid_default_cell, sizeof *gc);
205 	gcp = options_get_style(oo, name);
206 	if (gcp->flags & GRID_FLAG_FG256)
207 		colour_set_fg(gc, gcp->fg | 0x100);
208 	else
209 		colour_set_fg(gc, gcp->fg);
210 	if (gcp->flags & GRID_FLAG_BG256)
211 		colour_set_bg(gc, gcp->bg | 0x100);
212 	else
213 		colour_set_bg(gc, gcp->bg);
214 	gc->attr |= gcp->attr;
215 }
216 
217 /* Apply a style, updating if default. */
218 void
style_apply_update(struct grid_cell * gc,struct options * oo,const char * name)219 style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
220 {
221 	struct grid_cell	*gcp;
222 
223 	gcp = options_get_style(oo, name);
224 	if (gcp->fg != 8) {
225 		if (gcp->flags & GRID_FLAG_FG256)
226 			colour_set_fg(gc, gcp->fg | 0x100);
227 		else
228 			colour_set_fg(gc, gcp->fg);
229 	}
230 	if (gcp->bg != 8) {
231 		if (gcp->flags & GRID_FLAG_BG256)
232 			colour_set_bg(gc, gcp->bg | 0x100);
233 		else
234 			colour_set_bg(gc, gcp->bg);
235 	}
236 	if (gcp->attr != 0)
237 		gc->attr |= gcp->attr;
238 }
239