NeoMutt  2025-01-09-81-g753ae0
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mbtable.c
Go to the documentation of this file.
1
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, k;
70 mbstate_t mbstate = { 0 };
71 char *d = NULL;
72
73 slen = mutt_str_len(s);
74 if (!slen)
75 return NULL;
76
77 t = MUTT_MEM_CALLOC(1, struct MbTable);
78
79 t->orig_str = mutt_str_dup(s);
80 /* This could be more space efficient. However, being used on tiny
81 * strings (`$to_chars` and `$status_chars`), the overhead is not great. */
82 t->chars = MUTT_MEM_CALLOC(slen, char *);
83 t->segmented_str = MUTT_MEM_CALLOC(slen * 2, char);
84 d = t->segmented_str;
85
86 while (slen && (k = mbrtowc(NULL, s, slen, &mbstate)))
87 {
88 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
89 {
90 /* XXX put message in err buffer; fail? warning? */
91 mutt_debug(LL_DEBUG1, "mbrtowc returned %zd converting %s in %s\n", k, s, t->orig_str);
92 if (k == ICONV_ILLEGAL_SEQ)
93 memset(&mbstate, 0, sizeof(mbstate));
94 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : slen;
95 }
96
97 slen -= k;
98 t->chars[t->len++] = d;
99 while (k-- > 0)
100 *d++ = *s++;
101 *d++ = '\0';
102 }
103
104 return t;
105}
106
110static void mbtable_destroy(void *var, const struct ConfigDef *cdef)
111{
112 struct MbTable **m = var;
113 if (!*m)
114 return;
115
116 mbtable_free(m);
117}
118
122static int mbtable_string_set(void *var, struct ConfigDef *cdef,
123 const char *value, struct Buffer *err)
124{
125 /* Store empty mbtables as NULL */
126 if (value && (value[0] == '\0'))
127 value = NULL;
128
129 struct MbTable *table = NULL;
130
131 int rc = CSR_SUCCESS;
132
133 if (var)
134 {
135 struct MbTable *curval = *(struct MbTable **) var;
136 if (curval && mutt_str_equal(value, curval->orig_str))
138
139 if (startup_only(cdef, err))
141
142 table = mbtable_parse(value);
143
144 if (cdef->validator)
145 {
146 rc = cdef->validator(cdef, (intptr_t) table, err);
147
148 if (CSR_RESULT(rc) != CSR_SUCCESS)
149 {
150 mbtable_free(&table);
151 return rc | CSR_INV_VALIDATOR;
152 }
153 }
154
155 mbtable_destroy(var, cdef);
156
157 *(struct MbTable **) var = table;
158
159 if (!table)
160 rc |= CSR_SUC_EMPTY;
161 }
162 else
163 {
164 if (cdef->type & D_INTERNAL_INITIAL_SET)
165 FREE(&cdef->initial);
166
168 cdef->initial = (intptr_t) mutt_str_dup(value);
169 }
170
171 return rc;
172}
173
177static int mbtable_string_get(void *var, const struct ConfigDef *cdef, struct Buffer *result)
178{
179 const char *str = NULL;
180
181 if (var)
182 {
183 struct MbTable *table = *(struct MbTable **) var;
184 if (!table || !table->orig_str)
185 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
186 str = table->orig_str;
187 }
188 else
189 {
190 str = (char *) cdef->initial;
191 }
192
193 buf_addstr(result, str);
194 return CSR_SUCCESS;
195}
196
202static struct MbTable *mbtable_dup(struct MbTable *table)
203{
204 if (!table)
205 return NULL; /* LCOV_EXCL_LINE */
206
207 struct MbTable *m = MUTT_MEM_CALLOC(1, struct MbTable);
208 m->orig_str = mutt_str_dup(table->orig_str);
209 return m;
210}
211
215static int mbtable_native_set(void *var, const struct ConfigDef *cdef,
216 intptr_t value, struct Buffer *err)
217{
218 int rc;
219
220 if (mbtable_equal(*(struct MbTable **) var, (struct MbTable *) value))
222
223 if (startup_only(cdef, err))
225
226 if (cdef->validator)
227 {
228 rc = cdef->validator(cdef, value, err);
229
230 if (CSR_RESULT(rc) != CSR_SUCCESS)
231 return rc | CSR_INV_VALIDATOR;
232 }
233
234 mbtable_free(var);
235
236 struct MbTable *table = mbtable_dup((struct MbTable *) value);
237
238 rc = CSR_SUCCESS;
239 if (!table)
240 rc |= CSR_SUC_EMPTY;
241
242 *(struct MbTable **) var = table;
243 return rc;
244}
245
249static intptr_t mbtable_native_get(void *var, const struct ConfigDef *cdef, struct Buffer *err)
250{
251 struct MbTable *table = *(struct MbTable **) var;
252
253 return (intptr_t) table;
254}
255
259static bool mbtable_has_been_set(void *var, const struct ConfigDef *cdef)
260{
261 const char *initial = (const char *) cdef->initial;
262
263 struct MbTable *table = *(struct MbTable **) var;
264 const char *table_str = table ? table->orig_str : NULL;
265
266 return !mutt_str_equal(initial, table_str);
267}
268
272static int mbtable_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
273{
274 struct MbTable *table = NULL;
275 const char *initial = (const char *) cdef->initial;
276
277 struct MbTable *curtable = *(struct MbTable **) var;
278 const char *curval = curtable ? curtable->orig_str : NULL;
279
280 int rc = CSR_SUCCESS;
281 if (!curtable)
282 rc |= CSR_SUC_EMPTY;
283
284 if (mutt_str_equal(initial, curval))
285 return rc | CSR_SUC_NO_CHANGE;
286
287 if (startup_only(cdef, err))
289
290 if (initial)
291 table = mbtable_parse(initial);
292
293 if (cdef->validator)
294 {
295 rc = cdef->validator(cdef, (intptr_t) table, err);
296
297 if (CSR_RESULT(rc) != CSR_SUCCESS)
298 {
299 mbtable_destroy(&table, cdef);
300 return rc | CSR_INV_VALIDATOR;
301 }
302 }
303
304 if (!table)
305 rc |= CSR_SUC_EMPTY;
306
307 mbtable_destroy(var, cdef);
308
309 *(struct MbTable **) var = table;
310 return rc;
311}
312
317void mbtable_free(struct MbTable **ptr)
318{
319 if (!ptr || !*ptr)
320 return;
321
322 struct MbTable *table = *ptr;
323 FREE(&table->orig_str);
324 FREE(&table->chars);
325 FREE(&table->segmented_str);
326
327 FREE(ptr);
328}
329
340const char *mbtable_get_nth_wchar(const struct MbTable *table, int index)
341{
342 if (!table || !table->chars || (index < 0) || (index >= table->len))
343 return " ";
344
345 if (table->chars[index][0] == '\r')
346 return "";
347
348 return table->chars[index];
349}
350
354const struct ConfigSetType CstMbtable = {
356 "mbtable",
361 NULL, // string_plus_equals
362 NULL, // string_minus_equals
366};
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
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:38
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition: set.h:48
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition: set.h:44
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
static void mbtable_destroy(void *var, const struct ConfigDef *cdef)
Destroy an MbTable object - Implements ConfigSetType::destroy() -.
Definition: mbtable.c:110
static bool mbtable_has_been_set(void *var, const struct ConfigDef *cdef)
Is the config value different to its initial value? - Implements ConfigSetType::has_been_set() -.
Definition: mbtable.c:259
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:249
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:215
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:272
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:177
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:122
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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:202
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:340
void mbtable_free(struct MbTable **ptr)
Free an MbTable object.
Definition: mbtable.c:317
const struct ConfigSetType CstMbtable
Config type representing a multi-byte table.
Definition: mbtable.c:354
Type representing a multibyte character table.
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:98
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:96
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:497
Parse the 'set' command.
String manipulation buffer.
Definition: buffer.h:36
Definition: set.h:64
int(* validator)(const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition: set.h:81
intptr_t initial
Initial value.
Definition: set.h:67
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
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:89
@ DT_MBTABLE
multibyte char table
Definition: types.h:36