1 /* $OpenBSD: style.c,v 1.14 2017/03/22 07:16:54 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, fg, bg, attr, flags; 35 size_t end; 36 37 if (*in == '\0') 38 return (0); 39 if (strchr(delimiters, in[strlen(in) - 1]) != NULL) 40 return (-1); 41 memcpy(&savedgc, gc, sizeof savedgc); 42 43 fg = gc->fg; 44 bg = gc->bg; 45 attr = gc->attr; 46 flags = gc->flags; 47 do { 48 end = strcspn(in, delimiters); 49 if (end > (sizeof tmp) - 1) 50 goto error; 51 memcpy(tmp, in, end); 52 tmp[end] = '\0'; 53 54 if (strcasecmp(tmp, "default") == 0) { 55 fg = defgc->fg; 56 bg = defgc->bg; 57 attr = defgc->attr; 58 flags = defgc->flags; 59 } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) { 60 if ((val = colour_fromstring(tmp + 3)) == -1) 61 goto error; 62 if (*in == 'f' || *in == 'F') { 63 if (val != 8) 64 fg = val; 65 else 66 fg = defgc->fg; 67 } else if (*in == 'b' || *in == 'B') { 68 if (val != 8) 69 bg = val; 70 else 71 bg = defgc->bg; 72 } else 73 goto error; 74 } else if (strcasecmp(tmp, "none") == 0) 75 attr = 0; 76 else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) { 77 if ((val = attributes_fromstring(tmp + 2)) == -1) 78 goto error; 79 attr &= ~val; 80 } else { 81 if ((val = attributes_fromstring(tmp)) == -1) 82 goto error; 83 attr |= val; 84 } 85 86 in += end + strspn(in + end, delimiters); 87 } while (*in != '\0'); 88 gc->fg = fg; 89 gc->bg = bg; 90 gc->attr = attr; 91 gc->flags = flags; 92 93 return (0); 94 95 error: 96 memcpy(gc, &savedgc, sizeof *gc); 97 return (-1); 98 } 99 100 /* Convert style to a string. */ 101 const char * 102 style_tostring(struct grid_cell *gc) 103 { 104 int off = 0, comma = 0; 105 static char s[256]; 106 107 *s = '\0'; 108 109 if (gc->fg != 8) { 110 off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(gc->fg)); 111 comma = 1; 112 } 113 114 if (gc->bg != 8) { 115 off += xsnprintf(s + off, sizeof s - off, "%sbg=%s", 116 comma ? "," : "", colour_tostring(gc->bg)); 117 comma = 1; 118 } 119 120 if (gc->attr != 0 && gc->attr != GRID_ATTR_CHARSET) { 121 xsnprintf(s + off, sizeof s - off, "%s%s", 122 comma ? "," : "", attributes_tostring(gc->attr)); 123 } 124 125 if (*s == '\0') 126 return ("default"); 127 return (s); 128 } 129 130 /* Apply a style. */ 131 void 132 style_apply(struct grid_cell *gc, struct options *oo, const char *name) 133 { 134 const struct grid_cell *gcp; 135 136 memcpy(gc, &grid_default_cell, sizeof *gc); 137 gcp = options_get_style(oo, name); 138 gc->fg = gcp->fg; 139 gc->bg = gcp->bg; 140 gc->attr |= gcp->attr; 141 } 142 143 /* Apply a style, updating if default. */ 144 void 145 style_apply_update(struct grid_cell *gc, struct options *oo, const char *name) 146 { 147 const struct grid_cell *gcp; 148 149 gcp = options_get_style(oo, name); 150 if (gcp->fg != 8) 151 gc->fg = gcp->fg; 152 if (gcp->bg != 8) 153 gc->bg = gcp->bg; 154 if (gcp->attr != 0) 155 gc->attr |= gcp->attr; 156 } 157 158 /* Check if two styles are the same. */ 159 int 160 style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2) 161 { 162 return (gc1->fg == gc2->fg && 163 gc1->bg == gc2->bg && 164 (gc1->flags & ~GRID_FLAG_PADDING) == 165 (gc2->flags & ~GRID_FLAG_PADDING) && 166 (gc1->attr & ~GRID_ATTR_CHARSET) == 167 (gc2->attr & ~GRID_ATTR_CHARSET)); 168 } 169