NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mbtable.c
Go to the documentation of this file.
1
23
35
36#include "config.h"
37#include <stdint.h>
38#include <string.h>
39#include <wchar.h>
40#include "mutt/lib.h"
41#include "mbtable.h"
42#include "set.h"
43#include "types.h"
44
51bool mbtable_equal(const struct MbTable *a, const struct MbTable *b)
52{
53 if (!a && !b) /* both empty */
54 return true;
55 if (!a ^ !b) /* one is empty, but not the other */
56 return false;
57
58 return mutt_str_equal(a->orig_str, b->orig_str);
59}
60
66struct MbTable *mbtable_parse(const char *s)
67{
68 struct MbTable *t = NULL;
69 size_t slen;
70 size_t k;
71 mbstate_t mbstate = { 0 };
72 char *d = NULL;
73
74 slen = mutt_str_len(s);
75 if (!slen)
76 return NULL;
77
78 t = MUTT_MEM_CALLOC(1, struct MbTable);
79
80 t->orig_str = mutt_str_dup(s);
81 /* This could be more space efficient. However, being used on tiny
82 * strings (`$to_chars` and `$status_chars`), the overhead is not great. */
83 t->chars = MUTT_MEM_CALLOC(slen, char *);
84 t->segmented_str = MUTT_MEM_CALLOC(slen * 2, char);
85 d = t->segmented_str;
86
87 while (slen && (k = mbrtowc(NULL, s, slen, &mbstate)))
88 {
89 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
90 {
91 /* XXX put message in err buffer; fail? warning? */
92 mutt_debug(LL_DEBUG1, "mbrtowc returned %zd converting %s in %s\n", k, s, t->orig_str);
93 if (k == ICONV_ILLEGAL_SEQ)
94 memset(&mbstate, 0, sizeof(mbstate));
95 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : slen;
96 }
97
98 slen -= k;
99 t->chars[t->len++] = d;
100 while (k-- > 0)
101 *d++ = *s++;
102 *d++ = '\0';
103 }
104
105 return t;
106}
107
111static void mbtable_destroy(void *var, const struct ConfigDef *cdef)
112{
113 struct MbTable **m = var;
114 if (!*m)
115 return;
116
117 mbtable_free(m);
118}
119
123static int mbtable_string_set(void *var, struct ConfigDef *cdef,
124 const char *value, struct Buffer *err)
125{
126 /* Store empty mbtables as NULL */
127 if (value && (value[0] == '\0'))
128 value = NULL;
129
130 struct MbTable *table = NULL;
131
132 int rc = CSR_SUCCESS;
133
134 if (var)
135 {
136 struct MbTable *curval = *(struct MbTable **) var;
137 if (curval && mutt_str_equal(value, curval->orig_str))
139
140 if (startup_only(cdef, err))
142
143 table = mbtable_parse(value);
144
145 if (cdef->validator)
146 {
147 rc = cdef->validator(cdef, (intptr_t) table, err);
148
149 if (CSR_RESULT(rc) != CSR_SUCCESS)
150 {
151 mbtable_free(&table);
152 return rc | CSR_INV_VALIDATOR;
153 }
154 }
155
156 mbtable_destroy(var, cdef);
157
158 *(struct MbTable **) var = table;
159
160 if (!table)
161 rc |= CSR_SUC_EMPTY;
162 }
163 else
164 {
165 if (cdef->type & D_INTERNAL_INITIAL_SET)
166 FREE(&cdef->initial);
167
169 cdef->initial = (intptr_t) mutt_str_dup(value);
170 }
171
172 return rc;
173}
174
178static int mbtable_string_get(void *var, const struct ConfigDef *cdef, struct Buffer *result)
179{
180 const char *str = NULL;
181
182 if (var)
183 {
184 struct MbTable *table = *(struct MbTable **) var;
185 if (!table || !table->orig_str)
186 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
187 str = table->orig_str;
188 }
189 else
190 {
191 str = (char *) cdef->initial;
192 }
193
194 buf_addstr(result, str);
195 return CSR_SUCCESS;
196}
197
203static struct MbTable *mbtable_dup(struct MbTable *table)
204{
205 if (!table)
206 return NULL; /* LCOV_EXCL_LINE */
207
208 struct MbTable *m = MUTT_MEM_CALLOC(1, struct MbTable);
209 m->orig_str = mutt_str_dup(table->orig_str);
210 return m;
211}
212
216static int mbtable_native_set(void *var, const struct ConfigDef *cdef,
217 intptr_t value, struct Buffer *err)
218{
219 int rc;
220
221 if (mbtable_equal(*(struct MbTable **) var, (struct MbTable *) value))
223
224 if (startup_only(cdef, err))
226
227 if (cdef->validator)
228 {
229 rc = cdef->validator(cdef, value, err);
230
231 if (CSR_RESULT(rc) != CSR_SUCCESS)
232 return rc | CSR_INV_VALIDATOR;
233 }
234
235 mbtable_free(var);
236
237 struct MbTable *table = mbtable_dup((struct MbTable *) value);
238
239 rc = CSR_SUCCESS;
240 if (!table)
241 rc |= CSR_SUC_EMPTY;
242
243 *(struct MbTable **) var = table;
244 return rc;
245}
246
250static intptr_t mbtable_native_get(void *var, const struct ConfigDef *cdef, struct Buffer *err)
251{
252 struct MbTable *table = *(struct MbTable **) var;
253
254 return (intptr_t) table;
255}
256
260static bool mbtable_has_been_set(void *var, const struct ConfigDef *cdef)
261{
262 const char *initial = (const char *) cdef->initial;
263
264 struct MbTable *table = *(struct MbTable **) var;
265 const char *table_str = table ? table->orig_str : NULL;
266
267 return !mutt_str_equal(initial, table_str);
268}
269
273static int mbtable_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
274{
275 struct MbTable *table = NULL;
276 const char *initial = (const char *) cdef->initial;
277
278 struct MbTable *curtable = *(struct MbTable **) var;
279 const char *curval = curtable ? curtable->orig_str : NULL;
280
281 int rc = CSR_SUCCESS;
282 if (!curtable)
283 rc |= CSR_SUC_EMPTY;
284
285 if (mutt_str_equal(initial, curval))
286 return rc | CSR_SUC_NO_CHANGE;
287
288 if (startup_only(cdef, err))
290
291 if (initial)
292 table = mbtable_parse(initial);
293
294 if (cdef->validator)
295 {
296 rc = cdef->validator(cdef, (intptr_t) table, err);
297
298 if (CSR_RESULT(rc) != CSR_SUCCESS)
299 {
300 mbtable_destroy(&table, cdef);
301 return rc | CSR_INV_VALIDATOR;
302 }
303 }
304
305 if (!table)
306 rc |= CSR_SUC_EMPTY;
307
308 mbtable_destroy(var, cdef);
309
310 *(struct MbTable **) var = table;
311 return rc;
312}
313
318void mbtable_free(struct MbTable **ptr)
319{
320 if (!ptr || !*ptr)
321 return;
322
323 struct MbTable *table = *ptr;
324 FREE(&table->orig_str);
325 FREE(&table->chars);
326 FREE(&table->segmented_str);
327
328 FREE(ptr);
329}
330
341const char *mbtable_get_nth_wchar(const struct MbTable *table, int index)
342{
343 if (!table || !table->chars || (index < 0) || (index >= table->len))
344 return " ";
345
346 if (table->chars[index][0] == '\r')
347 return "";
348
349 return table->chars[index];
350}
351
355const struct ConfigSetType CstMbtable = {
357 "mbtable",
362 NULL, // string_plus_equals
363 NULL, // string_minus_equals
367};
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
A collection of config items.
static bool startup_only(const struct ConfigDef *cdef, struct Buffer *err)
Validator function for D_ON_STARTUP.
Definition set.h:296
#define CSR_ERR_INVALID
Value hasn't been set.
Definition set.h:36
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition set.h:46
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition set.h:42
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:53
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition set.h:40
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
static void mbtable_destroy(void *var, const struct ConfigDef *cdef)
Destroy an MbTable object - Implements ConfigSetType::destroy() -.
Definition mbtable.c:111
static bool mbtable_has_been_set(void *var, const struct ConfigDef *cdef)
Is the config value different to its initial value?
Definition mbtable.c:260
static intptr_t mbtable_native_get(void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get an MbTable object from a MbTable config item - Implements ConfigSetType::native_get() -.
Definition mbtable.c:250
static int mbtable_native_set(void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set an MbTable config item by MbTable object - Implements ConfigSetType::native_set() -.
Definition mbtable.c:216
static int mbtable_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset an MbTable to its initial value - Implements ConfigSetType::reset() -.
Definition mbtable.c:273
static int mbtable_string_get(void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get a MbTable as a string - Implements ConfigSetType::string_get() -.
Definition mbtable.c:178
static int mbtable_string_set(void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set an MbTable by string - Implements ConfigSetType::string_set() -.
Definition mbtable.c:123
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
bool mbtable_equal(const struct MbTable *a, const struct MbTable *b)
Compare two MbTables.
Definition mbtable.c:51
static struct MbTable * mbtable_dup(struct MbTable *table)
Create a copy of an MbTable object.
Definition mbtable.c:203
struct MbTable * mbtable_parse(const char *s)
Parse a multibyte string into a table.
Definition mbtable.c:66
const char * mbtable_get_nth_wchar(const struct MbTable *table, int index)
Extract one char from a multi-byte table.
Definition mbtable.c:341
void mbtable_free(struct MbTable **ptr)
Free an MbTable object.
Definition mbtable.c:318
const struct ConfigSetType CstMbtable
Config type representing a multi-byte table.
Definition mbtable.c:355
Type representing a multibyte character table.
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition charset.h:116
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition charset.h:114
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
String manipulation buffer.
Definition buffer.h:36
int(* validator)(const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition set.h:82
intptr_t initial
Initial value.
Definition set.h:68
uint32_t type
Variable type, e.g. DT_STRING.
Definition set.h:67
Multibyte character table.
Definition mbtable.h:36
char * orig_str
Original string used to generate this object.
Definition mbtable.h:37
int len
Number of characters.
Definition mbtable.h:38
char ** chars
The array of multibyte character strings.
Definition mbtable.h:39
char * segmented_str
Each chars entry points inside this string.
Definition mbtable.h:40
Constants for all the config types.
#define D_INTERNAL_INITIAL_SET
Config item must have its initial value freed.
Definition types.h:90
@ DT_MBTABLE
multibyte char table
Definition types.h:36