NeoMutt  2025-01-09-41-g086358
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
number.c
Go to the documentation of this file.
1
36#include "config.h"
37#include <limits.h>
38#include <stddef.h>
39#include <stdint.h>
40#include "mutt/lib.h"
41#include "number.h"
42#include "set.h"
43#include "subset.h"
44#include "types.h"
45
46#define TOGGLE_BIT ((SHRT_MAX + 1) << 1)
50static intptr_t native_get(void *var)
51{
52 // take care of endianess and always read intptr_t value
53 intptr_t v = *(intptr_t *) var;
54 return (v & TOGGLE_BIT) ? 0 : (short) v;
55}
56
60static void native_set(void *var, intptr_t val)
61{
62 // cast to unsigned short to clear any pending toggle status bits
63 val = (unsigned short) val;
64 *(intptr_t *) var = val;
65}
66
70static void native_toggle(void *var)
71{
72 *(intptr_t *) var = *(uintptr_t *) var ^ TOGGLE_BIT;
73}
74
78static int number_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
79 const char *value, struct Buffer *err)
80{
81 int num = 0;
82 if (value && *value && !mutt_str_atoi_full(value, &num))
83 {
84 buf_printf(err, _("Invalid number: %s"), value);
86 }
87
88 if ((num < SHRT_MIN) || (num > SHRT_MAX))
89 {
90 buf_printf(err, _("Number is too big: %s"), value);
92 }
93
94 if ((num < 0) && (cdef->type & D_INTEGER_NOT_NEGATIVE))
95 {
96 buf_printf(err, _("Option %s may not be negative"), cdef->name);
98 }
99
100 if (var)
101 {
102 if (num == native_get(var))
104
105 if (cdef->validator)
106 {
107 int rc = cdef->validator(cs, cdef, (intptr_t) num, err);
108
109 if (CSR_RESULT(rc) != CSR_SUCCESS)
110 return rc | CSR_INV_VALIDATOR;
111 }
112
113 if (startup_only(cdef, err))
115
116 native_set(var, num);
117 }
118 else
119 {
120 cdef->initial = num;
121 }
122
123 return CSR_SUCCESS;
124}
125
129static int number_string_get(const struct ConfigSet *cs, void *var,
130 const struct ConfigDef *cdef, struct Buffer *result)
131{
132 int value;
133
134 if (var)
135 value = native_get(var);
136 else
137 value = (int) cdef->initial;
138
139 buf_printf(result, "%d", value);
140 return CSR_SUCCESS;
141}
142
146static int number_native_set(const struct ConfigSet *cs, void *var,
147 const struct ConfigDef *cdef, intptr_t value,
148 struct Buffer *err)
149{
150 if ((value < SHRT_MIN) || (value > SHRT_MAX))
151 {
152 buf_printf(err, _("Invalid number: %ld"), (long) value);
154 }
155
156 if ((value < 0) && (cdef->type & D_INTEGER_NOT_NEGATIVE))
157 {
158 buf_printf(err, _("Option %s may not be negative"), cdef->name);
160 }
161
162 if (value == native_get(var))
164
165 if (cdef->validator)
166 {
167 int rc = cdef->validator(cs, cdef, value, err);
168
169 if (CSR_RESULT(rc) != CSR_SUCCESS)
170 return rc | CSR_INV_VALIDATOR;
171 }
172
173 if (startup_only(cdef, err))
175
176 native_set(var, value);
177 return CSR_SUCCESS;
178}
179
183static intptr_t number_native_get(const struct ConfigSet *cs, void *var,
184 const struct ConfigDef *cdef, struct Buffer *err)
185{
186 return native_get(var);
187}
188
192static int number_string_plus_equals(const struct ConfigSet *cs, void *var,
193 const struct ConfigDef *cdef,
194 const char *value, struct Buffer *err)
195{
196 int num = 0;
197 if (!mutt_str_atoi_full(value, &num))
198 {
199 buf_printf(err, _("Invalid number: %s"), NONULL(value));
201 }
202
203 int result = number_native_get(NULL, var, NULL, NULL) + num;
204 if ((result < SHRT_MIN) || (result > SHRT_MAX))
205 {
206 buf_printf(err, _("Number is too big: %s"), value);
208 }
209
210 if ((result < 0) && (cdef->type & D_INTEGER_NOT_NEGATIVE))
211 {
212 buf_printf(err, _("Option %s may not be negative"), cdef->name);
214 }
215
216 if (cdef->validator)
217 {
218 int rc = cdef->validator(cs, cdef, (intptr_t) result, err);
219
220 if (CSR_RESULT(rc) != CSR_SUCCESS)
221 return rc | CSR_INV_VALIDATOR;
222 }
223
224 if (startup_only(cdef, err))
226
227 native_set(var, result);
228 return CSR_SUCCESS;
229}
230
234static int number_string_minus_equals(const struct ConfigSet *cs, void *var,
235 const struct ConfigDef *cdef,
236 const char *value, struct Buffer *err)
237{
238 int num = 0;
239 if (!mutt_str_atoi(value, &num))
240 {
241 buf_printf(err, _("Invalid number: %s"), NONULL(value));
243 }
244
245 int result = native_get(var) - num;
246 if ((result < SHRT_MIN) || (result > SHRT_MAX))
247 {
248 buf_printf(err, _("Number is too big: %s"), value);
250 }
251
252 if ((result < 0) && (cdef->type & D_INTEGER_NOT_NEGATIVE))
253 {
254 buf_printf(err, _("Option %s may not be negative"), cdef->name);
256 }
257
258 if (cdef->validator)
259 {
260 int rc = cdef->validator(cs, cdef, (intptr_t) result, err);
261
262 if (CSR_RESULT(rc) != CSR_SUCCESS)
263 return rc | CSR_INV_VALIDATOR;
264 }
265
266 if (startup_only(cdef, err))
268
269 native_set(var, result);
270 return CSR_SUCCESS;
271}
272
276static int number_reset(const struct ConfigSet *cs, void *var,
277 const struct ConfigDef *cdef, struct Buffer *err)
278{
279 if (cdef->initial == native_get(var))
281
282 if (cdef->validator)
283 {
284 int rc = cdef->validator(cs, cdef, cdef->initial, err);
285
286 if (CSR_RESULT(rc) != CSR_SUCCESS)
287 return rc | CSR_INV_VALIDATOR;
288 }
289
290 if (startup_only(cdef, err))
292
293 native_set(var, cdef->initial);
294 return CSR_SUCCESS;
295}
296
304int number_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
305{
306 if (!sub || !he || !he->data)
307 return CSR_ERR_CODE;
308
309 struct HashElem *he_base = cs_get_base(he);
310 if (DTYPE(he_base->type) != DT_NUMBER)
311 return CSR_ERR_CODE;
312
313 struct ConfigDef *cdef = he_base->data;
314 native_toggle(&cdef->var);
315
317
318 return CSR_SUCCESS;
319}
320
324const struct ConfigSetType CstNumber = {
325 DT_NUMBER,
326 "number",
334 NULL, // destroy
335};
const char * mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: atoi.c:192
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition: set.c:160
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_TYPE
Value is not valid for the type.
Definition: set.h:47
#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_ERR_CODE
Problem with the code.
Definition: set.h:36
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
static intptr_t number_native_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get an int from a Number config item - Implements ConfigSetType::native_get() -.
Definition: number.c:183
static int number_native_set(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set a Number config item by int - Implements ConfigSetType::native_set() -.
Definition: number.c:146
static int number_reset(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset a Number to its initial value - Implements ConfigSetType::reset() -.
Definition: number.c:276
static int number_string_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get a Number as a string - Implements ConfigSetType::string_get() -.
Definition: number.c:129
static int number_string_minus_equals(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Subtract from a Number by string - Implements ConfigSetType::string_minus_equals() -.
Definition: number.c:234
static int number_string_plus_equals(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Add to a Number by string - Implements ConfigSetType::string_plus_equals() -.
Definition: number.c:192
static int number_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set a Number by string - Implements ConfigSetType::string_set() -.
Definition: number.c:78
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
static void native_set(void *var, intptr_t val)
Set an int into a Number config item.
Definition: number.c:60
const struct ConfigSetType CstNumber
Config type representing a number.
Definition: number.c:324
#define TOGGLE_BIT
Definition: number.c:46
static void native_toggle(void *var)
Toggle a Number config item.
Definition: number.c:70
static intptr_t native_get(void *var)
Get an int from a Number config item.
Definition: number.c:50
int number_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a number (value <-> 0)
Definition: number.c:304
Type representing a number.
Parse the 'set' command.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:36
Definition: set.h:64
const char * name
User-visible name.
Definition: set.h:65
intptr_t var
Storage for the variable.
Definition: set.h:85
int(* validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition: set.h:82
intptr_t initial
Initial value.
Definition: set.h:67
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
Container for lots of config items.
Definition: set.h:252
A set of inherited config items.
Definition: subset.h:47
The item stored in a Hash Table.
Definition: hash.h:43
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:44
void * data
User-supplied data.
Definition: hash.h:46
void cs_subset_notify_observers(const struct ConfigSubset *sub, struct HashElem *he, enum NotifyConfig ev)
Notify all observers of an event.
Definition: subset.c:237
Subset of Config Items.
@ NT_CONFIG_SET
Config item has been set.
Definition: subset.h:62
Constants for all the config types.
#define DTYPE(t)
Definition: types.h:50
@ DT_NUMBER
a number
Definition: types.h:39
#define D_INTEGER_NOT_NEGATIVE
Negative numbers are not allowed.
Definition: types.h:101