NeoMutt  2025-09-05-43-g177ed6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
subset.c
Go to the documentation of this file.
1
24
37
38#include "config.h"
39#include <limits.h>
40#include <stdint.h>
41#include <stdio.h>
42#include "mutt/lib.h"
43#include "subset.h"
44#include "set.h"
45#include "types.h"
46
47struct Notify;
48
52static const struct Mapping ConfigEventNames[] = {
53 // clang-format off
54 { "NT_CONFIG_SET", NT_CONFIG_SET },
55 { "NT_CONFIG_RESET", NT_CONFIG_RESET },
56 { "NT_CONFIG_DELETED", NT_CONFIG_DELETED },
57 { NULL, 0 },
58 // clang-format on
59};
60
64int elem_list_sort(const void *a, const void *b, void *sdata)
65{
66 if (!a || !b)
67 return 0;
68
69 const struct HashElem *hea = *(struct HashElem const *const *) a;
70 const struct HashElem *heb = *(struct HashElem const *const *) b;
71
72 return mutt_istr_cmp(hea->key.strkey, heb->key.strkey);
73}
74
81struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
82{
83 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
84
85 if (!cs)
86 return hea;
87
88 struct HashWalkState walk = { 0 };
89 struct HashElem *he = NULL;
90 while ((he = mutt_hash_walk(cs->hash, &walk)))
91 {
92 if ((CONFIG_TYPE(he->type) == DT_SYNONYM) || (he->type & D_INTERNAL_DEPRECATED))
93 continue;
94
95 if ((flags == GEL_CHANGED_CONFIG) && !cs_he_has_been_set(cs, he))
96 continue;
97
98 ARRAY_ADD(&hea, he);
99 }
100
101 ARRAY_SORT(&hea, elem_list_sort, NULL);
102
103 return hea;
104}
105
112void cs_subset_free(struct ConfigSubset **ptr)
113{
114 if (!ptr || !*ptr)
115 return;
116
117 struct ConfigSubset *sub = *ptr;
118
119 struct EventConfig ev_c = { sub, NULL, NULL };
120 mutt_debug(LL_NOTIFY, "NT_CONFIG_DELETED: ALL\n");
122
123 if (sub->cs && sub->name)
124 {
125 char scope[256] = { 0 };
126 snprintf(scope, sizeof(scope), "%s:", sub->name);
127
128 // We don't know if any config items have been set,
129 // so search for anything with a matching scope.
130 struct HashElemArray hea = get_elem_list(sub->cs, GEL_ALL_CONFIG);
131 struct HashElem **hep = NULL;
132 ARRAY_FOREACH(hep, &hea)
133 {
134 struct HashElem *he = *hep;
135 const char *item = he->key.strkey;
136 if (mutt_str_startswith(item, scope) != 0)
137 {
138 cs_uninherit_variable(sub->cs, item);
139 }
140 }
141 ARRAY_FREE(&hea);
142 }
143
144 notify_free(&sub->notify);
145 FREE(&sub->name);
146 FREE(ptr);
147}
148
158struct ConfigSubset *cs_subset_new(const char *name, struct ConfigSubset *sub_parent,
159 struct Notify *not_parent)
160{
161 struct ConfigSubset *sub = MUTT_MEM_CALLOC(1, struct ConfigSubset);
162
163 if (sub_parent)
164 {
165 sub->parent = sub_parent;
166 sub->cs = sub_parent->cs;
167 }
168
169 if (name)
170 {
171 char scope[256] = { 0 };
172
173 if (sub_parent && sub_parent->name)
174 snprintf(scope, sizeof(scope), "%s:%s", sub_parent->name, name);
175 else
176 mutt_str_copy(scope, name, sizeof(scope));
177
178 sub->name = mutt_str_dup(scope);
179 }
180
181 sub->notify = notify_new();
182 notify_set_parent(sub->notify, not_parent);
183
184 return sub;
185}
186
193struct HashElem *cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
194{
195 if (!sub || !name)
196 return NULL;
197
198 char scope[256] = { 0 };
199 if (sub->name)
200 snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
201 else
202 mutt_str_copy(scope, name, sizeof(scope));
203
204 return cs_get_elem(sub->cs, scope);
205}
206
214struct HashElem *cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
215{
216 if (!sub)
217 return NULL;
218
219 struct HashElem *he = cs_subset_lookup(sub, name);
220 if (he)
221 return he;
222
223 if (sub->parent)
224 {
225 // Create parent before creating name
226 he = cs_subset_create_inheritance(sub->parent, name);
227 }
228
229 if (!he)
230 return NULL;
231
232 char scope[256] = { 0 };
233 snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
234 return cs_inherit_variable(sub->cs, he, scope);
235}
236
244 struct HashElem *he, enum NotifyConfig ev)
245{
246 if (!sub || !he)
247 return;
248
249 struct HashElem *he_base = cs_get_base(he);
250 struct EventConfig ev_c = { sub, he_base->key.strkey, he };
251 mutt_debug(LL_NOTIFY, "%s: %s\n",
253 notify_send(sub->notify, NT_CONFIG, ev, &ev_c);
254}
255
265 struct HashElem *he, struct Buffer *err)
266{
267 if (!sub)
268 return INT_MIN;
269
270 return cs_he_native_get(sub->cs, he, err);
271}
272
282 intptr_t value, struct Buffer *err)
283{
284 if (!sub)
285 return CSR_ERR_CODE;
286
287 int rc = cs_he_native_set(sub->cs, he, value, err);
288
289 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
291
292 return rc;
293}
294
303int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name,
304 intptr_t value, struct Buffer *err)
305{
306 struct HashElem *he = cs_subset_create_inheritance(sub, name);
307
308 return cs_subset_he_native_set(sub, he, value, err);
309}
310
318int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
319{
320 if (!sub)
321 return CSR_ERR_CODE;
322
323 int rc = cs_he_reset(sub->cs, he, err);
324
325 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
327
328 return rc;
329}
330
338int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he,
339 struct Buffer *result)
340{
341 if (!sub)
342 return CSR_ERR_CODE;
343
344 return cs_he_string_get(sub->cs, he, result);
345}
346
354int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name,
355 struct Buffer *result)
356{
357 struct HashElem *he = cs_subset_create_inheritance(sub, name);
358
359 return cs_subset_he_string_get(sub, he, result);
360}
361
370int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he,
371 const char *value, struct Buffer *err)
372{
373 if (!sub)
374 return CSR_ERR_CODE;
375
376 int rc = cs_he_string_set(sub->cs, he, value, err);
377
378 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
380
381 return rc;
382}
383
392int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name,
393 const char *value, struct Buffer *err)
394{
395 struct HashElem *he = cs_subset_create_inheritance(sub, name);
396
397 return cs_subset_he_string_set(sub, he, value, err);
398}
399
408int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he,
409 const char *value, struct Buffer *err)
410{
411 if (!sub)
412 return CSR_ERR_CODE;
413
414 int rc = cs_he_string_plus_equals(sub->cs, he, value, err);
415
416 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
418
419 return rc;
420}
421
431 const char *value, struct Buffer *err)
432{
433 if (!sub)
434 return CSR_ERR_CODE;
435
436 int rc = cs_he_string_minus_equals(sub->cs, he, value, err);
437
438 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
440
441 return rc;
442}
443
451int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
452{
453 if (!sub)
454 return CSR_ERR_CODE;
455
456 const char *name = mutt_str_dup(he->key.strkey);
457 int rc = cs_he_delete(sub->cs, he, err);
458
459 if (CSR_RESULT(rc) == CSR_SUCCESS)
460 {
461 struct EventConfig ev_c = { sub, name, NULL };
462 mutt_debug(LL_NOTIFY, "NT_CONFIG_DELETED: %s\n", name);
464 }
465
466 FREE(&name);
467 return rc;
468}
#define ARRAY_SORT(head, fn, sdata)
Sort an array.
Definition array.h:335
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:156
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition set.c:175
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:892
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:399
int cs_he_delete(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Delete config item from a config set.
Definition set.c:1009
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:616
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition set.c:160
bool cs_he_has_been_set(const struct ConfigSet *cs, struct HashElem *he)
Is the config value different to its initial value?
Definition set.c:468
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:736
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:841
struct HashElem * cs_inherit_variable(const struct ConfigSet *cs, struct HashElem *he_parent, const char *name)
Create in inherited config item.
Definition set.c:355
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:691
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:951
void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
Remove an inherited config item.
Definition set.c:384
A collection of config items.
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition set.h:42
#define CSR_ERR_CODE
Problem with the code.
Definition set.h:34
#define CSR_RESULT(x)
Definition set.h:50
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define mutt_debug(LEVEL,...)
Definition logging2.h:90
int elem_list_sort(const void *a, const void *b, void *sdata)
Compare two HashElem pointers to config - Implements sort_t -.
Definition subset.c:64
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem's in a Hash Table.
Definition hash.c:489
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:49
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition mapping.c:42
#define FREE(x)
Definition memory.h:62
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:47
Convenience wrapper for the library headers.
struct Notify * notify_new(void)
Create a new notifications handler.
Definition notify.c:62
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition notify.c:95
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition notify.c:75
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition string.c:414
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:232
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition string.c:581
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition notify_type.h:43
#define NONULL(x)
Definition string2.h:43
String manipulation buffer.
Definition buffer.h:36
Container for lots of config items.
Definition set.h:248
A set of inherited config items.
Definition subset.h:46
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition subset.h:51
const char * name
Scope name of Subset.
Definition subset.h:47
struct ConfigSet * cs
Parent ConfigSet.
Definition subset.h:50
struct ConfigSubset * parent
Parent Subset.
Definition subset.h:49
enum ConfigScope scope
Scope of Subset, e.g. SET_SCOPE_ACCOUNT.
Definition subset.h:48
A config-change event.
Definition subset.h:70
const struct ConfigSubset * sub
Config Subset.
Definition subset.h:71
const char * name
Name of config item that changed.
Definition subset.h:72
struct HashElem * he
Config item that changed.
Definition subset.h:73
The item stored in a Hash Table.
Definition hash.h:44
union HashKey key
Key representing the data.
Definition hash.h:46
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
Cursor to iterate through a Hash Table.
Definition hash.h:134
Mapping between user-readable string and a constant.
Definition mapping.h:33
Notification API.
Definition notify.c:53
int cs_subset_he_string_minus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition subset.c:430
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition subset.c:338
int cs_subset_he_native_set(const struct ConfigSubset *sub, struct HashElem *he, intptr_t value, struct Buffer *err)
Natively set the value of a HashElem config item.
Definition subset.c:281
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
intptr_t cs_subset_he_native_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Natively get the value of a HashElem config item.
Definition subset.c:264
int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Delete config item from a config.
Definition subset.c:451
int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition subset.c:318
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition subset.c:354
int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Set a config item by string.
Definition subset.c:370
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition subset.c:392
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition subset.c:81
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition subset.c:214
struct ConfigSubset * cs_subset_new(const char *name, struct ConfigSubset *sub_parent, struct Notify *not_parent)
Create a new Config Subset.
Definition subset.c:158
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition subset.c:112
static const struct Mapping ConfigEventNames[]
Names for logging.
Definition subset.c:52
int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Add to a config item by string.
Definition subset.c:408
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition subset.c:193
void cs_subset_notify_observers(const struct ConfigSubset *sub, struct HashElem *he, enum NotifyConfig ev)
Notify all observers of an event.
Definition subset.c:243
Subset of Config Items.
NotifyConfig
Config notification types.
Definition subset.h:60
@ NT_CONFIG_DELETED
Config item has been deleted.
Definition subset.h:63
@ NT_CONFIG_RESET
Config item has been reset to initial, or parent, value.
Definition subset.h:62
@ NT_CONFIG_SET
Config item has been set.
Definition subset.h:61
GetElemListFlags
Flags for get_elem_list()
Definition subset.h:80
@ GEL_CHANGED_CONFIG
Only config that has been changed.
Definition subset.h:82
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition subset.h:81
Constants for all the config types.
#define CONFIG_TYPE(t)
Definition types.h:49
#define D_INTERNAL_DEPRECATED
Config item shouldn't be used any more.
Definition types.h:87
@ DT_SYNONYM
synonym for another variable
Definition types.h:45
const char * strkey
String key.
Definition hash.h:36