options.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* $OpenBSD$ */
  2. /*
  3. * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
  14. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  15. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/types.h>
  18. #include <stdarg.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "tmux.h"
  22. /*
  23. * Option handling; each option has a name, type and value and is stored in
  24. * a red-black tree.
  25. */
  26. struct options {
  27. RB_HEAD(options_tree, options_entry) tree;
  28. struct options *parent;
  29. };
  30. static int options_cmp(struct options_entry *, struct options_entry *);
  31. RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
  32. RB_GENERATE(options_tree, options_entry, entry, options_cmp);
  33. static void options_free1(struct options *, struct options_entry *);
  34. static int
  35. options_cmp(struct options_entry *o1, struct options_entry *o2)
  36. {
  37. return (strcmp(o1->name, o2->name));
  38. }
  39. struct options *
  40. options_create(struct options *parent)
  41. {
  42. struct options *oo;
  43. oo = xcalloc(1, sizeof *oo);
  44. RB_INIT(&oo->tree);
  45. oo->parent = parent;
  46. return (oo);
  47. }
  48. static void
  49. options_free1(struct options *oo, struct options_entry *o)
  50. {
  51. RB_REMOVE(options_tree, &oo->tree, o);
  52. free((char *)o->name);
  53. if (o->type == OPTIONS_STRING)
  54. free(o->str);
  55. free(o);
  56. }
  57. void
  58. options_free(struct options *oo)
  59. {
  60. struct options_entry *o, *o1;
  61. RB_FOREACH_SAFE (o, options_tree, &oo->tree, o1)
  62. options_free1(oo, o);
  63. free(oo);
  64. }
  65. struct options_entry *
  66. options_first(struct options *oo)
  67. {
  68. return (RB_MIN(options_tree, &oo->tree));
  69. }
  70. struct options_entry *
  71. options_next(struct options_entry *o)
  72. {
  73. return (RB_NEXT(options_tree, &oo->tree, o));
  74. }
  75. struct options_entry *
  76. options_find1(struct options *oo, const char *name)
  77. {
  78. struct options_entry p;
  79. p.name = (char *)name;
  80. return (RB_FIND(options_tree, &oo->tree, &p));
  81. }
  82. struct options_entry *
  83. options_find(struct options *oo, const char *name)
  84. {
  85. struct options_entry *o, p;
  86. p.name = (char *)name;
  87. o = RB_FIND(options_tree, &oo->tree, &p);
  88. while (o == NULL) {
  89. oo = oo->parent;
  90. if (oo == NULL)
  91. break;
  92. o = RB_FIND(options_tree, &oo->tree, &p);
  93. }
  94. return (o);
  95. }
  96. void
  97. options_remove(struct options *oo, const char *name)
  98. {
  99. struct options_entry *o;
  100. if ((o = options_find1(oo, name)) != NULL)
  101. options_free1(oo, o);
  102. }
  103. struct options_entry *
  104. options_set_string(struct options *oo, const char *name, const char *fmt, ...)
  105. {
  106. struct options_entry *o;
  107. va_list ap;
  108. if ((o = options_find1(oo, name)) == NULL) {
  109. o = xmalloc(sizeof *o);
  110. o->name = xstrdup(name);
  111. RB_INSERT(options_tree, &oo->tree, o);
  112. memcpy(&o->style, &grid_default_cell, sizeof o->style);
  113. } else if (o->type == OPTIONS_STRING)
  114. free(o->str);
  115. va_start(ap, fmt);
  116. o->type = OPTIONS_STRING;
  117. xvasprintf(&o->str, fmt, ap);
  118. va_end(ap);
  119. return (o);
  120. }
  121. char *
  122. options_get_string(struct options *oo, const char *name)
  123. {
  124. struct options_entry *o;
  125. if ((o = options_find(oo, name)) == NULL)
  126. fatalx("missing option %s", name);
  127. if (o->type != OPTIONS_STRING)
  128. fatalx("option %s not a string", name);
  129. return (o->str);
  130. }
  131. struct options_entry *
  132. options_set_number(struct options *oo, const char *name, long long value)
  133. {
  134. struct options_entry *o;
  135. if ((o = options_find1(oo, name)) == NULL) {
  136. o = xmalloc(sizeof *o);
  137. o->name = xstrdup(name);
  138. RB_INSERT(options_tree, &oo->tree, o);
  139. memcpy(&o->style, &grid_default_cell, sizeof o->style);
  140. } else if (o->type == OPTIONS_STRING)
  141. free(o->str);
  142. o->type = OPTIONS_NUMBER;
  143. o->num = value;
  144. return (o);
  145. }
  146. long long
  147. options_get_number(struct options *oo, const char *name)
  148. {
  149. struct options_entry *o;
  150. if ((o = options_find(oo, name)) == NULL)
  151. fatalx("missing option %s", name);
  152. if (o->type != OPTIONS_NUMBER)
  153. fatalx("option %s not a number", name);
  154. return (o->num);
  155. }
  156. struct options_entry *
  157. options_set_style(struct options *oo, const char *name, const char *value,
  158. int append)
  159. {
  160. struct options_entry *o;
  161. struct grid_cell tmpgc;
  162. o = options_find1(oo, name);
  163. if (o == NULL || !append)
  164. memcpy(&tmpgc, &grid_default_cell, sizeof tmpgc);
  165. else
  166. memcpy(&tmpgc, &o->style, sizeof tmpgc);
  167. if (style_parse(&grid_default_cell, &tmpgc, value) == -1)
  168. return (NULL);
  169. if (o == NULL) {
  170. o = xmalloc(sizeof *o);
  171. o->name = xstrdup(name);
  172. RB_INSERT(options_tree, &oo->tree, o);
  173. } else if (o->type == OPTIONS_STRING)
  174. free(o->str);
  175. o->type = OPTIONS_STYLE;
  176. memcpy(&o->style, &tmpgc, sizeof o->style);
  177. return (o);
  178. }
  179. struct grid_cell *
  180. options_get_style(struct options *oo, const char *name)
  181. {
  182. struct options_entry *o;
  183. if ((o = options_find(oo, name)) == NULL)
  184. fatalx("missing option %s", name);
  185. if (o->type != OPTIONS_STYLE)
  186. fatalx("option %s not a style", name);
  187. return (&o->style);
  188. }