NeoMutt  2020-09-25
Teaching an old dog new tricks
DOXYGEN
set.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <limits.h>
31 #include <stdio.h>
32 #include "mutt/lib.h"
33 #include "set.h"
34 #include "inheritance.h"
35 #include "types.h"
36 
37 struct ConfigSetType RegisteredTypes[18] = {
38  { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
39 };
40 
47 static void destroy(int type, void *obj, intptr_t data)
48 {
49  if (!obj || (data == 0))
50  return; /* LCOV_EXCL_LINE */
51 
52  struct ConfigSet *cs = (struct ConfigSet *) data;
53 
54  const struct ConfigSetType *cst = NULL;
55 
56  if (type & DT_INHERITED)
57  {
58  struct Inheritance *i = obj;
59 
60  struct HashElem *he_base = cs_get_base(i->parent);
61  struct ConfigDef *cdef = he_base->data;
62 
63  if (!cdef)
64  return; // LCOV_EXCL_LINE
65 
66  cst = cs_get_type_def(cs, he_base->type);
67  if (cst && cst->destroy)
68  cst->destroy(cs, (void **) &i->var, cdef);
69 
70  FREE(&i->name);
71  FREE(&i);
72  }
73  else
74  {
75  struct ConfigDef *cdef = obj;
76 
77  cst = cs_get_type_def(cs, type);
78  if (cst && cst->destroy)
79  {
80  if (cdef->type & DT_NO_VARIABLE)
81  cst->destroy(cs, &cdef->var, cdef);
82  else if (cdef->var)
83  cst->destroy(cs, cdef->var, cdef);
84  }
85 
86  /* If we allocated the initial value, clean it up */
87  if (cdef->type & DT_INITIAL_SET)
88  FREE(&cdef->initial);
89  }
90 }
91 
99 static struct HashElem *create_synonym(const struct ConfigSet *cs,
100  struct ConfigDef *cdef, struct Buffer *err)
101 {
102  if (!cs || !cdef)
103  return NULL; /* LCOV_EXCL_LINE */
104 
105  const char *name = (const char *) cdef->initial;
106  struct HashElem *parent = cs_get_elem(cs, name);
107  if (!parent)
108  {
109  mutt_buffer_printf(err, _("No such variable: %s"), name);
110  return NULL;
111  }
112 
113  struct HashElem *child =
114  mutt_hash_typed_insert(cs->hash, cdef->name, cdef->type, (void *) cdef);
115  if (!child)
116  return NULL; /* LCOV_EXCL_LINE */
117 
118  cdef->var = parent;
119  return child;
120 }
121 
129 static struct HashElem *reg_one_var(const struct ConfigSet *cs,
130  struct ConfigDef *cdef, struct Buffer *err)
131 {
132  if (!cs || !cdef)
133  return NULL; /* LCOV_EXCL_LINE */
134 
135  if (DTYPE(cdef->type) == DT_SYNONYM)
136  return create_synonym(cs, cdef, err);
137 
138  const struct ConfigSetType *cst = cs_get_type_def(cs, cdef->type);
139  if (!cst)
140  {
141  mutt_buffer_printf(err, _("Variable '%s' has an invalid type %d"),
142  cdef->name, cdef->type);
143  return NULL;
144  }
145 
146  struct HashElem *he = mutt_hash_typed_insert(cs->hash, cdef->name, cdef->type, cdef);
147  if (!he)
148  return NULL; /* LCOV_EXCL_LINE */
149 
150  if (cst && cst->reset)
151  {
152  if (cdef->type & DT_NO_VARIABLE)
153  cst->reset(cs, &cdef->var, cdef, err);
154  else if (cdef->var)
155  cst->reset(cs, cdef->var, cdef, err);
156  }
157 
158  return he;
159 }
160 
166 struct ConfigSet *cs_new(size_t size)
167 {
168  struct ConfigSet *cs = mutt_mem_calloc(1, sizeof(*cs));
169 
171  mutt_hash_set_destructor(cs->hash, destroy, (intptr_t) cs);
172 
173  return cs;
174 }
175 
180 void cs_free(struct ConfigSet **ptr)
181 {
182  if (!ptr || !*ptr)
183  return;
184 
185  struct ConfigSet *cs = *ptr;
186 
187  mutt_hash_free(&cs->hash);
188  FREE(ptr);
189 }
190 
199 struct HashElem *cs_get_base(struct HashElem *he)
200 {
201  if (!(he->type & DT_INHERITED))
202  return he;
203 
204  struct Inheritance *i = he->data;
205  return cs_get_base(i->parent);
206 }
207 
214 struct HashElem *cs_get_elem(const struct ConfigSet *cs, const char *name)
215 {
216  if (!cs || !name)
217  return NULL;
218 
219  struct HashElem *he = mutt_hash_find_elem(cs->hash, name);
220  if (!he)
221  return NULL;
222 
223  if (DTYPE(he->type) != DT_SYNONYM)
224  return he;
225 
226  const struct ConfigDef *cdef = he->data;
227 
228  return cdef->var;
229 }
230 
237 const struct ConfigSetType *cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
238 {
239  if (!cs)
240  return NULL;
241 
242  type = DTYPE(type);
243  if ((type < 1) || (type >= mutt_array_size(cs->types)))
244  return NULL;
245 
246  if (!cs->types[type].name)
247  return NULL;
248 
249  return &cs->types[type];
250 }
251 
258 bool cs_register_type(struct ConfigSet *cs, const struct ConfigSetType *cst)
259 {
260  if (!cs || !cst)
261  return false;
262 
263  if (!cst->name || !cst->string_set || !cst->string_get || !cst->reset ||
264  !cst->native_set || !cst->native_get)
265  {
266  return false;
267  }
268 
269  if (cst->type >= mutt_array_size(cs->types))
270  return false;
271 
272  if (cs->types[cst->type].name)
273  return false; /* already registered */
274 
275  cs->types[cst->type] = *cst;
276  return true;
277 }
278 
286 bool cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], int flags)
287 {
288  if (!cs || !vars)
289  return false;
290 
291  struct Buffer err = mutt_buffer_make(0);
292 
293  bool rc = true;
294 
295  for (size_t i = 0; vars[i].name; i++)
296  {
297  vars[i].type |= flags;
298  if (!reg_one_var(cs, &vars[i], &err))
299  {
300  mutt_debug(LL_DEBUG1, "%s\n", mutt_b2s(&err));
301  rc = false;
302  }
303  }
304 
305  mutt_buffer_dealloc(&err);
306  return rc;
307 }
308 
316 struct HashElem *cs_inherit_variable(const struct ConfigSet *cs,
317  struct HashElem *parent, const char *name)
318 {
319  if (!cs || !parent)
320  return NULL;
321 
322  struct Inheritance *i = mutt_mem_calloc(1, sizeof(*i));
323  i->parent = parent;
324  i->name = mutt_str_dup(name);
325 
326  struct HashElem *he = mutt_hash_typed_insert(cs->hash, i->name, DT_INHERITED, i);
327  if (!he)
328  {
329  FREE(&i->name);
330  FREE(&i);
331  }
332 
333  return he;
334 }
335 
341 void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
342 {
343  if (!cs || !name)
344  return;
345 
346  mutt_hash_delete(cs->hash, name, NULL);
347 }
348 
356 int cs_he_reset(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
357 {
358  if (!cs || !he)
359  return CSR_ERR_CODE;
360 
361  /* An inherited var that's already pointing to its parent.
362  * Return 'success', but don't send a notification. */
363  if ((he->type & DT_INHERITED) && (DTYPE(he->type) == 0))
364  return CSR_SUCCESS;
365 
366  int rc = CSR_SUCCESS;
367 
368  if (he->type & DT_INHERITED)
369  {
370  struct Inheritance *i = he->data;
371  struct HashElem *he_base = cs_get_base(he);
372  struct ConfigDef *cdef = he_base->data;
373  if (!cdef)
374  return CSR_ERR_CODE; // LCOV_EXCL_LINE
375 
376  const struct ConfigSetType *cst = cs_get_type_def(cs, he_base->type);
377  if (cst && cst->destroy)
378  cst->destroy(cs, (void **) &i->var, cdef);
379 
380  he->type = DT_INHERITED;
381  }
382  else
383  {
384  struct ConfigDef *cdef = he->data;
385  if (!cdef)
386  return CSR_ERR_CODE; // LCOV_EXCL_LINE
387 
388  const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
389  if (cst)
390  {
391  if (cdef->type & DT_NO_VARIABLE)
392  rc = cst->reset(cs, &cdef->var, cdef, err);
393  else if (cdef->var)
394  rc = cst->reset(cs, cdef->var, cdef, err);
395  }
396  }
397 
398  return rc;
399 }
400 
408 int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
409 {
410  if (!cs || !name)
411  return CSR_ERR_CODE;
412 
413  struct HashElem *he = cs_get_elem(cs, name);
414  if (!he)
415  {
416  mutt_buffer_printf(err, _("Unknown variable '%s'"), name);
417  return CSR_ERR_UNKNOWN;
418  }
419 
420  return cs_he_reset(cs, he, err);
421 }
422 
431 int cs_he_initial_set(const struct ConfigSet *cs, struct HashElem *he,
432  const char *value, struct Buffer *err)
433 {
434  if (!cs || !he)
435  return CSR_ERR_CODE;
436 
437  struct ConfigDef *cdef = NULL;
438 
439  if (he->type & DT_INHERITED)
440  {
441  struct HashElem *he_base = cs_get_base(he);
442  cdef = he_base->data;
443  mutt_debug(LL_DEBUG1, "Variable '%s' is inherited type\n", cdef->name);
444  return CSR_ERR_CODE;
445  }
446 
447  cdef = he->data;
448  if (!cdef)
449  return CSR_ERR_CODE; // LCOV_EXCL_LINE
450 
451  const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
452  if (!cst)
453  {
454  mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
455  return CSR_ERR_CODE;
456  }
457 
458  int rc = cst->string_set(cs, NULL, cdef, value, err);
459  if (CSR_RESULT(rc) != CSR_SUCCESS)
460  return rc;
461 
462  return CSR_SUCCESS;
463 }
464 
473 int cs_str_initial_set(const struct ConfigSet *cs, const char *name,
474  const char *value, struct Buffer *err)
475 {
476  if (!cs || !name)
477  return CSR_ERR_CODE;
478 
479  struct HashElem *he = cs_get_elem(cs, name);
480  if (!he)
481  {
482  mutt_buffer_printf(err, _("Unknown variable '%s'"), name);
483  return CSR_ERR_UNKNOWN;
484  }
485 
486  return cs_he_initial_set(cs, he, value, err);
487 }
488 
499 int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
500 {
501  if (!cs || !he || !result)
502  return CSR_ERR_CODE;
503 
504  const struct ConfigDef *cdef = NULL;
505  const struct ConfigSetType *cst = NULL;
506 
507  if (he->type & DT_INHERITED)
508  {
509  struct HashElem *he_base = cs_get_base(he);
510  cdef = he_base->data;
511  cst = cs_get_type_def(cs, he_base->type);
512  }
513  else
514  {
515  cdef = he->data;
516  cst = cs_get_type_def(cs, he->type);
517  }
518 
519  if (!cst)
520  return CSR_ERR_CODE; // LCOV_EXCL_LINE
521 
522  return cst->string_get(cs, NULL, cdef, result);
523 }
524 
535 int cs_str_initial_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
536 {
537  if (!cs || !name)
538  return CSR_ERR_CODE;
539 
540  struct HashElem *he = cs_get_elem(cs, name);
541  if (!he)
542  {
543  mutt_buffer_printf(result, _("Unknown variable '%s'"), name);
544  return CSR_ERR_UNKNOWN;
545  }
546 
547  return cs_he_initial_get(cs, he, result);
548 }
549 
558 int cs_he_string_set(const struct ConfigSet *cs, struct HashElem *he,
559  const char *value, struct Buffer *err)
560 {
561  if (!cs || !he)
562  return CSR_ERR_CODE;
563 
564  struct ConfigDef *cdef = NULL;
565  const struct ConfigSetType *cst = NULL;
566  void *var = NULL;
567 
568  if (he->type & DT_INHERITED)
569  {
570  struct Inheritance *i = he->data;
571  struct HashElem *he_base = cs_get_base(he);
572  cdef = he_base->data;
573  cst = cs_get_type_def(cs, he_base->type);
574  var = &i->var;
575  }
576  else
577  {
578  cdef = he->data;
579  cst = cs_get_type_def(cs, he->type);
580  if (cdef->type & DT_NO_VARIABLE)
581  var = &cdef->var;
582  else
583  var = cdef->var;
584  }
585 
586  if (!cdef)
587  return CSR_ERR_CODE; // LCOV_EXCL_LINE
588 
589  if (!cst)
590  {
591  mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
592  return CSR_ERR_CODE;
593  }
594 
595  int rc = cst->string_set(cs, var, cdef, value, err);
596  if (CSR_RESULT(rc) != CSR_SUCCESS)
597  return rc;
598 
599  if (he->type & DT_INHERITED)
600  he->type = cdef->type | DT_INHERITED;
601 
602  return rc;
603 }
604 
613 int cs_str_string_set(const struct ConfigSet *cs, const char *name,
614  const char *value, struct Buffer *err)
615 {
616  if (!cs || !name)
617  return CSR_ERR_CODE;
618 
619  struct HashElem *he = cs_get_elem(cs, name);
620  if (!he)
621  {
622  mutt_buffer_printf(err, _("Unknown variable '%s'"), name);
623  return CSR_ERR_UNKNOWN;
624  }
625 
626  return cs_he_string_set(cs, he, value, err);
627 }
628 
636 int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
637 {
638  if (!cs || !he || !result)
639  return CSR_ERR_CODE;
640 
641  struct ConfigDef *cdef = NULL;
642  const struct ConfigSetType *cst = NULL;
643  void *var = NULL;
644 
645  if (he->type & DT_INHERITED)
646  {
647  struct Inheritance *i = he->data;
648 
649  // inherited, value not set
650  if (DTYPE(he->type) == 0)
651  return cs_he_string_get(cs, i->parent, result);
652 
653  // inherited, value set
654  struct HashElem *he_base = cs_get_base(he);
655  cdef = he_base->data;
656  cst = cs_get_type_def(cs, he_base->type);
657  var = &i->var;
658  }
659  else
660  {
661  // not inherited
662  cdef = he->data;
663  cst = cs_get_type_def(cs, he->type);
664  if (cdef->type & DT_NO_VARIABLE)
665  var = &cdef->var;
666  else
667  var = cdef->var;
668  }
669 
670  if (!cdef || !cst)
671  return CSR_ERR_CODE; // LCOV_EXCL_LINE
672 
673  return cst->string_get(cs, var, cdef, result);
674 }
675 
683 int cs_str_string_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
684 {
685  if (!cs || !name)
686  return CSR_ERR_CODE;
687 
688  struct HashElem *he = cs_get_elem(cs, name);
689  if (!he)
690  {
691  mutt_buffer_printf(result, _("Unknown variable '%s'"), name);
692  return CSR_ERR_UNKNOWN;
693  }
694 
695  return cs_he_string_get(cs, he, result);
696 }
697 
706 int cs_he_native_set(const struct ConfigSet *cs, struct HashElem *he,
707  intptr_t value, struct Buffer *err)
708 {
709  if (!cs || !he)
710  return CSR_ERR_CODE;
711 
712  struct ConfigDef *cdef = NULL;
713  const struct ConfigSetType *cst = NULL;
714  void *var = NULL;
715 
716  if (he->type & DT_INHERITED)
717  {
718  struct Inheritance *i = he->data;
719  struct HashElem *he_base = cs_get_base(he);
720  cdef = he_base->data;
721  cst = cs_get_type_def(cs, he_base->type);
722  var = &i->var;
723  }
724  else
725  {
726  cdef = he->data;
727  cst = cs_get_type_def(cs, he->type);
728  if (cdef->type & DT_NO_VARIABLE)
729  var = &cdef->var;
730  else
731  var = cdef->var;
732  }
733 
734  if (!cst)
735  {
736  mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
737  return CSR_ERR_CODE;
738  }
739 
740  if (!var || !cdef)
741  return CSR_ERR_CODE; // LCOV_EXCL_LINE
742 
743  int rc = cst->native_set(cs, var, cdef, value, err);
744  if (CSR_RESULT(rc) != CSR_SUCCESS)
745  return rc;
746 
747  if (he->type & DT_INHERITED)
748  he->type = cdef->type | DT_INHERITED;
749 
750  return rc;
751 }
752 
761 int cs_str_native_set(const struct ConfigSet *cs, const char *name,
762  intptr_t value, struct Buffer *err)
763 {
764  if (!cs || !name)
765  return CSR_ERR_CODE;
766 
767  struct HashElem *he = cs_get_elem(cs, name);
768  if (!he)
769  {
770  mutt_buffer_printf(err, _("Unknown variable '%s'"), name);
771  return CSR_ERR_UNKNOWN;
772  }
773 
774  struct ConfigDef *cdef = NULL;
775  const struct ConfigSetType *cst = NULL;
776  void *var = NULL;
777 
778  if (he->type & DT_INHERITED)
779  {
780  struct Inheritance *i = he->data;
781  struct HashElem *he_base = cs_get_base(he);
782  cdef = he_base->data;
783  cst = cs_get_type_def(cs, he_base->type);
784  var = &i->var;
785  }
786  else
787  {
788  cdef = he->data;
789  cst = cs_get_type_def(cs, he->type);
790  if (cdef->type & DT_NO_VARIABLE)
791  var = &cdef->var;
792  else
793  var = cdef->var;
794  }
795 
796  if (!cst || !var || !cdef)
797  return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
798 
799  int rc = cst->native_set(cs, var, cdef, value, err);
800  if (CSR_RESULT(rc) != CSR_SUCCESS)
801  return rc;
802 
803  if (he->type & DT_INHERITED)
804  he->type = cdef->type | DT_INHERITED;
805 
806  return rc;
807 }
808 
817 intptr_t cs_he_native_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
818 {
819  if (!cs || !he)
820  return INT_MIN;
821 
822  struct ConfigDef *cdef = NULL;
823  const struct ConfigSetType *cst = NULL;
824  void *var = NULL;
825 
826  if (he->type & DT_INHERITED)
827  {
828  struct Inheritance *i = he->data;
829 
830  // inherited, value not set
831  if (DTYPE(he->type) == 0)
832  return cs_he_native_get(cs, i->parent, err);
833 
834  // inherited, value set
835  struct HashElem *he_base = cs_get_base(he);
836  cdef = he_base->data;
837  cst = cs_get_type_def(cs, he_base->type);
838  var = &i->var;
839  }
840  else
841  {
842  // not inherited
843  cdef = he->data;
844  cst = cs_get_type_def(cs, he->type);
845  if (cdef->type & DT_NO_VARIABLE)
846  var = &cdef->var;
847  else
848  var = cdef->var;
849  }
850 
851  if (!var || !cdef)
852  return INT_MIN; // LCOV_EXCL_LINE
853 
854  if (!cst)
855  {
856  mutt_buffer_printf(err, _("Variable '%s' has an invalid type %d"), cdef->name, he->type);
857  return INT_MIN;
858  }
859 
860  return cst->native_get(cs, var, cdef, err);
861 }
862 
871 intptr_t cs_str_native_get(const struct ConfigSet *cs, const char *name, struct Buffer *err)
872 {
873  if (!cs || !name)
874  return INT_MIN;
875 
876  struct HashElem *he = cs_get_elem(cs, name);
877  return cs_he_native_get(cs, he, err);
878 }
879 
888 int cs_he_string_plus_equals(const struct ConfigSet *cs, struct HashElem *he,
889  const char *value, struct Buffer *err)
890 {
891  if (!cs || !he)
892  return CSR_ERR_CODE;
893 
894  struct ConfigDef *cdef = NULL;
895  const struct ConfigSetType *cst = NULL;
896  void *var = NULL;
897 
898  if (he->type & DT_INHERITED)
899  {
900  struct Inheritance *i = he->data;
901  struct HashElem *he_base = cs_get_base(he);
902  cdef = he_base->data;
903  cst = cs_get_type_def(cs, he_base->type);
904  var = &i->var;
905  }
906  else
907  {
908  cdef = he->data;
909  cst = cs_get_type_def(cs, he->type);
910  if (cdef->type & DT_NO_VARIABLE)
911  var = &cdef->var;
912  else
913  var = cdef->var;
914  }
915 
916  if (!var || !cdef)
917  return INT_MIN; // LCOV_EXCL_LINE
918 
919  if (!cst)
920  {
921  mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
922  return CSR_ERR_CODE;
923  }
924 
925  if (!cst->string_plus_equals)
926  {
927  // L10N: e.g. Type 'boolean' doesn't support operation '+='
928  mutt_buffer_printf(err, _("Type '%s' doesn't support operation '%s'"), cst->name, "+=");
930  }
931 
932  int rc = cst->string_plus_equals(cs, var, cdef, value, err);
933  if (CSR_RESULT(rc) != CSR_SUCCESS)
934  return rc;
935 
936  if (he->type & DT_INHERITED)
937  he->type = cdef->type | DT_INHERITED;
938 
939  return rc;
940 }
941 
950 int cs_str_string_plus_equals(const struct ConfigSet *cs, const char *name,
951  const char *value, struct Buffer *err)
952 {
953  if (!cs || !name)
954  return CSR_ERR_CODE;
955 
956  struct HashElem *he = cs_get_elem(cs, name);
957  if (!he)
958  {
959  mutt_buffer_printf(err, _("Unknown variable '%s'"), name);
960  return CSR_ERR_UNKNOWN;
961  }
962 
963  return cs_he_string_plus_equals(cs, he, value, err);
964 }
965 
974 int cs_he_string_minus_equals(const struct ConfigSet *cs, struct HashElem *he,
975  const char *value, struct Buffer *err)
976 {
977  if (!cs || !he)
978  return CSR_ERR_CODE;
979 
980  struct ConfigDef *cdef = NULL;
981  const struct ConfigSetType *cst = NULL;
982  void *var = NULL;
983 
984  if (he->type & DT_INHERITED)
985  {
986  struct Inheritance *i = he->data;
987  struct HashElem *he_base = cs_get_base(he);
988  cdef = he_base->data;
989  cst = cs_get_type_def(cs, he_base->type);
990  var = &i->var;
991  }
992  else
993  {
994  cdef = he->data;
995  cst = cs_get_type_def(cs, he->type);
996  if (cdef->type & DT_NO_VARIABLE)
997  var = &cdef->var;
998  else
999  var = cdef->var;
1000  }
1001 
1002  if (!var || !cdef)
1003  return INT_MIN; // LCOV_EXCL_LINE
1004 
1005  if (!cst)
1006  {
1007  mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
1008  return CSR_ERR_CODE;
1009  }
1010 
1011  if (!cst->string_minus_equals)
1012  {
1013  // L10N: e.g. Type 'boolean' doesn't support operation '+='
1014  mutt_buffer_printf(err, _("Type '%s' doesn't support operation '%s'"), cst->name, "-=");
1016  }
1017 
1018  int rc = cst->string_minus_equals(cs, var, cdef, value, err);
1019  if (CSR_RESULT(rc) != CSR_SUCCESS)
1020  return rc;
1021 
1022  if (he->type & DT_INHERITED)
1023  he->type = cdef->type | DT_INHERITED;
1024 
1025  return rc;
1026 }
1027 
1036 int cs_str_string_minus_equals(const struct ConfigSet *cs, const char *name,
1037  const char *value, struct Buffer *err)
1038 {
1039  if (!cs || !name)
1040  return CSR_ERR_CODE;
1041 
1042  struct HashElem *he = cs_get_elem(cs, name);
1043  if (!he)
1044  {
1045  mutt_buffer_printf(err, _("Unknown variable '%s'"), name);
1046  return CSR_ERR_UNKNOWN;
1047  }
1048 
1049  return cs_he_string_minus_equals(cs, he, value, err);
1050 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
int cs_str_string_minus_equals(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition: set.c:1036
Type definition for a config item.
Definition: set.h:88
void(* destroy)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
Destroy a config item.
Definition: set.h:217
bool cs_register_type(struct ConfigSet *cs, const struct ConfigSetType *cst)
Register a type of config item.
Definition: set.c:258
Container for lots of config items.
Definition: set.h:228
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define DT_NO_VARIABLE
Config item doesn&#39;t have a backing global variable.
Definition: types.h:84
int type
Data type, e.g. DT_STRING.
Definition: set.h:90
int(* string_set)(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.h:108
#define CSR_ERR_INVALID
Value hasn&#39;t been set.
Definition: set.h:38
Constants for all the config types.
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
static struct HashElem * create_synonym(const struct ConfigSet *cs, struct ConfigDef *cdef, struct Buffer *err)
Create an alternative name for a config item.
Definition: set.c:99
void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
Remove an inherited config item.
Definition: set.c:341
A collection of config items.
struct ConfigSetType types[18]
All the defined config types.
Definition: set.h:231
intptr_t initial
Initial value.
Definition: set.h:66
int(* string_get)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get a config item as a string.
Definition: set.h:125
struct HashElem * cs_inherit_variable(const struct ConfigSet *cs, struct HashElem *parent, const char *name)
Create in inherited config item.
Definition: set.c:316
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define CSV_INV_NOT_IMPL
Operation not permitted for the type.
Definition: set.h:49
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define DT_INITIAL_SET
Config item must have its initial value freed.
Definition: types.h:81
#define _(a)
Definition: message.h:28
const char * name
Name of this config item.
Definition: inheritance.h:34
int cs_str_string_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:613
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Config item definition.
Definition: set.h:61
int(* native_set)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set a config item by string.
Definition: set.h:141
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
struct HashElem * mutt_hash_find_elem(const struct HashTable *table, const char *strkey)
Find the HashElem in a Hash Table element using a key.
Definition: hash.c:369
#define CSR_RESULT(x)
Definition: set.h:52
An inherited config item.
Definition: inheritance.h:31
intptr_t cs_he_native_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Natively get the value of a HashElem config item.
Definition: set.c:817
int cs_he_reset(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:356
#define mutt_array_size(x)
Definition: memory.h:33
intptr_t cs_str_native_get(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Natively get the value of a string config item.
Definition: set.c:871
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition: set.c:166
int cs_str_initial_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition: set.c:535
int cs_he_initial_set(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:431
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:473
const char * name
User-visible name.
Definition: set.h:63
#define CSR_ERR_UNKNOWN
Unrecognised config item.
Definition: set.h:37
int cs_he_string_minus_equals(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition: set.c:974
bool cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], int flags)
Register a set of config items.
Definition: set.c:286
struct HashTable * hash
HashTable storing the config items.
Definition: set.h:230
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_hash_set_destructor(struct HashTable *table, hash_hdata_free_t fn, intptr_t fn_data)
Set the destructor for a Hash Table.
Definition: hash.c:293
int cs_str_string_plus_equals(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: set.c:950
int cs_he_string_plus_equals(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: set.c:888
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition: set.c:499
int(* string_minus_equals)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Remove from a config item as a string.
Definition: set.h:189
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition: set.c:199
int cs_he_string_set(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:558
void * data
User-supplied data.
Definition: hash.h:47
void * var
Pointer to the global variable.
Definition: set.h:65
unsigned int type
Variable type, e.g. DT_STRING.
Definition: set.h:64
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:180
struct HashElem * mutt_hash_typed_insert(struct HashTable *table, const char *strkey, int type, void *data)
Insert a string with type info into a Hash Table.
Definition: hash.c:309
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
Log at debug level 1.
Definition: logging.h:40
An inherited config item.
const char * name
Name of the type, e.g. "String".
Definition: set.h:91
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#define FREE(x)
Definition: memory.h:40
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: set.c:636
The item stored in a Hash Table.
Definition: hash.h:43
int cs_str_native_set(const struct ConfigSet *cs, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: set.c:761
int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:408
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int(* string_plus_equals)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: set.h:173
struct HashElem * parent
HashElem of parent config item.
Definition: inheritance.h:33
int cs_he_native_set(const struct ConfigSet *cs, struct HashElem *he, intptr_t value, struct Buffer *err)
Natively set the value of a HashElem config item.
Definition: set.c:706
static struct HashElem * reg_one_var(const struct ConfigSet *cs, struct ConfigDef *cdef, struct Buffer *err)
Register one config item.
Definition: set.c:129
int cs_str_string_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: set.c:683
Convenience wrapper for the library headers.
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:237
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:214
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
static void destroy(int type, void *obj, intptr_t data)
Callback function for the Hash Table - Implements hash_hdata_free_t.
Definition: set.c:47
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:97
intptr_t(* native_get)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get a string from a config item.
Definition: set.h:157
#define DT_INHERITED
Config item is inherited.
Definition: types.h:80
intptr_t var
(Pointer to) value, of config item
Definition: inheritance.h:35
int(* reset)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.h:204