NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
set.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <assert.h>
33#include <stdbool.h>
34#include <stdio.h>
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "core/lib.h"
38#include "mutt.h"
39#include "set.h"
40#include "commands.h"
41#include "extract.h"
42#include "globals.h"
43#include "muttlib.h"
44
60static void command_set_expand_value(uint32_t type, struct Buffer *value)
61{
62 assert(value);
63 if (DTYPE(type) == DT_PATH)
64 {
65 if (type & (D_PATH_DIR | D_PATH_FILE))
66 buf_expand_path(value);
67 else
69 }
70 else if (IS_MAILBOX(type))
71 {
72 buf_expand_path(value);
73 }
74 else if (IS_COMMAND(type))
75 {
76 struct Buffer *scratch = buf_pool_get();
77 buf_copy(scratch, value);
78
79 if (!mutt_str_equal(value->data, "builtin"))
80 {
81 buf_expand_path(scratch);
82 }
83 buf_reset(value);
84 buf_addstr(value, buf_string(scratch));
85 buf_pool_release(&scratch);
86 }
87}
88
101static enum CommandResult command_set_set(struct Buffer *name,
102 struct Buffer *value, struct Buffer *err)
103{
104 assert(name);
105 assert(value);
106 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
107 if (!he)
108 {
109 // In case it is a my_var, we have to create it
110 if (mutt_str_startswith(name->data, "my_"))
111 {
112 struct ConfigDef my_cdef = { 0 };
113 my_cdef.name = name->data;
114 my_cdef.type = DT_MYVAR;
115 he = cs_create_variable(NeoMutt->sub->cs, &my_cdef, err);
116 if (!he)
117 return MUTT_CMD_ERROR;
118 }
119 else
120 {
121 buf_printf(err, _("Unknown option %s"), name->data);
122 return MUTT_CMD_ERROR;
123 }
124 }
125
126 int rc = CSR_ERR_CODE;
127
128 if (DTYPE(he->type) == DT_MYVAR)
129 {
130 // my variables do not expand their value
131 rc = cs_subset_he_string_set(NeoMutt->sub, he, value->data, err);
132 }
133 else
134 {
135 command_set_expand_value(he->type, value);
136 rc = cs_subset_he_string_set(NeoMutt->sub, he, value->data, err);
137 }
138 if (CSR_RESULT(rc) != CSR_SUCCESS)
139 return MUTT_CMD_ERROR;
140
141 return MUTT_CMD_SUCCESS;
142}
143
157 struct Buffer *value, struct Buffer *err)
158{
159 assert(name);
160 assert(value);
161 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
162 if (!he)
163 {
164 // In case it is a my_var, we have to create it
165 if (mutt_str_startswith(name->data, "my_"))
166 {
167 struct ConfigDef my_cdef = { 0 };
168 my_cdef.name = name->data;
169 my_cdef.type = DT_MYVAR;
170 he = cs_create_variable(NeoMutt->sub->cs, &my_cdef, err);
171 if (!he)
172 return MUTT_CMD_ERROR;
173 }
174 else
175 {
176 buf_printf(err, _("Unknown option %s"), name->data);
177 return MUTT_CMD_ERROR;
178 }
179 }
180
181 int rc = CSR_ERR_CODE;
182
183 if (DTYPE(he->type) == DT_MYVAR)
184 {
185 // my variables do not expand their value
186 rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, value->data, err);
187 }
188 else
189 {
190 command_set_expand_value(he->type, value);
191 rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, value->data, err);
192 }
193 if (CSR_RESULT(rc) != CSR_SUCCESS)
194 return MUTT_CMD_ERROR;
195
196 return MUTT_CMD_SUCCESS;
197}
198
212 struct Buffer *value, struct Buffer *err)
213{
214 assert(name);
215 assert(value);
216 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
217 if (!he)
218 {
219 buf_printf(err, _("Unknown option %s"), name->data);
220 return MUTT_CMD_ERROR;
221 }
222
223 command_set_expand_value(he->type, value);
224 int rc = cs_subset_he_string_minus_equals(NeoMutt->sub, he, value->data, err);
225 if (CSR_RESULT(rc) != CSR_SUCCESS)
226 return MUTT_CMD_ERROR;
227
228 return MUTT_CMD_SUCCESS;
229}
230
241static enum CommandResult command_set_unset(struct Buffer *name, struct Buffer *err)
242{
243 assert(name);
244 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
245 if (!he)
246 {
247 buf_printf(err, _("Unknown option %s"), name->data);
248 return MUTT_CMD_ERROR;
249 }
250
251 int rc = CSR_ERR_CODE;
252 if (DTYPE(he->type) == DT_MYVAR)
253 {
254 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
255 }
256 else if ((DTYPE(he->type) == DT_BOOL) || (DTYPE(he->type) == DT_QUAD))
257 {
258 rc = cs_subset_he_native_set(NeoMutt->sub, he, false, err);
259 }
260 else
261 {
262 rc = cs_subset_he_string_set(NeoMutt->sub, he, NULL, err);
263 }
264 if (CSR_RESULT(rc) != CSR_SUCCESS)
265 return MUTT_CMD_ERROR;
266
267 return MUTT_CMD_SUCCESS;
268}
269
280static enum CommandResult command_set_reset(struct Buffer *name, struct Buffer *err)
281{
282 assert(name);
283 // Handle special "reset all" syntax
284 if (mutt_str_equal(name->data, "all"))
285 {
286 struct HashElem **he_list = get_elem_list(NeoMutt->sub->cs);
287 if (!he_list)
288 return MUTT_CMD_ERROR;
289
290 for (size_t i = 0; he_list[i]; i++)
291 {
292 if (DTYPE(he_list[i]->type) == DT_MYVAR)
293 cs_subset_he_delete(NeoMutt->sub, he_list[i], err);
294 else
295 cs_subset_he_reset(NeoMutt->sub, he_list[i], NULL);
296 }
297
298 FREE(&he_list);
299 return MUTT_CMD_SUCCESS;
300 }
301
302 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
303 if (!he)
304 {
305 buf_printf(err, _("Unknown option %s"), name->data);
306 return MUTT_CMD_ERROR;
307 }
308
309 int rc = CSR_ERR_CODE;
310 if (DTYPE(he->type) == DT_MYVAR)
311 {
312 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
313 }
314 else
315 {
316 rc = cs_subset_he_reset(NeoMutt->sub, he, err);
317 }
318 if (CSR_RESULT(rc) != CSR_SUCCESS)
319 return MUTT_CMD_ERROR;
320
321 return MUTT_CMD_SUCCESS;
322}
323
334static enum CommandResult command_set_toggle(struct Buffer *name, struct Buffer *err)
335{
336 assert(name);
337 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
338 if (!he)
339 {
340 buf_printf(err, _("Unknown option %s"), name->data);
341 return MUTT_CMD_ERROR;
342 }
343
344 if (DTYPE(he->type) == DT_BOOL)
345 {
346 bool_he_toggle(NeoMutt->sub, he, err);
347 }
348 else if (DTYPE(he->type) == DT_QUAD)
349 {
350 quad_he_toggle(NeoMutt->sub, he, err);
351 }
352 else
353 {
354 buf_printf(err, _("Command '%s' can only be used with bool/quad variables"), "toggle");
355 return MUTT_CMD_ERROR;
356 }
357 return MUTT_CMD_SUCCESS;
358}
359
370static enum CommandResult command_set_query(struct Buffer *name, struct Buffer *err)
371{
372 assert(name);
373 // In the interactive case (outside of the initial parsing of neomuttrc) we
374 // support additional syntax: "set" (no arguments) and "set all".
375 // If not in interactive mode, we recognise them but do nothing.
376
377 // Handle "set" (no arguments), i.e. show list of changed variables.
378 if (buf_is_empty(name))
379 {
380 if (StartupComplete)
381 return set_dump(CS_DUMP_ONLY_CHANGED, err);
382 else
383 return MUTT_CMD_SUCCESS;
384 }
385 // Handle special "set all" syntax
386 if (mutt_str_equal(name->data, "all"))
387 {
388 if (StartupComplete)
389 return set_dump(CS_DUMP_NO_FLAGS, err);
390 else
391 return MUTT_CMD_SUCCESS;
392 }
393
394 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
395 if (!he)
396 {
397 buf_printf(err, _("Unknown option %s"), name->data);
398 return MUTT_CMD_ERROR;
399 }
400
401 buf_addstr(err, name->data);
402 buf_addch(err, '=');
403 struct Buffer *value = buf_pool_get();
404 int rc = cs_subset_he_string_get(NeoMutt->sub, he, value);
405 if (CSR_RESULT(rc) != CSR_SUCCESS)
406 {
407 buf_reset(err);
408 buf_addstr(err, value->data);
409 buf_pool_release(&value);
410 return MUTT_CMD_ERROR;
411 }
412 if (DTYPE(he->type) == DT_PATH)
413 mutt_pretty_mailbox(value->data, value->dsize);
414 pretty_var(value->data, err);
415 buf_pool_release(&value);
416
417 return MUTT_CMD_SUCCESS;
418}
419
425enum CommandResult parse_set(struct Buffer *buf, struct Buffer *s,
426 intptr_t data, struct Buffer *err)
427{
428 /* The order must match `enum MuttSetCommand` */
429 static const char *set_commands[] = { "set", "toggle", "unset", "reset" };
430
431 if (!buf || !s)
432 return MUTT_CMD_ERROR;
433
434 do
435 {
436 bool prefix = false;
437 bool query = false;
438 bool inv = (data == MUTT_SET_INV);
439 bool reset = (data == MUTT_SET_RESET);
440 bool unset = (data == MUTT_SET_UNSET);
441
442 if (*s->dptr == '?')
443 {
444 prefix = true;
445 query = true;
446 s->dptr++;
447 }
448 else if (mutt_str_startswith(s->dptr, "no"))
449 {
450 prefix = true;
451 unset = !unset;
452 s->dptr += 2;
453 }
454 else if (mutt_str_startswith(s->dptr, "inv"))
455 {
456 prefix = true;
457 inv = !inv;
458 s->dptr += 3;
459 }
460 else if (*s->dptr == '&')
461 {
462 prefix = true;
463 reset = true;
464 s->dptr++;
465 }
466
467 if (prefix && (data != MUTT_SET_SET))
468 {
469 buf_printf(err, _("Can't use 'inv', 'no', '&' or '?' with the '%s' command"),
470 set_commands[data]);
471 return MUTT_CMD_WARNING;
472 }
473
474 // get the variable name. Note that buf might be empty if no additional
475 // argument was given.
477 if (ret == -1)
478 return MUTT_CMD_ERROR;
479
480 bool bool_or_quad = false;
481 bool equals = false;
482 bool increment = false;
483 bool decrement = false;
484
485 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, buf->data);
486 if (he)
487 {
488 // Use the correct name if a synonym is used
489 buf_strcpy(buf, he->key.strkey);
490 bool_or_quad = ((DTYPE(he->type) == DT_BOOL) || (DTYPE(he->type) == DT_QUAD));
491 }
492
493 if (*s->dptr == '?')
494 {
495 if (prefix)
496 {
497 buf_printf(err, _("Can't use a prefix when querying a variable"));
498 return MUTT_CMD_WARNING;
499 }
500
501 if (reset || unset || inv)
502 {
503 buf_printf(err, _("Can't query option with the '%s' command"), set_commands[data]);
504 return MUTT_CMD_WARNING;
505 }
506
507 query = true;
508 s->dptr++;
509 }
510 else if ((*s->dptr == '+') || (*s->dptr == '-'))
511 {
512 if (prefix)
513 {
514 buf_printf(err, _("Can't use prefix when incrementing or decrementing a variable"));
515 return MUTT_CMD_WARNING;
516 }
517
518 if (reset || unset || inv)
519 {
520 buf_printf(err, _("Can't set option with the '%s' command"), set_commands[data]);
521 return MUTT_CMD_WARNING;
522 }
523 if (*s->dptr == '+')
524 increment = true;
525 else
526 decrement = true;
527
528 s->dptr++;
529 if (*s->dptr == '=')
530 {
531 equals = true;
532 s->dptr++;
533 }
534 else
535 {
536 buf_printf(err, _("'+' and '-' must be followed by '='"));
537 return MUTT_CMD_WARNING;
538 }
539 }
540 else if (*s->dptr == '=')
541 {
542 if (prefix)
543 {
544 buf_printf(err, _("Can't use prefix when setting a variable"));
545 return MUTT_CMD_WARNING;
546 }
547
548 if (reset || unset || inv)
549 {
550 buf_printf(err, _("Can't set option with the '%s' command"), set_commands[data]);
551 return MUTT_CMD_WARNING;
552 }
553
554 equals = true;
555 s->dptr++;
556 }
557
558 if (!bool_or_quad && (inv || (unset && prefix)))
559 {
560 if (data == MUTT_SET_SET)
561 {
562 buf_printf(err, _("Prefixes 'no' and 'inv' may only be used with bool/quad variables"));
563 }
564 else
565 {
566 buf_printf(err, _("Command '%s' can only be used with bool/quad variables"),
567 set_commands[data]);
568 }
569 return MUTT_CMD_WARNING;
570 }
571
572 // sanity checks for the above
573 // Each of inv, unset reset, query, equals implies that the others are not set.
574 // If none of them are set, then we are dealing with a "set foo" command.
575 // clang-format off
576 assert(!inv || !( unset || reset || query || equals ));
577 assert(!unset || !(inv || reset || query || equals ));
578 assert(!reset || !(inv || unset || query || equals ));
579 assert(!query || !(inv || unset || reset || equals ));
580 assert(!equals || !(inv || unset || reset || query || prefix));
581 // clang-format on
582 assert(!(increment && decrement)); // only one of increment or decrement is set
583 assert(!(increment || decrement) || equals); // increment/decrement implies equals
584 assert(!inv || bool_or_quad); // inv (aka toggle) implies bool or quad
585
587 if (query)
588 {
589 rc = command_set_query(buf, err);
590 return rc; // We can only do one query even if multiple config names are given
591 }
592 else if (reset)
593 {
594 rc = command_set_reset(buf, err);
595 }
596 else if (unset)
597 {
598 rc = command_set_unset(buf, err);
599 }
600 else if (inv)
601 {
602 rc = command_set_toggle(buf, err);
603 }
604 else if (equals)
605 {
606 // These three cases all need a value, since 'increment'/'decrement'
607 // implies 'equals', we can group them in this single case guarded by
608 // 'equals'.
609 struct Buffer *value = buf_pool_get();
611 if (increment)
612 rc = command_set_increment(buf, value, err);
613 else if (decrement)
614 rc = command_set_decrement(buf, value, err);
615 else
616 rc = command_set_set(buf, value, err);
617 buf_pool_release(&value);
618 }
619 else
620 {
621 // This is the "set foo" case which has different meanings depending on
622 // the type of the config variable
623 if (bool_or_quad)
624 {
625 struct Buffer *yes = buf_pool_get();
626 buf_addstr(yes, "yes");
627 rc = command_set_set(buf, yes, err);
628 buf_pool_release(&yes);
629 }
630 else
631 {
632 rc = command_set_query(buf, err);
633 return rc; // We can only do one query even if multiple config names are given
634 }
635 }
636 // Short circuit (i.e. skipping further config variable names) if the action on
637 // the current variable failed.
638 if (rc != MUTT_CMD_SUCCESS)
639 return rc;
640 } while (MoreArgs(s));
641
642 return MUTT_CMD_SUCCESS;
643}
int bool_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:196
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:75
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:290
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:394
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:600
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
enum CommandResult set_dump(ConfigDumpFlags flags, struct Buffer *err)
Dump list of config variables into a file/pager.
Definition: commands.c:873
Functions to parse commands in a config file.
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:85
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:475
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Definition: globals.c:38
struct HashElem * cs_create_variable(const struct ConfigSet *cs, struct ConfigDef *cdef, struct Buffer *err)
Create and register one config item.
Definition: set.c:318
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
#define CSR_RESULT(x)
Definition: set.h:52
bool StartupComplete
When the config has been read.
Definition: main.c:191
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
Convenience wrapper for the core headers.
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:50
Text parser.
#define TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: extract.h:54
#define TOKEN_EQUAL
Treat '=' as a special.
Definition: extract.h:47
#define TOKEN_PLUS
Treat '+' as a special.
Definition: extract.h:57
#define MoreArgs(buf)
Definition: extract.h:32
#define TOKEN_MINUS
Treat '-' as a special.
Definition: extract.h:58
#define TOKEN_QUESTION
Treat '?' as a special.
Definition: extract.h:56
enum CommandResult parse_set(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'set' family of commands - Implements Command::parse() -.
Definition: set.c:425
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_path_tilde(struct Buffer *path, const char *homedir)
Expand '~' in a path.
Definition: path.c:194
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:654
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:230
Many unsorted constants and some structs.
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:328
Some miscellaneous functions.
static enum CommandResult command_set_toggle(struct Buffer *name, struct Buffer *err)
Toggle a boolean or quad variable.
Definition: set.c:334
static enum CommandResult command_set_set(struct Buffer *name, struct Buffer *value, struct Buffer *err)
Set a variable to the given value.
Definition: set.c:101
static enum CommandResult command_set_reset(struct Buffer *name, struct Buffer *err)
Reset a variable.
Definition: set.c:280
static enum CommandResult command_set_unset(struct Buffer *name, struct Buffer *err)
Unset a variable.
Definition: set.c:241
static enum CommandResult command_set_query(struct Buffer *name, struct Buffer *err)
Query a variable.
Definition: set.c:370
static enum CommandResult command_set_increment(struct Buffer *name, struct Buffer *value, struct Buffer *err)
Increment a variable by a value.
Definition: set.c:156
static void command_set_expand_value(uint32_t type, struct Buffer *value)
Expand special characters.
Definition: set.c:60
static enum CommandResult command_set_decrement(struct Buffer *name, struct Buffer *value, struct Buffer *err)
Decrement a variable by a value.
Definition: set.c:211
Parse the 'set' command.
@ MUTT_SET_INV
default is to invert all vars
Definition: set.h:37
@ MUTT_SET_SET
default is to set all vars
Definition: set.h:36
@ MUTT_SET_RESET
default is to reset all vars to default
Definition: set.h:39
@ MUTT_SET_UNSET
default is to unset all vars
Definition: set.h:38
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
int quad_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a quad.
Definition: quad.c:217
String manipulation buffer.
Definition: buffer.h:36
char * dptr
Current read/write position.
Definition: buffer.h:38
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
Definition: set.h:64
const char * name
User-visible name.
Definition: set.h:65
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
The item stored in a Hash Table.
Definition: hash.h:43
union HashKey key
Key representing the data.
Definition: hash.h:45
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
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
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:424
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:332
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:275
int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Delete config item from a config.
Definition: subset.c:445
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:79
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:312
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:364
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:402
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:187
#define IS_MAILBOX(flags)
Definition: types.h:122
#define DTYPE(t)
Definition: types.h:50
#define D_PATH_DIR
Path is a directory.
Definition: types.h:103
#define D_PATH_FILE
Path is a file.
Definition: types.h:104
@ DT_BOOL
boolean option
Definition: types.h:32
@ DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:41
@ DT_MYVAR
a user-defined variable (my_foo)
Definition: types.h:38
@ DT_PATH
a path to a file/directory
Definition: types.h:40
#define IS_COMMAND(flags)
Definition: types.h:123
const char * strkey
String key.
Definition: hash.h:35