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