1 /* $OpenBSD: style.c,v 1.10 2016/07/15 00:42:56 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> 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 int fg, bg; 37 u_char attr, flags; 38 39 if (*in == '\0') 40 return (0); 41 if (strchr(delimiters, in[strlen(in) - 1]) != NULL) 42 return (-1); 43 memcpy(&savedgc, gc, sizeof savedgc); 44 45 fg = gc->fg; 46 bg = gc->bg; 47 attr = gc->attr; 48 flags = gc->flags; 49 do { 50 end = strcspn(in, delimiters); 51 if (end > (sizeof tmp) - 1) 52 goto error; 53 memcpy(tmp, in, end); 54 tmp[end] = '\0'; 55 56 if (strcasecmp(tmp, "default") == 0) { 57 fg = defgc->fg; 58 bg = defgc->bg; 59 attr = defgc->attr; 60 flags = defgc->flags; 61 } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) { 62 if ((val = colour_fromstring(tmp + 3)) == -1) 63 goto error; 64 if (*in == 'f' || *in == 'F') { 65 if (val != 8) 66 fg = val; 67 else 68 fg = defgc->fg; 69 } else if (*in == 'b' || *in == 'B') { 70 if (val != 8) 71 bg = val; 72 else 73 bg = defgc->bg; 74 } else 75 goto error; 76 } else if (strcasecmp(tmp, "none") == 0) 77 attr = 0; 78 else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) { 79 if ((val = attributes_fromstring(tmp + 2)) == -1) 80 goto error; 81 attr &= ~val; 82 } else { 83 if ((val = attributes_fromstring(tmp)) == -1) 84 goto error; 85 attr |= val; 86 } 87 88 in += end + strspn(in + end, delimiters); 89 } while (*in != '\0'); 90 gc->fg = fg; 91 gc->bg = bg; 92 gc->attr = attr; 93 gc->flags = flags; 94 95 return (0); 96 97 error: 98 memcpy(gc, &savedgc, sizeof *gc); 99 return (-1); 100 } 101 102 /* Convert style to a string. */ 103 const char * 104 style_tostring(struct grid_cell *gc) 105 { 106 int off = 0, comma = 0; 107 static char s[256]; 108 109 *s = '\0'; 110 111 if (gc->fg != 8) { 112 off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(gc->fg)); 113 comma = 1; 114 } 115 116 if (gc->bg != 8) { 117 off += xsnprintf(s + off, sizeof s - off, "%sbg=%s", 118 comma ? "," : "", colour_tostring(gc->bg)); 119 comma = 1; 120 } 121 122 if (gc->attr != 0 && gc->attr != GRID_ATTR_CHARSET) { 123 xsnprintf(s + off, sizeof s - off, "%s%s", 124 comma ? "," : "", attributes_tostring(gc->attr)); 125 } 126 127 if (*s == '\0') 128 return ("default"); 129 return (s); 130 } 131 132 /* Synchronize new -style option with the old one. */ 133 void 134 style_update_new(struct options *oo, const char *name, const char *newname) 135 { 136 int value; 137 struct grid_cell *gc; 138 struct options_entry *o; 139 140 /* It's a colour or attribute, but with no -style equivalent. */ 141 if (newname == NULL) 142 return; 143 144 o = options_find1(oo, newname); 145 if (o == NULL) 146 o = options_set_style(oo, newname, "default", 0); 147 gc = &o->style; 148 149 o = options_find1(oo, name); 150 if (o == NULL) 151 o = options_set_number(oo, name, 8); 152 value = o->num; 153 154 if (strstr(name, "-bg") != NULL) 155 gc->bg = value; 156 else if (strstr(name, "-fg") != NULL) 157 gc->fg = value; 158 else if (strstr(name, "-attr") != NULL) 159 gc->attr = value; 160 } 161 162 /* Synchronize all the old options with the new -style one. */ 163 void 164 style_update_old(struct options *oo, const char *name, struct grid_cell *gc) 165 { 166 char newname[128]; 167 int size; 168 169 size = strrchr(name, '-') - name; 170 171 xsnprintf(newname, sizeof newname, "%.*s-bg", size, name); 172 options_set_number(oo, newname, gc->bg); 173 174 xsnprintf(newname, sizeof newname, "%.*s-fg", size, name); 175 options_set_number(oo, newname, gc->fg); 176 177 xsnprintf(newname, sizeof newname, "%.*s-attr", size, name); 178 options_set_number(oo, newname, gc->attr); 179 } 180 181 /* Apply a style. */ 182 void 183 style_apply(struct grid_cell *gc, struct options *oo, const char *name) 184 { 185 struct grid_cell *gcp; 186 187 memcpy(gc, &grid_default_cell, sizeof *gc); 188 gcp = options_get_style(oo, name); 189 gc->fg = gcp->fg; 190 gc->bg = gcp->bg; 191 gc->attr |= gcp->attr; 192 } 193 194 /* Apply a style, updating if default. */ 195 void 196 style_apply_update(struct grid_cell *gc, struct options *oo, const char *name) 197 { 198 struct grid_cell *gcp; 199 200 gcp = options_get_style(oo, name); 201 if (gcp->fg != 8) 202 gc->fg = gcp->fg; 203 if (gcp->bg != 8) 204 gc->bg = gcp->bg; 205 if (gcp->attr != 0) 206 gc->attr |= gcp->attr; 207 } 208 209 /* Check if two styles are the same. */ 210 int 211 style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2) 212 { 213 return (gc1->fg == gc2->fg && 214 gc1->bg == gc2->bg && 215 (gc1->flags & ~GRID_FLAG_PADDING) == 216 (gc2->flags & ~GRID_FLAG_PADDING) && 217 (gc1->attr & ~GRID_ATTR_CHARSET) == 218 (gc2->attr & ~GRID_ATTR_CHARSET)); 219 } 220