Commit 4f12cc0c 4f12cc0c9924afccb721ef418efe6e83c95c0cd1 by Sergey Poznyakoff

Further improvements in `mail'.

* NEWS: Update.
* mail/mail.h (MOPTF_UNSET): New constant.
* mail/mailvar.c (MAILVAR_TYPEMASK): New define.
(struct mailvar_symbol): Remove `type'. Add `handler'.
The latter supplies special handling for certain variables.
(mailvar_tab): Update accordingly.
Implement "debug" variable.
(mailvar_set): Enforce correct variable type in variable-strict mode.
Handle MOPTF_UNSET flag.
Remove kludgy special handling for some attributes, use sym->handler
instead.
(set_decode_fallback, set_replyregex)
(set_screen, set_mailbox_debug_level, set_debug): New functions.
(describe_symbol): Handle alternative symbol types.
* mail/set.c: Use MOPTF_UNSET when unsetting the variable.
* mail/source.c: Set correct locus. This allows to display
locations along with error messages.
1 parent 0a7e5933
...@@ -47,7 +47,14 @@ In addition, the form ...@@ -47,7 +47,14 @@ In addition, the form
47 mail --file=mymbox 47 mail --file=mymbox
48 48
49 is also allowed. 49 is also allowed.
50 50
51 ** error locations
52
53 Diagnostic messages issued while processing `source' command
54 include file locations, in compliance with the GNU standards. This
55 also includes diagnostics issued during processing of the
56 system or user configuration file.
57
51 ** envelope command 58 ** envelope command
52 59
53 The env[elope] command displays the SMTP envelopes of the messages 60 The env[elope] command displays the SMTP envelopes of the messages
......
...@@ -344,6 +344,7 @@ extern void mailvar_variable_format (FILE *fp, ...@@ -344,6 +344,7 @@ extern void mailvar_variable_format (FILE *fp,
344 344
345 #define MOPTF_OVERWRITE 0x001 345 #define MOPTF_OVERWRITE 0x001
346 #define MOPTF_QUIET 0x002 346 #define MOPTF_QUIET 0x002
347 #define MOPTF_UNSET 0x004
347 extern int mailvar_set (const char *name, void *value, 348 extern int mailvar_set (const char *name, void *value,
348 enum mailvar_type type, int flags); 349 enum mailvar_type type, int flags);
349 extern int util_isdeleted (size_t msgno); 350 extern int util_isdeleted (size_t msgno);
......
...@@ -20,160 +20,241 @@ ...@@ -20,160 +20,241 @@
20 #define MAILVAR_RDONLY 0x0002 20 #define MAILVAR_RDONLY 0x0002
21 #define MAILVAR_HIDDEN 0x0004 21 #define MAILVAR_HIDDEN 0x0004
22 22
23 #define MAILVAR_TYPEMASK(type) (1<<(8+(type)))
24
23 struct mailvar_symbol 25 struct mailvar_symbol
24 { 26 {
25 struct mailvar_variable var; 27 struct mailvar_variable var;
26 enum mailvar_type type;
27 int flags; 28 int flags;
28 char *descr; 29 char *descr;
30 void (*handler) (struct mailvar_variable *);
29 }; 31 };
30 32
31 mu_list_t mailvar_list = NULL; 33 mu_list_t mailvar_list = NULL;
32 34
35 static void set_decode_fallback (struct mailvar_variable *);
36 static void set_replyregex (struct mailvar_variable *);
37 static void set_screen (struct mailvar_variable *);
38 static void set_debug (struct mailvar_variable *);
39
33 struct mailvar_symbol mailvar_tab[] = 40 struct mailvar_symbol mailvar_tab[] =
34 { 41 {
42 /* FIXME: */
43 { { "allnet", }, MAILVAR_HIDDEN },
44
35 /* For compatibility with other mailx implementations. 45 /* For compatibility with other mailx implementations.
36 Never used, always true. */ 46 Never used, always true. */
37 { { "append", }, mailvar_type_boolean, MAILVAR_RDONLY, 47 { { "append", },
48 MAILVAR_TYPEMASK (mailvar_type_boolean) | MAILVAR_RDONLY,
38 N_("messages saved in mbox are appended to the end rather than prepended") }, 49 N_("messages saved in mbox are appended to the end rather than prepended") },
39 { { "appenddeadletter", }, mailvar_type_boolean, 0, 50 { { "appenddeadletter", },
51 MAILVAR_TYPEMASK (mailvar_type_boolean),
40 N_("append the contents of canceled letter to dead.letter file") }, 52 N_("append the contents of canceled letter to dead.letter file") },
41 { { "askbcc", }, mailvar_type_boolean, 0, 53 { { "askbcc", },
54 MAILVAR_TYPEMASK (mailvar_type_boolean),
42 N_("prompt user for bcc before composing the message") }, 55 N_("prompt user for bcc before composing the message") },
43 { { "askcc", }, mailvar_type_boolean, 0, 56 { { "askcc", },
57 MAILVAR_TYPEMASK (mailvar_type_boolean),
44 N_("prompt user for cc before composing the message") }, 58 N_("prompt user for cc before composing the message") },
45 { { "ask", }, mailvar_type_boolean, 0, 59 { { "ask", },
60 MAILVAR_TYPEMASK (mailvar_type_boolean),
46 N_("prompt user for subject before composing the message") }, 61 N_("prompt user for subject before composing the message") },
47 { { "asksub", }, mailvar_type_whatever, MAILVAR_ALIAS, NULL }, 62 { { "asksub", }, MAILVAR_ALIAS, NULL },
48 { { "autoinc", }, mailvar_type_boolean, 0, 63 { { "autoinc", },
64 MAILVAR_TYPEMASK (mailvar_type_boolean),
49 N_("automatically incorporate newly arrived messages")}, 65 N_("automatically incorporate newly arrived messages")},
50 { { "autoprint", }, mailvar_type_boolean, 0, 66 { { "autoprint", },
67 MAILVAR_TYPEMASK (mailvar_type_boolean),
51 N_("delete command behaves like dp") }, 68 N_("delete command behaves like dp") },
52 { { "bang", }, mailvar_type_boolean, 0, 69 { { "bang", },
70 MAILVAR_TYPEMASK (mailvar_type_boolean),
53 N_("replace every occurrence of ! in arguments to the shell command" 71 N_("replace every occurrence of ! in arguments to the shell command"
54 " with the last executed command") }, 72 " with the last executed command") },
55 { { "charset", }, mailvar_type_string, 0, 73 { { "charset", },
74 MAILVAR_TYPEMASK (mailvar_type_string),
56 N_("output character set for decoded header fields") }, 75 N_("output character set for decoded header fields") },
57 { { "cmd", }, mailvar_type_string, 0, 76 { { "cmd", },
77 MAILVAR_TYPEMASK (mailvar_type_string),
58 N_("default shell command for pipe") }, 78 N_("default shell command for pipe") },
59 { { "columns", }, mailvar_type_number, 0, 79 { { "columns", },
80 MAILVAR_TYPEMASK (mailvar_type_number),
60 N_("number of columns on terminal screen") }, 81 N_("number of columns on terminal screen") },
61 { { "crt", }, mailvar_type_number, 0, 82 { { "crt", },
83 MAILVAR_TYPEMASK (mailvar_type_number) |
84 MAILVAR_TYPEMASK (mailvar_type_boolean),
62 N_("if numeric, sets the minimum number of output lines needed " 85 N_("if numeric, sets the minimum number of output lines needed "
63 "to engage paging; if boolean, use the height of the terminal " 86 "to engage paging; if boolean, use the height of the terminal "
64 "screen to compute the threshold") }, 87 "screen to compute the threshold") },
65 { { "datefield", }, mailvar_type_boolean, 0, 88 { { "datefield", },
89 MAILVAR_TYPEMASK (mailvar_type_boolean),
66 N_("get date from the `Date:' header, instead of the envelope") }, 90 N_("get date from the `Date:' header, instead of the envelope") },
67 { { "dot", }, mailvar_type_boolean, 0, 91 { { "debug", },
92 MAILVAR_TYPEMASK (mailvar_type_string) |
93 MAILVAR_TYPEMASK (mailvar_type_boolean),
94 N_("set Mailutils debug level"),
95 set_debug },
96 { { "decode-fallback", },
97 MAILVAR_TYPEMASK (mailvar_type_string),
98 N_("how to represent characters that cannot be rendered using the "
99 "current character set"),
100 set_decode_fallback },
101 { { "dot", },
102 MAILVAR_TYPEMASK (mailvar_type_boolean),
68 N_("input message is terminated with a dot alone on a line") }, 103 N_("input message is terminated with a dot alone on a line") },
69 { { "editheaders", }, mailvar_type_boolean, 0, 104 { { "editheaders", },
105 MAILVAR_TYPEMASK (mailvar_type_boolean),
70 N_("allow to edit message headers while composing") }, 106 N_("allow to edit message headers while composing") },
71 { { "emptystart", }, mailvar_type_boolean, 0, 107 { { "emptystart", },
108 MAILVAR_TYPEMASK (mailvar_type_boolean),
72 N_("start interactive mode if the mailbox is empty") }, 109 N_("start interactive mode if the mailbox is empty") },
73 { { "escape", }, mailvar_type_string, 0, 110 { { "escape", },
111 MAILVAR_TYPEMASK (mailvar_type_string),
74 N_("character denoting escapes") }, 112 N_("character denoting escapes") },
75 { { "flipr", }, mailvar_type_boolean, 0, 113 { { "flipr", },
114 MAILVAR_TYPEMASK (mailvar_type_boolean),
76 N_("swap the meaning of reply and Reply commands") }, 115 N_("swap the meaning of reply and Reply commands") },
77 { { "folder", }, mailvar_type_string, 0, 116 { { "folder", },
117 MAILVAR_TYPEMASK (mailvar_type_string),
78 N_("folder directory name") }, 118 N_("folder directory name") },
79 { { "fromfield", }, mailvar_type_boolean, 0, 119 { { "fromfield", },
120 MAILVAR_TYPEMASK (mailvar_type_boolean),
80 N_("get sender address from the `From:' header, instead of " 121 N_("get sender address from the `From:' header, instead of "
81 "the envelope") }, 122 "the envelope") },
82 { { "gnu-last-command", }, mailvar_type_boolean, MAILVAR_RDONLY, 123 { { "gnu-last-command", },
124 MAILVAR_TYPEMASK (mailvar_type_string) | MAILVAR_RDONLY,
83 N_("last executed command line") }, 125 N_("last executed command line") },
84 { { "header", }, mailvar_type_boolean, 0, 126 { { "header", },
127 MAILVAR_TYPEMASK (mailvar_type_boolean),
85 N_("run the `headers' command after entering interactive mode") }, 128 N_("run the `headers' command after entering interactive mode") },
86 { { "hold", }, mailvar_type_boolean, 0, 129 { { "hold", },
130 MAILVAR_TYPEMASK (mailvar_type_boolean),
87 N_("hold the read or saved messages in the system mailbox") }, 131 N_("hold the read or saved messages in the system mailbox") },
88 { { "ignore", }, mailvar_type_boolean, 0, 132 { { "ignore", },
133 MAILVAR_TYPEMASK (mailvar_type_boolean),
89 N_("ignore keyboard interrupts when composing messages") }, 134 N_("ignore keyboard interrupts when composing messages") },
90 { { "ignoreeof", }, mailvar_type_boolean, 0, 135 { { "ignoreeof", },
136 MAILVAR_TYPEMASK (mailvar_type_boolean),
91 N_("typing the EOF character terminates the letter being composed") }, 137 N_("typing the EOF character terminates the letter being composed") },
92 { { "indentprefix", }, mailvar_type_string, 0, 138 { { "indentprefix", },
139 MAILVAR_TYPEMASK (mailvar_type_string),
93 N_("string used by the ~m escape for indenting quoted messages") }, 140 N_("string used by the ~m escape for indenting quoted messages") },
94 { { "inplacealiases", }, mailvar_type_boolean, 0, 141 { { "inplacealiases", },
142 MAILVAR_TYPEMASK (mailvar_type_boolean),
95 N_("expand aliases in the address header field " 143 N_("expand aliases in the address header field "
96 "before entering send mode") }, 144 "before entering send mode") },
97 /* For compatibility with other mailx implementations. 145 /* For compatibility with other mailx implementations.
98 Never used, always true. */ 146 Never used, always true. */
99 { { "keep", }, mailvar_type_boolean, MAILVAR_RDONLY, 147 { { "keep", },
148 MAILVAR_TYPEMASK (mailvar_type_boolean) | MAILVAR_RDONLY,
100 N_("truncate the user's system mailbox when it is empty") }, 149 N_("truncate the user's system mailbox when it is empty") },
101 { { "keepsave", }, mailvar_type_boolean, 0, 150 { { "keepsave", },
151 MAILVAR_TYPEMASK (mailvar_type_boolean),
102 N_("keep saved messages in system mailbox too") }, 152 N_("keep saved messages in system mailbox too") },
103 { { "mailx", }, mailvar_type_boolean, 0, 153 { { "mailx", },
154 MAILVAR_TYPEMASK (mailvar_type_boolean),
104 N_("enable mailx compatibility mode") }, 155 N_("enable mailx compatibility mode") },
105 { { "metamail", }, mailvar_type_boolean, 0, 156 { { "metamail", },
157 MAILVAR_TYPEMASK (mailvar_type_boolean),
106 N_("interpret the content of message parts; if set to a string " 158 N_("interpret the content of message parts; if set to a string "
107 "specifies the name of the externam metamail command") }, 159 "specifies the name of the externam metamail command") },
108 { { "metoo", }, mailvar_type_boolean, 0, 160 { { "metoo", },
161 MAILVAR_TYPEMASK (mailvar_type_boolean),
109 N_("do not remove sender addresses from the recipient list") }, 162 N_("do not remove sender addresses from the recipient list") },
110 { { "mimenoask", }, mailvar_type_string, 0, 163 { { "mimenoask", },
164 MAILVAR_TYPEMASK (mailvar_type_string),
111 N_("a comma-separated list of MIME types for which " 165 N_("a comma-separated list of MIME types for which "
112 "no confirmation is needed before running metamail interpreter") }, 166 "no confirmation is needed before running metamail interpreter") },
113 { { "mode", }, mailvar_type_string, MAILVAR_RDONLY, 167 { { "mode", },
168 MAILVAR_TYPEMASK (mailvar_type_string) | MAILVAR_RDONLY,
114 N_("the name of current operation mode") }, 169 N_("the name of current operation mode") },
115 { { "nullbody", }, mailvar_type_boolean, 0, 170 { { "nullbody", },
171 MAILVAR_TYPEMASK (mailvar_type_boolean),
116 N_("accept messages with an empty body") }, 172 N_("accept messages with an empty body") },
117 { { "nullbodymsg", }, mailvar_type_string, 0, 173 { { "nullbodymsg", },
174 MAILVAR_TYPEMASK (mailvar_type_string),
118 N_("display this text when sending a message with empty body") }, 175 N_("display this text when sending a message with empty body") },
119 { { "outfolder", }, mailvar_type_string, 0, 176 { { "outfolder", },
177 MAILVAR_TYPEMASK (mailvar_type_string),
120 N_("keep created files in this folder") }, 178 N_("keep created files in this folder") },
121 { { "page", }, mailvar_type_boolean, 0, 179 { { "page", },
180 MAILVAR_TYPEMASK (mailvar_type_boolean),
122 N_("pipe command terminates each message with a linefeed") }, 181 N_("pipe command terminates each message with a linefeed") },
123 { { "prompt", }, mailvar_type_string, 0, 182 { { "prompt", },
183 MAILVAR_TYPEMASK (mailvar_type_string),
124 N_("command prompt sequence") }, 184 N_("command prompt sequence") },
125 { { "quit", }, mailvar_type_boolean, 0, 185 { { "quit", },
186 MAILVAR_TYPEMASK (mailvar_type_boolean),
126 N_("keyboard interrupts terminate the program") }, 187 N_("keyboard interrupts terminate the program") },
127 { { "rc", }, mailvar_type_boolean, 0, 188 { { "rc", },
189 MAILVAR_TYPEMASK (mailvar_type_boolean),
128 N_("read the system-wide configuration file upon startup") }, 190 N_("read the system-wide configuration file upon startup") },
129 { { "readonly", }, mailvar_type_boolean, 0, 191 { { "readonly", },
192 MAILVAR_TYPEMASK (mailvar_type_boolean),
130 N_("mailboxes are opened in readonly mode") }, 193 N_("mailboxes are opened in readonly mode") },
131 { { "record", }, mailvar_type_string, 0, 194 { { "record", },
195 MAILVAR_TYPEMASK (mailvar_type_string),
132 N_("save outgoing messages in this file") }, 196 N_("save outgoing messages in this file") },
133 { { "recursivealiases", }, mailvar_type_boolean, 0, 197 { { "recursivealiases", },
198 MAILVAR_TYPEMASK (mailvar_type_boolean),
134 N_("recursively expand aliases") }, 199 N_("recursively expand aliases") },
135 { { "regex", }, mailvar_type_boolean, 0, 200 { { "regex", },
201 MAILVAR_TYPEMASK (mailvar_type_boolean),
136 N_("use regular expressions in message specifications") }, 202 N_("use regular expressions in message specifications") },
137 { { "replyprefix", }, mailvar_type_string, 0, 203 { { "replyprefix", },
204 MAILVAR_TYPEMASK (mailvar_type_string),
138 N_("prefix for the subject line of a reply message") }, 205 N_("prefix for the subject line of a reply message") },
139 { { "replyregex", }, mailvar_type_string, 0, 206 { { "replyregex", },
140 N_("regexp for recognizing subject lines of reply messages") }, 207 MAILVAR_TYPEMASK (mailvar_type_string),
141 { { "save", }, mailvar_type_boolean, 0, 208 N_("regexp for recognizing subject lines of reply messages"),
209 set_replyregex },
210 { { "save", },
211 MAILVAR_TYPEMASK (mailvar_type_boolean),
142 N_("stored aborted messages in the user's dead.file") }, 212 N_("stored aborted messages in the user's dead.file") },
143 { { "screen", }, mailvar_type_number, 0, 213 { { "screen", },
144 N_("number of lines on terminal screen") }, 214 MAILVAR_TYPEMASK (mailvar_type_number),
145 { { "sendmail", }, mailvar_type_string, 0, 215 N_("number of lines on terminal screen"),
216 set_screen },
217 { { "sendmail", },
218 MAILVAR_TYPEMASK (mailvar_type_string),
146 N_("URL of the mail transport agent") }, 219 N_("URL of the mail transport agent") },
147 /* FIXME: Not yet used. */ 220 /* FIXME: Not yet used. */
148 { { "sendwait", }, mailvar_type_boolean, MAILVAR_HIDDEN, NULL }, 221 { { "sendwait", },
149 { { "sign", }, mailvar_type_string, 0, 222 MAILVAR_TYPEMASK (mailvar_type_boolean) | MAILVAR_HIDDEN, NULL },
223 { { "sign", },
224 MAILVAR_TYPEMASK (mailvar_type_string),
150 N_("signature for use with the ~a command") }, 225 N_("signature for use with the ~a command") },
151 { { "Sign", }, mailvar_type_string, 0, 226 { { "Sign", },
227 MAILVAR_TYPEMASK (mailvar_type_string),
152 N_("signature for use with the ~A command") }, 228 N_("signature for use with the ~A command") },
153 { { "showenvelope", }, mailvar_type_boolean, 0, 229 { { "showenvelope", },
230 MAILVAR_TYPEMASK (mailvar_type_boolean),
154 N_("`print' command includes the SMTP envelope in its output") }, 231 N_("`print' command includes the SMTP envelope in its output") },
155 { { "showto", }, mailvar_type_boolean, 0, 232 { { "showto", },
233 MAILVAR_TYPEMASK (mailvar_type_boolean),
156 N_("if the message was sent by the user, print its recipient address " 234 N_("if the message was sent by the user, print its recipient address "
157 "in the header summary") }, 235 "in the header summary") },
158 { { "toplines", }, mailvar_type_number, 0, 236 { { "toplines", },
237 MAILVAR_TYPEMASK (mailvar_type_number),
159 N_("number of lines to be displayed by `top' or `Top'") }, 238 N_("number of lines to be displayed by `top' or `Top'") },
160 { { "verbose", }, mailvar_type_boolean, 0, 239 { { "variable-pretty-print", },
161 N_("verbosely trace the process of message delivery") }, 240 MAILVAR_TYPEMASK (mailvar_type_boolean),
162 { { "xmailer", }, mailvar_type_boolean, 0,
163 N_("add the `X-Mailer' header to the outgoing messages") },
164
165 { { "variable-pretty-print", }, mailvar_type_boolean, 0,
166 N_("print variables with short descriptions") }, 241 N_("print variables with short descriptions") },
167 { { "varpp", }, mailvar_type_whatever, MAILVAR_ALIAS }, 242 { { "varpp", }, MAILVAR_ALIAS },
168 { { "variable-strict", }, mailvar_type_boolean, 0, 243 { { "variable-strict", },
244 MAILVAR_TYPEMASK (mailvar_type_boolean),
169 N_("perform strict checking when setting options") }, 245 N_("perform strict checking when setting options") },
170 { { "varstrict", }, mailvar_type_whatever, MAILVAR_ALIAS }, 246 { { "varstrict", }, MAILVAR_ALIAS },
247 { { "verbose", },
248 MAILVAR_TYPEMASK (mailvar_type_boolean),
249 N_("verbosely trace the process of message delivery") },
250 { { "xmailer", },
251 MAILVAR_TYPEMASK (mailvar_type_boolean),
252 N_("add the `X-Mailer' header to the outgoing messages") },
171 253
172 /* These will be implemented later */ 254 /* These will be implemented later */
173 { { "debug", }, mailvar_type_whatever, MAILVAR_HIDDEN, NULL }, 255 { { "onehop", }, MAILVAR_HIDDEN, NULL },
174 { { "onehop", }, mailvar_type_whatever, MAILVAR_HIDDEN, NULL },
175 256
176 { { "quiet", }, mailvar_type_boolean, MAILVAR_HIDDEN, 257 { { "quiet", }, MAILVAR_TYPEMASK (mailvar_type_boolean) | MAILVAR_HIDDEN,
177 "suppresses the printing of the version when first invoked" }, 258 "suppresses the printing of the version when first invoked" },
178 259
179 { { NULL }, } 260 { { NULL }, }
...@@ -381,12 +462,12 @@ mailvar_set (const char *variable, void *value, enum mailvar_type type, ...@@ -381,12 +462,12 @@ mailvar_set (const char *variable, void *value, enum mailvar_type type,
381 int flags) 462 int flags)
382 { 463 {
383 struct mailvar_variable *var; 464 struct mailvar_variable *var;
465 const struct mailvar_symbol *sym = find_mailvar_symbol (variable);
466 int unset = flags & MOPTF_UNSET;
384 467
385 if (!(flags & MOPTF_QUIET) 468 if (!(flags & MOPTF_QUIET)
386 && mailvar_get (NULL, "variable-strict", mailvar_type_boolean, 0) == 0) 469 && mailvar_get (NULL, "variable-strict", mailvar_type_boolean, 0) == 0)
387 { 470 {
388 const struct mailvar_symbol *sym = find_mailvar_symbol (variable);
389
390 if (!sym) 471 if (!sym)
391 mu_diag_output (MU_DIAG_WARNING, _("setting unknown variable %s"), 472 mu_diag_output (MU_DIAG_WARNING, _("setting unknown variable %s"),
392 variable); 473 variable);
...@@ -396,64 +477,149 @@ mailvar_set (const char *variable, void *value, enum mailvar_type type, ...@@ -396,64 +477,149 @@ mailvar_set (const char *variable, void *value, enum mailvar_type type,
396 variable); 477 variable);
397 return 1; 478 return 1;
398 } 479 }
480 else if (!(sym->flags & MAILVAR_TYPEMASK (type))
481 && !unset)
482 {
483 mu_error (_("Wrong type for %s"), variable);
484 return 1;
485 }
399 } 486 }
400 487
401 var = mailvar_find_variable (variable, 1); 488 var = mailvar_find_variable (variable, !unset);
402 489
403 if (!var || (var->set && !(flags & MOPTF_OVERWRITE))) 490 if (!var || (var->set && !(flags & MOPTF_OVERWRITE)))
404 return 0; 491 return 0;
405 492
406 mailvar_variable_reset (var); 493 mailvar_variable_reset (var);
407 494 if (!unset)
408 var->type = type;
409 if (value)
410 { 495 {
411 var->set = 1; 496 var->type = type;
412 switch (type) 497 if (value)
413 { 498 {
414 case mailvar_type_number: 499 var->set = 1;
415 var->value.number = *(int*)value; 500 switch (type)
416 break; 501 {
502 case mailvar_type_number:
503 var->value.number = *(int*)value;
504 break;
417 505
418 case mailvar_type_string: 506 case mailvar_type_string:
419 var->value.string = strdup (value); 507 var->value.string = strdup (value);
420 break; 508 break;
421 509
422 case mailvar_type_boolean: 510 case mailvar_type_boolean:
423 var->value.bool = *(int*)value; 511 var->value.bool = *(int*)value;
424 break; 512 break;
425 513
426 default: 514 default:
427 abort(); 515 abort();
516 }
428 } 517 }
429 } 518 }
430 519
431 /* Special handling for some variables */ 520 /* Special handling for some variables */
432 if (strcmp (variable, "replyregex") == 0) 521 if (sym && sym->flags & MAILVAR_TYPEMASK (type) && sym->handler)
433 { 522 sym->handler (var);
434 int rc; 523
435 char *err; 524 return 0;
436 525 }
437 if ((rc = mu_unre_set_regex (value, 0, &err))) 526
527
528 static void
529 set_decode_fallback (struct mailvar_variable *var)
530 {
531 if (mu_set_default_fallback (var->value.string))
532 mu_error (_("Incorrect value for decode-fallback"));
533 }
534
535 static void
536 set_replyregex (struct mailvar_variable *var)
537 {
538 int rc;
539 char *err;
540
541 if ((rc = mu_unre_set_regex (var->value.string, 0, &err)))
542 {
543 if (err)
544 mu_error ("%s: %s", mu_strerror (rc), err);
545 else
546 mu_error ("%s", mu_strerror (rc));
547 }
548 }
549
550 static void
551 set_screen (struct mailvar_variable *var)
552 {
553 page_invalidate (1);
554 }
555
556 static void
557 set_mailbox_debug_level (mu_log_level_t level)
558 {
559 if (mbox)
560 {
561 mu_debug_t mdbg;
562 mu_mailbox_get_debug (mbox, &mdbg);
563 mu_debug_set_level (mdbg, level);
564 }
565 }
566
567 #define DEFAULT_DEBUG_LEVEL \
568 (MU_DEBUG_INHERIT | MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE7))
569
570 static void
571 set_debug (struct mailvar_variable *var)
572 {
573 int rc;
574 int argc;
575 char **argv;
576 int i;
577 mu_debug_t dbg;
578
579 mu_global_debug_clear_level (NULL);
580 set_mailbox_debug_level (0);
581
582 if (var->type == mailvar_type_boolean)
583 {
584 if (var->set)
438 { 585 {
439 fprintf (stderr, "%s", mu_strerror (rc)); 586 /* FIXME: What to set here?
440 if (err) 587 mu_global_debug_set_level ("*", DEFAULT_DEBUG_LEVEL); */
441 { 588 set_mailbox_debug_level (DEFAULT_DEBUG_LEVEL);
442 fprintf (stderr, "%s", err);
443 free (err);
444 }
445 fprintf (stderr, "\n");
446 } 589 }
590 return;
447 } 591 }
448 else if (strcmp (variable, "decode-fallback") == 0) 592
593 mu_diag_get_debug (&dbg);
594
595 rc = mu_argcv_get (var->value.string, ";", NULL, &argc, &argv);
596 if (rc)
449 { 597 {
450 if (mu_set_default_fallback (value)) 598 mu_error (_("Cannot parse string: %s"), mu_strerror (rc));
451 mu_error (_("Incorrect value for decode-fallback")); 599 return;
600 }
601
602 for (i = 0; i < argc; i++)
603 {
604 char *p;
605 mu_log_level_t level = MU_DEBUG_INHERIT;
606 char *object_name = argv[i];
607
608 for (p = object_name; *p && *p != '='; p++)
609 ;
610
611 if (*p == '=')
612 {
613 *p++ = 0;
614 mu_debug_level_from_string (p, &level, dbg);
615 }
616 else
617 level |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT);
618
619 if (strcmp (object_name, "mailbox") == 0)
620 set_mailbox_debug_level (level);
621 mu_global_debug_set_level (object_name, level);
452 } 622 }
453 else if (strcmp (variable, "screen") == 0)
454 page_invalidate (1);
455
456 return 0;
457 } 623 }
458 624
459 625
...@@ -654,6 +820,7 @@ static void ...@@ -654,6 +820,7 @@ static void
654 describe_symbol (FILE *out, int width, const struct mailvar_symbol *sym) 820 describe_symbol (FILE *out, int width, const struct mailvar_symbol *sym)
655 { 821 {
656 int n; 822 int n;
823 int i, t;
657 const struct mailvar_symbol *ali; 824 const struct mailvar_symbol *ali;
658 825
659 n = fprintf (out, "%s", sym->var.name); 826 n = fprintf (out, "%s", sym->var.name);
...@@ -667,7 +834,18 @@ describe_symbol (FILE *out, int width, const struct mailvar_symbol *sym) ...@@ -667,7 +834,18 @@ describe_symbol (FILE *out, int width, const struct mailvar_symbol *sym)
667 } 834 }
668 fputc ('\n', out); 835 fputc ('\n', out);
669 836
670 fprintf (out, _("Type: %s\n"), gettext (typestr[sym->type])); 837 fprintf (out, _("Type: "));
838 for (i = 0, t = 0; i < sizeof (typestr) / sizeof (typestr[0]); i++)
839 if (sym->flags & MAILVAR_TYPEMASK (i))
840 {
841 if (t++)
842 fprintf (out, " %s ", _("or"));
843 fprintf (out, "%s", gettext (typestr[i]));
844 }
845 if (!t)
846 fprintf (out, "%s", gettext (typestr[0]));
847 fputc ('\n', out);
848
671 fprintf (out, "%s", _("Current value: ")); 849 fprintf (out, "%s", _("Current value: "));
672 mailvar_variable_format (out, &sym->var, _("[not set]")); 850 mailvar_variable_format (out, &sym->var, _("[not set]"));
673 851
......
...@@ -48,7 +48,8 @@ mail_set (int argc, char **argv) ...@@ -48,7 +48,8 @@ mail_set (int argc, char **argv)
48 48
49 if (!strncmp ("no", argv[i], 2) && !value) 49 if (!strncmp ("no", argv[i], 2) && !value)
50 { 50 {
51 mailvar_set (&argv[i][2], NULL, mailvar_type_boolean, flags); 51 mailvar_set (&argv[i][2], NULL, mailvar_type_boolean,
52 flags | MOPTF_UNSET);
52 } 53 }
53 else if (value) 54 else if (value)
54 { 55 {
......
...@@ -18,21 +18,25 @@ ...@@ -18,21 +18,25 @@
18 18
19 #include "mail.h" 19 #include "mail.h"
20 20
21
22 static char * 21 static char *
23 source_readline (void *closure, int cont MU_ARG_UNUSED) 22 source_readline (void *closure, int cont MU_ARG_UNUSED)
24 { 23 {
25 FILE *fp = closure; 24 FILE *fp = closure;
26 size_t s = 0; 25 size_t s = 0;
27 char *buf = NULL; 26 char *buf = NULL;
27 mu_debug_t debug;
28 struct mu_debug_locus locus;
28 29
29 if (getline (&buf, &s, fp) >= 0) 30 if (getline (&buf, &s, fp) >= 0)
30 { 31 {
31 int len = strlen (buf); 32 mu_rtrim_class (buf, MU_CTYPE_SPACE);
32 if (buf[len-1] == '\n') 33
33 buf[len-1] = '\0'; 34 mu_diag_get_debug (&debug);
35 mu_debug_get_locus (debug, &locus);
36 mu_debug_set_locus (debug, locus.file, locus.line + 1);
34 return buf; 37 return buf;
35 } 38 }
39
36 return NULL; 40 return NULL;
37 } 41 }
38 42
...@@ -45,11 +49,12 @@ mail_source (int argc, char **argv) ...@@ -45,11 +49,12 @@ mail_source (int argc, char **argv)
45 { 49 {
46 FILE *fp; 50 FILE *fp;
47 int save_term; 51 int save_term;
52 mu_debug_t debug;
48 53
49 if (argc != 2) 54 if (argc != 2)
50 { 55 {
51 /* TRANSLATORS: 'source' is a command name. Do not translate it! */ 56 /* TRANSLATORS: 'source' is a command name. Do not translate it! */
52 util_error (_("source requires an argument")); 57 util_error (_("source requires a single argument"));
53 return 1; 58 return 1;
54 } 59 }
55 60
...@@ -63,8 +68,11 @@ mail_source (int argc, char **argv) ...@@ -63,8 +68,11 @@ mail_source (int argc, char **argv)
63 68
64 save_term = interactive; 69 save_term = interactive;
65 interactive = 0; 70 interactive = 0;
66 mail_mainloop(source_readline, fp, 0); 71 mu_diag_get_debug (&debug);
72 mu_debug_set_locus (debug, argv[1], 0);
73 mail_mainloop (source_readline, fp, 0);
67 interactive = save_term; 74 interactive = save_term;
75 mu_debug_set_locus (debug, NULL, 0);
68 fclose (fp); 76 fclose (fp);
69 return 0; 77 return 0;
70 } 78 }
......