NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
neomutt.c
Go to the documentation of this file.
1
23
29
30#include "config.h"
31#include <errno.h>
32#include <locale.h>
33#include <stdio.h>
34#include <string.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include "mutt/lib.h"
38#include "config/lib.h"
39#include "neomutt.h"
40#include "account.h"
41#include "command.h"
42#include "mailbox.h"
43#include "module_api.h"
44#include "muttlib.h"
45#ifdef ENABLE_NLS
46#include <libintl.h>
47#endif
48
49struct NeoMutt *NeoMutt = NULL;
50
52#define CONFIG_INIT_TYPE(CS, NAME) \
53 extern const struct ConfigSetType Cst##NAME; \
54 cs_register_type(CS, &Cst##NAME)
55
57#define CONFIG_INIT_VARS(CS, NAME) \
58 bool config_init_##NAME(struct ConfigSet *cs); \
59 config_init_##NAME(CS)
60
67static bool init_env(struct NeoMutt *n, char **envp)
68{
69 if (!n)
70 return false;
71
74
75 envlist_free(&n->env);
76 n->env = envlist_init(envp);
77
78 return true;
79}
80
86static bool init_locale(struct NeoMutt *n)
87{
88 if (!n)
89 return false;
90
91 setlocale(LC_ALL, "");
92
93#ifdef ENABLE_NLS
94 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
95 if (domdir)
96 bindtextdomain(PACKAGE, domdir);
97 else
98 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
99 textdomain(PACKAGE);
100#endif
101
102 n->time_c_locale = duplocale(LC_GLOBAL_LOCALE);
103 if (n->time_c_locale)
104 n->time_c_locale = newlocale(LC_TIME_MASK, "C", n->time_c_locale);
105
106 if (!n->time_c_locale)
107 {
108 mutt_error("%s", strerror(errno)); // LCOV_EXCL_LINE
109 return false; // LCOV_EXCL_LINE
110 }
111
112#ifndef LOCALES_HACK
113 /* Do we have a locale definition? */
114 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
115 {
116 OptLocales = true;
117 }
118#endif
119
120 return true;
121}
122
123#ifdef ENABLE_NLS
128static void localise_config(struct ConfigSet *cs)
129{
130 struct Buffer *value = buf_pool_get();
131 struct HashElemArray hea = get_elem_list(cs, GEL_ALL_CONFIG);
132 struct HashElem **hep = NULL;
133
134 ARRAY_FOREACH(hep, &hea)
135 {
136 struct HashElem *he = *hep;
137 if (!(he->type & D_L10N_STRING))
138 continue;
139
140 buf_reset(value);
141 cs_he_initial_get(cs, he, value);
142
143 // Lookup the translation
144 const char *l10n = gettext(buf_string(value));
145 config_he_set_initial(cs, he, l10n);
146 }
147
148 ARRAY_FREE(&hea);
149 buf_pool_release(&value);
150}
151#endif
152
157static void reset_tilde(struct ConfigSet *cs)
158{
159 static const char *names[] = { "folder", "mbox", "postponed", "record" };
160
161 struct Buffer *value = buf_pool_get();
162 for (size_t i = 0; i < countof(names); i++)
163 {
164 struct HashElem *he = cs_get_elem(cs, names[i]);
165 if (!he)
166 continue;
167 buf_reset(value);
168 cs_he_initial_get(cs, he, value);
169 expand_path(value, false);
170 config_he_set_initial(cs, he, value->data);
171 }
172 buf_pool_release(&value);
173}
174
185static bool init_config(struct NeoMutt *n)
186{
187 if (!n)
188 return false;
189
190 n->cs = cs_new(500);
191
192 n->sub = cs_subset_new(NULL, NULL, n->notify);
194 n->sub->cs = n->cs;
195
196 bool rc = true;
197
198 // Set up the Config Types
199 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
200 {
201 const struct Module *mod = n->modules[id];
202 if (!mod)
203 continue;
204
205 if (mod->config_define_types)
206 {
207 mutt_debug(LL_DEBUG3, "%s:config_define_types()\n", mod->name);
208 rc &= mod->config_define_types(n, n->sub->cs);
209 }
210 }
211
212 if (!rc)
213 return false;
214
215 // Define the Config Variables
216 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
217 {
218 const struct Module *mod = n->modules[id];
219 if (!mod)
220 continue;
221
223 {
224 mutt_debug(LL_DEBUG3, "%s:config_define_variables()\n", mod->name);
225 rc &= mod->config_define_variables(n, n->sub->cs);
226 }
227 }
228
229 if (!rc)
230 return false;
231
232 // Post-processing
233#ifdef ENABLE_NLS
235#endif
236 reset_tilde(n->sub->cs);
237
238 /* Unset suspend by default if we're the session leader */
239 if (getsid(0) == getpid())
240 config_str_set_initial(n->sub->cs, "suspend", "no");
241
242 return rc;
243}
244
250static bool init_commands(struct NeoMutt *n)
251{
252 if (!n)
253 return false;
254
255 struct CommandArray *ca = &n->commands;
256
257 bool rc = true;
258
259 // Set up the Config Types
260 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
261 {
262 const struct Module *mod = n->modules[id];
263 if (!mod)
264 continue;
265
266 if (mod->commands_register)
267 {
268 mutt_debug(LL_DEBUG3, "%s:commands_register()\n", mod->name);
269 rc &= mod->commands_register(n, ca);
270 }
271 }
272
273 return rc;
274}
275
281static bool init_modules(struct NeoMutt *n)
282{
283 if (!n)
284 return false;
285
286 bool rc = true;
287
288 // Initialise the Modules
289 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
290 {
291 const struct Module *mod = n->modules[id];
292 if (!mod)
293 continue;
294
295 if (mod->init)
296 {
297 mutt_debug(LL_DEBUG3, "%s:init()\n", mod->name);
298 rc &= mod->init(n);
299 }
300 }
301
302 return rc;
303}
304
310static bool init_gui_modules(struct NeoMutt *n)
311{
312 if (!n)
313 return false;
314
315 bool rc = true;
316
317 // Initialise the Gui Modules
318 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
319 {
320 const struct Module *mod = n->modules[id];
321 if (!mod)
322 continue;
323
324 if (mod->gui_init)
325 {
326 mutt_debug(LL_DEBUG3, "%s:gui_init()\n", mod->name);
327 rc &= mod->gui_init(n);
328 }
329 }
330
331 return rc;
332}
333
338struct NeoMutt *neomutt_new(void)
339{
340 return MUTT_MEM_CALLOC(1, struct NeoMutt);
341}
342
350bool neomutt_init(struct NeoMutt *n, char **envp, const struct Module **modules)
351{
352 if (!n || !modules)
353 return false;
354
355 for (int i = 0; modules[i]; i++)
356 {
357 const struct Module *mod = modules[i];
358
359 n->modules[mod->mid] = mod;
360 }
361
362 if (!init_env(n, envp))
363 return false;
364
365 if (!init_locale(n))
366 return false;
367
368 if (!init_config(n))
369 return false;
370
371 if (!init_commands(n))
372 return false;
373
374 if (!init_modules(n))
375 return false;
376
377 ARRAY_INIT(&n->accounts);
378 n->notify = notify_new();
380
383
386
387 // Change the current umask, and save the original one
388 n->user_default_umask = umask(077);
389 mutt_debug(LL_DEBUG1, "user's umask %03o\n", n->user_default_umask);
390 mutt_debug(LL_DEBUG3, "umask set to 077\n");
391
392 return true;
393}
394
401{
402 if (!n)
403 return false;
404
405 return init_gui_modules(n);
406}
407
413static bool cleanup_modules(struct NeoMutt *n)
414{
415 if (!n)
416 return false;
417
418 bool rc = true;
419
420 // Cleanup the Modules
421 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
422 {
423 const struct Module *mod = n->modules[id];
424 if (!mod)
425 continue;
426
427 void *mod_data = n->module_data[mod->mid];
428
429 if (mod->cleanup && mod_data)
430 {
431 n->module_data[mod->mid] = NULL;
432 mutt_debug(LL_DEBUG3, "%s:cleanup()\n", mod->name);
433 rc &= mod->cleanup(n, mod_data);
434 }
435
436 if (n->module_data[mod->mid])
437 {
438 mutt_debug(LL_DEBUG1, "Module %s didn't clean up its data\n", mod->name);
439 rc = false;
440 }
441 }
442
443 return rc;
444}
445
450static void cleanup_gui_modules(struct NeoMutt *n)
451{
452 if (!n)
453 return;
454
455 // Cleanup the Gui Modules
456 for (enum ModuleId id = MODULE_ID_MAIN; id < MODULE_ID_MAX; id++)
457 {
458 const struct Module *mod = n->modules[id];
459 if (!mod)
460 continue;
461
462 if (mod->gui_cleanup)
463 {
464 mutt_debug(LL_DEBUG3, "%s:gui_cleanup()\n", mod->name);
465 mod->gui_cleanup(n);
466 }
467 }
468}
469
475{
476 if (!n)
477 return;
478
480
483}
484
490{
491 if (!n)
492 return;
493
495}
496
501void neomutt_free(struct NeoMutt **ptr)
502{
503 if (!ptr || !*ptr)
504 return;
505
506 struct NeoMutt *n = *ptr;
507
509
510 if (n->sub)
511 {
512 struct ConfigSet *cs = n->sub->cs;
513 cs_subset_free(&n->sub);
514 cs_free(&cs);
515 }
516
519 notify_free(&n->notify);
520 if (n->time_c_locale)
521 freelocale(n->time_c_locale);
522
523 FREE(&n->home_dir);
524 FREE(&n->username);
525
526 envlist_free(&n->env);
527
528 FREE(ptr);
529}
530
537bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
538{
539 if (!n || !a)
540 return false;
541
542 ARRAY_ADD(&n->accounts, a);
544
545 mutt_debug(LL_NOTIFY, "NT_ACCOUNT_ADD: %s %p\n",
546 mailbox_get_type_name(a->type), (void *) a);
547 struct EventAccount ev_a = { a };
549 return true;
550}
551
557void neomutt_account_remove(struct NeoMutt *n, struct Account *a)
558{
559 if (!n || !a || ARRAY_EMPTY(&n->accounts))
560 return;
561
562 struct Account **ap = NULL;
563 ARRAY_FOREACH(ap, &n->accounts)
564 {
565 if ((*ap) != a)
566 continue;
567
568 ARRAY_REMOVE(&n->accounts, ap);
569 account_free(&a);
570 break;
571 }
572}
573
579{
580 if (!n)
581 return;
582
583 if (!ARRAY_EMPTY(&n->accounts))
584 {
585 mutt_debug(LL_NOTIFY, "NT_ACCOUNT_DELETE_ALL\n");
586 struct EventAccount ev_a = { NULL };
588
589 struct Account **ap = NULL;
590 ARRAY_FOREACH(ap, &n->accounts)
591 {
592 account_free(ap);
593 }
594 }
595
596 ARRAY_FREE(&n->accounts);
597}
598
607struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
608{
609 struct MailboxArray ma = ARRAY_HEAD_INITIALIZER;
610
611 if (!n)
612 return ma;
613
614 struct Account **ap = NULL;
615 struct Mailbox **mp = NULL;
616
617 ARRAY_FOREACH(ap, &n->accounts)
618 {
619 struct Account *a = *ap;
620 if ((type > MUTT_UNKNOWN) && (a->type != type))
621 continue;
622
623 ARRAY_FOREACH(mp, &a->mailboxes)
624 {
625 ARRAY_ADD(&ma, *mp);
626 }
627 }
628
629 return ma;
630}
631
644FILE *mutt_file_fopen_masked_full(const char *path, const char *mode,
645 const char *file, int line, const char *func)
646{
647 // Set the user's umask (saved on startup)
648 mode_t old_umask = umask(NeoMutt->user_default_umask);
649 mutt_debug(LL_DEBUG3, "umask set to %03o\n", NeoMutt->user_default_umask);
650
651 // The permissions will be limited by the umask
652 FILE *fp = mutt_file_fopen_full(path, mode, 0666, file, line, func);
653
654 umask(old_umask); // Immediately restore the umask
655 mutt_debug(LL_DEBUG3, "umask set to %03o\n", old_umask);
656
657 return fp;
658}
659
666void *neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
667{
668 if (!n)
669 return NULL;
670
671 return n->module_data[id];
672}
673
680void neomutt_set_module_data(struct NeoMutt *n, enum ModuleId id, void *data)
681{
682 if (!n)
683 return;
684
685 n->module_data[id] = data;
686}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_REMOVE(head, elem)
Remove an entry from the array, shifting down the subsequent entries.
Definition array.h:355
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_INIT(head)
Initialize an array.
Definition array.h:65
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
NeoMutt commands API.
bool config_str_set_initial(struct ConfigSet *cs, const char *name, const char *value)
Set the initial value of a Config Option.
Definition helpers.c:332
bool config_he_set_initial(struct ConfigSet *cs, struct HashElem *he, const char *value)
Set the initial value of a Config Option.
Definition helpers.c:312
Convenience wrapper for the config headers.
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition set.c:176
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition set.c:142
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition set.c:128
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition set.c:582
void account_free(struct Account **ptr)
Free an Account.
Definition account.c:148
A group of associated Mailboxes.
@ NT_ACCOUNT_ADD
Account has been added.
Definition account.h:67
@ NT_ACCOUNT_DELETE_ALL
All Accounts are about to be deleted.
Definition account.h:69
void commands_clear(struct CommandArray *ca)
Clear an Array of Commands.
Definition command.c:70
const char * mailbox_get_type_name(enum MailboxType type)
Get the type of a Mailbox.
Definition mailbox.c:325
Representation of a mailbox.
MailboxType
Supported mailbox formats.
Definition mailbox.h:40
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition mailbox.h:43
void envlist_free(char ***envp)
Free the private copy of the environment.
Definition envlist.c:42
char ** envlist_init(char **envp)
Create a copy of the environment.
Definition envlist.c:58
FILE * mutt_file_fopen_full(const char *path, const char *mode, const mode_t perms, const char *file, int line, const char *func)
Call fopen() safely.
Definition file.c:556
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:50
bool OptLocales
(pseudo) set if user has valid locale definition
Definition mbyte.c:45
#define countof(x)
Definition memory.h:49
#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
Module API.
ModuleId
Unique Module Ids.
Definition module_api.h:42
@ MODULE_ID_MAX
Definition module_api.h:95
@ MODULE_ID_MAIN
ModuleMain, NeoMutt Email Client
Definition module_api.h:44
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
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition string.c:732
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
Some miscellaneous functions.
void neomutt_set_module_data(struct NeoMutt *n, enum ModuleId id, void *data)
Set the private data for a Module.
Definition neomutt.c:680
struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
Get an Array of matching Mailboxes.
Definition neomutt.c:607
static bool init_modules(struct NeoMutt *n)
Initialise the Modules.
Definition neomutt.c:281
static bool init_locale(struct NeoMutt *n)
Initialise the Locale/NLS settings.
Definition neomutt.c:86
static void localise_config(struct ConfigSet *cs)
Localise some config.
Definition neomutt.c:128
void neomutt_account_remove(struct NeoMutt *n, struct Account *a)
Remove an Account from the global list.
Definition neomutt.c:557
static void cleanup_gui_modules(struct NeoMutt *n)
Clean up each of the Gui Modules.
Definition neomutt.c:450
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition neomutt.c:157
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition neomutt.c:537
void neomutt_cleanup(struct NeoMutt *n)
Clean up NeoMutt and Modules.
Definition neomutt.c:474
bool neomutt_init(struct NeoMutt *n, char **envp, const struct Module **modules)
Initialise NeoMutt.
Definition neomutt.c:350
static bool cleanup_modules(struct NeoMutt *n)
Clean up each of the Modules.
Definition neomutt.c:413
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
void neomutt_accounts_free(struct NeoMutt *n)
Definition neomutt.c:578
void neomutt_gui_cleanup(struct NeoMutt *n)
Clean up the GUI Modules.
Definition neomutt.c:489
FILE * mutt_file_fopen_masked_full(const char *path, const char *mode, const char *file, int line, const char *func)
Wrapper around mutt_file_fopen_full()
Definition neomutt.c:644
struct NeoMutt * neomutt_new(void)
Create the main NeoMutt object.
Definition neomutt.c:338
static bool init_config(struct NeoMutt *n)
Initialise the config system.
Definition neomutt.c:185
static bool init_gui_modules(struct NeoMutt *n)
Initialise the Gui Modules.
Definition neomutt.c:310
static bool init_env(struct NeoMutt *n, char **envp)
Initialise the Environment.
Definition neomutt.c:67
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition neomutt.c:501
static bool init_commands(struct NeoMutt *n)
Initialise the NeoMutt commands.
Definition neomutt.c:250
bool neomutt_gui_init(struct NeoMutt *n)
Initialise the GUI Modules.
Definition neomutt.c:400
Container for Accounts, Notifications.
@ NT_ACCOUNT
Account has changed, NotifyAccount, EventAccount.
Definition notify_type.h:36
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
A group of associated Mailboxes.
Definition account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition account.h:37
struct Notify * notify
Notifications: NotifyAccount, EventAccount.
Definition account.h:41
struct MailboxArray mailboxes
All Mailboxes.
Definition account.h:40
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
Container for lots of config items.
Definition set.h:251
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition subset.h:51
struct ConfigSet * cs
Parent ConfigSet.
Definition subset.h:50
enum ConfigScope scope
Scope of Subset, e.g. SET_SCOPE_ACCOUNT.
Definition subset.h:48
An Event that happened to an Account.
Definition account.h:77
The item stored in a Hash Table.
Definition hash.h:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
A mailbox.
Definition mailbox.h:81
bool(* gui_init)(struct NeoMutt *n)
Definition module_api.h:167
void(* gui_cleanup)(struct NeoMutt *n)
Definition module_api.h:178
const char * name
Name of the library module.
Definition module_api.h:106
bool(* cleanup)(struct NeoMutt *n, void *data)
Definition module_api.h:191
enum ModuleId mid
Module Id.
Definition module_api.h:105
bool(* init)(struct NeoMutt *n)
Definition module_api.h:117
bool(* config_define_types)(struct NeoMutt *n, struct ConfigSet *cs)
Definition module_api.h:130
bool(* commands_register)(struct NeoMutt *n, struct CommandArray *ca)
Definition module_api.h:156
bool(* config_define_variables)(struct NeoMutt *n, struct ConfigSet *cs)
Definition module_api.h:143
Container for Accounts, Notifications.
Definition neomutt.h:41
const struct Module * modules[MODULE_ID_MAX]
Library modules.
Definition neomutt.h:42
struct Notify * notify_timeout
Timeout notifications handler.
Definition neomutt.h:47
struct AccountArray accounts
All Accounts.
Definition neomutt.h:50
struct CommandArray commands
NeoMutt commands.
Definition neomutt.h:53
struct Notify * notify_resize
Window resize notifications handler.
Definition neomutt.h:46
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
char * username
User's login name.
Definition neomutt.h:56
void * module_data[MODULE_ID_MAX]
Private library module data.
Definition neomutt.h:43
mode_t user_default_umask
User's default file writing permissions (inferred from umask)
Definition neomutt.h:52
char * home_dir
User's home directory.
Definition neomutt.h:55
struct ConfigSet * cs
Config set.
Definition neomutt.h:48
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition neomutt.h:51
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition subset.c:81
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
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition subset.h:81
@ SET_SCOPE_NEOMUTT
This Config is NeoMutt-specific (global)
Definition subset.h:37
#define D_L10N_STRING
String can be localised.
Definition types.h:82