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
, int *pos
)
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;
1321 *pos
= get_confline_number(screen
->current
);
1328 if(screen
&& screen
->ro_warning
){
1334 q_status_message1(SM_ORDER
|SM_DING
, 1, 3,
1335 _("%s can't change options or settings"),
1336 ps_global
->restricted
? "Alpine demo"
1337 : _("Config file not changeable,"));
1339 else if(screen
->current
->tool
){
1342 flags
= screen
->current
->flags
;
1343 flags
|= (changes
? CF_CHANGES
: 0);
1345 switch(i
=(*screen
->current
->tool
)(ps
, cmd
,
1346 &screen
->current
, flags
)){
1348 q_status_message2(SM_ORDER
, 0, 2,
1349 /* TRANSLATORS: Command <command letter> not defined here.
1350 Leave the trailing %s which might be a parenthetical
1352 _("Command \"%s\" not defined here.%s"),
1354 F_ON(F_BLANK_KEYMENU
,ps
) ? "" : " See key menu below.");
1384 bogus_utf8_command(utf8str
, "?");
1387 case MC_NONE
: /* simple timeout */
1392 screen
->current
= first_confline(screen
->current
);
1393 free_conflines(&screen
->current
);
1402 config_scroll_up(long int n
)
1404 CONF_S
*ctmp
= opt_screen
->top_line
;
1408 config_scroll_down(-n
);
1410 for(; n
>0 && ctmp
->next
; n
--){
1411 ctmp
= next_confline(ctmp
);
1412 if(prev_confline(ctmp
) == opt_screen
->current
)
1416 opt_screen
->top_line
= ctmp
;
1417 ps_global
->mangled_body
= 1;
1419 for(ctmp
= opt_screen
->top_line
;
1420 ctmp
&& (ctmp
->flags
& CF_NOSELECT
);
1421 ctmp
= next_confline(ctmp
))
1425 opt_screen
->current
= opt_screen
->prev
= ctmp
;
1427 while(opt_screen
->top_line
->flags
& CF_NOSELECT
)
1428 opt_screen
->top_line
= prev_confline(opt_screen
->top_line
);
1429 opt_screen
->current
= opt_screen
->prev
= opt_screen
->top_line
;
1437 * config_scroll_down -
1440 config_scroll_down(long int n
)
1442 CONF_S
*ctmp
= opt_screen
->top_line
, *last_sel
= NULL
;
1446 config_scroll_up(-n
);
1448 for(; n
>0 && ctmp
->prev
; n
--)
1449 ctmp
= prev_confline(ctmp
);
1451 opt_screen
->top_line
= ctmp
;
1452 ps_global
->mangled_body
= 1;
1453 for(ctmp
= opt_screen
->top_line
, i
= BODY_LINES(ps_global
);
1454 i
> 0 && ctmp
&& ctmp
!= opt_screen
->current
;
1455 ctmp
= next_confline(ctmp
), i
--)
1456 if(!(ctmp
->flags
& CF_NOSELECT
))
1460 opt_screen
->current
= opt_screen
->prev
= last_sel
;
1466 * config_scroll_to_pos -
1469 config_scroll_to_pos(long int n
)
1473 for(ctmp
= first_confline(opt_screen
->current
);
1474 n
&& ctmp
&& ctmp
!= opt_screen
->top_line
;
1475 ctmp
= next_confline(ctmp
), n
--)
1479 while(ctmp
&& ctmp
!= opt_screen
->top_line
)
1480 if((ctmp
= next_confline(ctmp
)) != NULL
)
1483 config_scroll_up(n
);
1488 * config_top_scroll - return pointer to the
1491 config_top_scroll(struct pine
*ps
, CONF_S
*topline
)
1496 for(ctmp
= topline
, i
= HS_MARGIN(ps
);
1498 ctmp
= next_confline(ctmp
), i
--)
1501 return(ctmp
? ctmp
: topline
);
1506 text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
1508 return(text_toolit(ps
, cmd
, cl
, flags
, 0));
1513 * simple text variable handler
1515 * note, things get a little involved due to the
1516 * screen struct <--> variable mapping. (but, once its
1517 * running it shouldn't need changing ;).
1519 * look_for_backslash == 1 means that backslash is an escape character.
1520 * In particular, \, can be used to put a literal comma
1521 * into a value. The value will still have the backslash
1522 * in it, but the comma after the backslash won't be treated
1523 * as an item separator.
1525 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
1526 * returns what conf_exit_cmd returns for exit command.
1529 text_toolit(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
, int look_for_backslash
)
1531 char prompt
[81], *sval
, *tmp
, *swap_val
, **newval
= NULL
;
1532 char *pval
, **apval
, **lval
, ***alval
;
1533 char *olddefval
= NULL
;
1534 int rv
= 0, skip_to_next
= 0, after
= 0, i
= 4, j
, k
;
1535 int lowrange
, hirange
, incr
, oeflags
, oebufsize
;
1536 int numval
, repeat_key
= 0;
1537 int curindex
, previndex
, nextindex
, deefault
;
1541 if((*cl
)->var
->is_list
){
1542 lval
= LVAL((*cl
)->var
, ew
);
1543 alval
= ALVAL((*cl
)->var
, ew
);
1546 pval
= PVAL((*cl
)->var
, ew
);
1547 apval
= APVAL((*cl
)->var
, ew
);
1550 oebufsize
= 6*MAXPATH
;
1551 sval
= (char *) fs_get(oebufsize
*sizeof(char));
1554 if(flags
&CF_NUMBER
){ /* only happens if !is_list */
1556 if((*cl
)->var
== &ps
->vars
[V_FILLCOL
]){
1558 hirange
= MAX_FILLCOL
;
1560 else if((*cl
)->var
== &ps
->vars
[V_SLEEP
]){
1564 else if((*cl
)->var
== &ps
->vars
[V_OVERLAP
]
1565 || (*cl
)->var
== &ps
->vars
[V_MARGIN
]){
1569 else if((*cl
)->var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
1570 lowrange
= -(Q_SUPP_LIMIT
-1);
1573 else if((*cl
)->var
== &ps
->vars
[V_MAXREMSTREAM
]){
1577 else if((*cl
)->var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
1581 else if((*cl
)->var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
1585 else if((*cl
)->var
== &ps
->vars
[V_MAILCHECK
] ||
1586 (*cl
)->var
== &ps
->vars
[V_INCCHECKINTERVAL
] ||
1587 (*cl
)->var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
] ||
1588 (*cl
)->var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
1593 else if((*cl
)->var
== &ps
->vars
[V_DEADLETS
]){
1597 else if((*cl
)->var
== &ps
->vars
[V_NMW_WIDTH
]){
1599 hirange
= MAX_SCREEN_COLS
;
1601 else if((*cl
)->var
== score_act_global_ptr
){
1605 else if((*cl
)->var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
1606 (*cl
)->var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
1607 (*cl
)->var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
1611 else if((*cl
)->var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
1612 (*cl
)->var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
1613 (*cl
)->var
== &ps
->vars
[V_SSHOPENTIMEO
] ||
1614 (*cl
)->var
== &ps
->vars
[V_USERINPUTTIMEO
]){
1618 else if((*cl
)->var
== &ps
->vars
[V_INCCHECKTIMEO
]){
1622 else if((*cl
)->var
== &ps
->vars
[V_MAILDROPCHECK
]){
1627 else if((*cl
)->var
== &ps
->vars
[V_NNTPRANGE
]){
1632 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
]){
1636 else if((*cl
)->var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
]){
1640 else if((*cl
)->var
== cat_lim_global_ptr
){
1653 ekey
[1].ch
= ctrl('P');
1654 ekey
[1].rval
= ctrl('P');
1655 ekey
[1].name
= "^P";
1656 ekey
[1].label
= N_("Decrease");
1657 ekey
[2].ch
= ctrl('N');
1658 ekey
[2].rval
= ctrl('N');
1659 ekey
[2].name
= "^N";
1660 ekey
[2].label
= N_("Increase");
1661 ekey
[3].ch
= KEY_DOWN
;
1662 ekey
[3].rval
= ctrl('P');
1665 ekey
[4].ch
= KEY_UP
;
1666 ekey
[4].rval
= ctrl('N');
1673 case MC_ADD
: /* add to list */
1674 if(fixed_var((*cl
)->var
, "add to", NULL
)){
1677 else if(!(*cl
)->var
->is_list
&& pval
){
1678 q_status_message(SM_ORDER
, 3, 3,
1679 _("Only single value allowed. Use \"Change\"."));
1685 if((*cl
)->var
->is_list
1686 && lval
&& lval
[0] && lval
[0][0]
1689 /* regular add to an existing list */
1691 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1692 tmpval
[sizeof(tmpval
)-1] = '\0';
1693 removing_trailing_white_space(tmpval
);
1695 /* 33 is the number of chars other than the value */
1696 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1697 k
= MIN(18, MAX(maxwidth
-33,0));
1698 if(utf8_width(tmpval
) > k
&& k
>= 3){
1699 (void) utf8_truncate(tmpval
, k
-3);
1700 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1701 tmpval
[sizeof(tmpval
)-1] = '\0';
1704 utf8_snprintf(prompt
, sizeof(prompt
),
1705 _("Enter text to insert before \"%.*w\": "), k
, tmpval
);
1706 prompt
[sizeof(prompt
)-1] = '\0';
1708 else if((*cl
)->var
->is_list
1710 && (*cl
)->var
->current_val
.l
){
1711 /* Add to list which doesn't exist, but default does exist */
1715 ekey
[0].label
= N_("Replace");
1719 ekey
[1].label
= N_("Add To");
1721 strncpy(prompt
, _("Replace or Add To default value ? "), sizeof(prompt
));
1722 prompt
[sizeof(prompt
)-1] = '\0';
1723 switch(radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, 'a', 'x',
1724 h_config_replace_add
, RB_NORM
)){
1727 for(j
= 0; (*cl
)->var
->current_val
.l
[j
]; j
++){
1728 sstrncpy(&p
, (*cl
)->var
->current_val
.l
[j
], oebufsize
-(p
-sval
));
1729 if(oebufsize
-(p
-sval
) > 2){
1734 if(oebufsize
-(p
-sval
) > 0)
1738 sval
[oebufsize
-1] = '\0';
1741 if(flags
& CF_NUMBER
)
1742 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1744 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1751 strncpy(sval
, olddefval
, oebufsize
);
1752 sval
[oebufsize
-1] = '\0';
1755 if(flags
& CF_NUMBER
)
1756 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric replacement text : "));
1758 snprintf(prompt
, sizeof(prompt
), _("Enter the replacement text : "));
1764 cmd_cancelled("Add");
1769 if(flags
& CF_NUMBER
)
1770 snprintf(prompt
, sizeof(prompt
), _("Enter the numeric text to be added : "));
1772 snprintf(prompt
, sizeof(prompt
), _("Enter the text to be added : "));
1775 prompt
[sizeof(prompt
)-1] = '\0';
1777 ps
->mangled_footer
= 1;
1784 if((*cl
)->var
->is_list
1785 && lval
&& lval
[0] && lval
[0][0]
1787 ekey
[0].ch
= ctrl('W');
1789 ekey
[0].name
= "^W";
1790 /* TRANSLATORS: Insert new item before current item */
1791 ekey
[0].label
= after
? N_("InsertBefore") : N_("InsertAfter");
1794 else if(!(flags
&CF_NUMBER
))
1797 oeflags
= OE_APPEND_CURRENT
;
1798 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
1800 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
1804 if((*cl
)->var
->is_list
)
1805 ps
->mangled_body
= 1;
1807 ps
->mangled_footer
= 1;
1809 removing_leading_and_trailing_white_space(sval
);
1811 * Coerce "" and <Empty Value> to empty string input.
1812 * Catch <No Value Set> as a substitute for deleting.
1814 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
1815 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
1817 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
1819 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
1821 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
1824 if((*cl
)->var
->is_list
){
1830 for(tmp
= sval
; *tmp
; tmp
++)
1832 i
++; /* conservative count of ,'s */
1835 ltmp
= (char **)fs_get(2 * sizeof(char *));
1836 ltmp
[0] = cpystr(sval
);
1840 ltmp
= parse_list(sval
, i
+ 1,
1842 ? PL_COMMAQUOTE
: 0,
1846 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
1851 q_status_message1(SM_ORDER
, 0, 3,
1852 _("Can't add %s to list"), _(empty_val
));
1853 rv
= ps
->mangled_body
= 0;
1856 fs_give((void **)<mp
);
1859 q_status_message1(SM_ORDER
, 0, 3,
1860 _("Can't add %s to list"), _(empty_val
));
1864 if(flags
&CF_NUMBER
&& sval
[0]
1865 && !(isdigit((unsigned char)sval
[0])
1866 || sval
[0] == '-' || sval
[0] == '+')){
1867 q_status_message(SM_ORDER
,3,3,
1868 _("Entry must be numeric"));
1869 i
= 3; /* to keep loop going */
1874 fs_give((void **)apval
);
1876 if(!(olddefval
&& !strcmp(sval
, olddefval
))
1877 || ((*cl
)->var
== &ps
->vars
[V_POST_CHAR_SET
])
1878 || want_to(_("Leave unset and use default "),
1879 'y', 'y', NO_HELP
, WT_FLUSH_IN
) == 'n')
1880 *apval
= cpystr(sval
);
1882 newval
= &(*cl
)->value
;
1886 cmd_cancelled("Add");
1889 help
= help
== NO_HELP
? h_config_add
: NO_HELP
;
1892 else if(i
== 4){ /* no redraw, yet */
1895 else if(i
== 5){ /* change from/to prepend to/from append */
1898 after
= after
? 0 : 1;
1899 strncpy(tmpval
, (*cl
)->value
, sizeof(tmpval
));
1900 tmpval
[sizeof(tmpval
)-1] = '\0';
1901 removing_trailing_white_space(tmpval
);
1902 /* 33 is the number of chars other than the value */
1903 maxwidth
= MIN(80, ps
->ttyo
->screen_cols
) - 15;
1904 k
= MIN(18, MAX(maxwidth
-33,0));
1905 if(utf8_width(tmpval
) > k
&& k
>= 3){
1906 (void) utf8_truncate(tmpval
, k
-3);
1907 strncat(tmpval
, "...", sizeof(tmpval
)-strlen(tmpval
)-1);
1908 tmpval
[sizeof(tmpval
)-1] = '\0';
1912 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert after \"%.*s\": "), k
, tmpval
);
1914 snprintf(prompt
, sizeof(prompt
), _("Enter text to insert before \"%.*s\": "), k
, tmpval
);
1918 else if(i
== ctrl('P')){
1920 numval
= atoi(sval
);
1923 numval
= atoi(pval
);
1925 numval
= lowrange
+ 1;
1928 if(numval
== lowrange
){
1930 * Protect user from repeating arrow key that
1931 * causes message to appear over and over.
1933 if(++repeat_key
> 0){
1934 q_status_message1(SM_ORDER
,3,3,
1935 _("Minimum value is %s"), comatose(lowrange
));
1942 numval
= MAX(numval
- incr
, lowrange
);
1943 snprintf(sval
, oebufsize
, "%d", numval
);
1944 sval
[oebufsize
-1] = '\0';
1947 else if(i
== ctrl('N')){
1949 numval
= atoi(sval
);
1952 numval
= atoi(pval
);
1954 numval
= lowrange
+ 1;
1957 if(numval
== hirange
){
1958 if(++repeat_key
> 0){
1959 q_status_message1(SM_ORDER
,3,3,
1960 _("Maximum value is %s"), comatose(hirange
));
1967 numval
= MIN(numval
+ incr
, hirange
);
1968 snprintf(sval
, oebufsize
, "%d", numval
);
1969 sval
[oebufsize
-1] = '\0';
1979 case MC_DELETE
: /* delete */
1981 if(!(*cl
)->var
->is_list
1983 && (*cl
)->var
->current_val
.p
){
1986 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
1987 pmt
[sizeof(pmt
)-1] = '\0';
1988 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
1990 *apval
= cpystr(sval
);
1991 newval
= &(*cl
)->value
;
1992 rv
= ps
->mangled_footer
= 1;
1995 else if((*cl
)->var
->is_list
1997 && (*cl
)->var
->current_val
.l
){
2000 snprintf(pmt
, sizeof(pmt
), _("Override default with %s"), _(empty_val2
));
2001 pmt
[sizeof(pmt
)-1] = '\0';
2002 if(want_to(pmt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2006 ltmp
= (char **)fs_get(2 * sizeof(char *));
2007 ltmp
[0] = cpystr(sval
);
2009 config_add_list(ps
, cl
, ltmp
, &newval
, 0);
2010 fs_give((void **)<mp
);
2011 rv
= ps
->mangled_body
= 1;
2014 else if(((*cl
)->var
->is_list
&& !lval
)
2015 || (!(*cl
)->var
->is_list
&& !pval
)){
2016 q_status_message(SM_ORDER
, 0, 3, _("No set value to delete"));
2019 if((*cl
)->var
->is_fixed
)
2020 snprintf(prompt
, sizeof(prompt
), _("Delete (unused) %s from %s "),
2022 ? (!*lval
[(*cl
)->varmem
])
2024 : lval
[(*cl
)->varmem
]
2032 snprintf(prompt
, sizeof(prompt
), _("Really delete %s%s from %s "),
2033 (*cl
)->var
->is_list
? "item " : "",
2035 ? int2string((*cl
)->varmem
+ 1)
2043 prompt
[sizeof(prompt
)-1] = '\0';
2046 ps
->mangled_footer
= 1;
2047 if(want_to(prompt
, 'n', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2049 if((*cl
)->var
->is_list
)
2050 ps
->mangled_body
= 1;
2052 ps
->mangled_footer
= 1;
2054 if((*cl
)->var
->is_list
){
2055 if(lval
[(*cl
)->varmem
])
2056 fs_give((void **)&lval
[(*cl
)->varmem
]);
2058 config_del_list_item(cl
, &newval
);
2062 fs_give((void **)apval
);
2064 newval
= &(*cl
)->value
;
2068 q_status_message(SM_ORDER
, 0, 3, _("Value not deleted"));
2073 case MC_EDIT
: /* edit/change list option */
2074 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2077 else if(((*cl
)->var
->is_list
2079 && (*cl
)->var
->current_val
.l
)
2081 (!(*cl
)->var
->is_list
2083 && (*cl
)->var
->current_val
.p
)){
2086 * In non-list case, offer default value for editing.
2088 if(!(*cl
)->var
->is_list
2089 && (*cl
)->var
!= &ps
->vars
[V_REPLY_INTRO
]
2090 && (*cl
)->var
->current_val
.p
[0]
2091 && strcmp(VSTRING
,(*cl
)->var
->current_val
.p
)){
2095 olddefval
= (char *) fs_get(strlen((*cl
)->var
->current_val
.p
)+3);
2097 if(!strncmp((*cl
)->var
->current_val
.p
,
2099 (len
=strlen(DSTRING
)))){
2100 /* strip DSTRING and trailing paren */
2101 strncpy(olddefval
, (*cl
)->var
->current_val
.p
+len
,
2102 strlen((*cl
)->var
->current_val
.p
)-len
-1);
2103 olddefval
[strlen((*cl
)->var
->current_val
.p
)-len
-1] = '\0';
2106 /* quote it if there are trailing spaces */
2107 quote_it
= ((*cl
)->var
->current_val
.p
[strlen((*cl
)->var
->current_val
.p
)-1] == SPACE
);
2108 snprintf(olddefval
, strlen((*cl
)->var
->current_val
.p
)+3, "%s%s%s", quote_it
? "\"" : "", (*cl
)->var
->current_val
.p
, quote_it
? "\"" : "");
2111 olddefval
[strlen((*cl
)->var
->current_val
.p
)+3-1] = '\0';
2116 else if(((*cl
)->var
->is_list
2118 && !(*cl
)->var
->current_val
.l
)
2120 (!(*cl
)->var
->is_list
2122 && !(*cl
)->var
->current_val
.p
)){
2130 fs_give((void **)&sval
);
2131 if((*cl
)->var
->is_list
){
2132 snprintf(prompt
, sizeof(prompt
), _("Change field %s list entry : "),
2134 prompt
[sizeof(prompt
)-1] = '\0';
2135 clptr
= lval
[(*cl
)->varmem
] ? lval
[(*cl
)->varmem
] : NULL
;
2138 if(flags
& CF_NUMBER
)
2139 snprintf(prompt
, sizeof(prompt
), _("Change numeric field %s value : "), (*cl
)->var
->name
);
2141 snprintf(prompt
, sizeof(prompt
), _("Change field %s value : "), (*cl
)->var
->name
);
2143 clptr
= pval
? pval
: NULL
;
2146 oebufsize
= clptr
? (int) MAX(MAXPATH
, 50+strlen(clptr
)) : MAXPATH
;
2147 sval
= (char *) fs_get(oebufsize
* sizeof(char));
2148 snprintf(sval
, oebufsize
, "%s", clptr
? clptr
: "");
2149 sval
[oebufsize
-1] = '\0';
2151 ps
->mangled_footer
= 1;
2154 if(!(flags
&CF_NUMBER
))
2157 oeflags
= OE_APPEND_CURRENT
;
2158 i
= optionally_enter(sval
, -FOOTER_ROWS(ps
), 0, oebufsize
,
2160 (ekey
[0].ch
!= -1) ? ekey
: NULL
,
2163 removing_leading_and_trailing_white_space(sval
);
2165 * Coerce "" and <Empty Value> to empty string input.
2166 * Catch <No Value Set> as a substitute for deleting.
2168 if((*sval
== '\"' && *(sval
+1) == '\"' && *(sval
+2) == '\0')
2169 || !struncmp(sval
, _(empty_val
), strlen(_(empty_val
)))
2171 && !struncmp(sval
+1, _(empty_val
), strlen(_(empty_val
)))))
2173 else if(!struncmp(sval
, _(no_val
), strlen(_(no_val
)))
2175 && !struncmp(sval
+1, _(no_val
), strlen(_(no_val
)))))
2179 if((*cl
)->var
->is_list
)
2180 ps
->mangled_body
= 1;
2182 ps
->mangled_footer
= 1;
2184 if((*cl
)->var
->is_list
){
2188 if(lval
[(*cl
)->varmem
])
2189 fs_give((void **)&lval
[(*cl
)->varmem
]);
2192 for(tmp
= sval
; *tmp
; tmp
++)
2194 i
++; /* conservative count of ,'s */
2197 ltmp
= parse_list(sval
, i
+ 1,
2199 ? PL_COMMAQUOTE
: 0,
2202 if(ltmp
&& !ltmp
[0]) /* only commas */
2204 else if(!i
|| (ltmp
&& !ltmp
[1])){ /* only one item */
2205 lval
[(*cl
)->varmem
] = cpystr(sval
);
2206 newval
= &(*cl
)->value
;
2209 fs_give((void **)<mp
[0]);
2213 * Looks like the value was changed to a
2214 * list, so delete old value, and insert
2217 * If more than one item in existing list and
2218 * current is end of existing list, then we
2219 * have to delete and append instead of
2220 * deleting and prepending.
2222 if(((*cl
)->varmem
> 0 || lval
[1])
2223 && !(lval
[(*cl
)->varmem
+1])){
2228 config_del_list_item(cl
, &newval
);
2229 config_add_list(ps
, cl
, ltmp
, &newval
, after
);
2233 fs_give((void **)<mp
);
2236 if(flags
&CF_NUMBER
&& sval
[0]
2237 && !(isdigit((unsigned char)sval
[0])
2238 || sval
[0] == '-' || sval
[0] == '+')){
2239 q_status_message(SM_ORDER
,3,3,
2240 _("Entry must be numeric"));
2245 fs_give((void **)apval
);
2247 if(sval
[0] && apval
)
2248 *apval
= cpystr(sval
);
2250 newval
= &(*cl
)->value
;
2254 cmd_cancelled("Change");
2257 help
= help
== NO_HELP
? h_config_change
: NO_HELP
;
2260 else if(i
== 4){ /* no redraw, yet */
2263 else if(i
== ctrl('P')){
2264 numval
= atoi(sval
);
2265 if(numval
== lowrange
){
2267 * Protect user from repeating arrow key that
2268 * causes message to appear over and over.
2270 if(++repeat_key
> 0){
2271 q_status_message1(SM_ORDER
,3,3,
2272 _("Minimum value is %s"), comatose(lowrange
));
2279 numval
= MAX(numval
- incr
, lowrange
);
2280 snprintf(sval
, oebufsize
, "%d", numval
);
2281 sval
[oebufsize
-1] = '\0';
2284 else if(i
== ctrl('N')){
2285 numval
= atoi(sval
);
2286 if(numval
== hirange
){
2287 if(++repeat_key
> 0){
2288 q_status_message1(SM_ORDER
,3,3,
2289 _("Maximum value is %s"), comatose(hirange
));
2296 numval
= MIN(numval
+ incr
, hirange
);
2297 snprintf(sval
, oebufsize
, "%d", numval
);
2298 sval
[oebufsize
-1] = '\0';
2309 if(!((*cl
)->var
&& (*cl
)->var
->is_list
)){
2310 q_status_message(SM_ORDER
, 0, 2,
2311 _("Can't shuffle single-valued setting"));
2318 curindex
= (*cl
)->varmem
;
2319 previndex
= curindex
-1;
2320 nextindex
= curindex
+1;
2321 if(!*alval
|| !(*alval
)[nextindex
])
2324 if((previndex
< 0 && nextindex
< 0) || !*alval
){
2325 q_status_message(SM_ORDER
, 0, 3,
2326 _("Shuffle only makes sense when there is more than one value defined"));
2330 /* Move it up or down? */
2335 ekey
[i
++].label
= N_("Up");
2340 ekey
[i
++].label
= N_("Down");
2345 if(previndex
< 0){ /* no up */
2349 else if(nextindex
< 0)
2350 ekey
[1].ch
= -2; /* no down */
2352 snprintf(prompt
, sizeof(prompt
), "Shuffle %s%s%s ? ",
2353 (ekey
[0].ch
!= -2) ? "UP" : "",
2354 (ekey
[0].ch
!= -2 && ekey
[1].ch
!= -2) ? " or " : "",
2355 (ekey
[1].ch
!= -2) ? "DOWN" : "");
2356 help
= (ekey
[0].ch
== -2) ? h_hdrcolor_shuf_down
2357 : (ekey
[1].ch
== -2) ? h_hdrcolor_shuf_up
2359 prompt
[sizeof(prompt
)-1] = '\0';
2361 i
= radio_buttons(prompt
, -FOOTER_ROWS(ps
), ekey
, deefault
, 'x',
2366 cmd_cancelled("Shuffle");
2376 swap_val
= (*alval
)[curindex
];
2377 (*alval
)[curindex
] = (*alval
)[nextindex
];
2378 (*alval
)[nextindex
] = swap_val
;
2381 swap_val
= (*alval
)[curindex
];
2382 (*alval
)[curindex
] = (*alval
)[previndex
];
2383 (*alval
)[previndex
] = swap_val
;
2385 else /* can't happen */
2389 * Fix the conf line values.
2393 fs_give((void **)&(*cl
)->value
);
2395 (*cl
)->value
= pretty_value(ps
, *cl
);
2398 if((*cl
)->next
->value
)
2399 fs_give((void **)&(*cl
)->next
->value
);
2401 (*cl
)->next
->value
= pretty_value(ps
, (*cl
)->next
);
2402 *cl
= next_confline(*cl
);
2405 if((*cl
)->prev
->value
)
2406 fs_give((void **)&(*cl
)->prev
->value
);
2408 (*cl
)->prev
->value
= pretty_value(ps
, (*cl
)->prev
);
2409 *cl
= prev_confline(*cl
);
2412 rv
= ps
->mangled_body
= 1;
2415 case MC_EXIT
: /* exit */
2416 rv
= config_exit_cmd(flags
);
2425 *cl
= next_confline(*cl
);
2428 * At this point, if changes occurred, var->user_val.X is set.
2429 * So, fix the current_val, and handle special cases...
2431 * NOTE: we don't worry about the "fixed variable" case here, because
2432 * editing such vars should have been prevented above...
2436 * Now go and set the current_val based on user_val changes
2437 * above. Turn off command line settings...
2439 set_current_val((*cl
)->var
, TRUE
, FALSE
);
2440 fix_side_effects(ps
, (*cl
)->var
, 0);
2443 * Delay setting the displayed value until "var.current_val" is set
2444 * in case current val get's changed due to a special case above.
2448 fs_give((void **) newval
);
2450 *newval
= pretty_value(ps
, *cl
);
2453 exception_override_warning((*cl
)->var
);
2457 fs_give((void **) &sval
);
2460 fs_give((void **) &olddefval
);
2467 config_exit_cmd(unsigned int flags
)
2469 return(screen_exit_cmd(flags
, "Configuration"));
2474 simple_exit_cmd(unsigned int flags
)
2481 * screen_exit_cmd - basic config/flag screen exit logic
2484 screen_exit_cmd(unsigned int flags
, char *cmd
)
2486 if(flags
& CF_CHANGES
){
2487 switch(want_to(EXIT_PMT
, 'y', 'x', h_config_undo
, WT_FLUSH_IN
)){
2489 q_status_message1(SM_ORDER
,0,3,"%s changes saved", cmd
);
2493 q_status_message1(SM_ORDER
,3,5,"No %s changes saved", cmd
);
2498 q_status_message(SM_ORDER
,3,5,"Changes not yet saved");
2511 config_add_list(struct pine
*ps
, CONF_S
**cl
, char **ltmp
, char ***newval
, int after
)
2514 char *tmp
, ***alval
;
2517 for(items
= 0, i
= 0; ltmp
[i
]; i
++) /* count list items */
2520 alval
= ALVAL((*cl
)->var
, ew
);
2522 if(alval
&& (*alval
)){
2523 if((*alval
)[0] && (*alval
)[0][0]){
2525 * Since we were already a list, make room
2526 * for the new member[s] and fall thru to
2527 * actually fill them in below...
2529 for(i
= 0; (*alval
)[i
]; i
++)
2532 fs_resize((void **)alval
, (i
+ items
+ 1) * sizeof(char *));
2535 * move the ones that will be bumped down to the bottom of the list
2537 for(; i
>= (*cl
)->varmem
+ (after
?1:0); i
--)
2538 (*alval
)[i
+items
] = (*alval
)[i
];
2545 free_list_array(alval
);
2547 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2548 memset((void *)(*alval
), 0, (items
+1)*sizeof(char *));
2549 (*alval
)[0] = ltmp
[0];
2551 *newval
= &(*cl
)->value
;
2554 fs_give((void **)&(*cl
)->value
);
2561 * since we were previously empty, we want
2562 * to replace the first CONF_S's value with
2563 * the first new value, and fill the other
2564 * in below if there's a list...
2566 * first, make sure we're at the beginning of this config
2567 * section and dump the config lines for the default list,
2568 * except for the first one, which we will over-write.
2570 *cl
= (*cl
)->varnamep
;
2571 while((*cl
)->next
&& (*cl
)->next
->varnamep
== (*cl
)->varnamep
)
2572 snip_confline(&(*cl
)->next
);
2575 * now allocate the new user_val array and fill in the first entry.
2577 *alval
= (char **)fs_get((items
+1)*sizeof(char *));
2578 memset((void *)(*alval
), 0, (items
+1) * sizeof(char *));
2579 (*alval
)[(*cl
)->varmem
=0] = ltmp
[0];
2581 *newval
= &(*cl
)->value
;
2584 fs_give((void **)&(*cl
)->value
);
2590 * Make new cl's to fit in the new space. Move the value from the current
2591 * line if inserting before it, else leave it where it is.
2593 for(; i
< items
; i
++){
2594 (*alval
)[i
+(*cl
)->varmem
+ (after
?1:0)] = ltmp
[i
];
2598 (*cl
)->value
= NULL
;
2602 (*cl
)->var
= (*cl
)->prev
->var
;
2603 (*cl
)->valoffset
= (*cl
)->prev
->valoffset
;
2604 (*cl
)->varoffset
= (*cl
)->prev
->varoffset
;
2605 (*cl
)->headingp
= (*cl
)->prev
->headingp
;
2606 (*cl
)->keymenu
= (*cl
)->prev
->keymenu
;
2607 (*cl
)->help
= (*cl
)->prev
->help
;
2608 (*cl
)->tool
= (*cl
)->prev
->tool
;
2609 (*cl
)->varnamep
= (*cl
)->prev
->varnamep
;
2612 (*cl
)->value
= NULL
;
2616 *newval
= &(*cl
)->next
->value
;
2618 *newval
= &(*cl
)->value
;
2623 * now fix up varmem values and fill in new values that have been
2626 for(ctmp
= (*cl
)->varnamep
, i
= 0;
2628 ctmp
= ctmp
->next
, i
++){
2631 /* BUG: We should be able to do this without the temp
2634 char *ptmp
= pretty_value(ps
, ctmp
);
2635 ctmp
->value
= (ctmp
->varnamep
->flags
& CF_PRINTER
) ? printer_name(ptmp
) : cpystr(ptmp
);
2636 fs_give((void **)&ptmp
);
2646 config_del_list_item(CONF_S
**cl
, char ***newval
)
2648 char **bufp
, ***alval
;
2652 alval
= ALVAL((*cl
)->var
, ew
);
2654 if((*alval
)[(*cl
)->varmem
+ 1]){
2655 for(bufp
= &(*alval
)[(*cl
)->varmem
];
2656 (*bufp
= *(bufp
+1)) != NULL
; bufp
++)
2659 if(*cl
== (*cl
)->varnamep
){ /* leading value */
2661 fs_give((void **)&(*cl
)->value
);
2664 (*cl
)->value
= ctmp
->value
;
2668 ctmp
= *cl
; /* blast the confline */
2670 if(ctmp
== opt_screen
->top_line
)
2671 opt_screen
->top_line
= *cl
;
2674 snip_confline(&ctmp
);
2676 for(ctmp
= (*cl
)->varnamep
, i
= 0; /* now fix up varmem values */
2678 ctmp
= ctmp
->next
, i
++)
2681 else if((*cl
)->varmem
){ /* blasted last in list */
2684 if(ctmp
== opt_screen
->top_line
)
2685 opt_screen
->top_line
= *cl
;
2687 snip_confline(&ctmp
);
2689 else{ /* blasted last remaining */
2691 fs_give((void **)alval
);
2693 *newval
= &(*cl
)->value
;
2699 * feature list manipulation tool
2702 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
2705 checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2710 case MC_TOGGLE
: /* mark/unmark feature */
2711 if((*cl
)->var
== &ps
->vars
[V_FEATURE_LIST
]){
2713 toggle_feature_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, *cl
, 0);
2716 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2717 "Programmer botch! Unknown checkbox type.");
2721 case MC_EXIT
: /* exit */
2722 rv
= config_exit_cmd(flags
);
2735 * simple radio-button style variable handler
2738 radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2742 NAMEVAL_S
*rule
= NULL
;
2748 apval
= APVAL((*cl
)->var
, ew
);
2751 case MC_CHOICE
: /* set/unset feature */
2753 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2754 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
2755 && want_to(_("Delete old unused personal option setting"),
2756 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2757 delete_user_vals((*cl
)->var
);
2758 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
2765 if(standard_radio_var(ps
, (*cl
)->var
) || (*cl
)->var
== startup_ptr
){
2766 PTR_TO_RULEFUNC rulefunc
;
2769 if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2770 old_uc
= pico_usingcolor();
2771 old_cs
= ps
->color_style
;
2775 if((*cl
)->var
->cmdline_val
.p
)
2776 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2779 fs_give((void **)apval
);
2781 rulefunc
= rulefunc_from_var(ps
, (*cl
)->var
);
2783 rule
= (*rulefunc
)((*cl
)->varmem
);
2786 *apval
= cpystr(S_OR_L(rule
));
2788 cur_rule_value((*cl
)->var
, TRUE
, TRUE
);
2789 set_radio_pretty_vals(ps
, cl
);
2791 if((*cl
)->var
== &ps
->vars
[V_AB_SORT_RULE
])
2792 addrbook_redo_sorts();
2793 else if((*cl
)->var
== &ps
->vars
[V_THREAD_DISP_STYLE
]){
2794 clear_index_cache(ps
->mail_stream
, 0);
2796 else if((*cl
)->var
== &ps
->vars
[V_THREAD_INDEX_STYLE
]){
2800 clear_index_cache(ps
->mail_stream
, 0);
2801 /* clear all hidden and collapsed flags */
2802 set_lflags(ps
->mail_stream
, ps
->msgmap
, MN_COLL
| MN_CHID
, 0);
2805 && SORT_IS_THREADED(ps
->msgmap
)
2806 && unview_thread(ps
, ps
->mail_stream
, ps
->msgmap
)){
2807 ps
->next_screen
= mail_index_screen
;
2808 ps
->view_skipped_index
= 0;
2809 ps
->mangled_screen
= 1;
2812 if(SORT_IS_THREADED(ps
->msgmap
)
2813 && (SEP_THRDINDX() || COLL_THRDS()))
2814 collapse_threads(ps
->mail_stream
, ps
->msgmap
, NULL
);
2816 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
2817 m
= ps_global
->s_pool
.streams
[i
];
2819 sp_set_viewing_a_thread(m
, 0);
2822 adjust_cur_to_visible(ps
->mail_stream
, ps
->msgmap
);
2825 else if((*cl
)->var
== &ps
->vars
[V_COLOR_STYLE
]){
2826 if(old_cs
!= ps
->color_style
){
2827 pico_toggle_color(0);
2828 switch(ps
->color_style
){
2831 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
2834 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
2837 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
2840 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
2844 if(ps
->color_style
!= COL_NONE
)
2845 pico_toggle_color(1);
2848 if(pico_usingcolor())
2849 pico_set_normal_color();
2851 if(!old_uc
&& pico_usingcolor()){
2854 * remove the explanatory warning line and a blank line
2857 /* first find the first blank line */
2858 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2859 if(ctmp
->flags
& CF_NOSELECT
)
2862 if(ctmp
&& ctmp
->flags
& CF_NOSELECT
&&
2863 ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
) &&
2864 ctmp
->next
&& ctmp
->next
->flags
& CF_NOSELECT
&&
2866 ctmp
->next
->next
->flags
& CF_NOSELECT
){
2867 ctmp
->prev
->next
= ctmp
->next
->next
;
2868 ctmp
->next
->next
->prev
= ctmp
->prev
;
2869 ctmp
->next
->next
= NULL
;
2870 free_conflines(&ctmp
);
2873 /* make all the colors selectable */
2874 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2875 if(ctmp
->flags
& CF_POT_SLCTBL
)
2876 ctmp
->flags
&= ~CF_NOSELECT
;
2878 else if(old_uc
&& !pico_usingcolor()){
2881 * add the explanatory warning line and a blank line
2884 /* first find the existing blank line */
2885 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2886 if(ctmp
->flags
& CF_NOSELECT
)
2889 /* add the explanatory warning line */
2890 new_confline(&ctmp
);
2891 ctmp
->help
= NO_HELP
;
2892 ctmp
->flags
|= CF_NOSELECT
;
2893 ctmp
->value
= cpystr(COLORNOSET
);
2895 /* and add another blank line */
2896 new_confline(&ctmp
);
2897 ctmp
->flags
|= (CF_NOSELECT
| CF_B_LINE
);
2899 /* make all the colors non-selectable */
2900 for(ctmp
= *cl
; ctmp
; ctmp
= next_confline(ctmp
))
2901 if(ctmp
->flags
& CF_POT_SLCTBL
)
2902 ctmp
->flags
|= CF_NOSELECT
;
2905 clear_index_cache(ps
->mail_stream
, 0);
2907 ps
->mangled_screen
= 1;
2911 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2914 else if((*cl
)->var
== &ps
->vars
[V_SORT_KEY
]){
2918 def_sort_rev
= (*cl
)->varmem
>= (short) EndofList
;
2919 def_sort
= (SortOrder
) ((*cl
)->varmem
- (def_sort_rev
2921 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def_sort
),
2922 (def_sort_rev
) ? "/Reverse" : "");
2924 if((*cl
)->var
->cmdline_val
.p
)
2925 fs_give((void **)&(*cl
)->var
->cmdline_val
.p
);
2929 fs_give((void **)apval
);
2931 *apval
= cpystr(tmp_20k_buf
);
2934 set_current_val((*cl
)->var
, TRUE
, TRUE
);
2935 if(decode_sort(ps
->VAR_SORT_KEY
, &def_sort
, &def_sort_rev
) != -1){
2936 ps
->def_sort
= def_sort
;
2937 ps
->def_sort_rev
= def_sort_rev
;
2940 set_radio_pretty_vals(ps
, cl
);
2941 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
2945 q_status_message(SM_ORDER
| SM_DING
, 3, 6,
2946 "Programmer botch! Unknown radiobutton type.");
2950 case MC_EXIT
: /* exit */
2951 rv
= config_exit_cmd(flags
);
2960 exception_override_warning((*cl
)->var
);
2967 * simple yes/no style variable handler
2970 yesno_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2972 int rv
= 0, yes
= 0;
2973 char *pval
, **apval
;
2975 pval
= PVAL((*cl
)->var
, ew
);
2976 apval
= APVAL((*cl
)->var
, ew
);
2979 case MC_TOGGLE
: /* toggle yes to no and back */
2980 if(fixed_var((*cl
)->var
, NULL
, NULL
)){
2981 if(((*cl
)->var
->post_user_val
.p
|| (*cl
)->var
->main_user_val
.p
)
2982 && want_to(_("Delete old unused personal option setting"),
2983 'y', 'n', NO_HELP
, WT_FLUSH_IN
) == 'y'){
2984 delete_user_vals((*cl
)->var
);
2985 q_status_message(SM_ORDER
, 0, 3, _("Deleted"));
2993 yes
= ((pval
&& !strucmp(pval
, yesstr
)) ||
2994 (!pval
&& (*cl
)->var
->current_val
.p
&&
2995 !strucmp((*cl
)->var
->current_val
.p
, yesstr
)));
2996 fs_give((void **)&(*cl
)->value
);
3000 fs_give((void **)apval
);
3003 *apval
= cpystr(nostr
);
3005 *apval
= cpystr(yesstr
);
3008 set_current_val((*cl
)->var
, FALSE
, FALSE
);
3010 fs_give((void **)&(*cl
)->value
);
3012 (*cl
)->value
= pretty_value(ps
, *cl
);
3013 fix_side_effects(ps
, (*cl
)->var
, 0);
3017 case MC_EXIT
: /* exit */
3018 rv
= config_exit_cmd(flags
);
3031 * Manage display of the config/options menu body.
3034 update_option_screen(struct pine
*ps
, OPT_SCREEN_S
*screen
, Pos
*cursor_pos
)
3036 int dline
, w
, save
= '\0';
3037 CONF_S
*top_line
, *ctmp
;
3040 int want_width
, first_width
;
3041 char *saveptr
= NULL
;
3044 int last_selectable
;
3045 mswin_beginupdate();
3047 if(screen
== NULL
|| BODY_LINES(ps
) < 1)
3050 opt_screen
= screen
;
3053 cursor_pos
->col
= 0;
3054 cursor_pos
->row
= -1; /* to tell us if we've set it yet */
3058 * calculate top line of display for reframing if the current field
3059 * is off the display defined by screen->top_line...
3061 if((ctmp
= screen
->top_line
) != NULL
)
3062 for(dline
= BODY_LINES(ps
);
3063 dline
&& ctmp
&& ctmp
!= screen
->current
;
3064 ctmp
= next_confline(ctmp
), dline
--)
3067 if(!ctmp
|| !dline
){ /* force reframing */
3069 ctmp
= top_line
= first_confline(screen
->current
);
3071 if(((dline
++)%BODY_LINES(ps
)) == 0)
3073 while(ctmp
!= screen
->current
&& (ctmp
= next_confline(ctmp
)));
3076 top_line
= screen
->top_line
;
3080 * Figure out how far down the top line is from the top and how many
3081 * total lines there are. Dumb to loop every time thru, but
3082 * there aren't that many lines, and it's cheaper than rewriting things
3083 * to maintain a line count in each structure...
3085 for(dline
= 0, ctmp
= prev_confline(top_line
); ctmp
; ctmp
= prev_confline(ctmp
))
3088 scroll_setpos(dline
);
3089 last_selectable
= dline
;
3090 for(ctmp
= next_confline(top_line
); ctmp
; ctmp
= next_confline(ctmp
)){
3092 if (!(ctmp
->flags
& CF_NOSELECT
))
3093 last_selectable
= dline
;
3095 dline
= last_selectable
;
3096 scroll_setrange(BODY_LINES(ps
), dline
);
3099 /* mangled body or new page, force redraw */
3100 if(ps
->mangled_body
|| screen
->top_line
!= top_line
)
3101 screen
->prev
= NULL
;
3103 /* loop thru painting what's needed */
3104 for(dline
= 0, ctmp
= top_line
;
3105 dline
< BODY_LINES(ps
);
3106 dline
++, ctmp
= next_confline(ctmp
)){
3109 * only fall thru painting if something needs painting...
3111 if(!(!screen
->prev
|| ctmp
== screen
->prev
|| ctmp
== screen
->current
3112 || ctmp
== screen
->prev
->varnamep
3113 || ctmp
== screen
->current
->varnamep
3114 || ctmp
== screen
->prev
->headingp
3115 || ctmp
== screen
->current
->headingp
))
3118 ClearLine(dline
+ HEADER_ROWS(ps
));
3121 if(ctmp
->flags
& CF_B_LINE
)
3124 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3125 if(ctmp
== screen
->current
&& cursor_pos
)
3126 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3128 if((ctmp
== screen
->current
3129 || ctmp
== screen
->current
->varnamep
3130 || ctmp
== screen
->current
->headingp
)
3131 && !(ctmp
->flags
& CF_NOHILITE
))
3134 if(ctmp
->flags
& CF_H_LINE
){
3135 MoveCursor(dline
+ HEADER_ROWS(ps
), 0);
3136 Write_to_screen(repeat_char(ps
->ttyo
->screen_cols
, '-'));
3139 if(ctmp
->flags
& CF_CENTERED
){
3140 int offset
= ps
->ttyo
->screen_cols
/2
3141 - (utf8_width(ctmp
->varname
)/2);
3142 MoveCursor(dline
+ HEADER_ROWS(ps
),
3143 (offset
> 0) ? offset
: 0);
3145 else if(ctmp
->varoffset
)
3146 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->varoffset
);
3148 Write_to_screen(ctmp
->varname
);
3149 if((ctmp
== screen
->current
3150 || ctmp
== screen
->current
->varnamep
3151 || ctmp
== screen
->current
->headingp
)
3152 && !(ctmp
->flags
& CF_NOHILITE
))
3156 value
= (ctmp
->flags
& CF_INHERIT
) ? INHERIT
: ctmp
->value
;
3162 memset(tmp_20k_buf
, '\0',
3163 (6*ps
->ttyo
->screen_cols
+ 1) * sizeof(char));
3164 if(ctmp
== screen
->current
){
3165 if(!(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
))
3169 cursor_pos
->row
= dline
+ HEADER_ROWS(ps
);
3172 if(ctmp
->flags
& CF_H_LINE
)
3173 memset(tmp_20k_buf
, '-',
3174 ps
->ttyo
->screen_cols
* sizeof(char));
3176 if(ctmp
->flags
& CF_CENTERED
){
3177 int offset
= ps
->ttyo
->screen_cols
/2
3178 - (utf8_width(value
)/2);
3179 /* BUG: tabs screw us figuring length above */
3183 p
= tmp_20k_buf
+ offset
;
3184 if(!*(q
= tmp_20k_buf
))
3193 * Copy the value to a temp buffer expanding tabs, and
3194 * making sure not to write beyond screen right...
3196 for(i
= 0, j
= ctmp
->valoffset
; value
[i
]; i
++){
3197 if(value
[i
] == ctrl('I')){
3200 while((++j
) & 0x07);
3208 if(ctmp
== screen
->current
&& cursor_pos
){
3209 if(ctmp
->flags
& CF_DOUBLEVAR
&& ctmp
->flags
& CF_VAR2
)
3210 cursor_pos
->col
= ctmp
->val2offset
;
3212 cursor_pos
->col
= ctmp
->valoffset
;
3214 if(ctmp
->tool
== radiobutton_tool
3216 || ctmp
->tool
==ldap_radiobutton_tool
3218 || ctmp
->tool
==role_radiobutton_tool
3219 || ctmp
->tool
==checkbox_tool
3220 || (ctmp
->tool
==color_setting_tool
&&
3221 ctmp
->valoffset
!= COLOR_INDENT
))
3225 if(ctmp
->flags
& CF_DOUBLEVAR
){
3229 first_width
= ctmp
->val2offset
- ctmp
->valoffset
- SPACE_BETWEEN_DOUBLEVARS
;
3230 if((l
=utf8_width(p
)) > first_width
&& first_width
>= 0){
3231 saveptr
= utf8_count_forw_width(p
, first_width
, &got_width
);
3233 * got_width != first_width indicates there's a problem
3234 * that should not happen. Ignore it.
3245 * If this is a COLOR_BLOB line we do special coloring.
3246 * The current object inverse hilite is only on the
3247 * checkbox part, the exact format comes from the
3248 * new_color_line function. If we change that we'll have
3249 * to change this to get the coloring right.
3251 if(p
[0] == '(' && p
[2] == ')' &&
3252 p
[3] == ' ' && p
[4] == ' ' &&
3253 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3254 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3255 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3256 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3258 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
);
3259 Write_to_screen_n(p
, 3);
3260 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3263 Write_to_screen_n(p
+3, 3);
3264 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3265 colorx(CFC_ICOLOR(ctmp
)));
3267 lastc
= pico_get_cur_color();
3268 (void)pico_set_colorp(newc
, PSC_NONE
);
3269 free_color_pair(&newc
);
3272 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3275 (void)pico_set_colorp(lastc
, PSC_NONE
);
3276 free_color_pair(&lastc
);
3279 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3282 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, p
);
3283 if(!(ctmp
->flags
& CF_VAR2
) && ctmp
== screen
->current
)
3290 PutLine0(dline
+HEADER_ROWS(ps
),
3291 ctmp
->val2offset
- SPACE_BETWEEN_DOUBLEVARS
,
3292 repeat_char(SPACE_BETWEEN_DOUBLEVARS
, SPACE
));
3294 if(l
> ctmp
->val2offset
- ctmp
->valoffset
&& ctmp
->val2offset
- ctmp
->valoffset
>= 0)
3295 p
= saveptr
+ SPACE_BETWEEN_DOUBLEVARS
;
3297 if(p
> tmp_20k_buf
){
3298 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3301 if(p
[0] == '(' && p
[2] == ')' &&
3302 p
[3] == ' ' && p
[4] == ' ' &&
3303 (!strncmp(p
+5, COLOR_BLOB
, COLOR_BLOB_LEN
)
3304 || !strncmp(p
+5, COLOR_BLOB_TRAN
, COLOR_BLOB_LEN
)
3305 || !strncmp(p
+5, COLOR_BLOB_NORM
, COLOR_BLOB_LEN
))){
3306 COLOR_PAIR
*lastc
= NULL
, *newc
= NULL
;
3308 MoveCursor(dline
+HEADER_ROWS(ps
), ctmp
->val2offset
);
3309 Write_to_screen_n(p
, 3);
3310 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3313 Write_to_screen_n(p
+3, 3);
3314 newc
= new_color_pair(colorx(CFC_ICOLOR(ctmp
)),
3315 colorx(CFC_ICOLOR(ctmp
)));
3317 lastc
= pico_get_cur_color();
3318 (void)pico_set_colorp(newc
, PSC_NONE
);
3319 free_color_pair(&newc
);
3322 Write_to_screen_n(p
+6, COLOR_BLOB_LEN
-2);
3325 (void)pico_set_colorp(lastc
, PSC_NONE
);
3326 free_color_pair(&lastc
);
3329 Write_to_screen(p
+6+COLOR_BLOB_LEN
-2);
3332 PutLine0(dline
+HEADER_ROWS(ps
),ctmp
->val2offset
,p
);
3333 if(ctmp
->flags
& CF_VAR2
&& ctmp
== screen
->current
)
3339 char *q
, *first_space
, *sample
, *ptr
;
3340 COLOR_PAIR
*lastc
, *newc
;
3344 if(ctmp
->flags
& CF_COLORSAMPLE
&&
3345 pico_usingcolor() &&
3346 ((q
= strstr(tmp_20k_buf
, SAMPLE_LEADER
)) ||
3347 (q
= strstr(tmp_20k_buf
, "Color"))) &&
3348 (first_space
= strindex(q
, SPACE
)) &&
3349 (strstr(value
, SAMP1
) ||
3350 strstr(value
, SAMP2
))){
3354 /* write out first part */
3355 *first_space
= '\0';
3356 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
,
3358 *first_space
= SPACE
;
3361 if(ctmp
== screen
->current
)
3364 sample
= skip_white_space(ptr
);
3365 /* if there's enough room to put some sample up */
3368 w
= utf8_width(tmp_20k_buf
);
3370 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3372 sample
++; /* for `[' at edge of sample */
3376 w
= utf8_width(tmp_20k_buf
);
3381 /* spaces and bracket before sample1 */
3382 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+w
, ptr
);
3387 /* then the color sample */
3388 if(ctmp
->var
== &ps
->vars
[V_VIEW_HDR_COLORS
]
3389 || ctmp
->var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
]){
3390 SPEC_COLOR_S
*hc
, *hcolors
;
3392 lastc
= newc
= NULL
;
3395 spec_colors_from_varlist(LVAL(ctmp
->var
, ew
),
3397 for(hc
= hcolors
, i
=0; hc
; hc
= hc
->next
, i
++)
3398 if(CFC_ICUST(ctmp
) == i
)
3401 if(hc
&& hc
->fg
&& hc
->fg
[0] && hc
->bg
&&
3403 newc
= new_color_pair(hc
->fg
, hc
->bg
);
3406 lastc
= pico_get_cur_color();
3407 (void)pico_set_colorp(newc
, PSC_NONE
);
3408 free_color_pair(&newc
);
3412 free_spec_colors(&hcolors
);
3415 /* print out sample1 */
3419 w
= utf8_width(tmp_20k_buf
);
3422 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3423 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3429 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3433 ptr
= strindex(ptr
, ']');
3436 (void)pico_set_colorp(lastc
, PSC_NONE
);
3437 free_color_pair(&lastc
);
3440 else if(ctmp
->var
== &ps
->vars
[V_KW_COLORS
]){
3442 SPEC_COLOR_S
*kw_col
= NULL
;
3444 lastc
= newc
= NULL
;
3446 /* find keyword associated with this line */
3447 for(kw
=ps
->keywords
, i
=0; kw
; kw
=kw
->next
, i
++)
3448 if(CFC_ICUST(ctmp
) == i
)
3453 spec_colors_from_varlist(LVAL(ctmp
->var
,ew
),
3456 /* color for this keyword */
3458 && ((kw
->nick
&& kw
->nick
[0]
3459 && (newc
=hdr_color(kw
->nick
, NULL
,
3462 (kw
->kw
&& kw
->kw
[0]
3463 && (newc
=hdr_color(kw
->kw
, NULL
,
3465 lastc
= pico_get_cur_color();
3466 (void)pico_set_colorp(newc
, PSC_NONE
);
3467 free_color_pair(&newc
);
3471 free_spec_colors(&kw_col
);
3473 /* print out sample1 */
3477 w
= utf8_width(tmp_20k_buf
);
3480 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3481 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3487 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3491 ptr
= strindex(ptr
, ']');
3494 (void)pico_set_colorp(lastc
, PSC_NONE
);
3495 free_color_pair(&lastc
);
3501 newc
= sample_color(ps
, ctmp
->var
);
3503 if((lastc
= pico_get_cur_color()) != NULL
)
3504 (void)pico_set_colorp(newc
, PSC_NONE
);
3506 free_color_pair(&newc
);
3508 else if(var_defaults_to_rev(ctmp
->var
)){
3509 if((newc
= pico_get_rev_color()) != NULL
){
3511 * Note, don't have to free newc.
3513 if((lastc
= pico_get_cur_color()) != NULL
)
3514 (void)pico_set_colorp(newc
, PSC_NONE
);
3522 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3524 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3525 !(PVAL(ctmp
->var
,ew
) &&
3526 PVAL(ctmp
->var
+1,ew
))))
3529 /* print out sample1 */
3533 w
= utf8_width(tmp_20k_buf
);
3536 want_width
= MIN(utf8_width(SAMP1
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3537 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3543 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3547 ptr
= strindex(ptr
, ']');
3549 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3551 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3552 !(PVAL(ctmp
->var
,ew
) &&
3553 PVAL(ctmp
->var
+1,ew
))))
3557 (void)pico_set_colorp(lastc
, PSC_NONE
);
3558 free_color_pair(&lastc
);
3565 * Finish sample1 with the right bracket.
3569 w
= utf8_width(tmp_20k_buf
);
3571 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3574 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3581 * Now check for an exception sample and paint it.
3583 if(ctmp
->valoffset
+ w
+ SBS
+ 1 < ps
->ttyo
->screen_cols
&& (q
= strstr(ptr
, SAMPEXC
))){
3587 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3592 * Figure out what color to paint it.
3593 * This only happens with normal variables,
3594 * not with V_VIEW_HDR_COLORS.
3598 newc
= sampleexc_color(ps
, ctmp
->var
);
3600 if((lastc
= pico_get_cur_color()) != NULL
)
3601 (void)pico_set_colorp(newc
, PSC_NONE
);
3603 free_color_pair(&newc
);
3605 else if(var_defaults_to_rev(ctmp
->var
)){
3606 if((newc
= pico_get_rev_color()) != NULL
){
3608 * Note, don't have to free newc.
3610 if((lastc
= pico_get_cur_color()) != NULL
)
3611 (void)pico_set_colorp(newc
, PSC_NONE
);
3619 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3621 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3622 !(PVAL(ctmp
->var
,Post
) &&
3623 PVAL(ctmp
->var
+1,Post
))))
3629 w
= utf8_width(tmp_20k_buf
);
3632 want_width
= MIN(utf8_width(SAMPEXC
)-2, ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
);
3633 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3639 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3643 ptr
= strindex(ptr
, ']');
3645 /* turn off bold and color */
3646 if(ctmp
->var
==&ps
->vars
[V_SLCTBL_FORE_COLOR
] &&
3648 (F_OFF(F_SLCTBL_ITEM_NOBOLD
, ps
) ||
3649 !(PVAL(ctmp
->var
,Post
) &&
3650 PVAL(ctmp
->var
+1,Post
))))
3654 (void)pico_set_colorp(lastc
, PSC_NONE
);
3655 free_color_pair(&lastc
);
3661 * Finish sample2 with the right bracket.
3665 w
= utf8_width(tmp_20k_buf
);
3667 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
){
3670 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3677 /* paint rest of the line if there is any left */
3678 if(ctmp
->valoffset
+ w
< ps
->ttyo
->screen_cols
&& *ptr
){
3679 want_width
= ps
->ttyo
->screen_cols
- w
- ctmp
->valoffset
;
3680 saveptr
= utf8_count_forw_width(ptr
, want_width
, &got_width
);
3686 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
+ w
, ptr
);
3693 w
= utf8_width(tmp_20k_buf
);
3694 want_width
= ps
->ttyo
->screen_cols
- ctmp
->valoffset
;
3696 saveptr
= utf8_count_forw_width(tmp_20k_buf
, want_width
, &got_width
);
3701 PutLine0(dline
+HEADER_ROWS(ps
), ctmp
->valoffset
, tmp_20k_buf
);
3702 if(ctmp
== screen
->current
)
3710 ps
->mangled_body
= 0;
3711 screen
->top_line
= top_line
;
3712 screen
->prev
= screen
->current
;
3724 print_option_screen(OPT_SCREEN_S
*screen
, char *prompt
)
3730 if(open_printer(prompt
) == 0){
3731 for(ctmp
= first_confline(screen
->current
);
3733 ctmp
= next_confline(ctmp
)){
3736 if(ctmp
->varname
&& !(ctmp
->flags
& CF_INVISIBLEVAR
)){
3738 snprintf(line
, sizeof(line
), "%*s%s", ctmp
->varoffset
, "",
3740 line
[sizeof(line
)-1] = '\0';
3742 so_far
= ctmp
->varoffset
+ utf8_width(ctmp
->varname
);
3745 if(ctmp
&& ctmp
->value
){
3746 char *p
= tmp_20k_buf
;
3749 /* Copy the value to a temp buffer expanding tabs. */
3750 for(i
= 0, j
= ctmp
->valoffset
; ctmp
->value
[i
]; i
++){
3751 if(ctmp
->value
[i
] == ctrl('I')){
3754 while((++j
) & 0x07);
3758 *p
++ = ctmp
->value
[i
];
3764 removing_trailing_white_space(tmp_20k_buf
);
3766 spaces
= MAX(ctmp
->valoffset
- so_far
, 0);
3767 snprintf(line
, sizeof(line
), "%*s%s\n", spaces
, "", tmp_20k_buf
);
3768 line
[sizeof(line
)-1] = '\0';
3783 option_screen_redrawer(void)
3785 ps_global
->mangled_body
= 1;
3786 update_option_screen(ps_global
, opt_screen
, (Pos
*)NULL
);
3792 * pretty_value - given the line, return an
3793 * alloc'd string for line's value...
3796 pretty_value(struct pine
*ps
, CONF_S
*cl
)
3802 if(v
== &ps
->vars
[V_FEATURE_LIST
])
3803 return(checkbox_pretty_value(ps
, cl
));
3804 else if(standard_radio_var(ps
, v
) || v
== startup_ptr
)
3805 return(radio_pretty_value(ps
, cl
));
3806 else if(v
== &ps
->vars
[V_SORT_KEY
])
3807 return(sort_pretty_value(ps
, cl
));
3808 else if(v
== &ps
->vars
[V_SIGNATURE_FILE
])
3809 return(sigfile_pretty_value(ps
, cl
));
3810 else if(v
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
])
3811 return(yesno_pretty_value(ps
, cl
));
3812 else if(color_holding_var(ps
, v
))
3813 return(color_pretty_value(ps
, cl
));
3815 return(text_pretty_value(ps
, cl
));
3820 text_pretty_value(struct pine
*ps
, CONF_S
*cl
)
3822 char tmp
[6*MAX_SCREEN_COLS
+20], *pvalnorm
, **lvalnorm
, *pvalexc
, **lvalexc
;
3823 char *p
, *pval
, **lval
, lastchar
= '\0';
3824 int editing_except
, fixed
, uvalset
, uvalposlen
;
3826 int comments
, except_set
, avail_width
;
3827 int norm_with_except
= 0, norm_with_except_inherit
= 0;
3828 int inherit_line
= 0;
3830 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
3831 fixed
= cl
->var
->is_fixed
;
3832 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
))
3833 norm_with_except
++; /* editing normal and except config exists */
3835 if(cl
->var
->is_list
){
3836 lvalnorm
= LVAL(cl
->var
, Main
);
3837 lvalexc
= LVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3839 uvalset
= lvalexc
!= NULL
;
3840 uvalposlen
= uvalset
&& lvalexc
[0] && lvalexc
[0][0];
3844 uvalset
= lvalnorm
!= NULL
;
3845 uvalposlen
= uvalset
&& lvalnorm
[0] && lvalnorm
[0][0];
3849 except_set
= lvalexc
!= NULL
;
3850 comments
= cl
->var
->current_val
.l
!= NULL
;
3851 if(norm_with_except
&& except_set
&& lvalexc
[0] &&
3852 !strcmp(lvalexc
[0],INHERIT
))
3853 norm_with_except_inherit
++;
3855 if(uvalset
&& !strcmp(lval
[0], INHERIT
)){
3856 if(cl
->varmem
== 0){
3862 /* only add extra comments on last member of list */
3863 if(uvalset
&& !inherit_line
&& lval
&& lval
[cl
->varmem
] &&
3864 lval
[cl
->varmem
+ 1])
3868 pvalnorm
= PVAL(cl
->var
, Main
);
3869 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
3871 uvalset
= pvalexc
!= NULL
;
3872 uvalposlen
= uvalset
&& *pvalexc
;
3876 uvalset
= pvalnorm
!= NULL
;
3877 uvalposlen
= uvalset
&& *pvalnorm
;
3881 except_set
= pvalexc
!= NULL
;
3882 comments
= cl
->var
->current_val
.p
!= NULL
;
3885 memset(tmp
, 0, sizeof(tmp
));
3889 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
3891 if(fixed
|| !uvalset
|| !uvalposlen
){
3892 p
+= utf8_to_width(p
, "<", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3893 avail_width
-= got_width
;
3897 p
+= utf8_to_width(p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3898 avail_width
-= got_width
;
3901 p
+= utf8_to_width(p
, _(no_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3902 avail_width
-= got_width
;
3904 else if(!uvalposlen
){
3905 p
+= utf8_to_width(p
, _(empty_val
), sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3906 avail_width
-= got_width
;
3908 else if(inherit_line
){
3909 p
+= utf8_to_width(p
, INHERIT
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3910 avail_width
-= got_width
;
3913 if(cl
->var
->is_list
){
3914 p
+= utf8_to_width(p
, lval
[cl
->varmem
], sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3915 avail_width
-= got_width
;
3918 p
+= utf8_to_width(p
, pval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3919 avail_width
-= got_width
;
3923 if(comments
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
3924 if(fixed
|| !uvalset
){
3925 p
+= utf8_to_width(p
, ": using ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3926 avail_width
-= got_width
;
3929 if(norm_with_except
&& except_set
){
3931 p
+= utf8_to_width(p
, "exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3932 avail_width
-= got_width
;
3936 p
+= utf8_to_width(p
, ": ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3937 avail_width
-= got_width
;
3940 p
+= utf8_to_width(p
, " (", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3941 avail_width
-= got_width
;
3944 if(norm_with_except_inherit
){
3945 p
+= utf8_to_width(p
, "added to by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3946 avail_width
-= got_width
;
3949 p
+= utf8_to_width(p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3950 avail_width
-= got_width
;
3955 if(avail_width
>= 7){
3956 if(cl
->var
== &ps_global
->vars
[V_POST_CHAR_SET
]){
3957 p
+= utf8_to_width(p
, "most specific (see help)", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3958 avail_width
-= got_width
;
3961 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
3963 if(cl
->var
->is_list
){
3966 the_list
= cl
->var
->current_val
.l
;
3968 if(norm_with_except
&& except_set
)
3971 if(the_list
&& the_list
[0] && !strcmp(the_list
[0], INHERIT
))
3974 for(lval
= the_list
; avail_width
-(p
-tmp
) > 0 && *lval
; lval
++){
3975 if(lval
!= the_list
){
3976 p
+= utf8_to_width(p
, ",", sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3977 avail_width
-= got_width
;
3980 p
+= utf8_to_width(p
, *lval
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3981 avail_width
-= got_width
;
3985 p
+= utf8_to_width(p
, cl
->var
->current_val
.p
, sizeof(tmp
)-(p
-tmp
), avail_width
, &got_width
);
3986 avail_width
-= got_width
;
3989 if(p
-tmp
+2 < sizeof(tmp
)){
3995 else if(*(p
-1) == SPACE
)
3999 tmp
[sizeof(tmp
)-1] = '\0';
4001 if(fixed
|| !uvalset
|| !uvalposlen
)
4003 else if(comments
&& norm_with_except
&& except_set
)
4007 if(p
-tmp
+2 < sizeof(tmp
)){
4013 tmp
[sizeof(tmp
)-1] = '\0';
4014 avail_width
= ps
->ttyo
->screen_cols
- cl
->valoffset
;
4016 if(utf8_width(tmp
) < avail_width
)
4017 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
), "%*s", avail_width
-utf8_width(tmp
), "");
4019 tmp
[sizeof(tmp
)-1] = '\0';
4021 return(cpystr(tmp
));
4026 checkbox_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4028 char tmp
[6*MAXPATH
];
4029 char *comment
= NULL
;
4030 int indent
, x
, screen_width
, need
;
4031 int longest_featname
, longest_comment
;
4032 int nwidcomm
; /* name width with comment */
4033 int nwidnocomm
; /* and without comment */
4036 screen_width
= (ps
&& ps
->ttyo
) ? ps
->ttyo
->screen_cols
: 80;
4039 longest_featname
= longest_feature_name();
4040 longest_comment
= longest_feature_comment(ps
, ew
);
4041 indent
= feature_indent();
4043 nwidcomm
= longest_featname
;
4044 nwidnocomm
= longest_featname
+ 2 + longest_comment
;
4046 if((need
= (indent
+ 5 + longest_featname
+ 2 + longest_comment
) - screen_width
) > 0){
4052 longest_comment
= 0;
4053 nwidnocomm
= longest_featname
;
4057 feature
= feature_list(cl
->varmem
);
4059 x
= feature_gets_an_x(ps
, cl
->var
, feature
, &comment
, ew
);
4061 if(longest_comment
&& comment
&& *comment
){
4062 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w %-*.*w", x
? 'X' : ' ',
4064 pretty_feature_name(feature
->name
, nwidcomm
),
4065 longest_comment
, longest_comment
, comment
? comment
: "");
4068 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w", x
? 'X' : ' ',
4069 nwidnocomm
, nwidnocomm
,
4070 pretty_feature_name(feature
->name
, nwidnocomm
));
4073 return(cpystr(tmp
));
4078 longest_feature_name(void)
4085 for(lv
= 0, i
= 0; (feature
= feature_list(i
)); i
++)
4086 if(feature_list_section(feature
)
4087 && lv
< (j
= utf8_width(pretty_feature_name(feature
->name
, -1))))
4098 feature_indent(void)
4105 yesno_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4107 char tmp
[6*MAXPATH
], *pvalnorm
, *pvalexc
;
4108 char *p
, *pval
, lastchar
= '\0';
4109 int editing_except
, fixed
, norm_with_except
, uvalset
;
4110 int curval
, except_set
;
4112 editing_except
= (ew
== ps_global
->ew_for_except_vars
);
4113 fixed
= cl
->var
->is_fixed
;
4114 if((ps_global
->ew_for_except_vars
== Main
) ||
4115 (ew
== ps_global
->ew_for_except_vars
))
4116 norm_with_except
= 0;
4118 norm_with_except
= 1; /* editing normal and except config exists */
4120 pvalnorm
= PVAL(cl
->var
, Main
);
4121 pvalexc
= PVAL(cl
->var
, ps_global
->ew_for_except_vars
);
4123 uvalset
= (pvalexc
!= NULL
&&
4124 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4128 uvalset
= (pvalnorm
!= NULL
&&
4129 (!strucmp(pvalnorm
,yesstr
) || !strucmp(pvalnorm
,nostr
)));
4133 except_set
= (pvalexc
!= NULL
&&
4134 (!strucmp(pvalexc
,yesstr
) || !strucmp(pvalexc
,nostr
)));
4135 curval
= (cl
->var
->current_val
.p
!= NULL
&&
4136 (!strucmp(cl
->var
->current_val
.p
,yesstr
) ||
4137 !strucmp(cl
->var
->current_val
.p
,nostr
)));
4142 if(fixed
|| !uvalset
)
4143 sstrncpy(&p
, "<", sizeof(tmp
)-(p
-tmp
));
4146 sstrncpy(&p
, _(fixed_val
), sizeof(tmp
)-(p
-tmp
));
4148 sstrncpy(&p
, _(no_val
), sizeof(tmp
)-(p
-tmp
));
4149 else if(!strucmp(pval
, yesstr
))
4150 sstrncpy(&p
, yesstr
, sizeof(tmp
)-(p
-tmp
));
4152 sstrncpy(&p
, nostr
, sizeof(tmp
)-(p
-tmp
));
4154 if(curval
&& (fixed
|| !uvalset
|| (norm_with_except
&& except_set
))){
4155 if(fixed
|| !uvalset
)
4156 sstrncpy(&p
, ": using ", sizeof(tmp
)-(p
-tmp
));
4158 if(norm_with_except
&& except_set
){
4160 sstrncpy(&p
, "exception ", sizeof(tmp
)-(p
-tmp
));
4162 sstrncpy(&p
, " (", sizeof(tmp
)-(p
-tmp
));
4163 sstrncpy(&p
, "overridden by exception ", sizeof(tmp
)-(p
-tmp
));
4167 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4168 sstrncpy(&p
, !strucmp(cl
->var
->current_val
.p
,yesstr
) ? yesstr
: nostr
, sizeof(tmp
)-(p
-tmp
));
4169 sstrncpy(&p
, "\"", sizeof(tmp
)-(p
-tmp
));
4172 if(fixed
|| !uvalset
)
4174 else if(curval
&& norm_with_except
&& except_set
)
4177 if(lastchar
&& sizeof(tmp
)-(p
-tmp
) > 1){
4182 tmp
[sizeof(tmp
)-1] = '\0';
4184 if(utf8_width(tmp
) < ps
->ttyo
->screen_cols
- cl
->valoffset
)
4185 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
),
4186 "%*s", ps
->ttyo
->screen_cols
- cl
->valoffset
- utf8_width(tmp
), "");
4188 tmp
[sizeof(tmp
)-1] = '\0';
4190 return(cpystr(tmp
));
4195 radio_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4197 char tmp
[6*MAXPATH
];
4198 char *pvalnorm
, *pvalexc
, *pval
;
4199 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4200 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4202 NAMEVAL_S
*rule
= NULL
, *f
;
4203 PTR_TO_RULEFUNC rulefunc
;
4209 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4211 editing_normal_which_isnt_except
= (ew
== Main
&&
4212 ew
!= ps_global
->ew_for_except_vars
);
4213 fixed
= cl
->var
->is_fixed
;
4214 pvalnorm
= PVAL(v
, Main
);
4215 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4217 rulefunc
= rulefunc_from_var(ps
, v
);
4218 rule
= rulefunc
? (*rulefunc
)(cl
->varmem
) : NULL
;
4220 /* find longest name */
4222 for(lv
= 0, i
= 0; (f
= (*rulefunc
)(i
)); i
++)
4223 if(lv
< (j
= utf8_width(f
->name
)))
4228 if(editing_except_which_isnt_normal
)
4234 is_set_for_this_level
++;
4237 pval
= v
->fixed_val
.p
;
4238 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4240 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4241 is_the_one
? R_SELD
: ' ',
4242 lv
, lv
, rule
->name
, is_the_one
? " (value is fixed)" : "");
4244 else if(is_set_for_this_level
){
4245 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4246 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4247 !strucmp(pvalexc
, S_OR_L(rule
)));
4248 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4249 is_the_one
? R_SELD
: ' ',
4251 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4252 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4254 editing_normal_which_isnt_except
&&
4256 !the_exc_one
) ? " (overridden by exceptions)" :
4261 is_the_one
= !strucmp(pvalexc
, S_OR_L(rule
));
4262 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4263 is_the_one
? R_SELD
: ' ',
4265 is_the_one
? " (value set in exceptions)" : "");
4268 pval
= v
->current_val
.p
;
4269 is_the_one
= (pval
&& !strucmp(pval
, S_OR_L(rule
)));
4270 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w%s",
4271 is_the_one
? R_SELD
: ' ',
4273 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4277 tmp
[sizeof(tmp
)-1] = '\0';
4279 return(cpystr(tmp
));
4284 sigfile_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4286 if(cl
&& cl
->var
== &ps
->vars
[V_SIGNATURE_FILE
] &&
4287 cl
->prev
&& cl
->prev
->var
== &ps
->vars
[V_LITERAL_SIG
]){
4288 if(cl
->prev
->var
->current_val
.p
){
4289 cl
->flags
|= CF_NOSELECT
; /* side effect */
4290 return(cpystr(_("<Ignored: using Literal-Signature instead>")));
4293 cl
->flags
&= ~CF_NOSELECT
;
4294 return(text_pretty_value(ps
, cl
));
4303 color_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4305 char tmp
[6*MAXPATH
];
4313 if(v
&& color_holding_var(ps
, v
) &&
4314 (p
=srchstr(v
->name
, "-foreground-color"))){
4316 is_index
= !struncmp(v
->name
, "index-", 6);
4318 q
= sampleexc_text(ps
, v
);
4319 utf8_snprintf(tmp
, sizeof(tmp
), "%c%.*s %sColor%*.50s %.20w%*s%.20w%.20w",
4320 islower((unsigned char)v
->name
[0])
4321 ? toupper((unsigned char)v
->name
[0])
4323 MIN(p
-v
->name
-1,30), v
->name
+1,
4324 is_index
? "Symbol " : "",
4325 MAX(EQ_COL
- COLOR_INDENT
-1 - MIN(p
-v
->name
-1,30)
4326 - 6 - (is_index
? 7 : 0) - 1,0), "",
4327 sample_text(ps
,v
), *q
? SBS
: 0, "", q
,
4328 color_parenthetical(v
));
4331 tmp
[sizeof(tmp
)-1] = '\0';
4333 return(cpystr(tmp
));
4338 sort_pretty_value(struct pine
*ps
, CONF_S
*cl
)
4340 return(generalized_sort_pretty_value(ps
, cl
, 1));
4345 generalized_sort_pretty_value(struct pine
*ps
, CONF_S
*cl
, int default_ok
)
4347 char tmp
[6*MAXPATH
];
4348 char *pvalnorm
, *pvalexc
, *pval
;
4349 int editing_except_which_isnt_normal
, editing_normal_which_isnt_except
;
4350 int fixed
, is_set_for_this_level
= 0, is_the_one
, the_exc_one
;
4353 SortOrder line_sort
, var_sort
, exc_sort
;
4354 int line_sort_rev
, var_sort_rev
, exc_sort_rev
;
4359 editing_except_which_isnt_normal
= (ew
== ps_global
->ew_for_except_vars
&&
4361 editing_normal_which_isnt_except
= (ew
== Main
&&
4362 ew
!= ps_global
->ew_for_except_vars
);
4363 fixed
= cl
->var
->is_fixed
;
4364 pvalnorm
= PVAL(v
, Main
);
4365 pvalexc
= PVAL(v
, ps_global
->ew_for_except_vars
);
4367 /* find longest value's name */
4368 for(lv
= 0, i
= 0; ps
->sort_types
[i
] != EndofList
; i
++)
4369 if(lv
< (j
= utf8_width(sort_name(ps
->sort_types
[i
]))))
4374 if(editing_except_which_isnt_normal
)
4380 is_set_for_this_level
++;
4382 /* the config line we're talking about */
4383 if(cl
->varmem
>= 0){
4384 line_sort_rev
= cl
->varmem
>= (short)EndofList
;
4385 line_sort
= (SortOrder
)(cl
->varmem
- (line_sort_rev
* EndofList
));
4389 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*w",
4390 (pval
== NULL
) ? R_SELD
: ' ',
4394 pval
= v
->fixed_val
.p
;
4395 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4396 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4398 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4399 is_the_one
? R_SELD
: ' ',
4400 line_sort_rev
? "Reverse " : "",
4401 lv
, sort_name(line_sort
),
4402 line_sort_rev
? 0 : 8, "",
4403 is_the_one
? " (value is fixed)" : "");
4405 else if(is_set_for_this_level
){
4406 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4407 is_the_one
= (var_sort_rev
== line_sort_rev
&& var_sort
== line_sort
);
4408 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4409 the_exc_one
= (editing_normal_which_isnt_except
&& pvalexc
&&
4410 exc_sort_rev
== line_sort_rev
&& exc_sort
== line_sort
);
4411 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4412 is_the_one
? R_SELD
: ' ',
4413 line_sort_rev
? "Reverse " : "",
4414 lv
, sort_name(line_sort
),
4415 line_sort_rev
? 0 : 8, "",
4416 (!is_the_one
&& the_exc_one
) ? " (value set in exceptions)" :
4417 (is_the_one
&& the_exc_one
) ? " (also set in exceptions)" :
4419 editing_normal_which_isnt_except
&&
4421 !the_exc_one
) ? " (overridden by exceptions)" :
4426 decode_sort(pvalexc
, &exc_sort
, &exc_sort_rev
);
4427 is_the_one
= (exc_sort_rev
== line_sort_rev
&&
4428 exc_sort
== line_sort
);
4429 utf8_snprintf(tmp
, sizeof(tmp
), "( ) %s%-*w%*s%s",
4430 line_sort_rev
? "Reverse " : "",
4431 lv
, sort_name(line_sort
),
4432 line_sort_rev
? 0 : 8, "",
4433 is_the_one
? " (value set in exceptions)" : "");
4436 pval
= v
->current_val
.p
;
4437 decode_sort(pval
, &var_sort
, &var_sort_rev
);
4438 is_the_one
= ((pval
|| default_ok
) &&
4439 var_sort_rev
== line_sort_rev
&&
4440 var_sort
== line_sort
);
4441 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %s%-*w%*s%s",
4442 is_the_one
? R_SELD
: ' ',
4443 line_sort_rev
? "Reverse " : "",
4444 lv
, sort_name(line_sort
),
4445 line_sort_rev
? 0 : 8, "",
4446 is_the_one
? ((editing_except_which_isnt_normal
&& pvalnorm
) ? " (default from regular config)" : " (default)") : "");
4450 return(cpystr(tmp
));
4455 sample_color(struct pine
*ps
, struct variable
*v
)
4457 COLOR_PAIR
*cp
= NULL
;
4458 char *pvalefg
, *pvalebg
;
4459 char *pvalmfg
, *pvalmbg
;
4461 pvalefg
= PVAL(v
, ew
);
4462 pvalebg
= PVAL(v
+1, ew
);
4463 pvalmfg
= PVAL(v
, Main
);
4464 pvalmbg
= PVAL(v
+1, Main
);
4465 if(v
&& color_holding_var(ps
, v
) &&
4466 srchstr(v
->name
, "-foreground-color")){
4467 if(pvalefg
&& pvalefg
[0] && pvalebg
&& pvalebg
[0])
4468 cp
= new_color_pair(pvalefg
, pvalebg
);
4469 else if(ew
== Post
&& pvalmfg
&& pvalmfg
[0] && pvalmbg
&& pvalmbg
[0])
4470 cp
= new_color_pair(pvalmfg
, pvalmbg
);
4471 else if(v
->global_val
.p
&& v
->global_val
.p
[0] &&
4472 (v
+1)->global_val
.p
&& (v
+1)->global_val
.p
[0])
4473 cp
= new_color_pair(v
->global_val
.p
, (v
+1)->global_val
.p
);
4481 sampleexc_color(struct pine
*ps
, struct variable
*v
)
4483 COLOR_PAIR
*cp
= NULL
;
4484 char *pvalfg
, *pvalbg
;
4486 pvalfg
= PVAL(v
, Post
);
4487 pvalbg
= PVAL(v
+1, Post
);
4488 if(v
&& color_holding_var(ps
, v
) &&
4489 srchstr(v
->name
, "-foreground-color") &&
4490 pvalfg
&& pvalfg
[0] && pvalbg
&& pvalbg
[0])
4491 cp
= new_color_pair(pvalfg
, pvalbg
);
4498 clear_feature(char ***l
, char *f
)
4500 char **list
= l
? *l
: NULL
;
4503 for(; list
&& *list
; list
++, count
++){
4504 if(f
&& !strucmp(((!struncmp(*list
,"no-",3)) ? *list
+ 3 : *list
), f
)){
4505 fs_give((void **)list
);
4510 *list
= *(list
+ 1);
4514 * this is helpful to keep the array from growing if a feature
4515 * get's set and unset repeatedly
4518 fs_resize((void **)l
, count
* sizeof(char *));
4526 toggle_feature_bit(struct pine
*ps
, int index
, struct variable
*var
, CONF_S
*cl
, int just_flip_value
)
4532 f
= feature_list(index
);
4534 og
= test_old_growth_bits(ps
, f
->id
);
4537 * if this feature is in the fixed set, or old-growth is in the fixed
4538 * set and this feature is in the old-growth set, don't alter it...
4540 for(vp
= var
->fixed_val
.l
; vp
&& *vp
; vp
++){
4541 p
= (struncmp(*vp
, "no-", 3)) ? *vp
: *vp
+ 3;
4542 if(!strucmp(p
, f
->name
) || (og
&& !strucmp(p
, "old-growth"))){
4543 q_status_message(SM_ORDER
, 3, 3,
4544 _("Can't change value fixed by sys-admin."));
4549 on_before
= F_ON(f
->id
, ps
);
4551 toggle_feature(ps
, var
, f
, just_flip_value
, ew
);
4554 * Handle any alpine-specific features that need attention here. Features
4555 * that aren't alpine-specific should be handled in toggle_feature instead.
4557 if(on_before
!= F_ON(f
->id
, ps
))
4559 case F_CMBND_ABOOK_DISP
:
4563 case F_PRESERVE_START_STOP
:
4564 /* toggle raw mode settings to make tty driver aware of new setting */
4570 ps
->orig_use_fkeys
= F_ON(F_USE_FK
, ps
);
4571 ps
->mangled_footer
= 1;
4572 mark_keymenu_dirty();
4576 ps
->mangled_header
= 1;
4579 case F_BLANK_KEYMENU
:
4580 if(F_ON(f
->id
, ps
)){
4581 FOOTER_ROWS(ps
) = 1;
4582 ps
->mangled_body
= 1;
4585 FOOTER_ROWS(ps
) = 3;
4586 ps
->mangled_footer
= 1;
4592 case F_ENABLE_INCOMING
:
4593 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4594 "Folder List changes will take effect your next Alpine session.");
4598 case F_SHOW_CURSOR
:
4599 mswin_showcaret(F_ON(f
->id
,ps
));
4602 case F_ENABLE_TRAYICON
:
4603 mswin_trayicon(F_ON(f
->id
,ps
));
4607 #if !defined(DOS) && !defined(OS2)
4617 case F_PASS_CONTROL_CHARS
:
4618 ps
->pass_ctrl_chars
= F_ON(F_PASS_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4622 case F_USE_CERT_STORE_ONLY
:
4623 if(F_OFF(F_USE_CERT_STORE_ONLY
, ps
))
4624 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4625 "Disabling this feature should only be done for testing. Press \"?\" for help");
4629 case F_PASS_C1_CONTROL_CHARS
:
4630 ps
->pass_c1_ctrl_chars
= F_ON(F_PASS_C1_CONTROL_CHARS
,ps_global
) ? 1 : 0;
4634 case F_ENABLE_MOUSE
:
4635 if(F_ON(f
->id
, ps
)){
4638 q_status_message(SM_ORDER
| SM_DING
, 3, 4,
4639 "Mouse tracking still off ($DISPLAY variable set?)");
4648 if(just_flip_value
){
4649 if(cl
->value
&& cl
->value
[0])
4650 cl
->value
[1] = (cl
->value
[1] == ' ') ? 'X' : ' ';
4654 * This fork is only called from the checkbox_tool, which has
4655 * varmem set to index correctly and cl->var set correctly.
4658 fs_give((void **)&cl
->value
);
4660 cl
->value
= pretty_value(ps
, cl
);
4666 * new_confline - create new CONF_S zero it out, and insert it after current.
4667 * NOTE current gets set to the new CONF_S too!
4670 new_confline(CONF_S
**current
)
4674 p
= (CONF_S
*)fs_get(sizeof(CONF_S
));
4675 memset((void *)p
, 0, sizeof(CONF_S
));
4678 p
->next
= (*current
)->next
;
4679 (*current
)->next
= p
;
4696 snip_confline(CONF_S
**p
)
4701 * Be careful. We need this line because the
4702 * q->prev->next = ...
4703 * may change q itself if &q == &q->prev->next.
4704 * Then the use of q in the next line is wrong.
4705 * That's what happens if we pass in the address of
4706 * some ->next and use *p directly instead of q.
4711 /* Yank it from the linked list */
4713 q
->prev
->next
= q
->next
;
4716 q
->next
->prev
= q
->prev
;
4718 /* Then free up it's memory */
4719 q
->prev
= q
->next
= NULL
;
4725 get_confline_number(CONF_S
*conf
)
4730 for (p
= first_confline(conf
), pos
= 0; p
!= conf
; p
= next_confline(p
), pos
++);
4737 set_confline_number(CONF_S
*conf
, int pos
)
4741 for(p
= first_confline(conf
), i
= 0; p
&& i
< pos
; p
=next_confline(p
), i
++);
4750 free_conflines(CONF_S
**p
)
4753 free_conflines(&(*p
)->next
);
4756 fs_give((void **) &(*p
)->varname
);
4759 fs_give((void **) &(*p
)->value
);
4761 fs_give((void **) p
);
4770 first_confline(CONF_S
*p
)
4780 * First selectable confline.
4783 first_sel_confline(CONF_S
*p
)
4785 for(p
= first_confline(p
); p
&& (p
->flags
&CF_NOSELECT
); p
=next_confline(p
))
4796 last_confline(CONF_S
*p
)
4809 fixed_var(struct variable
*v
, char *action
, char *name
)
4815 || ((lval
=v
->fixed_val
.l
) && lval
[0]
4816 && strcmp(INHERIT
, lval
[0]) != 0))){
4817 q_status_message2(SM_ORDER
, 3, 3,
4818 "Can't %s sys-admin defined %s.",
4819 action
? action
: "change", name
? name
: "value");
4828 exception_override_warning(struct variable
*v
)
4832 /* if exceptions config file exists and we're not editing it */
4833 if(v
&& (ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
4834 if((!v
->is_list
&& PVAL(v
, ps_global
->ew_for_except_vars
)) ||
4835 (v
->is_list
&& (lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
4836 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0))
4837 q_status_message1(SM_ORDER
, 3, 3,
4838 _("Warning: \"%s\" is overridden in your exceptions configuration"),
4845 offer_to_fix_pinerc(struct pine
*ps
)
4852 int rv
= 0, write_main
= 0, write_post
= 0;
4853 int i
, k
, j
, need
, exc
;
4854 char *clear
= ": delete it";
4857 dprint((4, "offer_to_fix_pinerc()\n"));
4859 ps
->fix_fixed_warning
= 0; /* so we only ask first time */
4861 if(ps
->readonly_pinerc
)
4864 set_titlebar(_("FIXING PINERC"), ps
->mail_stream
,
4865 ps
->context_current
,
4866 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0, NULL
);
4868 if(want_to(_("Some of your options conflict with site policy. Investigate"),
4869 'y', 'n', NO_HELP
, WT_FLUSH_IN
) != 'y')
4872 /* space want_to requires in addition to the string you pass in */
4873 #define WANTTO_SPACE 6
4874 need
= WANTTO_SPACE
+ utf8_width(clear
);
4876 for(v
= ps
->vars
; v
->name
; v
++){
4880 v
== &ps
->vars
[V_FEATURE_LIST
]) /* handle feature-list below */
4886 (v
->post_user_val
.l
|| v
->main_user_val
.l
)){
4889 active_list
= v
->post_user_val
.l
? v
->post_user_val
.l
4890 : v
->main_user_val
.l
;
4892 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is "), v
->name
);
4893 prompt
[sizeof(prompt
)-1] = '\0';
4894 p
= prompt
+ strlen(prompt
);
4895 for(i
= 0; active_list
[i
]; i
++){
4896 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4898 if(i
&& sizeof(prompt
)-(p
-prompt
) > 0)
4901 sstrncpy(&p
, active_list
[i
], sizeof(prompt
)-(p
-prompt
));
4902 if(sizeof(prompt
)-(p
-prompt
) > 0)
4905 prompt
[sizeof(prompt
)-1] = '\0';
4908 if(sizeof(prompt
)-(p
-prompt
) > 0)
4912 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"), v
->name
, _(empty_val2
));
4915 if(v
->post_user_val
.p
|| v
->main_user_val
.p
){
4918 active_var
= v
->post_user_val
.p
? v
->post_user_val
.p
4919 : v
->main_user_val
.p
;
4921 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4922 v
->name
, active_var
);
4925 snprintf(prompt
, sizeof(prompt
), _("Your setting for %s is %s"),
4926 v
->name
, _(empty_val2
));
4931 prompt
[sizeof(prompt
)-1] = '\0';
4934 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4935 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4937 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4938 prompt
[sizeof(prompt
)-1] = '\0';
4939 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4941 if(v
->main_user_val
.l
)
4943 if(v
->post_user_val
.l
)
4947 if(v
->main_user_val
.p
)
4949 if(v
->post_user_val
.p
)
4953 if(delete_user_vals(v
))
4961 * As always, feature-list has to be handled separately.
4963 exc
= (ps
->ew_for_except_vars
!= Main
);
4964 v
= &ps
->vars
[V_FEATURE_LIST
];
4965 list_fixed
= v
->fixed_val
.l
;
4967 for(j
= 0; j
< 2; j
++){
4968 plist
= (j
==0) ? &v
->main_user_val
.l
: &v
->post_user_val
.l
;
4971 for(i
= 0; list
[i
]; i
++){
4973 if(!struncmp(p
, "no-", 3))
4975 for(k
= 0; list_fixed
&& list_fixed
[k
]; k
++){
4977 if(!struncmp(q
, "no-", 3))
4979 if(!strucmp(q
, p
) && strucmp(list
[i
], list_fixed
[k
])){
4980 snprintf(prompt
, sizeof(prompt
), "Your %s is %s%s, fixed value is %s",
4981 p
, p
== list
[i
] ? _("ON") : _("OFF"),
4982 exc
? ((plist
== &v
->main_user_val
.l
) ? ""
4983 : " in postload-config")
4985 q
== list_fixed
[k
] ? _("ON") : _("OFF"));
4987 prompt
[sizeof(prompt
)-1] = '\0';
4988 if(utf8_width(prompt
) > ps
->ttyo
->screen_cols
- need
)
4989 (void) utf8_truncate(prompt
, ps
->ttyo
->screen_cols
- need
);
4991 (void) strncat(prompt
, clear
, sizeof(prompt
)-strlen(prompt
)-1);
4992 prompt
[sizeof(prompt
)-1] = '\0';
4993 if(want_to(prompt
, 'y', 'n', NO_HELP
, WT_NORM
) == 'y'){
4996 if(plist
== &v
->main_user_val
.l
)
5002 * Clear the feature from the user's pinerc
5003 * so that we'll stop bothering them when they
5006 clear_feature(plist
, p
);
5009 * clear_feature scoots the list up, so if list[i] was
5010 * the last one going in, now it is the end marker. We
5011 * just decrement i so that it will get incremented and
5012 * then test == 0 in the for loop. We could just goto
5013 * outta_here to accomplish the same thing.
5026 write_pinerc(ps
, Main
, WRP_NONE
);
5028 write_pinerc(ps
, Post
, WRP_NONE
);
5035 * Adjust side effects that happen because variable changes values.
5037 * Var->user_val should be set to the new value before calling this.
5040 fix_side_effects(struct pine
*ps
, struct variable
*var
, int revert
)
5043 char **v
, *q
, **apval
;
5044 struct variable
*vars
= ps
->vars
;
5046 /* move this up here so we get the Using default message */
5047 if(var
== &ps
->vars
[V_PERSONAL_NAME
]){
5048 if(!(var
->main_user_val
.p
||
5049 var
->post_user_val
.p
) && ps
->ui
.fullname
){
5050 if(var
->current_val
.p
)
5051 fs_give((void **)&var
->current_val
.p
);
5053 var
->current_val
.p
= cpystr(ps
->ui
.fullname
);
5060 && !(var
->main_user_val
.p
||
5061 var
->post_user_val
.p
)
5062 && var
->current_val
.p
)
5066 && !(var
->main_user_val
.l
||
5067 var
->post_user_val
.l
)
5068 && var
->current_val
.l
)))
5069 q_status_message(SM_ORDER
,0,3,_("Using default value"));
5071 if(var
== &ps
->vars
[V_USER_DOMAIN
]){
5074 if(ps
->VAR_USER_DOMAIN
5075 && ps
->VAR_USER_DOMAIN
[0]
5076 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5079 q_status_message2(SM_ORDER
, 3, 5,
5080 _("User-Domain (%s) cannot contain \"@\"; using %s"),
5081 ps
->VAR_USER_DOMAIN
, p
);
5082 q
= ps
->VAR_USER_DOMAIN
;
5083 while((*q
++ = *p
++) != '\0')
5088 q_status_message1(SM_ORDER
, 3, 5,
5089 _("User-domain (%s) cannot contain \"@\"; deleting"),
5090 ps
->VAR_USER_DOMAIN
);
5092 if(ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
){
5093 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].post_user_val
.p
);
5094 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5097 if(ps
->VAR_USER_DOMAIN
5098 && ps
->VAR_USER_DOMAIN
[0]
5099 && (p
= strrindex(ps
->VAR_USER_DOMAIN
, '@'))){
5100 if(ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
){
5101 fs_give((void **)&ps
->vars
[V_USER_DOMAIN
].main_user_val
.p
);
5102 set_current_val(&vars
[V_USER_DOMAIN
], TRUE
, TRUE
);
5109 * Reset various pointers pertaining to domain name and such...
5113 else if(var
== &ps
->vars
[V_INBOX_PATH
]){
5115 * fixup the inbox path based on global/default values...
5117 init_inbox_mapping(ps
->VAR_INBOX_PATH
, ps
->context_list
);
5119 if(!strucmp(ps
->cur_folder
, ps
->inbox_name
) && ps
->mail_stream
5120 && strcmp(ps
->VAR_INBOX_PATH
, ps
->mail_stream
->mailbox
)){
5122 * If we currently have "inbox" open and the mailbox name
5123 * doesn't match, reset the current folder's name and
5124 * remove the SP_INBOX flag.
5126 strncpy(ps
->cur_folder
, ps
->mail_stream
->mailbox
,
5127 sizeof(ps
->cur_folder
)-1);
5128 ps
->cur_folder
[sizeof(ps
->cur_folder
)-1] = '\0';
5129 sp_set_fldr(ps
->mail_stream
, ps
->cur_folder
);
5130 sp_unflag(ps
->mail_stream
, SP_INBOX
);
5131 ps
->mangled_header
= 1;
5133 else if(sp_inbox_stream()
5134 && strcmp(ps
->VAR_INBOX_PATH
, sp_inbox_stream()->original_mailbox
)){
5135 MAILSTREAM
*m
= sp_inbox_stream();
5138 * if we don't have inbox directly open, but have it
5139 * open for new mail notification, close the stream like
5140 * any other ordinary folder, and clean up...
5143 sp_unflag(m
, SP_PERMLOCKED
| SP_INBOX
);
5144 sp_set_fldr(m
, m
->mailbox
);
5145 expunge_and_close(m
, NULL
, EC_NONE
);
5149 else if(var
== &ps
->vars
[V_INCCHECKTIMEO
]){
5150 int old_value
= ps
->inc_check_timeout
;
5152 if(SVAR_INC_CHECK_TIMEO(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5154 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5157 ps
->inc_check_timeout
= 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_INCCHECKINTERVAL
]){
5163 int old_value
= ps
->inc_check_interval
;
5165 if(SVAR_INC_CHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5167 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5170 ps
->inc_check_interval
= old_value
;
5172 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5173 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5175 else if(var
== &ps
->vars
[V_INC2NDCHECKINTERVAL
]){
5176 int old_value
= ps
->inc_second_check_interval
;
5178 if(SVAR_INC_2NDCHECK_INTERV(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5180 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5183 ps
->inc_second_check_interval
= old_value
;
5185 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5186 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5188 else if(var
== &ps
->vars
[V_INCCHECKLIST
]){
5189 if(ps
->context_list
&& ps
->context_list
->use
& CNTXT_INCMNG
)
5190 reinit_incoming_folder_list(ps
, ps
->context_list
);
5192 if(!revert
&& (F_OFF(F_ENABLE_INCOMING
, ps
) || F_OFF(F_ENABLE_INCOMING_CHECKING
, ps
)))
5193 q_status_message(SM_ORDER
, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
5195 else if(var
== &ps
->vars
[V_ADDRESSBOOK
] ||
5196 var
== &ps
->vars
[V_GLOB_ADDRBOOK
] ||
5198 var
== &ps
->vars
[V_LDAP_SERVERS
] ||
5200 var
== &ps
->vars
[V_ABOOK_FORMATS
]){
5203 else if(var
== &ps
->vars
[V_INDEX_FORMAT
]){
5204 reset_index_format();
5205 clear_index_cache(ps
->mail_stream
, 0);
5207 else if(var
== &ps
->vars
[V_DEFAULT_FCC
] ||
5208 var
== &ps
->vars
[V_DEFAULT_SAVE_FOLDER
]){
5209 init_save_defaults();
5211 else if(var
== &ps
->vars
[V_KW_BRACES
] ||
5212 var
== &ps
->vars
[V_OPENING_SEP
] ||
5213 var
== &ps
->vars
[V_ALT_ADDRS
]){
5214 clear_index_cache(ps
->mail_stream
, 0);
5216 else if(var
== &ps
->vars
[V_KEYWORDS
]){
5217 if(ps_global
->keywords
)
5218 free_keyword_list(&ps_global
->keywords
);
5220 if(var
->current_val
.l
&& var
->current_val
.l
[0])
5221 ps_global
->keywords
= init_keyword_list(var
->current_val
.l
);
5223 clear_index_cache(ps
->mail_stream
, 0);
5225 else if(var
== &ps
->vars
[V_INIT_CMD_LIST
]){
5227 q_status_message(SM_ASYNC
, 0, 3,
5228 _("Initial command changes will affect your next Alpine session."));
5230 else if(var
== &ps
->vars
[V_VIEW_HEADERS
]){
5231 ps
->view_all_except
= 0;
5232 if(ps
->VAR_VIEW_HEADERS
)
5233 for(v
= ps
->VAR_VIEW_HEADERS
; (q
= *v
) != NULL
; v
++)
5237 removing_leading_white_space(q
);
5238 /* look for colon or space or end */
5239 for(p
= q
; *p
&& !isspace((unsigned char)*p
) && *p
!= ':'; p
++)
5243 if(strucmp(q
, ALL_EXCEPT
) == 0)
5244 ps
->view_all_except
= 1;
5247 else if(var
== &ps
->vars
[V_OVERLAP
]){
5248 int old_value
= ps
->viewer_overlap
;
5250 if(SVAR_OVERLAP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5252 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5255 ps
->viewer_overlap
= old_value
;
5257 else if(var
== &ps
->vars
[V_SLEEP
]){
5258 int old_value
= ps
->sleep
;
5260 if(SVAR_SLEEP(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5262 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5265 ps
->sleep
= old_value
;
5268 else if(smime_related_var(ps
, var
)){
5272 else if(var
== &ps
->vars
[V_MAXREMSTREAM
]){
5273 int old_value
= ps
->s_pool
.max_remstream
;
5275 if(SVAR_MAXREMSTREAM(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5277 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5280 ps
->s_pool
.max_remstream
= old_value
;
5282 dprint((9, "max_remstream goes to %d\n",
5283 ps
->s_pool
.max_remstream
));
5286 else if(var
== &ps
->vars
[V_CHAR_SET
]){
5289 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5291 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5294 if(reset_character_set_stuff(&err
) == -1)
5295 alpine_panic(err
? err
: "trouble with Character-Set");
5297 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5298 fs_give((void **) &err
);
5302 else if(var
== &ps
->vars
[V_KEY_CHAR_SET
]){
5305 if(F_ON(F_USE_SYSTEM_TRANS
, ps
)){
5307 q_status_message(SM_ORDER
, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
5310 if(reset_character_set_stuff(&err
) == -1)
5311 alpine_panic(err
? err
: "trouble with Character-Set");
5313 q_status_message(SM_ORDER
| SM_DING
, 3, 5, err
);
5314 fs_give((void **) &err
);
5318 #endif /* ! _WINDOWS */
5319 else if(var
== &ps
->vars
[V_POST_CHAR_SET
]){
5320 update_posting_charset(ps
, revert
);
5322 else if(var
== &ps
->vars
[V_MARGIN
]){
5323 int old_value
= ps
->scroll_margin
;
5325 if(SVAR_MARGIN(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5327 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5330 ps
->scroll_margin
= old_value
;
5332 else if(var
== &ps
->vars
[V_DEADLETS
]){
5333 int old_value
= ps
->deadlets
;
5335 if(SVAR_DEADLETS(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5337 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5340 ps
->deadlets
= old_value
;
5342 else if(var
== &ps
->vars
[V_FILLCOL
]){
5343 if(SVAR_FILLCOL(ps
, ps
->composer_fillcol
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5345 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5348 else if(var
== &ps
->vars
[V_QUOTE_SUPPRESSION
]){
5349 val
= ps
->quote_suppression_threshold
;
5350 if(val
< Q_SUPP_LIMIT
&& val
> 0)
5353 if(ps
->VAR_QUOTE_SUPPRESSION
5354 && SVAR_QUOTE_SUPPRESSION(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5356 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5359 if(val
> 0 && val
< Q_SUPP_LIMIT
){
5361 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, _("Ignoring Quote-Suppression-Threshold value of %s, see help"), ps
->VAR_QUOTE_SUPPRESSION
);
5362 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
5363 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5367 if(val
< 0 && val
!= Q_DEL_ALL
)
5368 ps
->quote_suppression_threshold
= -val
;
5370 ps
->quote_suppression_threshold
= val
;
5374 else if(var
== &ps
->vars
[V_STATUS_MSG_DELAY
]){
5375 if(SVAR_MSGDLAY(ps
, ps
->status_msg_delay
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5377 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5380 else if(var
== &ps
->vars
[V_ACTIVE_MSG_INTERVAL
]){
5381 if(SVAR_ACTIVEINTERVAL(ps
, ps
->active_status_interval
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5383 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5386 busy_cue(_("Active Example"), NULL
, 0);
5388 cancel_busy_cue(-1);
5391 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
5392 else if(var
== &ps
->vars
[V_FIFOPATH
]){
5393 init_newmailfifo(ps
->VAR_FIFOPATH
);
5396 else if(var
== &ps
->vars
[V_NMW_WIDTH
]){
5397 int old_value
= ps
->nmw_width
;
5399 if(SVAR_NMW_WIDTH(ps
, old_value
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5401 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5405 if(old_value
!= ps
->nmw_width
)
5406 mswin_setnewmailwidth(old_value
); /* actually the new value */
5408 ps
->nmw_width
= old_value
;
5411 else if(var
== &ps
->vars
[V_TCPOPENTIMEO
]){
5414 if(ps
->VAR_TCPOPENTIMEO
&& SVAR_TCP_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5415 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5417 else if(var
== &ps
->vars
[V_TCPREADWARNTIMEO
]){
5420 if(ps
->VAR_TCPREADWARNTIMEO
&& SVAR_TCP_READWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5421 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5423 else if(var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
]){
5426 if(ps
->VAR_TCPWRITEWARNTIMEO
&& SVAR_TCP_WRITEWARN(ps
,val
,tmp_20k_buf
, SIZEOF_20KBUF
))
5427 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5429 else if(var
== &ps
->vars
[V_TCPQUERYTIMEO
]){
5432 if(ps
->VAR_TCPQUERYTIMEO
&& SVAR_TCP_QUERY(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5433 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5435 else if(var
== &ps
->vars
[V_RSHOPENTIMEO
]){
5438 if(ps
->VAR_RSHOPENTIMEO
&& SVAR_RSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5439 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5441 else if(var
== &ps
->vars
[V_SSHOPENTIMEO
]){
5444 if(ps
->VAR_SSHOPENTIMEO
&& SVAR_SSH_OPEN(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
))
5445 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5447 else if(var
== &ps
->vars
[V_SIGNATURE_FILE
]){
5448 if(ps
->VAR_OPER_DIR
&& ps
->VAR_SIGNATURE_FILE
&&
5449 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
5450 !in_dir(ps
->VAR_OPER_DIR
, ps
->VAR_SIGNATURE_FILE
)){
5454 l
= strlen(ps
->VAR_OPER_DIR
) + 100;
5455 e
= (char *) fs_get((l
+1) * sizeof(char));
5456 snprintf(e
, l
+1, _("Warning: Sig file can't be outside of %s"),
5459 q_status_message(SM_ORDER
, 3, 6, e
);
5460 fs_give((void **)&e
);
5463 else if(var
== &ps
->vars
[V_OPER_DIR
]){
5464 if(ps
->VAR_OPER_DIR
&& !ps
->VAR_OPER_DIR
[0]){
5465 q_status_message(SM_ORDER
, 3, 5, "Operating-dir is turned off.");
5466 fs_give((void **)&ps
->vars
[V_OPER_DIR
].current_val
.p
);
5467 if(ps
->vars
[V_OPER_DIR
].fixed_val
.p
)
5468 fs_give((void **)&ps
->vars
[V_OPER_DIR
].fixed_val
.p
);
5469 if(ps
->vars
[V_OPER_DIR
].global_val
.p
)
5470 fs_give((void **)&ps
->vars
[V_OPER_DIR
].global_val
.p
);
5471 if(ps
->vars
[V_OPER_DIR
].cmdline_val
.p
)
5472 fs_give((void **)&ps
->vars
[V_OPER_DIR
].cmdline_val
.p
);
5473 if(ps
->vars
[V_OPER_DIR
].post_user_val
.p
)
5474 fs_give((void **)&ps
->vars
[V_OPER_DIR
].post_user_val
.p
);
5475 if(ps
->vars
[V_OPER_DIR
].main_user_val
.p
)
5476 fs_give((void **)&ps
->vars
[V_OPER_DIR
].main_user_val
.p
);
5479 else if(var
== &ps
->vars
[V_MAILCHECK
]){
5481 if(SVAR_MAILCHK(ps
, timeo
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5482 set_input_timeout(15);
5484 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5487 set_input_timeout(timeo
);
5488 if(get_input_timeout() == 0 && !revert
){
5489 q_status_message(SM_ORDER
, 4, 6,
5490 _("Warning: automatic new mail checking and mailbox checkpointing is disabled"));
5491 if(ps
->VAR_INBOX_PATH
&& ps
->VAR_INBOX_PATH
[0] == '{')
5492 q_status_message(SM_ASYNC
, 3, 6,
5493 _("Warning: Mail-Check-Interval=0 may cause IMAP server connection to time out"));
5497 else if(var
== &ps
->vars
[V_MAILCHECKNONCURR
]){
5498 val
= (int) ps
->check_interval_for_noncurr
;
5499 if(ps
->VAR_MAILCHECKNONCURR
5500 && SVAR_MAILCHKNONCURR(ps
, val
, tmp_20k_buf
, SIZEOF_20KBUF
)){
5502 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5505 ps
->check_interval_for_noncurr
= (time_t) val
;
5507 else if(var
== &ps
->vars
[V_MAILDROPCHECK
]){
5511 if(ps
->VAR_MAILDROPCHECK
&& SVAR_MAILDCHK(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5512 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5515 rvl
= (60L * 60L * 24L * 100L); /* 100 days */
5518 mail_parameters(NULL
, SET_SNARFINTERVAL
, (void *) rvl
);
5521 else if(var
== &ps
->vars
[V_NNTPRANGE
]){
5525 if(ps
->VAR_NNTPRANGE
&& SVAR_NNTPRANGE(ps
, rvl
, tmp_20k_buf
, SIZEOF_20KBUF
))
5526 q_status_message(SM_ORDER
, 3, 5, tmp_20k_buf
);
5529 mail_parameters(NULL
, SET_NNTPRANGE
, (void *) rvl
);
5532 else if(var
== &ps
->vars
[V_CUSTOM_HDRS
] || var
== &ps
->vars
[V_COMP_HDRS
]){
5533 /* this will give warnings about headers that can't be changed */
5534 if(!revert
&& var
->current_val
.l
&& var
->current_val
.l
[0])
5535 customized_hdr_setup(NULL
, var
->current_val
.l
, UseAsDef
);
5537 #if defined(DOS) || defined(OS2)
5538 else if(var
== &ps
->vars
[V_FOLDER_EXTENSION
]){
5539 mail_parameters(NULL
, SET_EXTENSION
,
5540 (void *)var
->current_val
.p
);
5542 else if(var
== &ps
->vars
[V_NEWSRC_PATH
]){
5543 if(var
->current_val
.p
&& var
->current_val
.p
[0])
5544 mail_parameters(NULL
, SET_NEWSRC
,
5545 (void *)var
->current_val
.p
);
5548 else if(revert
&& standard_radio_var(ps
, var
)){
5550 cur_rule_value(var
, TRUE
, FALSE
);
5551 if(var
== &ps_global
->vars
[V_AB_SORT_RULE
])
5552 addrbook_redo_sorts();
5553 else if(var
== &ps_global
->vars
[V_THREAD_INDEX_STYLE
]){
5554 clear_index_cache(ps_global
->mail_stream
, 0);
5555 set_lflags(ps_global
->mail_stream
, ps_global
->msgmap
,
5556 MN_COLL
| MN_CHID
, 0);
5557 if(SORT_IS_THREADED(ps_global
->msgmap
)
5558 && (SEP_THRDINDX() || COLL_THRDS()))
5559 collapse_threads(ps_global
->mail_stream
, ps_global
->msgmap
, NULL
);
5561 adjust_cur_to_visible(ps_global
->mail_stream
, ps_global
->msgmap
);
5564 else if(var
== &ps
->vars
[V_COLOR_STYLE
]){
5565 pico_toggle_color(0);
5566 switch(ps
->color_style
){
5569 pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT
: 0);
5572 pico_set_color_options(COLOR_ANSI8_OPT
|COLOR_TRANS_OPT
);
5575 pico_set_color_options(COLOR_ANSI16_OPT
|COLOR_TRANS_OPT
);
5578 pico_set_color_options(COLOR_ANSI256_OPT
|COLOR_TRANS_OPT
);
5582 if(ps
->color_style
!= COL_NONE
)
5583 pico_toggle_color(1);
5585 if(pico_usingcolor())
5586 pico_set_normal_color();
5588 clear_index_cache(ps_global
->mail_stream
, 0);
5590 ps
->mangled_screen
= 1;
5594 else if(revert
&& var
== &ps
->vars
[V_SORT_KEY
]){
5597 decode_sort(VAR_SORT_KEY
, &ps
->def_sort
, &def_sort_rev
);
5598 ps
->def_sort_rev
= def_sort_rev
;
5600 else if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5601 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5602 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5604 if(var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
] &&
5605 !(var
->current_val
.p
&& var
->current_val
.p
[0])){
5606 if(var
->current_val
.p
)
5607 fs_give((void **) &var
->current_val
.p
);
5609 q_status_message1(SM_ORDER
, 3, 5,
5610 _("\"%s\" can't be Empty, using default"), var
->name
);
5612 apval
= APVAL(var
, ew
);
5614 fs_give((void **)apval
);
5616 set_current_val(var
, FALSE
, FALSE
);
5618 if(!(var
->current_val
.p
&& var
->current_val
.p
[0]
5619 && !var
->current_val
.p
[1])){
5620 if(var
->current_val
.p
)
5621 fs_give((void **) &var
->current_val
.p
);
5623 var
->current_val
.p
= cpystr(DF_THREAD_LASTREPLY_CHAR
);
5627 if(var
== &ps
->vars
[V_THREAD_MORE_CHAR
] ||
5628 var
== &ps
->vars
[V_THREAD_EXP_CHAR
] ||
5629 var
== &ps
->vars
[V_THREAD_LASTREPLY_CHAR
]){
5630 if(var
->current_val
.p
&& var
->current_val
.p
[0] &&
5631 var
->current_val
.p
[1]){
5632 q_status_message1(SM_ORDER
, 3, 5,
5633 "Only first character of \"%s\" is used",
5635 var
->current_val
.p
[1] = '\0';
5638 if(var
->main_user_val
.p
&& var
->main_user_val
.p
[0] &&
5639 var
->main_user_val
.p
[1])
5640 var
->main_user_val
.p
[1] = '\0';
5642 if(var
->post_user_val
.p
&& var
->post_user_val
.p
[0] &&
5643 var
->post_user_val
.p
[1])
5644 var
->post_user_val
.p
[1] = '\0';
5647 clear_index_cache(ps_global
->mail_stream
, 0);
5648 set_need_format_setup(ps_global
->mail_stream
);
5650 else if(var
== &ps
->vars
[V_NNTP_SERVER
]){
5651 free_contexts(&ps_global
->context_list
);
5652 init_folders(ps_global
);
5654 else if(var
== &ps
->vars
[V_USE_ONLY_DOMAIN_NAME
]){
5657 else if(var
== &ps
->vars
[V_PRINTER
]){
5658 if(!revert
&& ps
->vars
[V_PERSONAL_PRINT_COMMAND
].is_fixed
){
5659 if(printer_value_check_and_adjust())
5660 q_status_message1(SM_ORDER
, 3, 5,
5661 _("Can't set \"%s\" to that value, see Setup/Printer"),
5662 pretty_var_name(var
->name
));
5665 else if(var
== &ps
->vars
[V_KW_COLORS
] ||
5666 var
== &ps
->vars
[V_INDEX_TOKEN_COLORS
] ||
5667 var
== &ps
->vars
[V_IND_PLUS_FORE_COLOR
] ||
5668 var
== &ps
->vars
[V_IND_IMP_FORE_COLOR
] ||
5669 var
== &ps
->vars
[V_IND_DEL_FORE_COLOR
] ||
5670 var
== &ps
->vars
[V_IND_ANS_FORE_COLOR
] ||
5671 var
== &ps
->vars
[V_IND_NEW_FORE_COLOR
] ||
5672 var
== &ps
->vars
[V_IND_UNS_FORE_COLOR
] ||
5673 var
== &ps
->vars
[V_IND_HIPRI_FORE_COLOR
]||
5674 var
== &ps
->vars
[V_IND_LOPRI_FORE_COLOR
]||
5675 var
== &ps
->vars
[V_IND_ARR_FORE_COLOR
] ||
5676 var
== &ps
->vars
[V_IND_REC_FORE_COLOR
] ||
5677 var
== &ps
->vars
[V_IND_FWD_FORE_COLOR
] ||
5678 var
== &ps
->vars
[V_IND_OP_FORE_COLOR
] ||
5679 var
== &ps
->vars
[V_IND_FROM_FORE_COLOR
] ||
5680 var
== &ps
->vars
[V_IND_SUBJ_FORE_COLOR
] ||
5681 var
== &ps
->vars
[V_IND_PLUS_BACK_COLOR
] ||
5682 var
== &ps
->vars
[V_IND_IMP_BACK_COLOR
] ||
5683 var
== &ps
->vars
[V_IND_DEL_BACK_COLOR
] ||
5684 var
== &ps
->vars
[V_IND_ANS_BACK_COLOR
] ||
5685 var
== &ps
->vars
[V_IND_NEW_BACK_COLOR
] ||
5686 var
== &ps
->vars
[V_IND_UNS_BACK_COLOR
] ||
5687 var
== &ps
->vars
[V_IND_ARR_BACK_COLOR
] ||
5688 var
== &ps
->vars
[V_IND_REC_BACK_COLOR
] ||
5689 var
== &ps
->vars
[V_IND_FWD_BACK_COLOR
] ||
5690 var
== &ps
->vars
[V_IND_OP_BACK_COLOR
] ||
5691 var
== &ps
->vars
[V_IND_FROM_BACK_COLOR
] ||
5692 var
== &ps
->vars
[V_IND_SUBJ_BACK_COLOR
]){
5693 clear_index_cache(ps_global
->mail_stream
, 0);
5695 else if(var
== score_act_global_ptr
){
5698 score
= atoi(var
->current_val
.p
);
5699 if(score
< SCORE_MIN
|| score
> SCORE_MAX
){
5700 q_status_message2(SM_ORDER
, 3, 5,
5701 _("Score Value must be in range %s to %s"),
5702 comatose(SCORE_MIN
), comatose(SCORE_MAX
));
5703 apval
= APVAL(var
, ew
);
5705 fs_give((void **)apval
);
5707 set_current_val(var
, FALSE
, FALSE
);
5710 else if(var
== scorei_pat_global_ptr
|| var
== age_pat_global_ptr
5711 || var
== size_pat_global_ptr
|| var
== cati_global_ptr
){
5712 apval
= APVAL(var
, ew
);
5715 iv
= parse_intvl(*apval
);
5717 fs_give((void **) apval
);
5718 *apval
= stringform_of_intvl(iv
);
5722 fs_give((void **) apval
);
5725 set_current_val(var
, FALSE
, FALSE
);
5727 else if(var
== &ps
->vars
[V_FEATURE_LIST
]){
5728 process_feature_list(ps
, var
->current_val
.l
, 0, 0, 0);
5730 else if(!revert
&& (var
== &ps
->vars
[V_LAST_TIME_PRUNE_QUESTION
] ||
5731 var
== &ps
->vars
[V_REMOTE_ABOOK_HISTORY
] ||
5732 var
== &ps
->vars
[V_REMOTE_ABOOK_VALIDITY
] ||
5733 var
== &ps
->vars
[V_USERINPUTTIMEO
] ||
5734 var
== &ps
->vars
[V_NEWS_ACTIVE_PATH
] ||
5735 var
== &ps
->vars
[V_NEWS_SPOOL_DIR
] ||
5736 var
== &ps
->vars
[V_INCOMING_FOLDERS
] ||
5737 var
== &ps
->vars
[V_FOLDER_SPEC
] ||
5738 var
== &ps
->vars
[V_NEWS_SPEC
] ||
5739 var
== &ps
->vars
[V_DISABLE_DRIVERS
] ||
5740 var
== &ps
->vars
[V_DISABLE_AUTHS
] ||
5741 var
== &ps
->vars
[V_RSHPATH
] ||
5742 var
== &ps
->vars
[V_RSHCMD
] ||
5743 var
== &ps
->vars
[V_SSHCMD
] ||
5744 var
== &ps
->vars
[V_SSHPATH
])){
5745 q_status_message2(SM_ASYNC
, 0, 3,
5746 _("Changes%s%s will affect your next Alpine session."),
5747 var
->name
? " to " : "", var
->name
? var
->name
: "");
5750 if(!revert
&& (var
== &ps
->vars
[V_TCPOPENTIMEO
] ||
5751 var
== &ps
->vars
[V_TCPREADWARNTIMEO
] ||
5752 var
== &ps
->vars
[V_TCPWRITEWARNTIMEO
] ||
5753 var
== &ps
->vars
[V_TCPQUERYTIMEO
] ||
5754 var
== &ps
->vars
[V_RSHOPENTIMEO
] ||
5755 var
== &ps
->vars
[V_SSHOPENTIMEO
]))
5756 q_status_message(SM_ASYNC
, 0, 3,
5757 _("Timeout changes will affect your next Alpine session."));
5762 * Compare saved user_val with current user_val to see if it changed.
5763 * If any have changed, change it back and take the appropriate action.
5766 revert_to_saved_config(struct pine
*ps
, SAVED_CONFIG_S
*vsave
, int allow_hard_to_config_remotely
)
5768 struct variable
*vreal
;
5772 char *pval
, **apval
, **lval
, ***alval
;
5775 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5776 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5781 lval
= LVAL(vreal
, ew
);
5782 alval
= ALVAL(vreal
, ew
);
5784 if((v
->saved_user_val
.l
&& !lval
)
5785 || (!v
->saved_user_val
.l
&& lval
))
5787 else if(!v
->saved_user_val
.l
&& !lval
)
5788 ;/* no change, nothing to do */
5790 for(i
= 0; v
->saved_user_val
.l
[i
] || lval
[i
]; i
++)
5791 if((v
->saved_user_val
.l
[i
]
5793 || strcmp(v
->saved_user_val
.l
[i
], lval
[i
])))
5795 (!v
->saved_user_val
.l
[i
] && lval
[i
])){
5805 free_list_array(alval
);
5807 /* copy back the original one */
5808 if(v
->saved_user_val
.l
){
5809 list
= v
->saved_user_val
.l
;
5811 /* count how many */
5815 *alval
= (char **)fs_get((n
+1) * sizeof(char *));
5817 for(i
= 0; i
< n
; i
++)
5818 (*alval
)[i
] = cpystr(v
->saved_user_val
.l
[i
]);
5826 pval
= PVAL(vreal
, ew
);
5827 apval
= APVAL(vreal
, ew
);
5829 if((v
->saved_user_val
.p
&&
5830 (!pval
|| strcmp(v
->saved_user_val
.p
, pval
))) ||
5831 (!v
->saved_user_val
.p
&& pval
)){
5832 /* It changed, fix it */
5835 /* free the changed value */
5837 fs_give((void **)apval
);
5839 if(v
->saved_user_val
.p
)
5840 *apval
= cpystr(v
->saved_user_val
.p
);
5846 if(vreal
== &ps
->vars
[V_FEATURE_LIST
])
5847 set_feature_list_current_val(vreal
);
5849 set_current_val(vreal
, TRUE
, FALSE
);
5851 fix_side_effects(ps
, vreal
, 1);
5858 save_config_vars(struct pine
*ps
, int allow_hard_to_config_remotely
)
5860 struct variable
*vreal
;
5861 SAVED_CONFIG_S
*vsave
, *v
;
5863 vsave
= (SAVED_CONFIG_S
*)fs_get((V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5864 memset((void *)vsave
, 0, (V_LAST_VAR
+1)*sizeof(SAVED_CONFIG_S
));
5866 for(vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5867 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5874 if(LVAL(vreal
, ew
)){
5875 /* count how many */
5877 list
= LVAL(vreal
, ew
);
5881 v
->saved_user_val
.l
= (char **)fs_get((n
+1) * sizeof(char *));
5882 memset((void *)v
->saved_user_val
.l
, 0, (n
+1)*sizeof(char *));
5883 for(i
= 0; i
< n
; i
++)
5884 v
->saved_user_val
.l
[i
] = cpystr(list
[i
]);
5886 v
->saved_user_val
.l
[n
] = NULL
;
5891 v
->saved_user_val
.p
= cpystr(PVAL(vreal
, ew
));
5900 free_saved_config(struct pine
*ps
, SAVED_CONFIG_S
**vsavep
, int allow_hard_to_config_remotely
)
5902 struct variable
*vreal
;
5905 if(vsavep
&& *vsavep
){
5906 for(v
= *vsavep
, vreal
= ps
->vars
; vreal
->name
; vreal
++,v
++){
5907 if(!save_include(ps
, vreal
, allow_hard_to_config_remotely
))
5910 if(vreal
->is_list
){ /* free saved_user_val.l */
5911 if(v
&& v
->saved_user_val
.l
)
5912 free_list_array(&v
->saved_user_val
.l
);
5914 else if(v
&& v
->saved_user_val
.p
)
5915 fs_give((void **)&v
->saved_user_val
.p
);
5918 fs_give((void **)vsavep
);
5924 * Returns positive if any thing was actually deleted.
5927 delete_user_vals(struct variable
*v
)
5933 if(v
->post_user_val
.l
){
5935 free_list_array(&v
->post_user_val
.l
);
5937 if(v
->main_user_val
.l
){
5939 free_list_array(&v
->main_user_val
.l
);
5943 if(v
->post_user_val
.p
){
5945 fs_give((void **)&v
->post_user_val
.p
);
5947 if(v
->main_user_val
.p
){
5949 fs_give((void **)&v
->main_user_val
.p
);
5959 * ../pith/conf.c required function
5962 unexpected_pinerc_change(void)
5965 if(want_to("Unexpected pinerc change! Overwrite with current config",
5966 'n', 0, NO_HELP
, WT_FLUSH_IN
) == 'n'){
5967 return(-1); /* abort pinerc write */
5970 return(0); /* overwrite */
5976 /*----------------------------------------------------------------------
5977 MSWin scroll callback. Called during scroll message processing.
5981 Args: cmd - what type of scroll operation.
5982 scroll_pos - paramter for operation.
5983 used as position for SCROLL_TO operation.
5985 Returns: TRUE - did the scroll operation.
5986 FALSE - was not able to do the scroll operation.
5989 config_scroll_callback (cmd
, scroll_pos
)
5994 case MSWIN_KEY_SCROLLUPLINE
:
5995 config_scroll_down (scroll_pos
);
5998 case MSWIN_KEY_SCROLLDOWNLINE
:
5999 config_scroll_up (scroll_pos
);
6002 case MSWIN_KEY_SCROLLUPPAGE
:
6003 config_scroll_down (BODY_LINES(ps_global
));
6006 case MSWIN_KEY_SCROLLDOWNPAGE
:
6007 config_scroll_up (BODY_LINES(ps_global
));
6010 case MSWIN_KEY_SCROLLTO
:
6011 config_scroll_to_pos (scroll_pos
);
6015 option_screen_redrawer();
6021 #endif /* _WINDOWS */