1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: setup.c 918 2008-01-23 19:39:38Z hubert@u.washington.edu $";
3 #endif
4
5 /*
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2021 Eduardo Chappa
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * ========================================================================
17 */
18
19 #include "headers.h"
20 #include "setup.h"
21 #include "keymenu.h"
22 #include "status.h"
23 #include "confscroll.h"
24 #include "colorconf.h"
25 #include "reply.h"
26 #include "radio.h"
27 #include "listsel.h"
28 #include "folder.h"
29 #include "mailcmd.h"
30 #include "../pith/state.h"
31 #include "../pith/conf.h"
32 #include "../pith/util.h"
33 #include "../pith/sort.h"
34 #include "../pith/folder.h"
35 #include "../pith/list.h"
36 #include "../pith/icache.h"
37
38
39 /*
40 * Internal prototypes
41 */
42 int inbox_path_text_tool(struct pine *, int, CONF_S **, unsigned);
43 int incoming_monitoring_list_tool(struct pine *, int, CONF_S **, unsigned);
44 int stayopen_list_tool(struct pine *, int, CONF_S **, unsigned);
45 char **adjust_list_of_monitored_incoming(CONTEXT_S *, EditWhich, int);
46 int to_charsets_text_tool(struct pine *, int, CONF_S **, unsigned);
47
48
49 #define CONFIG_SCREEN_TITLE _("SETUP CONFIGURATION")
50 #define CONFIG_SCREEN_TITLE_EXC _("SETUP CONFIGURATION EXCEPTIONS")
51
52
53
54 /*----------------------------------------------------------------------
55 Present pinerc data for manipulation
56
57 Args: None
58
59 Result: help edit certain pinerc fields.
60 ---*/
61 void
option_screen(struct pine * ps,int edit_exceptions)62 option_screen(struct pine *ps, int edit_exceptions)
63 {
64 char tmp[MAXPATH+1], *pval = NULL, **lval = NULL;
65 int i, j, ln = 0, readonly_warning = 0, pos;
66 struct variable *vtmp;
67 CONF_S *ctmpa = NULL, *ctmpb = NULL, *first_line = NULL;
68 FEATURE_S *feature;
69 PINERC_S *prc = NULL;
70 SAVED_CONFIG_S *vsave;
71 OPT_SCREEN_S screen;
72 int expose_hidden_config, add_hidden_vars_title = 0;
73
74 dprint((3, "-- option_screen --\n"));
75
76 expose_hidden_config = F_ON(F_EXPOSE_HIDDEN_CONFIG, ps_global);
77 treat_color_vars_as_text = expose_hidden_config;
78
79 ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
80
81 if(ps->restricted)
82 readonly_warning = 1;
83 else{
84 switch(ew){
85 case Main:
86 prc = ps->prc;
87 break;
88 case Post:
89 prc = ps->post_prc;
90 break;
91 default:
92 break;
93 }
94
95 readonly_warning = prc ? prc->readonly : 1;
96 if(prc && prc->quit_to_edit){
97 quit_to_edit_msg(prc);
98 treat_color_vars_as_text = 0;
99 return;
100 }
101 }
102
103 ps->next_screen = SCREEN_FUN_NULL;
104
105 mailcap_free(); /* free resources we won't be using for a while */
106
107 if(ps->fix_fixed_warning)
108 offer_to_fix_pinerc(ps);
109
110 pos = -1;
111 do { /* Beginning of BIG LOOP */
112 ctmpa = first_line = NULL;
113
114 /*
115 * First, find longest variable name
116 */
117 for(vtmp = ps->vars; vtmp->name; vtmp++){
118 if(exclude_config_var(ps, vtmp, expose_hidden_config))
119 continue;
120
121 if((i = utf8_width(pretty_var_name(vtmp->name))) > ln)
122 ln = i;
123 }
124
125 dprint((9, "initialize config list\n"));
126
127 /*
128 * Next, allocate and initialize config line list...
129 */
130 for(vtmp = ps->vars; vtmp->name; vtmp++){
131 /*
132 * INCOMING_FOLDERS is currently the first of the normally
133 * hidden variables. Should probably invent a more robust way
134 * to keep this up to date.
135 */
136 if(expose_hidden_config && vtmp == &ps->vars[V_INCOMING_FOLDERS])
137 add_hidden_vars_title = 1;
138
139 if(exclude_config_var(ps, vtmp, expose_hidden_config))
140 continue;
141
142 if(add_hidden_vars_title){
143
144 add_hidden_vars_title = 0;
145
146 new_confline(&ctmpa); /* Blank line */
147 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
148
149 new_confline(&ctmpa)->var = NULL;
150 ctmpa->help = NO_HELP;
151 ctmpa->valoffset = 2;
152 ctmpa->flags |= CF_NOSELECT;
153 ctmpa->value = cpystr("--- [ Normally hidden configuration options ] ---");
154
155 new_confline(&ctmpa); /* Blank line */
156 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
157 }
158
159 if(vtmp->is_list)
160 lval = LVAL(vtmp, ew);
161 else
162 pval = PVAL(vtmp, ew);
163
164 new_confline(&ctmpa)->var = vtmp;
165 if(!first_line)
166 first_line = ctmpa;
167
168 ctmpa->valoffset = ln + 3;
169 if(vtmp->is_list)
170 ctmpa->keymenu = &config_text_wshuf_keymenu;
171 else
172 ctmpa->keymenu = &config_text_keymenu;
173
174 ctmpa->help = config_help(vtmp - ps->vars, 0);
175 ctmpa->tool = text_tool;
176
177 utf8_snprintf(tmp, sizeof(tmp), "%-*.100w =", ln, pretty_var_name(vtmp->name));
178 tmp[sizeof(tmp)-1] = '\0';
179 ctmpa->varname = cpystr(tmp);
180 ctmpa->varnamep = ctmpb = ctmpa;
181 ctmpa->flags |= CF_STARTITEM;
182 if(vtmp == &ps->vars[V_FEATURE_LIST]){ /* special checkbox case */
183 char *this_sect, *new_sect;
184
185 ctmpa->flags |= CF_NOSELECT;
186 ctmpa->keymenu = &config_checkbox_keymenu;
187 ctmpa->tool = NULL;
188
189 /* put a nice delimiter before list */
190 new_confline(&ctmpa)->var = NULL;
191 ctmpa->varnamep = ctmpb;
192 ctmpa->keymenu = &config_checkbox_keymenu;
193 ctmpa->help = NO_HELP;
194 ctmpa->tool = checkbox_tool;
195 ctmpa->valoffset = feature_indent();
196 ctmpa->flags |= CF_NOSELECT;
197 ctmpa->value = cpystr("Set Feature Name");
198
199 new_confline(&ctmpa)->var = NULL;
200 ctmpa->varnamep = ctmpb;
201 ctmpa->keymenu = &config_checkbox_keymenu;
202 ctmpa->help = NO_HELP;
203 ctmpa->tool = checkbox_tool;
204 ctmpa->valoffset = feature_indent();
205 ctmpa->flags |= CF_NOSELECT;
206 ctmpa->value = cpystr("--- ----------------------");
207
208 for(i = 0, this_sect = NULL; (feature = feature_list(i)); i++)
209 if((new_sect = feature_list_section(feature)) &&
210 (strcmp(new_sect, HIDDEN_PREF) != 0)){
211 if(this_sect != new_sect){
212 new_confline(&ctmpa)->var = NULL;
213 ctmpa->varnamep = ctmpb;
214 ctmpa->keymenu = &config_checkbox_keymenu;
215 ctmpa->help = NO_HELP;
216 ctmpa->tool = checkbox_tool;
217 ctmpa->valoffset = 2;
218 ctmpa->flags |= (CF_NOSELECT | CF_STARTITEM);
219 snprintf(tmp, sizeof(tmp), "[ %s ]", this_sect = new_sect);
220 tmp[sizeof(tmp)-1] = '\0';
221 ctmpa->value = cpystr(tmp);
222 }
223
224 new_confline(&ctmpa)->var = vtmp;
225 ctmpa->varnamep = ctmpb;
226 ctmpa->keymenu = &config_checkbox_keymenu;
227 ctmpa->help = config_help(vtmp-ps->vars,
228 feature->id);
229 ctmpa->tool = checkbox_tool;
230 ctmpa->valoffset = feature_indent();
231 ctmpa->varmem = i;
232 ctmpa->value = pretty_value(ps, ctmpa);
233 }
234 }
235 else if(standard_radio_var(ps, vtmp)){
236 standard_radio_setup(ps, &ctmpa, vtmp, NULL);
237 }
238 else if(vtmp == &ps->vars[V_SORT_KEY]){ /* radio case */
239 SortOrder def_sort;
240 int def_sort_rev;
241
242 ctmpa->flags |= CF_NOSELECT;
243 ctmpa->keymenu = &config_radiobutton_keymenu;
244 ctmpa->tool = NULL;
245
246 /* put a nice delimiter before list */
247 new_confline(&ctmpa)->var = NULL;
248 ctmpa->varnamep = ctmpb;
249 ctmpa->keymenu = &config_radiobutton_keymenu;
250 ctmpa->help = NO_HELP;
251 ctmpa->tool = radiobutton_tool;
252 ctmpa->valoffset = 12;
253 ctmpa->flags |= CF_NOSELECT;
254 ctmpa->value = cpystr("Set Sort Options");
255
256 new_confline(&ctmpa)->var = NULL;
257 ctmpa->varnamep = ctmpb;
258 ctmpa->keymenu = &config_radiobutton_keymenu;
259 ctmpa->help = NO_HELP;
260 ctmpa->tool = radiobutton_tool;
261 ctmpa->valoffset = 12;
262 ctmpa->flags |= CF_NOSELECT;
263 ctmpa->value = cpystr("--- ----------------------");
264
265 decode_sort(pval, &def_sort, &def_sort_rev);
266
267 for(j = 0; j < 2; j++){
268 for(i = 0; ps->sort_types[i] != EndofList; i++){
269 new_confline(&ctmpa)->var = vtmp;
270 ctmpa->varnamep = ctmpb;
271 ctmpa->keymenu = &config_radiobutton_keymenu;
272 ctmpa->help = config_help(vtmp - ps->vars, 0);
273 ctmpa->tool = radiobutton_tool;
274 ctmpa->valoffset = 12;
275 ctmpa->varmem = i + (j * EndofList);
276 ctmpa->value = pretty_value(ps, ctmpa);
277 }
278 }
279 }
280 else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */
281 ctmpa->keymenu = &config_yesno_keymenu;
282 ctmpa->tool = yesno_tool;
283 ctmpa->value = pretty_value(ps, ctmpa);
284 }
285 else if(vtmp == &ps->vars[V_LITERAL_SIG]){
286 ctmpa->tool = litsig_text_tool;
287 ctmpa->value = pretty_value(ps, ctmpa);
288 }
289 else if(vtmp == &ps->vars[V_INBOX_PATH]){
290 ctmpa->tool = inbox_path_text_tool;
291 ctmpa->value = pretty_value(ps, ctmpa);
292 }
293 else if(vtmp == &ps->vars[V_POST_CHAR_SET]
294 #ifndef _WINDOWS
295 || vtmp == &ps->vars[V_CHAR_SET]
296 || vtmp == &ps->vars[V_KEY_CHAR_SET]
297 #endif /* !_WINDOWS */
298 || vtmp == &ps->vars[V_UNK_CHAR_SET]){
299 ctmpa->keymenu = &config_text_to_charsets_keymenu;
300 ctmpa->tool = to_charsets_text_tool;
301 ctmpa->value = pretty_value(ps, ctmpa);
302 }
303 else if(vtmp->is_list){
304 int (*t_tool)(struct pine *, int, CONF_S **, unsigned);
305 struct key_menu *km;
306
307 t_tool = NULL;
308 km = NULL;
309 if(vtmp == &ps->vars[V_INCCHECKLIST]){
310 t_tool = incoming_monitoring_list_tool;
311 km = &config_text_keymenu;
312 }
313 else if(vtmp == &ps->vars[V_PERMLOCKED]){
314 t_tool = stayopen_list_tool;
315 km = &config_text_wshufandfldr_keymenu;
316 }
317
318 if(lval){
319 for(i = 0; lval[i]; i++){
320 if(i)
321 (void)new_confline(&ctmpa);
322
323 ctmpa->var = vtmp;
324 ctmpa->varmem = i;
325 ctmpa->valoffset = ln + 3;
326 ctmpa->value = pretty_value(ps, ctmpa);
327 ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu;
328 ctmpa->help = config_help(vtmp - ps->vars, 0);
329 ctmpa->tool = t_tool ? t_tool : text_tool;
330 ctmpa->varnamep = ctmpb;
331 }
332 }
333 else{
334 ctmpa->varmem = 0;
335 ctmpa->value = pretty_value(ps, ctmpa);
336 ctmpa->tool = t_tool ? t_tool : text_tool;
337 ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu;
338 }
339 }
340 else{
341 if(vtmp == &ps->vars[V_FILLCOL]
342 || vtmp == &ps->vars[V_QUOTE_SUPPRESSION]
343 || vtmp == &ps->vars[V_OVERLAP]
344 || vtmp == &ps->vars[V_MAXREMSTREAM]
345 || vtmp == &ps->vars[V_MARGIN]
346 || vtmp == &ps->vars[V_DEADLETS]
347 || vtmp == &ps->vars[V_NMW_WIDTH]
348 || vtmp == &ps->vars[V_STATUS_MSG_DELAY]
349 || vtmp == &ps->vars[V_ACTIVE_MSG_INTERVAL]
350 || vtmp == &ps->vars[V_MAILCHECK]
351 || vtmp == &ps->vars[V_MAILCHECKNONCURR]
352 || vtmp == &ps->vars[V_MAILDROPCHECK]
353 || vtmp == &ps->vars[V_NNTPRANGE]
354 || vtmp == &ps->vars[V_TCPOPENTIMEO]
355 || vtmp == &ps->vars[V_TCPREADWARNTIMEO]
356 || vtmp == &ps->vars[V_TCPWRITEWARNTIMEO]
357 || vtmp == &ps->vars[V_TCPQUERYTIMEO]
358 || vtmp == &ps->vars[V_RSHOPENTIMEO]
359 || vtmp == &ps->vars[V_SSHOPENTIMEO]
360 || vtmp == &ps->vars[V_INCCHECKTIMEO]
361 || vtmp == &ps->vars[V_INCCHECKINTERVAL]
362 || vtmp == &ps->vars[V_INC2NDCHECKINTERVAL]
363 || vtmp == &ps->vars[V_USERINPUTTIMEO]
364 || vtmp == &ps->vars[V_REMOTE_ABOOK_VALIDITY]
365 || vtmp == &ps->vars[V_REMOTE_ABOOK_HISTORY])
366 ctmpa->flags |= CF_NUMBER;
367
368 ctmpa->value = pretty_value(ps, ctmpa);
369 }
370 }
371
372 dprint((9, "add hidden features\n"));
373
374 /* add the hidden features */
375 if(expose_hidden_config){
376 char *new_sect;
377
378 new_confline(&ctmpa); /* Blank line */
379 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
380
381 new_confline(&ctmpa)->var = NULL;
382 ctmpa->help = NO_HELP;
383 ctmpa->valoffset = 2;
384 ctmpa->flags |= CF_NOSELECT;
385 ctmpa->value = cpystr("--- [ Normally hidden configuration features ] ---");
386
387 new_confline(&ctmpa); /* Blank line */
388 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
389
390 vtmp = &ps->vars[V_FEATURE_LIST];
391
392 ctmpa->flags |= CF_NOSELECT;
393 ctmpa->keymenu = &config_checkbox_keymenu;
394 ctmpa->tool = NULL;
395
396 /* put a nice delimiter before list */
397 new_confline(&ctmpa)->var = NULL;
398 ctmpa->varnamep = ctmpb;
399 ctmpa->keymenu = &config_checkbox_keymenu;
400 ctmpa->help = NO_HELP;
401 ctmpa->tool = checkbox_tool;
402 ctmpa->valoffset = feature_indent();
403 ctmpa->flags |= CF_NOSELECT;
404 ctmpa->value = cpystr("Set Feature Name");
405
406 new_confline(&ctmpa)->var = NULL;
407 ctmpa->varnamep = ctmpb;
408 ctmpa->keymenu = &config_checkbox_keymenu;
409 ctmpa->help = NO_HELP;
410 ctmpa->tool = checkbox_tool;
411 ctmpa->valoffset = feature_indent();
412 ctmpa->flags |= CF_NOSELECT;
413 ctmpa->value = cpystr("--- ----------------------");
414
415 for(i = 0; (feature = feature_list(i)); i++)
416 if((new_sect = feature_list_section(feature)) &&
417 (strcmp(new_sect, HIDDEN_PREF) == 0)){
418
419 new_confline(&ctmpa)->var = vtmp;
420 ctmpa->varnamep = ctmpb;
421 ctmpa->keymenu = &config_checkbox_keymenu;
422 ctmpa->help = config_help(vtmp-ps->vars,
423 feature->id);
424 ctmpa->tool = checkbox_tool;
425 ctmpa->valoffset = feature_indent();
426 ctmpa->varmem = i;
427 ctmpa->value = pretty_value(ps, ctmpa);
428 }
429 }
430
431 vsave = save_config_vars(ps, expose_hidden_config);
432 first_line = pos < 0 ? first_sel_confline(first_line) : set_confline_number(first_line, pos);
433 pos = -1;
434 memset(&screen, 0, sizeof(screen));
435 screen.ro_warning = readonly_warning;
436 /* TRANSLATORS: Print something1 using something2.
437 "configuration" is something1 */
438 switch(conf_scroll_screen(ps, &screen, first_line,
439 edit_exceptions ? CONFIG_SCREEN_TITLE_EXC
440 : CONFIG_SCREEN_TITLE,
441 _("configuration"), 0, &pos)){
442 case 0:
443 break;
444
445 case 1:
446 write_pinerc(ps, ew, WRP_NONE);
447 break;
448
449 case 10:
450 revert_to_saved_config(ps, vsave, expose_hidden_config);
451 if(prc)
452 prc->outstanding_pinerc_changes = 0;
453
454 break;
455
456 default:
457 q_status_message(SM_ORDER,7,10,
458 "conf_scroll_screen bad ret, not supposed to happen");
459 break;
460 }
461 } while (pos >= 0);
462
463 pval = PVAL(&ps->vars[V_SORT_KEY], ew);
464 if(vsave[V_SORT_KEY].saved_user_val.p && pval
465 && strcmp(vsave[V_SORT_KEY].saved_user_val.p, pval)){
466 if(!mn_get_mansort(ps_global->msgmap)){
467 clear_index_cache(ps_global->mail_stream, 0);
468 reset_sort_order(SRT_VRB);
469 }
470 }
471
472 treat_color_vars_as_text = 0;
473 free_saved_config(ps, &vsave, expose_hidden_config);
474 #ifdef _WINDOWS
475 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
476 #endif
477 }
478
479
480 int
litsig_text_tool(struct pine * ps,int cmd,CONF_S ** cl,unsigned int flags)481 litsig_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
482 {
483 char **apval;
484 int rv = 0;
485
486 if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL))
487 return(rv);
488
489 apval = APVAL((*cl)->var, ew);
490
491 switch(cmd){
492 case MC_ADD:
493 case MC_EDIT :
494 if(apval){
495 char *input = NULL, *result = NULL, *err = NULL, *cstring_version;
496 char *olddefval = NULL, *start_with;
497 size_t len;
498
499 if(!*apval && (*cl)->var->current_val.p &&
500 (*cl)->var->current_val.p[0]){
501 if(!strncmp((*cl)->var->current_val.p,
502 DSTRING,
503 (len=strlen(DSTRING)))){
504 /* strip DSTRING and trailing paren */
505 olddefval = (char *)fs_get(strlen((*cl)->var->current_val.p)+1);
506 strncpy(olddefval, (*cl)->var->current_val.p+len,
507 strlen((*cl)->var->current_val.p)-len-1);
508 olddefval[strlen((*cl)->var->current_val.p)-len-1] = '\0';
509 start_with = olddefval;
510 }
511 else{
512 olddefval = cpystr((*cl)->var->current_val.p);
513 start_with = olddefval;
514 }
515 }
516 else
517 start_with = (*apval) ? *apval : "";
518
519 input = (char *)fs_get((strlen(start_with)+1) * sizeof(char));
520 input[0] = '\0';
521 cstring_to_string(start_with, input);
522 err = signature_edit_lit(input, &result,
523 ((*cl)->var == role_comment_ptr)
524 ? "COMMENT EDITOR"
525 : "SIGNATURE EDITOR",
526 ((*cl)->var == role_comment_ptr)
527 ? h_composer_commentedit
528 : h_composer_sigedit);
529
530 if(!err){
531 if(olddefval && !strcmp(input, result) &&
532 want_to(_("Leave unset and use default "), 'y',
533 'y', NO_HELP, WT_FLUSH_IN) == 'y'){
534 rv = 0;
535 }
536 else{
537 cstring_version = string_to_cstring(result);
538
539 if(apval && *apval)
540 fs_give((void **)apval);
541
542 if(apval){
543 *apval = cstring_version;
544 cstring_version = NULL;
545 }
546
547 if(cstring_version)
548 fs_give((void **)&cstring_version);
549
550 rv = 1;
551 }
552 }
553 else
554 rv = 0;
555
556 if(err){
557 q_status_message1(SM_ORDER, 3, 5, "%s", err);
558 fs_give((void **)&err);
559 }
560
561 if(result)
562 fs_give((void **)&result);
563 if(olddefval)
564 fs_give((void **)&olddefval);
565 if(input)
566 fs_give((void **)&input);
567 }
568
569 ps->mangled_screen = 1;
570 break;
571
572 default:
573 rv = text_tool(ps, cmd, cl, flags);
574 break;
575 }
576
577 /*
578 * At this point, if changes occurred, var->user_val.X is set.
579 * So, fix the current_val, and handle special cases...
580 *
581 * NOTE: we don't worry about the "fixed variable" case here, because
582 * editing such vars should have been prevented above...
583 */
584 if(rv == 1){
585 /*
586 * Now go and set the current_val based on user_val changes
587 * above. Turn off command line settings...
588 */
589 set_current_val((*cl)->var, TRUE, FALSE);
590
591 if((*cl)->value)
592 fs_give((void **)&(*cl)->value);
593
594 (*cl)->value = pretty_value(ps, *cl);
595
596 exception_override_warning((*cl)->var);
597
598 /*
599 * The value of literal sig can affect whether signature file is
600 * used or not. So it affects what we display for sig file variable.
601 */
602 if((*cl)->next && (*cl)->next->var == &ps->vars[V_SIGNATURE_FILE]){
603 if((*cl)->next->value)
604 fs_give((void **)&(*cl)->next->value);
605
606 (*cl)->next->value = pretty_value(ps, (*cl)->next);
607 }
608 }
609
610 return(rv);
611 }
612
613
614 int
inbox_path_text_tool(struct pine * ps,int cmd,CONF_S ** cl,unsigned int flags)615 inbox_path_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
616 {
617 char **apval;
618 int rv = 0;
619 char new_inbox_path[2*MAXFOLDER+1];
620 char *def = NULL;
621 CONTEXT_S *cntxt;
622
623 if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL))
624 return(rv);
625
626 apval = APVAL((*cl)->var, ew);
627
628 switch(cmd){
629 case MC_ADD:
630 case MC_EDIT:
631 cntxt = ps->context_list;
632 if(cmd == MC_EDIT && (*cl)->var){
633 if(ew == Post && (*cl)->var->post_user_val.p)
634 def = (*cl)->var->post_user_val.p;
635 else if(ew == Main && (*cl)->var->main_user_val.p)
636 def = (*cl)->var->main_user_val.p;
637 else if((*cl)->var->current_val.p)
638 def = (*cl)->var->current_val.p;
639 }
640
641 rv = add_new_folder(cntxt, ew, V_INBOX_PATH, new_inbox_path,
642 sizeof(new_inbox_path), NULL, def);
643 rv = rv ? 1 : 0;
644
645 ps->mangled_screen = 1;
646 break;
647
648 default:
649 rv = text_tool(ps, cmd, cl, flags);
650 break;
651 }
652
653 /*
654 * This is just like the end of text_tool.
655 */
656 if(rv == 1){
657 /*
658 * Now go and set the current_val based on user_val changes
659 * above. Turn off command line settings...
660 */
661 set_current_val((*cl)->var, TRUE, FALSE);
662 fix_side_effects(ps, (*cl)->var, 0);
663
664 if((*cl)->value)
665 fs_give((void **) &(*cl)->value);
666
667 (*cl)->value = pretty_value(ps, *cl);
668
669 exception_override_warning((*cl)->var);
670 }
671
672 return(rv);
673 }
674
675
676 int
incoming_monitoring_list_tool(struct pine * ps,int cmd,CONF_S ** cl,unsigned int flags)677 incoming_monitoring_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
678 {
679 int rv = 0;
680 CONTEXT_S *cntxt;
681 char **the_list;
682 CONF_S *ctmp;
683 char ***alval;
684 OPT_SCREEN_S *saved_screen;
685
686 if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL))
687 return(rv);
688
689 switch(cmd){
690 case MC_ADD:
691 case MC_EDIT:
692 cntxt = ps->context_list;
693 if(!(cntxt && cntxt->use & CNTXT_INCMNG)){
694 q_status_message1(SM_ORDER, 3, 3, _("Turn on incoming folders with Config feature \"%s\""), pretty_feature_name(feature_list_name(F_ENABLE_INCOMING), -1));
695 return(rv);
696 }
697
698 saved_screen = opt_screen;
699
700 the_list = adjust_list_of_monitored_incoming(cntxt, ew, V_INCCHECKLIST);
701
702 /* adjust top if it might be necessary */
703 for(ctmp = (*cl)->varnamep;
704 ctmp && ctmp->varnamep == (*cl)->varnamep;
705 ctmp = next_confline(ctmp))
706 if(ctmp == opt_screen->top_line)
707 opt_screen->top_line = (*cl)->varnamep;
708
709 if(the_list){
710 alval = ALVAL((*cl)->var, ew);
711 free_list_array(alval);
712 if(!*the_list){
713 q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders"));
714 if(alval){
715 /*
716 * Remove config lines except for first one.
717 */
718 *cl = (*cl)->varnamep;
719 while((*cl)->next && (*cl)->next->varnamep == (*cl)->varnamep)
720 snip_confline(&(*cl)->next);
721 }
722 }
723 else
724 config_add_list(ps, cl, the_list, NULL, 0);
725
726 /* only have to free the top-level pointer */
727 fs_give((void **) &the_list);
728 rv = 1;
729 }
730 else{
731 if(LVAL((*cl)->var, ew))
732 q_status_message(SM_ORDER, 0, 3, _("List is unchanged"));
733 else
734 q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders"));
735 }
736
737 opt_screen = saved_screen;
738 ps->mangled_screen = 1;
739 break;
740
741 default:
742 rv = text_tool(ps, cmd, cl, flags);
743 /* if we deleted last one, reverts to default */
744 if(cmd == MC_DELETE && rv == 1 && (*cl)->varmem == 0
745 && (!(*cl)->next || (*cl)->next->varnamep != (*cl)))
746 q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders"));
747
748 break;
749 }
750
751 /*
752 * This is just like the end of text_tool.
753 */
754 if(rv == 1){
755 /*
756 * Now go and set the current_val based on user_val changes
757 * above. Turn off command line settings...
758 */
759 set_current_val((*cl)->var, TRUE, FALSE);
760 fix_side_effects(ps, (*cl)->var, 0);
761
762 if((*cl)->value)
763 fs_give((void **) &(*cl)->value);
764
765 (*cl)->value = pretty_value(ps, *cl);
766
767 exception_override_warning((*cl)->var);
768 }
769
770 return(rv);
771 }
772
773
774 char **
adjust_list_of_monitored_incoming(CONTEXT_S * cntxt,EditWhich which,int varnum)775 adjust_list_of_monitored_incoming(CONTEXT_S *cntxt, EditWhich which, int varnum)
776 {
777 LIST_SEL_S *listhead, *p, *ls;
778 int i, cnt, ftotal;
779 long width;
780 FOLDER_S *f;
781 char **the_list = NULL, buf[1000];
782
783 if(!(cntxt && cntxt->use & CNTXT_INCMNG))
784 return(the_list);
785
786 p = listhead = NULL;
787
788 /* this width is determined by select_from_list_screen() */
789 width = ps_global->ttyo->screen_cols - 4;
790
791 /*
792 * Put together a list of folders to select from.
793 * We could choose to use the list associated with
794 * the config we're editing, and that may be correct.
795 * However, we think most users will expect the list
796 * to be the list that is in use. In any case, these
797 * are almost always the same.
798 */
799
800 ftotal = folder_total(FOLDERS(cntxt));
801
802 for(i = 0; i < ftotal; i++){
803
804 f = folder_entry(i, FOLDERS(cntxt));
805
806 ls = (LIST_SEL_S *) fs_get(sizeof(*ls));
807 memset(ls, 0, sizeof(*ls));
808
809 if(f && f->nickname){
810 ls->item = cpystr(f->nickname);
811 snprintf(buf, sizeof(buf), "%s (%s)", f->nickname, f->name ? f->name : "?");
812 ls->display_item = cpystr(buf);
813 }
814 else
815 ls->item = cpystr((f && f->name) ? f->name : "?");
816
817 if(f && f->last_unseen_update != LUU_NEVERCHK)
818 ls->selected = 1;
819
820 if(p){
821 p->next = ls;
822 p = p->next;
823 }
824 else{
825 /* add a heading */
826 listhead = (LIST_SEL_S *) fs_get(sizeof(*ls));
827 memset(listhead, 0, sizeof(*listhead));
828 listhead->flags = SFL_NOSELECT;
829 listhead->display_item = cpystr(_("Incoming folders to be monitored"));
830 listhead->next = (LIST_SEL_S *) fs_get(sizeof(*ls));
831 memset(listhead->next, 0, sizeof(*listhead));
832 listhead->next->flags = SFL_NOSELECT;
833 listhead->next->display_item = cpystr(repeat_char(width, '-'));
834
835 listhead->next->next = ls;
836 p = ls;
837 }
838 }
839
840 if(!listhead){
841 q_status_message1(SM_ORDER, 3, 3, _("Turn on incoming folders with Config feature \"%s\""), pretty_feature_name(feature_list_name(F_ENABLE_INCOMING), -1));
842 return(the_list);
843 }
844
845 if(!select_from_list_screen(listhead,
846 SFL_ALLOW_LISTMODE|SFL_STARTIN_LISTMODE|SFL_ONLY_LISTMODE|SFL_CTRLC,
847 _("SELECT FOLDERS TO MONITOR"), _("folders"),
848 h_select_incoming_to_monitor,
849 _("HELP FOR SELECTING FOLDERS"), NULL)){
850
851 for(cnt = 0, p = listhead; p; p = p->next)
852 if(p->selected)
853 cnt++;
854
855 if(cnt >= 0 && cnt <= ftotal){
856 the_list = (char **) fs_get((cnt+1) * sizeof(*the_list));
857 memset(the_list, 0, (cnt+1) * sizeof(*the_list));
858 for(i = 0, p = listhead; p; p = p->next)
859 if(p->selected)
860 the_list[i++] = cpystr(p->item ? p->item : "");
861 }
862 }
863
864 free_list_sel(&listhead);
865
866 return(the_list);
867 }
868
869
870 int
stayopen_list_tool(struct pine * ps,int cmd,CONF_S ** cl,unsigned int flags)871 stayopen_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
872 {
873 int rv = 0;
874 char **newval = NULL;
875 char **ltmp = NULL;
876 char *folder = NULL;
877 void (*prev_screen)(struct pine *) = ps->prev_screen,
878 (*redraw)(void) = ps->redrawer;
879 OPT_SCREEN_S *saved_screen = NULL;
880
881 switch(cmd){
882 case MC_CHOICE:
883 if(fixed_var((*cl)->var, NULL, NULL))
884 break;
885
886 ps->redrawer = NULL;
887 ps->next_screen = SCREEN_FUN_NULL;
888 saved_screen = opt_screen;
889 folder = folder_for_config(FOR_OPTIONSCREEN);
890 removing_leading_and_trailing_white_space(folder);
891 if(folder && *folder){
892 ltmp = (char **) fs_get(2 * sizeof(char *));
893 ltmp[0] = cpystr(folder);
894 ltmp[1] = NULL;
895
896 config_add_list(ps, cl, ltmp, &newval, 0);
897
898 if(ltmp)
899 fs_give((void **) <mp);
900
901 rv = 1;
902
903 /* this stuff is from bottom of text_toolit() */
904
905 /*
906 * At this point, if changes occurred, var->user_val.X is set.
907 * So, fix the current_val, and handle special cases...
908 *
909 * NOTE: we don't worry about the "fixed variable" case here, because
910 * editing such vars should have been prevented above...
911 */
912
913 /*
914 * Now go and set the current_val based on user_val changes
915 * above. Turn off command line settings...
916 */
917 set_current_val((*cl)->var, TRUE, FALSE);
918 fix_side_effects(ps, (*cl)->var, 0);
919
920 /*
921 * Delay setting the displayed value until "var.current_val" is set
922 * in case current val gets changed due to a special case above.
923 */
924 if(newval){
925 if(*newval)
926 fs_give((void **) newval);
927
928 *newval = pretty_value(ps, *cl);
929 }
930
931 exception_override_warning((*cl)->var);
932
933 if(folder)
934 fs_give((void **) &folder);
935 }
936 else{
937 ps->next_screen = prev_screen;
938 ps->redrawer = redraw;
939 rv = 0;
940 }
941
942 opt_screen = saved_screen;
943 ps->mangled_screen = 1;
944 break;
945
946 default:
947 rv = text_tool(ps, cmd, cl, flags);
948 break;
949 }
950
951 return(rv);
952 }
953
954
955 int
to_charsets_text_tool(struct pine * ps,int cmd,CONF_S ** cl,unsigned int flags)956 to_charsets_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
957 {
958 int rv = 0;
959 char **newval = NULL;
960 void (*prev_screen)(struct pine *) = ps->prev_screen,
961 (*redraw)(void) = ps->redrawer;
962 OPT_SCREEN_S *saved_screen = NULL;
963 char **apval;
964 char *charset = NULL;
965
966 switch(cmd){
967 case MC_CHOICE:
968 if(fixed_var((*cl)->var, NULL, NULL))
969 break;
970
971 apval = APVAL((*cl)->var, ew);
972
973 if(apval){
974 int cac_flags = CAC_ALL;
975
976 ps->redrawer = NULL;
977 ps->next_screen = SCREEN_FUN_NULL;
978 saved_screen = opt_screen;
979
980 if((*cl)->var == &ps->vars[V_POST_CHAR_SET])
981 cac_flags = CAC_POSTING;
982 #ifndef _WINDOWS
983 else if((*cl)->var == &ps->vars[V_CHAR_SET]
984 || (*cl)->var == &ps->vars[V_KEY_CHAR_SET])
985 cac_flags = CAC_DISPLAY;
986 #endif /* !_WINDOWS */
987
988 charset = choose_a_charset(cac_flags);
989
990 removing_leading_and_trailing_white_space(charset);
991 if(charset && *charset){
992 rv = 1;
993 if(apval && *apval)
994 fs_give((void **) apval);
995
996 *apval = charset;
997 charset = NULL;
998 newval = &(*cl)->value;
999
1000 /* this stuff is from bottom of text_toolit() */
1001
1002 /*
1003 * At this point, if changes occurred, var->user_val.X is set.
1004 * So, fix the current_val, and handle special cases...
1005 *
1006 * NOTE: we don't worry about the "fixed variable" case here, because
1007 * editing such vars should have been prevented above...
1008 */
1009
1010 /*
1011 * Now go and set the current_val based on user_val changes
1012 * above. Turn off command line settings...
1013 */
1014 set_current_val((*cl)->var, TRUE, FALSE);
1015 fix_side_effects(ps, (*cl)->var, 0);
1016 if(newval){
1017 if(*newval)
1018 fs_give((void **) newval);
1019
1020 *newval = pretty_value(ps, *cl);
1021 }
1022
1023 exception_override_warning((*cl)->var);
1024 }
1025 else{
1026 ps->next_screen = prev_screen;
1027 ps->redrawer = redraw;
1028 rv = 0;
1029 }
1030
1031 if(charset)
1032 fs_give((void **) &charset);
1033
1034 opt_screen = saved_screen;
1035 ps->mangled_screen = 1;
1036 }
1037 break;
1038
1039 default:
1040 rv = text_tool(ps, cmd, cl, flags);
1041 break;
1042 }
1043
1044 return(rv);
1045 }
1046
1047
1048 /*
1049 * pretty_var_name - return a pleasantly displayable form
1050 * of variable name variable
1051 */
1052 char *
pretty_var_name(char * varname)1053 pretty_var_name(char *varname)
1054 {
1055 struct variable *v;
1056 int i, upper = 1;
1057 static char vbuf[100];
1058
1059 vbuf[0] = '\0';
1060 v = var_from_name(varname);
1061
1062 if(!v)
1063 return(vbuf);
1064
1065 if(v->dname && v->dname[0])
1066 return(v->dname);
1067
1068 if(!(v->name && v->name[0]))
1069 return(vbuf);
1070
1071 /* default: uppercase first letters, dashes to spaces */
1072 for(i = 0; i < sizeof(vbuf)-1 && v->name[i]; i++)
1073 if(upper){
1074 vbuf[i] = (islower((unsigned char) v->name[i]))
1075 ? toupper((unsigned char) v->name[i])
1076 : v->name[i];
1077 upper = 0;
1078 }
1079 else if(v->name[i] == '-'){
1080 vbuf[i] = SPACE;
1081 upper++;
1082 }
1083 else
1084 vbuf[i] = v->name[i];
1085
1086 vbuf[i] = '\0';
1087 return(vbuf);
1088 }
1089
1090
1091 /*
1092 * pretty_feature_name - return a pleasantly displayable form
1093 * of feature name variable
1094 */
1095 char *
pretty_feature_name(char * feat,int width)1096 pretty_feature_name(char *feat, int width)
1097 {
1098 FEATURE_S *f;
1099 int i, upper = 1;
1100 static char fbuf[100];
1101
1102 f = feature_list(feature_list_index(feature_list_id(feat)));
1103 if(f && f->dname && f->dname[0])
1104 return(f->dname);
1105
1106 /* default: uppercase first letters, dashes become spaces */
1107 for(i = 0; i < sizeof(fbuf)-1 && feat[i]; i++)
1108 if(upper){
1109 fbuf[i] = (islower((unsigned char) feat[i]))
1110 ? toupper((unsigned char) feat[i])
1111 : feat[i];
1112 upper = 0;
1113 }
1114 else if(feat[i] == '-'){
1115 fbuf[i] = SPACE;
1116 upper++;
1117 }
1118 else
1119 fbuf[i] = feat[i];
1120
1121 fbuf[i] = '\0';
1122
1123 /* cut off right hand edge if necessary */
1124 if(width > 0){
1125 char *p, gbuf[100];
1126
1127 p = short_str(fbuf, gbuf, sizeof(gbuf), width, EndDots);
1128
1129 if(p != fbuf){
1130 strncpy(fbuf, p, sizeof(fbuf)-1);
1131 fbuf[sizeof(fbuf)-1] = '\0';
1132 }
1133 }
1134
1135 return(fbuf);
1136 }
1137