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-2015 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)
3045 opt_screen
= screen
;
3048 cursor_pos
->col
= 0;
3049 cursor_pos
->row
= -1; /* to tell us if we've set it yet */
3053 * calculate top line of display for reframing if the current field
3054 * is off the display defined by screen->top_line...
3056 if((ctmp
= screen
->top_line
) != NULL
)
3057 for(dline
= BODY_LINES(ps
);
3058 dline
&& ctmp
&& ctmp
!= screen
->current
;
3059 ctmp
= next_confline(ctmp
), dline
--)
3062 if(!ctmp
|| !dline
){ /* force reframing */
3064 ctmp
= top_line
= first_confline(screen
->current
);
3066 if(((dline
++)%BODY_LINES(ps
)) == 0)
3068 while(ctmp
!= screen
->current
&& (ctmp
= next_confline(ctmp
)));
3071 top_line
= screen
->top_line
;
3075 * Figure out how far down the top line is from the top and how many
3076 * total lines there are. Dumb to loop every time thru, but
3077 * there aren't that many lines, and it's cheaper than rewriting things
3078 * to maintain a line count in each structure...
3080 for(dline
= 0, ctmp
= prev_confline(top_line
); ctmp
; ctmp
= prev_confline(ctmp
))
3083 scroll_setpos(dline
);
3084 last_selectable
= dline
;
3085 for(ctmp
= next_confline(top_line
); ctmp
; ctmp
= next_confline(ctmp
)){
3087 if (!(ctmp
->flags
& CF_NOSELECT
))
3088 last_selectable
= dline
;
3090 dline
= last_selectable
;
3091 scroll_setrange(BODY_LINES(ps
), dline
);
3094 /* mangled body or new page, force redraw */
3095 if(ps
->mangled_body
|| screen
->top_line
!= top_line
)
3096 screen
->prev
= NULL
;
3098 /* loop thru painting what's needed */
3099 for(dline
= 0, ctmp
= top_line
;
3100 dline
< BODY_LINES(ps
);
3101 dline
++, ctmp
= next_confline(ctmp
)){
3104 * only fall thru painting if something needs painting...
3106 if(!(!screen
->prev
|| ctmp
== screen
->prev
|| ctmp
== screen
->current
3107 || ctmp
== screen
->prev
->varnamep
3108 || ctmp
== screen
->current
->varnamep
3109 || ctmp
== screen
->prev
->headingp
3110 || ctmp
== screen
->current
->headingp
))
3113 ClearLine(dline
+ HEADER_ROWS(ps
));
3116 if(ctmp
->flags
& CF_B_LINE
)
3119 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3120 if(ctmp
== screen
->current
&& cursor_pos
)
3121 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3123 if((ctmp
== screen
->current
3124 || ctmp
== screen
->current
->varnamep
3125 || ctmp
== screen
->current
->headingp
)
3126 && !(ctmp
->flags
& CF_NOHILITE
))
3129 if(ctmp
->flags
& CF_H_LINE
){
3130 MoveCursor(dline
+ HEADER_ROWS(ps
), 0);
3131 Write_to_screen(repeat_char(ps
->ttyo
->screen_cols
, '-'));
3134 if(ctmp
->flags
& CF_CENTERED
){
3135 int offset
= ps
->ttyo
->screen_cols
/2
3136 - (utf8_width(ctmp
->varname
)/2);
3137 MoveCursor(dline
+ HEADER_ROWS(ps
),
3138 (offset
> 0) ? offset
: 0);
3140 else if(ctmp
->varoffset
)
3141 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->varoffset
);
3143 Write_to_screen(ctmp
->varname
);
3144 if((ctmp
== screen
->current
3145 || ctmp
== screen
->current
->varnamep
3146 || ctmp
== screen
->current
->headingp
)
3147 && !(ctmp
->flags
& CF_NOHILITE
))
3151 value
= (ctmp
->flags
& CF_INHERIT
) ? INHERIT
: ctmp
->value
;
3157 memset(tmp_20k_buf
, '\0',
3158 (6*ps
->ttyo
->screen_cols
+ 1) * sizeof(char));
3159 if(ctmp
== screen
->current
){
3160 if(!(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
))
3164 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3167 if(ctmp
->flags
& CF_H_LINE
)
3168 memset(tmp_20k_buf
, '-',
3169 ps
->ttyo
->screen_cols
* sizeof(char));
3171 if(ctmp
->flags
& CF_CENTERED
){
3172 int offset
= ps
->ttyo
->screen_cols
/2
3173 - (utf8_width(value
)/2);
3174 /* BUG: tabs screw us figuring length above */
3178 p
= tmp_20k_buf
+ offset
;
3179 if(!*(q
= tmp_20k_buf
))
3188 * Copy the value to a temp buffer expanding tabs, and
3189 * making sure not to write beyond screen right...
3191 for(i
= 0, j
= ctmp
->valoffset
; value
[i
]; i
++){
3192 if(value
[i
] == ctrl('I')){
3195 while((++j
) & 0x07);
3203 if(ctmp
== screen
->current
&& cursor_pos
){
3204 if(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
)
3205 cursor_pos
->col
= ctmp
->val2offset
;
3207 cursor_pos
->col
= ctmp
->valoffset
;
3209 if(ctmp
->tool
== radiobutton_tool
3211 || ctmp
->tool
==ldap_radiobutton_tool
3213 || ctmp
->tool
==role_radiobutton_tool
3214 || ctmp
->tool
==checkbox_tool
3215 || (ctmp
->tool
==color_setting_tool
&&
3216 ctmp
->valoffset
!= COLOR_INDENT
))
3220 if(ctmp
->flags
& CF_DOUBLEVAR
){
3224 first_width
= ctmp
->val2offset
- ctmp
->valoffset
- SPACE_BETWEEN_DOUBLEVARS
;
3225 if((l
=utf8_width(p
)) > first_width
&& first_width
>= 0){
3226 saveptr
= utf8_count_forw_width(p
, first_width
, &got_width
);
3228 * got_width != first_width indicates there's a problem
3229 * that should not happen. Ignore it.
3240 * If this is a COLOR_BLOB line we do special coloring.
3241 * The current object inverse hilite is only on the
3242 * checkbox part, the exact format comes from the
3243 * new_color_line function. If we change that we'll have
3244 * to change this to get the coloring right.
3246 if(p
[0] == '(' && p
[2] == ')' &&
3247 p
[3] == ' ' && p
[4] == ' ' &&
3248 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3249 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3250 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3251 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3253 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
);
3254 Write_to_screen_n(p
, 3);
3255 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3258 Write_to_screen_n(p
+3, 3);
3259 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3260 colorx(CFC_ICOLOR(ctmp
)));
3262 lastc
= pico_get_cur_color();
3263 (void)pico_set_colorp(newc
, PSC_NONE
);
3264 free_color_pair(&newc
);
3267 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3270 (void)pico_set_colorp(lastc
, PSC_NONE
);
3271 free_color_pair(&lastc
);
3274 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3277 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, p
);
3278 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3285 PutLine0(dline
+HEADER_ROWS(ps
),
3286 ctmp
->val2offset
- SPACE_BETWEEN_DOUBLEVARS
,
3287 repeat_char(SPACE_BETWEEN_DOUBLEVARS
, SPACE
));
3289 if(l
> ctmp
->val2offset
- ctmp
->valoffset
&& ctmp
->val2offset
- ctmp
->valoffset
>= 0)
3290 p
= saveptr
+ SPACE_BETWEEN_DOUBLEVARS
;
3292 if(p
> tmp_20k_buf
){
3293 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3296 if(p
[0] == '(' && p
[2] == ')' &&
3297 p
[3] == ' ' && p
[4] == ' ' &&
3298 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3299 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3300 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3301 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3303 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->val2offset
);
3304 Write_to_screen_n(p
, 3);
3305 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3308 Write_to_screen_n(p
+3, 3);
3309 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3310 colorx(CFC_ICOLOR(ctmp
)));
3312 lastc
= pico_get_cur_color();
3313 (void)pico_set_colorp(newc
, PSC_NONE
);
3314 free_color_pair(&newc
);
3317 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3320 (void)pico_set_colorp(lastc
, PSC_NONE
);
3321 free_color_pair(&lastc
);
3324 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3327 PutLine0(dline
+HEADER_ROWS(ps
),ctmp
->val2offset
,p
);
3328 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3334 char *q
, *first_space
, *sample
, *ptr
;
3335 COLOR_PAIR
*lastc
, *newc
;
3339 if(ctmp
->flags
& CF_COLORSAMPLE
&&
3340 pico_usingcolor() &&
3341 ((q
= strstr(tmp_20k_buf
, SAMPLE_LEADER
)) ||
3342 (q
= strstr(tmp_20k_buf
, "Color"))) &&
3343 (first_space
= strindex(q
, SPACE
)) &&
3344 (strstr(value
, SAMP1
) ||
3345 strstr(value
, SAMP2
))){
3349 /* write out first part */
3350 *first_space
= '\0';
3351 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
,
3353 *first_space
= SPACE
;
3356 if(ctmp
== screen
->current
)
3359 sample
= skip_white_space(ptr
);
3360 /* if there's enough room to put some sample up */
3363 w
= utf8_width(tmp_20k_buf
);
3365 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3367 sample
++; /* for `[' at edge of sample */
3371 w
= utf8_width(tmp_20k_buf
);
3376 /* spaces and bracket before sample1 */
3377 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+w
, ptr
);
3382 /* then the color sample */
3383 if(ctmp
->var
== &ps
->vars
[V_VIEW_HDR_COLORS
]
3384 || ctmp
->var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
]){
3385 SPEC_COLOR_S
*hc
, *hcolors
;
3387 lastc
= newc
= NULL
;
3390 spec_colors_from_varlist(LVAL(ctmp
->var
, ew
),
3392 for(hc
= hcolors
, i
=0; hc
; hc
= hc
->next
, i
++)
3393 if(CFC_ICUST(ctmp
) == i
)
3396 if(hc
&& hc
->fg
&& hc
->fg
[0] && hc
->bg
&&
3398 newc
= new_color_pair(hc
->fg
, hc
->bg
);
3401 lastc
= pico_get_cur_color();
3402 (void)pico_set_colorp(newc
, PSC_NONE
);
3403 free_color_pair(&newc
);
3407 free_spec_colors(&hcolors
);
3410 /* print out sample1 */
3414 w
= utf8_width(tmp_20k_buf
);
3417 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3418 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3424 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3428 ptr
= strindex(ptr
, ']');
3431 (void)pico_set_colorp(lastc
, PSC_NONE
);
3432 free_color_pair(&lastc
);
3435 else if(ctmp
->var
== &ps
->vars
[V_KW_COLORS
]){
3437 SPEC_COLOR_S
*kw_col
= NULL
;
3439 lastc
= newc
= NULL
;
3441 /* find keyword associated with this line */
3442 for(kw
=ps
->keywords
, i
=0; kw
; kw
=kw
->next
, i
++)
3443 if(CFC_ICUST(ctmp
) == i
)
3448 spec_colors_from_varlist(LVAL(ctmp
->var
,ew
),
3451 /* color for this keyword */
3453 && ((kw
->nick
&& kw
->nick
[0]
3454 && (newc
=hdr_color(kw
->nick
, NULL
,
3457 (kw
->kw
&& kw
->kw
[0]
3458 && (newc
=hdr_color(kw
->kw
, NULL
,
3460 lastc
= pico_get_cur_color();
3461 (void)pico_set_colorp(newc
, PSC_NONE
);
3462 free_color_pair(&newc
);
3466 free_spec_colors(&kw_col
);
3468 /* print out sample1 */
3472 w
= utf8_width(tmp_20k_buf
);
3475 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3476 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3482 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3486 ptr
= strindex(ptr
, ']');
3489 (void)pico_set_colorp(lastc
, PSC_NONE
);
3490 free_color_pair(&lastc
);
3496 newc
= sample_color(ps
, ctmp
->var
);
3498 if((lastc
= pico_get_cur_color()) != NULL
)
3499 (void)pico_set_colorp(newc
, PSC_NONE
);
3501 free_color_pair(&newc
);
3503 else if(var_defaults_to_rev(ctmp
->var
)){
3504 if((newc
= pico_get_rev_color()) != NULL
){
3506 * Note, don't have to free newc.
3508 if((lastc
= pico_get_cur_color()) != NULL
)
3509 (void)pico_set_colorp(newc
, PSC_NONE
);
3517 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3519 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3520 !(PVAL(ctmp
->var
,ew
) &&
3521 PVAL(ctmp
->var
+1,ew
))))
3524 /* print out sample1 */
3528 w
= utf8_width(tmp_20k_buf
);
3531 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3532 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3538 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3542 ptr
= strindex(ptr
, ']');
3544 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3546 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3547 !(PVAL(ctmp
->var
,ew
) &&
3548 PVAL(ctmp
->var
+1,ew
))))
3552 (void)pico_set_colorp(lastc
, PSC_NONE
);
3553 free_color_pair(&lastc
);
3560 * Finish sample1 with the right bracket.
3564 w
= utf8_width(tmp_20k_buf
);
3566 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3569 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3576 * Now check for an exception sample and paint it.
3578 if(ctmp
->valoffset
+ w
+ SBS
+ 1 < ps
->ttyo
->screen_cols
&& (q
= strstr(ptr
, SAMPEXC
))){
3582 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3587 * Figure out what color to paint it.
3588 * This only happens with normal variables,
3589 * not with V_VIEW_HDR_COLORS.
3593 newc
= sampleexc_color(ps
, ctmp
->var
);
3595 if((lastc
= pico_get_cur_color()) != NULL
)
3596 (void)pico_set_colorp(newc
, PSC_NONE
);
3598 free_color_pair(&newc
);
3600 else if(var_defaults_to_rev(ctmp
->var
)){
3601 if((newc
= pico_get_rev_color()) != NULL
){
3603 * Note, don't have to free newc.
3605 if((lastc
= pico_get_cur_color()) != NULL
)
3606 (void)pico_set_colorp(newc
, PSC_NONE
);
3614 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3616 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3617 !(PVAL(ctmp
->var
,Post
) &&
3618 PVAL(ctmp
->var
+1,Post
))))
3624 w
= utf8_width(tmp_20k_buf
);
3627 want_width
= MIN(utf8_width(SAMPEXC
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3628 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3634 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3638 ptr
= strindex(ptr
, ']');
3640 /* turn off bold and color */
3641 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3643 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3644 !(PVAL(ctmp
->var
,Post
) &&
3645 PVAL(ctmp
->var
+1,Post
))))
3649 (void)pico_set_colorp(lastc
, PSC_NONE
);
3650 free_color_pair(&lastc
);
3656 * Finish sample2 with the right bracket.
3660 w
= utf8_width(tmp_20k_buf
);
3662 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3665 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3672 /* paint rest of the line if there is any left */
3673 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
&& *ptr
){
3674 want_width
= ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
;
3675 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3681 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3688 w
= utf8_width(tmp_20k_buf
);
3689 want_width
= ps
->ttyo
->screen_cols
- ctmp
->valoffset
;
3691 saveptr
= utf8_count_forw_width(tmp_20k_buf
, want_width
, &got_width
);
3696 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, tmp_20k_buf
);
3697 if(ctmp
== screen
->current
)
3705 ps
->mangled_body
= 0;
3706 screen
->top_line
= top_line
;
3707 screen
->prev
= screen
->current
;
3719 print_option_screen(OPT_SCREEN_S
*screen
, char *prompt
)
3725 if(open_printer(prompt
) == 0){
3726 for(ctmp
= first_confline(screen
->current
);
3728 ctmp
= next_confline(ctmp
)){
3731 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3733 snprintf(line
, sizeof(line
), "%*s%s", ctmp
->varoffset
, "",
3735 line
[sizeof(line
)-1] = '\0';
3737 so_far
= ctmp
->varoffset
+ utf8_width(ctmp
->varname
);
3740 if(ctmp
&& ctmp
->value
){
3741 char *p
= tmp_20k_buf
;
3744 /* Copy the value to a temp buffer expanding tabs. */
3745 for(i
= 0, j
= ctmp
->valoffset
; ctmp
->value
[i
]; i
++){
3746 if(ctmp
->value
[i
] == ctrl('I')){
3749 while((++j
) & 0x07);
3753 *p
++ = ctmp
->value
[i
];
3759 removing_trailing_white_space(tmp_20k_buf
);
3761 spaces
= MAX(ctmp
->valoffset
- so_far
, 0);
3762 snprintf(line
, sizeof(line
), "%*s%s\n", spaces
, "", tmp_20k_buf
);
3763 line
[sizeof(line
)-1] = '\0';
3778 option_screen_redrawer(void)
3780 ps_global
->mangled_body
= 1;
3781 update_option_screen(ps_global
, opt_screen
, (Pos
*)NULL
);
3787 * pretty_value - given the line, return an
3788 * alloc'd string for line's value...
3791 pretty_value(struct pine
*ps
, CONF_S
*cl
)
3797 if(v
== &ps
->vars
[V_FEATURE_LIST
])
3798 return(checkbox_pretty_value(ps
, cl
));
3799 else if(standard_radio_var(ps
, v
) || v
== startup_ptr
)
3800 return(radio_pretty_value(ps
, cl
));
3801 else if(v
== &ps
->vars
[V_SORT_KEY
])
3802 return(sort_pretty_value(ps
, cl
));
3803 else if(v
== &ps
->vars
[V_SIGNATURE_FILE
])
3804 return(sigfile_pretty_value(ps
, cl
));
3805 else if(v
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
])
3806 return(yesno_pretty_value(ps
, cl
));
3807 else if(color_holding_var(ps
, v
))
3808 return(color_pretty_value(ps
, cl
));
3810 return(text_pretty_value(ps
, cl
));
3815 text_pretty_value(struct pine
*ps
, CONF_S
*cl
)
3817 char tmp
[6*MAX_SCREEN_COLS
+20], *pvalnorm
, **lvalnorm
, *pvalexc
, **lvalexc
;
3818 char *p
, *pval
, **lval
, lastchar
= '\0';
3819 int editing_except
, fixed
, uvalset
, uvalposlen
;
3821 int comments
, except_set
, avail_width
;
3822 int norm_with_except
= 0, norm_with_except_inherit
= 0;
3823 int inherit_line
= 0;
3825 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
3826 fixed
= cl
->var
->is_fixed
;
3827 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
))
3828 norm_with_except
++; /* editing normal and except config exists */
3830 if(cl
->var
->is_list
){
3831 lvalnorm
= LVAL(cl
->var
, Main
);
3832 lvalexc
= LVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3834 uvalset
= lvalexc
!= NULL
;
3835 uvalposlen
= uvalset
&& lvalexc
[0] && lvalexc
[0][0];
3839 uvalset
= lvalnorm
!= NULL
;
3840 uvalposlen
= uvalset
&& lvalnorm
[0] && lvalnorm
[0][0];
3844 except_set
= lvalexc
!= NULL
;
3845 comments
= cl
->var
->current_val
.l
!= NULL
;
3846 if(norm_with_except
&& except_set
&& lvalexc
[0] &&
3847 !strcmp(lvalexc
[0],INHERIT
))
3848 norm_with_except_inherit
++;
3850 if(uvalset
&& !strcmp(lval
[0], INHERIT
)){
3851 if(cl
->varmem
== 0){
3857 /* only add extra comments on last member of list */
3858 if(uvalset
&& !inherit_line
&& lval
&& lval
[cl
->varmem
] &&
3859 lval
[cl
->varmem
+ 1])
3863 pvalnorm
= PVAL(cl
->var
, Main
);
3864 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3866 uvalset
= pvalexc
!= NULL
;
3867 uvalposlen
= uvalset
&& *pvalexc
;
3871 uvalset
= pvalnorm
!= NULL
;
3872 uvalposlen
= uvalset
&& *pvalnorm
;
3876 except_set
= pvalexc
!= NULL
;
3877 comments
= cl
->var
->current_val
.p
!= NULL
;
3880 memset(tmp
, 0, sizeof(tmp
));
3884 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
3886 if(fixed
|| !uvalset
|| !uvalposlen
){
3887 p
+= utf8_to_width(p
, "<", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3888 avail_width
-= got_width
;
3892 p
+= utf8_to_width(p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3893 avail_width
-= got_width
;
3896 p
+= utf8_to_width(p
, _(no_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3897 avail_width
-= got_width
;
3899 else if(!uvalposlen
){
3900 p
+= utf8_to_width(p
, _(empty_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3901 avail_width
-= got_width
;
3903 else if(inherit_line
){
3904 p
+= utf8_to_width(p
, INHERIT
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3905 avail_width
-= got_width
;
3908 if(cl
->var
->is_list
){
3909 p
+= utf8_to_width(p
, lval
[cl
->varmem
], sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3910 avail_width
-= got_width
;
3913 p
+= utf8_to_width(p
, pval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3914 avail_width
-= got_width
;
3918 if(comments
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
3919 if(fixed
|| !uvalset
){
3920 p
+= utf8_to_width(p
, ": using ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3921 avail_width
-= got_width
;
3924 if(norm_with_except
&& except_set
){
3926 p
+= utf8_to_width(p
, "exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3927 avail_width
-= got_width
;
3931 p
+= utf8_to_width(p
, ": ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3932 avail_width
-= got_width
;
3935 p
+= utf8_to_width(p
, " (", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3936 avail_width
-= got_width
;
3939 if(norm_with_except_inherit
){
3940 p
+= utf8_to_width(p
, "added to by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3941 avail_width
-= got_width
;
3944 p
+= utf8_to_width(p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3945 avail_width
-= got_width
;
3950 if(avail_width
>= 7){
3951 if(cl
->var
== &ps_global
->vars
[V_POST_CHAR_SET
]){
3952 p
+= utf8_to_width(p
, "most specific (see help)", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3953 avail_width
-= got_width
;
3956 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
3958 if(cl
->var
->is_list
){
3961 the_list
= cl
->var
->current_val
.l
;
3963 if(norm_with_except
&& except_set
)
3966 if(the_list
&& the_list
[0] && !strcmp(the_list
[0], INHERIT
))
3969 for(lval
= the_list
; avail_width
-(p
-tmp
) > 0 && *lval
; lval
++){
3970 if(lval
!= the_list
){
3971 p
+= utf8_to_width(p
, ",", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3972 avail_width
-= got_width
;
3975 p
+= utf8_to_width(p
, *lval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3976 avail_width
-= got_width
;
3980 p
+= utf8_to_width(p
, cl
->var
->current_val
.p
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3981 avail_width
-= got_width
;
3984 if(p
-tmp
+2 < sizeof(tmp
)){
3990 else if(*(p
-1) == SPACE
)
3994 tmp
[sizeof(tmp
)-1] = '\0';
3996 if(fixed
|| !uvalset
|| !uvalposlen
)
3998 else if(comments
&& norm_with_except
&& except_set
)
4002 if(p
-tmp
+2 < sizeof(tmp
)){
4008 tmp
[sizeof(tmp
)-1] = '\0';
4009 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
4011 if(utf8_width(tmp
) < avail_width
)
4012 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
), "%*s", avail_width
-utf8_width(tmp
), "");
4014 tmp
[sizeof(tmp
)-1] = '\0';
4016 return(cpystr(tmp
));
4021 checkbox_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4023 char tmp
[6*MAXPATH
];
4024 char *comment
= NULL
;
4025 int indent
, x
, screen_width
, need
;
4026 int longest_featname
, longest_comment
;
4027 int nwidcomm
; /* name width with comment */
4028 int nwidnocomm
; /* and without comment */
4031 screen_width
= (ps
&& ps
->ttyo
) ? ps
->ttyo
->screen_cols
: 80;
4034 longest_featname
= longest_feature_name();
4035 longest_comment
= longest_feature_comment(ps
, ew
);
4036 indent
= feature_indent();
4038 nwidcomm
= longest_featname
;
4039 nwidnocomm
= longest_featname
+ 2 + longest_comment
;
4041 if((need
= (indent
+ 5 + longest_featname
+ 2 + longest_comment
) - screen_width
) > 0){
4047 longest_comment
= 0;
4048 nwidnocomm
= longest_featname
;
4052 feature
= feature_list(cl
->varmem
);
4054 x
= feature_gets_an_x(ps
, cl
->var
, feature
, &comment
, ew
);
4056 if(longest_comment
&& comment
&& *comment
){
4057 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w %-*.*w", x
? 'X' : ' ',
4059 pretty_feature_name(feature
->name
, nwidcomm
),
4060 longest_comment
, longest_comment
, comment
? comment
: "");
4063 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w", x
? 'X' : ' ',
4064 nwidnocomm
, nwidnocomm
,
4065 pretty_feature_name(feature
->name
, nwidnocomm
));
4068 return(cpystr(tmp
));
4073 longest_feature_name(void)
4080 for(lv
= 0, i
= 0; (feature
= feature_list(i
)); i
++)
4081 if(feature_list_section(feature
)
4082 && lv
< (j
= utf8_width(pretty_feature_name(feature
->name
, -1))))
4093 feature_indent(void)
4100 yesno_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4102 char tmp
[6*MAXPATH
], *pvalnorm
, *pvalexc
;
4103 char *p
, *pval
, lastchar
= '\0';
4104 int editing_except
, fixed
, norm_with_except
, uvalset
;
4105 int curval
, except_set
;
4107 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
4108 fixed
= cl
->var
->is_fixed
;
4109 if((ps_global
->ew_for_except_vars
== Main
) ||
4110 (ew
== ps_global
->ew_for_except_vars
))
4111 norm_with_except
= 0;
4113 norm_with_except
= 1; /* editing normal and except config exists */
4115 pvalnorm
= PVAL(cl
->var
, Main
);
4116 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
4118 uvalset
= (pvalexc
!= NULL
&&
4119 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4123 uvalset
= (pvalnorm
!= NULL
&&
4124 (!strucmp(pvalnorm
,yesstr
) || !strucmp(pvalnorm
,nostr
)));
4128 except_set
= (pvalexc
!= NULL
&&
4129 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4130 curval
= (cl
->var
->current_val
.p
!= NULL
&&
4131 (!strucmp(cl
->var
->current_val
.p
,yesstr
) ||
4132 !strucmp(cl
->var
->current_val
.p
,nostr
)));
4137 if(fixed
|| !uvalset
)
4138 sstrncpy(&p
, "<", sizeof(tmp
)-(p
-tmp
));
4141 sstrncpy(&p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
));
4143 sstrncpy(&p
, _(no_val
), sizeof(tmp
)-(p
-tmp
));
4144 else if(!strucmp(pval
, yesstr
))
4145 sstrncpy(&p
, yesstr
, sizeof(tmp
)-(p
-tmp
));
4147 sstrncpy(&p
, nostr
, sizeof(tmp
)-(p
-tmp
));
4149 if(curval
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
4150 if(fixed
|| !uvalset
)
4151 sstrncpy(&p
, ": using ", sizeof(tmp
)-(p
-tmp
));
4153 if(norm_with_except
&& except_set
){
4155 sstrncpy(&p
, "exception ", sizeof(tmp
)-(p
-tmp
));
4157 sstrncpy(&p
, " (", sizeof(tmp
)-(p
-tmp
));
4158 sstrncpy(&p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
));
4162 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4163 sstrncpy(&p
, !strucmp(cl
->var
->current_val
.p
,yesstr
) ? yesstr
: nostr
, sizeof(tmp
)-(p
-tmp
));
4164 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4167 if(fixed
|| !uvalset
)
4169 else if(curval
&& norm_with_except
&& except_set
)
4172 if(lastchar
&& sizeof(tmp
)-(p
-tmp
) > 1){
4177 tmp
[sizeof(tmp
)-1] = '\0';
4179 if(utf8_width(tmp
) < ps
->ttyo
->screen_cols
- cl
->valoffset
)
4180 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
),
4181 "%*s", ps
->ttyo
->screen_cols
- cl
->valoffset
- utf8_width(tmp
), "");
4183 tmp
[sizeof(tmp
)-1] = '\0';
4185 return(cpystr(tmp
));
4190 radio_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4192 char tmp
[6*MAXPATH
];
4193 char *pvalnorm
, *pvalexc
, *pval
;
4194 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4195 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4197 NAMEVAL_S
*rule
= NULL
, *f
;
4198 PTR_TO_RULEFUNC rulefunc
;
4204 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4206 editing_normal_which_isnt_except
= (ew
== Main
&&
4207 ew
!= ps_global
->ew_for_except_vars
);
4208 fixed
= cl
->var
->is_fixed
;
4209 pvalnorm
= PVAL(v
, Main
);
4210 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4212 rulefunc
= rulefunc_from_var(ps
, v
);
4213 rule
= rulefunc
? (*rulefunc
)(cl
->varmem
) : NULL
;
4215 /* find longest name */
4217 for(lv
= 0, i
= 0; (f
= (*rulefunc
)(i
)); i
++)
4218 if(lv
< (j
= utf8_width(f
->name
)))
4223 if(editing_except_which_isnt_normal
)
4229 is_set_for_this_level
++;
4232 pval
= v
->fixed_val
.p
;
4233 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4235 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4236 is_the_one
? R_SELD
: ' ',
4237 lv
, lv
, rule
->name
, is_the_one
? " (value is fixed)" : "");
4239 else if(is_set_for_this_level
){
4240 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4241 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4242 !strucmp(pvalexc
, S_OR_L(rule
)));
4243 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4244 is_the_one
? R_SELD
: ' ',
4246 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4247 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4249 editing_normal_which_isnt_except
&&
4251 !the_exc_one
) ? " (overridden by exceptions)" :
4256 is_the_one
= !strucmp(pvalexc
, S_OR_L(rule
));
4257 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4258 is_the_one
? R_SELD
: ' ',
4260 is_the_one
? " (value set in exceptions)" : "");
4263 pval
= v
->current_val
.p
;
4264 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4265 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4266 is_the_one
? R_SELD
: ' ',
4268 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4272 tmp
[sizeof(tmp
)-1] = '\0';
4274 return(cpystr(tmp
));
4279 sigfile_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4281 if(cl
&& cl
->var
== &ps
->vars
[V_SIGNATURE_FILE
] &&
4282 cl
->prev
&& cl
->prev
->var
== &ps
->vars
[V_LITERAL_SIG
]){
4283 if(cl
->prev
->var
->current_val
.p
){
4284 cl
->flags
|= CF_NOSELECT
; /* side effect */
4285 return(cpystr(_("<Ignored: using Literal-Signature instead>")));
4288 cl
->flags
&= ~CF_NOSELECT
;
4289 return(text_pretty_value(ps
, cl
));
4298 color_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4300 char tmp
[6*MAXPATH
];
4308 if(v
&& color_holding_var(ps
, v
) &&
4309 (p
=srchstr(v
->name
, "-foreground-color"))){
4311 is_index
= !struncmp(v
->name
, "index-", 6);
4313 q
= sampleexc_text(ps
, v
);
4314 utf8_snprintf(tmp
, sizeof(tmp
), "%c%.*s %sColor%*.50s %.20w%*s%.20w%.20w",
4315 islower((unsigned char)v
->name
[0])
4316 ? toupper((unsigned char)v
->name
[0])
4318 MIN(p
-v
->name
-1,30), v
->name
+1,
4319 is_index
? "Symbol " : "",
4320 MAX(EQ_COL
- COLOR_INDENT
-1 - MIN(p
-v
->name
-1,30)
4321 - 6 - (is_index
? 7 : 0) - 1,0), "",
4322 sample_text(ps
,v
), *q
? SBS
: 0, "", q
,
4323 color_parenthetical(v
));
4326 tmp
[sizeof(tmp
)-1] = '\0';
4328 return(cpystr(tmp
));
4333 sort_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4335 return(generalized_sort_pretty_value(ps
, cl
, 1));
4340 generalized_sort_pretty_value(struct pine
*ps
, CONF_S
*cl
, int default_ok
)
4342 char tmp
[6*MAXPATH
];
4343 char *pvalnorm
, *pvalexc
, *pval
;
4344 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4345 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4348 SortOrder line_sort
, var_sort
, exc_sort
;
4349 int line_sort_rev
, var_sort_rev
, exc_sort_rev
;
4354 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4356 editing_normal_which_isnt_except
= (ew
== Main
&&
4357 ew
!= ps_global
->ew_for_except_vars
);
4358 fixed
= cl
->var
->is_fixed
;
4359 pvalnorm
= PVAL(v
, Main
);
4360 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4362 /* find longest value's name */
4363 for(lv
= 0, i
= 0; ps
->sort_types
[i
] != EndofList
; i
++)
4364 if(lv
< (j
= utf8_width(sort_name(ps
->sort_types
[i
]))))
4369 if(editing_except_which_isnt_normal
)
4375 is_set_for_this_level
++;
4377 /* the config line we're talking about */
4378 if(cl
->varmem
>= 0){
4379 line_sort_rev
= cl
->varmem
>= (short)EndofList
;
4380 line_sort
= (SortOrder
)(cl
->varmem
- (line_sort_rev
* EndofList
));
4384 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*w",
4385 (pval
== NULL
) ? R_SELD
: ' ',
4389 pval
= v
->fixed_val
.p
;
4390 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4391 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4393 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4394 is_the_one
? R_SELD
: ' ',
4395 line_sort_rev
? "Reverse " : "",
4396 lv
, sort_name(line_sort
),
4397 line_sort_rev
? 0 : 8, "",
4398 is_the_one
? " (value is fixed)" : "");
4400 else if(is_set_for_this_level
){
4401 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4402 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4403 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4404 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4405 exc_sort_rev
== line_sort_rev
&& exc_sort
== line_sort
);
4406 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4407 is_the_one
? R_SELD
: ' ',
4408 line_sort_rev
? "Reverse " : "",
4409 lv
, sort_name(line_sort
),
4410 line_sort_rev
? 0 : 8, "",
4411 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4412 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4414 editing_normal_which_isnt_except
&&
4416 !the_exc_one
) ? " (overridden by exceptions)" :
4421 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4422 is_the_one
= (exc_sort_rev
== line_sort_rev
&&
4423 exc_sort
== line_sort
);
4424 utf8_snprintf(tmp
, sizeof(tmp
), "( ) %s%-*w%*s%s",
4425 line_sort_rev
? "Reverse " : "",
4426 lv
, sort_name(line_sort
),
4427 line_sort_rev
? 0 : 8, "",
4428 is_the_one
? " (value set in exceptions)" : "");
4431 pval
= v
->current_val
.p
;
4432 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4433 is_the_one
= ((pval
|| default_ok
) &&
4434 var_sort_rev
== line_sort_rev
&&
4435 var_sort
== line_sort
);
4436 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4437 is_the_one
? R_SELD
: ' ',
4438 line_sort_rev
? "Reverse " : "",
4439 lv
, sort_name(line_sort
),
4440 line_sort_rev
? 0 : 8, "",
4441 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4445 return(cpystr(tmp
));
4450 sample_color(struct pine
*ps
, struct variable
*v
)
4452 COLOR_PAIR
*cp
= NULL
;
4453 char *pvalefg
, *pvalebg
;
4454 char *pvalmfg
, *pvalmbg
;
4456 pvalefg
= PVAL(v
, ew
);
4457 pvalebg
= PVAL(v
+1, ew
);
4458 pvalmfg
= PVAL(v
, Main
);
4459 pvalmbg
= PVAL(v
+1, Main
);
4460 if(v
&& color_holding_var(ps
, v
) &&
4461 srchstr(v
->name
, "-foreground-color")){
4462 if(pvalefg
&& pvalefg
[0] && pvalebg
&& pvalebg
[0])
4463 cp
= new_color_pair(pvalefg
, pvalebg
);
4464 else if(ew
== Post
&& pvalmfg
&& pvalmfg
[0] && pvalmbg
&& pvalmbg
[0])
4465 cp
= new_color_pair(pvalmfg
, pvalmbg
);
4466 else if(v
->global_val
.p
&& v
->global_val
.p
[0] &&
4467 (v
+1)->global_val
.p
&& (v
+1)->global_val
.p
[0])
4468 cp
= new_color_pair(v
->global_val
.p
, (v
+1)->global_val
.p
);
4476 sampleexc_color(struct pine
*ps
, struct variable
*v
)
4478 COLOR_PAIR
*cp
= NULL
;
4479 char *pvalfg
, *pvalbg
;
4481 pvalfg
= PVAL(v
, Post
);
4482 pvalbg
= PVAL(v
+1, Post
);
4483 if(v
&& color_holding_var(ps
, v
) &&
4484 srchstr(v
->name
, "-foreground-color") &&
4485 pvalfg
&& pvalfg
[0] && pvalbg
&& pvalbg
[0])
4486 cp
= new_color_pair(pvalfg
, pvalbg
);
4493 clear_feature(char ***l
, char *f
)
4495 char **list
= l
? *l
: NULL
;
4498 for(; list
&& *list
; list
++, count
++){
4499 if(f
&& !strucmp(((!struncmp(*list
,"no-",3)) ? *list
+ 3 : *list
), f
)){
4500 fs_give((void **)list
);
4505 *list
= *(list
+ 1);
4509 * this is helpful to keep the array from growing if a feature
4510 * get's set and unset repeatedly
4513 fs_resize((void **)l
, count
* sizeof(char *));
4521 toggle_feature_bit(struct pine
*ps
, int index
, struct variable
*var
, CONF_S
*cl
, int just_flip_value
)
4527 f
= feature_list(index
);
4529 og
= test_old_growth_bits(ps
, f
->id
);
4532 * if this feature is in the fixed set, or old-growth is in the fixed
4533 * set and this feature is in the old-growth set, don't alter it...
4535 for(vp
= var
->fixed_val
.l
; vp
&& *vp
; vp
++){
4536 p
= (struncmp(*vp
, "no-", 3)) ? *vp
: *vp
+ 3;
4537 if(!strucmp(p
, f
->name
) || (og
&& !strucmp(p
, "old-growth"))){
4538 q_status_message(SM_ORDER
, 3, 3,
4539 _("Can't change value fixed by sys-admin."));
4544 on_before
= F_ON(f
->id
, ps
);
4546 toggle_feature(ps
, var
, f
, just_flip_value
, ew
);
4549 * Handle any alpine-specific features that need attention here. Features
4550 * that aren't alpine-specific should be handled in toggle_feature instead.
4552 if(on_before
!= F_ON(f
->id
, ps
))
4554 case F_CMBND_ABOOK_DISP
:
4558 case F_PRESERVE_START_STOP
:
4559 /* toggle raw mode settings to make tty driver aware of new setting */
4565 ps
->orig_use_fkeys
= F_ON(F_USE_FK
, ps
);
4566 ps
->mangled_footer
= 1;
4567 mark_keymenu_dirty();
4571 ps
->mangled_header
= 1;
4574 case F_BLANK_KEYMENU
:
4575 if(F_ON(f
->id
, ps
)){
4576 FOOTER_ROWS(ps
) = 1;
4577 ps
->mangled_body
= 1;
4580 FOOTER_ROWS(ps
) = 3;
4581 ps
->mangled_footer
= 1;
4587 case F_ENABLE_INCOMING
:
4588 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4589 "Folder List changes will take effect your next Alpine session.");
4593 case F_SHOW_CURSOR
:
4594 mswin_showcaret(F_ON(f
->id
,ps
));
4597 case F_ENABLE_TRAYICON
:
4598 mswin_trayicon(F_ON(f
->id
,ps
));
4602 #if !defined(DOS) && !defined(OS2)
4612 case F_PASS_CONTROL_CHARS
:
4613 ps
->pass_ctrl_chars
= F_ON(F_PASS_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4617 case F_USE_CERT_STORE_ONLY
:
4618 if(F_OFF(F_USE_CERT_STORE_ONLY
, ps
))
4619 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4620 "Disabling this feature should only be done for testing. Press \"?\" for help");
4624 case F_PASS_C1_CONTROL_CHARS
:
4625 ps
->pass_c1_ctrl_chars
= F_ON(F_PASS_C1_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4629 case F_ENABLE_MOUSE
:
4630 if(F_ON(f
->id
, ps
)){
4633 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4634 "Mouse tracking still off ($DISPLAY variable set?)");
4643 if(just_flip_value
){
4644 if(cl
->value
&& cl
->value
[0])
4645 cl
->value
[1] = (cl
->value
[1] == ' ') ? 'X' : ' ';
4649 * This fork is only called from the checkbox_tool, which has
4650 * varmem set to index correctly and cl->var set correctly.
4653 fs_give((void **)&cl
->value
);
4655 cl
->value
= pretty_value(ps
, cl
);
4661 * new_confline - create new CONF_S zero it out, and insert it after current.
4662 * NOTE current gets set to the new CONF_S too!
4665 new_confline(CONF_S
**current
)
4669 p
= (CONF_S
*)fs_get(sizeof(CONF_S
));
4670 memset((void *)p
, 0, sizeof(CONF_S
));
4673 p
->next
= (*current
)->next
;
4674 (*current
)->next
= p
;
4691 snip_confline(CONF_S
**p
)
4696 * Be careful. We need this line because the
4697 * q->prev->next = ...
4698 * may change q itself if &q == &q->prev->next.
4699 * Then the use of q in the next line is wrong.
4700 * That's what happens if we pass in the address of
4701 * some ->next and use *p directly instead of q.
4706 /* Yank it from the linked list */
4708 q
->prev
->next
= q
->next
;
4711 q
->next
->prev
= q
->prev
;
4713 /* Then free up it's memory */
4714 q
->prev
= q
->next
= NULL
;
4724 free_conflines(CONF_S
**p
)
4727 free_conflines(&(*p
)->next
);
4730 fs_give((void **) &(*p
)->varname
);
4733 fs_give((void **) &(*p
)->value
);
4735 fs_give((void **) p
);
4744 first_confline(CONF_S
*p
)
4754 * First selectable confline.
4757 first_sel_confline(CONF_S
*p
)
4759 for(p
= first_confline(p
); p
&& (p
->flags
&CF_NOSELECT
); p
=next_confline(p
))
4770 last_confline(CONF_S
*p
)
4783 fixed_var(struct variable
*v
, char *action
, char *name
)
4789 || ((lval
=v
->fixed_val
.l
) && lval
[0]
4790 && strcmp(INHERIT
, lval
[0]) != 0))){
4791 q_status_message2(SM_ORDER
, 3, 3,
4792 "Can't %s sys-admin defined %s.",
4793 action
? action
: "change", name
? name
: "value");
4802 exception_override_warning(struct variable
*v
)
4806 /* if exceptions config file exists and we're not editing it */
4807 if(v
&& (ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
4808 if((!v
->is_list
&& PVAL(v
, ps_global
->ew_for_except_vars
)) ||
4809 (v
->is_list
&& (lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
4810 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0))
4811 q_status_message1(SM_ORDER
, 3, 3,
4812 _("Warning: \"%s\" is overridden in your exceptions configuration"),
4819 offer_to_fix_pinerc(struct pine
*ps
)
4826 int rv
= 0, write_main
= 0, write_post
= 0;
4827 int i
, k
, j
, need
, exc
;
4828 char *clear
= ": delete it";
4831 dprint((4, "offer_to_fix_pinerc()\n"));
4833 ps
->fix_fixed_warning
= 0; /* so we only ask first time */
4835 if(ps
->readonly_pinerc
)
4838 set_titlebar(_("FIXING PINERC"), ps
->mail_stream
,
4839 ps
->context_current
,
4840 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
4842 if(want_to(_("Some of your options conflict with site policy. Investigate"),
4843 'y', 'n', NO_HELP
, WT_FLUSH_IN
) != 'y')
4846 /* space want_to requires in addition to the string you pass in */
4847 #define WANTTO_SPACE 6
4848 need
= WANTTO_SPACE
+ utf8_width(clear
);
4850 for(v
= ps
->vars
; v
->name
; v
++){
4854 v
== &ps
->vars
[V_FEATURE_LIST
]) /* handle feature-list below */
4860 (v
->post_user_val
.l
|| v
->main_user_val
.l
)){
4863 active_list
= v
->post_user_val
.l
? v
->post_user_val
.l
4864 : v
->main_user_val
.l
;
4866 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is "), v
->name
);
4867 prompt
[sizeof(prompt
)-1] = '\0';
4868 p
= prompt
+ strlen(prompt
);
4869 for(i
= 0; active_list
[i
]; i
++){
4870 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4872 if(i
&& sizeof(prompt
)-(p
-prompt
) > 0)
4875 sstrncpy(&p
, active_list
[i
], sizeof(prompt
)-(p
-prompt
));
4876 if(sizeof(prompt
)-(p
-prompt
) > 0)
4879 prompt
[sizeof(prompt
)-1] = '\0';
4882 if(sizeof(prompt
)-(p
-prompt
) > 0)
4886 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"), v
->name
, _(empty_val2
));
4889 if(v
->post_user_val
.p
|| v
->main_user_val
.p
){
4892 active_var
= v
->post_user_val
.p
? v
->post_user_val
.p
4893 : v
->main_user_val
.p
;
4895 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4896 v
->name
, active_var
);
4899 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4900 v
->name
, _(empty_val2
));
4905 prompt
[sizeof(prompt
)-1] = '\0';
4908 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4909 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4911 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4912 prompt
[sizeof(prompt
)-1] = '\0';
4913 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4915 if(v
->main_user_val
.l
)
4917 if(v
->post_user_val
.l
)
4921 if(v
->main_user_val
.p
)
4923 if(v
->post_user_val
.p
)
4927 if(delete_user_vals(v
))
4935 * As always, feature-list has to be handled separately.
4937 exc
= (ps
->ew_for_except_vars
!= Main
);
4938 v
= &ps
->vars
[V_FEATURE_LIST
];
4939 list_fixed
= v
->fixed_val
.l
;
4941 for(j
= 0; j
< 2; j
++){
4942 plist
= (j
==0) ? &v
->main_user_val
.l
: &v
->post_user_val
.l
;
4945 for(i
= 0; list
[i
]; i
++){
4947 if(!struncmp(p
, "no-", 3))
4949 for(k
= 0; list_fixed
&& list_fixed
[k
]; k
++){
4951 if(!struncmp(q
, "no-", 3))
4953 if(!strucmp(q
, p
) && strucmp(list
[i
], list_fixed
[k
])){
4954 snprintf(prompt
, sizeof(prompt
), "Your %s is %s%s, fixed value is %s",
4955 p
, p
== list
[i
] ? _("ON") : _("OFF"),
4956 exc
? ((plist
== &v
->main_user_val
.l
) ? ""
4957 : " in postload-config")
4959 q
== list_fixed
[k
] ? _("ON") : _("OFF"));
4961 prompt
[sizeof(prompt
)-1] = '\0';
4962 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4963 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4965 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4966 prompt
[sizeof(prompt
)-1] = '\0';
4967 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4970 if(plist
== &v
->main_user_val
.l
)
4976 * Clear the feature from the user's pinerc
4977 * so that we'll stop bothering them when they
4980 clear_feature(plist
, p
);
4983 * clear_feature scoots the list up, so if list[i] was
4984 * the last one going in, now it is the end marker. We
4985 * just decrement i so that it will get incremented and
4986 * then test == 0 in the for loop. We could just goto
4987 * outta_here to accomplish the same thing.
5000 write_pinerc(ps
, Main
, WRP_NONE
);
5002 write_pinerc(ps
, Post
, WRP_NONE
);
5009 * Adjust side effects that happen because variable changes values.
5011 * Var->user_val should be set to the new value before calling this.
5014 fix_side_effects(struct pine
*ps
, struct variable
*var
, int revert
)
5017 char **v
, *q
, **apval
;
5018 struct variable
*vars
= ps
->vars
;
5020 /* move this up here so we get the Using default message */
5021 if(var
== &ps
->vars
[V_PERSONAL_NAME
]){
5022 if(!(var
->main_user_val
.p
||
5023 var
->post_user_val
.p
) && ps
->ui
.fullname
){
5024 if(var
->current_val
.p
)
5025 fs_give((void **)&var
->current_val
.p
);
5027 var
->current_val
.p
= cpystr(ps
->ui
.fullname
);
5034 && !(var
->main_user_val
.p
||
5035 var
->post_user_val
.p
)
5036 && var
->current_val
.p
)
5040 && !(var
->main_user_val
.l
||
5041 var
->post_user_val
.l
)
5042 && var
->current_val
.l
)))
5043 q_status_message(SM_ORDER
,0,3,_("Using default value"));
5045 if(var
== &ps
->vars
[V_USER_DOMAIN
]){
5048 if(ps
->VAR_USER_DOMAIN
5049 && ps
->VAR_USER_DOMAIN
[0]
5050 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5053 q_status_message2(SM_ORDER
, 3, 5,
5054 _("User-Domain (%s) cannot contain \"@\"; using %s"),
5055 ps
->VAR_USER_DOMAIN
, p
);
5056 q
= ps
->VAR_USER_DOMAIN
;
5057 while((*q
++ = *p
++) != '\0')
5062 q_status_message1(SM_ORDER
, 3, 5,
5063 _("User-domain (%s) cannot contain \"@\"; deleting"),
5064 ps
->VAR_USER_DOMAIN
);
5066 if(ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
){
5067 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
);
5068 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5071 if(ps
->VAR_USER_DOMAIN
5072 && ps
->VAR_USER_DOMAIN
[0]
5073 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5074 if(ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
){
5075 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
);
5076 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5083 * Reset various pointers pertaining to domain name and such...
5087 else if(var
== &ps
->vars
[V_INBOX_PATH
]){
5089 * fixup the inbox path based on global/default values...
5091 init_inbox_mapping(ps
->VAR_INBOX_PATH
, ps
->context_list
);
5093 if(!strucmp(ps
->cur_folder
, ps
->inbox_name
) && ps
->mail_stream
5094 && strcmp(ps
->VAR_INBOX_PATH
, ps
->mail_stream
->mailbox
)){
5096 * If we currently have "inbox" open and the mailbox name
5097 * doesn't match, reset the current folder's name and
5098 * remove the SP_INBOX flag.
5100 strncpy(ps
->cur_folder
, ps
->mail_stream
->mailbox
,
5101 sizeof(ps
->cur_folder
)-1);
5102 ps
->cur_folder
[sizeof(ps
->cur_folder
)-1] = '\0';
5103 sp_set_fldr(ps
->mail_stream
, ps
->cur_folder
);
5104 sp_unflag(ps
->mail_stream
, SP_INBOX
);
5105 ps
->mangled_header
= 1;
5107 else if(sp_inbox_stream()
5108 && strcmp(ps
->VAR_INBOX_PATH
, sp_inbox_stream()->original_mailbox
)){
5109 MAILSTREAM
*m
= sp_inbox_stream();
5112 * if we don't have inbox directly open, but have it
5113 * open for new mail notification, close the stream like
5114 * any other ordinary folder, and clean up...
5117 sp_unflag(m
, SP_PERMLOCKED
| SP_INBOX
);
5118 sp_set_fldr(m
, m
->mailbox
);
5119 expunge_and_close(m
, NULL
, EC_NONE
);
5123 else if(var
== &ps
->vars
[V_INCCHECKTIMEO
]){
5124 int old_value
= ps
->inc_check_timeout
;
5126 if(SVAR_INC_CHECK_TIMEO(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5128 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5131 ps
->inc_check_timeout
= old_value
;
5133 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5134 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5136 else if(var
== &ps
->vars
[V_INCCHECKINTERVAL
]){
5137 int old_value
= ps
->inc_check_interval
;
5139 if(SVAR_INC_CHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5141 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5144 ps
->inc_check_interval
= old_value
;
5146 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5147 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5149 else if(var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
]){
5150 int old_value
= ps
->inc_second_check_interval
;
5152 if(SVAR_INC_2NDCHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5154 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5157 ps
->inc_second_check_interval
= old_value
;
5159 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5160 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5162 else if(var
== &ps
->vars
[V_INCCHECKLIST
]){
5163 if(ps
->context_list
&& ps
->context_list
->use
& CNTXT_INCMNG
)
5164 reinit_incoming_folder_list(ps
, ps
->context_list
);
5166 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5167 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5169 else if(var
== &ps
->vars
[V_ADDRESSBOOK
] ||
5170 var
== &ps
->vars
[V_GLOB_ADDRBOOK
] ||
5172 var
== &ps
->vars
[V_LDAP_SERVERS
] ||
5174 var
== &ps
->vars
[V_ABOOK_FORMATS
]){
5177 else if(var
== &ps
->vars
[V_INDEX_FORMAT
]){
5178 reset_index_format();
5179 clear_index_cache(ps
->mail_stream
, 0);
5181 else if(var
== &ps
->vars
[V_DEFAULT_FCC
] ||
5182 var
== &ps
->vars
[V_DEFAULT_SAVE_FOLDER
]){
5183 init_save_defaults();
5185 else if(var
== &ps
->vars
[V_KW_BRACES
] ||
5186 var
== &ps
->vars
[V_OPENING_SEP
] ||
5187 var
== &ps
->vars
[V_ALT_ADDRS
]){
5188 clear_index_cache(ps
->mail_stream
, 0);
5190 else if(var
== &ps
->vars
[V_KEYWORDS
]){
5191 if(ps_global
->keywords
)
5192 free_keyword_list(&ps_global
->keywords
);
5194 if(var
->current_val
.l
&& var
->current_val
.l
[0])
5195 ps_global
->keywords
= init_keyword_list(var
->current_val
.l
);
5197 clear_index_cache(ps
->mail_stream
, 0);
5199 else if(var
== &ps
->vars
[V_INIT_CMD_LIST
]){
5201 q_status_message(SM_ASYNC
, 0, 3,
5202 _("Initial command changes will affect your next Alpine session."));
5204 else if(var
== &ps
->vars
[V_VIEW_HEADERS
]){
5205 ps
->view_all_except
= 0;
5206 if(ps
->VAR_VIEW_HEADERS
)
5207 for(v
= ps
->VAR_VIEW_HEADERS
; (q
= *v
) != NULL
; v
++)
5211 removing_leading_white_space(q
);
5212 /* look for colon or space or end */
5213 for(p
= q
; *p
&& !isspace((unsigned char)*p
) && *p
!= ':'; p
++)
5217 if(strucmp(q
, ALL_EXCEPT
) == 0)
5218 ps
->view_all_except
= 1;
5221 else if(var
== &ps
->vars
[V_OVERLAP
]){
5222 int old_value
= ps
->viewer_overlap
;
5224 if(SVAR_OVERLAP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5226 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5229 ps
->viewer_overlap
= old_value
;
5231 else if(var
== &ps
->vars
[V_SLEEP
]){
5232 int old_value
= ps
->sleep
;
5234 if(SVAR_SLEEP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5236 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5239 ps
->sleep
= old_value
;
5242 else if(smime_related_var(ps
, var
)){
5246 else if(var
== &ps
->vars
[V_MAXREMSTREAM
]){
5247 int old_value
= ps
->s_pool
.max_remstream
;
5249 if(SVAR_MAXREMSTREAM(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5251 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5254 ps
->s_pool
.max_remstream
= old_value
;
5256 dprint((9, "max_remstream goes to %d\n",
5257 ps
->s_pool
.max_remstream
));
5260 else if(var
== &ps
->vars
[V_CHAR_SET
]){
5263 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5265 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5268 if(reset_character_set_stuff(&err
) == -1)
5269 alpine_panic(err
? err
: "trouble with Character-Set");
5271 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5272 fs_give((void **) &err
);
5276 else if(var
== &ps
->vars
[V_KEY_CHAR_SET
]){
5279 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5281 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5284 if(reset_character_set_stuff(&err
) == -1)
5285 alpine_panic(err
? err
: "trouble with Character-Set");
5287 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5288 fs_give((void **) &err
);
5292 #endif /* ! _WINDOWS */
5293 else if(var
== &ps
->vars
[V_POST_CHAR_SET
]){
5294 update_posting_charset(ps
, revert
);
5296 else if(var
== &ps
->vars
[V_MARGIN
]){
5297 int old_value
= ps
->scroll_margin
;
5299 if(SVAR_MARGIN(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5301 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5304 ps
->scroll_margin
= old_value
;
5306 else if(var
== &ps
->vars
[V_DEADLETS
]){
5307 int old_value
= ps
->deadlets
;
5309 if(SVAR_DEADLETS(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5311 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5314 ps
->deadlets
= old_value
;
5316 else if(var
== &ps
->vars
[V_FILLCOL
]){
5317 if(SVAR_FILLCOL(ps
, ps
->composer_fillcol
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5319 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5322 else if(var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
5323 val
= ps
->quote_suppression_threshold
;
5324 if(val
< Q_SUPP_LIMIT
&& val
> 0)
5327 if(ps
->VAR_QUOTE_SUPPRESSION
5328 && SVAR_QUOTE_SUPPRESSION(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5330 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5333 if(val
> 0 && val
< Q_SUPP_LIMIT
){
5335 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, _("Ignoring Quote-Suppression-Threshold value of %s, see help"), ps
->VAR_QUOTE_SUPPRESSION
);
5336 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
5337 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5341 if(val
< 0 && val
!= Q_DEL_ALL
)
5342 ps
->quote_suppression_threshold
= -val
;
5344 ps
->quote_suppression_threshold
= val
;
5348 else if(var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
5349 if(SVAR_MSGDLAY(ps
, ps
->status_msg_delay
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5351 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5354 else if(var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
5355 if(SVAR_ACTIVEINTERVAL(ps
, ps
->active_status_interval
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5357 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5360 busy_cue(_("Active Example"), NULL
, 0);
5362 cancel_busy_cue(-1);
5365 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
5366 else if(var
== &ps
->vars
[V_FIFOPATH
]){
5367 init_newmailfifo(ps
->VAR_FIFOPATH
);
5370 else if(var
== &ps
->vars
[V_NMW_WIDTH
]){
5371 int old_value
= ps
->nmw_width
;
5373 if(SVAR_NMW_WIDTH(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5375 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5379 if(old_value
!= ps
->nmw_width
)
5380 mswin_setnewmailwidth(old_value
); /* actually the new value */
5382 ps
->nmw_width
= old_value
;
5385 else if(var
== &ps
->vars
[V_TCPOPENTIMEO
]){
5388 if(ps
->VAR_TCPOPENTIMEO
&& SVAR_TCP_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5389 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5391 else if(var
== &ps
->vars
[V_TCPREADWARNTIMEO
]){
5394 if(ps
->VAR_TCPREADWARNTIMEO
&& SVAR_TCP_READWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5395 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5397 else if(var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
]){
5400 if(ps
->VAR_TCPWRITEWARNTIMEO
&& SVAR_TCP_WRITEWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5401 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5403 else if(var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
5406 if(ps
->VAR_TCPQUERYTIMEO
&& SVAR_TCP_QUERY(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5407 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5409 else if(var
== &ps
->vars
[V_RSHOPENTIMEO
]){
5412 if(ps
->VAR_RSHOPENTIMEO
&& SVAR_RSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5413 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5415 else if(var
== &ps
->vars
[V_SSHOPENTIMEO
]){
5418 if(ps
->VAR_SSHOPENTIMEO
&& SVAR_SSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5419 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5421 else if(var
== &ps
->vars
[V_SIGNATURE_FILE
]){
5422 if(ps
->VAR_OPER_DIR
&& ps
->VAR_SIGNATURE_FILE
&&
5423 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
5424 !in_dir(ps
->VAR_OPER_DIR
, ps
->VAR_SIGNATURE_FILE
)){
5428 l
= strlen(ps
->VAR_OPER_DIR
) + 100;
5429 e
= (char *) fs_get((l
+1) * sizeof(char));
5430 snprintf(e
, l
+1, _("Warning: Sig file can't be outside of %s"),
5433 q_status_message(SM_ORDER
, 3, 6, e
);
5434 fs_give((void **)&e
);
5437 else if(var
== &ps
->vars
[V_OPER_DIR
]){
5438 if(ps
->VAR_OPER_DIR
&& !ps
->VAR_OPER_DIR
[0]){
5439 q_status_message(SM_ORDER
, 3, 5, "Operating-dir is turned off.");
5440 fs_give((void **)&ps
->vars
[V_OPER_DIR
].current_val
.p
);
5441 if(ps
->vars
[V_OPER_DIR
].fixed_val
.p
)
5442 fs_give((void **)&ps
->vars
[V_OPER_DIR
].fixed_val
.p
);
5443 if(ps
->vars
[V_OPER_DIR
].global_val
.p
)
5444 fs_give((void **)&ps
->vars
[V_OPER_DIR
].global_val
.p
);
5445 if(ps
->vars
[V_OPER_DIR
].cmdline_val
.p
)
5446 fs_give((void **)&ps
->vars
[V_OPER_DIR
].cmdline_val
.p
);
5447 if(ps
->vars
[V_OPER_DIR
].post_user_val
.p
)
5448 fs_give((void **)&ps
->vars
[V_OPER_DIR
].post_user_val
.p
);
5449 if(ps
->vars
[V_OPER_DIR
].main_user_val
.p
)
5450 fs_give((void **)&ps
->vars
[V_OPER_DIR
].main_user_val
.p
);
5453 else if(var
== &ps
->vars
[V_MAILCHECK
]){
5455 if(SVAR_MAILCHK(ps
, timeo
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5456 set_input_timeout(15);
5458 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5461 set_input_timeout(timeo
);
5462 if(get_input_timeout() == 0 && !revert
){
5463 q_status_message(SM_ORDER
, 4, 6,
5464 _("Warning: automatic new mail checking and mailbox checkpointing is disabled"));
5465 if(ps
->VAR_INBOX_PATH
&& ps
->VAR_INBOX_PATH
[0] == '{')
5466 q_status_message(SM_ASYNC
, 3, 6,
5467 _("Warning: Mail-Check-Interval=0 may cause IMAP server connection to time out"));
5471 else if(var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
5472 val
= (int) ps
->check_interval_for_noncurr
;
5473 if(ps
->VAR_MAILCHECKNONCURR
5474 && SVAR_MAILCHKNONCURR(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5476 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5479 ps
->check_interval_for_noncurr
= (time_t) val
;
5481 else if(var
== &ps
->vars
[V_MAILDROPCHECK
]){
5485 if(ps
->VAR_MAILDROPCHECK
&& SVAR_MAILDCHK(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5486 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5489 rvl
= (60L * 60L * 24L * 100L); /* 100 days */
5492 mail_parameters(NULL
, SET_SNARFINTERVAL
, (void *) rvl
);
5495 else if(var
== &ps
->vars
[V_NNTPRANGE
]){
5499 if(ps
->VAR_NNTPRANGE
&& SVAR_NNTPRANGE(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5500 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5503 mail_parameters(NULL
, SET_NNTPRANGE
, (void *) rvl
);
5506 else if(var
== &ps
->vars
[V_CUSTOM_HDRS
] || var
== &ps
->vars
[V_COMP_HDRS
]){
5507 /* this will give warnings about headers that can't be changed */
5508 if(!revert
&& var
->current_val
.l
&& var
->current_val
.l
[0])
5509 customized_hdr_setup(NULL
, var
->current_val
.l
, UseAsDef
);
5511 #if defined(DOS) || defined(OS2)
5512 else if(var
== &ps
->vars
[V_FOLDER_EXTENSION
]){
5513 mail_parameters(NULL
, SET_EXTENSION
,
5514 (void *)var
->current_val
.p
);
5516 else if(var
== &ps
->vars
[V_NEWSRC_PATH
]){
5517 if(var
->current_val
.p
&& var
->current_val
.p
[0])
5518 mail_parameters(NULL
, SET_NEWSRC
,
5519 (void *)var
->current_val
.p
);
5522 else if(revert
&& standard_radio_var(ps
, var
)){
5524 cur_rule_value(var
, TRUE
, FALSE
);
5525 if(var
== &ps_global
->vars
[V_AB_SORT_RULE
])
5526 addrbook_redo_sorts();
5527 else if(var
== &ps_global
->vars
[V_THREAD_INDEX_STYLE
]){
5528 clear_index_cache(ps_global
->mail_stream
, 0);
5529 set_lflags(ps_global
->mail_stream
, ps_global
->msgmap
,
5530 MN_COLL
| MN_CHID
, 0);
5531 if(SORT_IS_THREADED(ps_global
->msgmap
)
5532 && (SEP_THRDINDX() || COLL_THRDS()))
5533 collapse_threads(ps_global
->mail_stream
, ps_global
->msgmap
, NULL
);
5535 adjust_cur_to_visible(ps_global
->mail_stream
, ps_global
->msgmap
);
5538 else if(var
== &ps
->vars
[V_COLOR_STYLE
]){
5539 pico_toggle_color(0);
5540 switch(ps
->color_style
){
5543 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
5546 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
5549 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
5552 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
5556 if(ps
->color_style
!= COL_NONE
)
5557 pico_toggle_color(1);
5559 if(pico_usingcolor())
5560 pico_set_normal_color();
5562 clear_index_cache(ps_global
->mail_stream
, 0);
5564 ps
->mangled_screen
= 1;
5568 else if(revert
&& var
== &ps
->vars
[V_SORT_KEY
]){
5571 decode_sort(VAR_SORT_KEY
, &ps
->def_sort
, &def_sort_rev
);
5572 ps
->def_sort_rev
= def_sort_rev
;
5574 else if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5575 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5576 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5578 if(var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
] &&
5579 !(var
->current_val
.p
&& var
->current_val
.p
[0])){
5580 if(var
->current_val
.p
)
5581 fs_give((void **) &var
->current_val
.p
);
5583 q_status_message1(SM_ORDER
, 3, 5,
5584 _("\"%s\" can't be Empty, using default"), var
->name
);
5586 apval
= APVAL(var
, ew
);
5588 fs_give((void **)apval
);
5590 set_current_val(var
, FALSE
, FALSE
);
5592 if(!(var
->current_val
.p
&& var
->current_val
.p
[0]
5593 && !var
->current_val
.p
[1])){
5594 if(var
->current_val
.p
)
5595 fs_give((void **) &var
->current_val
.p
);
5597 var
->current_val
.p
= cpystr(DF_THREAD_LASTREPLY_CHAR
);
5601 if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5602 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5603 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5604 if(var
->current_val
.p
&& var
->current_val
.p
[0] &&
5605 var
->current_val
.p
[1]){
5606 q_status_message1(SM_ORDER
, 3, 5,
5607 "Only first character of \"%s\" is used",
5609 var
->current_val
.p
[1] = '\0';
5612 if(var
->main_user_val
.p
&& var
->main_user_val
.p
[0] &&
5613 var
->main_user_val
.p
[1])
5614 var
->main_user_val
.p
[1] = '\0';
5616 if(var
->post_user_val
.p
&& var
->post_user_val
.p
[0] &&
5617 var
->post_user_val
.p
[1])
5618 var
->post_user_val
.p
[1] = '\0';
5621 clear_index_cache(ps_global
->mail_stream
, 0);
5622 set_need_format_setup(ps_global
->mail_stream
);
5624 else if(var
== &ps
->vars
[V_NNTP_SERVER
]){
5625 free_contexts(&ps_global
->context_list
);
5626 init_folders(ps_global
);
5628 else if(var
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
]){
5631 else if(var
== &ps
->vars
[V_PRINTER
]){
5632 if(!revert
&& ps
->vars
[V_PERSONAL_PRINT_COMMAND
].is_fixed
){
5633 if(printer_value_check_and_adjust())
5634 q_status_message1(SM_ORDER
, 3, 5,
5635 _("Can't set \"%s\" to that value, see Setup/Printer"),
5636 pretty_var_name(var
->name
));
5639 else if(var
== &ps
->vars
[V_KW_COLORS
] ||
5640 var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
] ||
5641 var
== &ps
->vars
[V_IND_PLUS_FORE_COLOR
] ||
5642 var
== &ps
->vars
[V_IND_IMP_FORE_COLOR
] ||
5643 var
== &ps
->vars
[V_IND_DEL_FORE_COLOR
] ||
5644 var
== &ps
->vars
[V_IND_ANS_FORE_COLOR
] ||
5645 var
== &ps
->vars
[V_IND_NEW_FORE_COLOR
] ||
5646 var
== &ps
->vars
[V_IND_UNS_FORE_COLOR
] ||
5647 var
== &ps
->vars
[V_IND_HIPRI_FORE_COLOR
]||
5648 var
== &ps
->vars
[V_IND_LOPRI_FORE_COLOR
]||
5649 var
== &ps
->vars
[V_IND_ARR_FORE_COLOR
] ||
5650 var
== &ps
->vars
[V_IND_REC_FORE_COLOR
] ||
5651 var
== &ps
->vars
[V_IND_FWD_FORE_COLOR
] ||
5652 var
== &ps
->vars
[V_IND_OP_FORE_COLOR
] ||
5653 var
== &ps
->vars
[V_IND_FROM_FORE_COLOR
] ||
5654 var
== &ps
->vars
[V_IND_SUBJ_FORE_COLOR
] ||
5655 var
== &ps
->vars
[V_IND_PLUS_BACK_COLOR
] ||
5656 var
== &ps
->vars
[V_IND_IMP_BACK_COLOR
] ||
5657 var
== &ps
->vars
[V_IND_DEL_BACK_COLOR
] ||
5658 var
== &ps
->vars
[V_IND_ANS_BACK_COLOR
] ||
5659 var
== &ps
->vars
[V_IND_NEW_BACK_COLOR
] ||
5660 var
== &ps
->vars
[V_IND_UNS_BACK_COLOR
] ||
5661 var
== &ps
->vars
[V_IND_ARR_BACK_COLOR
] ||
5662 var
== &ps
->vars
[V_IND_REC_BACK_COLOR
] ||
5663 var
== &ps
->vars
[V_IND_FWD_BACK_COLOR
] ||
5664 var
== &ps
->vars
[V_IND_OP_BACK_COLOR
] ||
5665 var
== &ps
->vars
[V_IND_FROM_BACK_COLOR
] ||
5666 var
== &ps
->vars
[V_IND_SUBJ_BACK_COLOR
]){
5667 clear_index_cache(ps_global
->mail_stream
, 0);
5669 else if(var
== score_act_global_ptr
){
5672 score
= atoi(var
->current_val
.p
);
5673 if(score
< SCORE_MIN
|| score
> SCORE_MAX
){
5674 q_status_message2(SM_ORDER
, 3, 5,
5675 _("Score Value must be in range %s to %s"),
5676 comatose(SCORE_MIN
), comatose(SCORE_MAX
));
5677 apval
= APVAL(var
, ew
);
5679 fs_give((void **)apval
);
5681 set_current_val(var
, FALSE
, FALSE
);
5684 else if(var
== scorei_pat_global_ptr
|| var
== age_pat_global_ptr
5685 || var
== size_pat_global_ptr
|| var
== cati_global_ptr
){
5686 apval
= APVAL(var
, ew
);
5689 iv
= parse_intvl(*apval
);
5691 fs_give((void **) apval
);
5692 *apval
= stringform_of_intvl(iv
);
5696 fs_give((void **) apval
);
5699 set_current_val(var
, FALSE
, FALSE
);
5701 else if(var
== &ps
->vars
[V_FEATURE_LIST
]){
5702 process_feature_list(ps
, var
->current_val
.l
, 0, 0, 0);
5704 else if(!revert
&& (var
== &ps
->vars
[V_LAST_TIME_PRUNE_QUESTION
] ||
5705 var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
] ||
5706 var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
] ||
5707 var
== &ps
->vars
[V_USERINPUTTIMEO
] ||
5708 var
== &ps
->vars
[V_NEWS_ACTIVE_PATH
] ||
5709 var
== &ps
->vars
[V_NEWS_SPOOL_DIR
] ||
5710 var
== &ps
->vars
[V_INCOMING_FOLDERS
] ||
5711 var
== &ps
->vars
[V_FOLDER_SPEC
] ||
5712 var
== &ps
->vars
[V_NEWS_SPEC
] ||
5713 var
== &ps
->vars
[V_DISABLE_DRIVERS
] ||
5714 var
== &ps
->vars
[V_DISABLE_AUTHS
] ||
5715 var
== &ps
->vars
[V_RSHPATH
] ||
5716 var
== &ps
->vars
[V_RSHCMD
] ||
5717 var
== &ps
->vars
[V_SSHCMD
] ||
5718 var
== &ps
->vars
[V_SSHPATH
])){
5719 q_status_message2(SM_ASYNC
, 0, 3,
5720 _("Changes%s%s will affect your next Alpine session."),
5721 var
->name
? " to " : "", var
->name
? var
->name
: "");
5724 if(!revert
&& (var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
5725 var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
5726 var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
5727 var
== &ps
->vars
[V_TCPQUERYTIMEO
] ||
5728 var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
5729 var
== &ps
->vars
[V_SSHOPENTIMEO
]))
5730 q_status_message(SM_ASYNC
, 0, 3,
5731 _("Timeout changes will affect your next Alpine session."));
5736 * Compare saved user_val with current user_val to see if it changed.
5737 * If any have changed, change it back and take the appropriate action.
5740 revert_to_saved_config(struct pine
*ps
, SAVED_CONFIG_S
*vsave
, int allow_hard_to_config_remotely
)
5742 struct variable
*vreal
;
5746 char *pval
, **apval
, **lval
, ***alval
;
5749 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5750 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5755 lval
= LVAL(vreal
, ew
);
5756 alval
= ALVAL(vreal
, ew
);
5758 if((v
->saved_user_val
.l
&& !lval
)
5759 || (!v
->saved_user_val
.l
&& lval
))
5761 else if(!v
->saved_user_val
.l
&& !lval
)
5762 ;/* no change, nothing to do */
5764 for(i
= 0; v
->saved_user_val
.l
[i
] || lval
[i
]; i
++)
5765 if((v
->saved_user_val
.l
[i
]
5767 || strcmp(v
->saved_user_val
.l
[i
], lval
[i
])))
5769 (!v
->saved_user_val
.l
[i
] && lval
[i
])){
5779 free_list_array(alval
);
5781 /* copy back the original one */
5782 if(v
->saved_user_val
.l
){
5783 list
= v
->saved_user_val
.l
;
5785 /* count how many */
5789 *alval
= (char **)fs_get((n
+1) * sizeof(char *));
5791 for(i
= 0; i
< n
; i
++)
5792 (*alval
)[i
] = cpystr(v
->saved_user_val
.l
[i
]);
5800 pval
= PVAL(vreal
, ew
);
5801 apval
= APVAL(vreal
, ew
);
5803 if((v
->saved_user_val
.p
&&
5804 (!pval
|| strcmp(v
->saved_user_val
.p
, pval
))) ||
5805 (!v
->saved_user_val
.p
&& pval
)){
5806 /* It changed, fix it */
5809 /* free the changed value */
5811 fs_give((void **)apval
);
5813 if(v
->saved_user_val
.p
)
5814 *apval
= cpystr(v
->saved_user_val
.p
);
5820 if(vreal
== &ps
->vars
[V_FEATURE_LIST
])
5821 set_feature_list_current_val(vreal
);
5823 set_current_val(vreal
, TRUE
, FALSE
);
5825 fix_side_effects(ps
, vreal
, 1);
5832 save_config_vars(struct pine
*ps
, int allow_hard_to_config_remotely
)
5834 struct variable
*vreal
;
5835 SAVED_CONFIG_S
*vsave
, *v
;
5837 vsave
= (SAVED_CONFIG_S
*)fs_get((V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5838 memset((void *)vsave
, 0, (V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5840 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5841 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5848 if(LVAL(vreal
, ew
)){
5849 /* count how many */
5851 list
= LVAL(vreal
, ew
);
5855 v
->saved_user_val
.l
= (char **)fs_get((n
+1) * sizeof(char *));
5856 memset((void *)v
->saved_user_val
.l
, 0, (n
+1)*sizeof(char *));
5857 for(i
= 0; i
< n
; i
++)
5858 v
->saved_user_val
.l
[i
] = cpystr(list
[i
]);
5860 v
->saved_user_val
.l
[n
] = NULL
;
5865 v
->saved_user_val
.p
= cpystr(PVAL(vreal
, ew
));
5874 free_saved_config(struct pine
*ps
, SAVED_CONFIG_S
**vsavep
, int allow_hard_to_config_remotely
)
5876 struct variable
*vreal
;
5879 if(vsavep
&& *vsavep
){
5880 for(v
= *vsavep
, vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5881 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5884 if(vreal
->is_list
){ /* free saved_user_val.l */
5885 if(v
&& v
->saved_user_val
.l
)
5886 free_list_array(&v
->saved_user_val
.l
);
5888 else if(v
&& v
->saved_user_val
.p
)
5889 fs_give((void **)&v
->saved_user_val
.p
);
5892 fs_give((void **)vsavep
);
5898 * Returns positive if any thing was actually deleted.
5901 delete_user_vals(struct variable
*v
)
5907 if(v
->post_user_val
.l
){
5909 free_list_array(&v
->post_user_val
.l
);
5911 if(v
->main_user_val
.l
){
5913 free_list_array(&v
->main_user_val
.l
);
5917 if(v
->post_user_val
.p
){
5919 fs_give((void **)&v
->post_user_val
.p
);
5921 if(v
->main_user_val
.p
){
5923 fs_give((void **)&v
->main_user_val
.p
);
5933 * ../pith/conf.c required function
5936 unexpected_pinerc_change(void)
5939 if(want_to("Unexpected pinerc change! Overwrite with current config",
5940 'n', 0, NO_HELP
, WT_FLUSH_IN
) == 'n'){
5941 return(-1); /* abort pinerc write */
5944 return(0); /* overwrite */
5950 /*----------------------------------------------------------------------
5951 MSWin scroll callback. Called during scroll message processing.
5955 Args: cmd - what type of scroll operation.
5956 scroll_pos - paramter for operation.
5957 used as position for SCROLL_TO operation.
5959 Returns: TRUE - did the scroll operation.
5960 FALSE - was not able to do the scroll operation.
5963 config_scroll_callback (cmd
, scroll_pos
)
5968 case MSWIN_KEY_SCROLLUPLINE
:
5969 config_scroll_down (scroll_pos
);
5972 case MSWIN_KEY_SCROLLDOWNLINE
:
5973 config_scroll_up (scroll_pos
);
5976 case MSWIN_KEY_SCROLLUPPAGE
:
5977 config_scroll_down (BODY_LINES(ps_global
));
5980 case MSWIN_KEY_SCROLLDOWNPAGE
:
5981 config_scroll_up (BODY_LINES(ps_global
));
5984 case MSWIN_KEY_SCROLLTO
:
5985 config_scroll_to_pos (scroll_pos
);
5989 option_screen_redrawer();
5995 #endif /* _WINDOWS */