2 * ========================================================================
3 * Copyright 2006-2008 University of Washington
4 * Copyright 2013-2021 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
16 #include "confscroll.h"
25 #include "colorconf.h"
32 #include "xoauth2conf.h"
33 #include "../pith/state.h"
34 #include "../pith/flag.h"
35 #include "../pith/list.h"
36 #include "../pith/conf.h"
37 #include "../pith/util.h"
38 #include "../pith/newmail.h"
39 #include "../pith/sort.h"
40 #include "../pith/thread.h"
41 #include "../pith/color.h"
42 #include "../pith/hist.h"
43 #include "../pith/icache.h"
44 #include "../pith/conf.h"
45 #include "../pith/init.h"
46 #include "../pith/folder.h"
47 #include "../pith/busy.h"
48 #include "../pith/tempfile.h"
49 #include "../pith/pattern.h"
50 #include "../pith/charconv/utf8.h"
53 #define CONFIG_SCREEN_HELP_TITLE _("HELP FOR SETUP CONFIGURATION")
55 /* TRANSLATORS: Empty Value is what is shown in the configuration
56 screen when the user not only does not set an option but also
57 wants to explicitly not use the default value. Empty value means
58 an option with no value. */
59 char *empty_val
= N_("Empty Value");
60 char *empty_val2
= N_("<Empty Value>");
61 /* TRANSLATORS: No Value set is similar to Empty Value, but the
62 user has not explicitly decided to not use the default. It is
63 just an option which the user has left at the default value. */
64 char *no_val
= N_("No Value Set");
65 /* TRANSLATORS: Value is Fixed is what is displayed in the config
66 screen when the system managers have set an option to a specific
67 value and they don't allow the user to change it. The value
68 is fixed to a certain value. This isn't the same word as
69 Repaired, it means Unchanging. */
70 char *fixed_val
= N_("Value is Fixed");
71 char yesstr
[] = "Yes";
78 OPT_SCREEN_S
*opt_screen
;
82 * This is pretty ugly. Some of the routines operate differently depending
83 * on which variable they are operating on. Sometimes those variables are
84 * global (real alpine.h V_ style variables) and sometimes they are just
85 * local variables (as in role_config_edit_screen). These pointers are here
86 * so that the routines can figure out which variable they are operating
87 * on and do the right thing.
89 struct variable
*score_act_global_ptr
,
90 *scorei_pat_global_ptr
,
117 typedef NAMEVAL_S
*(*PTR_TO_RULEFUNC
)(int);
121 * Internal prototypes
123 PTR_TO_RULEFUNC
rulefunc_from_var(struct pine
*, struct variable
*);
124 void set_radio_pretty_vals(struct pine
*, CONF_S
**);
125 int save_include(struct pine
*, struct variable
*, int);
126 void config_scroll_up(long);
127 void config_scroll_down(long);
128 void config_scroll_to_pos(long);
129 CONF_S
*config_top_scroll(struct pine
*, CONF_S
*);
130 void update_option_screen(struct pine
*, OPT_SCREEN_S
*, Pos
*);
131 void print_option_screen(OPT_SCREEN_S
*, char *);
132 void option_screen_redrawer(void);
133 char *text_pretty_value(struct pine
*, CONF_S
*);
134 char *checkbox_pretty_value(struct pine
*, CONF_S
*);
135 char *yesno_pretty_value(struct pine
*, CONF_S
*);
136 char *radio_pretty_value(struct pine
*, CONF_S
*);
137 char *sigfile_pretty_value(struct pine
*, CONF_S
*);
138 char *color_pretty_value(struct pine
*, CONF_S
*);
139 char *sort_pretty_value(struct pine
*, CONF_S
*);
140 int longest_feature_name(void);
141 COLOR_PAIR
*sample_color(struct pine
*, struct variable
*);
142 COLOR_PAIR
*sampleexc_color(struct pine
*, struct variable
*);
143 void clear_feature(char ***, char *);
144 CONF_S
*last_confline(CONF_S
*);
146 int config_scroll_callback(int, long);
151 * We test for this same set of vars in a few places.
154 standard_radio_var(struct pine
*ps
, struct variable
*v
)
156 return(v
== &ps
->vars
[V_SAVED_MSG_NAME_RULE
] ||
157 v
== &ps
->vars
[V_FCC_RULE
] ||
158 v
== &ps
->vars
[V_GOTO_DEFAULT_RULE
] ||
159 v
== &ps
->vars
[V_INCOMING_STARTUP
] ||
160 v
== &ps
->vars
[V_PRUNING_RULE
] ||
161 v
== &ps
->vars
[V_REOPEN_RULE
] ||
162 v
== &ps
->vars
[V_THREAD_DISP_STYLE
] ||
163 v
== &ps
->vars
[V_THREAD_INDEX_STYLE
] ||
164 v
== &ps
->vars
[V_FLD_SORT_RULE
] ||
166 v
== &ps
->vars
[V_COLOR_STYLE
] ||
168 v
== &ps
->vars
[V_INDEX_COLOR_STYLE
] ||
169 v
== &ps
->vars
[V_TITLEBAR_COLOR_STYLE
] ||
170 v
== &ps
->vars
[V_AB_SORT_RULE
]);
175 rulefunc_from_var(struct pine
*ps
, struct variable
*v
)
177 PTR_TO_RULEFUNC rulefunc
= NULL
;
179 if(v
== &ps
->vars
[V_SAVED_MSG_NAME_RULE
])
180 rulefunc
= save_msg_rules
;
181 else if(v
== &ps
->vars
[V_FCC_RULE
])
182 rulefunc
= fcc_rules
;
183 else if(v
== &ps
->vars
[V_GOTO_DEFAULT_RULE
])
184 rulefunc
= goto_rules
;
185 else if(v
== &ps
->vars
[V_INCOMING_STARTUP
])
186 rulefunc
= incoming_startup_rules
;
187 else if(v
== startup_ptr
)
188 rulefunc
= startup_rules
;
189 else if(v
== &ps
->vars
[V_PRUNING_RULE
])
190 rulefunc
= pruning_rules
;
191 else if(v
== &ps
->vars
[V_REOPEN_RULE
])
192 rulefunc
= reopen_rules
;
193 else if(v
== &ps
->vars
[V_THREAD_DISP_STYLE
])
194 rulefunc
= thread_disp_styles
;
195 else if(v
== &ps
->vars
[V_THREAD_INDEX_STYLE
])
196 rulefunc
= thread_index_styles
;
197 else if(v
== &ps
->vars
[V_FLD_SORT_RULE
])
198 rulefunc
= fld_sort_rules
;
199 else if(v
== &ps
->vars
[V_AB_SORT_RULE
])
200 rulefunc
= ab_sort_rules
;
201 else if(v
== &ps
->vars
[V_INDEX_COLOR_STYLE
])
202 rulefunc
= index_col_style
;
203 else if(v
== &ps
->vars
[V_TITLEBAR_COLOR_STYLE
])
204 rulefunc
= titlebar_col_style
;
206 else if(v
== &ps
->vars
[V_COLOR_STYLE
])
207 rulefunc
= col_style
;
215 standard_radio_setup(struct pine
*ps
, CONF_S
**cl
, struct variable
*v
, CONF_S
**first_line
)
219 PTR_TO_RULEFUNC rulefunc
;
226 rulefunc
= rulefunc_from_var(ps
, v
);
229 (*cl
)->flags
|= CF_NOSELECT
;
230 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
233 /* put a nice delimiter before list */
234 new_confline(cl
)->var
= NULL
;
235 (*cl
)->varnamep
= ctmpb
;
236 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
237 (*cl
)->help
= NO_HELP
;
238 (*cl
)->tool
= radiobutton_tool
;
239 (*cl
)->valoffset
= rindent
;
240 (*cl
)->flags
|= CF_NOSELECT
;
241 /* TRANSLATORS: Set and Rule Values are the headings for an option
242 that can take one of several values. Underneath the Set heading
243 will be a column where one possibility is turned on (is Set).
244 The other column will be very short descriptions of what
245 the possibilities are (the Rule Values). */
246 utf8_snprintf(b
, sizeof(b
), "%-5.5w %s", _("Set"), _("Rule Values"));
247 (*cl
)->value
= cpystr(b
);
249 new_confline(cl
)->var
= NULL
;
250 (*cl
)->varnamep
= ctmpb
;
251 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
252 (*cl
)->help
= NO_HELP
;
253 (*cl
)->tool
= radiobutton_tool
;
254 (*cl
)->valoffset
= rindent
;
255 (*cl
)->flags
|= CF_NOSELECT
;
256 (*cl
)->value
= cpystr("--- ----------------------");
259 for(i
= 0; (f
= (*rulefunc
)(i
)); i
++){
260 new_confline(cl
)->var
= v
;
261 if(first_line
&& !*first_line
&& !pico_usingcolor())
264 (*cl
)->varnamep
= ctmpb
;
265 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
266 (*cl
)->help
= (v
== startup_ptr
)
267 ? h_config_other_startup
268 : config_help(v
- ps
->vars
,0);
269 (*cl
)->tool
= radiobutton_tool
;
270 (*cl
)->valoffset
= rindent
;
272 (*cl
)->value
= pretty_value(ps
, *cl
);
278 * Reset the displayed values for all of the lines for this
279 * variable because others besides this line may change.
282 set_radio_pretty_vals(struct pine
*ps
, CONF_S
**cl
)
287 ((*cl
)->var
== &ps
->vars
[V_SORT_KEY
] ||
288 standard_radio_var(ps
, (*cl
)->var
) ||
289 (*cl
)->var
== startup_ptr
)))
294 ctmp
&& !(ctmp
->flags
& CF_NOSELECT
) && !ctmp
->varname
;
295 ctmp
= prev_confline(ctmp
)){
297 fs_give((void **)&ctmp
->value
);
299 ctmp
->value
= pretty_value(ps
, ctmp
);
304 ctmp
&& !ctmp
->varname
&& !(ctmp
->flags
& CF_NOSELECT
);
305 ctmp
= next_confline(ctmp
)){
307 fs_give((void **)&ctmp
->value
);
309 ctmp
->value
= pretty_value(ps
, ctmp
);
315 * test whether or not a var is
317 * returns: 1 if it should be excluded, 0 otw
320 exclude_config_var(struct pine
*ps
, struct variable
*var
, int allow_hard_to_config_remotely
)
322 if((ew
!= Main
&& (var
->is_onlymain
)) ||
323 (ew
!= ps_global
->ew_for_except_vars
&& var
->is_outermost
))
326 if(allow_hard_to_config_remotely
)
327 return(!(var
->is_user
&& var
->is_used
&& !var
->is_obsolete
));
329 switch(var
- ps
->vars
){
330 case V_HTML_DIRECTORY
:
331 case V_MAIL_DIRECTORY
:
332 case V_INCOMING_FOLDERS
:
335 case V_STANDARD_PRINTER
:
336 case V_LAST_TIME_PRUNE_QUESTION
:
337 case V_LAST_VERS_USED
:
339 case V_GLOB_ADDRBOOK
:
340 case V_DISABLE_DRIVERS
:
341 case V_DISABLE_AUTHS
:
342 #ifdef DF_ENCRYPTION_RANGE
343 case V_ENCRYPTION_RANGE
:
344 #endif /* DF_ENCRYPTION_RANGE */
345 case V_REMOTE_ABOOK_METADATA
:
346 case V_REMOTE_ABOOK_HISTORY
:
347 case V_REMOTE_ABOOK_VALIDITY
:
349 case V_USERINPUTTIMEO
:
350 case V_TCPOPENTIMEO
:
351 case V_TCPREADWARNTIMEO
:
352 case V_TCPWRITEWARNTIMEO
:
353 case V_TCPQUERYTIMEO
:
354 case V_QUITQUERYTIMEO
:
357 case V_RSHOPENTIMEO
:
360 case V_SSHOPENTIMEO
:
361 case V_SENDMAIL_PATH
:
362 case V_NEW_VER_QUELL
:
371 case V_PERSONAL_PRINT_COMMAND
:
372 case V_PERSONAL_PRINT_CATEGORY
:
375 case V_WP_INDEXHEIGHT
:
376 case V_WP_INDEXLINES
:
381 case V_OLD_CHAR_SET
:
382 #endif /* ! _WINDOWS */
383 #if defined(DOS) || defined(OS2)
385 case V_UPLOAD_CMD_PREFIX
:
386 case V_DOWNLOAD_CMD
:
387 case V_DOWNLOAD_CMD_PREFIX
:
392 case V_FONT_CHAR_SET
:
393 case V_PRINT_FONT_NAME
:
394 case V_PRINT_FONT_SIZE
:
395 case V_PRINT_FONT_STYLE
:
396 case V_PRINT_FONT_CHAR_SET
:
397 case V_WINDOW_POSITION
:
398 case V_CURSOR_STYLE
:
399 #endif /* _WINDOWS */
402 case V_LDAP_SERVERS
:
403 #endif /* ENABLE_LDAP */
410 return(!(var
->is_user
&& var
->is_used
&& !var
->is_obsolete
&&
412 !smime_related_var(ps
, var
) &&
414 !color_related_var(ps
, var
)));
419 * Test to indicate what should be saved in case user wants to abandon
423 save_include(struct pine
*ps
, struct variable
*v
, int allow_hard_to_config_remotely
)
425 return(!exclude_config_var(ps
, v
, allow_hard_to_config_remotely
)
429 && (v
== &ps
->vars
[V_PERSONAL_PRINT_COMMAND
]
431 || v
== &ps
->vars
[V_LDAP_SERVERS
]
438 * Handles screen painting and motion. Passes other commands to
441 * Tool return values: Tools should return the following:
443 * -1 unrecognized command
444 * 1 something changed, conf_scroll_screen should remember that
445 * 2 tells conf_scroll_screen to return with value 1 or 0 depending
446 * on whether or not it has previously gotten a 1 from some tool.
447 * 3 tells conf_scroll_screen to return 1 (like 1 and 2 combined)
448 * ? Other tool-specific values can be used. They will cause
449 * conf_scroll_screen to return that value.
452 * 0 if nothing happened. That is, a tool returned 2 and we hadn't
453 * previously noted a return of 1
454 * 1 if something happened. That is, a tool returned 2 and we had
455 * previously noted a return of 1
456 * ? Tool-returned value different from -1, 0, 1, 2, or 3. This is it.
458 * Special proviso: If first_line->flags has CF_CHANGES set on entry, then
459 * that will cause things to behave like a change was made since entering
463 conf_scroll_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, CONF_S
*start_line
, char *title
, char *pdesc
, int multicol
, int *pos
)
468 int cmd
, i
, j
, done
= 0, changes
= 0;
470 int km_popped
= 0, stay_in_col
= 0;
471 struct key_menu
*km
= NULL
;
472 CONF_S
*ctmpa
= NULL
, *ctmpb
= NULL
;
474 OtherMenu what_keymenu
= FirstMenu
;
475 void (*prev_redrawer
)(void);
477 dprint((7, "conf_scroll_screen()\n"));
479 if(BODY_LINES(ps
) < 1){
480 q_status_message(SM_ORDER
| SM_DING
, 3, 3, _("Screen too small"));
484 if(screen
&& screen
->ro_warning
)
485 q_status_message1(SM_ORDER
, 1, 3,
486 /* TRANSLATORS: "Config file not changeable," is what replaces the %s */
487 _("%s can't change options or settings"),
488 ps_global
->restricted
? "Alpine demo"
489 : _("Config file not changeable,"));
491 screen
->current
= start_line
;
492 if(start_line
&& start_line
->flags
& CF_CHANGES
)
496 ps
->mangled_screen
= 1;
497 ps
->redrawer
= option_screen_redrawer
;
500 ps
->user_says_cancel
= 0;
505 ps
->mangled_body
= 1;
509 if(ps
->mangled_screen
){
510 ps
->mangled_header
= 1;
511 ps
->mangled_footer
= 1;
512 ps
->mangled_body
= 1;
513 ps
->mangled_screen
= 0;
516 /*----------- Check for new mail -----------*/
517 if(new_mail(0, NM_TIMING(ch
), NM_STATUS_MSG
| NM_DEFER_SORT
) >= 0)
518 ps
->mangled_header
= 1;
520 if(ps
->mangled_header
){
521 set_titlebar(title
, ps
->mail_stream
,
523 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
524 ps
->mangled_header
= 0;
527 update_option_screen(ps
, screen
, &cursor_pos
);
529 if(F_OFF(F_SHOW_CURSOR
, ps
)){
530 cursor_pos
.row
= ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
);
534 /*---- This displays new mail notification, or errors ---*/
537 mark_status_unknown();
543 mark_status_unknown();
546 if(ps
->mangled_footer
|| km
!= screen
->current
->keymenu
){
551 ps
->mangled_footer
= 0;
552 km
= screen
->current
->keymenu
;
555 (F_OFF(F_ARROW_NAV
, ps_global
) ||
556 F_ON(F_RELAXED_ARROW_NAV
, ps_global
))){
557 menu_clear_binding(km
, KEY_LEFT
);
558 menu_clear_binding(km
, KEY_RIGHT
);
559 menu_clear_binding(km
, KEY_UP
);
560 menu_clear_binding(km
, KEY_DOWN
);
561 menu_add_binding(km
, KEY_UP
, MC_CHARUP
);
562 menu_add_binding(km
, KEY_DOWN
, MC_CHARDOWN
);
563 menu_add_binding(km
, KEY_LEFT
, MC_PREVITEM
);
564 menu_add_binding(km
, ctrl('B'), MC_PREVITEM
);
565 menu_add_binding(km
, KEY_RIGHT
, MC_NEXTITEM
);
566 menu_add_binding(km
, ctrl('F'), MC_NEXTITEM
);
569 menu_clear_binding(km
, KEY_LEFT
);
570 menu_clear_binding(km
, KEY_RIGHT
);
571 menu_clear_binding(km
, KEY_UP
);
572 menu_clear_binding(km
, KEY_DOWN
);
575 * Fix up arrow nav mode if necessary...
577 if(F_ON(F_ARROW_NAV
, ps_global
)){
580 if((cmd
= menu_clear_binding(km
, '<')) != MC_UNKNOWN
){
581 menu_add_binding(km
, '<', cmd
);
582 menu_add_binding(km
, KEY_LEFT
, cmd
);
585 if((cmd
= menu_clear_binding(km
, '>')) != MC_UNKNOWN
){
586 menu_add_binding(km
, '>', cmd
);
587 menu_add_binding(km
, KEY_RIGHT
, cmd
);
590 if((cmd
= menu_clear_binding(km
, 'p')) != MC_UNKNOWN
){
591 menu_add_binding(km
, 'p', cmd
);
592 menu_add_binding(km
, KEY_UP
, cmd
);
595 if((cmd
= menu_clear_binding(km
, 'n')) != MC_UNKNOWN
){
596 menu_add_binding(km
, 'n', cmd
);
597 menu_add_binding(km
, KEY_DOWN
, cmd
);
607 draw_keymenu(km
, bitmap
, ps
->ttyo
->screen_cols
,
608 1-FOOTER_ROWS(ps
), 0, what_keymenu
);
609 what_keymenu
= SameMenu
;
613 mark_keymenu_dirty();
617 MoveCursor(cursor_pos
.row
, cursor_pos
.col
);
619 mouse_in_content(KEY_MOUSE
, -1, -1, 0, 0); /* prime the handler */
620 register_mfunc(mouse_in_content
, HEADER_ROWS(ps_global
), 0,
621 ps_global
->ttyo
->screen_rows
-(FOOTER_ROWS(ps_global
)+1),
622 ps_global
->ttyo
->screen_cols
);
625 mswin_setscrollcallback(config_scroll_callback
);
627 /*------ Read the command from the keyboard ----*/
628 ch
= READ_COMMAND(&utf8str
);
630 clear_mfunc(mouse_in_content
);
633 mswin_setscrollcallback(NULL
);
636 cmd
= menu_command(ch
, km
);
654 what_keymenu
= NextMenu
;
655 ps
->mangled_footer
= 1;
658 case MC_HELP
: /* help! */
659 if(FOOTER_ROWS(ps
) == 1 && km_popped
== 0){
661 ps
->mangled_footer
= 1;
665 if(screen
->current
->help
!= NO_HELP
){
666 prev_redrawer
= ps_global
->redrawer
;
667 helper(screen
->current
->help
,
668 (screen
->current
->help_title
)
669 ? screen
->current
->help_title
670 : CONFIG_SCREEN_HELP_TITLE
,
672 ps_global
->redrawer
= prev_redrawer
;
673 ps
->mangled_screen
= 1;
676 q_status_message(SM_ORDER
,0,3,_("No help yet."));
681 case MC_NEXTITEM
: /* next list element */
684 if(screen
->current
->flags
& CF_DOUBLEVAR
){
685 /* if going from col1 to col2, it's simple */
686 if(!(screen
->current
->flags
& CF_VAR2
) && cmd
== MC_NEXTITEM
){
687 screen
->current
->flags
|= CF_VAR2
;
691 /* otherwise we fall through to normal next */
692 stay_in_col
= (screen
->current
->flags
& CF_VAR2
&&
694 screen
->current
->flags
&= ~CF_VAR2
;
697 for(ctmpa
= next_confline(screen
->current
), i
= 1;
698 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
699 ctmpa
= next_confline(ctmpa
), i
++)
703 screen
->current
= ctmpa
;
704 if(screen
->current
->flags
& CF_DOUBLEVAR
&& stay_in_col
)
705 screen
->current
->flags
|= CF_VAR2
;
707 if(cmd
== MC_CHARDOWN
){
708 for(ctmpa
= screen
->top_line
,
709 j
= BODY_LINES(ps
) - 1 - HS_MARGIN(ps
);
710 j
> 0 && ctmpa
&& ctmpa
!= screen
->current
;
711 ctmpa
= next_confline(ctmpa
), j
--)
716 ctmpa
&& ctmpa
!= screen
->current
;
717 ctmpa
= next_confline(ctmpa
), i
++)
727 * Scroll screen a bit so we show the non-selectable
728 * lines at the bottom.
731 /* set ctmpa to the bottom line on the screen */
732 for(ctmpa
= screen
->top_line
, j
= BODY_LINES(ps
) - 1;
734 ctmpa
= next_confline(ctmpa
), j
--)
739 for(ctmpa
= next_confline(ctmpa
);
741 (ctmpa
->flags
& (CF_NOSELECT
| CF_B_LINE
)) ==
743 ctmpa
= next_confline(ctmpa
), i
++)
750 q_status_message(SM_ORDER
,0,1, _("Already at end of screen"));
755 case MC_PREVITEM
: /* prev list element */
758 if(screen
->current
->flags
& CF_DOUBLEVAR
){
759 if(screen
->current
->flags
& CF_VAR2
&& cmd
== MC_PREVITEM
){
760 screen
->current
->flags
&= ~CF_VAR2
;
764 /* otherwise we fall through to normal prev */
765 stay_in_col
= (!(screen
->current
->flags
& CF_VAR2
) &&
767 screen
->current
->flags
&= ~CF_VAR2
;
769 else if(cmd
== MC_CHARUP
)
772 ctmpa
= screen
->current
;
775 if(ctmpa
== config_top_scroll(ps
, screen
->top_line
))
779 while((ctmpa
= prev_confline(ctmpa
))
780 && (ctmpa
->flags
&CF_NOSELECT
));
783 screen
->current
= ctmpa
;
784 if(screen
->current
->flags
& CF_DOUBLEVAR
&& !stay_in_col
)
785 screen
->current
->flags
|= CF_VAR2
;
787 if((cmd
== MC_CHARUP
) && i
)
788 config_scroll_down(i
);
791 q_status_message(SM_ORDER
, 0, 1,
792 _("Already at start of screen"));
796 case MC_PAGEDN
: /* page forward */
797 screen
->current
->flags
&= ~CF_VAR2
;
798 for(ctmpa
= screen
->top_line
, i
= BODY_LINES(ps
);
800 ctmpb
= ctmpa
, ctmpa
= next_confline(ctmpa
), i
--)
803 if(ctmpa
){ /* first line off bottom of screen */
805 ps
->mangled_body
= 1;
806 /* find first selectable line on next page */
807 for(screen
->top_line
= ctmpa
;
808 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
809 ctmpa
= next_confline(ctmpa
))
813 * No selectable lines on next page. Slide up to first
817 for(ctmpa
= prev_confline(ctmpb
);
818 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
819 ctmpa
= prev_confline(ctmpa
))
823 screen
->top_line
= ctmpa
;
826 else{ /* on last screen */
827 /* just move current down to last entry on screen */
828 if(ctmpb
){ /* last line of data */
829 for(ctmpa
= ctmpb
, i
= BODY_LINES(ps
);
830 i
> 0 && ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
831 ctmpa
= prev_confline(ctmpa
), i
--)
834 if(ctmpa
== screen
->current
){
835 q_status_message(SM_ORDER
,0,1,
836 _("Already at end of screen"));
840 ps
->mangled_body
= 1;
845 screen
->current
= ctmpa
;
849 case MC_PAGEUP
: /* page backward */
850 ps
->mangled_body
= 1;
851 screen
->current
->flags
&= ~CF_VAR2
;
852 if(!(ctmpa
=prev_confline(screen
->top_line
)))
853 ctmpa
= screen
->current
;
855 for(i
= BODY_LINES(ps
) - 1;
856 i
> 0 && prev_confline(ctmpa
);
857 i
--, ctmpa
= prev_confline(ctmpa
))
860 for(screen
->top_line
= ctmpa
;
861 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
862 ctmpa
= next_confline(ctmpa
))
866 if(ctmpa
== screen
->current
){
868 * We get to here if there was nothing selectable on
869 * the previous page. There still may be something
870 * selectable further back than the previous page,
873 for(ctmpa
= prev_confline(screen
->top_line
);
874 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
875 ctmpa
= prev_confline(ctmpa
))
879 ctmpa
= screen
->current
;
880 q_status_message(SM_ORDER
, 0, 1,
881 _("Already at start of screen"));
885 screen
->current
= ctmpa
;
895 mouse_get_last (NULL
, &mp
);
896 mp
.row
-= HEADER_ROWS(ps
);
897 ctmpa
= screen
->top_line
;
899 while (mp
.row
&& ctmpa
!= NULL
) {
904 if (ctmpa
!= NULL
&& !(ctmpa
->flags
& CF_NOSELECT
)){
905 if(screen
->current
->flags
& CF_DOUBLEVAR
)
906 screen
->current
->flags
&= ~CF_VAR2
;
908 screen
->current
= ctmpa
;
910 if(screen
->current
->flags
& CF_DOUBLEVAR
&&
911 mp
.col
>= screen
->current
->val2offset
)
912 screen
->current
->flags
|= CF_VAR2
;
914 update_option_screen(ps
, screen
, &cursor_pos
);
916 if(mp
.button
== M_BUTTON_LEFT
&& mp
.doubleclick
){
918 if(screen
->current
->tool
){
922 flags
= screen
->current
->flags
;
923 flags
|= (changes
? CF_CHANGES
: 0);
925 default_cmd
= menu_command(ctrl('M'), km
);
926 switch(i
=(*screen
->current
->tool
)(ps
, default_cmd
,
927 &screen
->current
, flags
)){
954 else if(mp
.button
== M_BUTTON_RIGHT
) {
955 MPopup other_popup
[20];
957 struct key_menu
*sckm
= screen
->current
->keymenu
; /* only for popup */
959 if((cmd
= menu_command(ctrl('M'), sckm
)) != MC_UNKNOWN
){
960 i
= menu_binding_index(sckm
, cmd
);
961 other_popup
[++n
].type
= tQueue
;
962 other_popup
[n
].label
.style
= lNormal
;
963 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
964 other_popup
[n
].data
.val
= ctrl('M');
966 else if((cmd
= menu_command('>', sckm
)) != MC_UNKNOWN
){
967 i
= menu_binding_index(sckm
, cmd
);
968 other_popup
[++n
].type
= tQueue
;
969 other_popup
[n
].label
.style
= lNormal
;
970 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
971 other_popup
[n
].data
.val
= '>';
974 if(((i
= menu_binding_index(sckm
, MC_RGB1
)) >= 0) ||
975 ((i
= menu_binding_index(sckm
, MC_RGB2
)) >= 0)){
976 other_popup
[++n
].type
= tQueue
;
977 other_popup
[n
].label
.style
= lNormal
;
978 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
979 other_popup
[n
].data
.val
=
980 sckm
->keys
[i
].bind
.ch
[0];
983 if((cmd
= menu_command('<', sckm
)) != MC_UNKNOWN
){
984 i
= menu_binding_index(sckm
, cmd
);
985 other_popup
[++n
].type
= tQueue
;
986 other_popup
[n
].label
.style
= lNormal
;
987 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
988 other_popup
[n
].data
.val
= '<';
990 else if((i
= menu_binding_index(sckm
, MC_EXIT
)) >= 0){
991 other_popup
[++n
].type
= tQueue
;
992 other_popup
[n
].label
.style
= lNormal
;
993 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
994 other_popup
[n
].data
.val
=
995 sckm
->keys
[i
].bind
.ch
[0];
998 if((i
= menu_binding_index(sckm
, MC_HELP
)) >= 0){
1000 other_popup
[++n
].type
= tSeparator
;
1002 other_popup
[++n
].type
= tQueue
;
1003 other_popup
[n
].label
.style
= lNormal
;
1004 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1005 other_popup
[n
].data
.val
= sckm
->keys
[i
].bind
.ch
[0];
1009 other_popup
[++n
].type
= tTail
;
1010 mswin_popup(other_popup
);
1014 else if(mp
.button
== M_BUTTON_RIGHT
) {
1015 MPopup other_popup
[20];
1017 struct key_menu
*sckm
= screen
->current
->keymenu
; /* only for popup */
1019 if((cmd
= menu_command('<', sckm
)) != MC_UNKNOWN
){
1020 i
= menu_binding_index(sckm
, cmd
);
1021 other_popup
[++n
].type
= tQueue
;
1022 other_popup
[n
].label
.style
= lNormal
;
1023 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1024 other_popup
[n
].data
.val
= '<';
1026 else if((i
= menu_binding_index(sckm
, MC_EXIT
)) >= 0){
1027 other_popup
[++n
].type
= tQueue
;
1028 other_popup
[n
].label
.style
= lNormal
;
1029 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1030 other_popup
[n
].data
.val
= sckm
->keys
[i
].bind
.ch
[0];
1033 other_popup
[++n
].type
= tTail
;
1036 mswin_popup(other_popup
);
1043 case MC_PRINTTXT
: /* print screen */
1044 print_option_screen(screen
, pdesc
? pdesc
: "");
1047 case MC_WHEREIS
: /* whereis */
1048 /*--- get string ---*/
1050 #define FOUND_IT 0x01
1051 #define FOUND_CURRENT 0x02
1052 #define FOUND_WRAPPED 0x04
1053 #define FOUND_NOSELECT 0x08
1054 #define FOUND_ABOVE 0x10
1055 char *result
= NULL
, buf
[64];
1057 static HISTORY_S
*history
= NULL
;
1059 static ESCKEY_S ekey
[] = {
1061 /* TRANSLATORS: go to Top of screen */
1062 {ctrl('Y'), 10, "^Y", N_("Top")},
1063 {ctrl('V'), 11, "^V", N_("Bottom")},
1064 {KEY_UP
, 30, "", ""},
1065 {KEY_DOWN
, 31, "", ""},
1066 {-1, 0, NULL
, NULL
}};
1067 #define KU_WI (3) /* index of KEY_UP */
1069 init_hist(&history
, HISTSIZE
);
1071 if((p
= get_prev_hist(history
, "", 0, NULL
)) != NULL
){
1072 strncpy(last
, p
, sizeof(last
));
1073 last
[sizeof(last
)-1] = '\0';
1076 ps
->mangled_footer
= 1;
1078 snprintf(tmp
, sizeof(tmp
), "Word to find %s%s%s: ",
1079 (last
[0]) ? "[" : "",
1080 (last
[0]) ? last
: "",
1081 (last
[0]) ? "]" : "");
1082 tmp
[sizeof(tmp
)-1] = '\0';
1085 int flags
= OE_APPEND_CURRENT
;
1088 * 2 is really 1 because there will be one real entry and
1089 * one entry of "" because of the get_prev_hist above.
1091 if(items_in_hist(history
) > 2){
1092 ekey
[KU_WI
].name
= HISTORY_UP_KEYNAME
;
1093 ekey
[KU_WI
].label
= HISTORY_KEYLABEL
;
1094 ekey
[KU_WI
+1].name
= HISTORY_DOWN_KEYNAME
;
1095 ekey
[KU_WI
+1].label
= HISTORY_KEYLABEL
;
1098 ekey
[KU_WI
].name
= "";
1099 ekey
[KU_WI
].label
= "";
1100 ekey
[KU_WI
+1].name
= "";
1101 ekey
[KU_WI
+1].label
= "";
1104 rc
= optionally_enter(buf
,-FOOTER_ROWS(ps
),0,sizeof(buf
),
1105 tmp
,ekey
,help
,&flags
);
1107 help
= help
== NO_HELP
? h_config_whereis
: NO_HELP
;
1109 if((p
= get_prev_hist(history
, buf
, 0, NULL
)) != NULL
){
1110 strncpy(buf
, p
, sizeof(buf
));
1111 buf
[sizeof(buf
)-1] = '\0';
1119 if((p
= get_next_hist(history
, buf
, 0, NULL
)) != NULL
){
1120 strncpy(buf
, p
, sizeof(buf
));
1121 buf
[sizeof(buf
)-1] = '\0';
1128 else if(rc
== 0 || rc
== 1 || rc
== 10 || rc
== 11 || !buf
[0]){
1129 if(rc
== 0 && !buf
[0] && last
[0])
1130 strncpy(buf
, last
, 64);
1136 screen
->current
->flags
&= ~CF_VAR2
;
1137 if(rc
== 0 && buf
[0]){
1138 CONF_S
*started_here
;
1140 save_hist(history
, buf
, 0, NULL
);
1143 ctmpa
= screen
->current
;
1145 * Skip over the unselectable lines of this "item"
1146 * before starting search so that we don't find the
1149 while((ctmpb
= next_confline(ctmpa
)) &&
1150 (ctmpb
->flags
& CF_NOSELECT
) &&
1151 !(ctmpb
->flags
& CF_STARTITEM
))
1154 started_here
= next_confline(ctmpa
);
1155 while((ctmpa
= next_confline(ctmpa
)) != NULL
)
1156 if(srchstr(ctmpa
->varname
, buf
)
1157 || srchstr(ctmpa
->value
, buf
)){
1161 * If this line is not selectable, back up to the
1162 * previous selectable line, but not past the
1163 * start of this "entry".
1165 if(ctmpa
->flags
& CF_NOSELECT
)
1166 found
|= FOUND_NOSELECT
;
1168 while((ctmpa
->flags
& CF_NOSELECT
) &&
1169 !(ctmpa
->flags
& CF_STARTITEM
) &&
1170 (ctmpb
= prev_confline(ctmpa
)))
1174 * If that isn't selectable, better search forward
1175 * for something that is.
1177 while((ctmpa
->flags
& CF_NOSELECT
) &&
1178 (ctmpb
= next_confline(ctmpa
))){
1180 found
|= FOUND_ABOVE
;
1184 * If that still isn't selectable, better search
1185 * backwards for something that is.
1187 while((ctmpa
->flags
& CF_NOSELECT
) &&
1188 (ctmpb
= prev_confline(ctmpa
))){
1190 found
&= ~FOUND_ABOVE
;
1197 found
= FOUND_WRAPPED
;
1198 ctmpa
= first_confline(screen
->current
);
1200 while(ctmpa
!= started_here
)
1201 if(srchstr(ctmpa
->varname
, buf
)
1202 || srchstr(ctmpa
->value
, buf
)){
1205 if(ctmpa
->flags
& CF_NOSELECT
)
1206 found
|= FOUND_NOSELECT
;
1208 while((ctmpa
->flags
& CF_NOSELECT
) &&
1209 !(ctmpa
->flags
& CF_STARTITEM
) &&
1210 (ctmpb
= prev_confline(ctmpa
)))
1213 while((ctmpa
->flags
& CF_NOSELECT
) &&
1214 (ctmpb
= next_confline(ctmpa
))){
1216 found
|= FOUND_ABOVE
;
1219 if(ctmpa
== screen
->current
)
1220 found
|= FOUND_CURRENT
;
1225 ctmpa
= next_confline(ctmpa
);
1229 screen
->current
= first_confline(screen
->current
);
1230 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1231 for(ctmpa
= next_confline(screen
->current
);
1232 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1233 ctmpa
= next_confline(ctmpa
))
1237 screen
->current
= ctmpa
;
1240 /* TRANSLATORS: Searched to ... is the result of the search, searched
1241 to top means the search went past the bottom of the screen and
1242 wrapped back around to the top. */
1243 result
= _("Searched to top");
1246 screen
->current
= last_confline(screen
->current
);
1247 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1248 for(ctmpa
= prev_confline(screen
->current
);
1249 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1250 ctmpa
= prev_confline(ctmpa
))
1254 screen
->current
= ctmpa
;
1257 result
= _("Searched to bottom");
1260 result
= _("WhereIs cancelled");
1262 if((found
& FOUND_IT
) && ctmpa
){
1263 strncpy(last
, buf
, 64);
1265 (found
& FOUND_CURRENT
&& found
& FOUND_WRAPPED
&& found
& FOUND_NOSELECT
)
1266 ? _("Current item contains the only match")
1267 : (found
& FOUND_CURRENT
&& found
& FOUND_WRAPPED
)
1268 ? _("Current line contains the only match")
1269 : (found
& FOUND_NOSELECT
&& found
& FOUND_WRAPPED
)
1270 ? ((found
& FOUND_ABOVE
)
1271 ? _("Search wrapped: word found in text above current line")
1272 : _("Search wrapped: word found in text below current line"))
1273 : (found
& FOUND_WRAPPED
)
1274 ? _("Search wrapped to beginning: word found")
1275 : (found
& FOUND_NOSELECT
)
1276 ? ((found
& FOUND_ABOVE
)
1277 ? _("Word found in text above current line")
1278 : _("Word found in text below current line"))
1280 screen
->current
= ctmpa
;
1283 q_status_message(SM_ORDER
,0,3,result
? result
: _("Word not found"));
1289 screen
->current
= first_confline(screen
->current
);
1290 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1291 for(ctmpa
= next_confline(screen
->current
);
1292 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1293 ctmpa
= next_confline(ctmpa
))
1297 screen
->current
= ctmpa
;
1300 q_status_message(SM_ORDER
,0,3, _("Moved to top"));
1304 screen
->current
= last_confline(screen
->current
);
1305 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1306 for(ctmpa
= prev_confline(screen
->current
);
1307 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1308 ctmpa
= prev_confline(ctmpa
))
1312 screen
->current
= ctmpa
;
1315 q_status_message(SM_ORDER
,0,3, _("Moved to bottom"));
1318 case MC_XSHELP
: /* help! */
1319 if(FOOTER_ROWS(ps
) == 1 && km_popped
== 0){
1321 ps
->mangled_footer
= 1;
1325 prev_redrawer
= ps_global
->redrawer
;
1326 helper(h_xoauth2_config_screen
, "XOAUTH2 CONFIGURATION SCREEN", HLPD_SIMPLE
);
1327 ps_global
->redrawer
= prev_redrawer
;
1328 ps
->mangled_screen
= 1;
1331 case MC_XSDELETE
: /* Send caller to delete XOAUTH2 info */
1332 case MC_XSADD
: /* Send caller to add XOAUTH2 info */
1334 *pos
= get_confline_number(screen
->current
);
1336 retval
= cmd
== MC_XSADD
? 4 : 5;
1340 case MC_REPAINT
: /* redraw the display */
1343 ps
->mangled_screen
= 1;
1345 *pos
= get_confline_number(screen
->current
);
1352 if(screen
&& screen
->ro_warning
){
1358 q_status_message1(SM_ORDER
|SM_DING
, 1, 3,
1359 _("%s can't change options or settings"),
1360 ps_global
->restricted
? "Alpine demo"
1361 : _("Config file not changeable,"));
1363 else if(screen
->current
->tool
){
1366 flags
= screen
->current
->flags
;
1367 flags
|= (changes
? CF_CHANGES
: 0);
1369 switch(i
=(*screen
->current
->tool
)(ps
, cmd
,
1370 &screen
->current
, flags
)){
1372 q_status_message2(SM_ORDER
, 0, 2,
1373 /* TRANSLATORS: Command <command letter> not defined here.
1374 Leave the trailing %s which might be a parenthetical
1376 _("Command \"%s\" not defined here.%s"),
1378 F_ON(F_BLANK_KEYMENU
,ps
) ? "" : " See key menu below.");
1408 bogus_utf8_command(utf8str
, "?");
1411 case MC_NONE
: /* simple timeout */
1416 screen
->current
= first_confline(screen
->current
);
1417 free_conflines(&screen
->current
);
1426 config_scroll_up(long int n
)
1428 CONF_S
*ctmp
= opt_screen
->top_line
;
1432 config_scroll_down(-n
);
1434 for(; n
>0 && ctmp
->next
; n
--){
1435 ctmp
= next_confline(ctmp
);
1436 if(prev_confline(ctmp
) == opt_screen
->current
)
1440 opt_screen
->top_line
= ctmp
;
1441 ps_global
->mangled_body
= 1;
1443 for(ctmp
= opt_screen
->top_line
;
1444 ctmp
&& (ctmp
->flags
& CF_NOSELECT
);
1445 ctmp
= next_confline(ctmp
))
1449 opt_screen
->current
= opt_screen
->prev
= ctmp
;
1451 while(opt_screen
->top_line
->flags
& CF_NOSELECT
)
1452 opt_screen
->top_line
= prev_confline(opt_screen
->top_line
);
1453 opt_screen
->current
= opt_screen
->prev
= opt_screen
->top_line
;
1461 * config_scroll_down -
1464 config_scroll_down(long int n
)
1466 CONF_S
*ctmp
= opt_screen
->top_line
, *last_sel
= NULL
;
1470 config_scroll_up(-n
);
1472 for(; n
>0 && ctmp
->prev
; n
--)
1473 ctmp
= prev_confline(ctmp
);
1475 opt_screen
->top_line
= ctmp
;
1476 ps_global
->mangled_body
= 1;
1477 for(ctmp
= opt_screen
->top_line
, i
= BODY_LINES(ps_global
);
1478 i
> 0 && ctmp
&& ctmp
!= opt_screen
->current
;
1479 ctmp
= next_confline(ctmp
), i
--)
1480 if(!(ctmp
->flags
& CF_NOSELECT
))
1484 opt_screen
->current
= opt_screen
->prev
= last_sel
;
1490 * config_scroll_to_pos -
1493 config_scroll_to_pos(long int n
)
1497 for(ctmp
= first_confline(opt_screen
->current
);
1498 n
&& ctmp
&& ctmp
!= opt_screen
->top_line
;
1499 ctmp
= next_confline(ctmp
), n
--)
1503 while(ctmp
&& ctmp
!= opt_screen
->top_line
)
1504 if((ctmp
= next_confline(ctmp
)) != NULL
)
1507 config_scroll_up(n
);
1512 * config_top_scroll - return pointer to the
1515 config_top_scroll(struct pine
*ps
, CONF_S
*topline
)
1520 for(ctmp
= topline
, i
= HS_MARGIN(ps
);
1522 ctmp
= next_confline(ctmp
), i
--)
1525 return(ctmp
? ctmp
: topline
);
1530 text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
1532 return(text_toolit(ps
, cmd
, cl
, flags
, 0));
1537 * simple text variable handler
1539 * note, things get a little involved due to the
1540 * screen struct <--> variable mapping. (but, once its
1541 * running it shouldn't need changing ;).
1543 * look_for_backslash == 1 means that backslash is an escape character.
1544 * In particular, \, can be used to put a literal comma
1545 * into a value. The value will still have the backslash
1546 * in it, but the comma after the backslash won't be treated
1547 * as an item separator.
1549 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
1550 * returns what conf_exit_cmd returns for exit command.
1553 text_toolit(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
, int look_for_backslash
)
1555 char prompt
[81], *sval
, *tmp
, *swap_val
, **newval
= NULL
;
1556 char *pval
= NULL
, **apval
= NULL
, **lval
= NULL
, ***alval
= NULL
;
1557 char *olddefval
= NULL
;
1558 int rv
= 0, skip_to_next
= 0, after
= 0, i
= 4, j
, k
;
1559 int lowrange
= 0, hirange
= 0, incr
= 0, oeflags
, oebufsize
;
1560 int numval
, repeat_key
= 0;
1561 int curindex
, previndex
, nextindex
, deefault
;
1565 if((*cl
)->var
->is_list
){
1566 lval
= LVAL((*cl
)->var
, ew
);
1567 alval
= ALVAL((*cl
)->var
, ew
);
1570 pval
= PVAL((*cl
)->var
, ew
);
1571 apval
= APVAL((*cl
)->var
, ew
);
1574 oebufsize
= 6*MAXPATH
;
1575 sval
= (char *) fs_get(oebufsize
*sizeof(char));
1578 if(flags
&CF_NUMBER
){ /* only happens if !is_list */
1580 if((*cl
)->var
== &ps
->vars
[V_FILLCOL
]){
1582 hirange
= MAX_FILLCOL
;
1584 else if((*cl
)->var
== &ps
->vars
[V_OVERLAP
]
1585 || (*cl
)->var
== &ps
->vars
[V_MARGIN
]){
1589 else if((*cl
)->var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
1590 lowrange
= -(Q_SUPP_LIMIT
-1);
1593 else if((*cl
)->var
== &ps
->vars
[V_MAXREMSTREAM
]){
1597 else if((*cl
)->var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
1601 else if((*cl
)->var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
1605 else if((*cl
)->var
== &ps
->vars
[V_MAILCHECK
] ||
1606 (*cl
)->var
== &ps
->vars
[V_INCCHECKINTERVAL
] ||
1607 (*cl
)->var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
] ||
1608 (*cl
)->var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
1613 else if((*cl
)->var
== &ps
->vars
[V_DEADLETS
]){
1617 else if((*cl
)->var
== &ps
->vars
[V_NMW_WIDTH
]){
1619 hirange
= MAX_SCREEN_COLS
;
1621 else if((*cl
)->var
== score_act_global_ptr
){
1625 else if((*cl
)->var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
1626 (*cl
)->var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
1627 (*cl
)->var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
1631 else if((*cl
)->var
== &ps
->vars
[V_QUITQUERYTIMEO
]){
1635 else if((*cl
)->var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
1636 (*cl
)->var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
1637 (*cl
)->var
== &ps
->vars
[V_SSHOPENTIMEO
] ||
1638 (*cl
)->var
== &ps
->vars
[V_USERINPUTTIMEO
]){
1642 else if((*cl
)->var
== &ps
->vars
[V_INCCHECKTIMEO
]){
1646 else if((*cl
)->var
== &ps
->vars
[V_MAILDROPCHECK
]){
1651 else if((*cl
)->var
== &ps
->vars
[V_NNTPRANGE
]){
1656 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
]){
1660 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
]){
1664 else if((*cl
)->var
== cat_lim_global_ptr
){
1677 ekey
[1].ch
= ctrl('P');
1678 ekey
[1].rval
= ctrl('P');
1679 ekey
[1].name
= "^P";
1680 ekey
[1].label
= N_("Decrease");
1681 ekey
[2].ch
= ctrl('N');
1682 ekey
[2].rval
= ctrl('N');
1683 ekey
[2].name
= "^N";
1684 ekey
[2].label
= N_("Increase");
1685 ekey
[3].ch
= KEY_DOWN
;
1686 ekey
[3].rval
= ctrl('P');
1689 ekey
[4].ch
= KEY_UP
;
1690 ekey
[4].rval
= ctrl('N');
1697 case MC_ADD
: /* add to list */
1698 if(fixed_var((*cl
)->var
, "add to", NULL
)){
1701 else if(!(*cl
)->var
->is_list
&& pval
){
1702 q_status_message(SM_ORDER
, 3, 3,
1703 _("Only single value allowed. Use \"Change\"."));
1709 if((*cl
)->var
->is_list
1710 && lval
&& lval
[0] && lval
[0][0]
1713 /* regular add to an existing list */
1715 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1716 tmpval
[sizeof(tmpval
)-1] = '\0';
1717 removing_trailing_white_space(tmpval
);
1719 /* 33 is the number of chars other than the value */
1720 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1721 k
= MIN(18, MAX(maxwidth
-33,0));
1722 if(utf8_width(tmpval
) > k
&& k
>= 3){
1723 (void) utf8_truncate(tmpval
, k
-3);
1724 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1725 tmpval
[sizeof(tmpval
)-1] = '\0';
1728 utf8_snprintf(prompt
, sizeof(prompt
),
1729 _("Enter text to insert before \"%.*w\": "), k
, tmpval
);
1730 prompt
[sizeof(prompt
)-1] = '\0';
1732 else if((*cl
)->var
->is_list
1734 && (*cl
)->var
->current_val
.l
){
1735 /* Add to list which doesn't exist, but default does exist */
1739 ekey
[0].label
= N_("Replace");
1743 ekey
[1].label
= N_("Add To");
1745 strncpy(prompt
, _("Replace or Add To default value ? "), sizeof(prompt
));
1746 prompt
[sizeof(prompt
)-1] = '\0';
1747 switch(radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, 'a', 'x',
1748 h_config_replace_add
, RB_NORM
)){
1751 for(j
= 0; (*cl
)->var
->current_val
.l
[j
]; j
++){
1752 sstrncpy(&p
, (*cl
)->var
->current_val
.l
[j
], oebufsize
-(p
-sval
));
1753 if(oebufsize
-(p
-sval
) > 2){
1758 if(oebufsize
-(p
-sval
) > 0)
1762 sval
[oebufsize
-1] = '\0';
1765 if(flags
& CF_NUMBER
)
1766 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1768 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1775 strncpy(sval
, olddefval
, oebufsize
);
1776 sval
[oebufsize
-1] = '\0';
1779 if(flags
& CF_NUMBER
)
1780 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric replacement text : "));
1782 snprintf(prompt
, sizeof(prompt
), _("Enter the replacement text : "));
1788 cmd_cancelled("Add");
1793 if(flags
& CF_NUMBER
)
1794 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1796 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1799 prompt
[sizeof(prompt
)-1] = '\0';
1801 ps
->mangled_footer
= 1;
1808 if((*cl
)->var
->is_list
1809 && lval
&& lval
[0] && lval
[0][0]
1811 ekey
[0].ch
= ctrl('W');
1813 ekey
[0].name
= "^W";
1814 /* TRANSLATORS: Insert new item before current item */
1815 ekey
[0].label
= after
? N_("InsertBefore") : N_("InsertAfter");
1818 else if(!(flags
&CF_NUMBER
))
1821 oeflags
= OE_APPEND_CURRENT
;
1822 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
1824 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
1828 if((*cl
)->var
->is_list
)
1829 ps
->mangled_body
= 1;
1831 ps
->mangled_footer
= 1;
1833 removing_leading_and_trailing_white_space(sval
);
1835 * Coerce "" and <Empty Value> to empty string input.
1836 * Catch <No Value Set> as a substitute for deleting.
1838 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
1839 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
1841 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
1843 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
1845 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
1848 if((*cl
)->var
->is_list
){
1854 for(tmp
= sval
; *tmp
; tmp
++)
1856 i
++; /* conservative count of ,'s */
1859 ltmp
= (char **)fs_get(2 * sizeof(char *));
1860 ltmp
[0] = cpystr(sval
);
1864 ltmp
= parse_list(sval
, i
+ 1,
1866 ? PL_COMMAQUOTE
: 0,
1870 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
1875 q_status_message1(SM_ORDER
, 0, 3,
1876 _("Can't add %s to list"), _(empty_val
));
1877 rv
= ps
->mangled_body
= 0;
1880 fs_give((void **)<mp
);
1883 q_status_message1(SM_ORDER
, 0, 3,
1884 _("Can't add %s to list"), _(empty_val
));
1888 if(flags
&CF_NUMBER
&& sval
[0]
1889 && !(isdigit((unsigned char)sval
[0])
1890 || sval
[0] == '-' || sval
[0] == '+')){
1891 q_status_message(SM_ORDER
,3,3,
1892 _("Entry must be numeric"));
1893 i
= 3; /* to keep loop going */
1898 fs_give((void **)apval
);
1900 if(!(olddefval
&& !strcmp(sval
, olddefval
))
1901 || ((*cl
)->var
== &ps
->vars
[V_POST_CHAR_SET
])
1902 || want_to(_("Leave unset and use default "),
1903 'y', 'y', NO_HELP
, WT_FLUSH_IN
) == 'n')
1904 *apval
= cpystr(sval
);
1906 newval
= &(*cl
)->value
;
1910 cmd_cancelled("Add");
1913 help
= help
== NO_HELP
? h_config_add
: NO_HELP
;
1916 else if(i
== 4){ /* no redraw, yet */
1919 else if(i
== 5){ /* change from/to prepend to/from append */
1922 after
= after
? 0 : 1;
1923 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1924 tmpval
[sizeof(tmpval
)-1] = '\0';
1925 removing_trailing_white_space(tmpval
);
1926 /* 33 is the number of chars other than the value */
1927 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1928 k
= MIN(18, MAX(maxwidth
-33,0));
1929 if(utf8_width(tmpval
) > k
&& k
>= 3){
1930 (void) utf8_truncate(tmpval
, k
-3);
1931 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1932 tmpval
[sizeof(tmpval
)-1] = '\0';
1936 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert after \"%.*s\": "), k
, tmpval
);
1938 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert before \"%.*s\": "), k
, tmpval
);
1942 else if(i
== ctrl('P')){
1944 numval
= atoi(sval
);
1947 numval
= atoi(pval
);
1949 numval
= lowrange
+ 1;
1952 if(numval
== lowrange
){
1954 * Protect user from repeating arrow key that
1955 * causes message to appear over and over.
1957 if(++repeat_key
> 0){
1958 q_status_message1(SM_ORDER
,3,3,
1959 _("Minimum value is %s"), comatose(lowrange
));
1966 numval
= MAX(numval
- incr
, lowrange
);
1967 snprintf(sval
, oebufsize
, "%d", numval
);
1968 sval
[oebufsize
-1] = '\0';
1971 else if(i
== ctrl('N')){
1973 numval
= atoi(sval
);
1976 numval
= atoi(pval
);
1978 numval
= lowrange
+ 1;
1981 if(numval
== hirange
){
1982 if(++repeat_key
> 0){
1983 q_status_message1(SM_ORDER
,3,3,
1984 _("Maximum value is %s"), comatose(hirange
));
1991 numval
= MIN(numval
+ incr
, hirange
);
1992 snprintf(sval
, oebufsize
, "%d", numval
);
1993 sval
[oebufsize
-1] = '\0';
2003 case MC_DELETE
: /* delete */
2005 if(!(*cl
)->var
->is_list
2007 && (*cl
)->var
->current_val
.p
){
2010 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
2011 pmt
[sizeof(pmt
)-1] = '\0';
2012 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2014 *apval
= cpystr(sval
);
2015 newval
= &(*cl
)->value
;
2016 rv
= ps
->mangled_footer
= 1;
2019 else if((*cl
)->var
->is_list
2021 && (*cl
)->var
->current_val
.l
){
2024 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
2025 pmt
[sizeof(pmt
)-1] = '\0';
2026 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2030 ltmp
= (char **)fs_get(2 * sizeof(char *));
2031 ltmp
[0] = cpystr(sval
);
2033 config_add_list(ps
, cl
, ltmp
, &newval
, 0);
2034 fs_give((void **)<mp
);
2035 rv
= ps
->mangled_body
= 1;
2038 else if(((*cl
)->var
->is_list
&& !lval
)
2039 || (!(*cl
)->var
->is_list
&& !pval
)){
2040 q_status_message(SM_ORDER
, 0, 3, _("No set value to delete"));
2043 if((*cl
)->var
->is_fixed
)
2044 snprintf(prompt
, sizeof(prompt
), _("Delete (unused) %s from %s "),
2046 ? (!*lval
[(*cl
)->varmem
])
2048 : lval
[(*cl
)->varmem
]
2056 snprintf(prompt
, sizeof(prompt
), _("Really delete %s%s from %s "),
2057 (*cl
)->var
->is_list
? "item " : "",
2059 ? int2string((*cl
)->varmem
+ 1)
2067 prompt
[sizeof(prompt
)-1] = '\0';
2070 ps
->mangled_footer
= 1;
2071 if(want_to(prompt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2073 if((*cl
)->var
->is_list
)
2074 ps
->mangled_body
= 1;
2076 ps
->mangled_footer
= 1;
2078 if((*cl
)->var
->is_list
){
2079 if(lval
[(*cl
)->varmem
])
2080 fs_give((void **)&lval
[(*cl
)->varmem
]);
2082 config_del_list_item(cl
, &newval
);
2086 fs_give((void **)apval
);
2088 newval
= &(*cl
)->value
;
2092 q_status_message(SM_ORDER
, 0, 3, _("Value not deleted"));
2097 case MC_EDIT
: /* edit/change list option */
2098 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2101 else if(((*cl
)->var
->is_list
2103 && (*cl
)->var
->current_val
.l
)
2105 (!(*cl
)->var
->is_list
2107 && (*cl
)->var
->current_val
.p
)){
2110 * In non-list case, offer default value for editing.
2112 if(!(*cl
)->var
->is_list
2113 && (*cl
)->var
!= &ps
->vars
[V_REPLY_INTRO
]
2114 && (*cl
)->var
->current_val
.p
[0]
2115 && strcmp(VSTRING
,(*cl
)->var
->current_val
.p
)){
2119 olddefval
= (char *) fs_get(strlen((*cl
)->var
->current_val
.p
)+3);
2121 if(!strncmp((*cl
)->var
->current_val
.p
,
2123 (len
=strlen(DSTRING
)))){
2124 /* strip DSTRING and trailing paren */
2125 strncpy(olddefval
, (*cl
)->var
->current_val
.p
+len
,
2126 strlen((*cl
)->var
->current_val
.p
)-len
-1);
2127 olddefval
[strlen((*cl
)->var
->current_val
.p
)-len
-1] = '\0';
2130 /* quote it if there are trailing spaces */
2131 quote_it
= ((*cl
)->var
->current_val
.p
[strlen((*cl
)->var
->current_val
.p
)-1] == SPACE
);
2132 snprintf(olddefval
, strlen((*cl
)->var
->current_val
.p
)+3, "%s%s%s", quote_it
? "\"" : "", (*cl
)->var
->current_val
.p
, quote_it
? "\"" : "");
2135 olddefval
[strlen((*cl
)->var
->current_val
.p
)+3-1] = '\0';
2140 else if(((*cl
)->var
->is_list
2142 && !(*cl
)->var
->current_val
.l
)
2144 (!(*cl
)->var
->is_list
2146 && !(*cl
)->var
->current_val
.p
)){
2154 fs_give((void **)&sval
);
2155 if((*cl
)->var
->is_list
){
2156 snprintf(prompt
, sizeof(prompt
), _("Change field %s list entry : "),
2158 prompt
[sizeof(prompt
)-1] = '\0';
2159 clptr
= lval
[(*cl
)->varmem
] ? lval
[(*cl
)->varmem
] : NULL
;
2162 if(flags
& CF_NUMBER
)
2163 snprintf(prompt
, sizeof(prompt
), _("Change numeric field %s value : "), (*cl
)->var
->name
);
2165 snprintf(prompt
, sizeof(prompt
), _("Change field %s value : "), (*cl
)->var
->name
);
2167 clptr
= pval
? pval
: NULL
;
2170 oebufsize
= clptr
? (int) MAX(MAXPATH
, 50+strlen(clptr
)) : MAXPATH
;
2171 sval
= (char *) fs_get(oebufsize
* sizeof(char));
2172 snprintf(sval
, oebufsize
, "%s", clptr
? clptr
: "");
2173 sval
[oebufsize
-1] = '\0';
2175 ps
->mangled_footer
= 1;
2178 if(!(flags
&CF_NUMBER
))
2181 oeflags
= OE_APPEND_CURRENT
;
2182 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
2184 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
2187 removing_leading_and_trailing_white_space(sval
);
2189 * Coerce "" and <Empty Value> to empty string input.
2190 * Catch <No Value Set> as a substitute for deleting.
2192 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
2193 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
2195 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
2197 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
2199 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
2203 if((*cl
)->var
->is_list
)
2204 ps
->mangled_body
= 1;
2206 ps
->mangled_footer
= 1;
2208 if((*cl
)->var
->is_list
){
2212 if(lval
[(*cl
)->varmem
])
2213 fs_give((void **)&lval
[(*cl
)->varmem
]);
2216 for(tmp
= sval
; *tmp
; tmp
++)
2218 i
++; /* conservative count of ,'s */
2221 ltmp
= parse_list(sval
, i
+ 1,
2223 ? PL_COMMAQUOTE
: 0,
2226 if(ltmp
&& !ltmp
[0]) /* only commas */
2228 else if(!i
|| (ltmp
&& !ltmp
[1])){ /* only one item */
2229 lval
[(*cl
)->varmem
] = cpystr(sval
);
2230 newval
= &(*cl
)->value
;
2233 fs_give((void **)<mp
[0]);
2237 * Looks like the value was changed to a
2238 * list, so delete old value, and insert
2241 * If more than one item in existing list and
2242 * current is end of existing list, then we
2243 * have to delete and append instead of
2244 * deleting and prepending.
2246 if(((*cl
)->varmem
> 0 || lval
[1])
2247 && !(lval
[(*cl
)->varmem
+1])){
2252 config_del_list_item(cl
, &newval
);
2253 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
2257 fs_give((void **)<mp
);
2260 if(flags
&CF_NUMBER
&& sval
[0]
2261 && !(isdigit((unsigned char)sval
[0])
2262 || sval
[0] == '-' || sval
[0] == '+')){
2263 q_status_message(SM_ORDER
,3,3,
2264 _("Entry must be numeric"));
2269 fs_give((void **)apval
);
2271 if(sval
[0] && apval
)
2272 *apval
= cpystr(sval
);
2274 newval
= &(*cl
)->value
;
2278 cmd_cancelled("Change");
2281 help
= help
== NO_HELP
? h_config_change
: NO_HELP
;
2284 else if(i
== 4){ /* no redraw, yet */
2287 else if(i
== ctrl('P')){
2288 numval
= atoi(sval
);
2289 if(numval
== lowrange
){
2291 * Protect user from repeating arrow key that
2292 * causes message to appear over and over.
2294 if(++repeat_key
> 0){
2295 q_status_message1(SM_ORDER
,3,3,
2296 _("Minimum value is %s"), comatose(lowrange
));
2303 numval
= MAX(numval
- incr
, lowrange
);
2304 snprintf(sval
, oebufsize
, "%d", numval
);
2305 sval
[oebufsize
-1] = '\0';
2308 else if(i
== ctrl('N')){
2309 numval
= atoi(sval
);
2310 if(numval
== hirange
){
2311 if(++repeat_key
> 0){
2312 q_status_message1(SM_ORDER
,3,3,
2313 _("Maximum value is %s"), comatose(hirange
));
2320 numval
= MIN(numval
+ incr
, hirange
);
2321 snprintf(sval
, oebufsize
, "%d", numval
);
2322 sval
[oebufsize
-1] = '\0';
2333 if(!((*cl
)->var
&& (*cl
)->var
->is_list
)){
2334 q_status_message(SM_ORDER
, 0, 2,
2335 _("Can't shuffle single-valued setting"));
2342 curindex
= (*cl
)->varmem
;
2343 previndex
= curindex
-1;
2344 nextindex
= curindex
+1;
2345 if(!*alval
|| !(*alval
)[nextindex
])
2348 if((previndex
< 0 && nextindex
< 0) || !*alval
){
2349 q_status_message(SM_ORDER
, 0, 3,
2350 _("Shuffle only makes sense when there is more than one value defined"));
2354 /* Move it up or down? */
2359 ekey
[i
++].label
= N_("Up");
2364 ekey
[i
++].label
= N_("Down");
2369 if(previndex
< 0){ /* no up */
2373 else if(nextindex
< 0)
2374 ekey
[1].ch
= -2; /* no down */
2376 snprintf(prompt
, sizeof(prompt
), "Shuffle %s%s%s ? ",
2377 (ekey
[0].ch
!= -2) ? "UP" : "",
2378 (ekey
[0].ch
!= -2 && ekey
[1].ch
!= -2) ? " or " : "",
2379 (ekey
[1].ch
!= -2) ? "DOWN" : "");
2380 help
= (ekey
[0].ch
== -2) ? h_hdrcolor_shuf_down
2381 : (ekey
[1].ch
== -2) ? h_hdrcolor_shuf_up
2383 prompt
[sizeof(prompt
)-1] = '\0';
2385 i
= radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, deefault
, 'x',
2390 cmd_cancelled("Shuffle");
2400 swap_val
= (*alval
)[curindex
];
2401 (*alval
)[curindex
] = (*alval
)[nextindex
];
2402 (*alval
)[nextindex
] = swap_val
;
2405 swap_val
= (*alval
)[curindex
];
2406 (*alval
)[curindex
] = (*alval
)[previndex
];
2407 (*alval
)[previndex
] = swap_val
;
2409 else /* can't happen */
2413 * Fix the conf line values.
2417 fs_give((void **)&(*cl
)->value
);
2419 (*cl
)->value
= pretty_value(ps
, *cl
);
2422 if((*cl
)->next
->value
)
2423 fs_give((void **)&(*cl
)->next
->value
);
2425 (*cl
)->next
->value
= pretty_value(ps
, (*cl
)->next
);
2426 *cl
= next_confline(*cl
);
2429 if((*cl
)->prev
->value
)
2430 fs_give((void **)&(*cl
)->prev
->value
);
2432 (*cl
)->prev
->value
= pretty_value(ps
, (*cl
)->prev
);
2433 *cl
= prev_confline(*cl
);
2436 rv
= ps
->mangled_body
= 1;
2439 case MC_EXIT
: /* exit */
2440 rv
= config_exit_cmd(flags
);
2449 *cl
= next_confline(*cl
);
2452 * At this point, if changes occurred, var->user_val.X is set.
2453 * So, fix the current_val, and handle special cases...
2455 * NOTE: we don't worry about the "fixed variable" case here, because
2456 * editing such vars should have been prevented above...
2460 * Now go and set the current_val based on user_val changes
2461 * above. Turn off command line settings...
2463 set_current_val((*cl
)->var
, TRUE
, FALSE
);
2464 fix_side_effects(ps
, (*cl
)->var
, 0);
2467 * Delay setting the displayed value until "var.current_val" is set
2468 * in case current val gets changed due to a special case above.
2472 fs_give((void **) newval
);
2474 *newval
= pretty_value(ps
, *cl
);
2477 exception_override_warning((*cl
)->var
);
2481 fs_give((void **) &sval
);
2484 fs_give((void **) &olddefval
);
2491 config_exit_cmd(unsigned int flags
)
2493 return(screen_exit_cmd(flags
, "Configuration"));
2498 simple_exit_cmd(unsigned int flags
)
2505 * screen_exit_cmd - basic config/flag screen exit logic
2508 screen_exit_cmd(unsigned int flags
, char *cmd
)
2510 if(flags
& CF_CHANGES
){
2511 switch(want_to(EXIT_PMT
, 'y', 'x', h_config_undo
, WT_FLUSH_IN
)){
2513 q_status_message1(SM_ORDER
,0,3,"%s changes saved", cmd
);
2517 q_status_message1(SM_ORDER
,3,5,"No %s changes saved", cmd
);
2522 q_status_message(SM_ORDER
,3,5,"Changes not yet saved");
2535 config_add_list(struct pine
*ps
, CONF_S
**cl
, char **ltmp
, char ***newval
, int after
)
2538 char *tmp
, ***alval
;
2541 for(items
= 0, i
= 0; ltmp
[i
]; i
++) /* count list items */
2544 alval
= ALVAL((*cl
)->var
, ew
);
2546 if(alval
&& (*alval
)){
2547 if((*alval
)[0] && (*alval
)[0][0]){
2549 * Since we were already a list, make room
2550 * for the new member[s] and fall thru to
2551 * actually fill them in below...
2553 for(i
= 0; (*alval
)[i
]; i
++)
2556 fs_resize((void **)alval
, (i
+ items
+ 1) * sizeof(char *));
2559 * move the ones that will be bumped down to the bottom of the list
2561 for(; i
>= (*cl
)->varmem
+ (after
?1:0); i
--)
2562 (*alval
)[i
+items
] = (*alval
)[i
];
2569 free_list_array(alval
);
2571 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2572 memset((void *)(*alval
), 0, (items
+1)*sizeof(char *));
2573 (*alval
)[0] = ltmp
[0];
2575 *newval
= &(*cl
)->value
;
2578 fs_give((void **)&(*cl
)->value
);
2585 * since we were previously empty, we want
2586 * to replace the first CONF_S's value with
2587 * the first new value, and fill the other
2588 * in below if there's a list...
2590 * first, make sure we're at the beginning of this config
2591 * section and dump the config lines for the default list,
2592 * except for the first one, which we will over-write.
2594 *cl
= (*cl
)->varnamep
;
2595 while((*cl
)->next
&& (*cl
)->next
->varnamep
== (*cl
)->varnamep
)
2596 snip_confline(&(*cl
)->next
);
2599 * now allocate the new user_val array and fill in the first entry.
2601 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2602 memset((void *)(*alval
), 0, (items
+1) * sizeof(char *));
2603 (*alval
)[(*cl
)->varmem
=0] = ltmp
[0];
2605 *newval
= &(*cl
)->value
;
2608 fs_give((void **)&(*cl
)->value
);
2614 * Make new cl's to fit in the new space. Move the value from the current
2615 * line if inserting before it, else leave it where it is.
2617 for(; i
< items
; i
++){
2618 (*alval
)[i
+(*cl
)->varmem
+ (after
?1:0)] = ltmp
[i
];
2622 (*cl
)->value
= NULL
;
2626 (*cl
)->var
= (*cl
)->prev
->var
;
2627 (*cl
)->valoffset
= (*cl
)->prev
->valoffset
;
2628 (*cl
)->varoffset
= (*cl
)->prev
->varoffset
;
2629 (*cl
)->headingp
= (*cl
)->prev
->headingp
;
2630 (*cl
)->keymenu
= (*cl
)->prev
->keymenu
;
2631 (*cl
)->help
= (*cl
)->prev
->help
;
2632 (*cl
)->tool
= (*cl
)->prev
->tool
;
2633 (*cl
)->varnamep
= (*cl
)->prev
->varnamep
;
2636 (*cl
)->value
= NULL
;
2640 *newval
= &(*cl
)->next
->value
;
2642 *newval
= &(*cl
)->value
;
2647 * now fix up varmem values and fill in new values that have been
2650 for(ctmp
= (*cl
)->varnamep
, i
= 0;
2652 ctmp
= ctmp
->next
, i
++){
2655 /* BUG: We should be able to do this without the temp
2658 char *ptmp
= pretty_value(ps
, ctmp
);
2659 ctmp
->value
= (ctmp
->varnamep
->flags
& CF_PRINTER
) ? printer_name(ptmp
) : cpystr(ptmp
);
2660 fs_give((void **)&ptmp
);
2670 config_del_list_item(CONF_S
**cl
, char ***newval
)
2672 char **bufp
, ***alval
;
2676 alval
= ALVAL((*cl
)->var
, ew
);
2678 if((*alval
)[(*cl
)->varmem
+ 1]){
2679 for(bufp
= &(*alval
)[(*cl
)->varmem
];
2680 (*bufp
= *(bufp
+1)) != NULL
; bufp
++)
2683 if(*cl
== (*cl
)->varnamep
){ /* leading value */
2685 fs_give((void **)&(*cl
)->value
);
2688 (*cl
)->value
= ctmp
->value
;
2692 ctmp
= *cl
; /* blast the confline */
2694 if(ctmp
== opt_screen
->top_line
)
2695 opt_screen
->top_line
= *cl
;
2698 snip_confline(&ctmp
);
2700 for(ctmp
= (*cl
)->varnamep
, i
= 0; /* now fix up varmem values */
2702 ctmp
= ctmp
->next
, i
++)
2705 else if((*cl
)->varmem
){ /* blasted last in list */
2708 if(ctmp
== opt_screen
->top_line
)
2709 opt_screen
->top_line
= *cl
;
2711 snip_confline(&ctmp
);
2713 else{ /* blasted last remaining */
2715 fs_give((void **)alval
);
2717 *newval
= &(*cl
)->value
;
2723 * feature list manipulation tool
2726 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
2729 checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2734 case MC_TOGGLE
: /* mark/unmark feature */
2735 if((*cl
)->var
== &ps
->vars
[V_FEATURE_LIST
]){
2737 toggle_feature_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, *cl
, 0);
2740 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2741 "Programmer botch! Unknown checkbox type.");
2745 case MC_EXIT
: /* exit */
2746 rv
= config_exit_cmd(flags
);
2759 * simple radio-button style variable handler
2762 radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2766 NAMEVAL_S
*rule
= NULL
;
2768 int old_uc
= 0, old_cs
= 0;
2772 apval
= APVAL((*cl
)->var
, ew
);
2775 case MC_CHOICE
: /* set/unset feature */
2777 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2778 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
2779 && want_to(_("Delete old unused personal option setting"),
2780 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2781 delete_user_vals((*cl
)->var
);
2782 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
2789 if(standard_radio_var(ps
, (*cl
)->var
) || (*cl
)->var
== startup_ptr
){
2790 PTR_TO_RULEFUNC rulefunc
;
2793 if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2794 old_uc
= pico_usingcolor();
2795 old_cs
= ps
->color_style
;
2799 if((*cl
)->var
->cmdline_val
.p
)
2800 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2803 fs_give((void **)apval
);
2805 rulefunc
= rulefunc_from_var(ps
, (*cl
)->var
);
2807 rule
= (*rulefunc
)((*cl
)->varmem
);
2810 *apval
= cpystr(S_OR_L(rule
));
2812 cur_rule_value((*cl
)->var
, TRUE
, TRUE
);
2813 set_radio_pretty_vals(ps
, cl
);
2815 if((*cl
)->var
== &ps
->vars
[V_AB_SORT_RULE
])
2816 addrbook_redo_sorts();
2817 else if((*cl
)->var
== &ps
->vars
[V_THREAD_DISP_STYLE
]){
2818 clear_index_cache(ps
->mail_stream
, 0);
2820 else if((*cl
)->var
== &ps
->vars
[V_THREAD_INDEX_STYLE
]){
2824 clear_index_cache(ps
->mail_stream
, 0);
2825 /* clear all hidden and collapsed flags */
2826 set_lflags(ps
->mail_stream
, ps
->msgmap
, MN_COLL
| MN_CHID
, 0);
2829 && SORT_IS_THREADED(ps
->msgmap
)
2830 && unview_thread(ps
, ps
->mail_stream
, ps
->msgmap
)){
2831 ps
->next_screen
= mail_index_screen
;
2832 ps
->view_skipped_index
= 0;
2833 ps
->mangled_screen
= 1;
2836 if(SORT_IS_THREADED(ps
->msgmap
)
2837 && (SEP_THRDINDX() || COLL_THRDS()))
2838 collapse_threads(ps
->mail_stream
, ps
->msgmap
, NULL
);
2840 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
2841 m
= ps_global
->s_pool
.streams
[i
];
2843 sp_set_viewing_a_thread(m
, 0);
2846 adjust_cur_to_visible(ps
->mail_stream
, ps
->msgmap
);
2849 else if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2850 if(old_cs
!= ps
->color_style
){
2851 pico_toggle_color(0);
2852 switch(ps
->color_style
){
2855 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
2858 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
2861 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
2864 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
2868 if(ps
->color_style
!= COL_NONE
)
2869 pico_toggle_color(1);
2872 if(pico_usingcolor())
2873 pico_set_normal_color();
2875 if(!old_uc
&& pico_usingcolor()){
2878 * remove the explanatory warning line and a blank line
2881 /* first find the first blank line */
2882 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2883 if(ctmp
->flags
& CF_NOSELECT
)
2886 if(ctmp
&& ctmp
->flags
& CF_NOSELECT
&&
2887 ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
) &&
2888 ctmp
->next
&& ctmp
->next
->flags
& CF_NOSELECT
&&
2890 ctmp
->next
->next
->flags
& CF_NOSELECT
){
2891 ctmp
->prev
->next
= ctmp
->next
->next
;
2892 ctmp
->next
->next
->prev
= ctmp
->prev
;
2893 ctmp
->next
->next
= NULL
;
2894 free_conflines(&ctmp
);
2897 /* make all the colors selectable */
2898 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2899 if(ctmp
->flags
& CF_POT_SLCTBL
)
2900 ctmp
->flags
&= ~CF_NOSELECT
;
2902 else if(old_uc
&& !pico_usingcolor()){
2905 * add the explanatory warning line and a blank line
2908 /* first find the existing blank line */
2909 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2910 if(ctmp
->flags
& CF_NOSELECT
)
2913 /* add the explanatory warning line */
2914 new_confline(&ctmp
);
2915 ctmp
->help
= NO_HELP
;
2916 ctmp
->flags
|= CF_NOSELECT
;
2917 ctmp
->value
= cpystr(COLORNOSET
);
2919 /* and add another blank line */
2920 new_confline(&ctmp
);
2921 ctmp
->flags
|= (CF_NOSELECT
| CF_B_LINE
);
2923 /* make all the colors non-selectable */
2924 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2925 if(ctmp
->flags
& CF_POT_SLCTBL
)
2926 ctmp
->flags
|= CF_NOSELECT
;
2929 clear_index_cache(ps
->mail_stream
, 0);
2931 ps
->mangled_screen
= 1;
2935 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2938 else if((*cl
)->var
== &ps
->vars
[V_SORT_KEY
]){
2942 def_sort_rev
= (*cl
)->varmem
>= (short) EndofList
;
2943 def_sort
= (SortOrder
) ((*cl
)->varmem
- (def_sort_rev
2945 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def_sort
),
2946 (def_sort_rev
) ? "/Reverse" : "");
2948 if((*cl
)->var
->cmdline_val
.p
)
2949 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2953 fs_give((void **)apval
);
2955 *apval
= cpystr(tmp_20k_buf
);
2958 set_current_val((*cl
)->var
, TRUE
, TRUE
);
2959 if(decode_sort(ps
->VAR_SORT_KEY
, &def_sort
, &def_sort_rev
) != -1){
2960 ps
->def_sort
= def_sort
;
2961 ps
->def_sort_rev
= def_sort_rev
;
2964 set_radio_pretty_vals(ps
, cl
);
2965 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2969 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2970 "Programmer botch! Unknown radiobutton type.");
2974 case MC_EXIT
: /* exit */
2975 rv
= config_exit_cmd(flags
);
2984 exception_override_warning((*cl
)->var
);
2991 * simple yes/no style variable handler
2994 yesno_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2996 int rv
= 0, yes
= 0;
2997 char *pval
, **apval
;
2999 pval
= PVAL((*cl
)->var
, ew
);
3000 apval
= APVAL((*cl
)->var
, ew
);
3003 case MC_TOGGLE
: /* toggle yes to no and back */
3004 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
3005 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
3006 && want_to(_("Delete old unused personal option setting"),
3007 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
3008 delete_user_vals((*cl
)->var
);
3009 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
3017 yes
= ((pval
&& !strucmp(pval
, yesstr
)) ||
3018 (!pval
&& (*cl
)->var
->current_val
.p
&&
3019 !strucmp((*cl
)->var
->current_val
.p
, yesstr
)));
3020 fs_give((void **)&(*cl
)->value
);
3024 fs_give((void **)apval
);
3027 *apval
= cpystr(nostr
);
3029 *apval
= cpystr(yesstr
);
3032 set_current_val((*cl
)->var
, FALSE
, FALSE
);
3034 fs_give((void **)&(*cl
)->value
);
3036 (*cl
)->value
= pretty_value(ps
, *cl
);
3037 fix_side_effects(ps
, (*cl
)->var
, 0);
3041 case MC_EXIT
: /* exit */
3042 rv
= config_exit_cmd(flags
);
3055 * Manage display of the config/options menu body.
3058 update_option_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, Pos
*cursor_pos
)
3060 int dline
= 0, w
, save
= '\0';
3061 CONF_S
*top_line
, *ctmp
;
3064 int want_width
, first_width
;
3065 char *saveptr
= NULL
;
3068 int last_selectable
;
3069 mswin_beginupdate();
3071 if(screen
== NULL
|| BODY_LINES(ps
) < 1)
3074 opt_screen
= screen
;
3077 cursor_pos
->col
= 0;
3078 cursor_pos
->row
= -1; /* to tell us if we've set it yet */
3082 * calculate top line of display for reframing if the current field
3083 * is off the display defined by screen->top_line...
3085 if((ctmp
= screen
->top_line
) != NULL
)
3086 for(dline
= BODY_LINES(ps
);
3087 dline
&& ctmp
&& ctmp
!= screen
->current
;
3088 ctmp
= next_confline(ctmp
), dline
--)
3091 if(!ctmp
|| !dline
){ /* force reframing */
3093 ctmp
= top_line
= first_confline(screen
->current
);
3095 if(((dline
++)%BODY_LINES(ps
)) == 0)
3097 while(ctmp
!= screen
->current
&& (ctmp
= next_confline(ctmp
)));
3100 top_line
= screen
->top_line
;
3104 * Figure out how far down the top line is from the top and how many
3105 * total lines there are. Dumb to loop every time thru, but
3106 * there aren't that many lines, and it's cheaper than rewriting things
3107 * to maintain a line count in each structure...
3109 for(dline
= 0, ctmp
= prev_confline(top_line
); ctmp
; ctmp
= prev_confline(ctmp
))
3112 scroll_setpos(dline
);
3113 last_selectable
= dline
;
3114 for(ctmp
= next_confline(top_line
); ctmp
; ctmp
= next_confline(ctmp
)){
3116 if (!(ctmp
->flags
& CF_NOSELECT
))
3117 last_selectable
= dline
;
3119 dline
= last_selectable
;
3120 scroll_setrange(BODY_LINES(ps
), dline
);
3123 /* mangled body or new page, force redraw */
3124 if(ps
->mangled_body
|| screen
->top_line
!= top_line
)
3125 screen
->prev
= NULL
;
3127 /* loop thru painting what's needed */
3128 for(dline
= 0, ctmp
= top_line
;
3129 dline
< BODY_LINES(ps
);
3130 dline
++, ctmp
= next_confline(ctmp
)){
3133 * only fall thru painting if something needs painting...
3135 if(!(!screen
->prev
|| ctmp
== screen
->prev
|| ctmp
== screen
->current
3136 || ctmp
== screen
->prev
->varnamep
3137 || ctmp
== screen
->current
->varnamep
3138 || ctmp
== screen
->prev
->headingp
3139 || ctmp
== screen
->current
->headingp
))
3142 ClearLine(dline
+ HEADER_ROWS(ps
));
3145 if(ctmp
->flags
& CF_B_LINE
)
3148 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3149 if(ctmp
== screen
->current
&& cursor_pos
)
3150 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3152 if((ctmp
== screen
->current
3153 || ctmp
== screen
->current
->varnamep
3154 || ctmp
== screen
->current
->headingp
)
3155 && !(ctmp
->flags
& CF_NOHILITE
))
3158 if(ctmp
->flags
& CF_H_LINE
){
3159 MoveCursor(dline
+ HEADER_ROWS(ps
), 0);
3160 Write_to_screen(repeat_char(ps
->ttyo
->screen_cols
, '-'));
3163 if(ctmp
->flags
& CF_CENTERED
){
3164 int offset
= ps
->ttyo
->screen_cols
/2
3165 - (utf8_width(ctmp
->varname
)/2);
3166 MoveCursor(dline
+ HEADER_ROWS(ps
),
3167 (offset
> 0) ? offset
: 0);
3169 else if(ctmp
->varoffset
)
3170 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->varoffset
);
3172 Write_to_screen(ctmp
->varname
);
3173 if((ctmp
== screen
->current
3174 || ctmp
== screen
->current
->varnamep
3175 || ctmp
== screen
->current
->headingp
)
3176 && !(ctmp
->flags
& CF_NOHILITE
))
3180 value
= (ctmp
->flags
& CF_INHERIT
) ? INHERIT
: ctmp
->value
;
3186 memset(tmp_20k_buf
, '\0',
3187 (6*ps
->ttyo
->screen_cols
+ 1) * sizeof(char));
3188 if(ctmp
== screen
->current
){
3189 if(!(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
))
3193 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3196 if(ctmp
->flags
& CF_H_LINE
)
3197 memset(tmp_20k_buf
, '-',
3198 ps
->ttyo
->screen_cols
* sizeof(char));
3200 if(ctmp
->flags
& CF_CENTERED
){
3201 int offset
= ps
->ttyo
->screen_cols
/2
3202 - (utf8_width(value
)/2);
3203 /* BUG: tabs screw us figuring length above */
3207 p
= tmp_20k_buf
+ offset
;
3208 if(!*(q
= tmp_20k_buf
))
3217 * Copy the value to a temp buffer expanding tabs, and
3218 * making sure not to write beyond screen right...
3220 for(i
= 0, j
= ctmp
->valoffset
; value
[i
]; i
++){
3221 if(value
[i
] == ctrl('I')){
3224 while((++j
) & 0x07);
3232 if(ctmp
== screen
->current
&& cursor_pos
){
3233 if(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
)
3234 cursor_pos
->col
= ctmp
->val2offset
;
3236 cursor_pos
->col
= ctmp
->valoffset
;
3238 if(ctmp
->tool
== radiobutton_tool
3240 || ctmp
->tool
==ldap_radiobutton_tool
3242 || ctmp
->tool
==role_radiobutton_tool
3243 || ctmp
->tool
==checkbox_tool
3244 || (ctmp
->tool
==color_setting_tool
&&
3245 ctmp
->valoffset
!= COLOR_INDENT
))
3249 if(ctmp
->flags
& CF_DOUBLEVAR
){
3253 first_width
= ctmp
->val2offset
- ctmp
->valoffset
- SPACE_BETWEEN_DOUBLEVARS
;
3254 if((l
=utf8_width(p
)) > first_width
&& first_width
>= 0){
3255 saveptr
= utf8_count_forw_width(p
, first_width
, &got_width
);
3257 * got_width != first_width indicates there's a problem
3258 * that should not happen. Ignore it.
3269 * If this is a COLOR_BLOB line we do special coloring.
3270 * The current object inverse hilite is only on the
3271 * checkbox part, the exact format comes from the
3272 * new_color_line function. If we change that we'll have
3273 * to change this to get the coloring right.
3275 if(p
[0] == '(' && p
[2] == ')' &&
3276 p
[3] == ' ' && p
[4] == ' ' &&
3277 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3278 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3279 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3280 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3282 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
);
3283 Write_to_screen_n(p
, 3);
3284 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3287 Write_to_screen_n(p
+3, 3);
3288 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3289 colorx(CFC_ICOLOR(ctmp
)));
3291 lastc
= pico_get_cur_color();
3292 (void)pico_set_colorp(newc
, PSC_NONE
);
3293 free_color_pair(&newc
);
3296 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3299 (void)pico_set_colorp(lastc
, PSC_NONE
);
3300 free_color_pair(&lastc
);
3303 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3306 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, p
);
3307 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3314 PutLine0(dline
+HEADER_ROWS(ps
),
3315 ctmp
->val2offset
- SPACE_BETWEEN_DOUBLEVARS
,
3316 repeat_char(SPACE_BETWEEN_DOUBLEVARS
, SPACE
));
3318 if(l
> ctmp
->val2offset
- ctmp
->valoffset
&& ctmp
->val2offset
- ctmp
->valoffset
>= 0)
3319 p
= saveptr
+ SPACE_BETWEEN_DOUBLEVARS
;
3321 if(p
> tmp_20k_buf
){
3322 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3325 if(p
[0] == '(' && p
[2] == ')' &&
3326 p
[3] == ' ' && p
[4] == ' ' &&
3327 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3328 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3329 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3330 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3332 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->val2offset
);
3333 Write_to_screen_n(p
, 3);
3334 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3337 Write_to_screen_n(p
+3, 3);
3338 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3339 colorx(CFC_ICOLOR(ctmp
)));
3341 lastc
= pico_get_cur_color();
3342 (void)pico_set_colorp(newc
, PSC_NONE
);
3343 free_color_pair(&newc
);
3346 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3349 (void)pico_set_colorp(lastc
, PSC_NONE
);
3350 free_color_pair(&lastc
);
3353 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3356 PutLine0(dline
+HEADER_ROWS(ps
),ctmp
->val2offset
,p
);
3357 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3363 char *q
, *first_space
, *sample
, *ptr
;
3364 COLOR_PAIR
*lastc
, *newc
;
3368 if(ctmp
->flags
& CF_COLORSAMPLE
&&
3369 pico_usingcolor() &&
3370 ((q
= strstr(tmp_20k_buf
, SAMPLE_LEADER
)) ||
3371 (q
= strstr(tmp_20k_buf
, "Color"))) &&
3372 (first_space
= strindex(q
, SPACE
)) &&
3373 (strstr(value
, SAMP1
) ||
3374 strstr(value
, SAMP2
))){
3378 /* write out first part */
3379 *first_space
= '\0';
3380 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
,
3382 *first_space
= SPACE
;
3385 if(ctmp
== screen
->current
)
3388 sample
= skip_white_space(ptr
);
3389 /* if there's enough room to put some sample up */
3392 w
= utf8_width(tmp_20k_buf
);
3394 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3396 sample
++; /* for `[' at edge of sample */
3400 w
= utf8_width(tmp_20k_buf
);
3405 /* spaces and bracket before sample1 */
3406 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+w
, ptr
);
3411 /* then the color sample */
3412 if(ctmp
->var
== &ps
->vars
[V_VIEW_HDR_COLORS
]
3413 || ctmp
->var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
]){
3414 SPEC_COLOR_S
*hc
, *hcolors
;
3416 lastc
= newc
= NULL
;
3419 spec_colors_from_varlist(LVAL(ctmp
->var
, ew
),
3421 for(hc
= hcolors
, i
=0; hc
; hc
= hc
->next
, i
++)
3422 if(CFC_ICUST(ctmp
) == i
)
3425 if(hc
&& hc
->fg
&& hc
->fg
[0] && hc
->bg
&&
3427 newc
= new_color_pair(hc
->fg
, hc
->bg
);
3430 lastc
= pico_get_cur_color();
3431 (void)pico_set_colorp(newc
, PSC_NONE
);
3432 free_color_pair(&newc
);
3436 free_spec_colors(&hcolors
);
3439 /* print out sample1 */
3443 w
= utf8_width(tmp_20k_buf
);
3446 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3447 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3453 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3457 ptr
= strindex(ptr
, ']');
3460 (void)pico_set_colorp(lastc
, PSC_NONE
);
3461 free_color_pair(&lastc
);
3464 else if(ctmp
->var
== &ps
->vars
[V_KW_COLORS
]){
3466 SPEC_COLOR_S
*kw_col
= NULL
;
3468 lastc
= newc
= NULL
;
3470 /* find keyword associated with this line */
3471 for(kw
=ps
->keywords
, i
=0; kw
; kw
=kw
->next
, i
++)
3472 if(CFC_ICUST(ctmp
) == i
)
3477 spec_colors_from_varlist(LVAL(ctmp
->var
,ew
),
3480 /* color for this keyword */
3482 && ((kw
->nick
&& kw
->nick
[0]
3483 && (newc
=hdr_color(kw
->nick
, NULL
,
3486 (kw
->kw
&& kw
->kw
[0]
3487 && (newc
=hdr_color(kw
->kw
, NULL
,
3489 lastc
= pico_get_cur_color();
3490 (void)pico_set_colorp(newc
, PSC_NONE
);
3491 free_color_pair(&newc
);
3495 free_spec_colors(&kw_col
);
3497 /* print out sample1 */
3501 w
= utf8_width(tmp_20k_buf
);
3504 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3505 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3511 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3515 ptr
= strindex(ptr
, ']');
3518 (void)pico_set_colorp(lastc
, PSC_NONE
);
3519 free_color_pair(&lastc
);
3525 newc
= sample_color(ps
, ctmp
->var
);
3527 if((lastc
= pico_get_cur_color()) != NULL
)
3528 (void)pico_set_colorp(newc
, PSC_NONE
);
3530 free_color_pair(&newc
);
3532 else if(var_defaults_to_rev(ctmp
->var
)){
3533 if((newc
= pico_get_rev_color()) != NULL
){
3535 * Note, don't have to free newc.
3537 if((lastc
= pico_get_cur_color()) != NULL
)
3538 (void)pico_set_colorp(newc
, PSC_NONE
);
3546 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3548 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3549 !(PVAL(ctmp
->var
,ew
) &&
3550 PVAL(ctmp
->var
+1,ew
))))
3553 /* print out sample1 */
3557 w
= utf8_width(tmp_20k_buf
);
3560 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3561 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3567 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3571 ptr
= strindex(ptr
, ']');
3573 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3575 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3576 !(PVAL(ctmp
->var
,ew
) &&
3577 PVAL(ctmp
->var
+1,ew
))))
3581 (void)pico_set_colorp(lastc
, PSC_NONE
);
3582 free_color_pair(&lastc
);
3589 * Finish sample1 with the right bracket.
3593 w
= utf8_width(tmp_20k_buf
);
3595 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3598 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3605 * Now check for an exception sample and paint it.
3607 if(ctmp
->valoffset
+ w
+ SBS
+ 1 < ps
->ttyo
->screen_cols
&& (q
= strstr(ptr
, SAMPEXC
))){
3611 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3616 * Figure out what color to paint it.
3617 * This only happens with normal variables,
3618 * not with V_VIEW_HDR_COLORS.
3622 newc
= sampleexc_color(ps
, ctmp
->var
);
3624 if((lastc
= pico_get_cur_color()) != NULL
)
3625 (void)pico_set_colorp(newc
, PSC_NONE
);
3627 free_color_pair(&newc
);
3629 else if(var_defaults_to_rev(ctmp
->var
)){
3630 if((newc
= pico_get_rev_color()) != NULL
){
3632 * Note, don't have to free newc.
3634 if((lastc
= pico_get_cur_color()) != NULL
)
3635 (void)pico_set_colorp(newc
, PSC_NONE
);
3643 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3645 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3646 !(PVAL(ctmp
->var
,Post
) &&
3647 PVAL(ctmp
->var
+1,Post
))))
3653 w
= utf8_width(tmp_20k_buf
);
3656 want_width
= MIN(utf8_width(SAMPEXC
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3657 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3663 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3667 ptr
= strindex(ptr
, ']');
3669 /* turn off bold and color */
3670 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3672 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3673 !(PVAL(ctmp
->var
,Post
) &&
3674 PVAL(ctmp
->var
+1,Post
))))
3678 (void)pico_set_colorp(lastc
, PSC_NONE
);
3679 free_color_pair(&lastc
);
3685 * Finish sample2 with the right bracket.
3689 w
= utf8_width(tmp_20k_buf
);
3691 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3694 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3701 /* paint rest of the line if there is any left */
3702 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
&& *ptr
){
3703 want_width
= ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
;
3704 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3710 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3717 w
= utf8_width(tmp_20k_buf
);
3718 want_width
= ps
->ttyo
->screen_cols
- ctmp
->valoffset
;
3720 saveptr
= utf8_count_forw_width(tmp_20k_buf
, want_width
, &got_width
);
3725 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, tmp_20k_buf
);
3726 if(ctmp
== screen
->current
)
3734 ps
->mangled_body
= 0;
3735 screen
->top_line
= top_line
;
3736 screen
->prev
= screen
->current
;
3748 print_option_screen(OPT_SCREEN_S
*screen
, char *prompt
)
3754 if(open_printer(prompt
) == 0){
3755 for(ctmp
= first_confline(screen
->current
);
3757 ctmp
= next_confline(ctmp
)){
3760 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3762 snprintf(line
, sizeof(line
), "%*s%s", ctmp
->varoffset
, "",
3764 line
[sizeof(line
)-1] = '\0';
3766 so_far
= ctmp
->varoffset
+ utf8_width(ctmp
->varname
);
3769 if(ctmp
&& ctmp
->value
){
3770 char *p
= tmp_20k_buf
;
3773 /* Copy the value to a temp buffer expanding tabs. */
3774 for(i
= 0, j
= ctmp
->valoffset
; ctmp
->value
[i
]; i
++){
3775 if(ctmp
->value
[i
] == ctrl('I')){
3778 while((++j
) & 0x07);
3782 *p
++ = ctmp
->value
[i
];
3788 removing_trailing_white_space(tmp_20k_buf
);
3790 spaces
= MAX(ctmp
->valoffset
- so_far
, 0);
3791 snprintf(line
, sizeof(line
), "%*s%s\n", spaces
, "", tmp_20k_buf
);
3792 line
[sizeof(line
)-1] = '\0';
3807 option_screen_redrawer(void)
3809 ps_global
->mangled_body
= 1;
3810 update_option_screen(ps_global
, opt_screen
, (Pos
*)NULL
);
3816 * pretty_value - given the line, return an
3817 * alloc'd string for line's value...
3820 pretty_value(struct pine
*ps
, CONF_S
*cl
)
3826 if(v
== &ps
->vars
[V_FEATURE_LIST
])
3827 return(checkbox_pretty_value(ps
, cl
));
3828 else if(standard_radio_var(ps
, v
) || v
== startup_ptr
)
3829 return(radio_pretty_value(ps
, cl
));
3830 else if(v
== &ps
->vars
[V_SORT_KEY
])
3831 return(sort_pretty_value(ps
, cl
));
3832 else if(v
== &ps
->vars
[V_SIGNATURE_FILE
])
3833 return(sigfile_pretty_value(ps
, cl
));
3834 else if(v
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
])
3835 return(yesno_pretty_value(ps
, cl
));
3836 else if(color_holding_var(ps
, v
))
3837 return(color_pretty_value(ps
, cl
));
3839 return(text_pretty_value(ps
, cl
));
3844 text_pretty_value(struct pine
*ps
, CONF_S
*cl
)
3846 char tmp
[6*MAX_SCREEN_COLS
+20], *pvalnorm
, **lvalnorm
, *pvalexc
, **lvalexc
= NULL
;
3847 char *p
, *pval
= NULL
, **lval
= NULL
, lastchar
= '\0';
3848 int editing_except
, fixed
, uvalset
, uvalposlen
;
3850 int comments
, except_set
, avail_width
;
3851 int norm_with_except
= 0, norm_with_except_inherit
= 0;
3852 int inherit_line
= 0;
3854 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
3855 fixed
= cl
->var
->is_fixed
;
3856 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
))
3857 norm_with_except
++; /* editing normal and except config exists */
3859 if(cl
->var
->is_list
){
3860 lvalnorm
= LVAL(cl
->var
, Main
);
3861 lvalexc
= LVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3863 uvalset
= lvalexc
!= NULL
;
3864 uvalposlen
= uvalset
&& lvalexc
[0] && lvalexc
[0][0];
3868 uvalset
= lvalnorm
!= NULL
;
3869 uvalposlen
= uvalset
&& lvalnorm
[0] && lvalnorm
[0][0];
3873 except_set
= lvalexc
!= NULL
;
3874 comments
= cl
->var
->current_val
.l
!= NULL
;
3875 if(norm_with_except
&& except_set
&& lvalexc
[0] &&
3876 !strcmp(lvalexc
[0],INHERIT
))
3877 norm_with_except_inherit
++;
3879 if(uvalset
&& !strcmp(lval
[0], INHERIT
)){
3880 if(cl
->varmem
== 0){
3886 /* only add extra comments on last member of list */
3887 if(uvalset
&& !inherit_line
&& lval
&& lval
[cl
->varmem
] &&
3888 lval
[cl
->varmem
+ 1])
3892 pvalnorm
= PVAL(cl
->var
, Main
);
3893 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3895 uvalset
= pvalexc
!= NULL
;
3896 uvalposlen
= uvalset
&& *pvalexc
;
3900 uvalset
= pvalnorm
!= NULL
;
3901 uvalposlen
= uvalset
&& *pvalnorm
;
3905 except_set
= pvalexc
!= NULL
;
3906 comments
= cl
->var
->current_val
.p
!= NULL
;
3909 memset(tmp
, 0, sizeof(tmp
));
3913 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
3915 if(fixed
|| !uvalset
|| !uvalposlen
){
3916 p
+= utf8_to_width(p
, "<", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3917 avail_width
-= got_width
;
3921 p
+= utf8_to_width(p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3922 avail_width
-= got_width
;
3925 p
+= utf8_to_width(p
, _(no_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3926 avail_width
-= got_width
;
3928 else if(!uvalposlen
){
3929 p
+= utf8_to_width(p
, _(empty_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3930 avail_width
-= got_width
;
3932 else if(inherit_line
){
3933 p
+= utf8_to_width(p
, INHERIT
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3934 avail_width
-= got_width
;
3937 if(cl
->var
->is_list
){
3938 p
+= utf8_to_width(p
, lval
[cl
->varmem
], sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3939 avail_width
-= got_width
;
3942 p
+= utf8_to_width(p
, pval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3943 avail_width
-= got_width
;
3947 if(comments
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
3948 if(fixed
|| !uvalset
){
3949 p
+= utf8_to_width(p
, ": using ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3950 avail_width
-= got_width
;
3953 if(norm_with_except
&& except_set
){
3955 p
+= utf8_to_width(p
, "exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3956 avail_width
-= got_width
;
3960 p
+= utf8_to_width(p
, ": ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3961 avail_width
-= got_width
;
3964 p
+= utf8_to_width(p
, " (", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3965 avail_width
-= got_width
;
3968 if(norm_with_except_inherit
){
3969 p
+= utf8_to_width(p
, "added to by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3970 avail_width
-= got_width
;
3973 p
+= utf8_to_width(p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3974 avail_width
-= got_width
;
3979 if(avail_width
>= 7){
3980 if(cl
->var
== &ps_global
->vars
[V_POST_CHAR_SET
]){
3981 p
+= utf8_to_width(p
, "most specific (see help)", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3982 avail_width
-= got_width
;
3985 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
3987 if(cl
->var
->is_list
){
3990 the_list
= cl
->var
->current_val
.l
;
3992 if(norm_with_except
&& except_set
)
3995 if(the_list
&& the_list
[0] && !strcmp(the_list
[0], INHERIT
))
3998 for(lval
= the_list
; avail_width
-(p
-tmp
) > 0 && *lval
; lval
++){
3999 if(lval
!= the_list
){
4000 p
+= utf8_to_width(p
, ",", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
4001 avail_width
-= got_width
;
4004 p
+= utf8_to_width(p
, *lval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
4005 avail_width
-= got_width
;
4009 p
+= utf8_to_width(p
, cl
->var
->current_val
.p
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
4010 avail_width
-= got_width
;
4013 if(p
-tmp
+2 < sizeof(tmp
)){
4019 else if(*(p
-1) == SPACE
)
4023 tmp
[sizeof(tmp
)-1] = '\0';
4025 if(fixed
|| !uvalset
|| !uvalposlen
)
4027 else if(comments
&& norm_with_except
&& except_set
)
4031 if(p
-tmp
+2 < sizeof(tmp
)){
4037 tmp
[sizeof(tmp
)-1] = '\0';
4038 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
4040 if(utf8_width(tmp
) < avail_width
)
4041 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
), "%*s", avail_width
-utf8_width(tmp
), "");
4043 tmp
[sizeof(tmp
)-1] = '\0';
4045 return(cpystr(tmp
));
4050 checkbox_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4052 char tmp
[6*MAXPATH
];
4053 char *comment
= NULL
;
4054 int indent
, x
, screen_width
, need
;
4055 int longest_featname
, longest_comment
;
4056 int nwidcomm
; /* name width with comment */
4057 int nwidnocomm
; /* and without comment */
4060 screen_width
= (ps
&& ps
->ttyo
) ? ps
->ttyo
->screen_cols
: 80;
4063 longest_featname
= longest_feature_name();
4064 longest_comment
= longest_feature_comment(ps
, ew
);
4065 indent
= feature_indent();
4067 nwidcomm
= longest_featname
;
4068 nwidnocomm
= longest_featname
+ 2 + longest_comment
;
4070 if((need
= (indent
+ 5 + longest_featname
+ 2 + longest_comment
) - screen_width
) > 0){
4076 longest_comment
= 0;
4077 nwidnocomm
= longest_featname
;
4081 feature
= feature_list(cl
->varmem
);
4083 x
= feature_gets_an_x(ps
, cl
->var
, feature
, &comment
, ew
);
4085 if(longest_comment
&& comment
&& *comment
){
4086 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w %-*.*w", x
? 'X' : ' ',
4088 pretty_feature_name(feature
->name
, nwidcomm
),
4089 longest_comment
, longest_comment
, comment
? comment
: "");
4092 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w", x
? 'X' : ' ',
4093 nwidnocomm
, nwidnocomm
,
4094 pretty_feature_name(feature
->name
, nwidnocomm
));
4097 return(cpystr(tmp
));
4102 longest_feature_name(void)
4109 for(lv
= 0, i
= 0; (feature
= feature_list(i
)); i
++)
4110 if(feature_list_section(feature
)
4111 && lv
< (j
= utf8_width(pretty_feature_name(feature
->name
, -1))))
4122 feature_indent(void)
4129 yesno_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4131 char tmp
[6*MAXPATH
], *pvalnorm
, *pvalexc
;
4132 char *p
, *pval
, lastchar
= '\0';
4133 int editing_except
, fixed
, norm_with_except
, uvalset
;
4134 int curval
, except_set
;
4136 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
4137 fixed
= cl
->var
->is_fixed
;
4138 if((ps_global
->ew_for_except_vars
== Main
) ||
4139 (ew
== ps_global
->ew_for_except_vars
))
4140 norm_with_except
= 0;
4142 norm_with_except
= 1; /* editing normal and except config exists */
4144 pvalnorm
= PVAL(cl
->var
, Main
);
4145 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
4147 uvalset
= (pvalexc
!= NULL
&&
4148 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4152 uvalset
= (pvalnorm
!= NULL
&&
4153 (!strucmp(pvalnorm
,yesstr
) || !strucmp(pvalnorm
,nostr
)));
4157 except_set
= (pvalexc
!= NULL
&&
4158 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4159 curval
= (cl
->var
->current_val
.p
!= NULL
&&
4160 (!strucmp(cl
->var
->current_val
.p
,yesstr
) ||
4161 !strucmp(cl
->var
->current_val
.p
,nostr
)));
4166 if(fixed
|| !uvalset
)
4167 sstrncpy(&p
, "<", sizeof(tmp
)-(p
-tmp
));
4170 sstrncpy(&p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
));
4172 sstrncpy(&p
, _(no_val
), sizeof(tmp
)-(p
-tmp
));
4173 else if(!strucmp(pval
, yesstr
))
4174 sstrncpy(&p
, yesstr
, sizeof(tmp
)-(p
-tmp
));
4176 sstrncpy(&p
, nostr
, sizeof(tmp
)-(p
-tmp
));
4178 if(curval
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
4179 if(fixed
|| !uvalset
)
4180 sstrncpy(&p
, ": using ", sizeof(tmp
)-(p
-tmp
));
4182 if(norm_with_except
&& except_set
){
4184 sstrncpy(&p
, "exception ", sizeof(tmp
)-(p
-tmp
));
4186 sstrncpy(&p
, " (", sizeof(tmp
)-(p
-tmp
));
4187 sstrncpy(&p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
));
4191 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4192 sstrncpy(&p
, !strucmp(cl
->var
->current_val
.p
,yesstr
) ? yesstr
: nostr
, sizeof(tmp
)-(p
-tmp
));
4193 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4196 if(fixed
|| !uvalset
)
4198 else if(curval
&& norm_with_except
&& except_set
)
4201 if(lastchar
&& sizeof(tmp
)-(p
-tmp
) > 1){
4206 tmp
[sizeof(tmp
)-1] = '\0';
4208 if(utf8_width(tmp
) < ps
->ttyo
->screen_cols
- cl
->valoffset
)
4209 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
),
4210 "%*s", ps
->ttyo
->screen_cols
- cl
->valoffset
- utf8_width(tmp
), "");
4212 tmp
[sizeof(tmp
)-1] = '\0';
4214 return(cpystr(tmp
));
4219 radio_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4221 char tmp
[6*MAXPATH
];
4222 char *pvalnorm
, *pvalexc
, *pval
;
4223 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4224 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4226 NAMEVAL_S
*rule
= NULL
, *f
;
4227 PTR_TO_RULEFUNC rulefunc
;
4233 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4235 editing_normal_which_isnt_except
= (ew
== Main
&&
4236 ew
!= ps_global
->ew_for_except_vars
);
4237 fixed
= cl
->var
->is_fixed
;
4238 pvalnorm
= PVAL(v
, Main
);
4239 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4241 rulefunc
= rulefunc_from_var(ps
, v
);
4242 rule
= rulefunc
? (*rulefunc
)(cl
->varmem
) : NULL
;
4244 /* find longest name */
4246 for(lv
= 0, i
= 0; (f
= (*rulefunc
)(i
)); i
++)
4247 if(lv
< (j
= utf8_width(f
->name
)))
4252 if(editing_except_which_isnt_normal
)
4258 is_set_for_this_level
++;
4261 pval
= v
->fixed_val
.p
;
4262 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4264 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4265 is_the_one
? R_SELD
: ' ',
4266 lv
, lv
, rule
->name
, is_the_one
? " (value is fixed)" : "");
4268 else if(is_set_for_this_level
){
4269 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4270 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4271 !strucmp(pvalexc
, S_OR_L(rule
)));
4272 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4273 is_the_one
? R_SELD
: ' ',
4275 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4276 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4278 editing_normal_which_isnt_except
&&
4280 !the_exc_one
) ? " (overridden by exceptions)" :
4285 is_the_one
= !strucmp(pvalexc
, S_OR_L(rule
));
4286 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4287 is_the_one
? R_SELD
: ' ',
4289 is_the_one
? " (value set in exceptions)" : "");
4292 pval
= v
->current_val
.p
;
4293 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4294 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4295 is_the_one
? R_SELD
: ' ',
4297 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4301 tmp
[sizeof(tmp
)-1] = '\0';
4303 return(cpystr(tmp
));
4308 sigfile_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4310 if(cl
&& cl
->var
== &ps
->vars
[V_SIGNATURE_FILE
] &&
4311 cl
->prev
&& cl
->prev
->var
== &ps
->vars
[V_LITERAL_SIG
]){
4312 if(cl
->prev
->var
->current_val
.p
){
4313 cl
->flags
|= CF_NOSELECT
; /* side effect */
4314 return(cpystr(_("<Ignored: using Literal-Signature instead>")));
4317 cl
->flags
&= ~CF_NOSELECT
;
4318 return(text_pretty_value(ps
, cl
));
4327 color_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4329 char tmp
[6*MAXPATH
];
4337 if(v
&& color_holding_var(ps
, v
) &&
4338 (p
=srchstr(v
->name
, "-foreground-color"))){
4340 is_index
= !struncmp(v
->name
, "index-", 6);
4342 q
= sampleexc_text(ps
, v
);
4343 utf8_snprintf(tmp
, sizeof(tmp
), "%c%.*s %sColor%*.50s %.20w%*s%.20w%.20w",
4344 islower((unsigned char)v
->name
[0])
4345 ? toupper((unsigned char)v
->name
[0])
4347 MIN(p
-v
->name
-1,30), v
->name
+1,
4348 is_index
? "Symbol " : "",
4349 MAX(EQ_COL
- COLOR_INDENT
-1 - MIN(p
-v
->name
-1,30)
4350 - 6 - (is_index
? 7 : 0) - 1,0), "",
4351 sample_text(ps
,v
), *q
? SBS
: 0, "", q
,
4352 color_parenthetical(v
));
4355 tmp
[sizeof(tmp
)-1] = '\0';
4357 return(cpystr(tmp
));
4362 sort_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4364 return(generalized_sort_pretty_value(ps
, cl
, 1));
4369 generalized_sort_pretty_value(struct pine
*ps
, CONF_S
*cl
, int default_ok
)
4371 char tmp
[6*MAXPATH
];
4372 char *pvalnorm
, *pvalexc
, *pval
;
4373 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4374 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4377 SortOrder line_sort
, var_sort
, exc_sort
;
4378 int line_sort_rev
, var_sort_rev
, exc_sort_rev
;
4383 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4385 editing_normal_which_isnt_except
= (ew
== Main
&&
4386 ew
!= ps_global
->ew_for_except_vars
);
4387 fixed
= cl
->var
->is_fixed
;
4388 pvalnorm
= PVAL(v
, Main
);
4389 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4391 /* find longest value's name */
4392 for(lv
= 0, i
= 0; ps
->sort_types
[i
] != EndofList
; i
++)
4393 if(lv
< (j
= utf8_width(sort_name(ps
->sort_types
[i
]))))
4398 if(editing_except_which_isnt_normal
)
4404 is_set_for_this_level
++;
4406 /* the config line we're talking about */
4407 if(cl
->varmem
>= 0){
4408 line_sort_rev
= cl
->varmem
>= (short)EndofList
;
4409 line_sort
= (SortOrder
)(cl
->varmem
- (line_sort_rev
* EndofList
));
4413 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*w",
4414 (pval
== NULL
) ? R_SELD
: ' ',
4418 pval
= v
->fixed_val
.p
;
4419 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4420 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4422 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4423 is_the_one
? R_SELD
: ' ',
4424 line_sort_rev
? "Reverse " : "",
4425 lv
, sort_name(line_sort
),
4426 line_sort_rev
? 0 : 8, "",
4427 is_the_one
? " (value is fixed)" : "");
4429 else if(is_set_for_this_level
){
4430 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4431 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4432 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4433 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4434 exc_sort_rev
== line_sort_rev
&& exc_sort
== line_sort
);
4435 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4436 is_the_one
? R_SELD
: ' ',
4437 line_sort_rev
? "Reverse " : "",
4438 lv
, sort_name(line_sort
),
4439 line_sort_rev
? 0 : 8, "",
4440 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4441 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4443 editing_normal_which_isnt_except
&&
4445 !the_exc_one
) ? " (overridden by exceptions)" :
4450 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4451 is_the_one
= (exc_sort_rev
== line_sort_rev
&&
4452 exc_sort
== line_sort
);
4453 utf8_snprintf(tmp
, sizeof(tmp
), "( ) %s%-*w%*s%s",
4454 line_sort_rev
? "Reverse " : "",
4455 lv
, sort_name(line_sort
),
4456 line_sort_rev
? 0 : 8, "",
4457 is_the_one
? " (value set in exceptions)" : "");
4460 pval
= v
->current_val
.p
;
4461 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4462 is_the_one
= ((pval
|| default_ok
) &&
4463 var_sort_rev
== line_sort_rev
&&
4464 var_sort
== line_sort
);
4465 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4466 is_the_one
? R_SELD
: ' ',
4467 line_sort_rev
? "Reverse " : "",
4468 lv
, sort_name(line_sort
),
4469 line_sort_rev
? 0 : 8, "",
4470 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4474 return(cpystr(tmp
));
4479 sample_color(struct pine
*ps
, struct variable
*v
)
4481 COLOR_PAIR
*cp
= NULL
;
4482 char *pvalefg
, *pvalebg
;
4483 char *pvalmfg
, *pvalmbg
;
4485 pvalefg
= PVAL(v
, ew
);
4486 pvalebg
= PVAL(v
+1, ew
);
4487 pvalmfg
= PVAL(v
, Main
);
4488 pvalmbg
= PVAL(v
+1, Main
);
4489 if(v
&& color_holding_var(ps
, v
) &&
4490 srchstr(v
->name
, "-foreground-color")){
4491 if(pvalefg
&& pvalefg
[0] && pvalebg
&& pvalebg
[0])
4492 cp
= new_color_pair(pvalefg
, pvalebg
);
4493 else if(ew
== Post
&& pvalmfg
&& pvalmfg
[0] && pvalmbg
&& pvalmbg
[0])
4494 cp
= new_color_pair(pvalmfg
, pvalmbg
);
4495 else if(v
->global_val
.p
&& v
->global_val
.p
[0] &&
4496 (v
+1)->global_val
.p
&& (v
+1)->global_val
.p
[0])
4497 cp
= new_color_pair(v
->global_val
.p
, (v
+1)->global_val
.p
);
4505 sampleexc_color(struct pine
*ps
, struct variable
*v
)
4507 COLOR_PAIR
*cp
= NULL
;
4508 char *pvalfg
, *pvalbg
;
4510 pvalfg
= PVAL(v
, Post
);
4511 pvalbg
= PVAL(v
+1, Post
);
4512 if(v
&& color_holding_var(ps
, v
) &&
4513 srchstr(v
->name
, "-foreground-color") &&
4514 pvalfg
&& pvalfg
[0] && pvalbg
&& pvalbg
[0])
4515 cp
= new_color_pair(pvalfg
, pvalbg
);
4522 clear_feature(char ***l
, char *f
)
4524 char **list
= l
? *l
: NULL
;
4527 for(; list
&& *list
; list
++, count
++){
4528 if(f
&& !strucmp(((!struncmp(*list
,"no-",3)) ? *list
+ 3 : *list
), f
)){
4529 fs_give((void **)list
);
4534 *list
= *(list
+ 1);
4538 * this is helpful to keep the array from growing if a feature
4539 * gets set and unset repeatedly
4542 fs_resize((void **)l
, count
* sizeof(char *));
4550 toggle_feature_bit(struct pine
*ps
, int index
, struct variable
*var
, CONF_S
*cl
, int just_flip_value
)
4556 f
= feature_list(index
);
4558 og
= test_old_growth_bits(ps
, f
->id
);
4561 * if this feature is in the fixed set, or old-growth is in the fixed
4562 * set and this feature is in the old-growth set, don't alter it...
4564 for(vp
= var
->fixed_val
.l
; vp
&& *vp
; vp
++){
4565 p
= (struncmp(*vp
, "no-", 3)) ? *vp
: *vp
+ 3;
4566 if(!strucmp(p
, f
->name
) || (og
&& !strucmp(p
, "old-growth"))){
4567 q_status_message(SM_ORDER
, 3, 3,
4568 _("Can't change value fixed by sys-admin."));
4573 on_before
= F_ON(f
->id
, ps
);
4575 toggle_feature(ps
, var
, f
, just_flip_value
, ew
);
4578 * Handle any alpine-specific features that need attention here. Features
4579 * that aren't alpine-specific should be handled in toggle_feature instead.
4581 if(on_before
!= F_ON(f
->id
, ps
))
4583 case F_CMBND_ABOOK_DISP
:
4587 case F_PRESERVE_START_STOP
:
4588 /* toggle raw mode settings to make tty driver aware of new setting */
4594 ps
->orig_use_fkeys
= F_ON(F_USE_FK
, ps
);
4595 ps
->mangled_footer
= 1;
4596 mark_keymenu_dirty();
4600 ps
->mangled_header
= 1;
4603 case F_BLANK_KEYMENU
:
4604 if(F_ON(f
->id
, ps
)){
4605 FOOTER_ROWS(ps
) = 1;
4606 ps
->mangled_body
= 1;
4609 FOOTER_ROWS(ps
) = 3;
4610 ps
->mangled_footer
= 1;
4616 case F_ENABLE_INCOMING
:
4617 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4618 "Folder List changes will take effect your next Alpine session.");
4622 case F_SHOW_CURSOR
:
4623 mswin_showcaret(F_ON(f
->id
,ps
));
4626 case F_ENABLE_TRAYICON
:
4627 mswin_trayicon(F_ON(f
->id
,ps
));
4631 #if !defined(DOS) && !defined(OS2)
4641 case F_PASS_CONTROL_CHARS
:
4642 ps
->pass_ctrl_chars
= F_ON(F_PASS_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4646 case F_USE_CERT_STORE_ONLY
:
4647 if(F_OFF(F_USE_CERT_STORE_ONLY
, ps
))
4648 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4649 "Disabling this feature should only be done for testing. Press \"?\" for help");
4653 case F_PASS_C1_CONTROL_CHARS
:
4654 ps
->pass_c1_ctrl_chars
= F_ON(F_PASS_C1_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4658 case F_ENABLE_MOUSE
:
4659 if(F_ON(f
->id
, ps
)){
4662 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4663 "Mouse tracking still off ($DISPLAY variable set?)");
4672 if(just_flip_value
){
4673 if(cl
->value
&& cl
->value
[0])
4674 cl
->value
[1] = (cl
->value
[1] == ' ') ? 'X' : ' ';
4678 * This fork is only called from the checkbox_tool, which has
4679 * varmem set to index correctly and cl->var set correctly.
4682 fs_give((void **)&cl
->value
);
4684 cl
->value
= pretty_value(ps
, cl
);
4690 * new_confline - create new CONF_S zero it out, and insert it after current.
4691 * NOTE current gets set to the new CONF_S too!
4694 new_confline(CONF_S
**current
)
4698 p
= (CONF_S
*)fs_get(sizeof(CONF_S
));
4699 memset((void *)p
, 0, sizeof(CONF_S
));
4702 p
->next
= (*current
)->next
;
4703 (*current
)->next
= p
;
4720 snip_confline(CONF_S
**p
)
4725 * Be careful. We need this line because the
4726 * q->prev->next = ...
4727 * may change q itself if &q == &q->prev->next.
4728 * Then the use of q in the next line is wrong.
4729 * That's what happens if we pass in the address of
4730 * some ->next and use *p directly instead of q.
4735 /* Yank it from the linked list */
4737 q
->prev
->next
= q
->next
;
4740 q
->next
->prev
= q
->prev
;
4742 /* Then free up it's memory */
4743 q
->prev
= q
->next
= NULL
;
4749 get_confline_number(CONF_S
*conf
)
4754 for (p
= first_confline(conf
), pos
= 0; p
!= conf
; p
= next_confline(p
), pos
++);
4761 set_confline_number(CONF_S
*conf
, int pos
)
4765 for(p
= first_confline(conf
), i
= 0; p
&& i
< pos
; p
=next_confline(p
), i
++);
4774 free_conflines(CONF_S
**p
)
4777 free_conflines(&(*p
)->next
);
4780 fs_give((void **) &(*p
)->varname
);
4783 fs_give((void **) &(*p
)->value
);
4785 fs_give((void **) p
);
4794 first_confline(CONF_S
*p
)
4804 * First selectable confline.
4807 first_sel_confline(CONF_S
*p
)
4809 for(p
= first_confline(p
); p
&& (p
->flags
&CF_NOSELECT
); p
=next_confline(p
))
4820 last_confline(CONF_S
*p
)
4833 fixed_var(struct variable
*v
, char *action
, char *name
)
4839 || ((lval
=v
->fixed_val
.l
) && lval
[0]
4840 && strcmp(INHERIT
, lval
[0]) != 0))){
4841 q_status_message2(SM_ORDER
, 3, 3,
4842 "Can't %s sys-admin defined %s.",
4843 action
? action
: "change", name
? name
: "value");
4852 exception_override_warning(struct variable
*v
)
4856 /* if exceptions config file exists and we're not editing it */
4857 if(v
&& (ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
4858 if((!v
->is_list
&& PVAL(v
, ps_global
->ew_for_except_vars
)) ||
4859 (v
->is_list
&& (lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
4860 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0))
4861 q_status_message1(SM_ORDER
, 3, 3,
4862 _("Warning: \"%s\" is overridden in your exceptions configuration"),
4869 offer_to_fix_pinerc(struct pine
*ps
)
4876 int rv
= 0, write_main
= 0, write_post
= 0;
4877 int i
, k
, j
, need
, exc
;
4878 char *clear
= ": delete it";
4881 dprint((4, "offer_to_fix_pinerc()\n"));
4883 ps
->fix_fixed_warning
= 0; /* so we only ask first time */
4885 if(ps
->readonly_pinerc
)
4888 set_titlebar(_("FIXING PINERC"), ps
->mail_stream
,
4889 ps
->context_current
,
4890 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
4892 if(want_to(_("Some of your options conflict with site policy. Investigate"),
4893 'y', 'n', NO_HELP
, WT_FLUSH_IN
) != 'y')
4896 /* space want_to requires in addition to the string you pass in */
4897 #define WANTTO_SPACE 6
4898 need
= WANTTO_SPACE
+ utf8_width(clear
);
4900 for(v
= ps
->vars
; v
->name
; v
++){
4904 v
== &ps
->vars
[V_FEATURE_LIST
]) /* handle feature-list below */
4910 (v
->post_user_val
.l
|| v
->main_user_val
.l
)){
4913 active_list
= v
->post_user_val
.l
? v
->post_user_val
.l
4914 : v
->main_user_val
.l
;
4916 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is "), v
->name
);
4917 prompt
[sizeof(prompt
)-1] = '\0';
4918 p
= prompt
+ strlen(prompt
);
4919 for(i
= 0; active_list
[i
]; i
++){
4920 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4922 if(i
&& sizeof(prompt
)-(p
-prompt
) > 0)
4925 sstrncpy(&p
, active_list
[i
], sizeof(prompt
)-(p
-prompt
));
4926 if(sizeof(prompt
)-(p
-prompt
) > 0)
4929 prompt
[sizeof(prompt
)-1] = '\0';
4932 if(sizeof(prompt
)-(p
-prompt
) > 0)
4936 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"), v
->name
, _(empty_val2
));
4939 if(v
->post_user_val
.p
|| v
->main_user_val
.p
){
4942 active_var
= v
->post_user_val
.p
? v
->post_user_val
.p
4943 : v
->main_user_val
.p
;
4945 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4946 v
->name
, active_var
);
4949 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4950 v
->name
, _(empty_val2
));
4955 prompt
[sizeof(prompt
)-1] = '\0';
4958 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4959 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4961 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4962 prompt
[sizeof(prompt
)-1] = '\0';
4963 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4965 if(v
->main_user_val
.l
)
4967 if(v
->post_user_val
.l
)
4971 if(v
->main_user_val
.p
)
4973 if(v
->post_user_val
.p
)
4977 if(delete_user_vals(v
))
4985 * As always, feature-list has to be handled separately.
4987 exc
= (ps
->ew_for_except_vars
!= Main
);
4988 v
= &ps
->vars
[V_FEATURE_LIST
];
4989 list_fixed
= v
->fixed_val
.l
;
4991 for(j
= 0; j
< 2; j
++){
4992 plist
= (j
==0) ? &v
->main_user_val
.l
: &v
->post_user_val
.l
;
4995 for(i
= 0; list
[i
]; i
++){
4997 if(!struncmp(p
, "no-", 3))
4999 for(k
= 0; list_fixed
&& list_fixed
[k
]; k
++){
5001 if(!struncmp(q
, "no-", 3))
5003 if(!strucmp(q
, p
) && strucmp(list
[i
], list_fixed
[k
])){
5004 snprintf(prompt
, sizeof(prompt
), "Your %s is %s%s, fixed value is %s",
5005 p
, p
== list
[i
] ? _("ON") : _("OFF"),
5006 exc
? ((plist
== &v
->main_user_val
.l
) ? ""
5007 : " in postload-config")
5009 q
== list_fixed
[k
] ? _("ON") : _("OFF"));
5011 prompt
[sizeof(prompt
)-1] = '\0';
5012 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
5013 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
5015 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
5016 prompt
[sizeof(prompt
)-1] = '\0';
5017 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
5020 if(plist
== &v
->main_user_val
.l
)
5026 * Clear the feature from the user's pinerc
5027 * so that we'll stop bothering them when they
5030 clear_feature(plist
, p
);
5033 * clear_feature scoots the list up, so if list[i] was
5034 * the last one going in, now it is the end marker. We
5035 * just decrement i so that it will get incremented and
5036 * then test == 0 in the for loop. We could just goto
5037 * outta_here to accomplish the same thing.
5050 write_pinerc(ps
, Main
, WRP_NONE
);
5052 write_pinerc(ps
, Post
, WRP_NONE
);
5059 * Adjust side effects that happen because variable changes values.
5061 * Var->user_val should be set to the new value before calling this.
5064 fix_side_effects(struct pine
*ps
, struct variable
*var
, int revert
)
5067 char **v
, *q
, **apval
;
5068 struct variable
*vars
= ps
->vars
;
5070 /* move this up here so we get the Using default message */
5071 if(var
== &ps
->vars
[V_PERSONAL_NAME
]){
5072 if(!(var
->main_user_val
.p
||
5073 var
->post_user_val
.p
) && ps
->ui
.fullname
){
5074 if(var
->current_val
.p
)
5075 fs_give((void **)&var
->current_val
.p
);
5077 var
->current_val
.p
= cpystr(ps
->ui
.fullname
);
5084 && !(var
->main_user_val
.p
||
5085 var
->post_user_val
.p
)
5086 && var
->current_val
.p
)
5090 && !(var
->main_user_val
.l
||
5091 var
->post_user_val
.l
)
5092 && var
->current_val
.l
)))
5093 q_status_message(SM_ORDER
,0,3,_("Using default value"));
5095 if(var
== &ps
->vars
[V_USER_DOMAIN
]){
5098 if(ps
->VAR_USER_DOMAIN
5099 && ps
->VAR_USER_DOMAIN
[0]
5100 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5103 q_status_message2(SM_ORDER
, 3, 5,
5104 _("User-Domain (%s) cannot contain \"@\"; using %s"),
5105 ps
->VAR_USER_DOMAIN
, p
);
5106 q
= ps
->VAR_USER_DOMAIN
;
5107 while((*q
++ = *p
++) != '\0')
5112 q_status_message1(SM_ORDER
, 3, 5,
5113 _("User-domain (%s) cannot contain \"@\"; deleting"),
5114 ps
->VAR_USER_DOMAIN
);
5116 if(ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
){
5117 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
);
5118 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5121 if(ps
->VAR_USER_DOMAIN
5122 && ps
->VAR_USER_DOMAIN
[0]
5123 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5124 if(ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
){
5125 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
);
5126 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5133 * Reset various pointers pertaining to domain name and such...
5137 else if(var
== &ps
->vars
[V_INBOX_PATH
]){
5139 * fixup the inbox path based on global/default values...
5141 init_inbox_mapping(ps
->VAR_INBOX_PATH
, ps
->context_list
);
5143 if(!strucmp(ps
->cur_folder
, ps
->inbox_name
) && ps
->mail_stream
5144 && strcmp(ps
->VAR_INBOX_PATH
, ps
->mail_stream
->mailbox
)){
5146 * If we currently have "inbox" open and the mailbox name
5147 * doesn't match, reset the current folder's name and
5148 * remove the SP_INBOX flag.
5150 strncpy(ps
->cur_folder
, ps
->mail_stream
->mailbox
,
5151 sizeof(ps
->cur_folder
)-1);
5152 ps
->cur_folder
[sizeof(ps
->cur_folder
)-1] = '\0';
5153 sp_set_fldr(ps
->mail_stream
, ps
->cur_folder
);
5154 sp_unflag(ps
->mail_stream
, SP_INBOX
);
5155 ps
->mangled_header
= 1;
5157 else if(sp_inbox_stream()
5158 && strcmp(ps
->VAR_INBOX_PATH
, sp_inbox_stream()->original_mailbox
)){
5159 MAILSTREAM
*m
= sp_inbox_stream();
5162 * if we don't have inbox directly open, but have it
5163 * open for new mail notification, close the stream like
5164 * any other ordinary folder, and clean up...
5167 sp_unflag(m
, SP_PERMLOCKED
| SP_INBOX
);
5168 sp_set_fldr(m
, m
->mailbox
);
5169 expunge_and_close(m
, NULL
, EC_NONE
);
5173 else if(var
== &ps
->vars
[V_INCCHECKTIMEO
]){
5174 int old_value
= ps
->inc_check_timeout
;
5176 if(SVAR_INC_CHECK_TIMEO(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5178 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5181 ps
->inc_check_timeout
= old_value
;
5183 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5184 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5186 else if(var
== &ps
->vars
[V_INCCHECKINTERVAL
]){
5187 int old_value
= ps
->inc_check_interval
;
5189 if(SVAR_INC_CHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5191 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5194 ps
->inc_check_interval
= old_value
;
5196 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5197 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5199 else if(var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
]){
5200 int old_value
= ps
->inc_second_check_interval
;
5202 if(SVAR_INC_2NDCHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5204 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5207 ps
->inc_second_check_interval
= old_value
;
5209 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5210 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5212 else if(var
== &ps
->vars
[V_INCCHECKLIST
]){
5213 if(ps
->context_list
&& ps
->context_list
->use
& CNTXT_INCMNG
)
5214 reinit_incoming_folder_list(ps
, ps
->context_list
);
5216 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5217 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5219 else if(var
== &ps
->vars
[V_ADDRESSBOOK
] ||
5220 var
== &ps
->vars
[V_GLOB_ADDRBOOK
] ||
5222 var
== &ps
->vars
[V_LDAP_SERVERS
] ||
5224 var
== &ps
->vars
[V_ABOOK_FORMATS
]){
5227 else if(var
== &ps
->vars
[V_INDEX_FORMAT
]){
5228 reset_index_format();
5229 clear_index_cache(ps
->mail_stream
, 0);
5231 else if(var
== &ps
->vars
[V_DEFAULT_FCC
] ||
5232 var
== &ps
->vars
[V_DEFAULT_SAVE_FOLDER
]){
5233 init_save_defaults();
5235 else if(var
== &ps
->vars
[V_KW_BRACES
] ||
5236 var
== &ps
->vars
[V_OPENING_SEP
] ||
5237 var
== &ps
->vars
[V_ALT_ADDRS
]){
5238 clear_index_cache(ps
->mail_stream
, 0);
5240 else if(var
== &ps
->vars
[V_KEYWORDS
]){
5241 if(ps_global
->keywords
)
5242 free_keyword_list(&ps_global
->keywords
);
5244 if(var
->current_val
.l
&& var
->current_val
.l
[0])
5245 ps_global
->keywords
= init_keyword_list(var
->current_val
.l
);
5247 clear_index_cache(ps
->mail_stream
, 0);
5249 else if(var
== &ps
->vars
[V_INIT_CMD_LIST
]){
5251 q_status_message(SM_ASYNC
, 0, 3,
5252 _("Initial command changes will affect your next Alpine session."));
5254 else if(var
== &ps
->vars
[V_VIEW_HEADERS
]){
5255 ps
->view_all_except
= 0;
5256 if(ps
->VAR_VIEW_HEADERS
)
5257 for(v
= ps
->VAR_VIEW_HEADERS
; (q
= *v
) != NULL
; v
++)
5261 removing_leading_white_space(q
);
5262 /* look for colon or space or end */
5263 for(p
= q
; *p
&& !isspace((unsigned char)*p
) && *p
!= ':'; p
++)
5267 if(strucmp(q
, ALL_EXCEPT
) == 0)
5268 ps
->view_all_except
= 1;
5271 else if(var
== &ps
->vars
[V_OVERLAP
]){
5272 int old_value
= ps
->viewer_overlap
;
5274 if(SVAR_OVERLAP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5276 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5279 ps
->viewer_overlap
= old_value
;
5282 else if(smime_related_var(ps
, var
)){
5286 else if(var
== &ps
->vars
[V_MAXREMSTREAM
]){
5287 int old_value
= ps
->s_pool
.max_remstream
;
5289 if(SVAR_MAXREMSTREAM(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5291 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5294 ps
->s_pool
.max_remstream
= old_value
;
5296 dprint((9, "max_remstream goes to %d\n",
5297 ps
->s_pool
.max_remstream
));
5300 else if(var
== &ps
->vars
[V_CHAR_SET
]){
5303 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5305 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5308 if(reset_character_set_stuff(&err
) == -1)
5309 alpine_panic(err
? err
: "trouble with Character-Set");
5311 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5312 fs_give((void **) &err
);
5316 else if(var
== &ps
->vars
[V_KEY_CHAR_SET
]){
5319 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5321 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5324 if(reset_character_set_stuff(&err
) == -1)
5325 alpine_panic(err
? err
: "trouble with Character-Set");
5327 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5328 fs_give((void **) &err
);
5332 #endif /* ! _WINDOWS */
5333 else if(var
== &ps
->vars
[V_POST_CHAR_SET
]){
5334 update_posting_charset(ps
, revert
);
5336 else if(var
== &ps
->vars
[V_MARGIN
]){
5337 int old_value
= ps
->scroll_margin
;
5339 if(SVAR_MARGIN(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5341 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5344 ps
->scroll_margin
= old_value
;
5346 else if(var
== &ps
->vars
[V_DEADLETS
]){
5347 int old_value
= ps
->deadlets
;
5349 if(SVAR_DEADLETS(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5351 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5354 ps
->deadlets
= old_value
;
5356 else if(var
== &ps
->vars
[V_FILLCOL
]){
5357 if(SVAR_FILLCOL(ps
, ps
->composer_fillcol
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5359 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5362 else if(var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
5363 val
= ps
->quote_suppression_threshold
;
5364 if(val
< Q_SUPP_LIMIT
&& val
> 0)
5367 if(ps
->VAR_QUOTE_SUPPRESSION
5368 && SVAR_QUOTE_SUPPRESSION(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5370 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5373 if(val
> 0 && val
< Q_SUPP_LIMIT
){
5375 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, _("Ignoring Quote-Suppression-Threshold value of %s, see help"), ps
->VAR_QUOTE_SUPPRESSION
);
5376 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
5377 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5381 if(val
< 0 && val
!= Q_DEL_ALL
)
5382 ps
->quote_suppression_threshold
= -val
;
5384 ps
->quote_suppression_threshold
= val
;
5388 else if(var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
5389 if(SVAR_MSGDLAY(ps
, ps
->status_msg_delay
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5391 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5394 else if(var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
5395 if(SVAR_ACTIVEINTERVAL(ps
, ps
->active_status_interval
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5397 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5400 busy_cue(_("Active Example"), NULL
, 0);
5402 cancel_busy_cue(-1);
5405 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
5406 else if(var
== &ps
->vars
[V_FIFOPATH
]){
5407 init_newmailfifo(ps
->VAR_FIFOPATH
);
5410 else if(var
== &ps
->vars
[V_NMW_WIDTH
]){
5411 int old_value
= ps
->nmw_width
;
5413 if(SVAR_NMW_WIDTH(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5415 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5419 if(old_value
!= ps
->nmw_width
)
5420 mswin_setnewmailwidth(old_value
); /* actually the new value */
5422 ps
->nmw_width
= old_value
;
5425 else if(var
== &ps
->vars
[V_TCPOPENTIMEO
]){
5428 if(ps
->VAR_TCPOPENTIMEO
&& SVAR_TCP_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5429 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5431 else if(var
== &ps
->vars
[V_TCPREADWARNTIMEO
]){
5434 if(ps
->VAR_TCPREADWARNTIMEO
&& SVAR_TCP_READWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5435 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5437 else if(var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
]){
5440 if(ps
->VAR_TCPWRITEWARNTIMEO
&& SVAR_TCP_WRITEWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5441 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5443 else if(var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
5446 if(ps
->VAR_TCPQUERYTIMEO
&& SVAR_TCP_QUERY(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5447 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5449 else if(var
== &ps
->vars
[V_QUITQUERYTIMEO
]){
5452 if(ps
->VAR_QUITQUERYTIMEO
&& SVAR_QUIT_QUERY_TIMEO(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5453 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5455 else if(var
== &ps
->vars
[V_RSHOPENTIMEO
]){
5458 if(ps
->VAR_RSHOPENTIMEO
&& SVAR_RSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5459 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5461 else if(var
== &ps
->vars
[V_SSHOPENTIMEO
]){
5464 if(ps
->VAR_SSHOPENTIMEO
&& SVAR_SSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5465 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5467 else if(var
== &ps
->vars
[V_SIGNATURE_FILE
]){
5468 if(ps
->VAR_OPER_DIR
&& ps
->VAR_SIGNATURE_FILE
&&
5469 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
5470 !in_dir(ps
->VAR_OPER_DIR
, ps
->VAR_SIGNATURE_FILE
)){
5474 l
= strlen(ps
->VAR_OPER_DIR
) + 100;
5475 e
= (char *) fs_get((l
+1) * sizeof(char));
5476 snprintf(e
, l
+1, _("Warning: Sig file can't be outside of %s"),
5479 q_status_message(SM_ORDER
, 3, 6, e
);
5480 fs_give((void **)&e
);
5483 else if(var
== &ps
->vars
[V_OPER_DIR
]){
5484 if(ps
->VAR_OPER_DIR
&& !ps
->VAR_OPER_DIR
[0]){
5485 q_status_message(SM_ORDER
, 3, 5, "Operating-dir is turned off.");
5486 fs_give((void **)&ps
->vars
[V_OPER_DIR
].current_val
.p
);
5487 if(ps
->vars
[V_OPER_DIR
].fixed_val
.p
)
5488 fs_give((void **)&ps
->vars
[V_OPER_DIR
].fixed_val
.p
);
5489 if(ps
->vars
[V_OPER_DIR
].global_val
.p
)
5490 fs_give((void **)&ps
->vars
[V_OPER_DIR
].global_val
.p
);
5491 if(ps
->vars
[V_OPER_DIR
].cmdline_val
.p
)
5492 fs_give((void **)&ps
->vars
[V_OPER_DIR
].cmdline_val
.p
);
5493 if(ps
->vars
[V_OPER_DIR
].post_user_val
.p
)
5494 fs_give((void **)&ps
->vars
[V_OPER_DIR
].post_user_val
.p
);
5495 if(ps
->vars
[V_OPER_DIR
].main_user_val
.p
)
5496 fs_give((void **)&ps
->vars
[V_OPER_DIR
].main_user_val
.p
);
5499 else if(var
== &ps
->vars
[V_MAILCHECK
]){
5501 if(SVAR_MAILCHK(ps
, timeo
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5502 set_input_timeout(15);
5504 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5507 set_input_timeout(timeo
);
5508 if(get_input_timeout() == 0 && !revert
){
5509 q_status_message(SM_ORDER
, 4, 6,
5510 _("Warning: automatic new mail checking and mailbox checkpointing is disabled"));
5511 if(ps
->VAR_INBOX_PATH
&& ps
->VAR_INBOX_PATH
[0] == '{')
5512 q_status_message(SM_ASYNC
, 3, 6,
5513 _("Warning: Mail-Check-Interval=0 may cause IMAP server connection to time out"));
5517 else if(var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
5518 val
= (int) ps
->check_interval_for_noncurr
;
5519 if(ps
->VAR_MAILCHECKNONCURR
5520 && SVAR_MAILCHKNONCURR(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5522 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5525 ps
->check_interval_for_noncurr
= (time_t) val
;
5527 else if(var
== &ps
->vars
[V_MAILDROPCHECK
]){
5531 if(ps
->VAR_MAILDROPCHECK
&& SVAR_MAILDCHK(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5532 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5535 rvl
= (60L * 60L * 24L * 100L); /* 100 days */
5538 mail_parameters(NULL
, SET_SNARFINTERVAL
, (void *) rvl
);
5541 else if(var
== &ps
->vars
[V_NNTPRANGE
]){
5545 if(ps
->VAR_NNTPRANGE
&& SVAR_NNTPRANGE(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5546 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5549 mail_parameters(NULL
, SET_NNTPRANGE
, (void *) rvl
);
5552 else if(var
== &ps
->vars
[V_CUSTOM_HDRS
] || var
== &ps
->vars
[V_COMP_HDRS
]){
5553 /* this will give warnings about headers that can't be changed */
5554 if(!revert
&& var
->current_val
.l
&& var
->current_val
.l
[0])
5555 customized_hdr_setup(NULL
, var
->current_val
.l
, UseAsDef
);
5557 #if defined(DOS) || defined(OS2)
5558 else if(var
== &ps
->vars
[V_FOLDER_EXTENSION
]){
5559 mail_parameters(NULL
, SET_EXTENSION
,
5560 (void *)var
->current_val
.p
);
5562 else if(var
== &ps
->vars
[V_NEWSRC_PATH
]){
5563 if(var
->current_val
.p
&& var
->current_val
.p
[0])
5564 mail_parameters(NULL
, SET_NEWSRC
,
5565 (void *)var
->current_val
.p
);
5568 else if(revert
&& standard_radio_var(ps
, var
)){
5570 cur_rule_value(var
, TRUE
, FALSE
);
5571 if(var
== &ps_global
->vars
[V_AB_SORT_RULE
])
5572 addrbook_redo_sorts();
5573 else if(var
== &ps_global
->vars
[V_THREAD_INDEX_STYLE
]){
5574 clear_index_cache(ps_global
->mail_stream
, 0);
5575 set_lflags(ps_global
->mail_stream
, ps_global
->msgmap
,
5576 MN_COLL
| MN_CHID
, 0);
5577 if(SORT_IS_THREADED(ps_global
->msgmap
)
5578 && (SEP_THRDINDX() || COLL_THRDS()))
5579 collapse_threads(ps_global
->mail_stream
, ps_global
->msgmap
, NULL
);
5581 adjust_cur_to_visible(ps_global
->mail_stream
, ps_global
->msgmap
);
5584 else if(var
== &ps
->vars
[V_COLOR_STYLE
]){
5585 pico_toggle_color(0);
5586 switch(ps
->color_style
){
5589 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
5592 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
5595 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
5598 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
5602 if(ps
->color_style
!= COL_NONE
)
5603 pico_toggle_color(1);
5605 if(pico_usingcolor())
5606 pico_set_normal_color();
5608 clear_index_cache(ps_global
->mail_stream
, 0);
5610 ps
->mangled_screen
= 1;
5614 else if(revert
&& var
== &ps
->vars
[V_SORT_KEY
]){
5617 decode_sort(VAR_SORT_KEY
, &ps
->def_sort
, &def_sort_rev
);
5618 ps
->def_sort_rev
= def_sort_rev
;
5620 else if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5621 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5622 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5624 if(var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
] &&
5625 !(var
->current_val
.p
&& var
->current_val
.p
[0])){
5626 if(var
->current_val
.p
)
5627 fs_give((void **) &var
->current_val
.p
);
5629 q_status_message1(SM_ORDER
, 3, 5,
5630 _("\"%s\" can't be Empty, using default"), var
->name
);
5632 apval
= APVAL(var
, ew
);
5634 fs_give((void **)apval
);
5636 set_current_val(var
, FALSE
, FALSE
);
5638 if(!(var
->current_val
.p
&& var
->current_val
.p
[0]
5639 && !var
->current_val
.p
[1])){
5640 if(var
->current_val
.p
)
5641 fs_give((void **) &var
->current_val
.p
);
5643 var
->current_val
.p
= cpystr(DF_THREAD_LASTREPLY_CHAR
);
5647 if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5648 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5649 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5650 if(var
->current_val
.p
&& var
->current_val
.p
[0] &&
5651 var
->current_val
.p
[1]){
5652 q_status_message1(SM_ORDER
, 3, 5,
5653 "Only first character of \"%s\" is used",
5655 var
->current_val
.p
[1] = '\0';
5658 if(var
->main_user_val
.p
&& var
->main_user_val
.p
[0] &&
5659 var
->main_user_val
.p
[1])
5660 var
->main_user_val
.p
[1] = '\0';
5662 if(var
->post_user_val
.p
&& var
->post_user_val
.p
[0] &&
5663 var
->post_user_val
.p
[1])
5664 var
->post_user_val
.p
[1] = '\0';
5667 clear_index_cache(ps_global
->mail_stream
, 0);
5668 set_need_format_setup(ps_global
->mail_stream
);
5670 else if(var
== &ps
->vars
[V_NNTP_SERVER
]){
5671 free_contexts(&ps_global
->context_list
);
5672 init_folders(ps_global
);
5674 else if(var
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
]){
5677 else if(var
== &ps
->vars
[V_PRINTER
]){
5678 if(!revert
&& ps
->vars
[V_PERSONAL_PRINT_COMMAND
].is_fixed
){
5679 if(printer_value_check_and_adjust())
5680 q_status_message1(SM_ORDER
, 3, 5,
5681 _("Can't set \"%s\" to that value, see Setup/Printer"),
5682 pretty_var_name(var
->name
));
5685 else if(var
== &ps
->vars
[V_NORM_FORE_COLOR
] ||
5686 var
== &ps
->vars
[V_NORM_BACK_COLOR
] ||
5687 var
== &ps
->vars
[V_REV_FORE_COLOR
] ||
5688 var
== &ps
->vars
[V_REV_BACK_COLOR
] ||
5689 var
== &ps
->vars
[V_TITLE_FORE_COLOR
] ||
5690 var
== &ps
->vars
[V_TITLE_BACK_COLOR
] ||
5691 var
== &ps
->vars
[V_TITLECLOSED_FORE_COLOR
] ||
5692 var
== &ps
->vars
[V_TITLECLOSED_BACK_COLOR
] ||
5693 var
== &ps
->vars
[V_STATUS_FORE_COLOR
] ||
5694 var
== &ps
->vars
[V_STATUS_BACK_COLOR
] ||
5695 var
== &ps
->vars
[V_KEYLABEL_FORE_COLOR
] ||
5696 var
== &ps
->vars
[V_KEYLABEL_BACK_COLOR
] ||
5697 var
== &ps
->vars
[V_KEYNAME_FORE_COLOR
] ||
5698 var
== &ps
->vars
[V_KEYNAME_BACK_COLOR
]){
5699 set_current_color_vals(ps
);
5701 ps
->mangled_screen
= 1;
5703 else if(var
== &ps
->vars
[V_KW_COLORS
] ||
5704 var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
] ||
5705 var
== &ps
->vars
[V_IND_PLUS_FORE_COLOR
] ||
5706 var
== &ps
->vars
[V_IND_IMP_FORE_COLOR
] ||
5707 var
== &ps
->vars
[V_IND_DEL_FORE_COLOR
] ||
5708 var
== &ps
->vars
[V_IND_ANS_FORE_COLOR
] ||
5709 var
== &ps
->vars
[V_IND_NEW_FORE_COLOR
] ||
5710 var
== &ps
->vars
[V_IND_UNS_FORE_COLOR
] ||
5711 var
== &ps
->vars
[V_IND_HIPRI_FORE_COLOR
]||
5712 var
== &ps
->vars
[V_IND_LOPRI_FORE_COLOR
]||
5713 var
== &ps
->vars
[V_IND_ARR_FORE_COLOR
] ||
5714 var
== &ps
->vars
[V_IND_REC_FORE_COLOR
] ||
5715 var
== &ps
->vars
[V_IND_FWD_FORE_COLOR
] ||
5716 var
== &ps
->vars
[V_IND_OP_FORE_COLOR
] ||
5717 var
== &ps
->vars
[V_IND_FROM_FORE_COLOR
] ||
5718 var
== &ps
->vars
[V_IND_SUBJ_FORE_COLOR
] ||
5719 var
== &ps
->vars
[V_IND_PLUS_BACK_COLOR
] ||
5720 var
== &ps
->vars
[V_IND_IMP_BACK_COLOR
] ||
5721 var
== &ps
->vars
[V_IND_DEL_BACK_COLOR
] ||
5722 var
== &ps
->vars
[V_IND_ANS_BACK_COLOR
] ||
5723 var
== &ps
->vars
[V_IND_NEW_BACK_COLOR
] ||
5724 var
== &ps
->vars
[V_IND_UNS_BACK_COLOR
] ||
5725 var
== &ps
->vars
[V_IND_ARR_BACK_COLOR
] ||
5726 var
== &ps
->vars
[V_IND_REC_BACK_COLOR
] ||
5727 var
== &ps
->vars
[V_IND_FWD_BACK_COLOR
] ||
5728 var
== &ps
->vars
[V_IND_OP_BACK_COLOR
] ||
5729 var
== &ps
->vars
[V_IND_FROM_BACK_COLOR
] ||
5730 var
== &ps
->vars
[V_IND_SUBJ_BACK_COLOR
]){
5731 clear_index_cache(ps_global
->mail_stream
, 0);
5733 else if(var
== score_act_global_ptr
){
5736 score
= atoi(var
->current_val
.p
);
5737 if(score
< SCORE_MIN
|| score
> SCORE_MAX
){
5738 q_status_message2(SM_ORDER
, 3, 5,
5739 _("Score Value must be in range %s to %s"),
5740 comatose(SCORE_MIN
), comatose(SCORE_MAX
));
5741 apval
= APVAL(var
, ew
);
5743 fs_give((void **)apval
);
5745 set_current_val(var
, FALSE
, FALSE
);
5748 else if(var
== scorei_pat_global_ptr
|| var
== age_pat_global_ptr
5749 || var
== size_pat_global_ptr
|| var
== cati_global_ptr
){
5750 apval
= APVAL(var
, ew
);
5753 iv
= parse_intvl(*apval
);
5755 fs_give((void **) apval
);
5756 *apval
= stringform_of_intvl(iv
);
5760 fs_give((void **) apval
);
5763 set_current_val(var
, FALSE
, FALSE
);
5765 else if(var
== &ps
->vars
[V_FEATURE_LIST
]){
5766 process_feature_list(ps
, var
->current_val
.l
, 0, 0, 0);
5768 else if(!revert
&& (var
== &ps
->vars
[V_LAST_TIME_PRUNE_QUESTION
] ||
5769 var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
] ||
5770 var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
] ||
5771 var
== &ps
->vars
[V_USERINPUTTIMEO
] ||
5772 var
== &ps
->vars
[V_NEWS_ACTIVE_PATH
] ||
5773 var
== &ps
->vars
[V_NEWS_SPOOL_DIR
] ||
5774 var
== &ps
->vars
[V_INCOMING_FOLDERS
] ||
5775 var
== &ps
->vars
[V_FOLDER_SPEC
] ||
5776 var
== &ps
->vars
[V_NEWS_SPEC
] ||
5777 var
== &ps
->vars
[V_DISABLE_DRIVERS
] ||
5778 var
== &ps
->vars
[V_DISABLE_AUTHS
] ||
5779 #ifdef DF_ENCRYPTION_RANGE
5780 var
== &ps
->vars
[V_ENCRYPTION_RANGE
] ||
5781 #endif /* DF_ENCRYPTION_RANGE */
5782 #if !defined(_WINDOWS) || defined(ENABLE_WINDOWS_UNIXSSL_CERTS)
5783 var
== &ps
->vars
[V_SSLCAPATH
] ||
5784 var
== &ps
->vars
[V_SSLCAFILE
] ||
5785 var
== &ps
->vars
[V_USERSSLCAPATH
] ||
5786 var
== &ps
->vars
[V_USERSSLCAFILE
] ||
5787 var
== &ps
->vars
[V_SSLCIPHERS
] ||
5789 var
== &ps
->vars
[V_RSHPATH
] ||
5790 var
== &ps
->vars
[V_RSHCMD
] ||
5791 var
== &ps
->vars
[V_SSHCMD
] ||
5792 var
== &ps
->vars
[V_SSHPATH
])){
5793 q_status_message2(SM_ASYNC
, 0, 3,
5794 _("Changes%s%s will affect your next Alpine session."),
5795 var
->name
? " to " : "", var
->name
? var
->name
: "");
5798 if(!revert
&& (var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
5799 var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
5800 var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
5801 var
== &ps
->vars
[V_TCPQUERYTIMEO
] ||
5802 var
== &ps
->vars
[V_QUITQUERYTIMEO
] ||
5803 var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
5804 var
== &ps
->vars
[V_SSHOPENTIMEO
]))
5805 q_status_message(SM_ASYNC
, 0, 3,
5806 _("Timeout changes will affect your next Alpine session."));
5811 * Compare saved user_val with current user_val to see if it changed.
5812 * If any have changed, change it back and take the appropriate action.
5815 revert_to_saved_config(struct pine
*ps
, SAVED_CONFIG_S
*vsave
, int allow_hard_to_config_remotely
)
5817 struct variable
*vreal
;
5821 char *pval
, **apval
, **lval
, ***alval
;
5824 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5825 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5830 lval
= LVAL(vreal
, ew
);
5831 alval
= ALVAL(vreal
, ew
);
5833 if((v
->saved_user_val
.l
&& !lval
)
5834 || (!v
->saved_user_val
.l
&& lval
))
5836 else if(!v
->saved_user_val
.l
&& !lval
)
5837 ;/* no change, nothing to do */
5839 for(i
= 0; v
->saved_user_val
.l
[i
] || lval
[i
]; i
++)
5840 if((v
->saved_user_val
.l
[i
]
5842 || strcmp(v
->saved_user_val
.l
[i
], lval
[i
])))
5844 (!v
->saved_user_val
.l
[i
] && lval
[i
])){
5854 free_list_array(alval
);
5856 /* copy back the original one */
5857 if(v
->saved_user_val
.l
){
5858 list
= v
->saved_user_val
.l
;
5860 /* count how many */
5864 *alval
= (char **)fs_get((n
+1) * sizeof(char *));
5866 for(i
= 0; i
< n
; i
++)
5867 (*alval
)[i
] = cpystr(v
->saved_user_val
.l
[i
]);
5875 pval
= PVAL(vreal
, ew
);
5876 apval
= APVAL(vreal
, ew
);
5878 if((v
->saved_user_val
.p
&&
5879 (!pval
|| strcmp(v
->saved_user_val
.p
, pval
))) ||
5880 (!v
->saved_user_val
.p
&& pval
)){
5881 /* It changed, fix it */
5884 /* free the changed value */
5886 fs_give((void **)apval
);
5888 if(v
->saved_user_val
.p
)
5889 *apval
= cpystr(v
->saved_user_val
.p
);
5895 if(vreal
== &ps
->vars
[V_FEATURE_LIST
])
5896 set_feature_list_current_val(vreal
);
5898 set_current_val(vreal
, TRUE
, FALSE
);
5900 fix_side_effects(ps
, vreal
, 1);
5907 save_config_vars(struct pine
*ps
, int allow_hard_to_config_remotely
)
5909 struct variable
*vreal
;
5910 SAVED_CONFIG_S
*vsave
, *v
;
5912 vsave
= (SAVED_CONFIG_S
*)fs_get((V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5913 memset((void *)vsave
, 0, (V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5915 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5916 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5923 if(LVAL(vreal
, ew
)){
5924 /* count how many */
5926 list
= LVAL(vreal
, ew
);
5930 v
->saved_user_val
.l
= (char **)fs_get((n
+1) * sizeof(char *));
5931 memset((void *)v
->saved_user_val
.l
, 0, (n
+1)*sizeof(char *));
5932 for(i
= 0; i
< n
; i
++)
5933 v
->saved_user_val
.l
[i
] = cpystr(list
[i
]);
5935 v
->saved_user_val
.l
[n
] = NULL
;
5940 v
->saved_user_val
.p
= cpystr(PVAL(vreal
, ew
));
5949 free_saved_config(struct pine
*ps
, SAVED_CONFIG_S
**vsavep
, int allow_hard_to_config_remotely
)
5951 struct variable
*vreal
;
5954 if(vsavep
&& *vsavep
){
5955 for(v
= *vsavep
, vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5956 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5959 if(vreal
->is_list
){ /* free saved_user_val.l */
5960 if(v
&& v
->saved_user_val
.l
)
5961 free_list_array(&v
->saved_user_val
.l
);
5963 else if(v
&& v
->saved_user_val
.p
)
5964 fs_give((void **)&v
->saved_user_val
.p
);
5967 fs_give((void **)vsavep
);
5973 * Returns positive if any thing was actually deleted.
5976 delete_user_vals(struct variable
*v
)
5982 if(v
->post_user_val
.l
){
5984 free_list_array(&v
->post_user_val
.l
);
5986 if(v
->main_user_val
.l
){
5988 free_list_array(&v
->main_user_val
.l
);
5992 if(v
->post_user_val
.p
){
5994 fs_give((void **)&v
->post_user_val
.p
);
5996 if(v
->main_user_val
.p
){
5998 fs_give((void **)&v
->main_user_val
.p
);
6008 * ../pith/conf.c required function
6011 unexpected_pinerc_change(void)
6014 if(want_to("Unexpected pinerc change! Overwrite with current config",
6015 'n', 0, NO_HELP
, WT_FLUSH_IN
) == 'n'){
6016 return(-1); /* abort pinerc write */
6019 return(0); /* overwrite */
6025 /*----------------------------------------------------------------------
6026 MSWin scroll callback. Called during scroll message processing.
6030 Args: cmd - what type of scroll operation.
6031 scroll_pos - parameter for operation.
6032 used as position for SCROLL_TO operation.
6034 Returns: TRUE - did the scroll operation.
6035 FALSE - was not able to do the scroll operation.
6038 config_scroll_callback (cmd
, scroll_pos
)
6043 case MSWIN_KEY_SCROLLUPLINE
:
6044 config_scroll_down (scroll_pos
);
6047 case MSWIN_KEY_SCROLLDOWNLINE
:
6048 config_scroll_up (scroll_pos
);
6051 case MSWIN_KEY_SCROLLUPPAGE
:
6052 config_scroll_down (BODY_LINES(ps_global
));
6055 case MSWIN_KEY_SCROLLDOWNPAGE
:
6056 config_scroll_up (BODY_LINES(ps_global
));
6059 case MSWIN_KEY_SCROLLTO
:
6060 config_scroll_to_pos (scroll_pos
);
6064 option_screen_redrawer();
6070 #endif /* _WINDOWS */