1 /* $OpenBSD: style.c,v 1.13 2017/01/15 20:48:41 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 /* Apply a style. */ 133 void 134 style_apply(struct grid_cell *gc, struct options *oo, const char *name) 135 { 136 const struct grid_cell *gcp; 137 138 memcpy(gc, &grid_default_cell, sizeof *gc); 139 gcp = options_get_style(oo, name); 140 gc->fg = gcp->fg; 141 gc->bg = gcp->bg; 142 gc->attr |= gcp->attr; 143 } 144 145 /* Apply a style, updating if default. */ 146 void 147 style_apply_update(struct grid_cell *gc, struct options *oo, const char *name) 148 { 149 const struct grid_cell *gcp; 150 151 gcp = options_get_style(oo, name); 152 if (gcp->fg != 8) 153 gc->fg = gcp->fg; 154 if (gcp->bg != 8) 155 gc->bg = gcp->bg; 156 if (gcp->attr != 0) 157 gc->attr |= gcp->attr; 158 } 159 160 /* Check if two styles are the same. */ 161 int 162 style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2) 163 { 164 return (gc1->fg == gc2->fg && 165 gc1->bg == gc2->bg && 166 (gc1->flags & ~GRID_FLAG_PADDING) == 167 (gc2->flags & ~GRID_FLAG_PADDING) && 168 (gc1->attr & ~GRID_ATTR_CHARSET) == 169 (gc2->attr & ~GRID_ATTR_CHARSET)); 170 } 171