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-2014 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
20 #include "confscroll.h"
29 #include "colorconf.h"
36 #include "../pith/state.h"
37 #include "../pith/flag.h"
38 #include "../pith/list.h"
39 #include "../pith/conf.h"
40 #include "../pith/util.h"
41 #include "../pith/newmail.h"
42 #include "../pith/sort.h"
43 #include "../pith/thread.h"
44 #include "../pith/color.h"
45 #include "../pith/hist.h"
46 #include "../pith/icache.h"
47 #include "../pith/conf.h"
48 #include "../pith/init.h"
49 #include "../pith/folder.h"
50 #include "../pith/busy.h"
51 #include "../pith/tempfile.h"
52 #include "../pith/pattern.h"
53 #include "../pith/charconv/utf8.h"
56 #define CONFIG_SCREEN_HELP_TITLE _("HELP FOR SETUP CONFIGURATION")
58 /* TRANSLATORS: Empty Value is what is shown in the configuration
59 screen when the user not only does not set an option but also
60 wants to explicitly not use the default value. Empty value means
61 an option with no value. */
62 char *empty_val
= N_("Empty Value");
63 char *empty_val2
= N_("<Empty Value>");
64 /* TRANSLATORS: No Value set is similar to Empty Value, but the
65 user has not explicitly decided to not use the default. It is
66 just an option which the user has left at the default value. */
67 char *no_val
= N_("No Value Set");
68 /* TRANSLATORS: Value is Fixed is what is displayed in the config
69 screen when the system managers have set an option to a specific
70 value and they don't allow the user to change it. The value
71 is fixed to a certain value. This isn't the same word as
72 Repaired, it means Unchanging. */
73 char *fixed_val
= N_("Value is Fixed");
74 char yesstr
[] = "Yes";
81 OPT_SCREEN_S
*opt_screen
;
85 * This is pretty ugly. Some of the routines operate differently depending
86 * on which variable they are operating on. Sometimes those variables are
87 * global (real alpine.h V_ style variables) and sometimes they are just
88 * local variables (as in role_config_edit_screen). These pointers are here
89 * so that the routines can figure out which variable they are operating
90 * on and do the right thing.
92 struct variable
*score_act_global_ptr
,
93 *scorei_pat_global_ptr
,
120 typedef NAMEVAL_S
*(*PTR_TO_RULEFUNC
)(int);
124 * Internal prototypes
126 PTR_TO_RULEFUNC
rulefunc_from_var(struct pine
*, struct variable
*);
127 void set_radio_pretty_vals(struct pine
*, CONF_S
**);
128 int save_include(struct pine
*, struct variable
*, int);
129 void config_scroll_up(long);
130 void config_scroll_down(long);
131 void config_scroll_to_pos(long);
132 CONF_S
*config_top_scroll(struct pine
*, CONF_S
*);
133 void update_option_screen(struct pine
*, OPT_SCREEN_S
*, Pos
*);
134 void print_option_screen(OPT_SCREEN_S
*, char *);
135 void option_screen_redrawer(void);
136 char *text_pretty_value(struct pine
*, CONF_S
*);
137 char *checkbox_pretty_value(struct pine
*, CONF_S
*);
138 char *yesno_pretty_value(struct pine
*, CONF_S
*);
139 char *radio_pretty_value(struct pine
*, CONF_S
*);
140 char *sigfile_pretty_value(struct pine
*, CONF_S
*);
141 char *color_pretty_value(struct pine
*, CONF_S
*);
142 char *sort_pretty_value(struct pine
*, CONF_S
*);
143 int longest_feature_name(void);
144 COLOR_PAIR
*sample_color(struct pine
*, struct variable
*);
145 COLOR_PAIR
*sampleexc_color(struct pine
*, struct variable
*);
146 void clear_feature(char ***, char *);
147 CONF_S
*last_confline(CONF_S
*);
149 int config_scroll_callback(int, long);
154 * We test for this same set of vars in a few places.
157 standard_radio_var(struct pine
*ps
, struct variable
*v
)
159 return(v
== &ps
->vars
[V_SAVED_MSG_NAME_RULE
] ||
160 v
== &ps
->vars
[V_FCC_RULE
] ||
161 v
== &ps
->vars
[V_GOTO_DEFAULT_RULE
] ||
162 v
== &ps
->vars
[V_INCOMING_STARTUP
] ||
163 v
== &ps
->vars
[V_PRUNING_RULE
] ||
164 v
== &ps
->vars
[V_REOPEN_RULE
] ||
165 v
== &ps
->vars
[V_THREAD_DISP_STYLE
] ||
166 v
== &ps
->vars
[V_THREAD_INDEX_STYLE
] ||
167 v
== &ps
->vars
[V_FLD_SORT_RULE
] ||
169 v
== &ps
->vars
[V_COLOR_STYLE
] ||
171 v
== &ps
->vars
[V_INDEX_COLOR_STYLE
] ||
172 v
== &ps
->vars
[V_TITLEBAR_COLOR_STYLE
] ||
173 v
== &ps
->vars
[V_AB_SORT_RULE
]);
178 rulefunc_from_var(struct pine
*ps
, struct variable
*v
)
180 PTR_TO_RULEFUNC rulefunc
= NULL
;
182 if(v
== &ps
->vars
[V_SAVED_MSG_NAME_RULE
])
183 rulefunc
= save_msg_rules
;
184 else if(v
== &ps
->vars
[V_FCC_RULE
])
185 rulefunc
= fcc_rules
;
186 else if(v
== &ps
->vars
[V_GOTO_DEFAULT_RULE
])
187 rulefunc
= goto_rules
;
188 else if(v
== &ps
->vars
[V_INCOMING_STARTUP
])
189 rulefunc
= incoming_startup_rules
;
190 else if(v
== startup_ptr
)
191 rulefunc
= startup_rules
;
192 else if(v
== &ps
->vars
[V_PRUNING_RULE
])
193 rulefunc
= pruning_rules
;
194 else if(v
== &ps
->vars
[V_REOPEN_RULE
])
195 rulefunc
= reopen_rules
;
196 else if(v
== &ps
->vars
[V_THREAD_DISP_STYLE
])
197 rulefunc
= thread_disp_styles
;
198 else if(v
== &ps
->vars
[V_THREAD_INDEX_STYLE
])
199 rulefunc
= thread_index_styles
;
200 else if(v
== &ps
->vars
[V_FLD_SORT_RULE
])
201 rulefunc
= fld_sort_rules
;
202 else if(v
== &ps
->vars
[V_AB_SORT_RULE
])
203 rulefunc
= ab_sort_rules
;
204 else if(v
== &ps
->vars
[V_INDEX_COLOR_STYLE
])
205 rulefunc
= index_col_style
;
206 else if(v
== &ps
->vars
[V_TITLEBAR_COLOR_STYLE
])
207 rulefunc
= titlebar_col_style
;
209 else if(v
== &ps
->vars
[V_COLOR_STYLE
])
210 rulefunc
= col_style
;
218 standard_radio_setup(struct pine
*ps
, CONF_S
**cl
, struct variable
*v
, CONF_S
**first_line
)
222 PTR_TO_RULEFUNC rulefunc
;
229 rulefunc
= rulefunc_from_var(ps
, v
);
232 (*cl
)->flags
|= CF_NOSELECT
;
233 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
236 /* put a nice delimiter before list */
237 new_confline(cl
)->var
= NULL
;
238 (*cl
)->varnamep
= ctmpb
;
239 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
240 (*cl
)->help
= NO_HELP
;
241 (*cl
)->tool
= radiobutton_tool
;
242 (*cl
)->valoffset
= rindent
;
243 (*cl
)->flags
|= CF_NOSELECT
;
244 /* TRANSLATORS: Set and Rule Values are the headings for an option
245 that can take one of several values. Underneath the Set heading
246 will be a column where one possibility is turned on (is Set).
247 The other column will be very short descriptions of what
248 the possibilities are (the Rule Values). */
249 utf8_snprintf(b
, sizeof(b
), "%-5.5w %s", _("Set"), _("Rule Values"));
250 (*cl
)->value
= cpystr(b
);
252 new_confline(cl
)->var
= NULL
;
253 (*cl
)->varnamep
= ctmpb
;
254 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
255 (*cl
)->help
= NO_HELP
;
256 (*cl
)->tool
= radiobutton_tool
;
257 (*cl
)->valoffset
= rindent
;
258 (*cl
)->flags
|= CF_NOSELECT
;
259 (*cl
)->value
= cpystr("--- ----------------------");
262 for(i
= 0; (f
= (*rulefunc
)(i
)); i
++){
263 new_confline(cl
)->var
= v
;
264 if(first_line
&& !*first_line
&& !pico_usingcolor())
267 (*cl
)->varnamep
= ctmpb
;
268 (*cl
)->keymenu
= &config_radiobutton_keymenu
;
269 (*cl
)->help
= (v
== startup_ptr
)
270 ? h_config_other_startup
271 : config_help(v
- ps
->vars
,0);
272 (*cl
)->tool
= radiobutton_tool
;
273 (*cl
)->valoffset
= rindent
;
275 (*cl
)->value
= pretty_value(ps
, *cl
);
281 * Reset the displayed values for all of the lines for this
282 * variable because others besides this line may change.
285 set_radio_pretty_vals(struct pine
*ps
, CONF_S
**cl
)
290 ((*cl
)->var
== &ps
->vars
[V_SORT_KEY
] ||
291 standard_radio_var(ps
, (*cl
)->var
) ||
292 (*cl
)->var
== startup_ptr
)))
297 ctmp
&& !(ctmp
->flags
& CF_NOSELECT
) && !ctmp
->varname
;
298 ctmp
= prev_confline(ctmp
)){
300 fs_give((void **)&ctmp
->value
);
302 ctmp
->value
= pretty_value(ps
, ctmp
);
307 ctmp
&& !ctmp
->varname
&& !(ctmp
->flags
& CF_NOSELECT
);
308 ctmp
= next_confline(ctmp
)){
310 fs_give((void **)&ctmp
->value
);
312 ctmp
->value
= pretty_value(ps
, ctmp
);
318 * test whether or not a var is
320 * returns: 1 if it should be excluded, 0 otw
323 exclude_config_var(struct pine
*ps
, struct variable
*var
, int allow_hard_to_config_remotely
)
325 if((ew
!= Main
&& (var
->is_onlymain
)) ||
326 (ew
!= ps_global
->ew_for_except_vars
&& var
->is_outermost
))
329 if(allow_hard_to_config_remotely
)
330 return(!(var
->is_user
&& var
->is_used
&& !var
->is_obsolete
));
332 switch(var
- ps
->vars
){
333 case V_MAIL_DIRECTORY
:
334 case V_INCOMING_FOLDERS
:
337 case V_STANDARD_PRINTER
:
338 case V_LAST_TIME_PRUNE_QUESTION
:
339 case V_LAST_VERS_USED
:
341 case V_GLOB_ADDRBOOK
:
342 case V_DISABLE_DRIVERS
:
343 case V_DISABLE_AUTHS
:
344 case V_REMOTE_ABOOK_METADATA
:
345 case V_REMOTE_ABOOK_HISTORY
:
346 case V_REMOTE_ABOOK_VALIDITY
:
348 case V_USERINPUTTIMEO
:
349 case V_TCPOPENTIMEO
:
350 case V_TCPREADWARNTIMEO
:
351 case V_TCPWRITEWARNTIMEO
:
352 case V_TCPQUERYTIMEO
:
355 case V_RSHOPENTIMEO
:
358 case V_SSHOPENTIMEO
:
359 case V_SENDMAIL_PATH
:
360 case V_NEW_VER_QUELL
:
369 case V_PERSONAL_PRINT_COMMAND
:
370 case V_PERSONAL_PRINT_CATEGORY
:
373 case V_WP_INDEXHEIGHT
:
374 case V_WP_INDEXLINES
:
379 case V_OLD_CHAR_SET
:
380 #endif /* ! _WINDOWS */
381 #if defined(DOS) || defined(OS2)
383 case V_UPLOAD_CMD_PREFIX
:
384 case V_DOWNLOAD_CMD
:
385 case V_DOWNLOAD_CMD_PREFIX
:
390 case V_FONT_CHAR_SET
:
391 case V_PRINT_FONT_NAME
:
392 case V_PRINT_FONT_SIZE
:
393 case V_PRINT_FONT_STYLE
:
394 case V_PRINT_FONT_CHAR_SET
:
395 case V_WINDOW_POSITION
:
396 case V_CURSOR_STYLE
:
397 #endif /* _WINDOWS */
400 case V_LDAP_SERVERS
:
401 #endif /* ENABLE_LDAP */
408 return(!(var
->is_user
&& var
->is_used
&& !var
->is_obsolete
&&
410 !smime_related_var(ps
, var
) &&
412 !color_related_var(ps
, var
)));
417 * Test to indicate what should be saved in case user wants to abandon
421 save_include(struct pine
*ps
, struct variable
*v
, int allow_hard_to_config_remotely
)
423 return(!exclude_config_var(ps
, v
, allow_hard_to_config_remotely
)
427 && (v
== &ps
->vars
[V_PERSONAL_PRINT_COMMAND
]
429 || v
== &ps
->vars
[V_LDAP_SERVERS
]
436 * Handles screen painting and motion. Passes other commands to
439 * Tool return values: Tools should return the following:
441 * -1 unrecognized command
442 * 1 something changed, conf_scroll_screen should remember that
443 * 2 tells conf_scroll_screen to return with value 1 or 0 depending
444 * on whether or not it has previously gotten a 1 from some tool.
445 * 3 tells conf_scroll_screen to return 1 (like 1 and 2 combined)
446 * ? Other tool-specific values can be used. They will cause
447 * conf_scroll_screen to return that value.
450 * 0 if nothing happened. That is, a tool returned 2 and we hadn't
451 * previously noted a return of 1
452 * 1 if something happened. That is, a tool returned 2 and we had
453 * previously noted a return of 1
454 * ? Tool-returned value different from -1, 0, 1, 2, or 3. This is it.
456 * Special proviso: If first_line->flags has CF_CHANGES set on entry, then
457 * that will cause things to behave like a change was made since entering
461 conf_scroll_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, CONF_S
*start_line
, char *title
, char *pdesc
, int multicol
)
466 int cmd
, i
, j
, done
= 0, changes
= 0;
468 int km_popped
= 0, stay_in_col
= 0;
469 struct key_menu
*km
= NULL
;
470 CONF_S
*ctmpa
= NULL
, *ctmpb
= NULL
;
472 OtherMenu what_keymenu
= FirstMenu
;
473 void (*prev_redrawer
)(void);
475 dprint((7, "conf_scroll_screen()\n"));
477 if(BODY_LINES(ps
) < 1){
478 q_status_message(SM_ORDER
| SM_DING
, 3, 3, _("Screen too small"));
482 if(screen
&& screen
->ro_warning
)
483 q_status_message1(SM_ORDER
, 1, 3,
484 /* TRANSLATORS: "Config file not changeable," is what replaces the %s */
485 _("%s can't change options or settings"),
486 ps_global
->restricted
? "Alpine demo"
487 : _("Config file not changeable,"));
489 screen
->current
= start_line
;
490 if(start_line
&& start_line
->flags
& CF_CHANGES
)
494 ps
->mangled_screen
= 1;
495 ps
->redrawer
= option_screen_redrawer
;
498 ps
->user_says_cancel
= 0;
503 ps
->mangled_body
= 1;
507 if(ps
->mangled_screen
){
508 ps
->mangled_header
= 1;
509 ps
->mangled_footer
= 1;
510 ps
->mangled_body
= 1;
511 ps
->mangled_screen
= 0;
514 /*----------- Check for new mail -----------*/
515 if(new_mail(0, NM_TIMING(ch
), NM_STATUS_MSG
| NM_DEFER_SORT
) >= 0)
516 ps
->mangled_header
= 1;
518 if(ps
->mangled_header
){
519 set_titlebar(title
, ps
->mail_stream
,
521 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
522 ps
->mangled_header
= 0;
525 update_option_screen(ps
, screen
, &cursor_pos
);
527 if(F_OFF(F_SHOW_CURSOR
, ps
)){
528 cursor_pos
.row
= ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
);
532 /*---- This displays new mail notification, or errors ---*/
535 mark_status_unknown();
541 mark_status_unknown();
544 if(ps
->mangled_footer
|| km
!= screen
->current
->keymenu
){
549 ps
->mangled_footer
= 0;
550 km
= screen
->current
->keymenu
;
553 (F_OFF(F_ARROW_NAV
, ps_global
) ||
554 F_ON(F_RELAXED_ARROW_NAV
, ps_global
))){
555 menu_clear_binding(km
, KEY_LEFT
);
556 menu_clear_binding(km
, KEY_RIGHT
);
557 menu_clear_binding(km
, KEY_UP
);
558 menu_clear_binding(km
, KEY_DOWN
);
559 menu_add_binding(km
, KEY_UP
, MC_CHARUP
);
560 menu_add_binding(km
, KEY_DOWN
, MC_CHARDOWN
);
561 menu_add_binding(km
, KEY_LEFT
, MC_PREVITEM
);
562 menu_add_binding(km
, ctrl('B'), MC_PREVITEM
);
563 menu_add_binding(km
, KEY_RIGHT
, MC_NEXTITEM
);
564 menu_add_binding(km
, ctrl('F'), MC_NEXTITEM
);
567 menu_clear_binding(km
, KEY_LEFT
);
568 menu_clear_binding(km
, KEY_RIGHT
);
569 menu_clear_binding(km
, KEY_UP
);
570 menu_clear_binding(km
, KEY_DOWN
);
573 * Fix up arrow nav mode if necessary...
575 if(F_ON(F_ARROW_NAV
, ps_global
)){
578 if((cmd
= menu_clear_binding(km
, '<')) != MC_UNKNOWN
){
579 menu_add_binding(km
, '<', cmd
);
580 menu_add_binding(km
, KEY_LEFT
, cmd
);
583 if((cmd
= menu_clear_binding(km
, '>')) != MC_UNKNOWN
){
584 menu_add_binding(km
, '>', cmd
);
585 menu_add_binding(km
, KEY_RIGHT
, cmd
);
588 if((cmd
= menu_clear_binding(km
, 'p')) != MC_UNKNOWN
){
589 menu_add_binding(km
, 'p', cmd
);
590 menu_add_binding(km
, KEY_UP
, cmd
);
593 if((cmd
= menu_clear_binding(km
, 'n')) != MC_UNKNOWN
){
594 menu_add_binding(km
, 'n', cmd
);
595 menu_add_binding(km
, KEY_DOWN
, cmd
);
605 draw_keymenu(km
, bitmap
, ps
->ttyo
->screen_cols
,
606 1-FOOTER_ROWS(ps
), 0, what_keymenu
);
607 what_keymenu
= SameMenu
;
611 mark_keymenu_dirty();
615 MoveCursor(cursor_pos
.row
, cursor_pos
.col
);
617 mouse_in_content(KEY_MOUSE
, -1, -1, 0, 0); /* prime the handler */
618 register_mfunc(mouse_in_content
, HEADER_ROWS(ps_global
), 0,
619 ps_global
->ttyo
->screen_rows
-(FOOTER_ROWS(ps_global
)+1),
620 ps_global
->ttyo
->screen_cols
);
623 mswin_setscrollcallback(config_scroll_callback
);
625 /*------ Read the command from the keyboard ----*/
626 ch
= READ_COMMAND(&utf8str
);
628 clear_mfunc(mouse_in_content
);
631 mswin_setscrollcallback(NULL
);
634 cmd
= menu_command(ch
, km
);
652 what_keymenu
= NextMenu
;
653 ps
->mangled_footer
= 1;
656 case MC_HELP
: /* help! */
657 if(FOOTER_ROWS(ps
) == 1 && km_popped
== 0){
659 ps
->mangled_footer
= 1;
663 if(screen
->current
->help
!= NO_HELP
){
664 prev_redrawer
= ps_global
->redrawer
;
665 helper(screen
->current
->help
,
666 (screen
->current
->help_title
)
667 ? screen
->current
->help_title
668 : CONFIG_SCREEN_HELP_TITLE
,
670 ps_global
->redrawer
= prev_redrawer
;
671 ps
->mangled_screen
= 1;
674 q_status_message(SM_ORDER
,0,3,_("No help yet."));
679 case MC_NEXTITEM
: /* next list element */
682 if(screen
->current
->flags
& CF_DOUBLEVAR
){
683 /* if going from col1 to col2, it's simple */
684 if(!(screen
->current
->flags
& CF_VAR2
) && cmd
== MC_NEXTITEM
){
685 screen
->current
->flags
|= CF_VAR2
;
689 /* otherwise we fall through to normal next */
690 stay_in_col
= (screen
->current
->flags
& CF_VAR2
&&
692 screen
->current
->flags
&= ~CF_VAR2
;
695 for(ctmpa
= next_confline(screen
->current
), i
= 1;
696 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
697 ctmpa
= next_confline(ctmpa
), i
++)
701 screen
->current
= ctmpa
;
702 if(screen
->current
->flags
& CF_DOUBLEVAR
&& stay_in_col
)
703 screen
->current
->flags
|= CF_VAR2
;
705 if(cmd
== MC_CHARDOWN
){
706 for(ctmpa
= screen
->top_line
,
707 j
= BODY_LINES(ps
) - 1 - HS_MARGIN(ps
);
708 j
> 0 && ctmpa
&& ctmpa
!= screen
->current
;
709 ctmpa
= next_confline(ctmpa
), j
--)
714 ctmpa
&& ctmpa
!= screen
->current
;
715 ctmpa
= next_confline(ctmpa
), i
++)
725 * Scroll screen a bit so we show the non-selectable
726 * lines at the bottom.
729 /* set ctmpa to the bottom line on the screen */
730 for(ctmpa
= screen
->top_line
, j
= BODY_LINES(ps
) - 1;
732 ctmpa
= next_confline(ctmpa
), j
--)
737 for(ctmpa
= next_confline(ctmpa
);
739 (ctmpa
->flags
& (CF_NOSELECT
| CF_B_LINE
)) ==
741 ctmpa
= next_confline(ctmpa
), i
++)
748 q_status_message(SM_ORDER
,0,1, _("Already at end of screen"));
753 case MC_PREVITEM
: /* prev list element */
756 if(screen
->current
->flags
& CF_DOUBLEVAR
){
757 if(screen
->current
->flags
& CF_VAR2
&& cmd
== MC_PREVITEM
){
758 screen
->current
->flags
&= ~CF_VAR2
;
762 /* otherwise we fall through to normal prev */
763 stay_in_col
= (!(screen
->current
->flags
& CF_VAR2
) &&
765 screen
->current
->flags
&= ~CF_VAR2
;
767 else if(cmd
== MC_CHARUP
)
770 ctmpa
= screen
->current
;
773 if(ctmpa
== config_top_scroll(ps
, screen
->top_line
))
777 while((ctmpa
= prev_confline(ctmpa
))
778 && (ctmpa
->flags
&CF_NOSELECT
));
781 screen
->current
= ctmpa
;
782 if(screen
->current
->flags
& CF_DOUBLEVAR
&& !stay_in_col
)
783 screen
->current
->flags
|= CF_VAR2
;
785 if((cmd
== MC_CHARUP
) && i
)
786 config_scroll_down(i
);
789 q_status_message(SM_ORDER
, 0, 1,
790 _("Already at start of screen"));
794 case MC_PAGEDN
: /* page forward */
795 screen
->current
->flags
&= ~CF_VAR2
;
796 for(ctmpa
= screen
->top_line
, i
= BODY_LINES(ps
);
798 ctmpb
= ctmpa
, ctmpa
= next_confline(ctmpa
), i
--)
801 if(ctmpa
){ /* first line off bottom of screen */
803 ps
->mangled_body
= 1;
804 /* find first selectable line on next page */
805 for(screen
->top_line
= ctmpa
;
806 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
807 ctmpa
= next_confline(ctmpa
))
811 * No selectable lines on next page. Slide up to first
815 for(ctmpa
= prev_confline(ctmpb
);
816 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
817 ctmpa
= prev_confline(ctmpa
))
821 screen
->top_line
= ctmpa
;
824 else{ /* on last screen */
825 /* just move current down to last entry on screen */
826 if(ctmpb
){ /* last line of data */
827 for(ctmpa
= ctmpb
, i
= BODY_LINES(ps
);
828 i
> 0 && ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
829 ctmpa
= prev_confline(ctmpa
), i
--)
832 if(ctmpa
== screen
->current
){
833 q_status_message(SM_ORDER
,0,1,
834 _("Already at end of screen"));
838 ps
->mangled_body
= 1;
843 screen
->current
= ctmpa
;
847 case MC_PAGEUP
: /* page backward */
848 ps
->mangled_body
= 1;
849 screen
->current
->flags
&= ~CF_VAR2
;
850 if(!(ctmpa
=prev_confline(screen
->top_line
)))
851 ctmpa
= screen
->current
;
853 for(i
= BODY_LINES(ps
) - 1;
854 i
> 0 && prev_confline(ctmpa
);
855 i
--, ctmpa
= prev_confline(ctmpa
))
858 for(screen
->top_line
= ctmpa
;
859 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
860 ctmpa
= next_confline(ctmpa
))
864 if(ctmpa
== screen
->current
){
866 * We get to here if there was nothing selectable on
867 * the previous page. There still may be something
868 * selectable further back than the previous page,
871 for(ctmpa
= prev_confline(screen
->top_line
);
872 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
873 ctmpa
= prev_confline(ctmpa
))
877 ctmpa
= screen
->current
;
878 q_status_message(SM_ORDER
, 0, 1,
879 _("Already at start of screen"));
883 screen
->current
= ctmpa
;
893 mouse_get_last (NULL
, &mp
);
894 mp
.row
-= HEADER_ROWS(ps
);
895 ctmpa
= screen
->top_line
;
897 while (mp
.row
&& ctmpa
!= NULL
) {
902 if (ctmpa
!= NULL
&& !(ctmpa
->flags
& CF_NOSELECT
)){
903 if(screen
->current
->flags
& CF_DOUBLEVAR
)
904 screen
->current
->flags
&= ~CF_VAR2
;
906 screen
->current
= ctmpa
;
908 if(screen
->current
->flags
& CF_DOUBLEVAR
&&
909 mp
.col
>= screen
->current
->val2offset
)
910 screen
->current
->flags
|= CF_VAR2
;
912 update_option_screen(ps
, screen
, &cursor_pos
);
914 if(mp
.button
== M_BUTTON_LEFT
&& mp
.doubleclick
){
916 if(screen
->current
->tool
){
920 flags
= screen
->current
->flags
;
921 flags
|= (changes
? CF_CHANGES
: 0);
923 default_cmd
= menu_command(ctrl('M'), km
);
924 switch(i
=(*screen
->current
->tool
)(ps
, default_cmd
,
925 &screen
->current
, flags
)){
952 else if(mp
.button
== M_BUTTON_RIGHT
) {
953 MPopup other_popup
[20];
955 struct key_menu
*sckm
= screen
->current
->keymenu
; /* only for popup */
957 if((cmd
= menu_command(ctrl('M'), sckm
)) != MC_UNKNOWN
){
958 i
= menu_binding_index(sckm
, cmd
);
959 other_popup
[++n
].type
= tQueue
;
960 other_popup
[n
].label
.style
= lNormal
;
961 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
962 other_popup
[n
].data
.val
= ctrl('M');
964 else if((cmd
= menu_command('>', sckm
)) != MC_UNKNOWN
){
965 i
= menu_binding_index(sckm
, cmd
);
966 other_popup
[++n
].type
= tQueue
;
967 other_popup
[n
].label
.style
= lNormal
;
968 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
969 other_popup
[n
].data
.val
= '>';
972 if(((i
= menu_binding_index(sckm
, MC_RGB1
)) >= 0) ||
973 ((i
= menu_binding_index(sckm
, MC_RGB2
)) >= 0)){
974 other_popup
[++n
].type
= tQueue
;
975 other_popup
[n
].label
.style
= lNormal
;
976 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
977 other_popup
[n
].data
.val
=
978 sckm
->keys
[i
].bind
.ch
[0];
981 if((cmd
= menu_command('<', sckm
)) != MC_UNKNOWN
){
982 i
= menu_binding_index(sckm
, cmd
);
983 other_popup
[++n
].type
= tQueue
;
984 other_popup
[n
].label
.style
= lNormal
;
985 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
986 other_popup
[n
].data
.val
= '<';
988 else if((i
= menu_binding_index(sckm
, MC_EXIT
)) >= 0){
989 other_popup
[++n
].type
= tQueue
;
990 other_popup
[n
].label
.style
= lNormal
;
991 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
992 other_popup
[n
].data
.val
=
993 sckm
->keys
[i
].bind
.ch
[0];
996 if((i
= menu_binding_index(sckm
, MC_HELP
)) >= 0){
998 other_popup
[++n
].type
= tSeparator
;
1000 other_popup
[++n
].type
= tQueue
;
1001 other_popup
[n
].label
.style
= lNormal
;
1002 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1003 other_popup
[n
].data
.val
= sckm
->keys
[i
].bind
.ch
[0];
1007 other_popup
[++n
].type
= tTail
;
1008 mswin_popup(other_popup
);
1012 else if(mp
.button
== M_BUTTON_RIGHT
) {
1013 MPopup other_popup
[20];
1015 struct key_menu
*sckm
= screen
->current
->keymenu
; /* only for popup */
1017 if((cmd
= menu_command('<', sckm
)) != MC_UNKNOWN
){
1018 i
= menu_binding_index(sckm
, cmd
);
1019 other_popup
[++n
].type
= tQueue
;
1020 other_popup
[n
].label
.style
= lNormal
;
1021 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1022 other_popup
[n
].data
.val
= '<';
1024 else if((i
= menu_binding_index(sckm
, MC_EXIT
)) >= 0){
1025 other_popup
[++n
].type
= tQueue
;
1026 other_popup
[n
].label
.style
= lNormal
;
1027 other_popup
[n
].label
.string
= sckm
->keys
[i
].label
;
1028 other_popup
[n
].data
.val
= sckm
->keys
[i
].bind
.ch
[0];
1031 other_popup
[++n
].type
= tTail
;
1034 mswin_popup(other_popup
);
1041 case MC_PRINTTXT
: /* print screen */
1042 print_option_screen(screen
, pdesc
? pdesc
: "");
1045 case MC_WHEREIS
: /* whereis */
1046 /*--- get string ---*/
1048 #define FOUND_IT 0x01
1049 #define FOUND_CURRENT 0x02
1050 #define FOUND_WRAPPED 0x04
1051 #define FOUND_NOSELECT 0x08
1052 #define FOUND_ABOVE 0x10
1053 char *result
= NULL
, buf
[64];
1055 static HISTORY_S
*history
= NULL
;
1057 static ESCKEY_S ekey
[] = {
1059 /* TRANSLATORS: go to Top of screen */
1060 {ctrl('Y'), 10, "^Y", N_("Top")},
1061 {ctrl('V'), 11, "^V", N_("Bottom")},
1062 {KEY_UP
, 30, "", ""},
1063 {KEY_DOWN
, 31, "", ""},
1064 {-1, 0, NULL
, NULL
}};
1065 #define KU_WI (3) /* index of KEY_UP */
1067 init_hist(&history
, HISTSIZE
);
1069 if((p
= get_prev_hist(history
, "", 0, NULL
)) != NULL
){
1070 strncpy(last
, p
, sizeof(last
));
1071 last
[sizeof(last
)-1] = '\0';
1074 ps
->mangled_footer
= 1;
1076 snprintf(tmp
, sizeof(tmp
), "Word to find %s%s%s: ",
1077 (last
[0]) ? "[" : "",
1078 (last
[0]) ? last
: "",
1079 (last
[0]) ? "]" : "");
1080 tmp
[sizeof(tmp
)-1] = '\0';
1083 int flags
= OE_APPEND_CURRENT
;
1086 * 2 is really 1 because there will be one real entry and
1087 * one entry of "" because of the get_prev_hist above.
1089 if(items_in_hist(history
) > 2){
1090 ekey
[KU_WI
].name
= HISTORY_UP_KEYNAME
;
1091 ekey
[KU_WI
].label
= HISTORY_KEYLABEL
;
1092 ekey
[KU_WI
+1].name
= HISTORY_DOWN_KEYNAME
;
1093 ekey
[KU_WI
+1].label
= HISTORY_KEYLABEL
;
1096 ekey
[KU_WI
].name
= "";
1097 ekey
[KU_WI
].label
= "";
1098 ekey
[KU_WI
+1].name
= "";
1099 ekey
[KU_WI
+1].label
= "";
1102 rc
= optionally_enter(buf
,-FOOTER_ROWS(ps
),0,sizeof(buf
),
1103 tmp
,ekey
,help
,&flags
);
1105 help
= help
== NO_HELP
? h_config_whereis
: NO_HELP
;
1107 if((p
= get_prev_hist(history
, buf
, 0, NULL
)) != NULL
){
1108 strncpy(buf
, p
, sizeof(buf
));
1109 buf
[sizeof(buf
)-1] = '\0';
1117 if((p
= get_next_hist(history
, buf
, 0, NULL
)) != NULL
){
1118 strncpy(buf
, p
, sizeof(buf
));
1119 buf
[sizeof(buf
)-1] = '\0';
1126 else if(rc
== 0 || rc
== 1 || rc
== 10 || rc
== 11 || !buf
[0]){
1127 if(rc
== 0 && !buf
[0] && last
[0])
1128 strncpy(buf
, last
, 64);
1134 screen
->current
->flags
&= ~CF_VAR2
;
1135 if(rc
== 0 && buf
[0]){
1136 CONF_S
*started_here
;
1138 save_hist(history
, buf
, 0, NULL
);
1141 ctmpa
= screen
->current
;
1143 * Skip over the unselectable lines of this "item"
1144 * before starting search so that we don't find the
1147 while((ctmpb
= next_confline(ctmpa
)) &&
1148 (ctmpb
->flags
& CF_NOSELECT
) &&
1149 !(ctmpb
->flags
& CF_STARTITEM
))
1152 started_here
= next_confline(ctmpa
);
1153 while((ctmpa
= next_confline(ctmpa
)) != NULL
)
1154 if(srchstr(ctmpa
->varname
, buf
)
1155 || srchstr(ctmpa
->value
, buf
)){
1159 * If this line is not selectable, back up to the
1160 * previous selectable line, but not past the
1161 * start of this "entry".
1163 if(ctmpa
->flags
& CF_NOSELECT
)
1164 found
|= FOUND_NOSELECT
;
1166 while((ctmpa
->flags
& CF_NOSELECT
) &&
1167 !(ctmpa
->flags
& CF_STARTITEM
) &&
1168 (ctmpb
= prev_confline(ctmpa
)))
1172 * If that isn't selectable, better search forward
1173 * for something that is.
1175 while((ctmpa
->flags
& CF_NOSELECT
) &&
1176 (ctmpb
= next_confline(ctmpa
))){
1178 found
|= FOUND_ABOVE
;
1182 * If that still isn't selectable, better search
1183 * backwards for something that is.
1185 while((ctmpa
->flags
& CF_NOSELECT
) &&
1186 (ctmpb
= prev_confline(ctmpa
))){
1188 found
&= ~FOUND_ABOVE
;
1195 found
= FOUND_WRAPPED
;
1196 ctmpa
= first_confline(screen
->current
);
1198 while(ctmpa
!= started_here
)
1199 if(srchstr(ctmpa
->varname
, buf
)
1200 || srchstr(ctmpa
->value
, buf
)){
1203 if(ctmpa
->flags
& CF_NOSELECT
)
1204 found
|= FOUND_NOSELECT
;
1206 while((ctmpa
->flags
& CF_NOSELECT
) &&
1207 !(ctmpa
->flags
& CF_STARTITEM
) &&
1208 (ctmpb
= prev_confline(ctmpa
)))
1211 while((ctmpa
->flags
& CF_NOSELECT
) &&
1212 (ctmpb
= next_confline(ctmpa
))){
1214 found
|= FOUND_ABOVE
;
1217 if(ctmpa
== screen
->current
)
1218 found
|= FOUND_CURRENT
;
1223 ctmpa
= next_confline(ctmpa
);
1227 screen
->current
= first_confline(screen
->current
);
1228 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1229 for(ctmpa
= next_confline(screen
->current
);
1230 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1231 ctmpa
= next_confline(ctmpa
))
1235 screen
->current
= ctmpa
;
1238 /* TRANSLATORS: Searched to ... is the result of the search, searched
1239 to top means the search went past the bottom of the screen and
1240 wrapped back around to the top. */
1241 result
= _("Searched to top");
1244 screen
->current
= last_confline(screen
->current
);
1245 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1246 for(ctmpa
= prev_confline(screen
->current
);
1247 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1248 ctmpa
= prev_confline(ctmpa
))
1252 screen
->current
= ctmpa
;
1255 result
= _("Searched to bottom");
1258 result
= _("WhereIs cancelled");
1260 if((found
& FOUND_IT
) && ctmpa
){
1261 strncpy(last
, buf
, 64);
1263 (found
& FOUND_CURRENT
&& found
& FOUND_WRAPPED
&& found
& FOUND_NOSELECT
)
1264 ? _("Current item contains the only match")
1265 : (found
& FOUND_CURRENT
&& found
& FOUND_WRAPPED
)
1266 ? _("Current line contains the only match")
1267 : (found
& FOUND_NOSELECT
&& found
& FOUND_WRAPPED
)
1268 ? ((found
& FOUND_ABOVE
)
1269 ? _("Search wrapped: word found in text above current line")
1270 : _("Search wrapped: word found in text below current line"))
1271 : (found
& FOUND_WRAPPED
)
1272 ? _("Search wrapped to beginning: word found")
1273 : (found
& FOUND_NOSELECT
)
1274 ? ((found
& FOUND_ABOVE
)
1275 ? _("Word found in text above current line")
1276 : _("Word found in text below current line"))
1278 screen
->current
= ctmpa
;
1281 q_status_message(SM_ORDER
,0,3,result
? result
: _("Word not found"));
1287 screen
->current
= first_confline(screen
->current
);
1288 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1289 for(ctmpa
= next_confline(screen
->current
);
1290 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1291 ctmpa
= next_confline(ctmpa
))
1295 screen
->current
= ctmpa
;
1298 q_status_message(SM_ORDER
,0,3, _("Moved to top"));
1302 screen
->current
= last_confline(screen
->current
);
1303 if(screen
->current
&& screen
->current
->flags
& CF_NOSELECT
){
1304 for(ctmpa
= prev_confline(screen
->current
);
1305 ctmpa
&& (ctmpa
->flags
& CF_NOSELECT
);
1306 ctmpa
= prev_confline(ctmpa
))
1310 screen
->current
= ctmpa
;
1313 q_status_message(SM_ORDER
,0,3, _("Moved to bottom"));
1316 case MC_REPAINT
: /* redraw the display */
1319 ps
->mangled_screen
= 1;
1323 if(screen
&& screen
->ro_warning
){
1329 q_status_message1(SM_ORDER
|SM_DING
, 1, 3,
1330 _("%s can't change options or settings"),
1331 ps_global
->restricted
? "Alpine demo"
1332 : _("Config file not changeable,"));
1334 else if(screen
->current
->tool
){
1337 flags
= screen
->current
->flags
;
1338 flags
|= (changes
? CF_CHANGES
: 0);
1340 switch(i
=(*screen
->current
->tool
)(ps
, cmd
,
1341 &screen
->current
, flags
)){
1343 q_status_message2(SM_ORDER
, 0, 2,
1344 /* TRANSLATORS: Command <command letter> not defined here.
1345 Leave the trailing %s which might be a parenthetical
1347 _("Command \"%s\" not defined here.%s"),
1349 F_ON(F_BLANK_KEYMENU
,ps
) ? "" : " See key menu below.");
1379 bogus_utf8_command(utf8str
, "?");
1382 case MC_NONE
: /* simple timeout */
1387 screen
->current
= first_confline(screen
->current
);
1388 free_conflines(&screen
->current
);
1397 config_scroll_up(long int n
)
1399 CONF_S
*ctmp
= opt_screen
->top_line
;
1403 config_scroll_down(-n
);
1405 for(; n
>0 && ctmp
->next
; n
--){
1406 ctmp
= next_confline(ctmp
);
1407 if(prev_confline(ctmp
) == opt_screen
->current
)
1411 opt_screen
->top_line
= ctmp
;
1412 ps_global
->mangled_body
= 1;
1414 for(ctmp
= opt_screen
->top_line
;
1415 ctmp
&& (ctmp
->flags
& CF_NOSELECT
);
1416 ctmp
= next_confline(ctmp
))
1420 opt_screen
->current
= opt_screen
->prev
= ctmp
;
1422 while(opt_screen
->top_line
->flags
& CF_NOSELECT
)
1423 opt_screen
->top_line
= prev_confline(opt_screen
->top_line
);
1424 opt_screen
->current
= opt_screen
->prev
= opt_screen
->top_line
;
1432 * config_scroll_down -
1435 config_scroll_down(long int n
)
1437 CONF_S
*ctmp
= opt_screen
->top_line
, *last_sel
= NULL
;
1441 config_scroll_up(-n
);
1443 for(; n
>0 && ctmp
->prev
; n
--)
1444 ctmp
= prev_confline(ctmp
);
1446 opt_screen
->top_line
= ctmp
;
1447 ps_global
->mangled_body
= 1;
1448 for(ctmp
= opt_screen
->top_line
, i
= BODY_LINES(ps_global
);
1449 i
> 0 && ctmp
&& ctmp
!= opt_screen
->current
;
1450 ctmp
= next_confline(ctmp
), i
--)
1451 if(!(ctmp
->flags
& CF_NOSELECT
))
1455 opt_screen
->current
= opt_screen
->prev
= last_sel
;
1461 * config_scroll_to_pos -
1464 config_scroll_to_pos(long int n
)
1468 for(ctmp
= first_confline(opt_screen
->current
);
1469 n
&& ctmp
&& ctmp
!= opt_screen
->top_line
;
1470 ctmp
= next_confline(ctmp
), n
--)
1474 while(ctmp
&& ctmp
!= opt_screen
->top_line
)
1475 if((ctmp
= next_confline(ctmp
)) != NULL
)
1478 config_scroll_up(n
);
1483 * config_top_scroll - return pointer to the
1486 config_top_scroll(struct pine
*ps
, CONF_S
*topline
)
1491 for(ctmp
= topline
, i
= HS_MARGIN(ps
);
1493 ctmp
= next_confline(ctmp
), i
--)
1496 return(ctmp
? ctmp
: topline
);
1501 text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
1503 return(text_toolit(ps
, cmd
, cl
, flags
, 0));
1508 * simple text variable handler
1510 * note, things get a little involved due to the
1511 * screen struct <--> variable mapping. (but, once its
1512 * running it shouldn't need changing ;).
1514 * look_for_backslash == 1 means that backslash is an escape character.
1515 * In particular, \, can be used to put a literal comma
1516 * into a value. The value will still have the backslash
1517 * in it, but the comma after the backslash won't be treated
1518 * as an item separator.
1520 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
1521 * returns what conf_exit_cmd returns for exit command.
1524 text_toolit(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
, int look_for_backslash
)
1526 char prompt
[81], *sval
, *tmp
, *swap_val
, **newval
= NULL
;
1527 char *pval
, **apval
, **lval
, ***alval
;
1528 char *olddefval
= NULL
;
1529 int rv
= 0, skip_to_next
= 0, after
= 0, i
= 4, j
, k
;
1530 int lowrange
, hirange
, incr
, oeflags
, oebufsize
;
1531 int numval
, repeat_key
= 0;
1532 int curindex
, previndex
, nextindex
, deefault
;
1536 if((*cl
)->var
->is_list
){
1537 lval
= LVAL((*cl
)->var
, ew
);
1538 alval
= ALVAL((*cl
)->var
, ew
);
1541 pval
= PVAL((*cl
)->var
, ew
);
1542 apval
= APVAL((*cl
)->var
, ew
);
1545 oebufsize
= 6*MAXPATH
;
1546 sval
= (char *) fs_get(oebufsize
*sizeof(char));
1549 if(flags
&CF_NUMBER
){ /* only happens if !is_list */
1551 if((*cl
)->var
== &ps
->vars
[V_FILLCOL
]){
1553 hirange
= MAX_FILLCOL
;
1555 else if((*cl
)->var
== &ps
->vars
[V_SLEEP
]){
1559 else if((*cl
)->var
== &ps
->vars
[V_OVERLAP
]
1560 || (*cl
)->var
== &ps
->vars
[V_MARGIN
]){
1564 else if((*cl
)->var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
1565 lowrange
= -(Q_SUPP_LIMIT
-1);
1568 else if((*cl
)->var
== &ps
->vars
[V_MAXREMSTREAM
]){
1572 else if((*cl
)->var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
1576 else if((*cl
)->var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
1580 else if((*cl
)->var
== &ps
->vars
[V_MAILCHECK
] ||
1581 (*cl
)->var
== &ps
->vars
[V_INCCHECKINTERVAL
] ||
1582 (*cl
)->var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
] ||
1583 (*cl
)->var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
1588 else if((*cl
)->var
== &ps
->vars
[V_DEADLETS
]){
1592 else if((*cl
)->var
== &ps
->vars
[V_NMW_WIDTH
]){
1594 hirange
= MAX_SCREEN_COLS
;
1596 else if((*cl
)->var
== score_act_global_ptr
){
1600 else if((*cl
)->var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
1601 (*cl
)->var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
1602 (*cl
)->var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
1606 else if((*cl
)->var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
1607 (*cl
)->var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
1608 (*cl
)->var
== &ps
->vars
[V_SSHOPENTIMEO
] ||
1609 (*cl
)->var
== &ps
->vars
[V_USERINPUTTIMEO
]){
1613 else if((*cl
)->var
== &ps
->vars
[V_INCCHECKTIMEO
]){
1617 else if((*cl
)->var
== &ps
->vars
[V_MAILDROPCHECK
]){
1622 else if((*cl
)->var
== &ps
->vars
[V_NNTPRANGE
]){
1627 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
]){
1631 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
]){
1635 else if((*cl
)->var
== cat_lim_global_ptr
){
1648 ekey
[1].ch
= ctrl('P');
1649 ekey
[1].rval
= ctrl('P');
1650 ekey
[1].name
= "^P";
1651 ekey
[1].label
= N_("Decrease");
1652 ekey
[2].ch
= ctrl('N');
1653 ekey
[2].rval
= ctrl('N');
1654 ekey
[2].name
= "^N";
1655 ekey
[2].label
= N_("Increase");
1656 ekey
[3].ch
= KEY_DOWN
;
1657 ekey
[3].rval
= ctrl('P');
1660 ekey
[4].ch
= KEY_UP
;
1661 ekey
[4].rval
= ctrl('N');
1668 case MC_ADD
: /* add to list */
1669 if(fixed_var((*cl
)->var
, "add to", NULL
)){
1672 else if(!(*cl
)->var
->is_list
&& pval
){
1673 q_status_message(SM_ORDER
, 3, 3,
1674 _("Only single value allowed. Use \"Change\"."));
1680 if((*cl
)->var
->is_list
1681 && lval
&& lval
[0] && lval
[0][0]
1684 /* regular add to an existing list */
1686 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1687 tmpval
[sizeof(tmpval
)-1] = '\0';
1688 removing_trailing_white_space(tmpval
);
1690 /* 33 is the number of chars other than the value */
1691 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1692 k
= MIN(18, MAX(maxwidth
-33,0));
1693 if(utf8_width(tmpval
) > k
&& k
>= 3){
1694 (void) utf8_truncate(tmpval
, k
-3);
1695 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1696 tmpval
[sizeof(tmpval
)-1] = '\0';
1699 utf8_snprintf(prompt
, sizeof(prompt
),
1700 _("Enter text to insert before \"%.*w\": "), k
, tmpval
);
1701 prompt
[sizeof(prompt
)-1] = '\0';
1703 else if((*cl
)->var
->is_list
1705 && (*cl
)->var
->current_val
.l
){
1706 /* Add to list which doesn't exist, but default does exist */
1710 ekey
[0].label
= N_("Replace");
1714 ekey
[1].label
= N_("Add To");
1716 strncpy(prompt
, _("Replace or Add To default value ? "), sizeof(prompt
));
1717 prompt
[sizeof(prompt
)-1] = '\0';
1718 switch(radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, 'a', 'x',
1719 h_config_replace_add
, RB_NORM
)){
1722 for(j
= 0; (*cl
)->var
->current_val
.l
[j
]; j
++){
1723 sstrncpy(&p
, (*cl
)->var
->current_val
.l
[j
], oebufsize
-(p
-sval
));
1724 if(oebufsize
-(p
-sval
) > 2){
1729 if(oebufsize
-(p
-sval
) > 0)
1733 sval
[oebufsize
-1] = '\0';
1736 if(flags
& CF_NUMBER
)
1737 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1739 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1746 strncpy(sval
, olddefval
, oebufsize
);
1747 sval
[oebufsize
-1] = '\0';
1750 if(flags
& CF_NUMBER
)
1751 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric replacement text : "));
1753 snprintf(prompt
, sizeof(prompt
), _("Enter the replacement text : "));
1759 cmd_cancelled("Add");
1764 if(flags
& CF_NUMBER
)
1765 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1767 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1770 prompt
[sizeof(prompt
)-1] = '\0';
1772 ps
->mangled_footer
= 1;
1779 if((*cl
)->var
->is_list
1780 && lval
&& lval
[0] && lval
[0][0]
1782 ekey
[0].ch
= ctrl('W');
1784 ekey
[0].name
= "^W";
1785 /* TRANSLATORS: Insert new item before current item */
1786 ekey
[0].label
= after
? N_("InsertBefore") : N_("InsertAfter");
1789 else if(!(flags
&CF_NUMBER
))
1792 oeflags
= OE_APPEND_CURRENT
;
1793 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
1795 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
1799 if((*cl
)->var
->is_list
)
1800 ps
->mangled_body
= 1;
1802 ps
->mangled_footer
= 1;
1804 removing_leading_and_trailing_white_space(sval
);
1806 * Coerce "" and <Empty Value> to empty string input.
1807 * Catch <No Value Set> as a substitute for deleting.
1809 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
1810 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
1812 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
1814 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
1816 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
1819 if((*cl
)->var
->is_list
){
1825 for(tmp
= sval
; *tmp
; tmp
++)
1827 i
++; /* conservative count of ,'s */
1830 ltmp
= (char **)fs_get(2 * sizeof(char *));
1831 ltmp
[0] = cpystr(sval
);
1835 ltmp
= parse_list(sval
, i
+ 1,
1837 ? PL_COMMAQUOTE
: 0,
1841 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
1846 q_status_message1(SM_ORDER
, 0, 3,
1847 _("Can't add %s to list"), _(empty_val
));
1848 rv
= ps
->mangled_body
= 0;
1851 fs_give((void **)<mp
);
1854 q_status_message1(SM_ORDER
, 0, 3,
1855 _("Can't add %s to list"), _(empty_val
));
1859 if(flags
&CF_NUMBER
&& sval
[0]
1860 && !(isdigit((unsigned char)sval
[0])
1861 || sval
[0] == '-' || sval
[0] == '+')){
1862 q_status_message(SM_ORDER
,3,3,
1863 _("Entry must be numeric"));
1864 i
= 3; /* to keep loop going */
1869 fs_give((void **)apval
);
1871 if(!(olddefval
&& !strcmp(sval
, olddefval
))
1872 || ((*cl
)->var
== &ps
->vars
[V_POST_CHAR_SET
])
1873 || want_to(_("Leave unset and use default "),
1874 'y', 'y', NO_HELP
, WT_FLUSH_IN
) == 'n')
1875 *apval
= cpystr(sval
);
1877 newval
= &(*cl
)->value
;
1881 cmd_cancelled("Add");
1884 help
= help
== NO_HELP
? h_config_add
: NO_HELP
;
1887 else if(i
== 4){ /* no redraw, yet */
1890 else if(i
== 5){ /* change from/to prepend to/from append */
1893 after
= after
? 0 : 1;
1894 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1895 tmpval
[sizeof(tmpval
)-1] = '\0';
1896 removing_trailing_white_space(tmpval
);
1897 /* 33 is the number of chars other than the value */
1898 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1899 k
= MIN(18, MAX(maxwidth
-33,0));
1900 if(utf8_width(tmpval
) > k
&& k
>= 3){
1901 (void) utf8_truncate(tmpval
, k
-3);
1902 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1903 tmpval
[sizeof(tmpval
)-1] = '\0';
1907 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert after \"%.*s\": "), k
, tmpval
);
1909 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert before \"%.*s\": "), k
, tmpval
);
1913 else if(i
== ctrl('P')){
1915 numval
= atoi(sval
);
1918 numval
= atoi(pval
);
1920 numval
= lowrange
+ 1;
1923 if(numval
== lowrange
){
1925 * Protect user from repeating arrow key that
1926 * causes message to appear over and over.
1928 if(++repeat_key
> 0){
1929 q_status_message1(SM_ORDER
,3,3,
1930 _("Minimum value is %s"), comatose(lowrange
));
1937 numval
= MAX(numval
- incr
, lowrange
);
1938 snprintf(sval
, oebufsize
, "%d", numval
);
1939 sval
[oebufsize
-1] = '\0';
1942 else if(i
== ctrl('N')){
1944 numval
= atoi(sval
);
1947 numval
= atoi(pval
);
1949 numval
= lowrange
+ 1;
1952 if(numval
== hirange
){
1953 if(++repeat_key
> 0){
1954 q_status_message1(SM_ORDER
,3,3,
1955 _("Maximum value is %s"), comatose(hirange
));
1962 numval
= MIN(numval
+ incr
, hirange
);
1963 snprintf(sval
, oebufsize
, "%d", numval
);
1964 sval
[oebufsize
-1] = '\0';
1974 case MC_DELETE
: /* delete */
1976 if(!(*cl
)->var
->is_list
1978 && (*cl
)->var
->current_val
.p
){
1981 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
1982 pmt
[sizeof(pmt
)-1] = '\0';
1983 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
1985 *apval
= cpystr(sval
);
1986 newval
= &(*cl
)->value
;
1987 rv
= ps
->mangled_footer
= 1;
1990 else if((*cl
)->var
->is_list
1992 && (*cl
)->var
->current_val
.l
){
1995 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
1996 pmt
[sizeof(pmt
)-1] = '\0';
1997 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2001 ltmp
= (char **)fs_get(2 * sizeof(char *));
2002 ltmp
[0] = cpystr(sval
);
2004 config_add_list(ps
, cl
, ltmp
, &newval
, 0);
2005 fs_give((void **)<mp
);
2006 rv
= ps
->mangled_body
= 1;
2009 else if(((*cl
)->var
->is_list
&& !lval
)
2010 || (!(*cl
)->var
->is_list
&& !pval
)){
2011 q_status_message(SM_ORDER
, 0, 3, _("No set value to delete"));
2014 if((*cl
)->var
->is_fixed
)
2015 snprintf(prompt
, sizeof(prompt
), _("Delete (unused) %s from %s "),
2017 ? (!*lval
[(*cl
)->varmem
])
2019 : lval
[(*cl
)->varmem
]
2027 snprintf(prompt
, sizeof(prompt
), _("Really delete %s%s from %s "),
2028 (*cl
)->var
->is_list
? "item " : "",
2030 ? int2string((*cl
)->varmem
+ 1)
2038 prompt
[sizeof(prompt
)-1] = '\0';
2041 ps
->mangled_footer
= 1;
2042 if(want_to(prompt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2044 if((*cl
)->var
->is_list
)
2045 ps
->mangled_body
= 1;
2047 ps
->mangled_footer
= 1;
2049 if((*cl
)->var
->is_list
){
2050 if(lval
[(*cl
)->varmem
])
2051 fs_give((void **)&lval
[(*cl
)->varmem
]);
2053 config_del_list_item(cl
, &newval
);
2057 fs_give((void **)apval
);
2059 newval
= &(*cl
)->value
;
2063 q_status_message(SM_ORDER
, 0, 3, _("Value not deleted"));
2068 case MC_EDIT
: /* edit/change list option */
2069 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2072 else if(((*cl
)->var
->is_list
2074 && (*cl
)->var
->current_val
.l
)
2076 (!(*cl
)->var
->is_list
2078 && (*cl
)->var
->current_val
.p
)){
2081 * In non-list case, offer default value for editing.
2083 if(!(*cl
)->var
->is_list
2084 && (*cl
)->var
!= &ps
->vars
[V_REPLY_INTRO
]
2085 && (*cl
)->var
->current_val
.p
[0]
2086 && strcmp(VSTRING
,(*cl
)->var
->current_val
.p
)){
2090 olddefval
= (char *) fs_get(strlen((*cl
)->var
->current_val
.p
)+3);
2092 if(!strncmp((*cl
)->var
->current_val
.p
,
2094 (len
=strlen(DSTRING
)))){
2095 /* strip DSTRING and trailing paren */
2096 strncpy(olddefval
, (*cl
)->var
->current_val
.p
+len
,
2097 strlen((*cl
)->var
->current_val
.p
)-len
-1);
2098 olddefval
[strlen((*cl
)->var
->current_val
.p
)-len
-1] = '\0';
2101 /* quote it if there are trailing spaces */
2102 quote_it
= ((*cl
)->var
->current_val
.p
[strlen((*cl
)->var
->current_val
.p
)-1] == SPACE
);
2103 snprintf(olddefval
, strlen((*cl
)->var
->current_val
.p
)+3, "%s%s%s", quote_it
? "\"" : "", (*cl
)->var
->current_val
.p
, quote_it
? "\"" : "");
2106 olddefval
[strlen((*cl
)->var
->current_val
.p
)+3-1] = '\0';
2111 else if(((*cl
)->var
->is_list
2113 && !(*cl
)->var
->current_val
.l
)
2115 (!(*cl
)->var
->is_list
2117 && !(*cl
)->var
->current_val
.p
)){
2125 fs_give((void **)&sval
);
2126 if((*cl
)->var
->is_list
){
2127 snprintf(prompt
, sizeof(prompt
), _("Change field %s list entry : "),
2129 prompt
[sizeof(prompt
)-1] = '\0';
2130 clptr
= lval
[(*cl
)->varmem
] ? lval
[(*cl
)->varmem
] : NULL
;
2133 if(flags
& CF_NUMBER
)
2134 snprintf(prompt
, sizeof(prompt
), _("Change numeric field %s value : "), (*cl
)->var
->name
);
2136 snprintf(prompt
, sizeof(prompt
), _("Change field %s value : "), (*cl
)->var
->name
);
2138 clptr
= pval
? pval
: NULL
;
2141 oebufsize
= clptr
? (int) MAX(MAXPATH
, 50+strlen(clptr
)) : MAXPATH
;
2142 sval
= (char *) fs_get(oebufsize
* sizeof(char));
2143 snprintf(sval
, oebufsize
, "%s", clptr
? clptr
: "");
2144 sval
[oebufsize
-1] = '\0';
2146 ps
->mangled_footer
= 1;
2149 if(!(flags
&CF_NUMBER
))
2152 oeflags
= OE_APPEND_CURRENT
;
2153 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
2155 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
2158 removing_leading_and_trailing_white_space(sval
);
2160 * Coerce "" and <Empty Value> to empty string input.
2161 * Catch <No Value Set> as a substitute for deleting.
2163 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
2164 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
2166 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
2168 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
2170 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
2174 if((*cl
)->var
->is_list
)
2175 ps
->mangled_body
= 1;
2177 ps
->mangled_footer
= 1;
2179 if((*cl
)->var
->is_list
){
2183 if(lval
[(*cl
)->varmem
])
2184 fs_give((void **)&lval
[(*cl
)->varmem
]);
2187 for(tmp
= sval
; *tmp
; tmp
++)
2189 i
++; /* conservative count of ,'s */
2192 ltmp
= parse_list(sval
, i
+ 1,
2194 ? PL_COMMAQUOTE
: 0,
2197 if(ltmp
&& !ltmp
[0]) /* only commas */
2199 else if(!i
|| (ltmp
&& !ltmp
[1])){ /* only one item */
2200 lval
[(*cl
)->varmem
] = cpystr(sval
);
2201 newval
= &(*cl
)->value
;
2204 fs_give((void **)<mp
[0]);
2208 * Looks like the value was changed to a
2209 * list, so delete old value, and insert
2212 * If more than one item in existing list and
2213 * current is end of existing list, then we
2214 * have to delete and append instead of
2215 * deleting and prepending.
2217 if(((*cl
)->varmem
> 0 || lval
[1])
2218 && !(lval
[(*cl
)->varmem
+1])){
2223 config_del_list_item(cl
, &newval
);
2224 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
2228 fs_give((void **)<mp
);
2231 if(flags
&CF_NUMBER
&& sval
[0]
2232 && !(isdigit((unsigned char)sval
[0])
2233 || sval
[0] == '-' || sval
[0] == '+')){
2234 q_status_message(SM_ORDER
,3,3,
2235 _("Entry must be numeric"));
2240 fs_give((void **)apval
);
2242 if(sval
[0] && apval
)
2243 *apval
= cpystr(sval
);
2245 newval
= &(*cl
)->value
;
2249 cmd_cancelled("Change");
2252 help
= help
== NO_HELP
? h_config_change
: NO_HELP
;
2255 else if(i
== 4){ /* no redraw, yet */
2258 else if(i
== ctrl('P')){
2259 numval
= atoi(sval
);
2260 if(numval
== lowrange
){
2262 * Protect user from repeating arrow key that
2263 * causes message to appear over and over.
2265 if(++repeat_key
> 0){
2266 q_status_message1(SM_ORDER
,3,3,
2267 _("Minimum value is %s"), comatose(lowrange
));
2274 numval
= MAX(numval
- incr
, lowrange
);
2275 snprintf(sval
, oebufsize
, "%d", numval
);
2276 sval
[oebufsize
-1] = '\0';
2279 else if(i
== ctrl('N')){
2280 numval
= atoi(sval
);
2281 if(numval
== hirange
){
2282 if(++repeat_key
> 0){
2283 q_status_message1(SM_ORDER
,3,3,
2284 _("Maximum value is %s"), comatose(hirange
));
2291 numval
= MIN(numval
+ incr
, hirange
);
2292 snprintf(sval
, oebufsize
, "%d", numval
);
2293 sval
[oebufsize
-1] = '\0';
2304 if(!((*cl
)->var
&& (*cl
)->var
->is_list
)){
2305 q_status_message(SM_ORDER
, 0, 2,
2306 _("Can't shuffle single-valued setting"));
2313 curindex
= (*cl
)->varmem
;
2314 previndex
= curindex
-1;
2315 nextindex
= curindex
+1;
2316 if(!*alval
|| !(*alval
)[nextindex
])
2319 if((previndex
< 0 && nextindex
< 0) || !*alval
){
2320 q_status_message(SM_ORDER
, 0, 3,
2321 _("Shuffle only makes sense when there is more than one value defined"));
2325 /* Move it up or down? */
2330 ekey
[i
++].label
= N_("Up");
2335 ekey
[i
++].label
= N_("Down");
2340 if(previndex
< 0){ /* no up */
2344 else if(nextindex
< 0)
2345 ekey
[1].ch
= -2; /* no down */
2347 snprintf(prompt
, sizeof(prompt
), "Shuffle %s%s%s ? ",
2348 (ekey
[0].ch
!= -2) ? "UP" : "",
2349 (ekey
[0].ch
!= -2 && ekey
[1].ch
!= -2) ? " or " : "",
2350 (ekey
[1].ch
!= -2) ? "DOWN" : "");
2351 help
= (ekey
[0].ch
== -2) ? h_hdrcolor_shuf_down
2352 : (ekey
[1].ch
== -2) ? h_hdrcolor_shuf_up
2354 prompt
[sizeof(prompt
)-1] = '\0';
2356 i
= radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, deefault
, 'x',
2361 cmd_cancelled("Shuffle");
2371 swap_val
= (*alval
)[curindex
];
2372 (*alval
)[curindex
] = (*alval
)[nextindex
];
2373 (*alval
)[nextindex
] = swap_val
;
2376 swap_val
= (*alval
)[curindex
];
2377 (*alval
)[curindex
] = (*alval
)[previndex
];
2378 (*alval
)[previndex
] = swap_val
;
2380 else /* can't happen */
2384 * Fix the conf line values.
2388 fs_give((void **)&(*cl
)->value
);
2390 (*cl
)->value
= pretty_value(ps
, *cl
);
2393 if((*cl
)->next
->value
)
2394 fs_give((void **)&(*cl
)->next
->value
);
2396 (*cl
)->next
->value
= pretty_value(ps
, (*cl
)->next
);
2397 *cl
= next_confline(*cl
);
2400 if((*cl
)->prev
->value
)
2401 fs_give((void **)&(*cl
)->prev
->value
);
2403 (*cl
)->prev
->value
= pretty_value(ps
, (*cl
)->prev
);
2404 *cl
= prev_confline(*cl
);
2407 rv
= ps
->mangled_body
= 1;
2410 case MC_EXIT
: /* exit */
2411 rv
= config_exit_cmd(flags
);
2420 *cl
= next_confline(*cl
);
2423 * At this point, if changes occurred, var->user_val.X is set.
2424 * So, fix the current_val, and handle special cases...
2426 * NOTE: we don't worry about the "fixed variable" case here, because
2427 * editing such vars should have been prevented above...
2431 * Now go and set the current_val based on user_val changes
2432 * above. Turn off command line settings...
2434 set_current_val((*cl
)->var
, TRUE
, FALSE
);
2435 fix_side_effects(ps
, (*cl
)->var
, 0);
2438 * Delay setting the displayed value until "var.current_val" is set
2439 * in case current val get's changed due to a special case above.
2443 fs_give((void **) newval
);
2445 *newval
= pretty_value(ps
, *cl
);
2448 exception_override_warning((*cl
)->var
);
2452 fs_give((void **) &sval
);
2455 fs_give((void **) &olddefval
);
2462 config_exit_cmd(unsigned int flags
)
2464 return(screen_exit_cmd(flags
, "Configuration"));
2469 simple_exit_cmd(unsigned int flags
)
2476 * screen_exit_cmd - basic config/flag screen exit logic
2479 screen_exit_cmd(unsigned int flags
, char *cmd
)
2481 if(flags
& CF_CHANGES
){
2482 switch(want_to(EXIT_PMT
, 'y', 'x', h_config_undo
, WT_FLUSH_IN
)){
2484 q_status_message1(SM_ORDER
,0,3,"%s changes saved", cmd
);
2488 q_status_message1(SM_ORDER
,3,5,"No %s changes saved", cmd
);
2493 q_status_message(SM_ORDER
,3,5,"Changes not yet saved");
2506 config_add_list(struct pine
*ps
, CONF_S
**cl
, char **ltmp
, char ***newval
, int after
)
2509 char *tmp
, ***alval
;
2512 for(items
= 0, i
= 0; ltmp
[i
]; i
++) /* count list items */
2515 alval
= ALVAL((*cl
)->var
, ew
);
2517 if(alval
&& (*alval
)){
2518 if((*alval
)[0] && (*alval
)[0][0]){
2520 * Since we were already a list, make room
2521 * for the new member[s] and fall thru to
2522 * actually fill them in below...
2524 for(i
= 0; (*alval
)[i
]; i
++)
2527 fs_resize((void **)alval
, (i
+ items
+ 1) * sizeof(char *));
2530 * move the ones that will be bumped down to the bottom of the list
2532 for(; i
>= (*cl
)->varmem
+ (after
?1:0); i
--)
2533 (*alval
)[i
+items
] = (*alval
)[i
];
2540 free_list_array(alval
);
2542 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2543 memset((void *)(*alval
), 0, (items
+1)*sizeof(char *));
2544 (*alval
)[0] = ltmp
[0];
2546 *newval
= &(*cl
)->value
;
2549 fs_give((void **)&(*cl
)->value
);
2556 * since we were previously empty, we want
2557 * to replace the first CONF_S's value with
2558 * the first new value, and fill the other
2559 * in below if there's a list...
2561 * first, make sure we're at the beginning of this config
2562 * section and dump the config lines for the default list,
2563 * except for the first one, which we will over-write.
2565 *cl
= (*cl
)->varnamep
;
2566 while((*cl
)->next
&& (*cl
)->next
->varnamep
== (*cl
)->varnamep
)
2567 snip_confline(&(*cl
)->next
);
2570 * now allocate the new user_val array and fill in the first entry.
2572 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2573 memset((void *)(*alval
), 0, (items
+1) * sizeof(char *));
2574 (*alval
)[(*cl
)->varmem
=0] = ltmp
[0];
2576 *newval
= &(*cl
)->value
;
2579 fs_give((void **)&(*cl
)->value
);
2585 * Make new cl's to fit in the new space. Move the value from the current
2586 * line if inserting before it, else leave it where it is.
2588 for(; i
< items
; i
++){
2589 (*alval
)[i
+(*cl
)->varmem
+ (after
?1:0)] = ltmp
[i
];
2593 (*cl
)->value
= NULL
;
2597 (*cl
)->var
= (*cl
)->prev
->var
;
2598 (*cl
)->valoffset
= (*cl
)->prev
->valoffset
;
2599 (*cl
)->varoffset
= (*cl
)->prev
->varoffset
;
2600 (*cl
)->headingp
= (*cl
)->prev
->headingp
;
2601 (*cl
)->keymenu
= (*cl
)->prev
->keymenu
;
2602 (*cl
)->help
= (*cl
)->prev
->help
;
2603 (*cl
)->tool
= (*cl
)->prev
->tool
;
2604 (*cl
)->varnamep
= (*cl
)->prev
->varnamep
;
2607 (*cl
)->value
= NULL
;
2611 *newval
= &(*cl
)->next
->value
;
2613 *newval
= &(*cl
)->value
;
2618 * now fix up varmem values and fill in new values that have been
2621 for(ctmp
= (*cl
)->varnamep
, i
= 0;
2623 ctmp
= ctmp
->next
, i
++){
2626 /* BUG: We should be able to do this without the temp
2629 char *ptmp
= pretty_value(ps
, ctmp
);
2630 ctmp
->value
= (ctmp
->varnamep
->flags
& CF_PRINTER
) ? printer_name(ptmp
) : cpystr(ptmp
);
2631 fs_give((void **)&ptmp
);
2641 config_del_list_item(CONF_S
**cl
, char ***newval
)
2643 char **bufp
, ***alval
;
2647 alval
= ALVAL((*cl
)->var
, ew
);
2649 if((*alval
)[(*cl
)->varmem
+ 1]){
2650 for(bufp
= &(*alval
)[(*cl
)->varmem
];
2651 (*bufp
= *(bufp
+1)) != NULL
; bufp
++)
2654 if(*cl
== (*cl
)->varnamep
){ /* leading value */
2656 fs_give((void **)&(*cl
)->value
);
2659 (*cl
)->value
= ctmp
->value
;
2663 ctmp
= *cl
; /* blast the confline */
2665 if(ctmp
== opt_screen
->top_line
)
2666 opt_screen
->top_line
= *cl
;
2669 snip_confline(&ctmp
);
2671 for(ctmp
= (*cl
)->varnamep
, i
= 0; /* now fix up varmem values */
2673 ctmp
= ctmp
->next
, i
++)
2676 else if((*cl
)->varmem
){ /* blasted last in list */
2679 if(ctmp
== opt_screen
->top_line
)
2680 opt_screen
->top_line
= *cl
;
2682 snip_confline(&ctmp
);
2684 else{ /* blasted last remaining */
2686 fs_give((void **)alval
);
2688 *newval
= &(*cl
)->value
;
2694 * feature list manipulation tool
2697 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
2700 checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2705 case MC_TOGGLE
: /* mark/unmark feature */
2706 if((*cl
)->var
== &ps
->vars
[V_FEATURE_LIST
]){
2708 toggle_feature_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, *cl
, 0);
2711 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2712 "Programmer botch! Unknown checkbox type.");
2716 case MC_EXIT
: /* exit */
2717 rv
= config_exit_cmd(flags
);
2730 * simple radio-button style variable handler
2733 radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2737 NAMEVAL_S
*rule
= NULL
;
2743 apval
= APVAL((*cl
)->var
, ew
);
2746 case MC_CHOICE
: /* set/unset feature */
2748 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2749 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
2750 && want_to(_("Delete old unused personal option setting"),
2751 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2752 delete_user_vals((*cl
)->var
);
2753 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
2760 if(standard_radio_var(ps
, (*cl
)->var
) || (*cl
)->var
== startup_ptr
){
2761 PTR_TO_RULEFUNC rulefunc
;
2764 if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2765 old_uc
= pico_usingcolor();
2766 old_cs
= ps
->color_style
;
2770 if((*cl
)->var
->cmdline_val
.p
)
2771 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2774 fs_give((void **)apval
);
2776 rulefunc
= rulefunc_from_var(ps
, (*cl
)->var
);
2778 rule
= (*rulefunc
)((*cl
)->varmem
);
2781 *apval
= cpystr(S_OR_L(rule
));
2783 cur_rule_value((*cl
)->var
, TRUE
, TRUE
);
2784 set_radio_pretty_vals(ps
, cl
);
2786 if((*cl
)->var
== &ps
->vars
[V_AB_SORT_RULE
])
2787 addrbook_redo_sorts();
2788 else if((*cl
)->var
== &ps
->vars
[V_THREAD_DISP_STYLE
]){
2789 clear_index_cache(ps
->mail_stream
, 0);
2791 else if((*cl
)->var
== &ps
->vars
[V_THREAD_INDEX_STYLE
]){
2795 clear_index_cache(ps
->mail_stream
, 0);
2796 /* clear all hidden and collapsed flags */
2797 set_lflags(ps
->mail_stream
, ps
->msgmap
, MN_COLL
| MN_CHID
, 0);
2800 && SORT_IS_THREADED(ps
->msgmap
)
2801 && unview_thread(ps
, ps
->mail_stream
, ps
->msgmap
)){
2802 ps
->next_screen
= mail_index_screen
;
2803 ps
->view_skipped_index
= 0;
2804 ps
->mangled_screen
= 1;
2807 if(SORT_IS_THREADED(ps
->msgmap
)
2808 && (SEP_THRDINDX() || COLL_THRDS()))
2809 collapse_threads(ps
->mail_stream
, ps
->msgmap
, NULL
);
2811 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
2812 m
= ps_global
->s_pool
.streams
[i
];
2814 sp_set_viewing_a_thread(m
, 0);
2817 adjust_cur_to_visible(ps
->mail_stream
, ps
->msgmap
);
2820 else if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2821 if(old_cs
!= ps
->color_style
){
2822 pico_toggle_color(0);
2823 switch(ps
->color_style
){
2826 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
2829 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
2832 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
2835 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
2839 if(ps
->color_style
!= COL_NONE
)
2840 pico_toggle_color(1);
2843 if(pico_usingcolor())
2844 pico_set_normal_color();
2846 if(!old_uc
&& pico_usingcolor()){
2849 * remove the explanatory warning line and a blank line
2852 /* first find the first blank line */
2853 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2854 if(ctmp
->flags
& CF_NOSELECT
)
2857 if(ctmp
&& ctmp
->flags
& CF_NOSELECT
&&
2858 ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
) &&
2859 ctmp
->next
&& ctmp
->next
->flags
& CF_NOSELECT
&&
2861 ctmp
->next
->next
->flags
& CF_NOSELECT
){
2862 ctmp
->prev
->next
= ctmp
->next
->next
;
2863 ctmp
->next
->next
->prev
= ctmp
->prev
;
2864 ctmp
->next
->next
= NULL
;
2865 free_conflines(&ctmp
);
2868 /* make all the colors selectable */
2869 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2870 if(ctmp
->flags
& CF_POT_SLCTBL
)
2871 ctmp
->flags
&= ~CF_NOSELECT
;
2873 else if(old_uc
&& !pico_usingcolor()){
2876 * add the explanatory warning line and a blank line
2879 /* first find the existing blank line */
2880 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2881 if(ctmp
->flags
& CF_NOSELECT
)
2884 /* add the explanatory warning line */
2885 new_confline(&ctmp
);
2886 ctmp
->help
= NO_HELP
;
2887 ctmp
->flags
|= CF_NOSELECT
;
2888 ctmp
->value
= cpystr(COLORNOSET
);
2890 /* and add another blank line */
2891 new_confline(&ctmp
);
2892 ctmp
->flags
|= (CF_NOSELECT
| CF_B_LINE
);
2894 /* make all the colors non-selectable */
2895 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2896 if(ctmp
->flags
& CF_POT_SLCTBL
)
2897 ctmp
->flags
|= CF_NOSELECT
;
2900 clear_index_cache(ps
->mail_stream
, 0);
2902 ps
->mangled_screen
= 1;
2906 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2909 else if((*cl
)->var
== &ps
->vars
[V_SORT_KEY
]){
2913 def_sort_rev
= (*cl
)->varmem
>= (short) EndofList
;
2914 def_sort
= (SortOrder
) ((*cl
)->varmem
- (def_sort_rev
2916 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def_sort
),
2917 (def_sort_rev
) ? "/Reverse" : "");
2919 if((*cl
)->var
->cmdline_val
.p
)
2920 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2924 fs_give((void **)apval
);
2926 *apval
= cpystr(tmp_20k_buf
);
2929 set_current_val((*cl
)->var
, TRUE
, TRUE
);
2930 if(decode_sort(ps
->VAR_SORT_KEY
, &def_sort
, &def_sort_rev
) != -1){
2931 ps
->def_sort
= def_sort
;
2932 ps
->def_sort_rev
= def_sort_rev
;
2935 set_radio_pretty_vals(ps
, cl
);
2936 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2940 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2941 "Programmer botch! Unknown radiobutton type.");
2945 case MC_EXIT
: /* exit */
2946 rv
= config_exit_cmd(flags
);
2955 exception_override_warning((*cl
)->var
);
2962 * simple yes/no style variable handler
2965 yesno_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2967 int rv
= 0, yes
= 0;
2968 char *pval
, **apval
;
2970 pval
= PVAL((*cl
)->var
, ew
);
2971 apval
= APVAL((*cl
)->var
, ew
);
2974 case MC_TOGGLE
: /* toggle yes to no and back */
2975 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2976 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
2977 && want_to(_("Delete old unused personal option setting"),
2978 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2979 delete_user_vals((*cl
)->var
);
2980 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
2988 yes
= ((pval
&& !strucmp(pval
, yesstr
)) ||
2989 (!pval
&& (*cl
)->var
->current_val
.p
&&
2990 !strucmp((*cl
)->var
->current_val
.p
, yesstr
)));
2991 fs_give((void **)&(*cl
)->value
);
2995 fs_give((void **)apval
);
2998 *apval
= cpystr(nostr
);
3000 *apval
= cpystr(yesstr
);
3003 set_current_val((*cl
)->var
, FALSE
, FALSE
);
3005 fs_give((void **)&(*cl
)->value
);
3007 (*cl
)->value
= pretty_value(ps
, *cl
);
3008 fix_side_effects(ps
, (*cl
)->var
, 0);
3012 case MC_EXIT
: /* exit */
3013 rv
= config_exit_cmd(flags
);
3026 * Manage display of the config/options menu body.
3029 update_option_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, Pos
*cursor_pos
)
3031 int dline
, w
, save
= '\0';
3032 CONF_S
*top_line
, *ctmp
;
3035 int want_width
, first_width
;
3036 char *saveptr
= NULL
;
3039 int last_selectable
;
3040 mswin_beginupdate();
3042 if(screen
== NULL
|| BODY_LINES(ps
) < 1)
3046 cursor_pos
->col
= 0;
3047 cursor_pos
->row
= -1; /* to tell us if we've set it yet */
3051 * calculate top line of display for reframing if the current field
3052 * is off the display defined by screen->top_line...
3054 if((ctmp
= screen
->top_line
) != NULL
)
3055 for(dline
= BODY_LINES(ps
);
3056 dline
&& ctmp
&& ctmp
!= screen
->current
;
3057 ctmp
= next_confline(ctmp
), dline
--)
3060 if(!ctmp
|| !dline
){ /* force reframing */
3062 ctmp
= top_line
= first_confline(screen
->current
);
3064 if(((dline
++)%BODY_LINES(ps
)) == 0)
3066 while(ctmp
!= screen
->current
&& (ctmp
= next_confline(ctmp
)));
3069 top_line
= screen
->top_line
;
3073 * Figure out how far down the top line is from the top and how many
3074 * total lines there are. Dumb to loop every time thru, but
3075 * there aren't that many lines, and it's cheaper than rewriting things
3076 * to maintain a line count in each structure...
3078 for(dline
= 0, ctmp
= prev_confline(top_line
); ctmp
; ctmp
= prev_confline(ctmp
))
3081 scroll_setpos(dline
);
3082 last_selectable
= dline
;
3083 for(ctmp
= next_confline(top_line
); ctmp
; ctmp
= next_confline(ctmp
)){
3085 if (!(ctmp
->flags
& CF_NOSELECT
))
3086 last_selectable
= dline
;
3088 dline
= last_selectable
;
3089 scroll_setrange(BODY_LINES(ps
), dline
);
3092 /* mangled body or new page, force redraw */
3093 if(ps
->mangled_body
|| screen
->top_line
!= top_line
)
3094 screen
->prev
= NULL
;
3096 /* loop thru painting what's needed */
3097 for(dline
= 0, ctmp
= top_line
;
3098 dline
< BODY_LINES(ps
);
3099 dline
++, ctmp
= next_confline(ctmp
)){
3102 * only fall thru painting if something needs painting...
3104 if(!(!screen
->prev
|| ctmp
== screen
->prev
|| ctmp
== screen
->current
3105 || ctmp
== screen
->prev
->varnamep
3106 || ctmp
== screen
->current
->varnamep
3107 || ctmp
== screen
->prev
->headingp
3108 || ctmp
== screen
->current
->headingp
))
3111 ClearLine(dline
+ HEADER_ROWS(ps
));
3114 if(ctmp
->flags
& CF_B_LINE
)
3117 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3118 if(ctmp
== screen
->current
&& cursor_pos
)
3119 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3121 if((ctmp
== screen
->current
3122 || ctmp
== screen
->current
->varnamep
3123 || ctmp
== screen
->current
->headingp
)
3124 && !(ctmp
->flags
& CF_NOHILITE
))
3127 if(ctmp
->flags
& CF_H_LINE
){
3128 MoveCursor(dline
+ HEADER_ROWS(ps
), 0);
3129 Write_to_screen(repeat_char(ps
->ttyo
->screen_cols
, '-'));
3132 if(ctmp
->flags
& CF_CENTERED
){
3133 int offset
= ps
->ttyo
->screen_cols
/2
3134 - (utf8_width(ctmp
->varname
)/2);
3135 MoveCursor(dline
+ HEADER_ROWS(ps
),
3136 (offset
> 0) ? offset
: 0);
3138 else if(ctmp
->varoffset
)
3139 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->varoffset
);
3141 Write_to_screen(ctmp
->varname
);
3142 if((ctmp
== screen
->current
3143 || ctmp
== screen
->current
->varnamep
3144 || ctmp
== screen
->current
->headingp
)
3145 && !(ctmp
->flags
& CF_NOHILITE
))
3149 value
= (ctmp
->flags
& CF_INHERIT
) ? INHERIT
: ctmp
->value
;
3155 memset(tmp_20k_buf
, '\0',
3156 (6*ps
->ttyo
->screen_cols
+ 1) * sizeof(char));
3157 if(ctmp
== screen
->current
){
3158 if(!(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
))
3162 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3165 if(ctmp
->flags
& CF_H_LINE
)
3166 memset(tmp_20k_buf
, '-',
3167 ps
->ttyo
->screen_cols
* sizeof(char));
3169 if(ctmp
->flags
& CF_CENTERED
){
3170 int offset
= ps
->ttyo
->screen_cols
/2
3171 - (utf8_width(value
)/2);
3172 /* BUG: tabs screw us figuring length above */
3176 p
= tmp_20k_buf
+ offset
;
3177 if(!*(q
= tmp_20k_buf
))
3186 * Copy the value to a temp buffer expanding tabs, and
3187 * making sure not to write beyond screen right...
3189 for(i
= 0, j
= ctmp
->valoffset
; value
[i
]; i
++){
3190 if(value
[i
] == ctrl('I')){
3193 while((++j
) & 0x07);
3201 if(ctmp
== screen
->current
&& cursor_pos
){
3202 if(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
)
3203 cursor_pos
->col
= ctmp
->val2offset
;
3205 cursor_pos
->col
= ctmp
->valoffset
;
3207 if(ctmp
->tool
== radiobutton_tool
3209 || ctmp
->tool
==ldap_radiobutton_tool
3211 || ctmp
->tool
==role_radiobutton_tool
3212 || ctmp
->tool
==checkbox_tool
3213 || (ctmp
->tool
==color_setting_tool
&&
3214 ctmp
->valoffset
!= COLOR_INDENT
))
3218 if(ctmp
->flags
& CF_DOUBLEVAR
){
3222 first_width
= ctmp
->val2offset
- ctmp
->valoffset
- SPACE_BETWEEN_DOUBLEVARS
;
3223 if((l
=utf8_width(p
)) > first_width
&& first_width
>= 0){
3224 saveptr
= utf8_count_forw_width(p
, first_width
, &got_width
);
3226 * got_width != first_width indicates there's a problem
3227 * that should not happen. Ignore it.
3238 * If this is a COLOR_BLOB line we do special coloring.
3239 * The current object inverse hilite is only on the
3240 * checkbox part, the exact format comes from the
3241 * new_color_line function. If we change that we'll have
3242 * to change this to get the coloring right.
3244 if(p
[0] == '(' && p
[2] == ')' &&
3245 p
[3] == ' ' && p
[4] == ' ' &&
3246 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3247 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3248 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3249 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3251 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
);
3252 Write_to_screen_n(p
, 3);
3253 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3256 Write_to_screen_n(p
+3, 3);
3257 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3258 colorx(CFC_ICOLOR(ctmp
)));
3260 lastc
= pico_get_cur_color();
3261 (void)pico_set_colorp(newc
, PSC_NONE
);
3262 free_color_pair(&newc
);
3265 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3268 (void)pico_set_colorp(lastc
, PSC_NONE
);
3269 free_color_pair(&lastc
);
3272 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3275 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, p
);
3276 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3283 PutLine0(dline
+HEADER_ROWS(ps
),
3284 ctmp
->val2offset
- SPACE_BETWEEN_DOUBLEVARS
,
3285 repeat_char(SPACE_BETWEEN_DOUBLEVARS
, SPACE
));
3287 if(l
> ctmp
->val2offset
- ctmp
->valoffset
&& ctmp
->val2offset
- ctmp
->valoffset
>= 0)
3288 p
= saveptr
+ SPACE_BETWEEN_DOUBLEVARS
;
3290 if(p
> tmp_20k_buf
){
3291 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3294 if(p
[0] == '(' && p
[2] == ')' &&
3295 p
[3] == ' ' && p
[4] == ' ' &&
3296 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3297 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3298 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3299 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3301 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->val2offset
);
3302 Write_to_screen_n(p
, 3);
3303 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3306 Write_to_screen_n(p
+3, 3);
3307 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3308 colorx(CFC_ICOLOR(ctmp
)));
3310 lastc
= pico_get_cur_color();
3311 (void)pico_set_colorp(newc
, PSC_NONE
);
3312 free_color_pair(&newc
);
3315 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3318 (void)pico_set_colorp(lastc
, PSC_NONE
);
3319 free_color_pair(&lastc
);
3322 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3325 PutLine0(dline
+HEADER_ROWS(ps
),ctmp
->val2offset
,p
);
3326 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3332 char *q
, *first_space
, *sample
, *ptr
;
3333 COLOR_PAIR
*lastc
, *newc
;
3337 if(ctmp
->flags
& CF_COLORSAMPLE
&&
3338 pico_usingcolor() &&
3339 ((q
= strstr(tmp_20k_buf
, SAMPLE_LEADER
)) ||
3340 (q
= strstr(tmp_20k_buf
, "Color"))) &&
3341 (first_space
= strindex(q
, SPACE
)) &&
3342 (strstr(value
, SAMP1
) ||
3343 strstr(value
, SAMP2
))){
3347 /* write out first part */
3348 *first_space
= '\0';
3349 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
,
3351 *first_space
= SPACE
;
3354 if(ctmp
== screen
->current
)
3357 sample
= skip_white_space(ptr
);
3358 /* if there's enough room to put some sample up */
3361 w
= utf8_width(tmp_20k_buf
);
3363 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3365 sample
++; /* for `[' at edge of sample */
3369 w
= utf8_width(tmp_20k_buf
);
3374 /* spaces and bracket before sample1 */
3375 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+w
, ptr
);
3380 /* then the color sample */
3381 if(ctmp
->var
== &ps
->vars
[V_VIEW_HDR_COLORS
]
3382 || ctmp
->var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
]){
3383 SPEC_COLOR_S
*hc
, *hcolors
;
3385 lastc
= newc
= NULL
;
3388 spec_colors_from_varlist(LVAL(ctmp
->var
, ew
),
3390 for(hc
= hcolors
, i
=0; hc
; hc
= hc
->next
, i
++)
3391 if(CFC_ICUST(ctmp
) == i
)
3394 if(hc
&& hc
->fg
&& hc
->fg
[0] && hc
->bg
&&
3396 newc
= new_color_pair(hc
->fg
, hc
->bg
);
3399 lastc
= pico_get_cur_color();
3400 (void)pico_set_colorp(newc
, PSC_NONE
);
3401 free_color_pair(&newc
);
3405 free_spec_colors(&hcolors
);
3408 /* print out sample1 */
3412 w
= utf8_width(tmp_20k_buf
);
3415 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3416 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3422 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3426 ptr
= strindex(ptr
, ']');
3429 (void)pico_set_colorp(lastc
, PSC_NONE
);
3430 free_color_pair(&lastc
);
3433 else if(ctmp
->var
== &ps
->vars
[V_KW_COLORS
]){
3435 SPEC_COLOR_S
*kw_col
= NULL
;
3437 lastc
= newc
= NULL
;
3439 /* find keyword associated with this line */
3440 for(kw
=ps
->keywords
, i
=0; kw
; kw
=kw
->next
, i
++)
3441 if(CFC_ICUST(ctmp
) == i
)
3446 spec_colors_from_varlist(LVAL(ctmp
->var
,ew
),
3449 /* color for this keyword */
3451 && ((kw
->nick
&& kw
->nick
[0]
3452 && (newc
=hdr_color(kw
->nick
, NULL
,
3455 (kw
->kw
&& kw
->kw
[0]
3456 && (newc
=hdr_color(kw
->kw
, NULL
,
3458 lastc
= pico_get_cur_color();
3459 (void)pico_set_colorp(newc
, PSC_NONE
);
3460 free_color_pair(&newc
);
3464 free_spec_colors(&kw_col
);
3466 /* print out sample1 */
3470 w
= utf8_width(tmp_20k_buf
);
3473 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3474 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3480 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3484 ptr
= strindex(ptr
, ']');
3487 (void)pico_set_colorp(lastc
, PSC_NONE
);
3488 free_color_pair(&lastc
);
3494 newc
= sample_color(ps
, ctmp
->var
);
3496 if((lastc
= pico_get_cur_color()) != NULL
)
3497 (void)pico_set_colorp(newc
, PSC_NONE
);
3499 free_color_pair(&newc
);
3501 else if(var_defaults_to_rev(ctmp
->var
)){
3502 if((newc
= pico_get_rev_color()) != NULL
){
3504 * Note, don't have to free newc.
3506 if((lastc
= pico_get_cur_color()) != NULL
)
3507 (void)pico_set_colorp(newc
, PSC_NONE
);
3515 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3517 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3518 !(PVAL(ctmp
->var
,ew
) &&
3519 PVAL(ctmp
->var
+1,ew
))))
3522 /* print out sample1 */
3526 w
= utf8_width(tmp_20k_buf
);
3529 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3530 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3536 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3540 ptr
= strindex(ptr
, ']');
3542 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3544 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3545 !(PVAL(ctmp
->var
,ew
) &&
3546 PVAL(ctmp
->var
+1,ew
))))
3550 (void)pico_set_colorp(lastc
, PSC_NONE
);
3551 free_color_pair(&lastc
);
3558 * Finish sample1 with the right bracket.
3562 w
= utf8_width(tmp_20k_buf
);
3564 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3567 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3574 * Now check for an exception sample and paint it.
3576 if(ctmp
->valoffset
+ w
+ SBS
+ 1 < ps
->ttyo
->screen_cols
&& (q
= strstr(ptr
, SAMPEXC
))){
3580 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3585 * Figure out what color to paint it.
3586 * This only happens with normal variables,
3587 * not with V_VIEW_HDR_COLORS.
3591 newc
= sampleexc_color(ps
, ctmp
->var
);
3593 if((lastc
= pico_get_cur_color()) != NULL
)
3594 (void)pico_set_colorp(newc
, PSC_NONE
);
3596 free_color_pair(&newc
);
3598 else if(var_defaults_to_rev(ctmp
->var
)){
3599 if((newc
= pico_get_rev_color()) != NULL
){
3601 * Note, don't have to free newc.
3603 if((lastc
= pico_get_cur_color()) != NULL
)
3604 (void)pico_set_colorp(newc
, PSC_NONE
);
3612 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3614 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3615 !(PVAL(ctmp
->var
,Post
) &&
3616 PVAL(ctmp
->var
+1,Post
))))
3622 w
= utf8_width(tmp_20k_buf
);
3625 want_width
= MIN(utf8_width(SAMPEXC
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3626 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3632 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3636 ptr
= strindex(ptr
, ']');
3638 /* turn off bold and color */
3639 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3641 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3642 !(PVAL(ctmp
->var
,Post
) &&
3643 PVAL(ctmp
->var
+1,Post
))))
3647 (void)pico_set_colorp(lastc
, PSC_NONE
);
3648 free_color_pair(&lastc
);
3654 * Finish sample2 with the right bracket.
3658 w
= utf8_width(tmp_20k_buf
);
3660 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3663 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3670 /* paint rest of the line if there is any left */
3671 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
&& *ptr
){
3672 want_width
= ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
;
3673 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3679 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3686 w
= utf8_width(tmp_20k_buf
);
3687 want_width
= ps
->ttyo
->screen_cols
- ctmp
->valoffset
;
3689 saveptr
= utf8_count_forw_width(tmp_20k_buf
, want_width
, &got_width
);
3694 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, tmp_20k_buf
);
3695 if(ctmp
== screen
->current
)
3703 ps
->mangled_body
= 0;
3704 screen
->top_line
= top_line
;
3705 screen
->prev
= screen
->current
;
3717 print_option_screen(OPT_SCREEN_S
*screen
, char *prompt
)
3723 if(open_printer(prompt
) == 0){
3724 for(ctmp
= first_confline(screen
->current
);
3726 ctmp
= next_confline(ctmp
)){
3729 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3731 snprintf(line
, sizeof(line
), "%*s%s", ctmp
->varoffset
, "",
3733 line
[sizeof(line
)-1] = '\0';
3735 so_far
= ctmp
->varoffset
+ utf8_width(ctmp
->varname
);
3738 if(ctmp
&& ctmp
->value
){
3739 char *p
= tmp_20k_buf
;
3742 /* Copy the value to a temp buffer expanding tabs. */
3743 for(i
= 0, j
= ctmp
->valoffset
; ctmp
->value
[i
]; i
++){
3744 if(ctmp
->value
[i
] == ctrl('I')){
3747 while((++j
) & 0x07);
3751 *p
++ = ctmp
->value
[i
];
3757 removing_trailing_white_space(tmp_20k_buf
);
3759 spaces
= MAX(ctmp
->valoffset
- so_far
, 0);
3760 snprintf(line
, sizeof(line
), "%*s%s\n", spaces
, "", tmp_20k_buf
);
3761 line
[sizeof(line
)-1] = '\0';
3776 option_screen_redrawer(void)
3778 ps_global
->mangled_body
= 1;
3779 update_option_screen(ps_global
, opt_screen
, (Pos
*)NULL
);
3785 * pretty_value - given the line, return an
3786 * alloc'd string for line's value...
3789 pretty_value(struct pine
*ps
, CONF_S
*cl
)
3795 if(v
== &ps
->vars
[V_FEATURE_LIST
])
3796 return(checkbox_pretty_value(ps
, cl
));
3797 else if(standard_radio_var(ps
, v
) || v
== startup_ptr
)
3798 return(radio_pretty_value(ps
, cl
));
3799 else if(v
== &ps
->vars
[V_SORT_KEY
])
3800 return(sort_pretty_value(ps
, cl
));
3801 else if(v
== &ps
->vars
[V_SIGNATURE_FILE
])
3802 return(sigfile_pretty_value(ps
, cl
));
3803 else if(v
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
])
3804 return(yesno_pretty_value(ps
, cl
));
3805 else if(color_holding_var(ps
, v
))
3806 return(color_pretty_value(ps
, cl
));
3808 return(text_pretty_value(ps
, cl
));
3813 text_pretty_value(struct pine
*ps
, CONF_S
*cl
)
3815 char tmp
[6*MAX_SCREEN_COLS
+20], *pvalnorm
, **lvalnorm
, *pvalexc
, **lvalexc
;
3816 char *p
, *pval
, **lval
, lastchar
= '\0';
3817 int editing_except
, fixed
, uvalset
, uvalposlen
;
3819 int comments
, except_set
, avail_width
;
3820 int norm_with_except
= 0, norm_with_except_inherit
= 0;
3821 int inherit_line
= 0;
3823 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
3824 fixed
= cl
->var
->is_fixed
;
3825 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
))
3826 norm_with_except
++; /* editing normal and except config exists */
3828 if(cl
->var
->is_list
){
3829 lvalnorm
= LVAL(cl
->var
, Main
);
3830 lvalexc
= LVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3832 uvalset
= lvalexc
!= NULL
;
3833 uvalposlen
= uvalset
&& lvalexc
[0] && lvalexc
[0][0];
3837 uvalset
= lvalnorm
!= NULL
;
3838 uvalposlen
= uvalset
&& lvalnorm
[0] && lvalnorm
[0][0];
3842 except_set
= lvalexc
!= NULL
;
3843 comments
= cl
->var
->current_val
.l
!= NULL
;
3844 if(norm_with_except
&& except_set
&& lvalexc
[0] &&
3845 !strcmp(lvalexc
[0],INHERIT
))
3846 norm_with_except_inherit
++;
3848 if(uvalset
&& !strcmp(lval
[0], INHERIT
)){
3849 if(cl
->varmem
== 0){
3855 /* only add extra comments on last member of list */
3856 if(uvalset
&& !inherit_line
&& lval
&& lval
[cl
->varmem
] &&
3857 lval
[cl
->varmem
+ 1])
3861 pvalnorm
= PVAL(cl
->var
, Main
);
3862 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3864 uvalset
= pvalexc
!= NULL
;
3865 uvalposlen
= uvalset
&& *pvalexc
;
3869 uvalset
= pvalnorm
!= NULL
;
3870 uvalposlen
= uvalset
&& *pvalnorm
;
3874 except_set
= pvalexc
!= NULL
;
3875 comments
= cl
->var
->current_val
.p
!= NULL
;
3878 memset(tmp
, 0, sizeof(tmp
));
3882 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
3884 if(fixed
|| !uvalset
|| !uvalposlen
){
3885 p
+= utf8_to_width(p
, "<", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3886 avail_width
-= got_width
;
3890 p
+= utf8_to_width(p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3891 avail_width
-= got_width
;
3894 p
+= utf8_to_width(p
, _(no_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3895 avail_width
-= got_width
;
3897 else if(!uvalposlen
){
3898 p
+= utf8_to_width(p
, _(empty_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3899 avail_width
-= got_width
;
3901 else if(inherit_line
){
3902 p
+= utf8_to_width(p
, INHERIT
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3903 avail_width
-= got_width
;
3906 if(cl
->var
->is_list
){
3907 p
+= utf8_to_width(p
, lval
[cl
->varmem
], sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3908 avail_width
-= got_width
;
3911 p
+= utf8_to_width(p
, pval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3912 avail_width
-= got_width
;
3916 if(comments
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
3917 if(fixed
|| !uvalset
){
3918 p
+= utf8_to_width(p
, ": using ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3919 avail_width
-= got_width
;
3922 if(norm_with_except
&& except_set
){
3924 p
+= utf8_to_width(p
, "exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3925 avail_width
-= got_width
;
3929 p
+= utf8_to_width(p
, ": ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3930 avail_width
-= got_width
;
3933 p
+= utf8_to_width(p
, " (", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3934 avail_width
-= got_width
;
3937 if(norm_with_except_inherit
){
3938 p
+= utf8_to_width(p
, "added to by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3939 avail_width
-= got_width
;
3942 p
+= utf8_to_width(p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3943 avail_width
-= got_width
;
3948 if(avail_width
>= 7){
3949 if(cl
->var
== &ps_global
->vars
[V_POST_CHAR_SET
]){
3950 p
+= utf8_to_width(p
, "most specific (see help)", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3951 avail_width
-= got_width
;
3954 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
3956 if(cl
->var
->is_list
){
3959 the_list
= cl
->var
->current_val
.l
;
3961 if(norm_with_except
&& except_set
)
3964 if(the_list
&& the_list
[0] && !strcmp(the_list
[0], INHERIT
))
3967 for(lval
= the_list
; avail_width
-(p
-tmp
) > 0 && *lval
; lval
++){
3968 if(lval
!= the_list
){
3969 p
+= utf8_to_width(p
, ",", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3970 avail_width
-= got_width
;
3973 p
+= utf8_to_width(p
, *lval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3974 avail_width
-= got_width
;
3978 p
+= utf8_to_width(p
, cl
->var
->current_val
.p
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3979 avail_width
-= got_width
;
3982 if(p
-tmp
+2 < sizeof(tmp
)){
3988 else if(*(p
-1) == SPACE
)
3992 tmp
[sizeof(tmp
)-1] = '\0';
3994 if(fixed
|| !uvalset
|| !uvalposlen
)
3996 else if(comments
&& norm_with_except
&& except_set
)
4000 if(p
-tmp
+2 < sizeof(tmp
)){
4006 tmp
[sizeof(tmp
)-1] = '\0';
4007 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
4009 if(utf8_width(tmp
) < avail_width
)
4010 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
), "%*s", avail_width
-utf8_width(tmp
), "");
4012 tmp
[sizeof(tmp
)-1] = '\0';
4014 return(cpystr(tmp
));
4019 checkbox_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4021 char tmp
[6*MAXPATH
];
4022 char *comment
= NULL
;
4023 int indent
, x
, screen_width
, need
;
4024 int longest_featname
, longest_comment
;
4025 int nwidcomm
; /* name width with comment */
4026 int nwidnocomm
; /* and without comment */
4029 screen_width
= (ps
&& ps
->ttyo
) ? ps
->ttyo
->screen_cols
: 80;
4032 longest_featname
= longest_feature_name();
4033 longest_comment
= longest_feature_comment(ps
, ew
);
4034 indent
= feature_indent();
4036 nwidcomm
= longest_featname
;
4037 nwidnocomm
= longest_featname
+ 2 + longest_comment
;
4039 if((need
= (indent
+ 5 + longest_featname
+ 2 + longest_comment
) - screen_width
) > 0){
4045 longest_comment
= 0;
4046 nwidnocomm
= longest_featname
;
4050 feature
= feature_list(cl
->varmem
);
4052 x
= feature_gets_an_x(ps
, cl
->var
, feature
, &comment
, ew
);
4054 if(longest_comment
&& comment
&& *comment
){
4055 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w %-*.*w", x
? 'X' : ' ',
4057 pretty_feature_name(feature
->name
, nwidcomm
),
4058 longest_comment
, longest_comment
, comment
? comment
: "");
4061 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w", x
? 'X' : ' ',
4062 nwidnocomm
, nwidnocomm
,
4063 pretty_feature_name(feature
->name
, nwidnocomm
));
4066 return(cpystr(tmp
));
4071 longest_feature_name(void)
4078 for(lv
= 0, i
= 0; (feature
= feature_list(i
)); i
++)
4079 if(feature_list_section(feature
)
4080 && lv
< (j
= utf8_width(pretty_feature_name(feature
->name
, -1))))
4091 feature_indent(void)
4098 yesno_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4100 char tmp
[6*MAXPATH
], *pvalnorm
, *pvalexc
;
4101 char *p
, *pval
, lastchar
= '\0';
4102 int editing_except
, fixed
, norm_with_except
, uvalset
;
4103 int curval
, except_set
;
4105 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
4106 fixed
= cl
->var
->is_fixed
;
4107 if((ps_global
->ew_for_except_vars
== Main
) ||
4108 (ew
== ps_global
->ew_for_except_vars
))
4109 norm_with_except
= 0;
4111 norm_with_except
= 1; /* editing normal and except config exists */
4113 pvalnorm
= PVAL(cl
->var
, Main
);
4114 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
4116 uvalset
= (pvalexc
!= NULL
&&
4117 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4121 uvalset
= (pvalnorm
!= NULL
&&
4122 (!strucmp(pvalnorm
,yesstr
) || !strucmp(pvalnorm
,nostr
)));
4126 except_set
= (pvalexc
!= NULL
&&
4127 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4128 curval
= (cl
->var
->current_val
.p
!= NULL
&&
4129 (!strucmp(cl
->var
->current_val
.p
,yesstr
) ||
4130 !strucmp(cl
->var
->current_val
.p
,nostr
)));
4135 if(fixed
|| !uvalset
)
4136 sstrncpy(&p
, "<", sizeof(tmp
)-(p
-tmp
));
4139 sstrncpy(&p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
));
4141 sstrncpy(&p
, _(no_val
), sizeof(tmp
)-(p
-tmp
));
4142 else if(!strucmp(pval
, yesstr
))
4143 sstrncpy(&p
, yesstr
, sizeof(tmp
)-(p
-tmp
));
4145 sstrncpy(&p
, nostr
, sizeof(tmp
)-(p
-tmp
));
4147 if(curval
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
4148 if(fixed
|| !uvalset
)
4149 sstrncpy(&p
, ": using ", sizeof(tmp
)-(p
-tmp
));
4151 if(norm_with_except
&& except_set
){
4153 sstrncpy(&p
, "exception ", sizeof(tmp
)-(p
-tmp
));
4155 sstrncpy(&p
, " (", sizeof(tmp
)-(p
-tmp
));
4156 sstrncpy(&p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
));
4160 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4161 sstrncpy(&p
, !strucmp(cl
->var
->current_val
.p
,yesstr
) ? yesstr
: nostr
, sizeof(tmp
)-(p
-tmp
));
4162 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4165 if(fixed
|| !uvalset
)
4167 else if(curval
&& norm_with_except
&& except_set
)
4170 if(lastchar
&& sizeof(tmp
)-(p
-tmp
) > 1){
4175 tmp
[sizeof(tmp
)-1] = '\0';
4177 if(utf8_width(tmp
) < ps
->ttyo
->screen_cols
- cl
->valoffset
)
4178 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
),
4179 "%*s", ps
->ttyo
->screen_cols
- cl
->valoffset
- utf8_width(tmp
), "");
4181 tmp
[sizeof(tmp
)-1] = '\0';
4183 return(cpystr(tmp
));
4188 radio_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4190 char tmp
[6*MAXPATH
];
4191 char *pvalnorm
, *pvalexc
, *pval
;
4192 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4193 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4195 NAMEVAL_S
*rule
= NULL
, *f
;
4196 PTR_TO_RULEFUNC rulefunc
;
4202 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4204 editing_normal_which_isnt_except
= (ew
== Main
&&
4205 ew
!= ps_global
->ew_for_except_vars
);
4206 fixed
= cl
->var
->is_fixed
;
4207 pvalnorm
= PVAL(v
, Main
);
4208 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4210 rulefunc
= rulefunc_from_var(ps
, v
);
4211 rule
= rulefunc
? (*rulefunc
)(cl
->varmem
) : NULL
;
4213 /* find longest name */
4215 for(lv
= 0, i
= 0; (f
= (*rulefunc
)(i
)); i
++)
4216 if(lv
< (j
= utf8_width(f
->name
)))
4221 if(editing_except_which_isnt_normal
)
4227 is_set_for_this_level
++;
4230 pval
= v
->fixed_val
.p
;
4231 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4233 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4234 is_the_one
? R_SELD
: ' ',
4235 lv
, lv
, rule
->name
, is_the_one
? " (value is fixed)" : "");
4237 else if(is_set_for_this_level
){
4238 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4239 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4240 !strucmp(pvalexc
, S_OR_L(rule
)));
4241 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4242 is_the_one
? R_SELD
: ' ',
4244 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4245 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4247 editing_normal_which_isnt_except
&&
4249 !the_exc_one
) ? " (overridden by exceptions)" :
4254 is_the_one
= !strucmp(pvalexc
, S_OR_L(rule
));
4255 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4256 is_the_one
? R_SELD
: ' ',
4258 is_the_one
? " (value set in exceptions)" : "");
4261 pval
= v
->current_val
.p
;
4262 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4263 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4264 is_the_one
? R_SELD
: ' ',
4266 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4270 tmp
[sizeof(tmp
)-1] = '\0';
4272 return(cpystr(tmp
));
4277 sigfile_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4279 if(cl
&& cl
->var
== &ps
->vars
[V_SIGNATURE_FILE
] &&
4280 cl
->prev
&& cl
->prev
->var
== &ps
->vars
[V_LITERAL_SIG
]){
4281 if(cl
->prev
->var
->current_val
.p
){
4282 cl
->flags
|= CF_NOSELECT
; /* side effect */
4283 return(cpystr(_("<Ignored: using Literal-Signature instead>")));
4286 cl
->flags
&= ~CF_NOSELECT
;
4287 return(text_pretty_value(ps
, cl
));
4296 color_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4298 char tmp
[6*MAXPATH
];
4306 if(v
&& color_holding_var(ps
, v
) &&
4307 (p
=srchstr(v
->name
, "-foreground-color"))){
4309 is_index
= !struncmp(v
->name
, "index-", 6);
4311 q
= sampleexc_text(ps
, v
);
4312 utf8_snprintf(tmp
, sizeof(tmp
), "%c%.*s %sColor%*.50s %.20w%*s%.20w%.20w",
4313 islower((unsigned char)v
->name
[0])
4314 ? toupper((unsigned char)v
->name
[0])
4316 MIN(p
-v
->name
-1,30), v
->name
+1,
4317 is_index
? "Symbol " : "",
4318 MAX(EQ_COL
- COLOR_INDENT
-1 - MIN(p
-v
->name
-1,30)
4319 - 6 - (is_index
? 7 : 0) - 1,0), "",
4320 sample_text(ps
,v
), *q
? SBS
: 0, "", q
,
4321 color_parenthetical(v
));
4324 tmp
[sizeof(tmp
)-1] = '\0';
4326 return(cpystr(tmp
));
4331 sort_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4333 return(generalized_sort_pretty_value(ps
, cl
, 1));
4338 generalized_sort_pretty_value(struct pine
*ps
, CONF_S
*cl
, int default_ok
)
4340 char tmp
[6*MAXPATH
];
4341 char *pvalnorm
, *pvalexc
, *pval
;
4342 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4343 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4346 SortOrder line_sort
, var_sort
, exc_sort
;
4347 int line_sort_rev
, var_sort_rev
, exc_sort_rev
;
4352 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4354 editing_normal_which_isnt_except
= (ew
== Main
&&
4355 ew
!= ps_global
->ew_for_except_vars
);
4356 fixed
= cl
->var
->is_fixed
;
4357 pvalnorm
= PVAL(v
, Main
);
4358 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4360 /* find longest value's name */
4361 for(lv
= 0, i
= 0; ps
->sort_types
[i
] != EndofList
; i
++)
4362 if(lv
< (j
= utf8_width(sort_name(ps
->sort_types
[i
]))))
4367 if(editing_except_which_isnt_normal
)
4373 is_set_for_this_level
++;
4375 /* the config line we're talking about */
4376 if(cl
->varmem
>= 0){
4377 line_sort_rev
= cl
->varmem
>= (short)EndofList
;
4378 line_sort
= (SortOrder
)(cl
->varmem
- (line_sort_rev
* EndofList
));
4382 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*w",
4383 (pval
== NULL
) ? R_SELD
: ' ',
4387 pval
= v
->fixed_val
.p
;
4388 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4389 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4391 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4392 is_the_one
? R_SELD
: ' ',
4393 line_sort_rev
? "Reverse " : "",
4394 lv
, sort_name(line_sort
),
4395 line_sort_rev
? 0 : 8, "",
4396 is_the_one
? " (value is fixed)" : "");
4398 else if(is_set_for_this_level
){
4399 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4400 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4401 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4402 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4403 exc_sort_rev
== line_sort_rev
&& exc_sort
== line_sort
);
4404 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4405 is_the_one
? R_SELD
: ' ',
4406 line_sort_rev
? "Reverse " : "",
4407 lv
, sort_name(line_sort
),
4408 line_sort_rev
? 0 : 8, "",
4409 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4410 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4412 editing_normal_which_isnt_except
&&
4414 !the_exc_one
) ? " (overridden by exceptions)" :
4419 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4420 is_the_one
= (exc_sort_rev
== line_sort_rev
&&
4421 exc_sort
== line_sort
);
4422 utf8_snprintf(tmp
, sizeof(tmp
), "( ) %s%-*w%*s%s",
4423 line_sort_rev
? "Reverse " : "",
4424 lv
, sort_name(line_sort
),
4425 line_sort_rev
? 0 : 8, "",
4426 is_the_one
? " (value set in exceptions)" : "");
4429 pval
= v
->current_val
.p
;
4430 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4431 is_the_one
= ((pval
|| default_ok
) &&
4432 var_sort_rev
== line_sort_rev
&&
4433 var_sort
== line_sort
);
4434 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4435 is_the_one
? R_SELD
: ' ',
4436 line_sort_rev
? "Reverse " : "",
4437 lv
, sort_name(line_sort
),
4438 line_sort_rev
? 0 : 8, "",
4439 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4443 return(cpystr(tmp
));
4448 sample_color(struct pine
*ps
, struct variable
*v
)
4450 COLOR_PAIR
*cp
= NULL
;
4451 char *pvalefg
, *pvalebg
;
4452 char *pvalmfg
, *pvalmbg
;
4454 pvalefg
= PVAL(v
, ew
);
4455 pvalebg
= PVAL(v
+1, ew
);
4456 pvalmfg
= PVAL(v
, Main
);
4457 pvalmbg
= PVAL(v
+1, Main
);
4458 if(v
&& color_holding_var(ps
, v
) &&
4459 srchstr(v
->name
, "-foreground-color")){
4460 if(pvalefg
&& pvalefg
[0] && pvalebg
&& pvalebg
[0])
4461 cp
= new_color_pair(pvalefg
, pvalebg
);
4462 else if(ew
== Post
&& pvalmfg
&& pvalmfg
[0] && pvalmbg
&& pvalmbg
[0])
4463 cp
= new_color_pair(pvalmfg
, pvalmbg
);
4464 else if(v
->global_val
.p
&& v
->global_val
.p
[0] &&
4465 (v
+1)->global_val
.p
&& (v
+1)->global_val
.p
[0])
4466 cp
= new_color_pair(v
->global_val
.p
, (v
+1)->global_val
.p
);
4474 sampleexc_color(struct pine
*ps
, struct variable
*v
)
4476 COLOR_PAIR
*cp
= NULL
;
4477 char *pvalfg
, *pvalbg
;
4479 pvalfg
= PVAL(v
, Post
);
4480 pvalbg
= PVAL(v
+1, Post
);
4481 if(v
&& color_holding_var(ps
, v
) &&
4482 srchstr(v
->name
, "-foreground-color") &&
4483 pvalfg
&& pvalfg
[0] && pvalbg
&& pvalbg
[0])
4484 cp
= new_color_pair(pvalfg
, pvalbg
);
4491 clear_feature(char ***l
, char *f
)
4493 char **list
= l
? *l
: NULL
;
4496 for(; list
&& *list
; list
++, count
++){
4497 if(f
&& !strucmp(((!struncmp(*list
,"no-",3)) ? *list
+ 3 : *list
), f
)){
4498 fs_give((void **)list
);
4503 *list
= *(list
+ 1);
4507 * this is helpful to keep the array from growing if a feature
4508 * get's set and unset repeatedly
4511 fs_resize((void **)l
, count
* sizeof(char *));
4519 toggle_feature_bit(struct pine
*ps
, int index
, struct variable
*var
, CONF_S
*cl
, int just_flip_value
)
4525 f
= feature_list(index
);
4527 og
= test_old_growth_bits(ps
, f
->id
);
4530 * if this feature is in the fixed set, or old-growth is in the fixed
4531 * set and this feature is in the old-growth set, don't alter it...
4533 for(vp
= var
->fixed_val
.l
; vp
&& *vp
; vp
++){
4534 p
= (struncmp(*vp
, "no-", 3)) ? *vp
: *vp
+ 3;
4535 if(!strucmp(p
, f
->name
) || (og
&& !strucmp(p
, "old-growth"))){
4536 q_status_message(SM_ORDER
, 3, 3,
4537 _("Can't change value fixed by sys-admin."));
4542 on_before
= F_ON(f
->id
, ps
);
4544 toggle_feature(ps
, var
, f
, just_flip_value
, ew
);
4547 * Handle any alpine-specific features that need attention here. Features
4548 * that aren't alpine-specific should be handled in toggle_feature instead.
4550 if(on_before
!= F_ON(f
->id
, ps
))
4552 case F_CMBND_ABOOK_DISP
:
4556 case F_PRESERVE_START_STOP
:
4557 /* toggle raw mode settings to make tty driver aware of new setting */
4563 ps
->orig_use_fkeys
= F_ON(F_USE_FK
, ps
);
4564 ps
->mangled_footer
= 1;
4565 mark_keymenu_dirty();
4569 ps
->mangled_header
= 1;
4572 case F_BLANK_KEYMENU
:
4573 if(F_ON(f
->id
, ps
)){
4574 FOOTER_ROWS(ps
) = 1;
4575 ps
->mangled_body
= 1;
4578 FOOTER_ROWS(ps
) = 3;
4579 ps
->mangled_footer
= 1;
4585 case F_ENABLE_INCOMING
:
4586 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4587 "Folder List changes will take effect your next Alpine session.");
4591 case F_SHOW_CURSOR
:
4592 mswin_showcaret(F_ON(f
->id
,ps
));
4595 case F_ENABLE_TRAYICON
:
4596 mswin_trayicon(F_ON(f
->id
,ps
));
4600 #if !defined(DOS) && !defined(OS2)
4610 case F_PASS_CONTROL_CHARS
:
4611 ps
->pass_ctrl_chars
= F_ON(F_PASS_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4614 case F_PASS_C1_CONTROL_CHARS
:
4615 ps
->pass_c1_ctrl_chars
= F_ON(F_PASS_C1_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4619 case F_ENABLE_MOUSE
:
4620 if(F_ON(f
->id
, ps
)){
4623 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4624 "Mouse tracking still off ($DISPLAY variable set?)");
4633 if(just_flip_value
){
4634 if(cl
->value
&& cl
->value
[0])
4635 cl
->value
[1] = (cl
->value
[1] == ' ') ? 'X' : ' ';
4639 * This fork is only called from the checkbox_tool, which has
4640 * varmem set to index correctly and cl->var set correctly.
4643 fs_give((void **)&cl
->value
);
4645 cl
->value
= pretty_value(ps
, cl
);
4651 * new_confline - create new CONF_S zero it out, and insert it after current.
4652 * NOTE current gets set to the new CONF_S too!
4655 new_confline(CONF_S
**current
)
4659 p
= (CONF_S
*)fs_get(sizeof(CONF_S
));
4660 memset((void *)p
, 0, sizeof(CONF_S
));
4663 p
->next
= (*current
)->next
;
4664 (*current
)->next
= p
;
4681 snip_confline(CONF_S
**p
)
4686 * Be careful. We need this line because the
4687 * q->prev->next = ...
4688 * may change q itself if &q == &q->prev->next.
4689 * Then the use of q in the next line is wrong.
4690 * That's what happens if we pass in the address of
4691 * some ->next and use *p directly instead of q.
4696 /* Yank it from the linked list */
4698 q
->prev
->next
= q
->next
;
4701 q
->next
->prev
= q
->prev
;
4703 /* Then free up it's memory */
4704 q
->prev
= q
->next
= NULL
;
4714 free_conflines(CONF_S
**p
)
4717 free_conflines(&(*p
)->next
);
4720 fs_give((void **) &(*p
)->varname
);
4723 fs_give((void **) &(*p
)->value
);
4725 fs_give((void **) p
);
4734 first_confline(CONF_S
*p
)
4744 * First selectable confline.
4747 first_sel_confline(CONF_S
*p
)
4749 for(p
= first_confline(p
); p
&& (p
->flags
&CF_NOSELECT
); p
=next_confline(p
))
4760 last_confline(CONF_S
*p
)
4773 fixed_var(struct variable
*v
, char *action
, char *name
)
4779 || ((lval
=v
->fixed_val
.l
) && lval
[0]
4780 && strcmp(INHERIT
, lval
[0]) != 0))){
4781 q_status_message2(SM_ORDER
, 3, 3,
4782 "Can't %s sys-admin defined %s.",
4783 action
? action
: "change", name
? name
: "value");
4792 exception_override_warning(struct variable
*v
)
4796 /* if exceptions config file exists and we're not editing it */
4797 if(v
&& (ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
4798 if((!v
->is_list
&& PVAL(v
, ps_global
->ew_for_except_vars
)) ||
4799 (v
->is_list
&& (lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
4800 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0))
4801 q_status_message1(SM_ORDER
, 3, 3,
4802 _("Warning: \"%s\" is overridden in your exceptions configuration"),
4809 offer_to_fix_pinerc(struct pine
*ps
)
4816 int rv
= 0, write_main
= 0, write_post
= 0;
4817 int i
, k
, j
, need
, exc
;
4818 char *clear
= ": delete it";
4821 dprint((4, "offer_to_fix_pinerc()\n"));
4823 ps
->fix_fixed_warning
= 0; /* so we only ask first time */
4825 if(ps
->readonly_pinerc
)
4828 set_titlebar(_("FIXING PINERC"), ps
->mail_stream
,
4829 ps
->context_current
,
4830 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
4832 if(want_to(_("Some of your options conflict with site policy. Investigate"),
4833 'y', 'n', NO_HELP
, WT_FLUSH_IN
) != 'y')
4836 /* space want_to requires in addition to the string you pass in */
4837 #define WANTTO_SPACE 6
4838 need
= WANTTO_SPACE
+ utf8_width(clear
);
4840 for(v
= ps
->vars
; v
->name
; v
++){
4844 v
== &ps
->vars
[V_FEATURE_LIST
]) /* handle feature-list below */
4850 (v
->post_user_val
.l
|| v
->main_user_val
.l
)){
4853 active_list
= v
->post_user_val
.l
? v
->post_user_val
.l
4854 : v
->main_user_val
.l
;
4856 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is "), v
->name
);
4857 prompt
[sizeof(prompt
)-1] = '\0';
4858 p
= prompt
+ strlen(prompt
);
4859 for(i
= 0; active_list
[i
]; i
++){
4860 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4862 if(i
&& sizeof(prompt
)-(p
-prompt
) > 0)
4865 sstrncpy(&p
, active_list
[i
], sizeof(prompt
)-(p
-prompt
));
4866 if(sizeof(prompt
)-(p
-prompt
) > 0)
4869 prompt
[sizeof(prompt
)-1] = '\0';
4872 if(sizeof(prompt
)-(p
-prompt
) > 0)
4876 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"), v
->name
, _(empty_val2
));
4879 if(v
->post_user_val
.p
|| v
->main_user_val
.p
){
4882 active_var
= v
->post_user_val
.p
? v
->post_user_val
.p
4883 : v
->main_user_val
.p
;
4885 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4886 v
->name
, active_var
);
4889 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4890 v
->name
, _(empty_val2
));
4895 prompt
[sizeof(prompt
)-1] = '\0';
4898 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4899 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4901 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4902 prompt
[sizeof(prompt
)-1] = '\0';
4903 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4905 if(v
->main_user_val
.l
)
4907 if(v
->post_user_val
.l
)
4911 if(v
->main_user_val
.p
)
4913 if(v
->post_user_val
.p
)
4917 if(delete_user_vals(v
))
4925 * As always, feature-list has to be handled separately.
4927 exc
= (ps
->ew_for_except_vars
!= Main
);
4928 v
= &ps
->vars
[V_FEATURE_LIST
];
4929 list_fixed
= v
->fixed_val
.l
;
4931 for(j
= 0; j
< 2; j
++){
4932 plist
= (j
==0) ? &v
->main_user_val
.l
: &v
->post_user_val
.l
;
4935 for(i
= 0; list
[i
]; i
++){
4937 if(!struncmp(p
, "no-", 3))
4939 for(k
= 0; list_fixed
&& list_fixed
[k
]; k
++){
4941 if(!struncmp(q
, "no-", 3))
4943 if(!strucmp(q
, p
) && strucmp(list
[i
], list_fixed
[k
])){
4944 snprintf(prompt
, sizeof(prompt
), "Your %s is %s%s, fixed value is %s",
4945 p
, p
== list
[i
] ? _("ON") : _("OFF"),
4946 exc
? ((plist
== &v
->main_user_val
.l
) ? ""
4947 : " in postload-config")
4949 q
== list_fixed
[k
] ? _("ON") : _("OFF"));
4951 prompt
[sizeof(prompt
)-1] = '\0';
4952 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4953 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4955 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4956 prompt
[sizeof(prompt
)-1] = '\0';
4957 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4960 if(plist
== &v
->main_user_val
.l
)
4966 * Clear the feature from the user's pinerc
4967 * so that we'll stop bothering them when they
4970 clear_feature(plist
, p
);
4973 * clear_feature scoots the list up, so if list[i] was
4974 * the last one going in, now it is the end marker. We
4975 * just decrement i so that it will get incremented and
4976 * then test == 0 in the for loop. We could just goto
4977 * outta_here to accomplish the same thing.
4990 write_pinerc(ps
, Main
, WRP_NONE
);
4992 write_pinerc(ps
, Post
, WRP_NONE
);
4999 * Adjust side effects that happen because variable changes values.
5001 * Var->user_val should be set to the new value before calling this.
5004 fix_side_effects(struct pine
*ps
, struct variable
*var
, int revert
)
5007 char **v
, *q
, **apval
;
5008 struct variable
*vars
= ps
->vars
;
5010 /* move this up here so we get the Using default message */
5011 if(var
== &ps
->vars
[V_PERSONAL_NAME
]){
5012 if(!(var
->main_user_val
.p
||
5013 var
->post_user_val
.p
) && ps
->ui
.fullname
){
5014 if(var
->current_val
.p
)
5015 fs_give((void **)&var
->current_val
.p
);
5017 var
->current_val
.p
= cpystr(ps
->ui
.fullname
);
5024 && !(var
->main_user_val
.p
||
5025 var
->post_user_val
.p
)
5026 && var
->current_val
.p
)
5030 && !(var
->main_user_val
.l
||
5031 var
->post_user_val
.l
)
5032 && var
->current_val
.l
)))
5033 q_status_message(SM_ORDER
,0,3,_("Using default value"));
5035 if(var
== &ps
->vars
[V_USER_DOMAIN
]){
5038 if(ps
->VAR_USER_DOMAIN
5039 && ps
->VAR_USER_DOMAIN
[0]
5040 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5043 q_status_message2(SM_ORDER
, 3, 5,
5044 _("User-Domain (%s) cannot contain \"@\"; using %s"),
5045 ps
->VAR_USER_DOMAIN
, p
);
5046 q
= ps
->VAR_USER_DOMAIN
;
5047 while((*q
++ = *p
++) != '\0')
5052 q_status_message1(SM_ORDER
, 3, 5,
5053 _("User-domain (%s) cannot contain \"@\"; deleting"),
5054 ps
->VAR_USER_DOMAIN
);
5056 if(ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
){
5057 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
);
5058 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5061 if(ps
->VAR_USER_DOMAIN
5062 && ps
->VAR_USER_DOMAIN
[0]
5063 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5064 if(ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
){
5065 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
);
5066 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5073 * Reset various pointers pertaining to domain name and such...
5077 else if(var
== &ps
->vars
[V_INBOX_PATH
]){
5079 * fixup the inbox path based on global/default values...
5081 init_inbox_mapping(ps
->VAR_INBOX_PATH
, ps
->context_list
);
5083 if(!strucmp(ps
->cur_folder
, ps
->inbox_name
) && ps
->mail_stream
5084 && strcmp(ps
->VAR_INBOX_PATH
, ps
->mail_stream
->mailbox
)){
5086 * If we currently have "inbox" open and the mailbox name
5087 * doesn't match, reset the current folder's name and
5088 * remove the SP_INBOX flag.
5090 strncpy(ps
->cur_folder
, ps
->mail_stream
->mailbox
,
5091 sizeof(ps
->cur_folder
)-1);
5092 ps
->cur_folder
[sizeof(ps
->cur_folder
)-1] = '\0';
5093 sp_set_fldr(ps
->mail_stream
, ps
->cur_folder
);
5094 sp_unflag(ps
->mail_stream
, SP_INBOX
);
5095 ps
->mangled_header
= 1;
5097 else if(sp_inbox_stream()
5098 && strcmp(ps
->VAR_INBOX_PATH
, sp_inbox_stream()->original_mailbox
)){
5099 MAILSTREAM
*m
= sp_inbox_stream();
5102 * if we don't have inbox directly open, but have it
5103 * open for new mail notification, close the stream like
5104 * any other ordinary folder, and clean up...
5107 sp_unflag(m
, SP_PERMLOCKED
| SP_INBOX
);
5108 sp_set_fldr(m
, m
->mailbox
);
5109 expunge_and_close(m
, NULL
, EC_NONE
);
5113 else if(var
== &ps
->vars
[V_INCCHECKTIMEO
]){
5114 int old_value
= ps
->inc_check_timeout
;
5116 if(SVAR_INC_CHECK_TIMEO(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5118 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5121 ps
->inc_check_timeout
= old_value
;
5123 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5124 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5126 else if(var
== &ps
->vars
[V_INCCHECKINTERVAL
]){
5127 int old_value
= ps
->inc_check_interval
;
5129 if(SVAR_INC_CHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5131 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5134 ps
->inc_check_interval
= old_value
;
5136 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5137 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5139 else if(var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
]){
5140 int old_value
= ps
->inc_second_check_interval
;
5142 if(SVAR_INC_2NDCHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5144 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5147 ps
->inc_second_check_interval
= old_value
;
5149 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5150 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5152 else if(var
== &ps
->vars
[V_INCCHECKLIST
]){
5153 if(ps
->context_list
&& ps
->context_list
->use
& CNTXT_INCMNG
)
5154 reinit_incoming_folder_list(ps
, ps
->context_list
);
5156 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5157 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5159 else if(var
== &ps
->vars
[V_ADDRESSBOOK
] ||
5160 var
== &ps
->vars
[V_GLOB_ADDRBOOK
] ||
5162 var
== &ps
->vars
[V_LDAP_SERVERS
] ||
5164 var
== &ps
->vars
[V_ABOOK_FORMATS
]){
5167 else if(var
== &ps
->vars
[V_INDEX_FORMAT
]){
5168 reset_index_format();
5169 clear_index_cache(ps
->mail_stream
, 0);
5171 else if(var
== &ps
->vars
[V_DEFAULT_FCC
] ||
5172 var
== &ps
->vars
[V_DEFAULT_SAVE_FOLDER
]){
5173 init_save_defaults();
5175 else if(var
== &ps
->vars
[V_KW_BRACES
] ||
5176 var
== &ps
->vars
[V_OPENING_SEP
] ||
5177 var
== &ps
->vars
[V_ALT_ADDRS
]){
5178 clear_index_cache(ps
->mail_stream
, 0);
5180 else if(var
== &ps
->vars
[V_KEYWORDS
]){
5181 if(ps_global
->keywords
)
5182 free_keyword_list(&ps_global
->keywords
);
5184 if(var
->current_val
.l
&& var
->current_val
.l
[0])
5185 ps_global
->keywords
= init_keyword_list(var
->current_val
.l
);
5187 clear_index_cache(ps
->mail_stream
, 0);
5189 else if(var
== &ps
->vars
[V_INIT_CMD_LIST
]){
5191 q_status_message(SM_ASYNC
, 0, 3,
5192 _("Initial command changes will affect your next Alpine session."));
5194 else if(var
== &ps
->vars
[V_VIEW_HEADERS
]){
5195 ps
->view_all_except
= 0;
5196 if(ps
->VAR_VIEW_HEADERS
)
5197 for(v
= ps
->VAR_VIEW_HEADERS
; (q
= *v
) != NULL
; v
++)
5201 removing_leading_white_space(q
);
5202 /* look for colon or space or end */
5203 for(p
= q
; *p
&& !isspace((unsigned char)*p
) && *p
!= ':'; p
++)
5207 if(strucmp(q
, ALL_EXCEPT
) == 0)
5208 ps
->view_all_except
= 1;
5211 else if(var
== &ps
->vars
[V_OVERLAP
]){
5212 int old_value
= ps
->viewer_overlap
;
5214 if(SVAR_OVERLAP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5216 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5219 ps
->viewer_overlap
= old_value
;
5221 else if(var
== &ps
->vars
[V_SLEEP
]){
5222 int old_value
= ps
->sleep
;
5224 if(SVAR_SLEEP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5226 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5229 ps
->sleep
= old_value
;
5232 else if(smime_related_var(ps
, var
)){
5236 else if(var
== &ps
->vars
[V_MAXREMSTREAM
]){
5237 int old_value
= ps
->s_pool
.max_remstream
;
5239 if(SVAR_MAXREMSTREAM(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5241 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5244 ps
->s_pool
.max_remstream
= old_value
;
5246 dprint((9, "max_remstream goes to %d\n",
5247 ps
->s_pool
.max_remstream
));
5250 else if(var
== &ps
->vars
[V_CHAR_SET
]){
5253 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5255 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5258 if(reset_character_set_stuff(&err
) == -1)
5259 panic(err
? err
: "trouble with Character-Set");
5261 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5262 fs_give((void **) &err
);
5266 else if(var
== &ps
->vars
[V_KEY_CHAR_SET
]){
5269 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5271 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5274 if(reset_character_set_stuff(&err
) == -1)
5275 panic(err
? err
: "trouble with Character-Set");
5277 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5278 fs_give((void **) &err
);
5282 #endif /* ! _WINDOWS */
5283 else if(var
== &ps
->vars
[V_POST_CHAR_SET
]){
5284 update_posting_charset(ps
, revert
);
5286 else if(var
== &ps
->vars
[V_MARGIN
]){
5287 int old_value
= ps
->scroll_margin
;
5289 if(SVAR_MARGIN(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5291 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5294 ps
->scroll_margin
= old_value
;
5296 else if(var
== &ps
->vars
[V_DEADLETS
]){
5297 int old_value
= ps
->deadlets
;
5299 if(SVAR_DEADLETS(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5301 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5304 ps
->deadlets
= old_value
;
5306 else if(var
== &ps
->vars
[V_FILLCOL
]){
5307 if(SVAR_FILLCOL(ps
, ps
->composer_fillcol
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5309 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5312 else if(var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
5313 val
= ps
->quote_suppression_threshold
;
5314 if(val
< Q_SUPP_LIMIT
&& val
> 0)
5317 if(ps
->VAR_QUOTE_SUPPRESSION
5318 && SVAR_QUOTE_SUPPRESSION(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5320 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5323 if(val
> 0 && val
< Q_SUPP_LIMIT
){
5325 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, _("Ignoring Quote-Suppression-Threshold value of %s, see help"), ps
->VAR_QUOTE_SUPPRESSION
);
5326 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
5327 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5331 if(val
< 0 && val
!= Q_DEL_ALL
)
5332 ps
->quote_suppression_threshold
= -val
;
5334 ps
->quote_suppression_threshold
= val
;
5338 else if(var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
5339 if(SVAR_MSGDLAY(ps
, ps
->status_msg_delay
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5341 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5344 else if(var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
5345 if(SVAR_ACTIVEINTERVAL(ps
, ps
->active_status_interval
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5347 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5350 busy_cue(_("Active Example"), NULL
, 0);
5352 cancel_busy_cue(-1);
5355 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
5356 else if(var
== &ps
->vars
[V_FIFOPATH
]){
5357 init_newmailfifo(ps
->VAR_FIFOPATH
);
5360 else if(var
== &ps
->vars
[V_NMW_WIDTH
]){
5361 int old_value
= ps
->nmw_width
;
5363 if(SVAR_NMW_WIDTH(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5365 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5369 if(old_value
!= ps
->nmw_width
)
5370 mswin_setnewmailwidth(old_value
); /* actually the new value */
5372 ps
->nmw_width
= old_value
;
5375 else if(var
== &ps
->vars
[V_TCPOPENTIMEO
]){
5378 if(ps
->VAR_TCPOPENTIMEO
&& SVAR_TCP_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5379 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5381 else if(var
== &ps
->vars
[V_TCPREADWARNTIMEO
]){
5384 if(ps
->VAR_TCPREADWARNTIMEO
&& SVAR_TCP_READWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5385 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5387 else if(var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
]){
5390 if(ps
->VAR_TCPWRITEWARNTIMEO
&& SVAR_TCP_WRITEWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5391 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5393 else if(var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
5396 if(ps
->VAR_TCPQUERYTIMEO
&& SVAR_TCP_QUERY(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5397 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5399 else if(var
== &ps
->vars
[V_RSHOPENTIMEO
]){
5402 if(ps
->VAR_RSHOPENTIMEO
&& SVAR_RSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5403 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5405 else if(var
== &ps
->vars
[V_SSHOPENTIMEO
]){
5408 if(ps
->VAR_SSHOPENTIMEO
&& SVAR_SSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5409 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5411 else if(var
== &ps
->vars
[V_SIGNATURE_FILE
]){
5412 if(ps
->VAR_OPER_DIR
&& ps
->VAR_SIGNATURE_FILE
&&
5413 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
5414 !in_dir(ps
->VAR_OPER_DIR
, ps
->VAR_SIGNATURE_FILE
)){
5418 l
= strlen(ps
->VAR_OPER_DIR
) + 100;
5419 e
= (char *) fs_get((l
+1) * sizeof(char));
5420 snprintf(e
, l
+1, _("Warning: Sig file can't be outside of %s"),
5423 q_status_message(SM_ORDER
, 3, 6, e
);
5424 fs_give((void **)&e
);
5427 else if(var
== &ps
->vars
[V_OPER_DIR
]){
5428 if(ps
->VAR_OPER_DIR
&& !ps
->VAR_OPER_DIR
[0]){
5429 q_status_message(SM_ORDER
, 3, 5, "Operating-dir is turned off.");
5430 fs_give((void **)&ps
->vars
[V_OPER_DIR
].current_val
.p
);
5431 if(ps
->vars
[V_OPER_DIR
].fixed_val
.p
)
5432 fs_give((void **)&ps
->vars
[V_OPER_DIR
].fixed_val
.p
);
5433 if(ps
->vars
[V_OPER_DIR
].global_val
.p
)
5434 fs_give((void **)&ps
->vars
[V_OPER_DIR
].global_val
.p
);
5435 if(ps
->vars
[V_OPER_DIR
].cmdline_val
.p
)
5436 fs_give((void **)&ps
->vars
[V_OPER_DIR
].cmdline_val
.p
);
5437 if(ps
->vars
[V_OPER_DIR
].post_user_val
.p
)
5438 fs_give((void **)&ps
->vars
[V_OPER_DIR
].post_user_val
.p
);
5439 if(ps
->vars
[V_OPER_DIR
].main_user_val
.p
)
5440 fs_give((void **)&ps
->vars
[V_OPER_DIR
].main_user_val
.p
);
5443 else if(var
== &ps
->vars
[V_MAILCHECK
]){
5445 if(SVAR_MAILCHK(ps
, timeo
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5446 set_input_timeout(15);
5448 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5451 set_input_timeout(timeo
);
5452 if(get_input_timeout() == 0 && !revert
){
5453 q_status_message(SM_ORDER
, 4, 6,
5454 _("Warning: automatic new mail checking and mailbox checkpointing is disabled"));
5455 if(ps
->VAR_INBOX_PATH
&& ps
->VAR_INBOX_PATH
[0] == '{')
5456 q_status_message(SM_ASYNC
, 3, 6,
5457 _("Warning: Mail-Check-Interval=0 may cause IMAP server connection to time out"));
5461 else if(var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
5462 val
= (int) ps
->check_interval_for_noncurr
;
5463 if(ps
->VAR_MAILCHECKNONCURR
5464 && SVAR_MAILCHKNONCURR(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5466 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5469 ps
->check_interval_for_noncurr
= (time_t) val
;
5471 else if(var
== &ps
->vars
[V_MAILDROPCHECK
]){
5475 if(ps
->VAR_MAILDROPCHECK
&& SVAR_MAILDCHK(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5476 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5479 rvl
= (60L * 60L * 24L * 100L); /* 100 days */
5482 mail_parameters(NULL
, SET_SNARFINTERVAL
, (void *) rvl
);
5485 else if(var
== &ps
->vars
[V_NNTPRANGE
]){
5489 if(ps
->VAR_NNTPRANGE
&& SVAR_NNTPRANGE(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5490 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5493 mail_parameters(NULL
, SET_NNTPRANGE
, (void *) rvl
);
5496 else if(var
== &ps
->vars
[V_CUSTOM_HDRS
] || var
== &ps
->vars
[V_COMP_HDRS
]){
5497 /* this will give warnings about headers that can't be changed */
5498 if(!revert
&& var
->current_val
.l
&& var
->current_val
.l
[0])
5499 customized_hdr_setup(NULL
, var
->current_val
.l
, UseAsDef
);
5501 #if defined(DOS) || defined(OS2)
5502 else if(var
== &ps
->vars
[V_FOLDER_EXTENSION
]){
5503 mail_parameters(NULL
, SET_EXTENSION
,
5504 (void *)var
->current_val
.p
);
5506 else if(var
== &ps
->vars
[V_NEWSRC_PATH
]){
5507 if(var
->current_val
.p
&& var
->current_val
.p
[0])
5508 mail_parameters(NULL
, SET_NEWSRC
,
5509 (void *)var
->current_val
.p
);
5512 else if(revert
&& standard_radio_var(ps
, var
)){
5514 cur_rule_value(var
, TRUE
, FALSE
);
5515 if(var
== &ps_global
->vars
[V_AB_SORT_RULE
])
5516 addrbook_redo_sorts();
5517 else if(var
== &ps_global
->vars
[V_THREAD_INDEX_STYLE
]){
5518 clear_index_cache(ps_global
->mail_stream
, 0);
5519 set_lflags(ps_global
->mail_stream
, ps_global
->msgmap
,
5520 MN_COLL
| MN_CHID
, 0);
5521 if(SORT_IS_THREADED(ps_global
->msgmap
)
5522 && (SEP_THRDINDX() || COLL_THRDS()))
5523 collapse_threads(ps_global
->mail_stream
, ps_global
->msgmap
, NULL
);
5525 adjust_cur_to_visible(ps_global
->mail_stream
, ps_global
->msgmap
);
5528 else if(var
== &ps
->vars
[V_COLOR_STYLE
]){
5529 pico_toggle_color(0);
5530 switch(ps
->color_style
){
5533 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
5536 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
5539 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
5542 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
5546 if(ps
->color_style
!= COL_NONE
)
5547 pico_toggle_color(1);
5549 if(pico_usingcolor())
5550 pico_set_normal_color();
5552 clear_index_cache(ps_global
->mail_stream
, 0);
5554 ps
->mangled_screen
= 1;
5558 else if(revert
&& var
== &ps
->vars
[V_SORT_KEY
]){
5561 decode_sort(VAR_SORT_KEY
, &ps
->def_sort
, &def_sort_rev
);
5562 ps
->def_sort_rev
= def_sort_rev
;
5564 else if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5565 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5566 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5568 if(var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
] &&
5569 !(var
->current_val
.p
&& var
->current_val
.p
[0])){
5570 if(var
->current_val
.p
)
5571 fs_give((void **) &var
->current_val
.p
);
5573 q_status_message1(SM_ORDER
, 3, 5,
5574 _("\"%s\" can't be Empty, using default"), var
->name
);
5576 apval
= APVAL(var
, ew
);
5578 fs_give((void **)apval
);
5580 set_current_val(var
, FALSE
, FALSE
);
5582 if(!(var
->current_val
.p
&& var
->current_val
.p
[0]
5583 && !var
->current_val
.p
[1])){
5584 if(var
->current_val
.p
)
5585 fs_give((void **) &var
->current_val
.p
);
5587 var
->current_val
.p
= cpystr(DF_THREAD_LASTREPLY_CHAR
);
5591 if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5592 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5593 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5594 if(var
->current_val
.p
&& var
->current_val
.p
[0] &&
5595 var
->current_val
.p
[1]){
5596 q_status_message1(SM_ORDER
, 3, 5,
5597 "Only first character of \"%s\" is used",
5599 var
->current_val
.p
[1] = '\0';
5602 if(var
->main_user_val
.p
&& var
->main_user_val
.p
[0] &&
5603 var
->main_user_val
.p
[1])
5604 var
->main_user_val
.p
[1] = '\0';
5606 if(var
->post_user_val
.p
&& var
->post_user_val
.p
[0] &&
5607 var
->post_user_val
.p
[1])
5608 var
->post_user_val
.p
[1] = '\0';
5611 clear_index_cache(ps_global
->mail_stream
, 0);
5612 set_need_format_setup(ps_global
->mail_stream
);
5614 else if(var
== &ps
->vars
[V_NNTP_SERVER
]){
5615 free_contexts(&ps_global
->context_list
);
5616 init_folders(ps_global
);
5618 else if(var
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
]){
5621 else if(var
== &ps
->vars
[V_PRINTER
]){
5622 if(!revert
&& ps
->vars
[V_PERSONAL_PRINT_COMMAND
].is_fixed
){
5623 if(printer_value_check_and_adjust())
5624 q_status_message1(SM_ORDER
, 3, 5,
5625 _("Can't set \"%s\" to that value, see Setup/Printer"),
5626 pretty_var_name(var
->name
));
5629 else if(var
== &ps
->vars
[V_KW_COLORS
] ||
5630 var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
] ||
5631 var
== &ps
->vars
[V_IND_PLUS_FORE_COLOR
] ||
5632 var
== &ps
->vars
[V_IND_IMP_FORE_COLOR
] ||
5633 var
== &ps
->vars
[V_IND_DEL_FORE_COLOR
] ||
5634 var
== &ps
->vars
[V_IND_ANS_FORE_COLOR
] ||
5635 var
== &ps
->vars
[V_IND_NEW_FORE_COLOR
] ||
5636 var
== &ps
->vars
[V_IND_UNS_FORE_COLOR
] ||
5637 var
== &ps
->vars
[V_IND_HIPRI_FORE_COLOR
]||
5638 var
== &ps
->vars
[V_IND_LOPRI_FORE_COLOR
]||
5639 var
== &ps
->vars
[V_IND_ARR_FORE_COLOR
] ||
5640 var
== &ps
->vars
[V_IND_REC_FORE_COLOR
] ||
5641 var
== &ps
->vars
[V_IND_FWD_FORE_COLOR
] ||
5642 var
== &ps
->vars
[V_IND_OP_FORE_COLOR
] ||
5643 var
== &ps
->vars
[V_IND_FROM_FORE_COLOR
] ||
5644 var
== &ps
->vars
[V_IND_SUBJ_FORE_COLOR
] ||
5645 var
== &ps
->vars
[V_IND_PLUS_BACK_COLOR
] ||
5646 var
== &ps
->vars
[V_IND_IMP_BACK_COLOR
] ||
5647 var
== &ps
->vars
[V_IND_DEL_BACK_COLOR
] ||
5648 var
== &ps
->vars
[V_IND_ANS_BACK_COLOR
] ||
5649 var
== &ps
->vars
[V_IND_NEW_BACK_COLOR
] ||
5650 var
== &ps
->vars
[V_IND_UNS_BACK_COLOR
] ||
5651 var
== &ps
->vars
[V_IND_ARR_BACK_COLOR
] ||
5652 var
== &ps
->vars
[V_IND_REC_BACK_COLOR
] ||
5653 var
== &ps
->vars
[V_IND_FWD_BACK_COLOR
] ||
5654 var
== &ps
->vars
[V_IND_OP_BACK_COLOR
] ||
5655 var
== &ps
->vars
[V_IND_FROM_BACK_COLOR
] ||
5656 var
== &ps
->vars
[V_IND_SUBJ_BACK_COLOR
]){
5657 clear_index_cache(ps_global
->mail_stream
, 0);
5659 else if(var
== score_act_global_ptr
){
5662 score
= atoi(var
->current_val
.p
);
5663 if(score
< SCORE_MIN
|| score
> SCORE_MAX
){
5664 q_status_message2(SM_ORDER
, 3, 5,
5665 _("Score Value must be in range %s to %s"),
5666 comatose(SCORE_MIN
), comatose(SCORE_MAX
));
5667 apval
= APVAL(var
, ew
);
5669 fs_give((void **)apval
);
5671 set_current_val(var
, FALSE
, FALSE
);
5674 else if(var
== scorei_pat_global_ptr
|| var
== age_pat_global_ptr
5675 || var
== size_pat_global_ptr
|| var
== cati_global_ptr
){
5676 apval
= APVAL(var
, ew
);
5679 iv
= parse_intvl(*apval
);
5681 fs_give((void **) apval
);
5682 *apval
= stringform_of_intvl(iv
);
5686 fs_give((void **) apval
);
5689 set_current_val(var
, FALSE
, FALSE
);
5691 else if(var
== &ps
->vars
[V_FEATURE_LIST
]){
5692 process_feature_list(ps
, var
->current_val
.l
, 0, 0, 0);
5694 else if(!revert
&& (var
== &ps
->vars
[V_LAST_TIME_PRUNE_QUESTION
] ||
5695 var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
] ||
5696 var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
] ||
5697 var
== &ps
->vars
[V_USERINPUTTIMEO
] ||
5698 var
== &ps
->vars
[V_NEWS_ACTIVE_PATH
] ||
5699 var
== &ps
->vars
[V_NEWS_SPOOL_DIR
] ||
5700 var
== &ps
->vars
[V_INCOMING_FOLDERS
] ||
5701 var
== &ps
->vars
[V_FOLDER_SPEC
] ||
5702 var
== &ps
->vars
[V_NEWS_SPEC
] ||
5703 var
== &ps
->vars
[V_DISABLE_DRIVERS
] ||
5704 var
== &ps
->vars
[V_DISABLE_AUTHS
] ||
5705 var
== &ps
->vars
[V_RSHPATH
] ||
5706 var
== &ps
->vars
[V_RSHCMD
] ||
5707 var
== &ps
->vars
[V_SSHCMD
] ||
5708 var
== &ps
->vars
[V_SSHPATH
])){
5709 q_status_message2(SM_ASYNC
, 0, 3,
5710 _("Changes%s%s will affect your next Alpine session."),
5711 var
->name
? " to " : "", var
->name
? var
->name
: "");
5714 if(!revert
&& (var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
5715 var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
5716 var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
5717 var
== &ps
->vars
[V_TCPQUERYTIMEO
] ||
5718 var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
5719 var
== &ps
->vars
[V_SSHOPENTIMEO
]))
5720 q_status_message(SM_ASYNC
, 0, 3,
5721 _("Timeout changes will affect your next Alpine session."));
5726 * Compare saved user_val with current user_val to see if it changed.
5727 * If any have changed, change it back and take the appropriate action.
5730 revert_to_saved_config(struct pine
*ps
, SAVED_CONFIG_S
*vsave
, int allow_hard_to_config_remotely
)
5732 struct variable
*vreal
;
5736 char *pval
, **apval
, **lval
, ***alval
;
5739 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5740 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5745 lval
= LVAL(vreal
, ew
);
5746 alval
= ALVAL(vreal
, ew
);
5748 if((v
->saved_user_val
.l
&& !lval
)
5749 || (!v
->saved_user_val
.l
&& lval
))
5751 else if(!v
->saved_user_val
.l
&& !lval
)
5752 ;/* no change, nothing to do */
5754 for(i
= 0; v
->saved_user_val
.l
[i
] || lval
[i
]; i
++)
5755 if((v
->saved_user_val
.l
[i
]
5757 || strcmp(v
->saved_user_val
.l
[i
], lval
[i
])))
5759 (!v
->saved_user_val
.l
[i
] && lval
[i
])){
5769 free_list_array(alval
);
5771 /* copy back the original one */
5772 if(v
->saved_user_val
.l
){
5773 list
= v
->saved_user_val
.l
;
5775 /* count how many */
5779 *alval
= (char **)fs_get((n
+1) * sizeof(char *));
5781 for(i
= 0; i
< n
; i
++)
5782 (*alval
)[i
] = cpystr(v
->saved_user_val
.l
[i
]);
5790 pval
= PVAL(vreal
, ew
);
5791 apval
= APVAL(vreal
, ew
);
5793 if((v
->saved_user_val
.p
&&
5794 (!pval
|| strcmp(v
->saved_user_val
.p
, pval
))) ||
5795 (!v
->saved_user_val
.p
&& pval
)){
5796 /* It changed, fix it */
5799 /* free the changed value */
5801 fs_give((void **)apval
);
5803 if(v
->saved_user_val
.p
)
5804 *apval
= cpystr(v
->saved_user_val
.p
);
5810 if(vreal
== &ps
->vars
[V_FEATURE_LIST
])
5811 set_feature_list_current_val(vreal
);
5813 set_current_val(vreal
, TRUE
, FALSE
);
5815 fix_side_effects(ps
, vreal
, 1);
5822 save_config_vars(struct pine
*ps
, int allow_hard_to_config_remotely
)
5824 struct variable
*vreal
;
5825 SAVED_CONFIG_S
*vsave
, *v
;
5827 vsave
= (SAVED_CONFIG_S
*)fs_get((V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5828 memset((void *)vsave
, 0, (V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5830 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5831 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5838 if(LVAL(vreal
, ew
)){
5839 /* count how many */
5841 list
= LVAL(vreal
, ew
);
5845 v
->saved_user_val
.l
= (char **)fs_get((n
+1) * sizeof(char *));
5846 memset((void *)v
->saved_user_val
.l
, 0, (n
+1)*sizeof(char *));
5847 for(i
= 0; i
< n
; i
++)
5848 v
->saved_user_val
.l
[i
] = cpystr(list
[i
]);
5850 v
->saved_user_val
.l
[n
] = NULL
;
5855 v
->saved_user_val
.p
= cpystr(PVAL(vreal
, ew
));
5864 free_saved_config(struct pine
*ps
, SAVED_CONFIG_S
**vsavep
, int allow_hard_to_config_remotely
)
5866 struct variable
*vreal
;
5869 if(vsavep
&& *vsavep
){
5870 for(v
= *vsavep
, vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5871 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5874 if(vreal
->is_list
){ /* free saved_user_val.l */
5875 if(v
&& v
->saved_user_val
.l
)
5876 free_list_array(&v
->saved_user_val
.l
);
5878 else if(v
&& v
->saved_user_val
.p
)
5879 fs_give((void **)&v
->saved_user_val
.p
);
5882 fs_give((void **)vsavep
);
5888 * Returns positive if any thing was actually deleted.
5891 delete_user_vals(struct variable
*v
)
5897 if(v
->post_user_val
.l
){
5899 free_list_array(&v
->post_user_val
.l
);
5901 if(v
->main_user_val
.l
){
5903 free_list_array(&v
->main_user_val
.l
);
5907 if(v
->post_user_val
.p
){
5909 fs_give((void **)&v
->post_user_val
.p
);
5911 if(v
->main_user_val
.p
){
5913 fs_give((void **)&v
->main_user_val
.p
);
5923 * ../pith/conf.c required function
5926 unexpected_pinerc_change(void)
5929 if(want_to("Unexpected pinerc change! Overwrite with current config",
5930 'n', 0, NO_HELP
, WT_FLUSH_IN
) == 'n'){
5931 return(-1); /* abort pinerc write */
5934 return(0); /* overwrite */
5940 /*----------------------------------------------------------------------
5941 MSWin scroll callback. Called during scroll message processing.
5945 Args: cmd - what type of scroll operation.
5946 scroll_pos - paramter for operation.
5947 used as position for SCROLL_TO operation.
5949 Returns: TRUE - did the scroll operation.
5950 FALSE - was not able to do the scroll operation.
5953 config_scroll_callback (cmd
, scroll_pos
)
5958 case MSWIN_KEY_SCROLLUPLINE
:
5959 config_scroll_down (scroll_pos
);
5962 case MSWIN_KEY_SCROLLDOWNLINE
:
5963 config_scroll_up (scroll_pos
);
5966 case MSWIN_KEY_SCROLLUPPAGE
:
5967 config_scroll_down (BODY_LINES(ps_global
));
5970 case MSWIN_KEY_SCROLLDOWNPAGE
:
5971 config_scroll_up (BODY_LINES(ps_global
));
5974 case MSWIN_KEY_SCROLLTO
:
5975 config_scroll_to_pos (scroll_pos
);
5979 option_screen_redrawer();
5985 #endif /* _WINDOWS */