* Update to version 2.19.5
[alpine.git] / alpine / setup.c
blob8279f3aa3f14dd58013df80f3d6a106b45bf00cf
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
5 /*
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2014 Eduardo Chappa
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
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
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"
40 * Internal prototypes
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);
49 #define CONFIG_SCREEN_TITLE _("SETUP CONFIGURATION")
50 #define CONFIG_SCREEN_TITLE_EXC _("SETUP CONFIGURATION EXCEPTIONS")
54 /*----------------------------------------------------------------------
55 Present pinerc data for manipulation
57 Args: None
59 Result: help edit certain pinerc fields.
60 ---*/
61 void
62 option_screen(struct pine *ps, int edit_exceptions)
64 char tmp[MAXPATH+1], *pval, **lval;
65 int i, j, ln = 0, readonly_warning = 0;
66 struct variable *vtmp;
67 CONF_S *ctmpa = NULL, *ctmpb, *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;
74 dprint((3, "-- option_screen --\n"));
76 expose_hidden_config = F_ON(F_EXPOSE_HIDDEN_CONFIG, ps_global);
77 treat_color_vars_as_text = expose_hidden_config;
79 ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
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;
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;
103 ps->next_screen = SCREEN_FUN_NULL;
105 mailcap_free(); /* free resources we won't be using for a while */
107 if(ps->fix_fixed_warning)
108 offer_to_fix_pinerc(ps);
111 * First, find longest variable name
113 for(vtmp = ps->vars; vtmp->name; vtmp++){
114 if(exclude_config_var(ps, vtmp, expose_hidden_config))
115 continue;
117 if((i = utf8_width(pretty_var_name(vtmp->name))) > ln)
118 ln = i;
121 dprint((9, "initialize config list\n"));
124 * Next, allocate and initialize config line list...
126 for(vtmp = ps->vars; vtmp->name; vtmp++){
128 * INCOMING_FOLDERS is currently the first of the normally
129 * hidden variables. Should probably invent a more robust way
130 * to keep this up to date.
132 if(expose_hidden_config && vtmp == &ps->vars[V_INCOMING_FOLDERS])
133 add_hidden_vars_title = 1;
135 if(exclude_config_var(ps, vtmp, expose_hidden_config))
136 continue;
138 if(add_hidden_vars_title){
140 add_hidden_vars_title = 0;
142 new_confline(&ctmpa); /* Blank line */
143 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
145 new_confline(&ctmpa)->var = NULL;
146 ctmpa->help = NO_HELP;
147 ctmpa->valoffset = 2;
148 ctmpa->flags |= CF_NOSELECT;
149 ctmpa->value = cpystr("--- [ Normally hidden configuration options ] ---");
151 new_confline(&ctmpa); /* Blank line */
152 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
155 if(vtmp->is_list)
156 lval = LVAL(vtmp, ew);
157 else
158 pval = PVAL(vtmp, ew);
160 new_confline(&ctmpa)->var = vtmp;
161 if(!first_line)
162 first_line = ctmpa;
164 ctmpa->valoffset = ln + 3;
165 if(vtmp->is_list)
166 ctmpa->keymenu = &config_text_wshuf_keymenu;
167 else
168 ctmpa->keymenu = &config_text_keymenu;
170 ctmpa->help = config_help(vtmp - ps->vars, 0);
171 ctmpa->tool = text_tool;
173 utf8_snprintf(tmp, sizeof(tmp), "%-*.100w =", ln, pretty_var_name(vtmp->name));
174 tmp[sizeof(tmp)-1] = '\0';
175 ctmpa->varname = cpystr(tmp);
176 ctmpa->varnamep = ctmpb = ctmpa;
177 ctmpa->flags |= CF_STARTITEM;
178 if(vtmp == &ps->vars[V_FEATURE_LIST]){ /* special checkbox case */
179 char *this_sect, *new_sect;
181 ctmpa->flags |= CF_NOSELECT;
182 ctmpa->keymenu = &config_checkbox_keymenu;
183 ctmpa->tool = NULL;
185 /* put a nice delimiter before list */
186 new_confline(&ctmpa)->var = NULL;
187 ctmpa->varnamep = ctmpb;
188 ctmpa->keymenu = &config_checkbox_keymenu;
189 ctmpa->help = NO_HELP;
190 ctmpa->tool = checkbox_tool;
191 ctmpa->valoffset = feature_indent();
192 ctmpa->flags |= CF_NOSELECT;
193 ctmpa->value = cpystr("Set Feature Name");
195 new_confline(&ctmpa)->var = NULL;
196 ctmpa->varnamep = ctmpb;
197 ctmpa->keymenu = &config_checkbox_keymenu;
198 ctmpa->help = NO_HELP;
199 ctmpa->tool = checkbox_tool;
200 ctmpa->valoffset = feature_indent();
201 ctmpa->flags |= CF_NOSELECT;
202 ctmpa->value = cpystr("--- ----------------------");
204 for(i = 0, this_sect = NULL; (feature = feature_list(i)); i++)
205 if((new_sect = feature_list_section(feature)) &&
206 (strcmp(new_sect, HIDDEN_PREF) != 0)){
207 if(this_sect != new_sect){
208 new_confline(&ctmpa)->var = NULL;
209 ctmpa->varnamep = ctmpb;
210 ctmpa->keymenu = &config_checkbox_keymenu;
211 ctmpa->help = NO_HELP;
212 ctmpa->tool = checkbox_tool;
213 ctmpa->valoffset = 2;
214 ctmpa->flags |= (CF_NOSELECT | CF_STARTITEM);
215 snprintf(tmp, sizeof(tmp), "[ %s ]", this_sect = new_sect);
216 tmp[sizeof(tmp)-1] = '\0';
217 ctmpa->value = cpystr(tmp);
220 new_confline(&ctmpa)->var = vtmp;
221 ctmpa->varnamep = ctmpb;
222 ctmpa->keymenu = &config_checkbox_keymenu;
223 ctmpa->help = config_help(vtmp-ps->vars,
224 feature->id);
225 ctmpa->tool = checkbox_tool;
226 ctmpa->valoffset = feature_indent();
227 ctmpa->varmem = i;
228 ctmpa->value = pretty_value(ps, ctmpa);
231 else if(standard_radio_var(ps, vtmp)){
232 standard_radio_setup(ps, &ctmpa, vtmp, NULL);
234 else if(vtmp == &ps->vars[V_SORT_KEY]){ /* radio case */
235 SortOrder def_sort;
236 int def_sort_rev;
238 ctmpa->flags |= CF_NOSELECT;
239 ctmpa->keymenu = &config_radiobutton_keymenu;
240 ctmpa->tool = NULL;
242 /* put a nice delimiter before list */
243 new_confline(&ctmpa)->var = NULL;
244 ctmpa->varnamep = ctmpb;
245 ctmpa->keymenu = &config_radiobutton_keymenu;
246 ctmpa->help = NO_HELP;
247 ctmpa->tool = radiobutton_tool;
248 ctmpa->valoffset = 12;
249 ctmpa->flags |= CF_NOSELECT;
250 ctmpa->value = cpystr("Set Sort Options");
252 new_confline(&ctmpa)->var = NULL;
253 ctmpa->varnamep = ctmpb;
254 ctmpa->keymenu = &config_radiobutton_keymenu;
255 ctmpa->help = NO_HELP;
256 ctmpa->tool = radiobutton_tool;
257 ctmpa->valoffset = 12;
258 ctmpa->flags |= CF_NOSELECT;
259 ctmpa->value = cpystr("--- ----------------------");
261 decode_sort(pval, &def_sort, &def_sort_rev);
263 for(j = 0; j < 2; j++){
264 for(i = 0; ps->sort_types[i] != EndofList; i++){
265 new_confline(&ctmpa)->var = vtmp;
266 ctmpa->varnamep = ctmpb;
267 ctmpa->keymenu = &config_radiobutton_keymenu;
268 ctmpa->help = config_help(vtmp - ps->vars, 0);
269 ctmpa->tool = radiobutton_tool;
270 ctmpa->valoffset = 12;
271 ctmpa->varmem = i + (j * EndofList);
272 ctmpa->value = pretty_value(ps, ctmpa);
276 else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */
277 ctmpa->keymenu = &config_yesno_keymenu;
278 ctmpa->tool = yesno_tool;
279 ctmpa->value = pretty_value(ps, ctmpa);
281 else if(vtmp == &ps->vars[V_LITERAL_SIG]){
282 ctmpa->tool = litsig_text_tool;
283 ctmpa->value = pretty_value(ps, ctmpa);
285 else if(vtmp == &ps->vars[V_INBOX_PATH]){
286 ctmpa->tool = inbox_path_text_tool;
287 ctmpa->value = pretty_value(ps, ctmpa);
289 else if(vtmp == &ps->vars[V_POST_CHAR_SET]
290 #ifndef _WINDOWS
291 || vtmp == &ps->vars[V_CHAR_SET]
292 || vtmp == &ps->vars[V_KEY_CHAR_SET]
293 #endif /* !_WINDOWS */
294 || vtmp == &ps->vars[V_UNK_CHAR_SET]){
295 ctmpa->keymenu = &config_text_to_charsets_keymenu;
296 ctmpa->tool = to_charsets_text_tool;
297 ctmpa->value = pretty_value(ps, ctmpa);
299 else if(vtmp->is_list){
300 int (*t_tool)(struct pine *, int, CONF_S **, unsigned);
301 struct key_menu *km;
303 t_tool = NULL;
304 km = NULL;
305 if(vtmp == &ps->vars[V_INCCHECKLIST]){
306 t_tool = incoming_monitoring_list_tool;
307 km = &config_text_keymenu;
309 else if(vtmp == &ps->vars[V_PERMLOCKED]){
310 t_tool = stayopen_list_tool;
311 km = &config_text_wshufandfldr_keymenu;
314 if(lval){
315 for(i = 0; lval[i]; i++){
316 if(i)
317 (void)new_confline(&ctmpa);
319 ctmpa->var = vtmp;
320 ctmpa->varmem = i;
321 ctmpa->valoffset = ln + 3;
322 ctmpa->value = pretty_value(ps, ctmpa);
323 ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu;
324 ctmpa->help = config_help(vtmp - ps->vars, 0);
325 ctmpa->tool = t_tool ? t_tool : text_tool;
326 ctmpa->varnamep = ctmpb;
329 else{
330 ctmpa->varmem = 0;
331 ctmpa->value = pretty_value(ps, ctmpa);
332 ctmpa->tool = t_tool ? t_tool : text_tool;
333 ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu;
336 else{
337 if(vtmp == &ps->vars[V_FILLCOL]
338 || vtmp == &ps->vars[V_SLEEP]
339 || vtmp == &ps->vars[V_QUOTE_SUPPRESSION]
340 || vtmp == &ps->vars[V_OVERLAP]
341 || vtmp == &ps->vars[V_MAXREMSTREAM]
342 || vtmp == &ps->vars[V_MARGIN]
343 || vtmp == &ps->vars[V_DEADLETS]
344 || vtmp == &ps->vars[V_NMW_WIDTH]
345 || vtmp == &ps->vars[V_STATUS_MSG_DELAY]
346 || vtmp == &ps->vars[V_ACTIVE_MSG_INTERVAL]
347 || vtmp == &ps->vars[V_MAILCHECK]
348 || vtmp == &ps->vars[V_MAILCHECKNONCURR]
349 || vtmp == &ps->vars[V_MAILDROPCHECK]
350 || vtmp == &ps->vars[V_NNTPRANGE]
351 || vtmp == &ps->vars[V_TCPOPENTIMEO]
352 || vtmp == &ps->vars[V_TCPREADWARNTIMEO]
353 || vtmp == &ps->vars[V_TCPWRITEWARNTIMEO]
354 || vtmp == &ps->vars[V_TCPQUERYTIMEO]
355 || vtmp == &ps->vars[V_RSHOPENTIMEO]
356 || vtmp == &ps->vars[V_SSHOPENTIMEO]
357 || vtmp == &ps->vars[V_INCCHECKTIMEO]
358 || vtmp == &ps->vars[V_INCCHECKINTERVAL]
359 || vtmp == &ps->vars[V_INC2NDCHECKINTERVAL]
360 || vtmp == &ps->vars[V_USERINPUTTIMEO]
361 || vtmp == &ps->vars[V_REMOTE_ABOOK_VALIDITY]
362 || vtmp == &ps->vars[V_REMOTE_ABOOK_HISTORY])
363 ctmpa->flags |= CF_NUMBER;
365 ctmpa->value = pretty_value(ps, ctmpa);
369 dprint((9, "add hidden features\n"));
371 /* add the hidden features */
372 if(expose_hidden_config){
373 char *new_sect;
375 new_confline(&ctmpa); /* Blank line */
376 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
378 new_confline(&ctmpa)->var = NULL;
379 ctmpa->help = NO_HELP;
380 ctmpa->valoffset = 2;
381 ctmpa->flags |= CF_NOSELECT;
382 ctmpa->value = cpystr("--- [ Normally hidden configuration features ] ---");
384 new_confline(&ctmpa); /* Blank line */
385 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
387 vtmp = &ps->vars[V_FEATURE_LIST];
389 ctmpa->flags |= CF_NOSELECT;
390 ctmpa->keymenu = &config_checkbox_keymenu;
391 ctmpa->tool = NULL;
393 /* put a nice delimiter before list */
394 new_confline(&ctmpa)->var = NULL;
395 ctmpa->varnamep = ctmpb;
396 ctmpa->keymenu = &config_checkbox_keymenu;
397 ctmpa->help = NO_HELP;
398 ctmpa->tool = checkbox_tool;
399 ctmpa->valoffset = feature_indent();
400 ctmpa->flags |= CF_NOSELECT;
401 ctmpa->value = cpystr("Set Feature Name");
403 new_confline(&ctmpa)->var = NULL;
404 ctmpa->varnamep = ctmpb;
405 ctmpa->keymenu = &config_checkbox_keymenu;
406 ctmpa->help = NO_HELP;
407 ctmpa->tool = checkbox_tool;
408 ctmpa->valoffset = feature_indent();
409 ctmpa->flags |= CF_NOSELECT;
410 ctmpa->value = cpystr("--- ----------------------");
412 for(i = 0; (feature = feature_list(i)); i++)
413 if((new_sect = feature_list_section(feature)) &&
414 (strcmp(new_sect, HIDDEN_PREF) == 0)){
416 new_confline(&ctmpa)->var = vtmp;
417 ctmpa->varnamep = ctmpb;
418 ctmpa->keymenu = &config_checkbox_keymenu;
419 ctmpa->help = config_help(vtmp-ps->vars,
420 feature->id);
421 ctmpa->tool = checkbox_tool;
422 ctmpa->valoffset = feature_indent();
423 ctmpa->varmem = i;
424 ctmpa->value = pretty_value(ps, ctmpa);
428 vsave = save_config_vars(ps, expose_hidden_config);
429 first_line = first_sel_confline(first_line);
431 memset(&screen, 0, sizeof(screen));
432 screen.ro_warning = readonly_warning;
433 /* TRANSLATORS: Print something1 using something2.
434 "configuration" is something1 */
435 switch(conf_scroll_screen(ps, &screen, first_line,
436 edit_exceptions ? CONFIG_SCREEN_TITLE_EXC
437 : CONFIG_SCREEN_TITLE,
438 _("configuration"), 0)){
439 case 0:
440 break;
442 case 1:
443 write_pinerc(ps, ew, WRP_NONE);
444 break;
446 case 10:
447 revert_to_saved_config(ps, vsave, expose_hidden_config);
448 if(prc)
449 prc->outstanding_pinerc_changes = 0;
451 break;
453 default:
454 q_status_message(SM_ORDER,7,10,
455 "conf_scroll_screen bad ret, not supposed to happen");
456 break;
459 pval = PVAL(&ps->vars[V_SORT_KEY], ew);
460 if(vsave[V_SORT_KEY].saved_user_val.p && pval
461 && strcmp(vsave[V_SORT_KEY].saved_user_val.p, pval)){
462 if(!mn_get_mansort(ps_global->msgmap)){
463 clear_index_cache(ps_global->mail_stream, 0);
464 reset_sort_order(SRT_VRB);
468 treat_color_vars_as_text = 0;
469 free_saved_config(ps, &vsave, expose_hidden_config);
470 #ifdef _WINDOWS
471 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
472 #endif
477 litsig_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
479 char **apval;
480 int rv = 0;
482 if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL))
483 return(rv);
485 apval = APVAL((*cl)->var, ew);
487 switch(cmd){
488 case MC_ADD:
489 case MC_EDIT :
490 if(apval){
491 char *input = NULL, *result = NULL, *err = NULL, *cstring_version;
492 char *olddefval = NULL, *start_with;
493 size_t len;
495 if(!*apval && (*cl)->var->current_val.p &&
496 (*cl)->var->current_val.p[0]){
497 if(!strncmp((*cl)->var->current_val.p,
498 DSTRING,
499 (len=strlen(DSTRING)))){
500 /* strip DSTRING and trailing paren */
501 olddefval = (char *)fs_get(strlen((*cl)->var->current_val.p)+1);
502 strncpy(olddefval, (*cl)->var->current_val.p+len,
503 strlen((*cl)->var->current_val.p)-len-1);
504 olddefval[strlen((*cl)->var->current_val.p)-len-1] = '\0';
505 start_with = olddefval;
507 else{
508 olddefval = cpystr((*cl)->var->current_val.p);
509 start_with = olddefval;
512 else
513 start_with = (*apval) ? *apval : "";
515 input = (char *)fs_get((strlen(start_with)+1) * sizeof(char));
516 input[0] = '\0';
517 cstring_to_string(start_with, input);
518 err = signature_edit_lit(input, &result,
519 ((*cl)->var == role_comment_ptr)
520 ? "COMMENT EDITOR"
521 : "SIGNATURE EDITOR",
522 ((*cl)->var == role_comment_ptr)
523 ? h_composer_commentedit
524 : h_composer_sigedit);
526 if(!err){
527 if(olddefval && !strcmp(input, result) &&
528 want_to(_("Leave unset and use default "), 'y',
529 'y', NO_HELP, WT_FLUSH_IN) == 'y'){
530 rv = 0;
532 else{
533 cstring_version = string_to_cstring(result);
535 if(apval && *apval)
536 fs_give((void **)apval);
538 if(apval){
539 *apval = cstring_version;
540 cstring_version = NULL;
543 if(cstring_version)
544 fs_give((void **)&cstring_version);
546 rv = 1;
549 else
550 rv = 0;
552 if(err){
553 q_status_message1(SM_ORDER, 3, 5, "%s", err);
554 fs_give((void **)&err);
557 if(result)
558 fs_give((void **)&result);
559 if(olddefval)
560 fs_give((void **)&olddefval);
561 if(input)
562 fs_give((void **)&input);
565 ps->mangled_screen = 1;
566 break;
568 default:
569 rv = text_tool(ps, cmd, cl, flags);
570 break;
574 * At this point, if changes occurred, var->user_val.X is set.
575 * So, fix the current_val, and handle special cases...
577 * NOTE: we don't worry about the "fixed variable" case here, because
578 * editing such vars should have been prevented above...
580 if(rv == 1){
582 * Now go and set the current_val based on user_val changes
583 * above. Turn off command line settings...
585 set_current_val((*cl)->var, TRUE, FALSE);
587 if((*cl)->value)
588 fs_give((void **)&(*cl)->value);
590 (*cl)->value = pretty_value(ps, *cl);
592 exception_override_warning((*cl)->var);
595 * The value of literal sig can affect whether signature file is
596 * used or not. So it affects what we display for sig file variable.
598 if((*cl)->next && (*cl)->next->var == &ps->vars[V_SIGNATURE_FILE]){
599 if((*cl)->next->value)
600 fs_give((void **)&(*cl)->next->value);
602 (*cl)->next->value = pretty_value(ps, (*cl)->next);
606 return(rv);
611 inbox_path_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
613 char **apval;
614 int rv = 0;
615 char new_inbox_path[2*MAXFOLDER+1];
616 char *def = NULL;
617 CONTEXT_S *cntxt;
619 if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL))
620 return(rv);
622 apval = APVAL((*cl)->var, ew);
624 switch(cmd){
625 case MC_ADD:
626 case MC_EDIT:
627 cntxt = ps->context_list;
628 if(cmd == MC_EDIT && (*cl)->var){
629 if(ew == Post && (*cl)->var->post_user_val.p)
630 def = (*cl)->var->post_user_val.p;
631 else if(ew == Main && (*cl)->var->main_user_val.p)
632 def = (*cl)->var->main_user_val.p;
633 else if((*cl)->var->current_val.p)
634 def = (*cl)->var->current_val.p;
637 rv = add_new_folder(cntxt, ew, V_INBOX_PATH, new_inbox_path,
638 sizeof(new_inbox_path), NULL, def);
639 rv = rv ? 1 : 0;
641 ps->mangled_screen = 1;
642 break;
644 default:
645 rv = text_tool(ps, cmd, cl, flags);
646 break;
650 * This is just like the end of text_tool.
652 if(rv == 1){
654 * Now go and set the current_val based on user_val changes
655 * above. Turn off command line settings...
657 set_current_val((*cl)->var, TRUE, FALSE);
658 fix_side_effects(ps, (*cl)->var, 0);
660 if((*cl)->value)
661 fs_give((void **) &(*cl)->value);
663 (*cl)->value = pretty_value(ps, *cl);
665 exception_override_warning((*cl)->var);
668 return(rv);
673 incoming_monitoring_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
675 int rv = 0;
676 CONTEXT_S *cntxt;
677 char **the_list;
678 CONF_S *ctmp;
679 char ***alval;
680 OPT_SCREEN_S *saved_screen;
682 if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL))
683 return(rv);
685 switch(cmd){
686 case MC_ADD:
687 case MC_EDIT:
688 cntxt = ps->context_list;
689 if(!(cntxt && cntxt->use & CNTXT_INCMNG)){
690 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));
691 return(rv);
694 saved_screen = opt_screen;
696 the_list = adjust_list_of_monitored_incoming(cntxt, ew, V_INCCHECKLIST);
698 /* adjust top if it might be necessary */
699 for(ctmp = (*cl)->varnamep;
700 ctmp && ctmp->varnamep == (*cl)->varnamep;
701 ctmp = next_confline(ctmp))
702 if(ctmp == opt_screen->top_line)
703 opt_screen->top_line = (*cl)->varnamep;
705 if(the_list){
706 alval = ALVAL((*cl)->var, ew);
707 free_list_array(alval);
708 if(!*the_list){
709 q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders"));
710 if(alval){
712 * Remove config lines except for first one.
714 *cl = (*cl)->varnamep;
715 while((*cl)->next && (*cl)->next->varnamep == (*cl)->varnamep)
716 snip_confline(&(*cl)->next);
719 else
720 config_add_list(ps, cl, the_list, NULL, 0);
722 /* only have to free the top-level pointer */
723 fs_give((void **) &the_list);
724 rv = 1;
726 else{
727 if(LVAL((*cl)->var, ew))
728 q_status_message(SM_ORDER, 0, 3, _("List is unchanged"));
729 else
730 q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders"));
733 opt_screen = saved_screen;
734 ps->mangled_screen = 1;
735 break;
737 default:
738 rv = text_tool(ps, cmd, cl, flags);
739 /* if we deleted last one, reverts to default */
740 if(cmd == MC_DELETE && rv == 1 && (*cl)->varmem == 0
741 && (!(*cl)->next || (*cl)->next->varnamep != (*cl)))
742 q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders"));
744 break;
748 * This is just like the end of text_tool.
750 if(rv == 1){
752 * Now go and set the current_val based on user_val changes
753 * above. Turn off command line settings...
755 set_current_val((*cl)->var, TRUE, FALSE);
756 fix_side_effects(ps, (*cl)->var, 0);
758 if((*cl)->value)
759 fs_give((void **) &(*cl)->value);
761 (*cl)->value = pretty_value(ps, *cl);
763 exception_override_warning((*cl)->var);
766 return(rv);
770 char **
771 adjust_list_of_monitored_incoming(CONTEXT_S *cntxt, EditWhich which, int varnum)
773 LIST_SEL_S *listhead, *p, *ls;
774 int i, cnt, ftotal;
775 long width;
776 FOLDER_S *f;
777 char **the_list = NULL, buf[1000];
779 if(!(cntxt && cntxt->use & CNTXT_INCMNG))
780 return(the_list);
782 p = listhead = NULL;
784 /* this width is determined by select_from_list_screen() */
785 width = ps_global->ttyo->screen_cols - 4;
788 * Put together a list of folders to select from.
789 * We could choose to use the list associated with
790 * the config we're editing, and that may be correct.
791 * However, we think most users will expect the list
792 * to be the list that is in use. In any case, these
793 * are almost always the same.
796 ftotal = folder_total(FOLDERS(cntxt));
798 for(i = 0; i < ftotal; i++){
800 f = folder_entry(i, FOLDERS(cntxt));
802 ls = (LIST_SEL_S *) fs_get(sizeof(*ls));
803 memset(ls, 0, sizeof(*ls));
805 if(f && f->nickname){
806 ls->item = cpystr(f->nickname);
807 snprintf(buf, sizeof(buf), "%s (%s)", f->nickname, f->name ? f->name : "?");
808 ls->display_item = cpystr(buf);
810 else
811 ls->item = cpystr((f && f->name) ? f->name : "?");
813 if(f && f->last_unseen_update != LUU_NEVERCHK)
814 ls->selected = 1;
816 if(p){
817 p->next = ls;
818 p = p->next;
820 else{
821 /* add a heading */
822 listhead = (LIST_SEL_S *) fs_get(sizeof(*ls));
823 memset(listhead, 0, sizeof(*listhead));
824 listhead->flags = SFL_NOSELECT;
825 listhead->display_item = cpystr(_("Incoming folders to be monitored"));
826 listhead->next = (LIST_SEL_S *) fs_get(sizeof(*ls));
827 memset(listhead->next, 0, sizeof(*listhead));
828 listhead->next->flags = SFL_NOSELECT;
829 listhead->next->display_item = cpystr(repeat_char(width, '-'));
831 listhead->next->next = ls;
832 p = ls;
836 if(!listhead){
837 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));
838 return(the_list);
841 if(!select_from_list_screen(listhead,
842 SFL_ALLOW_LISTMODE|SFL_STARTIN_LISTMODE|SFL_ONLY_LISTMODE|SFL_CTRLC,
843 _("SELECT FOLDERS TO MONITOR"), _("folders"),
844 h_select_incoming_to_monitor,
845 _("HELP FOR SELECTING FOLDERS"), NULL)){
847 for(cnt = 0, p = listhead; p; p = p->next)
848 if(p->selected)
849 cnt++;
851 if(cnt >= 0 && cnt <= ftotal){
852 the_list = (char **) fs_get((cnt+1) * sizeof(*the_list));
853 memset(the_list, 0, (cnt+1) * sizeof(*the_list));
854 for(i = 0, p = listhead; p; p = p->next)
855 if(p->selected)
856 the_list[i++] = cpystr(p->item ? p->item : "");
860 free_list_sel(&listhead);
862 return(the_list);
867 stayopen_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
869 int rv = 0;
870 char **newval = NULL;
871 char **ltmp = NULL;
872 char *folder = NULL;
873 void (*prev_screen)(struct pine *) = ps->prev_screen,
874 (*redraw)(void) = ps->redrawer;
875 OPT_SCREEN_S *saved_screen = NULL;
877 switch(cmd){
878 case MC_CHOICE:
879 if(fixed_var((*cl)->var, NULL, NULL))
880 break;
882 ps->redrawer = NULL;
883 ps->next_screen = SCREEN_FUN_NULL;
884 saved_screen = opt_screen;
885 folder = folder_for_config(FOR_OPTIONSCREEN);
886 removing_leading_and_trailing_white_space(folder);
887 if(folder && *folder){
888 ltmp = (char **) fs_get(2 * sizeof(char *));
889 ltmp[0] = cpystr(folder);
890 ltmp[1] = NULL;
892 config_add_list(ps, cl, ltmp, &newval, 0);
894 if(ltmp)
895 fs_give((void **) &ltmp);
897 rv = 1;
899 /* this stuff is from bottom of text_toolit() */
902 * At this point, if changes occurred, var->user_val.X is set.
903 * So, fix the current_val, and handle special cases...
905 * NOTE: we don't worry about the "fixed variable" case here, because
906 * editing such vars should have been prevented above...
910 * Now go and set the current_val based on user_val changes
911 * above. Turn off command line settings...
913 set_current_val((*cl)->var, TRUE, FALSE);
914 fix_side_effects(ps, (*cl)->var, 0);
917 * Delay setting the displayed value until "var.current_val" is set
918 * in case current val get's changed due to a special case above.
920 if(newval){
921 if(*newval)
922 fs_give((void **) newval);
924 *newval = pretty_value(ps, *cl);
927 exception_override_warning((*cl)->var);
929 if(folder)
930 fs_give((void **) &folder);
932 else{
933 ps->next_screen = prev_screen;
934 ps->redrawer = redraw;
935 rv = 0;
938 opt_screen = saved_screen;
939 ps->mangled_screen = 1;
940 break;
942 default:
943 rv = text_tool(ps, cmd, cl, flags);
944 break;
947 return(rv);
952 to_charsets_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
954 int rv = 0;
955 char **newval = NULL;
956 void (*prev_screen)(struct pine *) = ps->prev_screen,
957 (*redraw)(void) = ps->redrawer;
958 OPT_SCREEN_S *saved_screen = NULL;
959 char **apval;
960 char *charset = NULL;
962 switch(cmd){
963 case MC_CHOICE:
964 if(fixed_var((*cl)->var, NULL, NULL))
965 break;
967 apval = APVAL((*cl)->var, ew);
969 if(apval){
970 int cac_flags = CAC_ALL;
972 ps->redrawer = NULL;
973 ps->next_screen = SCREEN_FUN_NULL;
974 saved_screen = opt_screen;
976 if((*cl)->var == &ps->vars[V_POST_CHAR_SET])
977 cac_flags = CAC_POSTING;
978 #ifndef _WINDOWS
979 else if((*cl)->var == &ps->vars[V_CHAR_SET]
980 || (*cl)->var == &ps->vars[V_KEY_CHAR_SET])
981 cac_flags = CAC_DISPLAY;
982 #endif /* !_WINDOWS */
984 charset = choose_a_charset(cac_flags);
986 removing_leading_and_trailing_white_space(charset);
987 if(charset && *charset){
988 rv = 1;
989 if(apval && *apval)
990 fs_give((void **) apval);
992 *apval = charset;
993 charset = NULL;
994 newval = &(*cl)->value;
996 /* this stuff is from bottom of text_toolit() */
999 * At this point, if changes occurred, var->user_val.X is set.
1000 * So, fix the current_val, and handle special cases...
1002 * NOTE: we don't worry about the "fixed variable" case here, because
1003 * editing such vars should have been prevented above...
1007 * Now go and set the current_val based on user_val changes
1008 * above. Turn off command line settings...
1010 set_current_val((*cl)->var, TRUE, FALSE);
1011 fix_side_effects(ps, (*cl)->var, 0);
1012 if(newval){
1013 if(*newval)
1014 fs_give((void **) newval);
1016 *newval = pretty_value(ps, *cl);
1019 exception_override_warning((*cl)->var);
1021 else{
1022 ps->next_screen = prev_screen;
1023 ps->redrawer = redraw;
1024 rv = 0;
1027 if(charset)
1028 fs_give((void **) &charset);
1030 opt_screen = saved_screen;
1031 ps->mangled_screen = 1;
1033 break;
1035 default:
1036 rv = text_tool(ps, cmd, cl, flags);
1037 break;
1040 return(rv);
1045 * pretty_var_name - return a pleasantly displayable form
1046 * of variable name variable
1048 char *
1049 pretty_var_name(char *varname)
1051 struct variable *v;
1052 int i, upper = 1;
1053 static char vbuf[100];
1055 vbuf[0] = '\0';
1056 v = var_from_name(varname);
1058 if(!v)
1059 return(vbuf);
1061 if(v->dname && v->dname[0])
1062 return(v->dname);
1064 if(!(v->name && v->name[0]))
1065 return(vbuf);
1067 /* default: uppercase first letters, dashes to spaces */
1068 for(i = 0; i < sizeof(vbuf)-1 && v->name[i]; i++)
1069 if(upper){
1070 vbuf[i] = (islower((unsigned char) v->name[i]))
1071 ? toupper((unsigned char) v->name[i])
1072 : v->name[i];
1073 upper = 0;
1075 else if(v->name[i] == '-'){
1076 vbuf[i] = SPACE;
1077 upper++;
1079 else
1080 vbuf[i] = v->name[i];
1082 vbuf[i] = '\0';
1083 return(vbuf);
1088 * pretty_feature_name - return a pleasantly displayable form
1089 * of feature name variable
1091 char *
1092 pretty_feature_name(char *feat, int width)
1094 FEATURE_S *f;
1095 int i, upper = 1;
1096 static char fbuf[100];
1098 f = feature_list(feature_list_index(feature_list_id(feat)));
1099 if(f && f->dname && f->dname[0])
1100 return(f->dname);
1102 /* default: uppercase first letters, dashes become spaces */
1103 for(i = 0; i < sizeof(fbuf)-1 && feat[i]; i++)
1104 if(upper){
1105 fbuf[i] = (islower((unsigned char) feat[i]))
1106 ? toupper((unsigned char) feat[i])
1107 : feat[i];
1108 upper = 0;
1110 else if(feat[i] == '-'){
1111 fbuf[i] = SPACE;
1112 upper++;
1114 else
1115 fbuf[i] = feat[i];
1117 fbuf[i] = '\0';
1119 /* cut off right hand edge if necessary */
1120 if(width > 0){
1121 char *p, gbuf[100];
1123 p = short_str(fbuf, gbuf, sizeof(gbuf), width, EndDots);
1125 if(p != fbuf){
1126 strncpy(fbuf, p, sizeof(fbuf)-1);
1127 fbuf[sizeof(fbuf)-1] = '\0';
1131 return(fbuf);