1 /* $OpenBSD: style.c,v 1.3 2014/05/08 05:53:29 nicm Exp $ */ 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 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 * 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 || gc->flags & GRID_FLAG_FG256) { 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 || gc->flags & GRID_FLAG_BG256) { 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 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 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 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 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 || gcp->flags & GRID_FLAG_FG256) { 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 || gcp->flags & GRID_FLAG_BG256) { 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