1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: confscroll.c 1169 2008-08-27 06:42:06Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2020 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
20 #include "confscroll.h"
29 #include "colorconf.h"
36 #include "xoauth2conf.h"
37 #include "../pith/state.h"
38 #include "../pith/flag.h"
39 #include "../pith/list.h"
40 #include "../pith/conf.h"
41 #include "../pith/util.h"
42 #include "../pith/newmail.h"
43 #include "../pith/sort.h"
44 #include "../pith/thread.h"
45 #include "../pith/color.h"
46 #include "../pith/hist.h"
47 #include "../pith/icache.h"
48 #include "../pith/conf.h"
49 #include "../pith/init.h"
50 #include "../pith/folder.h"
51 #include "../pith/busy.h"
52 #include "../pith/tempfile.h"
53 #include "../pith/pattern.h"
54 #include "../pith/charconv/utf8.h"
57 #define CONFIG_SCREEN_HELP_TITLE _("HELP FOR SETUP CONFIGURATION")
59 /* TRANSLATORS: Empty Value is what is shown in the configuration
60 screen when the user not only does not set an option but also
61 wants to explicitly not use the default value. Empty value means
62 an option with no value. */
63 char *empty_val
= N_("Empty Value");
64 char *empty_val2
= N_("<Empty Value>");
65 /* TRANSLATORS: No Value set is similar to Empty Value, but the
66 user has not explicitly decided to not use the default. It is
67 just an option which the user has left at the default value. */
68 char *no_val
= N_("No Value Set");
69 /* TRANSLATORS: Value is Fixed is what is displayed in the config
70 screen when the system managers have set an option to a specific
71 value and they don't allow the user to change it. The value
72 is fixed to a certain value. This isn't the same word as
73 Repaired, it means Unchanging. */
74 char *fixed_val
= N_("Value is Fixed");
75 char yesstr
[] = "Yes";
82 OPT_SCREEN_S
*opt_screen
;
86 * This is pretty ugly. Some of the routines operate differently depending
87 * on which variable they are operating on. Sometimes those variables are
88 * global (real alpine.h V_ style variables) and sometimes they are just
89 * local variables (as in role_config_edit_screen). These pointers are here
90 * so that the routines can figure out which variable they are operating
91 * on and do the right thing.
93 struct variable
*score_act_global_ptr
,
94 *scorei_pat_global_ptr
,
121 typedef NAMEVAL_S
*(*PTR_TO_RULEFUNC
)(int);
125 * Internal prototypes
127 PTR_TO_RULEFUNC
rulefunc_from_var(struct pine
*, struct variable
*);
128 void set_radio_pretty_vals(struct pine
*, CONF_S
**);
129 int save_include(struct pine
*, struct variable
*, int);
130 void config_scroll_up(long);
131 void config_scroll_down(long);
132 void config_scroll_to_pos(long);
133 CONF_S
*config_top_scroll(struct pine
*, CONF_S
*);
134 void update_option_screen(struct pine
*, OPT_SCREEN_S
*, Pos
*);
135 void print_option_screen(OPT_SCREEN_S
*, char *);
136 void option_screen_redrawer(void);
137 char *text_pretty_value(struct pine
*, CONF_S
*);
138 char *checkbox_pretty_value(struct pine
*, CONF_S
*);
139 char *yesno_pretty_value(struct pine
*, CONF_S
*);
140 char *radio_pretty_value(struct pine
*, CONF_S
*);
141 char *sigfile_pretty_value(struct pine
*, CONF_S
*);
142 char *color_pretty_value(struct pine
*, CONF_S
*);
143 char *sort_pretty_value(struct pine
*, CONF_S
*);
144 int longest_feature_name(void);
145 COLOR_PAIR
*sample_color(struct pine
*, struct variable
*);
146 COLOR_PAIR
*sampleexc_color(struct pine
*, struct variable
*);
147 void clear_feature(char ***, char *);
148 CONF_S
*last_confline(CONF_S
*);
150 int config_scroll_callback(int, long);
155 * We test for this same set of vars in a few places.
158 standard_radio_var(struct pine
*ps
, struct variable
*v
)
160 return(v
== &ps
->vars
[V_SAVED_MSG_NAME_RULE
] ||
161 v
== &ps
->vars
[V_FCC_RULE
] ||
162 v
== &ps
->vars
[V_GOTO_DEFAULT_RULE
] ||
163 v
== &ps
->vars
[V_INCOMING_STARTUP
] ||
164 v
== &ps
->vars
[V_PRUNING_RULE
] ||
165 v
== &ps
->vars
[V_REOPEN_RULE
] ||
166 v
== &ps
->vars
[V_THREAD_DISP_STYLE
] ||
167 v
== &ps
->vars
[V_THREAD_INDEX_STYLE
] ||
168 v
== &ps
->vars
[V_FLD_SORT_RULE
] ||
170 v
== &ps
->vars
[V_COLOR_STYLE
] ||
172 v
== &ps
->vars
[V_INDEX_COLOR_STYLE
] ||
173 v
== &ps
->vars
[V_TITLEBAR_COLOR_STYLE
] ||
174 v
== &ps
->vars
[V_AB_SORT_RULE
]);
179 rulefunc_from_var(struct pine
*ps
, struct variable
*v
)
181 PTR_TO_RULEFUNC rulefunc
= NULL
;
183 if(v
== &ps
->vars
[V_SAVED_MSG_NAME_RULE
])
184 rulefunc
= save_msg_rules
;
185 else if(v
== &ps
->vars
[V_FCC_RULE
])
186 rulefunc
= fcc_rules
;
187 else if(v
== &ps
->vars
[V_GOTO_DEFAULT_RULE
])
188 rulefunc
= goto_rules
;
189 else if(v
== &ps
->vars
[V_INCOMING_STARTUP
])
190 rulefunc
= incoming_startup_rules
;
191 else if(v
== startup_ptr
)
192 rulefunc
= startup_rules
;
193 else if(v
== &ps
->vars
[V_PRUNING_RULE
])
194 rulefunc
= pruning_rules
;
195 else if(v
== &ps
->vars
[V_REOPEN_RULE
])
196 rulefunc
= reopen_rules
;
197 else if(v
== &ps
->vars
[V_THREAD_DISP_STYLE
])
198 rulefunc
= thread_disp_styles
;
199 else if(v
== &ps
->vars
[V_THREAD_INDEX_STYLE
])
200 rulefunc
= thread_index_styles
;
201 else if(v
== &ps
->vars
[V_FLD_SORT_RULE
])
202 rulefunc
= fld_sort_rules
;
203 else if(v
== &ps
->vars
[V_AB_SORT_RULE
])
204 rulefunc
= ab_sort_rules
;
205 else if(v
== &ps
->vars
[V_INDEX_COLOR_STYLE
])
206 rulefunc
= index_col_style
;
207 else if(v
== &ps
->vars
[V_TITLEBAR_COLOR_STYLE
])
208 rulefunc
= titlebar_col_style
;
210 else if(v
== &ps
->vars
[V_COLOR_STYLE
])
211 rulefunc
= col_style
;
219 standard_radio_setup(struct pine
*ps
, CONF_S
**cl
, struct variable
*v
, CONF_S
**first_line
)
223 PTR_TO_RULEFUNC rulefunc
;
230 rulefunc
= rulefunc_from_var(ps
, v
);
233 (*cl
)->flags
|= CF_NOSELECT
;
234 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
237 /* put a nice delimiter before list */
238 new_confline(cl
)->var
= NULL
;
239 (*cl
)->varnamep
= ctmpb
;
240 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
241 (*cl
)->help
= NO_HELP
;
242 (*cl
)->tool
= radiobutton_tool
;
243 (*cl
)->valoffset
= rindent
;
244 (*cl
)->flags
|= CF_NOSELECT
;
245 /* TRANSLATORS: Set and Rule Values are the headings for an option
246 that can take one of several values. Underneath the Set heading
247 will be a column where one possibility is turned on (is Set).
248 The other column will be very short descriptions of what
249 the possibilities are (the Rule Values). */
250 utf8_snprintf(b
, sizeof(b
), "%-5.5w %s", _("Set"), _("Rule Values"));
251 (*cl
)->value
= cpystr(b
);
253 new_confline(cl
)->var
= NULL
;
254 (*cl
)->varnamep
= ctmpb
;
255 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
256 (*cl
)->help
= NO_HELP
;
257 (*cl
)->tool
= radiobutton_tool
;
258 (*cl
)->valoffset
= rindent
;
259 (*cl
)->flags
|= CF_NOSELECT
;
260 (*cl
)->value
= cpystr("--- ----------------------");
263 for(i
= 0; (f
= (*rulefunc
)(i
)); i
++){
264 new_confline(cl
)->var
= v
;
265 if(first_line
&& !*first_line
&& !pico_usingcolor())
268 (*cl
)->varnamep
= ctmpb
;
269 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
270 (*cl
)->help
= (v
== startup_ptr
)
271 ? h_config_other_startup
272 : config_help(v
- ps
->vars
,0);
273 (*cl
)->tool
= radiobutton_tool
;
274 (*cl
)->valoffset
= rindent
;
276 (*cl
)->value
= pretty_value(ps
, *cl
);
282 * Reset the displayed values for all of the lines for this
283 * variable because others besides this line may change.
286 set_radio_pretty_vals(struct pine
*ps
, CONF_S
**cl
)
291 ((*cl
)->var
== &ps
->vars
[V_SORT_KEY
] ||
292 standard_radio_var(ps
, (*cl
)->var
) ||
293 (*cl
)->var
== startup_ptr
)))
298 ctmp
&& !(ctmp
->flags
& CF_NOSELECT
) && !ctmp
->varname
;
299 ctmp
= prev_confline(ctmp
)){
301 fs_give((void **)&ctmp
->value
);
303 ctmp
->value
= pretty_value(ps
, ctmp
);
308 ctmp
&& !ctmp
->varname
&& !(ctmp
->flags
& CF_NOSELECT
);
309 ctmp
= next_confline(ctmp
)){
311 fs_give((void **)&ctmp
->value
);
313 ctmp
->value
= pretty_value(ps
, ctmp
);
319 * test whether or not a var is
321 * returns: 1 if it should be excluded, 0 otw
324 exclude_config_var(struct pine
*ps
, struct variable
*var
, int allow_hard_to_config_remotely
)
326 if((ew
!= Main
&& (var
->is_onlymain
)) ||
327 (ew
!= ps_global
->ew_for_except_vars
&& var
->is_outermost
))
330 if(allow_hard_to_config_remotely
)
331 return(!(var
->is_user
&& var
->is_used
&& !var
->is_obsolete
));
333 switch(var
- ps
->vars
){
334 case V_HTML_DIRECTORY
:
335 case V_MAIL_DIRECTORY
:
336 case V_INCOMING_FOLDERS
:
339 case V_STANDARD_PRINTER
:
340 case V_LAST_TIME_PRUNE_QUESTION
:
341 case V_LAST_VERS_USED
:
343 case V_GLOB_ADDRBOOK
:
344 case V_DISABLE_DRIVERS
:
345 case V_DISABLE_AUTHS
:
346 case V_ENCRYPTION_RANGE
:
347 case V_REMOTE_ABOOK_METADATA
:
348 case V_REMOTE_ABOOK_HISTORY
:
349 case V_REMOTE_ABOOK_VALIDITY
:
351 case V_USERINPUTTIMEO
:
352 case V_TCPOPENTIMEO
:
353 case V_TCPREADWARNTIMEO
:
354 case V_TCPWRITEWARNTIMEO
:
355 case V_TCPQUERYTIMEO
:
356 case V_QUITQUERYTIMEO
:
359 case V_RSHOPENTIMEO
:
362 case V_SSHOPENTIMEO
:
363 case V_SENDMAIL_PATH
:
364 case V_NEW_VER_QUELL
:
373 case V_PERSONAL_PRINT_COMMAND
:
374 case V_PERSONAL_PRINT_CATEGORY
:
377 case V_WP_INDEXHEIGHT
:
378 case V_WP_INDEXLINES
:
383 case V_OLD_CHAR_SET
:
384 #endif /* ! _WINDOWS */
385 #if defined(DOS) || defined(OS2)
387 case V_UPLOAD_CMD_PREFIX
:
388 case V_DOWNLOAD_CMD
:
389 case V_DOWNLOAD_CMD_PREFIX
:
394 case V_FONT_CHAR_SET
:
395 case V_PRINT_FONT_NAME
:
396 case V_PRINT_FONT_SIZE
:
397 case V_PRINT_FONT_STYLE
:
398 case V_PRINT_FONT_CHAR_SET
:
399 case V_WINDOW_POSITION
:
400 case V_CURSOR_STYLE
:
401 #endif /* _WINDOWS */
404 case V_LDAP_SERVERS
:
405 #endif /* ENABLE_LDAP */
412 return(!(var
->is_user
&& var
->is_used
&& !var
->is_obsolete
&&
414 !smime_related_var(ps
, var
) &&
416 !color_related_var(ps
, var
)));
421 * Test to indicate what should be saved in case user wants to abandon
425 save_include(struct pine
*ps
, struct variable
*v
, int allow_hard_to_config_remotely
)
427 return(!exclude_config_var(ps
, v
, allow_hard_to_config_remotely
)
431 && (v
== &ps
->vars
[V_PERSONAL_PRINT_COMMAND
]
433 || v
== &ps
->vars
[V_LDAP_SERVERS
]
440 * Handles screen painting and motion. Passes other commands to
443 * Tool return values: Tools should return the following:
445 * -1 unrecognized command
446 * 1 something changed, conf_scroll_screen should remember that
447 * 2 tells conf_scroll_screen to return with value 1 or 0 depending
448 * on whether or not it has previously gotten a 1 from some tool.
449 * 3 tells conf_scroll_screen to return 1 (like 1 and 2 combined)
450 * ? Other tool-specific values can be used. They will cause
451 * conf_scroll_screen to return that value.
454 * 0 if nothing happened. That is, a tool returned 2 and we hadn't
455 * previously noted a return of 1
456 * 1 if something happened. That is, a tool returned 2 and we had
457 * previously noted a return of 1
458 * ? Tool-returned value different from -1, 0, 1, 2, or 3. This is it.
460 * Special proviso: If first_line->flags has CF_CHANGES set on entry, then
461 * that will cause things to behave like a change was made since entering
465 conf_scroll_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, CONF_S
*start_line
, char *title
, char *pdesc
, int multicol
, int *pos
)
470 int cmd
, i
, j
, done
= 0, changes
= 0;
472 int km_popped
= 0, stay_in_col
= 0;
473 struct key_menu
*km
= NULL
;
474 CONF_S
*ctmpa
= NULL
, *ctmpb
= NULL
;
476 OtherMenu what_keymenu
= FirstMenu
;
477 void (*prev_redrawer
)(void);
479 dprint((7, "conf_scroll_screen()\n"));
481 if(BODY_LINES(ps
) < 1){
482 q_status_message(SM_ORDER
| SM_DING
, 3, 3, _("Screen too small"));
486 if(screen
&& screen
->ro_warning
)
487 q_status_message1(SM_ORDER
, 1, 3,
488 /* TRANSLATORS: "Config file not changeable," is what replaces the %s */
489 _("%s can't change options or settings"),
490 ps_global
->restricted
? "Alpine demo"
491 : _("Config file not changeable,"));
493 screen
->current
= start_line
;
494 if(start_line
&& start_line
->flags
& CF_CHANGES
)
498 ps
->mangled_screen
= 1;
499 ps
->redrawer
= option_screen_redrawer
;
502 ps
->user_says_cancel
= 0;
507 ps
->mangled_body
= 1;
511 if(ps
->mangled_screen
){
512 ps
->mangled_header
= 1;
513 ps
->mangled_footer
= 1;
514 ps
->mangled_body
= 1;
515 ps
->mangled_screen
= 0;
518 /*----------- Check for new mail -----------*/
519 if(new_mail(0, NM_TIMING(ch
), NM_STATUS_MSG
| NM_DEFER_SORT
) >= 0)
520 ps
->mangled_header
= 1;
522 if(ps
->mangled_header
){
523 set_titlebar(title
, ps
->mail_stream
,
525 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
526 ps
->mangled_header
= 0;
529 update_option_screen(ps
, screen
, &cursor_pos
);
531 if(F_OFF(F_SHOW_CURSOR
, ps
)){
532 cursor_pos
.row
= ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
);
536 /*---- This displays new mail notification, or errors ---*/
539 mark_status_unknown();
545 mark_status_unknown();
548 if(ps
->mangled_footer
|| km
!= screen
->current
->keymenu
){
553 ps
->mangled_footer
= 0;
554 km
= screen
->current
->keymenu
;
557 (F_OFF(F_ARROW_NAV
, ps_global
) ||
558 F_ON(F_RELAXED_ARROW_NAV
, ps_global
))){
559 menu_clear_binding(km
, KEY_LEFT
);
560 menu_clear_binding(km
, KEY_RIGHT
);
561 menu_clear_binding(km
, KEY_UP
);
562 menu_clear_binding(km
, KEY_DOWN
);
563 menu_add_binding(km
, KEY_UP
, MC_CHARUP
);
564 menu_add_binding(km
, KEY_DOWN
, MC_CHARDOWN
);
565 menu_add_binding(km
, KEY_LEFT
, MC_PREVITEM
);
566 menu_add_binding(km
, ctrl('B'), MC_PREVITEM
);
567 menu_add_binding(km
, KEY_RIGHT
, MC_NEXTITEM
);
568 menu_add_binding(km
, ctrl('F'), MC_NEXTITEM
);
571 menu_clear_binding(km
, KEY_LEFT
);
572 menu_clear_binding(km
, KEY_RIGHT
);
573 menu_clear_binding(km
, KEY_UP
);
574 menu_clear_binding(km
, KEY_DOWN
);
577 * Fix up arrow nav mode if necessary...
579 if(F_ON(F_ARROW_NAV
, ps_global
)){
582 if((cmd
= menu_clear_binding(km
, '<')) != MC_UNKNOWN
){
583 menu_add_binding(km
, '<', cmd
);
584 menu_add_binding(km
, KEY_LEFT
, cmd
);
587 if((cmd
= menu_clear_binding(km
, '>')) != MC_UNKNOWN
){
588 menu_add_binding(km
, '>', cmd
);
589 menu_add_binding(km
, KEY_RIGHT
, cmd
);
592 if((cmd
= menu_clear_binding(km
, 'p')) != MC_UNKNOWN
){
593 menu_add_binding(km
, 'p', cmd
);
594 menu_add_binding(km
, KEY_UP
, cmd
);
597 if((cmd
= menu_clear_binding(km
, 'n')) != MC_UNKNOWN
){
598 menu_add_binding(km
, 'n', cmd
);
599 menu_add_binding(km
, KEY_DOWN
, cmd
);
609 draw_keymenu(km
, bitmap
, ps
->ttyo
->screen_cols
,
610 1-FOOTER_ROWS(ps
), 0, what_keymenu
);
611 what_keymenu
= SameMenu
;
615 mark_keymenu_dirty();
619 MoveCursor(cursor_pos
.row
, cursor_pos
.col
);
621 mouse_in_content(KEY_MOUSE
, -1, -1, 0, 0); /* prime the handler */
622 register_mfunc(mouse_in_content
, HEADER_ROWS(ps_global
), 0,
623 ps_global
->ttyo
->screen_rows
-(FOOTER_ROWS(ps_global
)+1),
624 ps_global
->ttyo
->screen_cols
);
627 mswin_setscrollcallback(config_scroll_callback
);
629 /*------ Read the command from the keyboard ----*/
630 ch
= READ_COMMAND(&utf8str
);
632 clear_mfunc(mouse_in_content
);
635 mswin_setscrollcallback(NULL
);
638 cmd
= menu_command(ch
, km
);
656 what_keymenu
= NextMenu
;
657 ps
->mangled_footer
= 1;
660 case MC_HELP
: /* help! */
661 if(FOOTER_ROWS(ps
) == 1 && km_popped
== 0){
663 ps
->mangled_footer
= 1;
667 if(screen
->current
->help
!= NO_HELP
){
668 prev_redrawer
= ps_global
->redrawer
;
669 helper(screen
->current
->help
,
670 (screen
->current
->help_title
)
671 ? screen
->current
->help_title
672 : CONFIG_SCREEN_HELP_TITLE
,
674 ps_global
->redrawer
= prev_redrawer
;
675 ps
->mangled_screen
= 1;
678 q_status_message(SM_ORDER
,0,3,_("No help yet."));
683 case MC_NEXTITEM
: /* next list element */
686 if(screen
->current
->flags
& CF_DOUBLEVAR
){
687 /* if going from col1 to col2, it's simple */
688 if(!(screen
->current
->flags
& CF_VAR2
) && cmd
== MC_NEXTITEM
){
689 screen
->current
->flags
|= CF_VAR2
;
693 /* otherwise we fall through to normal next */
694 stay_in_col
= (screen
->current
->flags
& CF_VAR2
&&
696 screen
->current
->flags
&= ~CF_VAR2
;
699 for(ctmpa
= next_confline(screen
->current
), i
= 1;
700 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
701 ctmpa
= next_confline(ctmpa
), i
++)
705 screen
->current
= ctmpa
;
706 if(screen
->current
->flags
& CF_DOUBLEVAR
&& stay_in_col
)
707 screen
->current
->flags
|= CF_VAR2
;
709 if(cmd
== MC_CHARDOWN
){
710 for(ctmpa
= screen
->top_line
,
711 j
= BODY_LINES(ps
) - 1 - HS_MARGIN(ps
);
712 j
> 0 && ctmpa
&& ctmpa
!= screen
->current
;
713 ctmpa
= next_confline(ctmpa
), j
--)
718 ctmpa
&& ctmpa
!= screen
->current
;
719 ctmpa
= next_confline(ctmpa
), i
++)
729 * Scroll screen a bit so we show the non-selectable
730 * lines at the bottom.
733 /* set ctmpa to the bottom line on the screen */
734 for(ctmpa
= screen
->top_line
, j
= BODY_LINES(ps
) - 1;
736 ctmpa
= next_confline(ctmpa
), j
--)
741 for(ctmpa
= next_confline(ctmpa
);
743 (ctmpa
->flags
& (CF_NOSELECT
| CF_B_LINE
)) ==
745 ctmpa
= next_confline(ctmpa
), i
++)
752 q_status_message(SM_ORDER
,0,1, _("Already at end of screen"));
757 case MC_PREVITEM
: /* prev list element */
760 if(screen
->current
->flags
& CF_DOUBLEVAR
){
761 if(screen
->current
->flags
& CF_VAR2
&& cmd
== MC_PREVITEM
){
762 screen
->current
->flags
&= ~CF_VAR2
;
766 /* otherwise we fall through to normal prev */
767 stay_in_col
= (!(screen
->current
->flags
& CF_VAR2
) &&
769 screen
->current
->flags
&= ~CF_VAR2
;
771 else if(cmd
== MC_CHARUP
)
774 ctmpa
= screen
->current
;
777 if(ctmpa
== config_top_scroll(ps
, screen
->top_line
))
781 while((ctmpa
= prev_confline(ctmpa
))
782 && (ctmpa
->flags
&CF_NOSELECT
));
785 screen
->current
= ctmpa
;
786 if(screen
->current
->flags
& CF_DOUBLEVAR
&& !stay_in_col
)
787 screen
->current
->flags
|= CF_VAR2
;
789 if((cmd
== MC_CHARUP
) && i
)
790 config_scroll_down(i
);
793 q_status_message(SM_ORDER
, 0, 1,
794 _("Already at start of screen"));
798 case MC_PAGEDN
: /* page forward */
799 screen
->current
->flags
&= ~CF_VAR2
;
800 for(ctmpa
= screen
->top_line
, i
= BODY_LINES(ps
);
802 ctmpb
= ctmpa
, ctmpa
= next_confline(ctmpa
), i
--)
805 if(ctmpa
){ /* first line off bottom of screen */
807 ps
->mangled_body
= 1;
808 /* find first selectable line on next page */
809 for(screen
->top_line
= ctmpa
;
810 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
811 ctmpa
= next_confline(ctmpa
))
815 * No selectable lines on next page. Slide up to first
819 for(ctmpa
= prev_confline(ctmpb
);
820 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
821 ctmpa
= prev_confline(ctmpa
))
825 screen
->top_line
= ctmpa
;
828 else{ /* on last screen */
829 /* just move current down to last entry on screen */
830 if(ctmpb
){ /* last line of data */
831 for(ctmpa
= ctmpb
, i
= BODY_LINES(ps
);
832 i
> 0 && ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
833 ctmpa
= prev_confline(ctmpa
), i
--)
836 if(ctmpa
== screen
->current
){
837 q_status_message(SM_ORDER
,0,1,
838 _("Already at end of screen"));
842 ps
->mangled_body
= 1;
847 screen
->current
= ctmpa
;
851 case MC_PAGEUP
: /* page backward */
852 ps
->mangled_body
= 1;
853 screen
->current
->flags
&= ~CF_VAR2
;
854 if(!(ctmpa
=prev_confline(screen
->top_line
)))
855 ctmpa
= screen
->current
;
857 for(i
= BODY_LINES(ps
) - 1;
858 i
> 0 && prev_confline(ctmpa
);
859 i
--, ctmpa
= prev_confline(ctmpa
))
862 for(screen
->top_line
= ctmpa
;
863 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
864 ctmpa
= next_confline(ctmpa
))
868 if(ctmpa
== screen
->current
){
870 * We get to here if there was nothing selectable on
871 * the previous page. There still may be something
872 * selectable further back than the previous page,
875 for(ctmpa
= prev_confline(screen
->top_line
);
876 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
877 ctmpa
= prev_confline(ctmpa
))
881 ctmpa
= screen
->current
;
882 q_status_message(SM_ORDER
, 0, 1,
883 _("Already at start of screen"));
887 screen
->current
= ctmpa
;
897 mouse_get_last (NULL
, &mp
);
898 mp
.row
-= HEADER_ROWS(ps
);
899 ctmpa
= screen
->top_line
;
901 while (mp
.row
&& ctmpa
!= NULL
) {
906 if (ctmpa
!= NULL
&& !(ctmpa
->flags
& CF_NOSELECT
)){
907 if(screen
->current
->flags
& CF_DOUBLEVAR
)
908 screen
->current
->flags
&= ~CF_VAR2
;
910 screen
->current
= ctmpa
;
912 if(screen
->current
->flags
& CF_DOUBLEVAR
&&
913 mp
.col
>= screen
->current
->val2offset
)
914 screen
->current
->flags
|= CF_VAR2
;
916 update_option_screen(ps
, screen
, &cursor_pos
);
918 if(mp
.button
== M_BUTTON_LEFT
&& mp
.doubleclick
){
920 if(screen
->current
->tool
){
924 flags
= screen
->current
->flags
;
925 flags
|= (changes
? CF_CHANGES
: 0);
927 default_cmd
= menu_command(ctrl('M'), km
);
928 switch(i
=(*screen
->current
->tool
)(ps
, default_cmd
,
929 &screen
->current
, flags
)){
956 else if(mp
.button
== M_BUTTON_RIGHT
) {
957 MPopup other_popup
[20];
959 struct key_menu
*sckm
= screen
->current
->keymenu
; /* only for popup */
961 if((cmd
= menu_command(ctrl('M'), sckm
)) != MC_UNKNOWN
){
962 i
= menu_binding_index(sckm
, cmd
);
963 other_popup
[++n
].type
= tQueue
;
964 other_popup
[n
].label
.style
= lNormal
;
965 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
966 other_popup
[n
].data
.val
= ctrl('M');
968 else if((cmd
= menu_command('>', sckm
)) != MC_UNKNOWN
){
969 i
= menu_binding_index(sckm
, cmd
);
970 other_popup
[++n
].type
= tQueue
;
971 other_popup
[n
].label
.style
= lNormal
;
972 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
973 other_popup
[n
].data
.val
= '>';
976 if(((i
= menu_binding_index(sckm
, MC_RGB1
)) >= 0) ||
977 ((i
= menu_binding_index(sckm
, MC_RGB2
)) >= 0)){
978 other_popup
[++n
].type
= tQueue
;
979 other_popup
[n
].label
.style
= lNormal
;
980 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
981 other_popup
[n
].data
.val
=
982 sckm
->keys
[i
].bind
.ch
[0];
985 if((cmd
= menu_command('<', sckm
)) != MC_UNKNOWN
){
986 i
= menu_binding_index(sckm
, cmd
);
987 other_popup
[++n
].type
= tQueue
;
988 other_popup
[n
].label
.style
= lNormal
;
989 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
990 other_popup
[n
].data
.val
= '<';
992 else if((i
= menu_binding_index(sckm
, MC_EXIT
)) >= 0){
993 other_popup
[++n
].type
= tQueue
;
994 other_popup
[n
].label
.style
= lNormal
;
995 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
996 other_popup
[n
].data
.val
=
997 sckm
->keys
[i
].bind
.ch
[0];
1000 if((i
= menu_binding_index(sckm
, MC_HELP
)) >= 0){
1002 other_popup
[++n
].type
= tSeparator
;
1004 other_popup
[++n
].type
= tQueue
;
1005 other_popup
[n
].label
.style
= lNormal
;
1006 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1007 other_popup
[n
].data
.val
= sckm
->keys
[i
].bind
.ch
[0];
1011 other_popup
[++n
].type
= tTail
;
1012 mswin_popup(other_popup
);
1016 else if(mp
.button
== M_BUTTON_RIGHT
) {
1017 MPopup other_popup
[20];
1019 struct key_menu
*sckm
= screen
->current
->keymenu
; /* only for popup */
1021 if((cmd
= menu_command('<', sckm
)) != MC_UNKNOWN
){
1022 i
= menu_binding_index(sckm
, cmd
);
1023 other_popup
[++n
].type
= tQueue
;
1024 other_popup
[n
].label
.style
= lNormal
;
1025 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1026 other_popup
[n
].data
.val
= '<';
1028 else if((i
= menu_binding_index(sckm
, MC_EXIT
)) >= 0){
1029 other_popup
[++n
].type
= tQueue
;
1030 other_popup
[n
].label
.style
= lNormal
;
1031 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1032 other_popup
[n
].data
.val
= sckm
->keys
[i
].bind
.ch
[0];
1035 other_popup
[++n
].type
= tTail
;
1038 mswin_popup(other_popup
);
1045 case MC_PRINTTXT
: /* print screen */
1046 print_option_screen(screen
, pdesc
? pdesc
: "");
1049 case MC_WHEREIS
: /* whereis */
1050 /*--- get string ---*/
1052 #define FOUND_IT 0x01
1053 #define FOUND_CURRENT 0x02
1054 #define FOUND_WRAPPED 0x04
1055 #define FOUND_NOSELECT 0x08
1056 #define FOUND_ABOVE 0x10
1057 char *result
= NULL
, buf
[64];
1059 static HISTORY_S
*history
= NULL
;
1061 static ESCKEY_S ekey
[] = {
1063 /* TRANSLATORS: go to Top of screen */
1064 {ctrl('Y'), 10, "^Y", N_("Top")},
1065 {ctrl('V'), 11, "^V", N_("Bottom")},
1066 {KEY_UP
, 30, "", ""},
1067 {KEY_DOWN
, 31, "", ""},
1068 {-1, 0, NULL
, NULL
}};
1069 #define KU_WI (3) /* index of KEY_UP */
1071 init_hist(&history
, HISTSIZE
);
1073 if((p
= get_prev_hist(history
, "", 0, NULL
)) != NULL
){
1074 strncpy(last
, p
, sizeof(last
));
1075 last
[sizeof(last
)-1] = '\0';
1078 ps
->mangled_footer
= 1;
1080 snprintf(tmp
, sizeof(tmp
), "Word to find %s%s%s: ",
1081 (last
[0]) ? "[" : "",
1082 (last
[0]) ? last
: "",
1083 (last
[0]) ? "]" : "");
1084 tmp
[sizeof(tmp
)-1] = '\0';
1087 int flags
= OE_APPEND_CURRENT
;
1090 * 2 is really 1 because there will be one real entry and
1091 * one entry of "" because of the get_prev_hist above.
1093 if(items_in_hist(history
) > 2){
1094 ekey
[KU_WI
].name
= HISTORY_UP_KEYNAME
;
1095 ekey
[KU_WI
].label
= HISTORY_KEYLABEL
;
1096 ekey
[KU_WI
+1].name
= HISTORY_DOWN_KEYNAME
;
1097 ekey
[KU_WI
+1].label
= HISTORY_KEYLABEL
;
1100 ekey
[KU_WI
].name
= "";
1101 ekey
[KU_WI
].label
= "";
1102 ekey
[KU_WI
+1].name
= "";
1103 ekey
[KU_WI
+1].label
= "";
1106 rc
= optionally_enter(buf
,-FOOTER_ROWS(ps
),0,sizeof(buf
),
1107 tmp
,ekey
,help
,&flags
);
1109 help
= help
== NO_HELP
? h_config_whereis
: NO_HELP
;
1111 if((p
= get_prev_hist(history
, buf
, 0, NULL
)) != NULL
){
1112 strncpy(buf
, p
, sizeof(buf
));
1113 buf
[sizeof(buf
)-1] = '\0';
1121 if((p
= get_next_hist(history
, buf
, 0, NULL
)) != NULL
){
1122 strncpy(buf
, p
, sizeof(buf
));
1123 buf
[sizeof(buf
)-1] = '\0';
1130 else if(rc
== 0 || rc
== 1 || rc
== 10 || rc
== 11 || !buf
[0]){
1131 if(rc
== 0 && !buf
[0] && last
[0])
1132 strncpy(buf
, last
, 64);
1138 screen
->current
->flags
&= ~CF_VAR2
;
1139 if(rc
== 0 && buf
[0]){
1140 CONF_S
*started_here
;
1142 save_hist(history
, buf
, 0, NULL
);
1145 ctmpa
= screen
->current
;
1147 * Skip over the unselectable lines of this "item"
1148 * before starting search so that we don't find the
1151 while((ctmpb
= next_confline(ctmpa
)) &&
1152 (ctmpb
->flags
& CF_NOSELECT
) &&
1153 !(ctmpb
->flags
& CF_STARTITEM
))
1156 started_here
= next_confline(ctmpa
);
1157 while((ctmpa
= next_confline(ctmpa
)) != NULL
)
1158 if(srchstr(ctmpa
->varname
, buf
)
1159 || srchstr(ctmpa
->value
, buf
)){
1163 * If this line is not selectable, back up to the
1164 * previous selectable line, but not past the
1165 * start of this "entry".
1167 if(ctmpa
->flags
& CF_NOSELECT
)
1168 found
|= FOUND_NOSELECT
;
1170 while((ctmpa
->flags
& CF_NOSELECT
) &&
1171 !(ctmpa
->flags
& CF_STARTITEM
) &&
1172 (ctmpb
= prev_confline(ctmpa
)))
1176 * If that isn't selectable, better search forward
1177 * for something that is.
1179 while((ctmpa
->flags
& CF_NOSELECT
) &&
1180 (ctmpb
= next_confline(ctmpa
))){
1182 found
|= FOUND_ABOVE
;
1186 * If that still isn't selectable, better search
1187 * backwards for something that is.
1189 while((ctmpa
->flags
& CF_NOSELECT
) &&
1190 (ctmpb
= prev_confline(ctmpa
))){
1192 found
&= ~FOUND_ABOVE
;
1199 found
= FOUND_WRAPPED
;
1200 ctmpa
= first_confline(screen
->current
);
1202 while(ctmpa
!= started_here
)
1203 if(srchstr(ctmpa
->varname
, buf
)
1204 || srchstr(ctmpa
->value
, buf
)){
1207 if(ctmpa
->flags
& CF_NOSELECT
)
1208 found
|= FOUND_NOSELECT
;
1210 while((ctmpa
->flags
& CF_NOSELECT
) &&
1211 !(ctmpa
->flags
& CF_STARTITEM
) &&
1212 (ctmpb
= prev_confline(ctmpa
)))
1215 while((ctmpa
->flags
& CF_NOSELECT
) &&
1216 (ctmpb
= next_confline(ctmpa
))){
1218 found
|= FOUND_ABOVE
;
1221 if(ctmpa
== screen
->current
)
1222 found
|= FOUND_CURRENT
;
1227 ctmpa
= next_confline(ctmpa
);
1231 screen
->current
= first_confline(screen
->current
);
1232 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1233 for(ctmpa
= next_confline(screen
->current
);
1234 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1235 ctmpa
= next_confline(ctmpa
))
1239 screen
->current
= ctmpa
;
1242 /* TRANSLATORS: Searched to ... is the result of the search, searched
1243 to top means the search went past the bottom of the screen and
1244 wrapped back around to the top. */
1245 result
= _("Searched to top");
1248 screen
->current
= last_confline(screen
->current
);
1249 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1250 for(ctmpa
= prev_confline(screen
->current
);
1251 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1252 ctmpa
= prev_confline(ctmpa
))
1256 screen
->current
= ctmpa
;
1259 result
= _("Searched to bottom");
1262 result
= _("WhereIs cancelled");
1264 if((found
& FOUND_IT
) && ctmpa
){
1265 strncpy(last
, buf
, 64);
1267 (found
& FOUND_CURRENT
&& found
& FOUND_WRAPPED
&& found
& FOUND_NOSELECT
)
1268 ? _("Current item contains the only match")
1269 : (found
& FOUND_CURRENT
&& found
& FOUND_WRAPPED
)
1270 ? _("Current line contains the only match")
1271 : (found
& FOUND_NOSELECT
&& found
& FOUND_WRAPPED
)
1272 ? ((found
& FOUND_ABOVE
)
1273 ? _("Search wrapped: word found in text above current line")
1274 : _("Search wrapped: word found in text below current line"))
1275 : (found
& FOUND_WRAPPED
)
1276 ? _("Search wrapped to beginning: word found")
1277 : (found
& FOUND_NOSELECT
)
1278 ? ((found
& FOUND_ABOVE
)
1279 ? _("Word found in text above current line")
1280 : _("Word found in text below current line"))
1282 screen
->current
= ctmpa
;
1285 q_status_message(SM_ORDER
,0,3,result
? result
: _("Word not found"));
1291 screen
->current
= first_confline(screen
->current
);
1292 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1293 for(ctmpa
= next_confline(screen
->current
);
1294 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1295 ctmpa
= next_confline(ctmpa
))
1299 screen
->current
= ctmpa
;
1302 q_status_message(SM_ORDER
,0,3, _("Moved to top"));
1306 screen
->current
= last_confline(screen
->current
);
1307 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1308 for(ctmpa
= prev_confline(screen
->current
);
1309 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1310 ctmpa
= prev_confline(ctmpa
))
1314 screen
->current
= ctmpa
;
1317 q_status_message(SM_ORDER
,0,3, _("Moved to bottom"));
1320 case MC_XSHELP
: /* help! */
1321 if(FOOTER_ROWS(ps
) == 1 && km_popped
== 0){
1323 ps
->mangled_footer
= 1;
1327 prev_redrawer
= ps_global
->redrawer
;
1328 helper(h_xoauth2_config_screen
, "XOAUTH2 CONFIGURATION SCREEN", HLPD_SIMPLE
);
1329 ps_global
->redrawer
= prev_redrawer
;
1330 ps
->mangled_screen
= 1;
1333 case MC_XSDELETE
: /* Send caller to delete XOAUTH2 info */
1334 case MC_XSADD
: /* Send caller to add XOAUTH2 info */
1336 *pos
= get_confline_number(screen
->current
);
1338 retval
= cmd
== MC_XSADD
? 4 : 5;
1342 case MC_REPAINT
: /* redraw the display */
1345 ps
->mangled_screen
= 1;
1347 *pos
= get_confline_number(screen
->current
);
1354 if(screen
&& screen
->ro_warning
){
1360 q_status_message1(SM_ORDER
|SM_DING
, 1, 3,
1361 _("%s can't change options or settings"),
1362 ps_global
->restricted
? "Alpine demo"
1363 : _("Config file not changeable,"));
1365 else if(screen
->current
->tool
){
1368 flags
= screen
->current
->flags
;
1369 flags
|= (changes
? CF_CHANGES
: 0);
1371 switch(i
=(*screen
->current
->tool
)(ps
, cmd
,
1372 &screen
->current
, flags
)){
1374 q_status_message2(SM_ORDER
, 0, 2,
1375 /* TRANSLATORS: Command <command letter> not defined here.
1376 Leave the trailing %s which might be a parenthetical
1378 _("Command \"%s\" not defined here.%s"),
1380 F_ON(F_BLANK_KEYMENU
,ps
) ? "" : " See key menu below.");
1410 bogus_utf8_command(utf8str
, "?");
1413 case MC_NONE
: /* simple timeout */
1418 screen
->current
= first_confline(screen
->current
);
1419 free_conflines(&screen
->current
);
1428 config_scroll_up(long int n
)
1430 CONF_S
*ctmp
= opt_screen
->top_line
;
1434 config_scroll_down(-n
);
1436 for(; n
>0 && ctmp
->next
; n
--){
1437 ctmp
= next_confline(ctmp
);
1438 if(prev_confline(ctmp
) == opt_screen
->current
)
1442 opt_screen
->top_line
= ctmp
;
1443 ps_global
->mangled_body
= 1;
1445 for(ctmp
= opt_screen
->top_line
;
1446 ctmp
&& (ctmp
->flags
& CF_NOSELECT
);
1447 ctmp
= next_confline(ctmp
))
1451 opt_screen
->current
= opt_screen
->prev
= ctmp
;
1453 while(opt_screen
->top_line
->flags
& CF_NOSELECT
)
1454 opt_screen
->top_line
= prev_confline(opt_screen
->top_line
);
1455 opt_screen
->current
= opt_screen
->prev
= opt_screen
->top_line
;
1463 * config_scroll_down -
1466 config_scroll_down(long int n
)
1468 CONF_S
*ctmp
= opt_screen
->top_line
, *last_sel
= NULL
;
1472 config_scroll_up(-n
);
1474 for(; n
>0 && ctmp
->prev
; n
--)
1475 ctmp
= prev_confline(ctmp
);
1477 opt_screen
->top_line
= ctmp
;
1478 ps_global
->mangled_body
= 1;
1479 for(ctmp
= opt_screen
->top_line
, i
= BODY_LINES(ps_global
);
1480 i
> 0 && ctmp
&& ctmp
!= opt_screen
->current
;
1481 ctmp
= next_confline(ctmp
), i
--)
1482 if(!(ctmp
->flags
& CF_NOSELECT
))
1486 opt_screen
->current
= opt_screen
->prev
= last_sel
;
1492 * config_scroll_to_pos -
1495 config_scroll_to_pos(long int n
)
1499 for(ctmp
= first_confline(opt_screen
->current
);
1500 n
&& ctmp
&& ctmp
!= opt_screen
->top_line
;
1501 ctmp
= next_confline(ctmp
), n
--)
1505 while(ctmp
&& ctmp
!= opt_screen
->top_line
)
1506 if((ctmp
= next_confline(ctmp
)) != NULL
)
1509 config_scroll_up(n
);
1514 * config_top_scroll - return pointer to the
1517 config_top_scroll(struct pine
*ps
, CONF_S
*topline
)
1522 for(ctmp
= topline
, i
= HS_MARGIN(ps
);
1524 ctmp
= next_confline(ctmp
), i
--)
1527 return(ctmp
? ctmp
: topline
);
1532 text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
1534 return(text_toolit(ps
, cmd
, cl
, flags
, 0));
1539 * simple text variable handler
1541 * note, things get a little involved due to the
1542 * screen struct <--> variable mapping. (but, once its
1543 * running it shouldn't need changing ;).
1545 * look_for_backslash == 1 means that backslash is an escape character.
1546 * In particular, \, can be used to put a literal comma
1547 * into a value. The value will still have the backslash
1548 * in it, but the comma after the backslash won't be treated
1549 * as an item separator.
1551 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
1552 * returns what conf_exit_cmd returns for exit command.
1555 text_toolit(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
, int look_for_backslash
)
1557 char prompt
[81], *sval
, *tmp
, *swap_val
, **newval
= NULL
;
1558 char *pval
, **apval
, **lval
, ***alval
;
1559 char *olddefval
= NULL
;
1560 int rv
= 0, skip_to_next
= 0, after
= 0, i
= 4, j
, k
;
1561 int lowrange
, hirange
, incr
, oeflags
, oebufsize
;
1562 int numval
, repeat_key
= 0;
1563 int curindex
, previndex
, nextindex
, deefault
;
1567 if((*cl
)->var
->is_list
){
1568 lval
= LVAL((*cl
)->var
, ew
);
1569 alval
= ALVAL((*cl
)->var
, ew
);
1572 pval
= PVAL((*cl
)->var
, ew
);
1573 apval
= APVAL((*cl
)->var
, ew
);
1576 oebufsize
= 6*MAXPATH
;
1577 sval
= (char *) fs_get(oebufsize
*sizeof(char));
1580 if(flags
&CF_NUMBER
){ /* only happens if !is_list */
1582 if((*cl
)->var
== &ps
->vars
[V_FILLCOL
]){
1584 hirange
= MAX_FILLCOL
;
1586 else if((*cl
)->var
== &ps
->vars
[V_OVERLAP
]
1587 || (*cl
)->var
== &ps
->vars
[V_MARGIN
]){
1591 else if((*cl
)->var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
1592 lowrange
= -(Q_SUPP_LIMIT
-1);
1595 else if((*cl
)->var
== &ps
->vars
[V_MAXREMSTREAM
]){
1599 else if((*cl
)->var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
1603 else if((*cl
)->var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
1607 else if((*cl
)->var
== &ps
->vars
[V_MAILCHECK
] ||
1608 (*cl
)->var
== &ps
->vars
[V_INCCHECKINTERVAL
] ||
1609 (*cl
)->var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
] ||
1610 (*cl
)->var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
1615 else if((*cl
)->var
== &ps
->vars
[V_DEADLETS
]){
1619 else if((*cl
)->var
== &ps
->vars
[V_NMW_WIDTH
]){
1621 hirange
= MAX_SCREEN_COLS
;
1623 else if((*cl
)->var
== score_act_global_ptr
){
1627 else if((*cl
)->var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
1628 (*cl
)->var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
1629 (*cl
)->var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
1633 else if((*cl
)->var
== &ps
->vars
[V_QUITQUERYTIMEO
]){
1637 else if((*cl
)->var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
1638 (*cl
)->var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
1639 (*cl
)->var
== &ps
->vars
[V_SSHOPENTIMEO
] ||
1640 (*cl
)->var
== &ps
->vars
[V_USERINPUTTIMEO
]){
1644 else if((*cl
)->var
== &ps
->vars
[V_INCCHECKTIMEO
]){
1648 else if((*cl
)->var
== &ps
->vars
[V_MAILDROPCHECK
]){
1653 else if((*cl
)->var
== &ps
->vars
[V_NNTPRANGE
]){
1658 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
]){
1662 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
]){
1666 else if((*cl
)->var
== cat_lim_global_ptr
){
1679 ekey
[1].ch
= ctrl('P');
1680 ekey
[1].rval
= ctrl('P');
1681 ekey
[1].name
= "^P";
1682 ekey
[1].label
= N_("Decrease");
1683 ekey
[2].ch
= ctrl('N');
1684 ekey
[2].rval
= ctrl('N');
1685 ekey
[2].name
= "^N";
1686 ekey
[2].label
= N_("Increase");
1687 ekey
[3].ch
= KEY_DOWN
;
1688 ekey
[3].rval
= ctrl('P');
1691 ekey
[4].ch
= KEY_UP
;
1692 ekey
[4].rval
= ctrl('N');
1699 case MC_ADD
: /* add to list */
1700 if(fixed_var((*cl
)->var
, "add to", NULL
)){
1703 else if(!(*cl
)->var
->is_list
&& pval
){
1704 q_status_message(SM_ORDER
, 3, 3,
1705 _("Only single value allowed. Use \"Change\"."));
1711 if((*cl
)->var
->is_list
1712 && lval
&& lval
[0] && lval
[0][0]
1715 /* regular add to an existing list */
1717 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1718 tmpval
[sizeof(tmpval
)-1] = '\0';
1719 removing_trailing_white_space(tmpval
);
1721 /* 33 is the number of chars other than the value */
1722 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1723 k
= MIN(18, MAX(maxwidth
-33,0));
1724 if(utf8_width(tmpval
) > k
&& k
>= 3){
1725 (void) utf8_truncate(tmpval
, k
-3);
1726 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1727 tmpval
[sizeof(tmpval
)-1] = '\0';
1730 utf8_snprintf(prompt
, sizeof(prompt
),
1731 _("Enter text to insert before \"%.*w\": "), k
, tmpval
);
1732 prompt
[sizeof(prompt
)-1] = '\0';
1734 else if((*cl
)->var
->is_list
1736 && (*cl
)->var
->current_val
.l
){
1737 /* Add to list which doesn't exist, but default does exist */
1741 ekey
[0].label
= N_("Replace");
1745 ekey
[1].label
= N_("Add To");
1747 strncpy(prompt
, _("Replace or Add To default value ? "), sizeof(prompt
));
1748 prompt
[sizeof(prompt
)-1] = '\0';
1749 switch(radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, 'a', 'x',
1750 h_config_replace_add
, RB_NORM
)){
1753 for(j
= 0; (*cl
)->var
->current_val
.l
[j
]; j
++){
1754 sstrncpy(&p
, (*cl
)->var
->current_val
.l
[j
], oebufsize
-(p
-sval
));
1755 if(oebufsize
-(p
-sval
) > 2){
1760 if(oebufsize
-(p
-sval
) > 0)
1764 sval
[oebufsize
-1] = '\0';
1767 if(flags
& CF_NUMBER
)
1768 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1770 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1777 strncpy(sval
, olddefval
, oebufsize
);
1778 sval
[oebufsize
-1] = '\0';
1781 if(flags
& CF_NUMBER
)
1782 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric replacement text : "));
1784 snprintf(prompt
, sizeof(prompt
), _("Enter the replacement text : "));
1790 cmd_cancelled("Add");
1795 if(flags
& CF_NUMBER
)
1796 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1798 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1801 prompt
[sizeof(prompt
)-1] = '\0';
1803 ps
->mangled_footer
= 1;
1810 if((*cl
)->var
->is_list
1811 && lval
&& lval
[0] && lval
[0][0]
1813 ekey
[0].ch
= ctrl('W');
1815 ekey
[0].name
= "^W";
1816 /* TRANSLATORS: Insert new item before current item */
1817 ekey
[0].label
= after
? N_("InsertBefore") : N_("InsertAfter");
1820 else if(!(flags
&CF_NUMBER
))
1823 oeflags
= OE_APPEND_CURRENT
;
1824 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
1826 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
1830 if((*cl
)->var
->is_list
)
1831 ps
->mangled_body
= 1;
1833 ps
->mangled_footer
= 1;
1835 removing_leading_and_trailing_white_space(sval
);
1837 * Coerce "" and <Empty Value> to empty string input.
1838 * Catch <No Value Set> as a substitute for deleting.
1840 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
1841 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
1843 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
1845 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
1847 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
1850 if((*cl
)->var
->is_list
){
1856 for(tmp
= sval
; *tmp
; tmp
++)
1858 i
++; /* conservative count of ,'s */
1861 ltmp
= (char **)fs_get(2 * sizeof(char *));
1862 ltmp
[0] = cpystr(sval
);
1866 ltmp
= parse_list(sval
, i
+ 1,
1868 ? PL_COMMAQUOTE
: 0,
1872 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
1877 q_status_message1(SM_ORDER
, 0, 3,
1878 _("Can't add %s to list"), _(empty_val
));
1879 rv
= ps
->mangled_body
= 0;
1882 fs_give((void **)<mp
);
1885 q_status_message1(SM_ORDER
, 0, 3,
1886 _("Can't add %s to list"), _(empty_val
));
1890 if(flags
&CF_NUMBER
&& sval
[0]
1891 && !(isdigit((unsigned char)sval
[0])
1892 || sval
[0] == '-' || sval
[0] == '+')){
1893 q_status_message(SM_ORDER
,3,3,
1894 _("Entry must be numeric"));
1895 i
= 3; /* to keep loop going */
1900 fs_give((void **)apval
);
1902 if(!(olddefval
&& !strcmp(sval
, olddefval
))
1903 || ((*cl
)->var
== &ps
->vars
[V_POST_CHAR_SET
])
1904 || want_to(_("Leave unset and use default "),
1905 'y', 'y', NO_HELP
, WT_FLUSH_IN
) == 'n')
1906 *apval
= cpystr(sval
);
1908 newval
= &(*cl
)->value
;
1912 cmd_cancelled("Add");
1915 help
= help
== NO_HELP
? h_config_add
: NO_HELP
;
1918 else if(i
== 4){ /* no redraw, yet */
1921 else if(i
== 5){ /* change from/to prepend to/from append */
1924 after
= after
? 0 : 1;
1925 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1926 tmpval
[sizeof(tmpval
)-1] = '\0';
1927 removing_trailing_white_space(tmpval
);
1928 /* 33 is the number of chars other than the value */
1929 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1930 k
= MIN(18, MAX(maxwidth
-33,0));
1931 if(utf8_width(tmpval
) > k
&& k
>= 3){
1932 (void) utf8_truncate(tmpval
, k
-3);
1933 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1934 tmpval
[sizeof(tmpval
)-1] = '\0';
1938 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert after \"%.*s\": "), k
, tmpval
);
1940 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert before \"%.*s\": "), k
, tmpval
);
1944 else if(i
== ctrl('P')){
1946 numval
= atoi(sval
);
1949 numval
= atoi(pval
);
1951 numval
= lowrange
+ 1;
1954 if(numval
== lowrange
){
1956 * Protect user from repeating arrow key that
1957 * causes message to appear over and over.
1959 if(++repeat_key
> 0){
1960 q_status_message1(SM_ORDER
,3,3,
1961 _("Minimum value is %s"), comatose(lowrange
));
1968 numval
= MAX(numval
- incr
, lowrange
);
1969 snprintf(sval
, oebufsize
, "%d", numval
);
1970 sval
[oebufsize
-1] = '\0';
1973 else if(i
== ctrl('N')){
1975 numval
= atoi(sval
);
1978 numval
= atoi(pval
);
1980 numval
= lowrange
+ 1;
1983 if(numval
== hirange
){
1984 if(++repeat_key
> 0){
1985 q_status_message1(SM_ORDER
,3,3,
1986 _("Maximum value is %s"), comatose(hirange
));
1993 numval
= MIN(numval
+ incr
, hirange
);
1994 snprintf(sval
, oebufsize
, "%d", numval
);
1995 sval
[oebufsize
-1] = '\0';
2005 case MC_DELETE
: /* delete */
2007 if(!(*cl
)->var
->is_list
2009 && (*cl
)->var
->current_val
.p
){
2012 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
2013 pmt
[sizeof(pmt
)-1] = '\0';
2014 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2016 *apval
= cpystr(sval
);
2017 newval
= &(*cl
)->value
;
2018 rv
= ps
->mangled_footer
= 1;
2021 else if((*cl
)->var
->is_list
2023 && (*cl
)->var
->current_val
.l
){
2026 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
2027 pmt
[sizeof(pmt
)-1] = '\0';
2028 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2032 ltmp
= (char **)fs_get(2 * sizeof(char *));
2033 ltmp
[0] = cpystr(sval
);
2035 config_add_list(ps
, cl
, ltmp
, &newval
, 0);
2036 fs_give((void **)<mp
);
2037 rv
= ps
->mangled_body
= 1;
2040 else if(((*cl
)->var
->is_list
&& !lval
)
2041 || (!(*cl
)->var
->is_list
&& !pval
)){
2042 q_status_message(SM_ORDER
, 0, 3, _("No set value to delete"));
2045 if((*cl
)->var
->is_fixed
)
2046 snprintf(prompt
, sizeof(prompt
), _("Delete (unused) %s from %s "),
2048 ? (!*lval
[(*cl
)->varmem
])
2050 : lval
[(*cl
)->varmem
]
2058 snprintf(prompt
, sizeof(prompt
), _("Really delete %s%s from %s "),
2059 (*cl
)->var
->is_list
? "item " : "",
2061 ? int2string((*cl
)->varmem
+ 1)
2069 prompt
[sizeof(prompt
)-1] = '\0';
2072 ps
->mangled_footer
= 1;
2073 if(want_to(prompt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2075 if((*cl
)->var
->is_list
)
2076 ps
->mangled_body
= 1;
2078 ps
->mangled_footer
= 1;
2080 if((*cl
)->var
->is_list
){
2081 if(lval
[(*cl
)->varmem
])
2082 fs_give((void **)&lval
[(*cl
)->varmem
]);
2084 config_del_list_item(cl
, &newval
);
2088 fs_give((void **)apval
);
2090 newval
= &(*cl
)->value
;
2094 q_status_message(SM_ORDER
, 0, 3, _("Value not deleted"));
2099 case MC_EDIT
: /* edit/change list option */
2100 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2103 else if(((*cl
)->var
->is_list
2105 && (*cl
)->var
->current_val
.l
)
2107 (!(*cl
)->var
->is_list
2109 && (*cl
)->var
->current_val
.p
)){
2112 * In non-list case, offer default value for editing.
2114 if(!(*cl
)->var
->is_list
2115 && (*cl
)->var
!= &ps
->vars
[V_REPLY_INTRO
]
2116 && (*cl
)->var
->current_val
.p
[0]
2117 && strcmp(VSTRING
,(*cl
)->var
->current_val
.p
)){
2121 olddefval
= (char *) fs_get(strlen((*cl
)->var
->current_val
.p
)+3);
2123 if(!strncmp((*cl
)->var
->current_val
.p
,
2125 (len
=strlen(DSTRING
)))){
2126 /* strip DSTRING and trailing paren */
2127 strncpy(olddefval
, (*cl
)->var
->current_val
.p
+len
,
2128 strlen((*cl
)->var
->current_val
.p
)-len
-1);
2129 olddefval
[strlen((*cl
)->var
->current_val
.p
)-len
-1] = '\0';
2132 /* quote it if there are trailing spaces */
2133 quote_it
= ((*cl
)->var
->current_val
.p
[strlen((*cl
)->var
->current_val
.p
)-1] == SPACE
);
2134 snprintf(olddefval
, strlen((*cl
)->var
->current_val
.p
)+3, "%s%s%s", quote_it
? "\"" : "", (*cl
)->var
->current_val
.p
, quote_it
? "\"" : "");
2137 olddefval
[strlen((*cl
)->var
->current_val
.p
)+3-1] = '\0';
2142 else if(((*cl
)->var
->is_list
2144 && !(*cl
)->var
->current_val
.l
)
2146 (!(*cl
)->var
->is_list
2148 && !(*cl
)->var
->current_val
.p
)){
2156 fs_give((void **)&sval
);
2157 if((*cl
)->var
->is_list
){
2158 snprintf(prompt
, sizeof(prompt
), _("Change field %s list entry : "),
2160 prompt
[sizeof(prompt
)-1] = '\0';
2161 clptr
= lval
[(*cl
)->varmem
] ? lval
[(*cl
)->varmem
] : NULL
;
2164 if(flags
& CF_NUMBER
)
2165 snprintf(prompt
, sizeof(prompt
), _("Change numeric field %s value : "), (*cl
)->var
->name
);
2167 snprintf(prompt
, sizeof(prompt
), _("Change field %s value : "), (*cl
)->var
->name
);
2169 clptr
= pval
? pval
: NULL
;
2172 oebufsize
= clptr
? (int) MAX(MAXPATH
, 50+strlen(clptr
)) : MAXPATH
;
2173 sval
= (char *) fs_get(oebufsize
* sizeof(char));
2174 snprintf(sval
, oebufsize
, "%s", clptr
? clptr
: "");
2175 sval
[oebufsize
-1] = '\0';
2177 ps
->mangled_footer
= 1;
2180 if(!(flags
&CF_NUMBER
))
2183 oeflags
= OE_APPEND_CURRENT
;
2184 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
2186 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
2189 removing_leading_and_trailing_white_space(sval
);
2191 * Coerce "" and <Empty Value> to empty string input.
2192 * Catch <No Value Set> as a substitute for deleting.
2194 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
2195 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
2197 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
2199 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
2201 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
2205 if((*cl
)->var
->is_list
)
2206 ps
->mangled_body
= 1;
2208 ps
->mangled_footer
= 1;
2210 if((*cl
)->var
->is_list
){
2214 if(lval
[(*cl
)->varmem
])
2215 fs_give((void **)&lval
[(*cl
)->varmem
]);
2218 for(tmp
= sval
; *tmp
; tmp
++)
2220 i
++; /* conservative count of ,'s */
2223 ltmp
= parse_list(sval
, i
+ 1,
2225 ? PL_COMMAQUOTE
: 0,
2228 if(ltmp
&& !ltmp
[0]) /* only commas */
2230 else if(!i
|| (ltmp
&& !ltmp
[1])){ /* only one item */
2231 lval
[(*cl
)->varmem
] = cpystr(sval
);
2232 newval
= &(*cl
)->value
;
2235 fs_give((void **)<mp
[0]);
2239 * Looks like the value was changed to a
2240 * list, so delete old value, and insert
2243 * If more than one item in existing list and
2244 * current is end of existing list, then we
2245 * have to delete and append instead of
2246 * deleting and prepending.
2248 if(((*cl
)->varmem
> 0 || lval
[1])
2249 && !(lval
[(*cl
)->varmem
+1])){
2254 config_del_list_item(cl
, &newval
);
2255 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
2259 fs_give((void **)<mp
);
2262 if(flags
&CF_NUMBER
&& sval
[0]
2263 && !(isdigit((unsigned char)sval
[0])
2264 || sval
[0] == '-' || sval
[0] == '+')){
2265 q_status_message(SM_ORDER
,3,3,
2266 _("Entry must be numeric"));
2271 fs_give((void **)apval
);
2273 if(sval
[0] && apval
)
2274 *apval
= cpystr(sval
);
2276 newval
= &(*cl
)->value
;
2280 cmd_cancelled("Change");
2283 help
= help
== NO_HELP
? h_config_change
: NO_HELP
;
2286 else if(i
== 4){ /* no redraw, yet */
2289 else if(i
== ctrl('P')){
2290 numval
= atoi(sval
);
2291 if(numval
== lowrange
){
2293 * Protect user from repeating arrow key that
2294 * causes message to appear over and over.
2296 if(++repeat_key
> 0){
2297 q_status_message1(SM_ORDER
,3,3,
2298 _("Minimum value is %s"), comatose(lowrange
));
2305 numval
= MAX(numval
- incr
, lowrange
);
2306 snprintf(sval
, oebufsize
, "%d", numval
);
2307 sval
[oebufsize
-1] = '\0';
2310 else if(i
== ctrl('N')){
2311 numval
= atoi(sval
);
2312 if(numval
== hirange
){
2313 if(++repeat_key
> 0){
2314 q_status_message1(SM_ORDER
,3,3,
2315 _("Maximum value is %s"), comatose(hirange
));
2322 numval
= MIN(numval
+ incr
, hirange
);
2323 snprintf(sval
, oebufsize
, "%d", numval
);
2324 sval
[oebufsize
-1] = '\0';
2335 if(!((*cl
)->var
&& (*cl
)->var
->is_list
)){
2336 q_status_message(SM_ORDER
, 0, 2,
2337 _("Can't shuffle single-valued setting"));
2344 curindex
= (*cl
)->varmem
;
2345 previndex
= curindex
-1;
2346 nextindex
= curindex
+1;
2347 if(!*alval
|| !(*alval
)[nextindex
])
2350 if((previndex
< 0 && nextindex
< 0) || !*alval
){
2351 q_status_message(SM_ORDER
, 0, 3,
2352 _("Shuffle only makes sense when there is more than one value defined"));
2356 /* Move it up or down? */
2361 ekey
[i
++].label
= N_("Up");
2366 ekey
[i
++].label
= N_("Down");
2371 if(previndex
< 0){ /* no up */
2375 else if(nextindex
< 0)
2376 ekey
[1].ch
= -2; /* no down */
2378 snprintf(prompt
, sizeof(prompt
), "Shuffle %s%s%s ? ",
2379 (ekey
[0].ch
!= -2) ? "UP" : "",
2380 (ekey
[0].ch
!= -2 && ekey
[1].ch
!= -2) ? " or " : "",
2381 (ekey
[1].ch
!= -2) ? "DOWN" : "");
2382 help
= (ekey
[0].ch
== -2) ? h_hdrcolor_shuf_down
2383 : (ekey
[1].ch
== -2) ? h_hdrcolor_shuf_up
2385 prompt
[sizeof(prompt
)-1] = '\0';
2387 i
= radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, deefault
, 'x',
2392 cmd_cancelled("Shuffle");
2402 swap_val
= (*alval
)[curindex
];
2403 (*alval
)[curindex
] = (*alval
)[nextindex
];
2404 (*alval
)[nextindex
] = swap_val
;
2407 swap_val
= (*alval
)[curindex
];
2408 (*alval
)[curindex
] = (*alval
)[previndex
];
2409 (*alval
)[previndex
] = swap_val
;
2411 else /* can't happen */
2415 * Fix the conf line values.
2419 fs_give((void **)&(*cl
)->value
);
2421 (*cl
)->value
= pretty_value(ps
, *cl
);
2424 if((*cl
)->next
->value
)
2425 fs_give((void **)&(*cl
)->next
->value
);
2427 (*cl
)->next
->value
= pretty_value(ps
, (*cl
)->next
);
2428 *cl
= next_confline(*cl
);
2431 if((*cl
)->prev
->value
)
2432 fs_give((void **)&(*cl
)->prev
->value
);
2434 (*cl
)->prev
->value
= pretty_value(ps
, (*cl
)->prev
);
2435 *cl
= prev_confline(*cl
);
2438 rv
= ps
->mangled_body
= 1;
2441 case MC_EXIT
: /* exit */
2442 rv
= config_exit_cmd(flags
);
2451 *cl
= next_confline(*cl
);
2454 * At this point, if changes occurred, var->user_val.X is set.
2455 * So, fix the current_val, and handle special cases...
2457 * NOTE: we don't worry about the "fixed variable" case here, because
2458 * editing such vars should have been prevented above...
2462 * Now go and set the current_val based on user_val changes
2463 * above. Turn off command line settings...
2465 set_current_val((*cl
)->var
, TRUE
, FALSE
);
2466 fix_side_effects(ps
, (*cl
)->var
, 0);
2469 * Delay setting the displayed value until "var.current_val" is set
2470 * in case current val gets changed due to a special case above.
2474 fs_give((void **) newval
);
2476 *newval
= pretty_value(ps
, *cl
);
2479 exception_override_warning((*cl
)->var
);
2483 fs_give((void **) &sval
);
2486 fs_give((void **) &olddefval
);
2493 config_exit_cmd(unsigned int flags
)
2495 return(screen_exit_cmd(flags
, "Configuration"));
2500 simple_exit_cmd(unsigned int flags
)
2507 * screen_exit_cmd - basic config/flag screen exit logic
2510 screen_exit_cmd(unsigned int flags
, char *cmd
)
2512 if(flags
& CF_CHANGES
){
2513 switch(want_to(EXIT_PMT
, 'y', 'x', h_config_undo
, WT_FLUSH_IN
)){
2515 q_status_message1(SM_ORDER
,0,3,"%s changes saved", cmd
);
2519 q_status_message1(SM_ORDER
,3,5,"No %s changes saved", cmd
);
2524 q_status_message(SM_ORDER
,3,5,"Changes not yet saved");
2537 config_add_list(struct pine
*ps
, CONF_S
**cl
, char **ltmp
, char ***newval
, int after
)
2540 char *tmp
, ***alval
;
2543 for(items
= 0, i
= 0; ltmp
[i
]; i
++) /* count list items */
2546 alval
= ALVAL((*cl
)->var
, ew
);
2548 if(alval
&& (*alval
)){
2549 if((*alval
)[0] && (*alval
)[0][0]){
2551 * Since we were already a list, make room
2552 * for the new member[s] and fall thru to
2553 * actually fill them in below...
2555 for(i
= 0; (*alval
)[i
]; i
++)
2558 fs_resize((void **)alval
, (i
+ items
+ 1) * sizeof(char *));
2561 * move the ones that will be bumped down to the bottom of the list
2563 for(; i
>= (*cl
)->varmem
+ (after
?1:0); i
--)
2564 (*alval
)[i
+items
] = (*alval
)[i
];
2571 free_list_array(alval
);
2573 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2574 memset((void *)(*alval
), 0, (items
+1)*sizeof(char *));
2575 (*alval
)[0] = ltmp
[0];
2577 *newval
= &(*cl
)->value
;
2580 fs_give((void **)&(*cl
)->value
);
2587 * since we were previously empty, we want
2588 * to replace the first CONF_S's value with
2589 * the first new value, and fill the other
2590 * in below if there's a list...
2592 * first, make sure we're at the beginning of this config
2593 * section and dump the config lines for the default list,
2594 * except for the first one, which we will over-write.
2596 *cl
= (*cl
)->varnamep
;
2597 while((*cl
)->next
&& (*cl
)->next
->varnamep
== (*cl
)->varnamep
)
2598 snip_confline(&(*cl
)->next
);
2601 * now allocate the new user_val array and fill in the first entry.
2603 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2604 memset((void *)(*alval
), 0, (items
+1) * sizeof(char *));
2605 (*alval
)[(*cl
)->varmem
=0] = ltmp
[0];
2607 *newval
= &(*cl
)->value
;
2610 fs_give((void **)&(*cl
)->value
);
2616 * Make new cl's to fit in the new space. Move the value from the current
2617 * line if inserting before it, else leave it where it is.
2619 for(; i
< items
; i
++){
2620 (*alval
)[i
+(*cl
)->varmem
+ (after
?1:0)] = ltmp
[i
];
2624 (*cl
)->value
= NULL
;
2628 (*cl
)->var
= (*cl
)->prev
->var
;
2629 (*cl
)->valoffset
= (*cl
)->prev
->valoffset
;
2630 (*cl
)->varoffset
= (*cl
)->prev
->varoffset
;
2631 (*cl
)->headingp
= (*cl
)->prev
->headingp
;
2632 (*cl
)->keymenu
= (*cl
)->prev
->keymenu
;
2633 (*cl
)->help
= (*cl
)->prev
->help
;
2634 (*cl
)->tool
= (*cl
)->prev
->tool
;
2635 (*cl
)->varnamep
= (*cl
)->prev
->varnamep
;
2638 (*cl
)->value
= NULL
;
2642 *newval
= &(*cl
)->next
->value
;
2644 *newval
= &(*cl
)->value
;
2649 * now fix up varmem values and fill in new values that have been
2652 for(ctmp
= (*cl
)->varnamep
, i
= 0;
2654 ctmp
= ctmp
->next
, i
++){
2657 /* BUG: We should be able to do this without the temp
2660 char *ptmp
= pretty_value(ps
, ctmp
);
2661 ctmp
->value
= (ctmp
->varnamep
->flags
& CF_PRINTER
) ? printer_name(ptmp
) : cpystr(ptmp
);
2662 fs_give((void **)&ptmp
);
2672 config_del_list_item(CONF_S
**cl
, char ***newval
)
2674 char **bufp
, ***alval
;
2678 alval
= ALVAL((*cl
)->var
, ew
);
2680 if((*alval
)[(*cl
)->varmem
+ 1]){
2681 for(bufp
= &(*alval
)[(*cl
)->varmem
];
2682 (*bufp
= *(bufp
+1)) != NULL
; bufp
++)
2685 if(*cl
== (*cl
)->varnamep
){ /* leading value */
2687 fs_give((void **)&(*cl
)->value
);
2690 (*cl
)->value
= ctmp
->value
;
2694 ctmp
= *cl
; /* blast the confline */
2696 if(ctmp
== opt_screen
->top_line
)
2697 opt_screen
->top_line
= *cl
;
2700 snip_confline(&ctmp
);
2702 for(ctmp
= (*cl
)->varnamep
, i
= 0; /* now fix up varmem values */
2704 ctmp
= ctmp
->next
, i
++)
2707 else if((*cl
)->varmem
){ /* blasted last in list */
2710 if(ctmp
== opt_screen
->top_line
)
2711 opt_screen
->top_line
= *cl
;
2713 snip_confline(&ctmp
);
2715 else{ /* blasted last remaining */
2717 fs_give((void **)alval
);
2719 *newval
= &(*cl
)->value
;
2725 * feature list manipulation tool
2728 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
2731 checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2736 case MC_TOGGLE
: /* mark/unmark feature */
2737 if((*cl
)->var
== &ps
->vars
[V_FEATURE_LIST
]){
2739 toggle_feature_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, *cl
, 0);
2742 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2743 "Programmer botch! Unknown checkbox type.");
2747 case MC_EXIT
: /* exit */
2748 rv
= config_exit_cmd(flags
);
2761 * simple radio-button style variable handler
2764 radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2768 NAMEVAL_S
*rule
= NULL
;
2774 apval
= APVAL((*cl
)->var
, ew
);
2777 case MC_CHOICE
: /* set/unset feature */
2779 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2780 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
2781 && want_to(_("Delete old unused personal option setting"),
2782 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2783 delete_user_vals((*cl
)->var
);
2784 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
2791 if(standard_radio_var(ps
, (*cl
)->var
) || (*cl
)->var
== startup_ptr
){
2792 PTR_TO_RULEFUNC rulefunc
;
2795 if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2796 old_uc
= pico_usingcolor();
2797 old_cs
= ps
->color_style
;
2801 if((*cl
)->var
->cmdline_val
.p
)
2802 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2805 fs_give((void **)apval
);
2807 rulefunc
= rulefunc_from_var(ps
, (*cl
)->var
);
2809 rule
= (*rulefunc
)((*cl
)->varmem
);
2812 *apval
= cpystr(S_OR_L(rule
));
2814 cur_rule_value((*cl
)->var
, TRUE
, TRUE
);
2815 set_radio_pretty_vals(ps
, cl
);
2817 if((*cl
)->var
== &ps
->vars
[V_AB_SORT_RULE
])
2818 addrbook_redo_sorts();
2819 else if((*cl
)->var
== &ps
->vars
[V_THREAD_DISP_STYLE
]){
2820 clear_index_cache(ps
->mail_stream
, 0);
2822 else if((*cl
)->var
== &ps
->vars
[V_THREAD_INDEX_STYLE
]){
2826 clear_index_cache(ps
->mail_stream
, 0);
2827 /* clear all hidden and collapsed flags */
2828 set_lflags(ps
->mail_stream
, ps
->msgmap
, MN_COLL
| MN_CHID
, 0);
2831 && SORT_IS_THREADED(ps
->msgmap
)
2832 && unview_thread(ps
, ps
->mail_stream
, ps
->msgmap
)){
2833 ps
->next_screen
= mail_index_screen
;
2834 ps
->view_skipped_index
= 0;
2835 ps
->mangled_screen
= 1;
2838 if(SORT_IS_THREADED(ps
->msgmap
)
2839 && (SEP_THRDINDX() || COLL_THRDS()))
2840 collapse_threads(ps
->mail_stream
, ps
->msgmap
, NULL
);
2842 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
2843 m
= ps_global
->s_pool
.streams
[i
];
2845 sp_set_viewing_a_thread(m
, 0);
2848 adjust_cur_to_visible(ps
->mail_stream
, ps
->msgmap
);
2851 else if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2852 if(old_cs
!= ps
->color_style
){
2853 pico_toggle_color(0);
2854 switch(ps
->color_style
){
2857 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
2860 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
2863 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
2866 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
2870 if(ps
->color_style
!= COL_NONE
)
2871 pico_toggle_color(1);
2874 if(pico_usingcolor())
2875 pico_set_normal_color();
2877 if(!old_uc
&& pico_usingcolor()){
2880 * remove the explanatory warning line and a blank line
2883 /* first find the first blank line */
2884 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2885 if(ctmp
->flags
& CF_NOSELECT
)
2888 if(ctmp
&& ctmp
->flags
& CF_NOSELECT
&&
2889 ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
) &&
2890 ctmp
->next
&& ctmp
->next
->flags
& CF_NOSELECT
&&
2892 ctmp
->next
->next
->flags
& CF_NOSELECT
){
2893 ctmp
->prev
->next
= ctmp
->next
->next
;
2894 ctmp
->next
->next
->prev
= ctmp
->prev
;
2895 ctmp
->next
->next
= NULL
;
2896 free_conflines(&ctmp
);
2899 /* make all the colors selectable */
2900 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2901 if(ctmp
->flags
& CF_POT_SLCTBL
)
2902 ctmp
->flags
&= ~CF_NOSELECT
;
2904 else if(old_uc
&& !pico_usingcolor()){
2907 * add the explanatory warning line and a blank line
2910 /* first find the existing blank line */
2911 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2912 if(ctmp
->flags
& CF_NOSELECT
)
2915 /* add the explanatory warning line */
2916 new_confline(&ctmp
);
2917 ctmp
->help
= NO_HELP
;
2918 ctmp
->flags
|= CF_NOSELECT
;
2919 ctmp
->value
= cpystr(COLORNOSET
);
2921 /* and add another blank line */
2922 new_confline(&ctmp
);
2923 ctmp
->flags
|= (CF_NOSELECT
| CF_B_LINE
);
2925 /* make all the colors non-selectable */
2926 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2927 if(ctmp
->flags
& CF_POT_SLCTBL
)
2928 ctmp
->flags
|= CF_NOSELECT
;
2931 clear_index_cache(ps
->mail_stream
, 0);
2933 ps
->mangled_screen
= 1;
2937 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2940 else if((*cl
)->var
== &ps
->vars
[V_SORT_KEY
]){
2944 def_sort_rev
= (*cl
)->varmem
>= (short) EndofList
;
2945 def_sort
= (SortOrder
) ((*cl
)->varmem
- (def_sort_rev
2947 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def_sort
),
2948 (def_sort_rev
) ? "/Reverse" : "");
2950 if((*cl
)->var
->cmdline_val
.p
)
2951 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2955 fs_give((void **)apval
);
2957 *apval
= cpystr(tmp_20k_buf
);
2960 set_current_val((*cl
)->var
, TRUE
, TRUE
);
2961 if(decode_sort(ps
->VAR_SORT_KEY
, &def_sort
, &def_sort_rev
) != -1){
2962 ps
->def_sort
= def_sort
;
2963 ps
->def_sort_rev
= def_sort_rev
;
2966 set_radio_pretty_vals(ps
, cl
);
2967 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2971 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2972 "Programmer botch! Unknown radiobutton type.");
2976 case MC_EXIT
: /* exit */
2977 rv
= config_exit_cmd(flags
);
2986 exception_override_warning((*cl
)->var
);
2993 * simple yes/no style variable handler
2996 yesno_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2998 int rv
= 0, yes
= 0;
2999 char *pval
, **apval
;
3001 pval
= PVAL((*cl
)->var
, ew
);
3002 apval
= APVAL((*cl
)->var
, ew
);
3005 case MC_TOGGLE
: /* toggle yes to no and back */
3006 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
3007 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
3008 && want_to(_("Delete old unused personal option setting"),
3009 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
3010 delete_user_vals((*cl
)->var
);
3011 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
3019 yes
= ((pval
&& !strucmp(pval
, yesstr
)) ||
3020 (!pval
&& (*cl
)->var
->current_val
.p
&&
3021 !strucmp((*cl
)->var
->current_val
.p
, yesstr
)));
3022 fs_give((void **)&(*cl
)->value
);
3026 fs_give((void **)apval
);
3029 *apval
= cpystr(nostr
);
3031 *apval
= cpystr(yesstr
);
3034 set_current_val((*cl
)->var
, FALSE
, FALSE
);
3036 fs_give((void **)&(*cl
)->value
);
3038 (*cl
)->value
= pretty_value(ps
, *cl
);
3039 fix_side_effects(ps
, (*cl
)->var
, 0);
3043 case MC_EXIT
: /* exit */
3044 rv
= config_exit_cmd(flags
);
3057 * Manage display of the config/options menu body.
3060 update_option_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, Pos
*cursor_pos
)
3062 int dline
, w
, save
= '\0';
3063 CONF_S
*top_line
, *ctmp
;
3066 int want_width
, first_width
;
3067 char *saveptr
= NULL
;
3070 int last_selectable
;
3071 mswin_beginupdate();
3073 if(screen
== NULL
|| BODY_LINES(ps
) < 1)
3076 opt_screen
= screen
;
3079 cursor_pos
->col
= 0;
3080 cursor_pos
->row
= -1; /* to tell us if we've set it yet */
3084 * calculate top line of display for reframing if the current field
3085 * is off the display defined by screen->top_line...
3087 if((ctmp
= screen
->top_line
) != NULL
)
3088 for(dline
= BODY_LINES(ps
);
3089 dline
&& ctmp
&& ctmp
!= screen
->current
;
3090 ctmp
= next_confline(ctmp
), dline
--)
3093 if(!ctmp
|| !dline
){ /* force reframing */
3095 ctmp
= top_line
= first_confline(screen
->current
);
3097 if(((dline
++)%BODY_LINES(ps
)) == 0)
3099 while(ctmp
!= screen
->current
&& (ctmp
= next_confline(ctmp
)));
3102 top_line
= screen
->top_line
;
3106 * Figure out how far down the top line is from the top and how many
3107 * total lines there are. Dumb to loop every time thru, but
3108 * there aren't that many lines, and it's cheaper than rewriting things
3109 * to maintain a line count in each structure...
3111 for(dline
= 0, ctmp
= prev_confline(top_line
); ctmp
; ctmp
= prev_confline(ctmp
))
3114 scroll_setpos(dline
);
3115 last_selectable
= dline
;
3116 for(ctmp
= next_confline(top_line
); ctmp
; ctmp
= next_confline(ctmp
)){
3118 if (!(ctmp
->flags
& CF_NOSELECT
))
3119 last_selectable
= dline
;
3121 dline
= last_selectable
;
3122 scroll_setrange(BODY_LINES(ps
), dline
);
3125 /* mangled body or new page, force redraw */
3126 if(ps
->mangled_body
|| screen
->top_line
!= top_line
)
3127 screen
->prev
= NULL
;
3129 /* loop thru painting what's needed */
3130 for(dline
= 0, ctmp
= top_line
;
3131 dline
< BODY_LINES(ps
);
3132 dline
++, ctmp
= next_confline(ctmp
)){
3135 * only fall thru painting if something needs painting...
3137 if(!(!screen
->prev
|| ctmp
== screen
->prev
|| ctmp
== screen
->current
3138 || ctmp
== screen
->prev
->varnamep
3139 || ctmp
== screen
->current
->varnamep
3140 || ctmp
== screen
->prev
->headingp
3141 || ctmp
== screen
->current
->headingp
))
3144 ClearLine(dline
+ HEADER_ROWS(ps
));
3147 if(ctmp
->flags
& CF_B_LINE
)
3150 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3151 if(ctmp
== screen
->current
&& cursor_pos
)
3152 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3154 if((ctmp
== screen
->current
3155 || ctmp
== screen
->current
->varnamep
3156 || ctmp
== screen
->current
->headingp
)
3157 && !(ctmp
->flags
& CF_NOHILITE
))
3160 if(ctmp
->flags
& CF_H_LINE
){
3161 MoveCursor(dline
+ HEADER_ROWS(ps
), 0);
3162 Write_to_screen(repeat_char(ps
->ttyo
->screen_cols
, '-'));
3165 if(ctmp
->flags
& CF_CENTERED
){
3166 int offset
= ps
->ttyo
->screen_cols
/2
3167 - (utf8_width(ctmp
->varname
)/2);
3168 MoveCursor(dline
+ HEADER_ROWS(ps
),
3169 (offset
> 0) ? offset
: 0);
3171 else if(ctmp
->varoffset
)
3172 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->varoffset
);
3174 Write_to_screen(ctmp
->varname
);
3175 if((ctmp
== screen
->current
3176 || ctmp
== screen
->current
->varnamep
3177 || ctmp
== screen
->current
->headingp
)
3178 && !(ctmp
->flags
& CF_NOHILITE
))
3182 value
= (ctmp
->flags
& CF_INHERIT
) ? INHERIT
: ctmp
->value
;
3188 memset(tmp_20k_buf
, '\0',
3189 (6*ps
->ttyo
->screen_cols
+ 1) * sizeof(char));
3190 if(ctmp
== screen
->current
){
3191 if(!(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
))
3195 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3198 if(ctmp
->flags
& CF_H_LINE
)
3199 memset(tmp_20k_buf
, '-',
3200 ps
->ttyo
->screen_cols
* sizeof(char));
3202 if(ctmp
->flags
& CF_CENTERED
){
3203 int offset
= ps
->ttyo
->screen_cols
/2
3204 - (utf8_width(value
)/2);
3205 /* BUG: tabs screw us figuring length above */
3209 p
= tmp_20k_buf
+ offset
;
3210 if(!*(q
= tmp_20k_buf
))
3219 * Copy the value to a temp buffer expanding tabs, and
3220 * making sure not to write beyond screen right...
3222 for(i
= 0, j
= ctmp
->valoffset
; value
[i
]; i
++){
3223 if(value
[i
] == ctrl('I')){
3226 while((++j
) & 0x07);
3234 if(ctmp
== screen
->current
&& cursor_pos
){
3235 if(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
)
3236 cursor_pos
->col
= ctmp
->val2offset
;
3238 cursor_pos
->col
= ctmp
->valoffset
;
3240 if(ctmp
->tool
== radiobutton_tool
3242 || ctmp
->tool
==ldap_radiobutton_tool
3244 || ctmp
->tool
==role_radiobutton_tool
3245 || ctmp
->tool
==checkbox_tool
3246 || (ctmp
->tool
==color_setting_tool
&&
3247 ctmp
->valoffset
!= COLOR_INDENT
))
3251 if(ctmp
->flags
& CF_DOUBLEVAR
){
3255 first_width
= ctmp
->val2offset
- ctmp
->valoffset
- SPACE_BETWEEN_DOUBLEVARS
;
3256 if((l
=utf8_width(p
)) > first_width
&& first_width
>= 0){
3257 saveptr
= utf8_count_forw_width(p
, first_width
, &got_width
);
3259 * got_width != first_width indicates there's a problem
3260 * that should not happen. Ignore it.
3271 * If this is a COLOR_BLOB line we do special coloring.
3272 * The current object inverse hilite is only on the
3273 * checkbox part, the exact format comes from the
3274 * new_color_line function. If we change that we'll have
3275 * to change this to get the coloring right.
3277 if(p
[0] == '(' && p
[2] == ')' &&
3278 p
[3] == ' ' && p
[4] == ' ' &&
3279 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3280 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3281 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3282 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3284 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
);
3285 Write_to_screen_n(p
, 3);
3286 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3289 Write_to_screen_n(p
+3, 3);
3290 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3291 colorx(CFC_ICOLOR(ctmp
)));
3293 lastc
= pico_get_cur_color();
3294 (void)pico_set_colorp(newc
, PSC_NONE
);
3295 free_color_pair(&newc
);
3298 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3301 (void)pico_set_colorp(lastc
, PSC_NONE
);
3302 free_color_pair(&lastc
);
3305 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3308 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, p
);
3309 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3316 PutLine0(dline
+HEADER_ROWS(ps
),
3317 ctmp
->val2offset
- SPACE_BETWEEN_DOUBLEVARS
,
3318 repeat_char(SPACE_BETWEEN_DOUBLEVARS
, SPACE
));
3320 if(l
> ctmp
->val2offset
- ctmp
->valoffset
&& ctmp
->val2offset
- ctmp
->valoffset
>= 0)
3321 p
= saveptr
+ SPACE_BETWEEN_DOUBLEVARS
;
3323 if(p
> tmp_20k_buf
){
3324 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3327 if(p
[0] == '(' && p
[2] == ')' &&
3328 p
[3] == ' ' && p
[4] == ' ' &&
3329 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3330 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3331 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3332 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3334 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->val2offset
);
3335 Write_to_screen_n(p
, 3);
3336 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3339 Write_to_screen_n(p
+3, 3);
3340 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3341 colorx(CFC_ICOLOR(ctmp
)));
3343 lastc
= pico_get_cur_color();
3344 (void)pico_set_colorp(newc
, PSC_NONE
);
3345 free_color_pair(&newc
);
3348 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3351 (void)pico_set_colorp(lastc
, PSC_NONE
);
3352 free_color_pair(&lastc
);
3355 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3358 PutLine0(dline
+HEADER_ROWS(ps
),ctmp
->val2offset
,p
);
3359 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3365 char *q
, *first_space
, *sample
, *ptr
;
3366 COLOR_PAIR
*lastc
, *newc
;
3370 if(ctmp
->flags
& CF_COLORSAMPLE
&&
3371 pico_usingcolor() &&
3372 ((q
= strstr(tmp_20k_buf
, SAMPLE_LEADER
)) ||
3373 (q
= strstr(tmp_20k_buf
, "Color"))) &&
3374 (first_space
= strindex(q
, SPACE
)) &&
3375 (strstr(value
, SAMP1
) ||
3376 strstr(value
, SAMP2
))){
3380 /* write out first part */
3381 *first_space
= '\0';
3382 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
,
3384 *first_space
= SPACE
;
3387 if(ctmp
== screen
->current
)
3390 sample
= skip_white_space(ptr
);
3391 /* if there's enough room to put some sample up */
3394 w
= utf8_width(tmp_20k_buf
);
3396 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3398 sample
++; /* for `[' at edge of sample */
3402 w
= utf8_width(tmp_20k_buf
);
3407 /* spaces and bracket before sample1 */
3408 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+w
, ptr
);
3413 /* then the color sample */
3414 if(ctmp
->var
== &ps
->vars
[V_VIEW_HDR_COLORS
]
3415 || ctmp
->var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
]){
3416 SPEC_COLOR_S
*hc
, *hcolors
;
3418 lastc
= newc
= NULL
;
3421 spec_colors_from_varlist(LVAL(ctmp
->var
, ew
),
3423 for(hc
= hcolors
, i
=0; hc
; hc
= hc
->next
, i
++)
3424 if(CFC_ICUST(ctmp
) == i
)
3427 if(hc
&& hc
->fg
&& hc
->fg
[0] && hc
->bg
&&
3429 newc
= new_color_pair(hc
->fg
, hc
->bg
);
3432 lastc
= pico_get_cur_color();
3433 (void)pico_set_colorp(newc
, PSC_NONE
);
3434 free_color_pair(&newc
);
3438 free_spec_colors(&hcolors
);
3441 /* print out sample1 */
3445 w
= utf8_width(tmp_20k_buf
);
3448 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3449 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3455 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3459 ptr
= strindex(ptr
, ']');
3462 (void)pico_set_colorp(lastc
, PSC_NONE
);
3463 free_color_pair(&lastc
);
3466 else if(ctmp
->var
== &ps
->vars
[V_KW_COLORS
]){
3468 SPEC_COLOR_S
*kw_col
= NULL
;
3470 lastc
= newc
= NULL
;
3472 /* find keyword associated with this line */
3473 for(kw
=ps
->keywords
, i
=0; kw
; kw
=kw
->next
, i
++)
3474 if(CFC_ICUST(ctmp
) == i
)
3479 spec_colors_from_varlist(LVAL(ctmp
->var
,ew
),
3482 /* color for this keyword */
3484 && ((kw
->nick
&& kw
->nick
[0]
3485 && (newc
=hdr_color(kw
->nick
, NULL
,
3488 (kw
->kw
&& kw
->kw
[0]
3489 && (newc
=hdr_color(kw
->kw
, NULL
,
3491 lastc
= pico_get_cur_color();
3492 (void)pico_set_colorp(newc
, PSC_NONE
);
3493 free_color_pair(&newc
);
3497 free_spec_colors(&kw_col
);
3499 /* print out sample1 */
3503 w
= utf8_width(tmp_20k_buf
);
3506 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3507 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3513 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3517 ptr
= strindex(ptr
, ']');
3520 (void)pico_set_colorp(lastc
, PSC_NONE
);
3521 free_color_pair(&lastc
);
3527 newc
= sample_color(ps
, ctmp
->var
);
3529 if((lastc
= pico_get_cur_color()) != NULL
)
3530 (void)pico_set_colorp(newc
, PSC_NONE
);
3532 free_color_pair(&newc
);
3534 else if(var_defaults_to_rev(ctmp
->var
)){
3535 if((newc
= pico_get_rev_color()) != NULL
){
3537 * Note, don't have to free newc.
3539 if((lastc
= pico_get_cur_color()) != NULL
)
3540 (void)pico_set_colorp(newc
, PSC_NONE
);
3548 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3550 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3551 !(PVAL(ctmp
->var
,ew
) &&
3552 PVAL(ctmp
->var
+1,ew
))))
3555 /* print out sample1 */
3559 w
= utf8_width(tmp_20k_buf
);
3562 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3563 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3569 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3573 ptr
= strindex(ptr
, ']');
3575 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3577 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3578 !(PVAL(ctmp
->var
,ew
) &&
3579 PVAL(ctmp
->var
+1,ew
))))
3583 (void)pico_set_colorp(lastc
, PSC_NONE
);
3584 free_color_pair(&lastc
);
3591 * Finish sample1 with the right bracket.
3595 w
= utf8_width(tmp_20k_buf
);
3597 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3600 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3607 * Now check for an exception sample and paint it.
3609 if(ctmp
->valoffset
+ w
+ SBS
+ 1 < ps
->ttyo
->screen_cols
&& (q
= strstr(ptr
, SAMPEXC
))){
3613 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3618 * Figure out what color to paint it.
3619 * This only happens with normal variables,
3620 * not with V_VIEW_HDR_COLORS.
3624 newc
= sampleexc_color(ps
, ctmp
->var
);
3626 if((lastc
= pico_get_cur_color()) != NULL
)
3627 (void)pico_set_colorp(newc
, PSC_NONE
);
3629 free_color_pair(&newc
);
3631 else if(var_defaults_to_rev(ctmp
->var
)){
3632 if((newc
= pico_get_rev_color()) != NULL
){
3634 * Note, don't have to free newc.
3636 if((lastc
= pico_get_cur_color()) != NULL
)
3637 (void)pico_set_colorp(newc
, PSC_NONE
);
3645 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3647 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3648 !(PVAL(ctmp
->var
,Post
) &&
3649 PVAL(ctmp
->var
+1,Post
))))
3655 w
= utf8_width(tmp_20k_buf
);
3658 want_width
= MIN(utf8_width(SAMPEXC
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3659 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3665 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3669 ptr
= strindex(ptr
, ']');
3671 /* turn off bold and color */
3672 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3674 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3675 !(PVAL(ctmp
->var
,Post
) &&
3676 PVAL(ctmp
->var
+1,Post
))))
3680 (void)pico_set_colorp(lastc
, PSC_NONE
);
3681 free_color_pair(&lastc
);
3687 * Finish sample2 with the right bracket.
3691 w
= utf8_width(tmp_20k_buf
);
3693 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3696 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3703 /* paint rest of the line if there is any left */
3704 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
&& *ptr
){
3705 want_width
= ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
;
3706 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3712 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3719 w
= utf8_width(tmp_20k_buf
);
3720 want_width
= ps
->ttyo
->screen_cols
- ctmp
->valoffset
;
3722 saveptr
= utf8_count_forw_width(tmp_20k_buf
, want_width
, &got_width
);
3727 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, tmp_20k_buf
);
3728 if(ctmp
== screen
->current
)
3736 ps
->mangled_body
= 0;
3737 screen
->top_line
= top_line
;
3738 screen
->prev
= screen
->current
;
3750 print_option_screen(OPT_SCREEN_S
*screen
, char *prompt
)
3756 if(open_printer(prompt
) == 0){
3757 for(ctmp
= first_confline(screen
->current
);
3759 ctmp
= next_confline(ctmp
)){
3762 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3764 snprintf(line
, sizeof(line
), "%*s%s", ctmp
->varoffset
, "",
3766 line
[sizeof(line
)-1] = '\0';
3768 so_far
= ctmp
->varoffset
+ utf8_width(ctmp
->varname
);
3771 if(ctmp
&& ctmp
->value
){
3772 char *p
= tmp_20k_buf
;
3775 /* Copy the value to a temp buffer expanding tabs. */
3776 for(i
= 0, j
= ctmp
->valoffset
; ctmp
->value
[i
]; i
++){
3777 if(ctmp
->value
[i
] == ctrl('I')){
3780 while((++j
) & 0x07);
3784 *p
++ = ctmp
->value
[i
];
3790 removing_trailing_white_space(tmp_20k_buf
);
3792 spaces
= MAX(ctmp
->valoffset
- so_far
, 0);
3793 snprintf(line
, sizeof(line
), "%*s%s\n", spaces
, "", tmp_20k_buf
);
3794 line
[sizeof(line
)-1] = '\0';
3809 option_screen_redrawer(void)
3811 ps_global
->mangled_body
= 1;
3812 update_option_screen(ps_global
, opt_screen
, (Pos
*)NULL
);
3818 * pretty_value - given the line, return an
3819 * alloc'd string for line's value...
3822 pretty_value(struct pine
*ps
, CONF_S
*cl
)
3828 if(v
== &ps
->vars
[V_FEATURE_LIST
])
3829 return(checkbox_pretty_value(ps
, cl
));
3830 else if(standard_radio_var(ps
, v
) || v
== startup_ptr
)
3831 return(radio_pretty_value(ps
, cl
));
3832 else if(v
== &ps
->vars
[V_SORT_KEY
])
3833 return(sort_pretty_value(ps
, cl
));
3834 else if(v
== &ps
->vars
[V_SIGNATURE_FILE
])
3835 return(sigfile_pretty_value(ps
, cl
));
3836 else if(v
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
])
3837 return(yesno_pretty_value(ps
, cl
));
3838 else if(color_holding_var(ps
, v
))
3839 return(color_pretty_value(ps
, cl
));
3841 return(text_pretty_value(ps
, cl
));
3846 text_pretty_value(struct pine
*ps
, CONF_S
*cl
)
3848 char tmp
[6*MAX_SCREEN_COLS
+20], *pvalnorm
, **lvalnorm
, *pvalexc
, **lvalexc
;
3849 char *p
, *pval
, **lval
, lastchar
= '\0';
3850 int editing_except
, fixed
, uvalset
, uvalposlen
;
3852 int comments
, except_set
, avail_width
;
3853 int norm_with_except
= 0, norm_with_except_inherit
= 0;
3854 int inherit_line
= 0;
3856 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
3857 fixed
= cl
->var
->is_fixed
;
3858 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
))
3859 norm_with_except
++; /* editing normal and except config exists */
3861 if(cl
->var
->is_list
){
3862 lvalnorm
= LVAL(cl
->var
, Main
);
3863 lvalexc
= LVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3865 uvalset
= lvalexc
!= NULL
;
3866 uvalposlen
= uvalset
&& lvalexc
[0] && lvalexc
[0][0];
3870 uvalset
= lvalnorm
!= NULL
;
3871 uvalposlen
= uvalset
&& lvalnorm
[0] && lvalnorm
[0][0];
3875 except_set
= lvalexc
!= NULL
;
3876 comments
= cl
->var
->current_val
.l
!= NULL
;
3877 if(norm_with_except
&& except_set
&& lvalexc
[0] &&
3878 !strcmp(lvalexc
[0],INHERIT
))
3879 norm_with_except_inherit
++;
3881 if(uvalset
&& !strcmp(lval
[0], INHERIT
)){
3882 if(cl
->varmem
== 0){
3888 /* only add extra comments on last member of list */
3889 if(uvalset
&& !inherit_line
&& lval
&& lval
[cl
->varmem
] &&
3890 lval
[cl
->varmem
+ 1])
3894 pvalnorm
= PVAL(cl
->var
, Main
);
3895 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3897 uvalset
= pvalexc
!= NULL
;
3898 uvalposlen
= uvalset
&& *pvalexc
;
3902 uvalset
= pvalnorm
!= NULL
;
3903 uvalposlen
= uvalset
&& *pvalnorm
;
3907 except_set
= pvalexc
!= NULL
;
3908 comments
= cl
->var
->current_val
.p
!= NULL
;
3911 memset(tmp
, 0, sizeof(tmp
));
3915 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
3917 if(fixed
|| !uvalset
|| !uvalposlen
){
3918 p
+= utf8_to_width(p
, "<", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3919 avail_width
-= got_width
;
3923 p
+= utf8_to_width(p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3924 avail_width
-= got_width
;
3927 p
+= utf8_to_width(p
, _(no_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3928 avail_width
-= got_width
;
3930 else if(!uvalposlen
){
3931 p
+= utf8_to_width(p
, _(empty_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3932 avail_width
-= got_width
;
3934 else if(inherit_line
){
3935 p
+= utf8_to_width(p
, INHERIT
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3936 avail_width
-= got_width
;
3939 if(cl
->var
->is_list
){
3940 p
+= utf8_to_width(p
, lval
[cl
->varmem
], sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3941 avail_width
-= got_width
;
3944 p
+= utf8_to_width(p
, pval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3945 avail_width
-= got_width
;
3949 if(comments
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
3950 if(fixed
|| !uvalset
){
3951 p
+= utf8_to_width(p
, ": using ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3952 avail_width
-= got_width
;
3955 if(norm_with_except
&& except_set
){
3957 p
+= utf8_to_width(p
, "exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3958 avail_width
-= got_width
;
3962 p
+= utf8_to_width(p
, ": ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3963 avail_width
-= got_width
;
3966 p
+= utf8_to_width(p
, " (", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3967 avail_width
-= got_width
;
3970 if(norm_with_except_inherit
){
3971 p
+= utf8_to_width(p
, "added to by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3972 avail_width
-= got_width
;
3975 p
+= utf8_to_width(p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3976 avail_width
-= got_width
;
3981 if(avail_width
>= 7){
3982 if(cl
->var
== &ps_global
->vars
[V_POST_CHAR_SET
]){
3983 p
+= utf8_to_width(p
, "most specific (see help)", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3984 avail_width
-= got_width
;
3987 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
3989 if(cl
->var
->is_list
){
3992 the_list
= cl
->var
->current_val
.l
;
3994 if(norm_with_except
&& except_set
)
3997 if(the_list
&& the_list
[0] && !strcmp(the_list
[0], INHERIT
))
4000 for(lval
= the_list
; avail_width
-(p
-tmp
) > 0 && *lval
; lval
++){
4001 if(lval
!= the_list
){
4002 p
+= utf8_to_width(p
, ",", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
4003 avail_width
-= got_width
;
4006 p
+= utf8_to_width(p
, *lval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
4007 avail_width
-= got_width
;
4011 p
+= utf8_to_width(p
, cl
->var
->current_val
.p
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
4012 avail_width
-= got_width
;
4015 if(p
-tmp
+2 < sizeof(tmp
)){
4021 else if(*(p
-1) == SPACE
)
4025 tmp
[sizeof(tmp
)-1] = '\0';
4027 if(fixed
|| !uvalset
|| !uvalposlen
)
4029 else if(comments
&& norm_with_except
&& except_set
)
4033 if(p
-tmp
+2 < sizeof(tmp
)){
4039 tmp
[sizeof(tmp
)-1] = '\0';
4040 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
4042 if(utf8_width(tmp
) < avail_width
)
4043 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
), "%*s", avail_width
-utf8_width(tmp
), "");
4045 tmp
[sizeof(tmp
)-1] = '\0';
4047 return(cpystr(tmp
));
4052 checkbox_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4054 char tmp
[6*MAXPATH
];
4055 char *comment
= NULL
;
4056 int indent
, x
, screen_width
, need
;
4057 int longest_featname
, longest_comment
;
4058 int nwidcomm
; /* name width with comment */
4059 int nwidnocomm
; /* and without comment */
4062 screen_width
= (ps
&& ps
->ttyo
) ? ps
->ttyo
->screen_cols
: 80;
4065 longest_featname
= longest_feature_name();
4066 longest_comment
= longest_feature_comment(ps
, ew
);
4067 indent
= feature_indent();
4069 nwidcomm
= longest_featname
;
4070 nwidnocomm
= longest_featname
+ 2 + longest_comment
;
4072 if((need
= (indent
+ 5 + longest_featname
+ 2 + longest_comment
) - screen_width
) > 0){
4078 longest_comment
= 0;
4079 nwidnocomm
= longest_featname
;
4083 feature
= feature_list(cl
->varmem
);
4085 x
= feature_gets_an_x(ps
, cl
->var
, feature
, &comment
, ew
);
4087 if(longest_comment
&& comment
&& *comment
){
4088 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w %-*.*w", x
? 'X' : ' ',
4090 pretty_feature_name(feature
->name
, nwidcomm
),
4091 longest_comment
, longest_comment
, comment
? comment
: "");
4094 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w", x
? 'X' : ' ',
4095 nwidnocomm
, nwidnocomm
,
4096 pretty_feature_name(feature
->name
, nwidnocomm
));
4099 return(cpystr(tmp
));
4104 longest_feature_name(void)
4111 for(lv
= 0, i
= 0; (feature
= feature_list(i
)); i
++)
4112 if(feature_list_section(feature
)
4113 && lv
< (j
= utf8_width(pretty_feature_name(feature
->name
, -1))))
4124 feature_indent(void)
4131 yesno_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4133 char tmp
[6*MAXPATH
], *pvalnorm
, *pvalexc
;
4134 char *p
, *pval
, lastchar
= '\0';
4135 int editing_except
, fixed
, norm_with_except
, uvalset
;
4136 int curval
, except_set
;
4138 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
4139 fixed
= cl
->var
->is_fixed
;
4140 if((ps_global
->ew_for_except_vars
== Main
) ||
4141 (ew
== ps_global
->ew_for_except_vars
))
4142 norm_with_except
= 0;
4144 norm_with_except
= 1; /* editing normal and except config exists */
4146 pvalnorm
= PVAL(cl
->var
, Main
);
4147 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
4149 uvalset
= (pvalexc
!= NULL
&&
4150 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4154 uvalset
= (pvalnorm
!= NULL
&&
4155 (!strucmp(pvalnorm
,yesstr
) || !strucmp(pvalnorm
,nostr
)));
4159 except_set
= (pvalexc
!= NULL
&&
4160 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4161 curval
= (cl
->var
->current_val
.p
!= NULL
&&
4162 (!strucmp(cl
->var
->current_val
.p
,yesstr
) ||
4163 !strucmp(cl
->var
->current_val
.p
,nostr
)));
4168 if(fixed
|| !uvalset
)
4169 sstrncpy(&p
, "<", sizeof(tmp
)-(p
-tmp
));
4172 sstrncpy(&p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
));
4174 sstrncpy(&p
, _(no_val
), sizeof(tmp
)-(p
-tmp
));
4175 else if(!strucmp(pval
, yesstr
))
4176 sstrncpy(&p
, yesstr
, sizeof(tmp
)-(p
-tmp
));
4178 sstrncpy(&p
, nostr
, sizeof(tmp
)-(p
-tmp
));
4180 if(curval
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
4181 if(fixed
|| !uvalset
)
4182 sstrncpy(&p
, ": using ", sizeof(tmp
)-(p
-tmp
));
4184 if(norm_with_except
&& except_set
){
4186 sstrncpy(&p
, "exception ", sizeof(tmp
)-(p
-tmp
));
4188 sstrncpy(&p
, " (", sizeof(tmp
)-(p
-tmp
));
4189 sstrncpy(&p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
));
4193 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4194 sstrncpy(&p
, !strucmp(cl
->var
->current_val
.p
,yesstr
) ? yesstr
: nostr
, sizeof(tmp
)-(p
-tmp
));
4195 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4198 if(fixed
|| !uvalset
)
4200 else if(curval
&& norm_with_except
&& except_set
)
4203 if(lastchar
&& sizeof(tmp
)-(p
-tmp
) > 1){
4208 tmp
[sizeof(tmp
)-1] = '\0';
4210 if(utf8_width(tmp
) < ps
->ttyo
->screen_cols
- cl
->valoffset
)
4211 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
),
4212 "%*s", ps
->ttyo
->screen_cols
- cl
->valoffset
- utf8_width(tmp
), "");
4214 tmp
[sizeof(tmp
)-1] = '\0';
4216 return(cpystr(tmp
));
4221 radio_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4223 char tmp
[6*MAXPATH
];
4224 char *pvalnorm
, *pvalexc
, *pval
;
4225 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4226 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4228 NAMEVAL_S
*rule
= NULL
, *f
;
4229 PTR_TO_RULEFUNC rulefunc
;
4235 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4237 editing_normal_which_isnt_except
= (ew
== Main
&&
4238 ew
!= ps_global
->ew_for_except_vars
);
4239 fixed
= cl
->var
->is_fixed
;
4240 pvalnorm
= PVAL(v
, Main
);
4241 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4243 rulefunc
= rulefunc_from_var(ps
, v
);
4244 rule
= rulefunc
? (*rulefunc
)(cl
->varmem
) : NULL
;
4246 /* find longest name */
4248 for(lv
= 0, i
= 0; (f
= (*rulefunc
)(i
)); i
++)
4249 if(lv
< (j
= utf8_width(f
->name
)))
4254 if(editing_except_which_isnt_normal
)
4260 is_set_for_this_level
++;
4263 pval
= v
->fixed_val
.p
;
4264 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4266 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4267 is_the_one
? R_SELD
: ' ',
4268 lv
, lv
, rule
->name
, is_the_one
? " (value is fixed)" : "");
4270 else if(is_set_for_this_level
){
4271 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4272 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4273 !strucmp(pvalexc
, S_OR_L(rule
)));
4274 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4275 is_the_one
? R_SELD
: ' ',
4277 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4278 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4280 editing_normal_which_isnt_except
&&
4282 !the_exc_one
) ? " (overridden by exceptions)" :
4287 is_the_one
= !strucmp(pvalexc
, S_OR_L(rule
));
4288 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4289 is_the_one
? R_SELD
: ' ',
4291 is_the_one
? " (value set in exceptions)" : "");
4294 pval
= v
->current_val
.p
;
4295 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4296 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4297 is_the_one
? R_SELD
: ' ',
4299 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4303 tmp
[sizeof(tmp
)-1] = '\0';
4305 return(cpystr(tmp
));
4310 sigfile_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4312 if(cl
&& cl
->var
== &ps
->vars
[V_SIGNATURE_FILE
] &&
4313 cl
->prev
&& cl
->prev
->var
== &ps
->vars
[V_LITERAL_SIG
]){
4314 if(cl
->prev
->var
->current_val
.p
){
4315 cl
->flags
|= CF_NOSELECT
; /* side effect */
4316 return(cpystr(_("<Ignored: using Literal-Signature instead>")));
4319 cl
->flags
&= ~CF_NOSELECT
;
4320 return(text_pretty_value(ps
, cl
));
4329 color_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4331 char tmp
[6*MAXPATH
];
4339 if(v
&& color_holding_var(ps
, v
) &&
4340 (p
=srchstr(v
->name
, "-foreground-color"))){
4342 is_index
= !struncmp(v
->name
, "index-", 6);
4344 q
= sampleexc_text(ps
, v
);
4345 utf8_snprintf(tmp
, sizeof(tmp
), "%c%.*s %sColor%*.50s %.20w%*s%.20w%.20w",
4346 islower((unsigned char)v
->name
[0])
4347 ? toupper((unsigned char)v
->name
[0])
4349 MIN(p
-v
->name
-1,30), v
->name
+1,
4350 is_index
? "Symbol " : "",
4351 MAX(EQ_COL
- COLOR_INDENT
-1 - MIN(p
-v
->name
-1,30)
4352 - 6 - (is_index
? 7 : 0) - 1,0), "",
4353 sample_text(ps
,v
), *q
? SBS
: 0, "", q
,
4354 color_parenthetical(v
));
4357 tmp
[sizeof(tmp
)-1] = '\0';
4359 return(cpystr(tmp
));
4364 sort_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4366 return(generalized_sort_pretty_value(ps
, cl
, 1));
4371 generalized_sort_pretty_value(struct pine
*ps
, CONF_S
*cl
, int default_ok
)
4373 char tmp
[6*MAXPATH
];
4374 char *pvalnorm
, *pvalexc
, *pval
;
4375 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4376 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4379 SortOrder line_sort
, var_sort
, exc_sort
;
4380 int line_sort_rev
, var_sort_rev
, exc_sort_rev
;
4385 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4387 editing_normal_which_isnt_except
= (ew
== Main
&&
4388 ew
!= ps_global
->ew_for_except_vars
);
4389 fixed
= cl
->var
->is_fixed
;
4390 pvalnorm
= PVAL(v
, Main
);
4391 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4393 /* find longest value's name */
4394 for(lv
= 0, i
= 0; ps
->sort_types
[i
] != EndofList
; i
++)
4395 if(lv
< (j
= utf8_width(sort_name(ps
->sort_types
[i
]))))
4400 if(editing_except_which_isnt_normal
)
4406 is_set_for_this_level
++;
4408 /* the config line we're talking about */
4409 if(cl
->varmem
>= 0){
4410 line_sort_rev
= cl
->varmem
>= (short)EndofList
;
4411 line_sort
= (SortOrder
)(cl
->varmem
- (line_sort_rev
* EndofList
));
4415 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*w",
4416 (pval
== NULL
) ? R_SELD
: ' ',
4420 pval
= v
->fixed_val
.p
;
4421 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4422 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4424 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4425 is_the_one
? R_SELD
: ' ',
4426 line_sort_rev
? "Reverse " : "",
4427 lv
, sort_name(line_sort
),
4428 line_sort_rev
? 0 : 8, "",
4429 is_the_one
? " (value is fixed)" : "");
4431 else if(is_set_for_this_level
){
4432 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4433 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4434 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4435 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4436 exc_sort_rev
== line_sort_rev
&& exc_sort
== line_sort
);
4437 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4438 is_the_one
? R_SELD
: ' ',
4439 line_sort_rev
? "Reverse " : "",
4440 lv
, sort_name(line_sort
),
4441 line_sort_rev
? 0 : 8, "",
4442 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4443 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4445 editing_normal_which_isnt_except
&&
4447 !the_exc_one
) ? " (overridden by exceptions)" :
4452 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4453 is_the_one
= (exc_sort_rev
== line_sort_rev
&&
4454 exc_sort
== line_sort
);
4455 utf8_snprintf(tmp
, sizeof(tmp
), "( ) %s%-*w%*s%s",
4456 line_sort_rev
? "Reverse " : "",
4457 lv
, sort_name(line_sort
),
4458 line_sort_rev
? 0 : 8, "",
4459 is_the_one
? " (value set in exceptions)" : "");
4462 pval
= v
->current_val
.p
;
4463 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4464 is_the_one
= ((pval
|| default_ok
) &&
4465 var_sort_rev
== line_sort_rev
&&
4466 var_sort
== line_sort
);
4467 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4468 is_the_one
? R_SELD
: ' ',
4469 line_sort_rev
? "Reverse " : "",
4470 lv
, sort_name(line_sort
),
4471 line_sort_rev
? 0 : 8, "",
4472 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4476 return(cpystr(tmp
));
4481 sample_color(struct pine
*ps
, struct variable
*v
)
4483 COLOR_PAIR
*cp
= NULL
;
4484 char *pvalefg
, *pvalebg
;
4485 char *pvalmfg
, *pvalmbg
;
4487 pvalefg
= PVAL(v
, ew
);
4488 pvalebg
= PVAL(v
+1, ew
);
4489 pvalmfg
= PVAL(v
, Main
);
4490 pvalmbg
= PVAL(v
+1, Main
);
4491 if(v
&& color_holding_var(ps
, v
) &&
4492 srchstr(v
->name
, "-foreground-color")){
4493 if(pvalefg
&& pvalefg
[0] && pvalebg
&& pvalebg
[0])
4494 cp
= new_color_pair(pvalefg
, pvalebg
);
4495 else if(ew
== Post
&& pvalmfg
&& pvalmfg
[0] && pvalmbg
&& pvalmbg
[0])
4496 cp
= new_color_pair(pvalmfg
, pvalmbg
);
4497 else if(v
->global_val
.p
&& v
->global_val
.p
[0] &&
4498 (v
+1)->global_val
.p
&& (v
+1)->global_val
.p
[0])
4499 cp
= new_color_pair(v
->global_val
.p
, (v
+1)->global_val
.p
);
4507 sampleexc_color(struct pine
*ps
, struct variable
*v
)
4509 COLOR_PAIR
*cp
= NULL
;
4510 char *pvalfg
, *pvalbg
;
4512 pvalfg
= PVAL(v
, Post
);
4513 pvalbg
= PVAL(v
+1, Post
);
4514 if(v
&& color_holding_var(ps
, v
) &&
4515 srchstr(v
->name
, "-foreground-color") &&
4516 pvalfg
&& pvalfg
[0] && pvalbg
&& pvalbg
[0])
4517 cp
= new_color_pair(pvalfg
, pvalbg
);
4524 clear_feature(char ***l
, char *f
)
4526 char **list
= l
? *l
: NULL
;
4529 for(; list
&& *list
; list
++, count
++){
4530 if(f
&& !strucmp(((!struncmp(*list
,"no-",3)) ? *list
+ 3 : *list
), f
)){
4531 fs_give((void **)list
);
4536 *list
= *(list
+ 1);
4540 * this is helpful to keep the array from growing if a feature
4541 * gets set and unset repeatedly
4544 fs_resize((void **)l
, count
* sizeof(char *));
4552 toggle_feature_bit(struct pine
*ps
, int index
, struct variable
*var
, CONF_S
*cl
, int just_flip_value
)
4558 f
= feature_list(index
);
4560 og
= test_old_growth_bits(ps
, f
->id
);
4563 * if this feature is in the fixed set, or old-growth is in the fixed
4564 * set and this feature is in the old-growth set, don't alter it...
4566 for(vp
= var
->fixed_val
.l
; vp
&& *vp
; vp
++){
4567 p
= (struncmp(*vp
, "no-", 3)) ? *vp
: *vp
+ 3;
4568 if(!strucmp(p
, f
->name
) || (og
&& !strucmp(p
, "old-growth"))){
4569 q_status_message(SM_ORDER
, 3, 3,
4570 _("Can't change value fixed by sys-admin."));
4575 on_before
= F_ON(f
->id
, ps
);
4577 toggle_feature(ps
, var
, f
, just_flip_value
, ew
);
4580 * Handle any alpine-specific features that need attention here. Features
4581 * that aren't alpine-specific should be handled in toggle_feature instead.
4583 if(on_before
!= F_ON(f
->id
, ps
))
4585 case F_CMBND_ABOOK_DISP
:
4589 case F_PRESERVE_START_STOP
:
4590 /* toggle raw mode settings to make tty driver aware of new setting */
4596 ps
->orig_use_fkeys
= F_ON(F_USE_FK
, ps
);
4597 ps
->mangled_footer
= 1;
4598 mark_keymenu_dirty();
4602 ps
->mangled_header
= 1;
4605 case F_BLANK_KEYMENU
:
4606 if(F_ON(f
->id
, ps
)){
4607 FOOTER_ROWS(ps
) = 1;
4608 ps
->mangled_body
= 1;
4611 FOOTER_ROWS(ps
) = 3;
4612 ps
->mangled_footer
= 1;
4618 case F_ENABLE_INCOMING
:
4619 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4620 "Folder List changes will take effect your next Alpine session.");
4624 case F_SHOW_CURSOR
:
4625 mswin_showcaret(F_ON(f
->id
,ps
));
4628 case F_ENABLE_TRAYICON
:
4629 mswin_trayicon(F_ON(f
->id
,ps
));
4633 #if !defined(DOS) && !defined(OS2)
4643 case F_PASS_CONTROL_CHARS
:
4644 ps
->pass_ctrl_chars
= F_ON(F_PASS_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4648 case F_USE_CERT_STORE_ONLY
:
4649 if(F_OFF(F_USE_CERT_STORE_ONLY
, ps
))
4650 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4651 "Disabling this feature should only be done for testing. Press \"?\" for help");
4655 case F_PASS_C1_CONTROL_CHARS
:
4656 ps
->pass_c1_ctrl_chars
= F_ON(F_PASS_C1_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4660 case F_ENABLE_MOUSE
:
4661 if(F_ON(f
->id
, ps
)){
4664 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4665 "Mouse tracking still off ($DISPLAY variable set?)");
4674 if(just_flip_value
){
4675 if(cl
->value
&& cl
->value
[0])
4676 cl
->value
[1] = (cl
->value
[1] == ' ') ? 'X' : ' ';
4680 * This fork is only called from the checkbox_tool, which has
4681 * varmem set to index correctly and cl->var set correctly.
4684 fs_give((void **)&cl
->value
);
4686 cl
->value
= pretty_value(ps
, cl
);
4692 * new_confline - create new CONF_S zero it out, and insert it after current.
4693 * NOTE current gets set to the new CONF_S too!
4696 new_confline(CONF_S
**current
)
4700 p
= (CONF_S
*)fs_get(sizeof(CONF_S
));
4701 memset((void *)p
, 0, sizeof(CONF_S
));
4704 p
->next
= (*current
)->next
;
4705 (*current
)->next
= p
;
4722 snip_confline(CONF_S
**p
)
4727 * Be careful. We need this line because the
4728 * q->prev->next = ...
4729 * may change q itself if &q == &q->prev->next.
4730 * Then the use of q in the next line is wrong.
4731 * That's what happens if we pass in the address of
4732 * some ->next and use *p directly instead of q.
4737 /* Yank it from the linked list */
4739 q
->prev
->next
= q
->next
;
4742 q
->next
->prev
= q
->prev
;
4744 /* Then free up it's memory */
4745 q
->prev
= q
->next
= NULL
;
4751 get_confline_number(CONF_S
*conf
)
4756 for (p
= first_confline(conf
), pos
= 0; p
!= conf
; p
= next_confline(p
), pos
++);
4763 set_confline_number(CONF_S
*conf
, int pos
)
4767 for(p
= first_confline(conf
), i
= 0; p
&& i
< pos
; p
=next_confline(p
), i
++);
4776 free_conflines(CONF_S
**p
)
4779 free_conflines(&(*p
)->next
);
4782 fs_give((void **) &(*p
)->varname
);
4785 fs_give((void **) &(*p
)->value
);
4787 fs_give((void **) p
);
4796 first_confline(CONF_S
*p
)
4806 * First selectable confline.
4809 first_sel_confline(CONF_S
*p
)
4811 for(p
= first_confline(p
); p
&& (p
->flags
&CF_NOSELECT
); p
=next_confline(p
))
4822 last_confline(CONF_S
*p
)
4835 fixed_var(struct variable
*v
, char *action
, char *name
)
4841 || ((lval
=v
->fixed_val
.l
) && lval
[0]
4842 && strcmp(INHERIT
, lval
[0]) != 0))){
4843 q_status_message2(SM_ORDER
, 3, 3,
4844 "Can't %s sys-admin defined %s.",
4845 action
? action
: "change", name
? name
: "value");
4854 exception_override_warning(struct variable
*v
)
4858 /* if exceptions config file exists and we're not editing it */
4859 if(v
&& (ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
4860 if((!v
->is_list
&& PVAL(v
, ps_global
->ew_for_except_vars
)) ||
4861 (v
->is_list
&& (lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
4862 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0))
4863 q_status_message1(SM_ORDER
, 3, 3,
4864 _("Warning: \"%s\" is overridden in your exceptions configuration"),
4871 offer_to_fix_pinerc(struct pine
*ps
)
4878 int rv
= 0, write_main
= 0, write_post
= 0;
4879 int i
, k
, j
, need
, exc
;
4880 char *clear
= ": delete it";
4883 dprint((4, "offer_to_fix_pinerc()\n"));
4885 ps
->fix_fixed_warning
= 0; /* so we only ask first time */
4887 if(ps
->readonly_pinerc
)
4890 set_titlebar(_("FIXING PINERC"), ps
->mail_stream
,
4891 ps
->context_current
,
4892 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
4894 if(want_to(_("Some of your options conflict with site policy. Investigate"),
4895 'y', 'n', NO_HELP
, WT_FLUSH_IN
) != 'y')
4898 /* space want_to requires in addition to the string you pass in */
4899 #define WANTTO_SPACE 6
4900 need
= WANTTO_SPACE
+ utf8_width(clear
);
4902 for(v
= ps
->vars
; v
->name
; v
++){
4906 v
== &ps
->vars
[V_FEATURE_LIST
]) /* handle feature-list below */
4912 (v
->post_user_val
.l
|| v
->main_user_val
.l
)){
4915 active_list
= v
->post_user_val
.l
? v
->post_user_val
.l
4916 : v
->main_user_val
.l
;
4918 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is "), v
->name
);
4919 prompt
[sizeof(prompt
)-1] = '\0';
4920 p
= prompt
+ strlen(prompt
);
4921 for(i
= 0; active_list
[i
]; i
++){
4922 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4924 if(i
&& sizeof(prompt
)-(p
-prompt
) > 0)
4927 sstrncpy(&p
, active_list
[i
], sizeof(prompt
)-(p
-prompt
));
4928 if(sizeof(prompt
)-(p
-prompt
) > 0)
4931 prompt
[sizeof(prompt
)-1] = '\0';
4934 if(sizeof(prompt
)-(p
-prompt
) > 0)
4938 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"), v
->name
, _(empty_val2
));
4941 if(v
->post_user_val
.p
|| v
->main_user_val
.p
){
4944 active_var
= v
->post_user_val
.p
? v
->post_user_val
.p
4945 : v
->main_user_val
.p
;
4947 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4948 v
->name
, active_var
);
4951 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4952 v
->name
, _(empty_val2
));
4957 prompt
[sizeof(prompt
)-1] = '\0';
4960 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4961 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4963 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4964 prompt
[sizeof(prompt
)-1] = '\0';
4965 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4967 if(v
->main_user_val
.l
)
4969 if(v
->post_user_val
.l
)
4973 if(v
->main_user_val
.p
)
4975 if(v
->post_user_val
.p
)
4979 if(delete_user_vals(v
))
4987 * As always, feature-list has to be handled separately.
4989 exc
= (ps
->ew_for_except_vars
!= Main
);
4990 v
= &ps
->vars
[V_FEATURE_LIST
];
4991 list_fixed
= v
->fixed_val
.l
;
4993 for(j
= 0; j
< 2; j
++){
4994 plist
= (j
==0) ? &v
->main_user_val
.l
: &v
->post_user_val
.l
;
4997 for(i
= 0; list
[i
]; i
++){
4999 if(!struncmp(p
, "no-", 3))
5001 for(k
= 0; list_fixed
&& list_fixed
[k
]; k
++){
5003 if(!struncmp(q
, "no-", 3))
5005 if(!strucmp(q
, p
) && strucmp(list
[i
], list_fixed
[k
])){
5006 snprintf(prompt
, sizeof(prompt
), "Your %s is %s%s, fixed value is %s",
5007 p
, p
== list
[i
] ? _("ON") : _("OFF"),
5008 exc
? ((plist
== &v
->main_user_val
.l
) ? ""
5009 : " in postload-config")
5011 q
== list_fixed
[k
] ? _("ON") : _("OFF"));
5013 prompt
[sizeof(prompt
)-1] = '\0';
5014 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
5015 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
5017 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
5018 prompt
[sizeof(prompt
)-1] = '\0';
5019 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
5022 if(plist
== &v
->main_user_val
.l
)
5028 * Clear the feature from the user's pinerc
5029 * so that we'll stop bothering them when they
5032 clear_feature(plist
, p
);
5035 * clear_feature scoots the list up, so if list[i] was
5036 * the last one going in, now it is the end marker. We
5037 * just decrement i so that it will get incremented and
5038 * then test == 0 in the for loop. We could just goto
5039 * outta_here to accomplish the same thing.
5052 write_pinerc(ps
, Main
, WRP_NONE
);
5054 write_pinerc(ps
, Post
, WRP_NONE
);
5061 * Adjust side effects that happen because variable changes values.
5063 * Var->user_val should be set to the new value before calling this.
5066 fix_side_effects(struct pine
*ps
, struct variable
*var
, int revert
)
5069 char **v
, *q
, **apval
;
5070 struct variable
*vars
= ps
->vars
;
5072 /* move this up here so we get the Using default message */
5073 if(var
== &ps
->vars
[V_PERSONAL_NAME
]){
5074 if(!(var
->main_user_val
.p
||
5075 var
->post_user_val
.p
) && ps
->ui
.fullname
){
5076 if(var
->current_val
.p
)
5077 fs_give((void **)&var
->current_val
.p
);
5079 var
->current_val
.p
= cpystr(ps
->ui
.fullname
);
5086 && !(var
->main_user_val
.p
||
5087 var
->post_user_val
.p
)
5088 && var
->current_val
.p
)
5092 && !(var
->main_user_val
.l
||
5093 var
->post_user_val
.l
)
5094 && var
->current_val
.l
)))
5095 q_status_message(SM_ORDER
,0,3,_("Using default value"));
5097 if(var
== &ps
->vars
[V_USER_DOMAIN
]){
5100 if(ps
->VAR_USER_DOMAIN
5101 && ps
->VAR_USER_DOMAIN
[0]
5102 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5105 q_status_message2(SM_ORDER
, 3, 5,
5106 _("User-Domain (%s) cannot contain \"@\"; using %s"),
5107 ps
->VAR_USER_DOMAIN
, p
);
5108 q
= ps
->VAR_USER_DOMAIN
;
5109 while((*q
++ = *p
++) != '\0')
5114 q_status_message1(SM_ORDER
, 3, 5,
5115 _("User-domain (%s) cannot contain \"@\"; deleting"),
5116 ps
->VAR_USER_DOMAIN
);
5118 if(ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
){
5119 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
);
5120 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5123 if(ps
->VAR_USER_DOMAIN
5124 && ps
->VAR_USER_DOMAIN
[0]
5125 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5126 if(ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
){
5127 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
);
5128 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5135 * Reset various pointers pertaining to domain name and such...
5139 else if(var
== &ps
->vars
[V_INBOX_PATH
]){
5141 * fixup the inbox path based on global/default values...
5143 init_inbox_mapping(ps
->VAR_INBOX_PATH
, ps
->context_list
);
5145 if(!strucmp(ps
->cur_folder
, ps
->inbox_name
) && ps
->mail_stream
5146 && strcmp(ps
->VAR_INBOX_PATH
, ps
->mail_stream
->mailbox
)){
5148 * If we currently have "inbox" open and the mailbox name
5149 * doesn't match, reset the current folder's name and
5150 * remove the SP_INBOX flag.
5152 strncpy(ps
->cur_folder
, ps
->mail_stream
->mailbox
,
5153 sizeof(ps
->cur_folder
)-1);
5154 ps
->cur_folder
[sizeof(ps
->cur_folder
)-1] = '\0';
5155 sp_set_fldr(ps
->mail_stream
, ps
->cur_folder
);
5156 sp_unflag(ps
->mail_stream
, SP_INBOX
);
5157 ps
->mangled_header
= 1;
5159 else if(sp_inbox_stream()
5160 && strcmp(ps
->VAR_INBOX_PATH
, sp_inbox_stream()->original_mailbox
)){
5161 MAILSTREAM
*m
= sp_inbox_stream();
5164 * if we don't have inbox directly open, but have it
5165 * open for new mail notification, close the stream like
5166 * any other ordinary folder, and clean up...
5169 sp_unflag(m
, SP_PERMLOCKED
| SP_INBOX
);
5170 sp_set_fldr(m
, m
->mailbox
);
5171 expunge_and_close(m
, NULL
, EC_NONE
);
5175 else if(var
== &ps
->vars
[V_INCCHECKTIMEO
]){
5176 int old_value
= ps
->inc_check_timeout
;
5178 if(SVAR_INC_CHECK_TIMEO(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5180 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5183 ps
->inc_check_timeout
= old_value
;
5185 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5186 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5188 else if(var
== &ps
->vars
[V_INCCHECKINTERVAL
]){
5189 int old_value
= ps
->inc_check_interval
;
5191 if(SVAR_INC_CHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5193 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5196 ps
->inc_check_interval
= old_value
;
5198 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5199 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5201 else if(var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
]){
5202 int old_value
= ps
->inc_second_check_interval
;
5204 if(SVAR_INC_2NDCHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5206 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5209 ps
->inc_second_check_interval
= old_value
;
5211 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5212 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5214 else if(var
== &ps
->vars
[V_INCCHECKLIST
]){
5215 if(ps
->context_list
&& ps
->context_list
->use
& CNTXT_INCMNG
)
5216 reinit_incoming_folder_list(ps
, ps
->context_list
);
5218 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5219 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5221 else if(var
== &ps
->vars
[V_ADDRESSBOOK
] ||
5222 var
== &ps
->vars
[V_GLOB_ADDRBOOK
] ||
5224 var
== &ps
->vars
[V_LDAP_SERVERS
] ||
5226 var
== &ps
->vars
[V_ABOOK_FORMATS
]){
5229 else if(var
== &ps
->vars
[V_INDEX_FORMAT
]){
5230 reset_index_format();
5231 clear_index_cache(ps
->mail_stream
, 0);
5233 else if(var
== &ps
->vars
[V_DEFAULT_FCC
] ||
5234 var
== &ps
->vars
[V_DEFAULT_SAVE_FOLDER
]){
5235 init_save_defaults();
5237 else if(var
== &ps
->vars
[V_KW_BRACES
] ||
5238 var
== &ps
->vars
[V_OPENING_SEP
] ||
5239 var
== &ps
->vars
[V_ALT_ADDRS
]){
5240 clear_index_cache(ps
->mail_stream
, 0);
5242 else if(var
== &ps
->vars
[V_KEYWORDS
]){
5243 if(ps_global
->keywords
)
5244 free_keyword_list(&ps_global
->keywords
);
5246 if(var
->current_val
.l
&& var
->current_val
.l
[0])
5247 ps_global
->keywords
= init_keyword_list(var
->current_val
.l
);
5249 clear_index_cache(ps
->mail_stream
, 0);
5251 else if(var
== &ps
->vars
[V_INIT_CMD_LIST
]){
5253 q_status_message(SM_ASYNC
, 0, 3,
5254 _("Initial command changes will affect your next Alpine session."));
5256 else if(var
== &ps
->vars
[V_VIEW_HEADERS
]){
5257 ps
->view_all_except
= 0;
5258 if(ps
->VAR_VIEW_HEADERS
)
5259 for(v
= ps
->VAR_VIEW_HEADERS
; (q
= *v
) != NULL
; v
++)
5263 removing_leading_white_space(q
);
5264 /* look for colon or space or end */
5265 for(p
= q
; *p
&& !isspace((unsigned char)*p
) && *p
!= ':'; p
++)
5269 if(strucmp(q
, ALL_EXCEPT
) == 0)
5270 ps
->view_all_except
= 1;
5273 else if(var
== &ps
->vars
[V_OVERLAP
]){
5274 int old_value
= ps
->viewer_overlap
;
5276 if(SVAR_OVERLAP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5278 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5281 ps
->viewer_overlap
= old_value
;
5284 else if(smime_related_var(ps
, var
)){
5288 else if(var
== &ps
->vars
[V_MAXREMSTREAM
]){
5289 int old_value
= ps
->s_pool
.max_remstream
;
5291 if(SVAR_MAXREMSTREAM(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5293 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5296 ps
->s_pool
.max_remstream
= old_value
;
5298 dprint((9, "max_remstream goes to %d\n",
5299 ps
->s_pool
.max_remstream
));
5302 else if(var
== &ps
->vars
[V_CHAR_SET
]){
5305 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5307 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5310 if(reset_character_set_stuff(&err
) == -1)
5311 alpine_panic(err
? err
: "trouble with Character-Set");
5313 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5314 fs_give((void **) &err
);
5318 else if(var
== &ps
->vars
[V_KEY_CHAR_SET
]){
5321 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5323 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5326 if(reset_character_set_stuff(&err
) == -1)
5327 alpine_panic(err
? err
: "trouble with Character-Set");
5329 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5330 fs_give((void **) &err
);
5334 #endif /* ! _WINDOWS */
5335 else if(var
== &ps
->vars
[V_POST_CHAR_SET
]){
5336 update_posting_charset(ps
, revert
);
5338 else if(var
== &ps
->vars
[V_MARGIN
]){
5339 int old_value
= ps
->scroll_margin
;
5341 if(SVAR_MARGIN(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5343 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5346 ps
->scroll_margin
= old_value
;
5348 else if(var
== &ps
->vars
[V_DEADLETS
]){
5349 int old_value
= ps
->deadlets
;
5351 if(SVAR_DEADLETS(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5353 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5356 ps
->deadlets
= old_value
;
5358 else if(var
== &ps
->vars
[V_FILLCOL
]){
5359 if(SVAR_FILLCOL(ps
, ps
->composer_fillcol
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5361 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5364 else if(var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
5365 val
= ps
->quote_suppression_threshold
;
5366 if(val
< Q_SUPP_LIMIT
&& val
> 0)
5369 if(ps
->VAR_QUOTE_SUPPRESSION
5370 && SVAR_QUOTE_SUPPRESSION(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5372 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5375 if(val
> 0 && val
< Q_SUPP_LIMIT
){
5377 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, _("Ignoring Quote-Suppression-Threshold value of %s, see help"), ps
->VAR_QUOTE_SUPPRESSION
);
5378 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
5379 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5383 if(val
< 0 && val
!= Q_DEL_ALL
)
5384 ps
->quote_suppression_threshold
= -val
;
5386 ps
->quote_suppression_threshold
= val
;
5390 else if(var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
5391 if(SVAR_MSGDLAY(ps
, ps
->status_msg_delay
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5393 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5396 else if(var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
5397 if(SVAR_ACTIVEINTERVAL(ps
, ps
->active_status_interval
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5399 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5402 busy_cue(_("Active Example"), NULL
, 0);
5404 cancel_busy_cue(-1);
5407 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
5408 else if(var
== &ps
->vars
[V_FIFOPATH
]){
5409 init_newmailfifo(ps
->VAR_FIFOPATH
);
5412 else if(var
== &ps
->vars
[V_NMW_WIDTH
]){
5413 int old_value
= ps
->nmw_width
;
5415 if(SVAR_NMW_WIDTH(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5417 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5421 if(old_value
!= ps
->nmw_width
)
5422 mswin_setnewmailwidth(old_value
); /* actually the new value */
5424 ps
->nmw_width
= old_value
;
5427 else if(var
== &ps
->vars
[V_TCPOPENTIMEO
]){
5430 if(ps
->VAR_TCPOPENTIMEO
&& SVAR_TCP_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5431 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5433 else if(var
== &ps
->vars
[V_TCPREADWARNTIMEO
]){
5436 if(ps
->VAR_TCPREADWARNTIMEO
&& SVAR_TCP_READWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5437 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5439 else if(var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
]){
5442 if(ps
->VAR_TCPWRITEWARNTIMEO
&& SVAR_TCP_WRITEWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5443 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5445 else if(var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
5448 if(ps
->VAR_TCPQUERYTIMEO
&& SVAR_TCP_QUERY(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5449 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5451 else if(var
== &ps
->vars
[V_QUITQUERYTIMEO
]){
5454 if(ps
->VAR_QUITQUERYTIMEO
&& SVAR_QUIT_QUERY_TIMEO(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5455 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5457 else if(var
== &ps
->vars
[V_RSHOPENTIMEO
]){
5460 if(ps
->VAR_RSHOPENTIMEO
&& SVAR_RSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5461 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5463 else if(var
== &ps
->vars
[V_SSHOPENTIMEO
]){
5466 if(ps
->VAR_SSHOPENTIMEO
&& SVAR_SSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5467 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5469 else if(var
== &ps
->vars
[V_SIGNATURE_FILE
]){
5470 if(ps
->VAR_OPER_DIR
&& ps
->VAR_SIGNATURE_FILE
&&
5471 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
5472 !in_dir(ps
->VAR_OPER_DIR
, ps
->VAR_SIGNATURE_FILE
)){
5476 l
= strlen(ps
->VAR_OPER_DIR
) + 100;
5477 e
= (char *) fs_get((l
+1) * sizeof(char));
5478 snprintf(e
, l
+1, _("Warning: Sig file can't be outside of %s"),
5481 q_status_message(SM_ORDER
, 3, 6, e
);
5482 fs_give((void **)&e
);
5485 else if(var
== &ps
->vars
[V_OPER_DIR
]){
5486 if(ps
->VAR_OPER_DIR
&& !ps
->VAR_OPER_DIR
[0]){
5487 q_status_message(SM_ORDER
, 3, 5, "Operating-dir is turned off.");
5488 fs_give((void **)&ps
->vars
[V_OPER_DIR
].current_val
.p
);
5489 if(ps
->vars
[V_OPER_DIR
].fixed_val
.p
)
5490 fs_give((void **)&ps
->vars
[V_OPER_DIR
].fixed_val
.p
);
5491 if(ps
->vars
[V_OPER_DIR
].global_val
.p
)
5492 fs_give((void **)&ps
->vars
[V_OPER_DIR
].global_val
.p
);
5493 if(ps
->vars
[V_OPER_DIR
].cmdline_val
.p
)
5494 fs_give((void **)&ps
->vars
[V_OPER_DIR
].cmdline_val
.p
);
5495 if(ps
->vars
[V_OPER_DIR
].post_user_val
.p
)
5496 fs_give((void **)&ps
->vars
[V_OPER_DIR
].post_user_val
.p
);
5497 if(ps
->vars
[V_OPER_DIR
].main_user_val
.p
)
5498 fs_give((void **)&ps
->vars
[V_OPER_DIR
].main_user_val
.p
);
5501 else if(var
== &ps
->vars
[V_MAILCHECK
]){
5503 if(SVAR_MAILCHK(ps
, timeo
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5504 set_input_timeout(15);
5506 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5509 set_input_timeout(timeo
);
5510 if(get_input_timeout() == 0 && !revert
){
5511 q_status_message(SM_ORDER
, 4, 6,
5512 _("Warning: automatic new mail checking and mailbox checkpointing is disabled"));
5513 if(ps
->VAR_INBOX_PATH
&& ps
->VAR_INBOX_PATH
[0] == '{')
5514 q_status_message(SM_ASYNC
, 3, 6,
5515 _("Warning: Mail-Check-Interval=0 may cause IMAP server connection to time out"));
5519 else if(var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
5520 val
= (int) ps
->check_interval_for_noncurr
;
5521 if(ps
->VAR_MAILCHECKNONCURR
5522 && SVAR_MAILCHKNONCURR(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5524 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5527 ps
->check_interval_for_noncurr
= (time_t) val
;
5529 else if(var
== &ps
->vars
[V_MAILDROPCHECK
]){
5533 if(ps
->VAR_MAILDROPCHECK
&& SVAR_MAILDCHK(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5534 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5537 rvl
= (60L * 60L * 24L * 100L); /* 100 days */
5540 mail_parameters(NULL
, SET_SNARFINTERVAL
, (void *) rvl
);
5543 else if(var
== &ps
->vars
[V_NNTPRANGE
]){
5547 if(ps
->VAR_NNTPRANGE
&& SVAR_NNTPRANGE(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5548 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5551 mail_parameters(NULL
, SET_NNTPRANGE
, (void *) rvl
);
5554 else if(var
== &ps
->vars
[V_CUSTOM_HDRS
] || var
== &ps
->vars
[V_COMP_HDRS
]){
5555 /* this will give warnings about headers that can't be changed */
5556 if(!revert
&& var
->current_val
.l
&& var
->current_val
.l
[0])
5557 customized_hdr_setup(NULL
, var
->current_val
.l
, UseAsDef
);
5559 #if defined(DOS) || defined(OS2)
5560 else if(var
== &ps
->vars
[V_FOLDER_EXTENSION
]){
5561 mail_parameters(NULL
, SET_EXTENSION
,
5562 (void *)var
->current_val
.p
);
5564 else if(var
== &ps
->vars
[V_NEWSRC_PATH
]){
5565 if(var
->current_val
.p
&& var
->current_val
.p
[0])
5566 mail_parameters(NULL
, SET_NEWSRC
,
5567 (void *)var
->current_val
.p
);
5570 else if(revert
&& standard_radio_var(ps
, var
)){
5572 cur_rule_value(var
, TRUE
, FALSE
);
5573 if(var
== &ps_global
->vars
[V_AB_SORT_RULE
])
5574 addrbook_redo_sorts();
5575 else if(var
== &ps_global
->vars
[V_THREAD_INDEX_STYLE
]){
5576 clear_index_cache(ps_global
->mail_stream
, 0);
5577 set_lflags(ps_global
->mail_stream
, ps_global
->msgmap
,
5578 MN_COLL
| MN_CHID
, 0);
5579 if(SORT_IS_THREADED(ps_global
->msgmap
)
5580 && (SEP_THRDINDX() || COLL_THRDS()))
5581 collapse_threads(ps_global
->mail_stream
, ps_global
->msgmap
, NULL
);
5583 adjust_cur_to_visible(ps_global
->mail_stream
, ps_global
->msgmap
);
5586 else if(var
== &ps
->vars
[V_COLOR_STYLE
]){
5587 pico_toggle_color(0);
5588 switch(ps
->color_style
){
5591 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
5594 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
5597 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
5600 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
5604 if(ps
->color_style
!= COL_NONE
)
5605 pico_toggle_color(1);
5607 if(pico_usingcolor())
5608 pico_set_normal_color();
5610 clear_index_cache(ps_global
->mail_stream
, 0);
5612 ps
->mangled_screen
= 1;
5616 else if(revert
&& var
== &ps
->vars
[V_SORT_KEY
]){
5619 decode_sort(VAR_SORT_KEY
, &ps
->def_sort
, &def_sort_rev
);
5620 ps
->def_sort_rev
= def_sort_rev
;
5622 else if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5623 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5624 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5626 if(var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
] &&
5627 !(var
->current_val
.p
&& var
->current_val
.p
[0])){
5628 if(var
->current_val
.p
)
5629 fs_give((void **) &var
->current_val
.p
);
5631 q_status_message1(SM_ORDER
, 3, 5,
5632 _("\"%s\" can't be Empty, using default"), var
->name
);
5634 apval
= APVAL(var
, ew
);
5636 fs_give((void **)apval
);
5638 set_current_val(var
, FALSE
, FALSE
);
5640 if(!(var
->current_val
.p
&& var
->current_val
.p
[0]
5641 && !var
->current_val
.p
[1])){
5642 if(var
->current_val
.p
)
5643 fs_give((void **) &var
->current_val
.p
);
5645 var
->current_val
.p
= cpystr(DF_THREAD_LASTREPLY_CHAR
);
5649 if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5650 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5651 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5652 if(var
->current_val
.p
&& var
->current_val
.p
[0] &&
5653 var
->current_val
.p
[1]){
5654 q_status_message1(SM_ORDER
, 3, 5,
5655 "Only first character of \"%s\" is used",
5657 var
->current_val
.p
[1] = '\0';
5660 if(var
->main_user_val
.p
&& var
->main_user_val
.p
[0] &&
5661 var
->main_user_val
.p
[1])
5662 var
->main_user_val
.p
[1] = '\0';
5664 if(var
->post_user_val
.p
&& var
->post_user_val
.p
[0] &&
5665 var
->post_user_val
.p
[1])
5666 var
->post_user_val
.p
[1] = '\0';
5669 clear_index_cache(ps_global
->mail_stream
, 0);
5670 set_need_format_setup(ps_global
->mail_stream
);
5672 else if(var
== &ps
->vars
[V_NNTP_SERVER
]){
5673 free_contexts(&ps_global
->context_list
);
5674 init_folders(ps_global
);
5676 else if(var
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
]){
5679 else if(var
== &ps
->vars
[V_PRINTER
]){
5680 if(!revert
&& ps
->vars
[V_PERSONAL_PRINT_COMMAND
].is_fixed
){
5681 if(printer_value_check_and_adjust())
5682 q_status_message1(SM_ORDER
, 3, 5,
5683 _("Can't set \"%s\" to that value, see Setup/Printer"),
5684 pretty_var_name(var
->name
));
5687 else if(var
== &ps
->vars
[V_NORM_FORE_COLOR
] ||
5688 var
== &ps
->vars
[V_NORM_BACK_COLOR
] ||
5689 var
== &ps
->vars
[V_REV_FORE_COLOR
] ||
5690 var
== &ps
->vars
[V_REV_BACK_COLOR
] ||
5691 var
== &ps
->vars
[V_TITLE_FORE_COLOR
] ||
5692 var
== &ps
->vars
[V_TITLE_BACK_COLOR
] ||
5693 var
== &ps
->vars
[V_TITLECLOSED_FORE_COLOR
] ||
5694 var
== &ps
->vars
[V_TITLECLOSED_BACK_COLOR
] ||
5695 var
== &ps
->vars
[V_STATUS_FORE_COLOR
] ||
5696 var
== &ps
->vars
[V_STATUS_BACK_COLOR
] ||
5697 var
== &ps
->vars
[V_KEYLABEL_FORE_COLOR
] ||
5698 var
== &ps
->vars
[V_KEYLABEL_BACK_COLOR
] ||
5699 var
== &ps
->vars
[V_KEYNAME_FORE_COLOR
] ||
5700 var
== &ps
->vars
[V_KEYNAME_BACK_COLOR
]){
5701 set_current_color_vals(ps
);
5703 ps
->mangled_screen
= 1;
5705 else if(var
== &ps
->vars
[V_KW_COLORS
] ||
5706 var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
] ||
5707 var
== &ps
->vars
[V_IND_PLUS_FORE_COLOR
] ||
5708 var
== &ps
->vars
[V_IND_IMP_FORE_COLOR
] ||
5709 var
== &ps
->vars
[V_IND_DEL_FORE_COLOR
] ||
5710 var
== &ps
->vars
[V_IND_ANS_FORE_COLOR
] ||
5711 var
== &ps
->vars
[V_IND_NEW_FORE_COLOR
] ||
5712 var
== &ps
->vars
[V_IND_UNS_FORE_COLOR
] ||
5713 var
== &ps
->vars
[V_IND_HIPRI_FORE_COLOR
]||
5714 var
== &ps
->vars
[V_IND_LOPRI_FORE_COLOR
]||
5715 var
== &ps
->vars
[V_IND_ARR_FORE_COLOR
] ||
5716 var
== &ps
->vars
[V_IND_REC_FORE_COLOR
] ||
5717 var
== &ps
->vars
[V_IND_FWD_FORE_COLOR
] ||
5718 var
== &ps
->vars
[V_IND_OP_FORE_COLOR
] ||
5719 var
== &ps
->vars
[V_IND_FROM_FORE_COLOR
] ||
5720 var
== &ps
->vars
[V_IND_SUBJ_FORE_COLOR
] ||
5721 var
== &ps
->vars
[V_IND_PLUS_BACK_COLOR
] ||
5722 var
== &ps
->vars
[V_IND_IMP_BACK_COLOR
] ||
5723 var
== &ps
->vars
[V_IND_DEL_BACK_COLOR
] ||
5724 var
== &ps
->vars
[V_IND_ANS_BACK_COLOR
] ||
5725 var
== &ps
->vars
[V_IND_NEW_BACK_COLOR
] ||
5726 var
== &ps
->vars
[V_IND_UNS_BACK_COLOR
] ||
5727 var
== &ps
->vars
[V_IND_ARR_BACK_COLOR
] ||
5728 var
== &ps
->vars
[V_IND_REC_BACK_COLOR
] ||
5729 var
== &ps
->vars
[V_IND_FWD_BACK_COLOR
] ||
5730 var
== &ps
->vars
[V_IND_OP_BACK_COLOR
] ||
5731 var
== &ps
->vars
[V_IND_FROM_BACK_COLOR
] ||
5732 var
== &ps
->vars
[V_IND_SUBJ_BACK_COLOR
]){
5733 clear_index_cache(ps_global
->mail_stream
, 0);
5735 else if(var
== score_act_global_ptr
){
5738 score
= atoi(var
->current_val
.p
);
5739 if(score
< SCORE_MIN
|| score
> SCORE_MAX
){
5740 q_status_message2(SM_ORDER
, 3, 5,
5741 _("Score Value must be in range %s to %s"),
5742 comatose(SCORE_MIN
), comatose(SCORE_MAX
));
5743 apval
= APVAL(var
, ew
);
5745 fs_give((void **)apval
);
5747 set_current_val(var
, FALSE
, FALSE
);
5750 else if(var
== scorei_pat_global_ptr
|| var
== age_pat_global_ptr
5751 || var
== size_pat_global_ptr
|| var
== cati_global_ptr
){
5752 apval
= APVAL(var
, ew
);
5755 iv
= parse_intvl(*apval
);
5757 fs_give((void **) apval
);
5758 *apval
= stringform_of_intvl(iv
);
5762 fs_give((void **) apval
);
5765 set_current_val(var
, FALSE
, FALSE
);
5767 else if(var
== &ps
->vars
[V_FEATURE_LIST
]){
5768 process_feature_list(ps
, var
->current_val
.l
, 0, 0, 0);
5770 else if(!revert
&& (var
== &ps
->vars
[V_LAST_TIME_PRUNE_QUESTION
] ||
5771 var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
] ||
5772 var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
] ||
5773 var
== &ps
->vars
[V_USERINPUTTIMEO
] ||
5774 var
== &ps
->vars
[V_NEWS_ACTIVE_PATH
] ||
5775 var
== &ps
->vars
[V_NEWS_SPOOL_DIR
] ||
5776 var
== &ps
->vars
[V_INCOMING_FOLDERS
] ||
5777 var
== &ps
->vars
[V_FOLDER_SPEC
] ||
5778 var
== &ps
->vars
[V_NEWS_SPEC
] ||
5779 var
== &ps
->vars
[V_DISABLE_DRIVERS
] ||
5780 var
== &ps
->vars
[V_DISABLE_AUTHS
] ||
5781 var
== &ps
->vars
[V_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
] ||
5788 var
== &ps
->vars
[V_RSHPATH
] ||
5789 var
== &ps
->vars
[V_RSHCMD
] ||
5790 var
== &ps
->vars
[V_SSHCMD
] ||
5791 var
== &ps
->vars
[V_SSHPATH
])){
5792 q_status_message2(SM_ASYNC
, 0, 3,
5793 _("Changes%s%s will affect your next Alpine session."),
5794 var
->name
? " to " : "", var
->name
? var
->name
: "");
5797 if(!revert
&& (var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
5798 var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
5799 var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
5800 var
== &ps
->vars
[V_TCPQUERYTIMEO
] ||
5801 var
== &ps
->vars
[V_QUITQUERYTIMEO
] ||
5802 var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
5803 var
== &ps
->vars
[V_SSHOPENTIMEO
]))
5804 q_status_message(SM_ASYNC
, 0, 3,
5805 _("Timeout changes will affect your next Alpine session."));
5810 * Compare saved user_val with current user_val to see if it changed.
5811 * If any have changed, change it back and take the appropriate action.
5814 revert_to_saved_config(struct pine
*ps
, SAVED_CONFIG_S
*vsave
, int allow_hard_to_config_remotely
)
5816 struct variable
*vreal
;
5820 char *pval
, **apval
, **lval
, ***alval
;
5823 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5824 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5829 lval
= LVAL(vreal
, ew
);
5830 alval
= ALVAL(vreal
, ew
);
5832 if((v
->saved_user_val
.l
&& !lval
)
5833 || (!v
->saved_user_val
.l
&& lval
))
5835 else if(!v
->saved_user_val
.l
&& !lval
)
5836 ;/* no change, nothing to do */
5838 for(i
= 0; v
->saved_user_val
.l
[i
] || lval
[i
]; i
++)
5839 if((v
->saved_user_val
.l
[i
]
5841 || strcmp(v
->saved_user_val
.l
[i
], lval
[i
])))
5843 (!v
->saved_user_val
.l
[i
] && lval
[i
])){
5853 free_list_array(alval
);
5855 /* copy back the original one */
5856 if(v
->saved_user_val
.l
){
5857 list
= v
->saved_user_val
.l
;
5859 /* count how many */
5863 *alval
= (char **)fs_get((n
+1) * sizeof(char *));
5865 for(i
= 0; i
< n
; i
++)
5866 (*alval
)[i
] = cpystr(v
->saved_user_val
.l
[i
]);
5874 pval
= PVAL(vreal
, ew
);
5875 apval
= APVAL(vreal
, ew
);
5877 if((v
->saved_user_val
.p
&&
5878 (!pval
|| strcmp(v
->saved_user_val
.p
, pval
))) ||
5879 (!v
->saved_user_val
.p
&& pval
)){
5880 /* It changed, fix it */
5883 /* free the changed value */
5885 fs_give((void **)apval
);
5887 if(v
->saved_user_val
.p
)
5888 *apval
= cpystr(v
->saved_user_val
.p
);
5894 if(vreal
== &ps
->vars
[V_FEATURE_LIST
])
5895 set_feature_list_current_val(vreal
);
5897 set_current_val(vreal
, TRUE
, FALSE
);
5899 fix_side_effects(ps
, vreal
, 1);
5906 save_config_vars(struct pine
*ps
, int allow_hard_to_config_remotely
)
5908 struct variable
*vreal
;
5909 SAVED_CONFIG_S
*vsave
, *v
;
5911 vsave
= (SAVED_CONFIG_S
*)fs_get((V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5912 memset((void *)vsave
, 0, (V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5914 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5915 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5922 if(LVAL(vreal
, ew
)){
5923 /* count how many */
5925 list
= LVAL(vreal
, ew
);
5929 v
->saved_user_val
.l
= (char **)fs_get((n
+1) * sizeof(char *));
5930 memset((void *)v
->saved_user_val
.l
, 0, (n
+1)*sizeof(char *));
5931 for(i
= 0; i
< n
; i
++)
5932 v
->saved_user_val
.l
[i
] = cpystr(list
[i
]);
5934 v
->saved_user_val
.l
[n
] = NULL
;
5939 v
->saved_user_val
.p
= cpystr(PVAL(vreal
, ew
));
5948 free_saved_config(struct pine
*ps
, SAVED_CONFIG_S
**vsavep
, int allow_hard_to_config_remotely
)
5950 struct variable
*vreal
;
5953 if(vsavep
&& *vsavep
){
5954 for(v
= *vsavep
, vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5955 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5958 if(vreal
->is_list
){ /* free saved_user_val.l */
5959 if(v
&& v
->saved_user_val
.l
)
5960 free_list_array(&v
->saved_user_val
.l
);
5962 else if(v
&& v
->saved_user_val
.p
)
5963 fs_give((void **)&v
->saved_user_val
.p
);
5966 fs_give((void **)vsavep
);
5972 * Returns positive if any thing was actually deleted.
5975 delete_user_vals(struct variable
*v
)
5981 if(v
->post_user_val
.l
){
5983 free_list_array(&v
->post_user_val
.l
);
5985 if(v
->main_user_val
.l
){
5987 free_list_array(&v
->main_user_val
.l
);
5991 if(v
->post_user_val
.p
){
5993 fs_give((void **)&v
->post_user_val
.p
);
5995 if(v
->main_user_val
.p
){
5997 fs_give((void **)&v
->main_user_val
.p
);
6007 * ../pith/conf.c required function
6010 unexpected_pinerc_change(void)
6013 if(want_to("Unexpected pinerc change! Overwrite with current config",
6014 'n', 0, NO_HELP
, WT_FLUSH_IN
) == 'n'){
6015 return(-1); /* abort pinerc write */
6018 return(0); /* overwrite */
6024 /*----------------------------------------------------------------------
6025 MSWin scroll callback. Called during scroll message processing.
6029 Args: cmd - what type of scroll operation.
6030 scroll_pos - parameter for operation.
6031 used as position for SCROLL_TO operation.
6033 Returns: TRUE - did the scroll operation.
6034 FALSE - was not able to do the scroll operation.
6037 config_scroll_callback (cmd
, scroll_pos
)
6042 case MSWIN_KEY_SCROLLUPLINE
:
6043 config_scroll_down (scroll_pos
);
6046 case MSWIN_KEY_SCROLLDOWNLINE
:
6047 config_scroll_up (scroll_pos
);
6050 case MSWIN_KEY_SCROLLUPPAGE
:
6051 config_scroll_down (BODY_LINES(ps_global
));
6054 case MSWIN_KEY_SCROLLDOWNPAGE
:
6055 config_scroll_up (BODY_LINES(ps_global
));
6058 case MSWIN_KEY_SCROLLTO
:
6059 config_scroll_to_pos (scroll_pos
);
6063 option_screen_redrawer();
6069 #endif /* _WINDOWS */