style.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* $OpenBSD$ */
  2. /*
  3. * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
  4. * Copyright (c) 2014 Tiago Cunha <tcunha@users.sourceforge.net>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
  15. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  16. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <sys/types.h>
  19. #include <string.h>
  20. #include "tmux.h"
  21. /* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */
  22. int
  23. style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
  24. const char *in)
  25. {
  26. struct grid_cell savedgc;
  27. const char delimiters[] = " ,";
  28. char tmp[32];
  29. int val;
  30. size_t end;
  31. u_char fg, bg, attr, flags;
  32. if (*in == '\0')
  33. return (0);
  34. if (strchr(delimiters, in[strlen(in) - 1]) != NULL)
  35. return (-1);
  36. memcpy(&savedgc, gc, sizeof savedgc);
  37. fg = gc->fg;
  38. bg = gc->bg;
  39. attr = gc->attr;
  40. flags = gc->flags;
  41. do {
  42. end = strcspn(in, delimiters);
  43. if (end > (sizeof tmp) - 1)
  44. goto error;
  45. memcpy(tmp, in, end);
  46. tmp[end] = '\0';
  47. if (strcasecmp(tmp, "default") == 0) {
  48. fg = defgc->fg;
  49. bg = defgc->bg;
  50. attr = defgc->attr;
  51. flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
  52. flags |=
  53. defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
  54. } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
  55. if ((val = colour_fromstring(tmp + 3)) == -1)
  56. goto error;
  57. if (*in == 'f' || *in == 'F') {
  58. if (val != 8) {
  59. if (val & 0x100) {
  60. flags |= GRID_FLAG_FG256;
  61. val &= ~0x100;
  62. } else
  63. flags &= ~GRID_FLAG_FG256;
  64. fg = val;
  65. } else {
  66. fg = defgc->fg;
  67. flags &= ~GRID_FLAG_FG256;
  68. flags |= defgc->flags & GRID_FLAG_FG256;
  69. }
  70. } else if (*in == 'b' || *in == 'B') {
  71. if (val != 8) {
  72. if (val & 0x100) {
  73. flags |= GRID_FLAG_BG256;
  74. val &= ~0x100;
  75. } else
  76. flags &= ~GRID_FLAG_BG256;
  77. bg = val;
  78. } else {
  79. bg = defgc->bg;
  80. flags &= ~GRID_FLAG_BG256;
  81. flags |= defgc->flags & GRID_FLAG_BG256;
  82. }
  83. } else
  84. goto error;
  85. } else if (strcasecmp(tmp, "none") == 0)
  86. attr = 0;
  87. else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
  88. if ((val = attributes_fromstring(tmp + 2)) == -1)
  89. goto error;
  90. attr &= ~val;
  91. } else {
  92. if ((val = attributes_fromstring(tmp)) == -1)
  93. goto error;
  94. attr |= val;
  95. }
  96. in += end + strspn(in + end, delimiters);
  97. } while (*in != '\0');
  98. gc->fg = fg;
  99. gc->bg = bg;
  100. gc->attr = attr;
  101. gc->flags = flags;
  102. return (0);
  103. error:
  104. memcpy(gc, &savedgc, sizeof *gc);
  105. return (-1);
  106. }
  107. /* Convert style to a string. */
  108. const char *
  109. style_tostring(struct grid_cell *gc)
  110. {
  111. int c, off = 0, comma = 0;
  112. static char s[256];
  113. *s = '\0';
  114. if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
  115. if (gc->flags & GRID_FLAG_FG256)
  116. c = gc->fg | 0x100;
  117. else
  118. c = gc->fg;
  119. off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
  120. comma = 1;
  121. }
  122. if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
  123. if (gc->flags & GRID_FLAG_BG256)
  124. c = gc->bg | 0x100;
  125. else
  126. c = gc->bg;
  127. off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
  128. comma ? "," : "", colour_tostring(c));
  129. comma = 1;
  130. }
  131. if (gc->attr != 0 && gc->attr != GRID_ATTR_CHARSET) {
  132. xsnprintf(s + off, sizeof s - off, "%s%s",
  133. comma ? "," : "", attributes_tostring(gc->attr));
  134. }
  135. if (*s == '\0')
  136. return ("default");
  137. return (s);
  138. }
  139. /* Synchronize new -style option with the old one. */
  140. void
  141. style_update_new(struct options *oo, const char *name, const char *newname)
  142. {
  143. int value;
  144. struct grid_cell *gc;
  145. struct options_entry *o;
  146. /* It's a colour or attribute, but with no -style equivalent. */
  147. if (newname == NULL)
  148. return;
  149. o = options_find1(oo, newname);
  150. if (o == NULL)
  151. o = options_set_style(oo, newname, "default", 0);
  152. gc = &o->style;
  153. o = options_find1(oo, name);
  154. if (o == NULL)
  155. o = options_set_number(oo, name, 8);
  156. value = o->num;
  157. if (strstr(name, "-bg") != NULL)
  158. colour_set_bg(gc, value);
  159. else if (strstr(name, "-fg") != NULL)
  160. colour_set_fg(gc, value);
  161. else if (strstr(name, "-attr") != NULL)
  162. gc->attr = value;
  163. }
  164. /* Synchronize all the old options with the new -style one. */
  165. void
  166. style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
  167. {
  168. char newname[128];
  169. int c, size;
  170. size = strrchr(name, '-') - name;
  171. if (gc->flags & GRID_FLAG_BG256)
  172. c = gc->bg | 0x100;
  173. else
  174. c = gc->bg;
  175. xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
  176. options_set_number(oo, newname, c);
  177. if (gc->flags & GRID_FLAG_FG256)
  178. c = gc->fg | 0x100;
  179. else
  180. c = gc->fg;
  181. xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
  182. options_set_number(oo, newname, c);
  183. xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
  184. options_set_number(oo, newname, gc->attr);
  185. }
  186. /* Apply a style. */
  187. void
  188. style_apply(struct grid_cell *gc, struct options *oo, const char *name)
  189. {
  190. struct grid_cell *gcp;
  191. memcpy(gc, &grid_default_cell, sizeof *gc);
  192. gcp = options_get_style(oo, name);
  193. if (gcp->flags & GRID_FLAG_FG256)
  194. colour_set_fg(gc, gcp->fg | 0x100);
  195. else
  196. colour_set_fg(gc, gcp->fg);
  197. if (gcp->flags & GRID_FLAG_BG256)
  198. colour_set_bg(gc, gcp->bg | 0x100);
  199. else
  200. colour_set_bg(gc, gcp->bg);
  201. gc->attr |= gcp->attr;
  202. }
  203. /* Apply a style, updating if default. */
  204. void
  205. style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
  206. {
  207. struct grid_cell *gcp;
  208. gcp = options_get_style(oo, name);
  209. if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) {
  210. if (gcp->flags & GRID_FLAG_FG256)
  211. colour_set_fg(gc, gcp->fg | 0x100);
  212. else
  213. colour_set_fg(gc, gcp->fg);
  214. }
  215. if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) {
  216. if (gcp->flags & GRID_FLAG_BG256)
  217. colour_set_bg(gc, gcp->bg | 0x100);
  218. else
  219. colour_set_bg(gc, gcp->bg);
  220. }
  221. if (gcp->attr != 0)
  222. gc->attr |= gcp->attr;
  223. }
  224. /* Check if two styles are the same. */
  225. int
  226. style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
  227. {
  228. return gc1->fg == gc2->fg &&
  229. gc1->bg == gc2->bg &&
  230. (gc1->flags & ~GRID_FLAG_PADDING) ==
  231. (gc2->flags & ~GRID_FLAG_PADDING) &&
  232. (gc1->attr & ~GRID_ATTR_CHARSET) ==
  233. (gc2->attr & ~GRID_ATTR_CHARSET);
  234. }