2 * ========================================================================
3 * Copyright 2006-2008 University of Washington
4 * Copyright 2013-2022 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
17 #include "colorconf.h"
19 #include "confscroll.h"
28 #include "../pith/state.h"
29 #include "../pith/conf.h"
30 #include "../pith/msgno.h"
31 #include "../pith/bitmap.h"
32 #include "../pith/sort.h"
33 #include "../pith/addrstring.h"
34 #include "../pith/list.h"
35 #include "../pith/flag.h"
36 #include "../pith/bldaddr.h"
37 #include "../pith/news.h"
38 #include "../pith/util.h"
39 #include "../pith/detoken.h"
40 #include "../pith/icache.h"
41 #include "../pith/ablookup.h"
42 #include "../pith/pattern.h"
43 #include "../pith/tempfile.h"
50 #define ARB_HELP _("HELP FOR ARBITRARY HEADER PATTERNS")
51 #define ADDXHDRS _("Add Extra Headers")
57 int role_select_tool(struct pine
*, int, CONF_S
**, unsigned);
58 PATTERN_S
*addrlst_to_pattern(ADDRESS
*);
59 void role_config_init_disp(struct pine
*, CONF_S
**, long, PAT_STATE
*);
60 void add_patline_to_display(struct pine
*, CONF_S
**, int, CONF_S
**, CONF_S
**, PAT_LINE_S
*, long);
61 void add_role_to_display(CONF_S
**, PAT_LINE_S
*, PAT_S
*, int, CONF_S
**, int, long);
62 void add_fake_first_role(CONF_S
**, int, long);
63 int role_config_tool(struct pine
*, int, CONF_S
**, unsigned);
64 int role_config_add(struct pine
*, CONF_S
**, long);
65 int role_config_replicate(struct pine
*, CONF_S
**, long);
66 int role_config_edit(struct pine
*, CONF_S
**, long);
67 int role_config_del(struct pine
*, CONF_S
**, long);
68 void delete_a_role(CONF_S
**, long);
69 int role_config_shuffle(struct pine
*, CONF_S
**);
70 int role_config_addfile(struct pine
*, CONF_S
**, long);
71 int role_config_delfile(struct pine
*, CONF_S
**, long);
72 void swap_literal_roles(CONF_S
*, CONF_S
*);
73 void swap_file_roles(CONF_S
*, CONF_S
*);
74 void move_role_into_file(CONF_S
**, int);
75 void move_role_outof_file(CONF_S
**, int);
76 void move_role_around_file(CONF_S
**, int);
77 int role_config_edit_screen(struct pine
*, PAT_S
*, char *, long, PAT_S
**);
78 void setup_dummy_pattern_var(struct variable
*, char *, PATTERN_S
*);
79 void setup_role_pat(struct pine
*, CONF_S
**, struct variable
*, HelpType
, char *,
81 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
83 void setup_role_pat_alt(struct pine
*, CONF_S
**, struct variable
*, HelpType
, char *,
85 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
87 void free_earb(EARB_S
**);
88 void calculate_inick_stuff(struct pine
*);
89 int check_role_folders(char **, unsigned);
90 void maybe_add_to_incoming(CONTEXT_S
*, char *);
91 int role_filt_exitcheck(CONF_S
**, unsigned);
92 int role_filt_text_tool(struct pine
*, int, CONF_S
**, unsigned);
93 int role_filt_addhdr_tool(struct pine
*, int, CONF_S
**, unsigned);
94 int role_addhdr_tool(struct pine
*, int, CONF_S
**, unsigned);
95 int role_filt_radiobutton_tool(struct pine
*, int, CONF_S
**, unsigned);
96 int role_sort_tool(struct pine
*, int, CONF_S
**, unsigned);
97 char **get_role_specific_folder(CONF_S
**);
98 int role_litsig_text_tool(struct pine
*, int, CONF_S
**, unsigned);
99 int role_cstm_text_tool(struct pine
*, int, CONF_S
**, unsigned);
100 int role_text_tool(struct pine
*, int, CONF_S
**, unsigned);
101 int role_text_tool_inick(struct pine
*, int, CONF_S
**, unsigned);
102 int role_text_tool_kword(struct pine
*, int, CONF_S
**, unsigned);
103 int role_text_tool_charset(struct pine
*, int, CONF_S
**, unsigned);
104 int role_text_tool_afrom(struct pine
*, int, CONF_S
**, unsigned);
105 char *role_type_print(char *, size_t, char *, long);
106 int feat_checkbox_tool(struct pine
*, int, CONF_S
**, unsigned);
107 void toggle_feat_option_bit(struct pine
*, int, struct variable
*, char *);
108 NAMEVAL_S
*feat_feature_list(int);
109 int inabook_checkbox_tool(struct pine
*, int, CONF_S
**, unsigned);
110 void toggle_inabook_type_bit(struct pine
*, int, struct variable
*, char *);
111 NAMEVAL_S
*inabook_feature_list(int);
114 static char *set_choose
= "--- --------------------";
115 static long role_global_flags
;
116 static PAT_STATE
*role_global_pstate
;
120 role_select_screen(struct pine
*ps
, ACTION_S
**role
, int alt_compose
)
122 CONF_S
*ctmp
= NULL
, *first_line
= NULL
;
124 PAT_S
*pat
, *sel_pat
= NULL
;
126 int change_default
= 0;
127 long rflags
= ROLE_DO_ROLES
;
137 if(!(nonempty_patterns(rflags
, &pstate
) &&
138 first_pattern(&pstate
))){
139 q_status_message(SM_ORDER
, 3, 3,
140 _("No roles available. Use Setup/Rules to add roles."));
146 menu_init_binding(&role_select_km
,
147 alt_compose
== MC_FORWARD
? 'F' :
148 alt_compose
== MC_REPLY
? 'R' :
149 alt_compose
== MC_COMPOSE
? 'C' : 'B',
151 alt_compose
== MC_FORWARD
? "F" :
152 alt_compose
== MC_REPLY
? "R" :
153 alt_compose
== MC_COMPOSE
? "C" : "B",
154 alt_compose
== MC_FORWARD
? "[" N_("ForwardAs") "]" :
155 alt_compose
== MC_REPLY
? "[" N_("ReplyAs") "]" :
156 alt_compose
== MC_COMPOSE
? "[" N_("ComposeAs") "]" : "[" N_("BounceAs") "]",
158 menu_add_binding(&role_select_km
, ctrl('J'), MC_CHOICE
);
159 menu_add_binding(&role_select_km
, ctrl('M'), MC_CHOICE
);
162 menu_init_binding(&role_select_km
, 'S', MC_CHOICE
, "S", "[" N_("Select") "]",
164 menu_add_binding(&role_select_km
, ctrl('J'), MC_CHOICE
);
165 menu_add_binding(&role_select_km
, ctrl('M'), MC_CHOICE
);
168 help
= h_role_select
;
169 if(alt_compose
== MC_BOUNCE
)
170 helptitle
= _("HELP FOR SELECTING A ROLE TO BOUNCE AS");
172 helptitle
= _("HELP FOR SELECTING A ROLE TO COMPOSE AS");
174 helptitle
= _("HELP FOR SELECTING A ROLE");
176 menu_init_binding(&role_select_km
, 'D', MC_TOGGLE
, "D", "changeDef", CHANGEDEF_KEY
);
178 for(pat
= first_pattern(&pstate
);
180 pat
= next_pattern(&pstate
)){
185 ctmp
->value
= cpystr((pat
->patgrp
&& pat
->patgrp
->nick
)
186 ? pat
->patgrp
->nick
: "?");
187 ctmp
->d
.r
.selected
= &sel_pat
;
189 ctmp
->d
.r
.change_def
= &change_default
;
190 ctmp
->keymenu
= &role_select_km
;
192 ctmp
->help_title
= helptitle
;
193 ctmp
->tool
= role_select_tool
;
194 ctmp
->flags
= CF_STARTITEM
;
198 memset(&screen
, 0, sizeof(screen
));
199 /* TRANSLATORS: Print something1 using something2.
200 "roles" is something1 */
201 (void)conf_scroll_screen(ps
, &screen
, first_line
, _("SELECT ROLE"),
202 _("roles"), 0, NULL
);
205 *role
= sel_pat
->action
;
206 if(change_default
== 1)
207 ps_global
->default_role
= *role
;
208 else if(change_default
== 2)
209 ps_global
->default_role
= NULL
;
214 ps
->mangled_screen
= 1;
220 role_select_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
222 int retval
= 0, newval
;
226 *((*cl
)->d
.r
.selected
) = (*cl
)->d
.r
.pat
;
227 retval
= simple_exit_cmd(flags
);
231 newval
= (*((*cl
)->d
.r
.change_def
) + 1) % 3;
232 *((*cl
)->d
.r
.change_def
) = newval
;
233 menu_init_binding((*cl
)->keymenu
, 'D', MC_TOGGLE
, "D",
234 (newval
== 0) ? "changeDef" : (newval
== 1) ? "removeDef" : "leaveDef",
237 if(ps_global
->default_role
)
238 q_status_message(SM_ORDER
, 0, 3,
239 _("Default role will be changed to the role you Select"));
241 q_status_message(SM_ORDER
, 0, 3,
242 _("Default role will be set to the role you Select"));
244 else if(newval
== 2){
245 q_status_message(SM_ORDER
, 0, 3, _("Default role will be unset"));
247 else{ /* newval == 0 */
248 if(ps_global
->default_role
)
249 q_status_message(SM_ORDER
, 0, 3, _("Default role will remain unchanged"));
251 q_status_message(SM_ORDER
, 0, 3, _("Default role will remain unset"));
254 ps
->mangled_footer
= 1;
259 retval
= simple_exit_cmd(flags
);
268 ps
->mangled_body
= 1;
275 role_config_screen(struct pine
*ps
, long int rflags
, int edit_exceptions
)
280 int readonly_warning
= 0;
282 struct variable
*v
= NULL
;
284 dprint((4, "role_config_screen()\n"));
286 if(ps
->fix_fixed_warning
)
287 offer_to_fix_pinerc(ps
);
289 ew
= edit_exceptions
? ps_global
->ew_for_except_vars
: Main
;
292 readonly_warning
= 1;
294 PINERC_S
*prc
= NULL
;
299 rflags
|= PAT_USE_MAIN
;
303 rflags
|= PAT_USE_POST
;
309 readonly_warning
= prc
? prc
->readonly
: 1;
310 if(prc
&& prc
->quit_to_edit
){
311 quit_to_edit_msg(prc
);
316 if(!any_patterns(rflags
, &pstate
))
319 if(rflags
& ROLE_DO_ROLES
)
320 v
= &ps_global
->vars
[V_PAT_ROLES
];
321 else if(rflags
& ROLE_DO_INCOLS
)
322 v
= &ps_global
->vars
[V_PAT_INCOLS
];
323 else if(rflags
& ROLE_DO_OTHER
)
324 v
= &ps_global
->vars
[V_PAT_OTHER
];
325 else if(rflags
& ROLE_DO_SCORES
)
326 v
= &ps_global
->vars
[V_PAT_SCORES
];
327 else if(rflags
& ROLE_DO_FILTER
)
328 v
= &ps_global
->vars
[V_PAT_FILTS
];
329 else if(rflags
& ROLE_DO_SRCH
)
330 v
= &ps_global
->vars
[V_PAT_SRCH
];
332 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
335 if((lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
336 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0){
337 role_type_print(title
, sizeof(title
), _("Warning: \"%sRules\" are overridden in your exceptions configuration"), rflags
);
338 q_status_message(SM_ORDER
, 7, 7, title
);
342 role_type_print(title
, sizeof(title
), "%sRules", rflags
);
343 if(fixed_var(v
, "change", title
))
349 snprintf(title
, sizeof(title
), "SETUP%s ", edit_exceptions
? " EXCEPTIONAL" : "");
350 title
[sizeof(title
)-1] = '\0';
351 role_type_print(title
+strlen(title
), sizeof(title
)-strlen(title
), "%sRULES", rflags
);
352 role_global_flags
= rflags
;
353 role_global_pstate
= &pstate
;
354 role_config_init_disp(ps
, &first_line
, rflags
, &pstate
);
357 role_global_flags
= 0;
358 ps
->mangled_screen
= 1;
359 q_status_message(SM_ORDER
,5,5,
360 _("Unexpected problem: config file modified externally?"));
361 q_status_message1(SM_ORDER
,5,5,
362 _("Perhaps a newer version of pine was used to set variable \"%s\"?"),
364 dprint((1, "Unexpected problem: config file modified externally?\nPerhaps by a newer pine? Variable \"%s\" has unexpected contents.\n",
365 (v
&& v
->name
) ? v
->name
: "?"));
369 memset(&screen
, 0, sizeof(screen
));
370 screen
.deferred_ro_warning
= readonly_warning
;
371 /* TRANSLATORS: Print something1 using something2.
372 "rules" is something1 */
373 switch(conf_scroll_screen(ps
, &screen
, first_line
, title
, _("rules"), 0, NULL
)){
378 /* flush changes and re-read orig */
379 close_patterns(rflags
);
383 if(write_patterns(rflags
))
387 * Flush out current_vals of anything we've possibly changed.
390 if(ps_global
->default_role
){
391 q_status_message(SM_ORDER
,0,3, "Default role is unset");
392 ps_global
->default_role
= NULL
;
395 close_patterns((rflags
& ROLE_MASK
) | PAT_USE_CURRENT
);
397 /* scores may have changed */
398 if(rflags
& ROLE_DO_SCORES
){
402 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
403 m
= ps_global
->s_pool
.streams
[i
];
405 clear_folder_scores(m
);
406 clear_index_cache(m
, 0);
410 if(mn_get_sort(sp_msgmap(ps_global
->mail_stream
)) == SortScore
)
411 refresh_sort(ps_global
->mail_stream
,
412 sp_msgmap(ps_global
->mail_stream
), SRT_VRB
);
415 /* recalculate need for scores */
416 scores_are_used(SCOREUSE_INVALID
);
418 /* we may want to fetch more or fewer headers each fetch */
421 (void) mail_parameters(NULL
, SET_IMAPEXTRAHEADERS
,
422 (void *) get_extra_hdrs());
424 if(rflags
& ROLE_DO_INCOLS
&& pico_usingcolor())
425 clear_index_cache(ps_global
->mail_stream
, 0);
427 if(rflags
& ROLE_DO_FILTER
)
428 role_process_filters();
431 * ROLE_DO_OTHER is made up of a bunch of different variables
432 * that may have changed. Assume they all changed and fix them.
434 if(rflags
& ROLE_DO_OTHER
){
435 reset_index_format();
436 clear_index_cache(ps_global
->mail_stream
, 0);
437 if(!mn_get_mansort(ps_global
->msgmap
))
438 reset_sort_order(SRT_VRB
);
444 q_status_message(SM_ORDER
,7,10, "conf_scroll_screen unexpected ret");
448 role_global_flags
= 0;
449 ps
->mangled_screen
= 1;
454 * This is called from process_cmd to add a new pattern to the end of the
455 * list of patterns. The pattern is seeded with values from the current
459 role_take(struct pine
*ps
, MSGNO_S
*msgmap
, int rtype
)
461 PAT_S
*defpat
, *newpat
= NULL
;
462 PAT_LINE_S
*new_patline
, *patline
;
463 ENVELOPE
*env
= NULL
;
465 char *s
, title
[100], specific_fldr
[MAXPATH
+1];
469 dprint((4, "role_take()\n"));
471 if(mn_get_cur(msgmap
) > 0){
472 env
= pine_mail_fetchstructure(ps
->mail_stream
,
473 mn_m2raw(msgmap
, mn_get_cur(msgmap
)),
477 q_status_message(SM_ORDER
, 3, 7,
478 _("problem getting addresses from message"));
485 rflags
= ROLE_DO_ROLES
;
486 ew
= ps_global
->ew_for_role_take
;
489 rflags
= ROLE_DO_SCORES
;
490 ew
= ps_global
->ew_for_score_take
;
493 rflags
= ROLE_DO_INCOLS
;
494 ew
= ps_global
->ew_for_incol_take
;
497 rflags
= ROLE_DO_FILTER
;
498 ew
= ps_global
->ew_for_filter_take
;
501 rflags
= ROLE_DO_OTHER
;
502 ew
= ps_global
->ew_for_other_take
;
505 rflags
= ROLE_DO_SRCH
;
506 ew
= ps_global
->ew_for_srch_take
;
516 rflags
|= PAT_USE_MAIN
;
519 rflags
|= PAT_USE_POST
;
525 if(!any_patterns(rflags
, &pstate
)){
526 q_status_message(SM_ORDER
, 3, 7, _("problem accessing rules"));
530 /* set this so that even if we don't edit at all, we'll be asked */
531 rflags
|= ROLE_CHANGES
;
534 * Make a pattern out of the information in the envelope and
535 * use that as the default pattern we give to the role editor.
536 * It will have a pattern but no actions set.
538 defpat
= (PAT_S
*)fs_get(sizeof(*defpat
));
539 memset((void *)defpat
, 0, sizeof(*defpat
));
541 defpat
->patgrp
= (PATGRP_S
*)fs_get(sizeof(*defpat
->patgrp
));
542 memset((void *)defpat
->patgrp
, 0, sizeof(*defpat
->patgrp
));
546 defpat
->patgrp
->to
= addrlst_to_pattern(env
->to
);
549 defpat
->patgrp
->from
= addrlst_to_pattern(env
->from
);
552 defpat
->patgrp
->cc
= addrlst_to_pattern(env
->cc
);
555 (!env
->from
|| !address_is_same(env
->sender
, env
->from
)))
556 defpat
->patgrp
->sender
= addrlst_to_pattern(env
->sender
);
559 * Env->newsgroups is already comma-separated and there shouldn't be
560 * any commas or backslashes in newsgroup names, so we don't add the
564 defpat
->patgrp
->news
= string_to_pattern(env
->newsgroups
);
567 * Subject may have commas or backslashes, so we add escapes.
573 * Mail_strip_subject not only strips the Re's and Fwd's but
574 * it also canonicalizes to UTF-8.
576 mail_strip_subject(env
->subject
, &q
);
578 t
= add_roletake_escapes(q
);
579 fs_give((void **)&q
);
583 defpat
->patgrp
->subj
= string_to_pattern(t
);
584 fs_give((void **)&t
);
589 if(IS_NEWS(ps
->mail_stream
))
590 defpat
->patgrp
->fldr_type
= FLDR_NEWS
;
592 defpat
->patgrp
->fldr_type
= FLDR_EMAIL
;
594 specific_fldr
[0] = specific_fldr
[sizeof(specific_fldr
)-1] = '\0';
595 if(sp_flagged(ps
->mail_stream
, SP_INBOX
))
596 strncpy(specific_fldr
, ps_global
->inbox_name
, sizeof(specific_fldr
)-1);
597 else if(ps
->context_current
598 && ps
->context_current
->use
& CNTXT_INCMNG
&&
599 folder_is_nick(ps
->cur_folder
, FOLDERS(ps
->context_current
), 0))
600 strncpy(specific_fldr
, ps
->cur_folder
, sizeof(specific_fldr
)-1);
602 context_apply(specific_fldr
, ps
->context_current
, ps
->cur_folder
,
603 sizeof(specific_fldr
));
605 if(specific_fldr
[0]){
606 s
= add_comma_escapes(specific_fldr
);
609 defpat
->patgrp
->fldr_type
= FLDR_SPECIFIC
;
611 defpat
->patgrp
->folder
= string_to_pattern(s
);
612 fs_give((void **)&s
);
616 role_type_print(title
, sizeof(title
), "ADD NEW %sRULE", rflags
);
619 * Role_config_edit_screen is sometimes called as a tool or a sub
620 * routine called from a tool within conf_scroll_screen, but here it
621 * is going to be at the top-level (we're not inside conf_scroll_screen
622 * right now). It uses opt_screen to set the ro_warning bit. We need
623 * to let it know that we're at the top, which we do by setting
624 * opt_screen to NULL. Otherwise, the thing that opt_screen is pointing
625 * to is just random stack stuff from some previous conf_scroll_screen
626 * call which has already exited.
630 if(role_config_edit_screen(ps
, defpat
, title
, rflags
,
631 &newpat
) == 1 && newpat
){
633 if(ps
->never_allow_changing_from
&& newpat
->action
&&
634 newpat
->action
->from
)
635 q_status_message(SM_ORDER
|SM_DING
, 3, 7,
636 _("Site policy doesn't allow changing From address so From is ignored"));
638 if(rflags
& ROLE_DO_ROLES
&& newpat
->patgrp
&& newpat
->patgrp
->nick
){
641 for(pat
= first_pattern(&pstate
);
643 pat
= next_pattern(&pstate
)){
644 if(pat
->patgrp
&& pat
->patgrp
->nick
&&
645 !strucmp(pat
->patgrp
->nick
, newpat
->patgrp
->nick
)){
646 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of the new role is already in use."));
653 set_pathandle(rflags
);
655 /* need a new patline */
656 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
657 memset((void *)new_patline
, 0, sizeof(*new_patline
));
658 new_patline
->type
= Literal
;
659 (*cur_pat_h
)->dirtypinerc
= 1;
661 /* tie together with new pattern */
662 new_patline
->first
= new_patline
->last
= newpat
;
663 newpat
->patline
= new_patline
;
665 /* find last current patline */
666 for(patline
= (*cur_pat_h
)->patlinehead
;
667 patline
&& patline
->next
;
668 patline
= patline
->next
)
671 /* add new patline to end of list */
673 patline
->next
= new_patline
;
674 new_patline
->prev
= patline
;
677 (*cur_pat_h
)->patlinehead
= new_patline
;
679 if(write_patterns(rflags
) == 0){
683 * Flush out current_vals of anything we've possibly changed.
686 if(rflags
& ROLE_DO_ROLES
&& ps_global
->default_role
){
687 q_status_message(SM_ORDER
,0,3, "Default role is unset");
688 ps_global
->default_role
= NULL
;
691 close_patterns(rflags
| PAT_USE_CURRENT
);
693 role_type_print(msg
, sizeof(msg
), "New %srule saved", rflags
);
694 q_status_message(SM_ORDER
, 0, 3, msg
);
696 /* scores may have changed */
697 if(rflags
& ROLE_DO_SCORES
){
701 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
702 m
= ps_global
->s_pool
.streams
[i
];
704 clear_folder_scores(m
);
705 clear_index_cache(m
, 0);
709 /* We've already bound msgmap to global mail_stream
710 * at the start of this function, but if we wanted to
711 * we could clean this up.
713 if(mn_get_sort(msgmap
) == SortScore
)
714 refresh_sort(ps_global
->mail_stream
, msgmap
, SRT_VRB
);
717 if(rflags
& ROLE_DO_FILTER
)
718 role_process_filters();
720 /* recalculate need for scores */
721 scores_are_used(SCOREUSE_INVALID
);
723 /* we may want to fetch more or fewer headers each fetch */
726 (void) mail_parameters(NULL
, SET_IMAPEXTRAHEADERS
,
727 (void *) get_extra_hdrs());
729 if(rflags
& ROLE_DO_INCOLS
&& pico_usingcolor())
730 clear_index_cache(ps_global
->mail_stream
, 0);
733 * ROLE_DO_OTHER is made up of a bunch of different variables
734 * that may have changed. Assume they all changed and fix them.
736 if(rflags
& ROLE_DO_OTHER
){
737 reset_index_format();
738 clear_index_cache(ps_global
->mail_stream
, 0);
739 if(!mn_get_mansort(msgmap
))
740 reset_sort_order(SRT_VRB
);
748 ps
->mangled_screen
= 1;
753 addrlst_to_pattern(struct mail_address
*addr
)
761 t
= s
= (char *) fs_get((l
+1) * sizeof(char));
764 u
= simple_addr_string(addr
, tmp_20k_buf
, SIZEOF_20KBUF
);
765 v
= add_roletake_escapes(u
);
768 sstrncpy(&t
, ",", l
-(t
-s
));
770 sstrncpy(&t
, v
, l
-(t
-s
));
771 fs_give((void **)&v
);
780 p
= string_to_pattern(s
);
782 fs_give((void **) &s
);
790 role_config_init_disp(struct pine
*ps
, CONF_S
**first_line
, long int rflags
, PAT_STATE
*pstate
)
794 int inherit
= 0, added_fake
= 0;
800 * Set cur_pat_h and manipulate directly.
802 set_pathandle(rflags
);
803 patline
= *cur_pat_h
? (*cur_pat_h
)->patlinehead
: NULL
;
804 if(patline
&& patline
->type
== Inherit
){
805 add_patline_to_display(ps
, &ctmp
, 0, first_line
, NULL
, patline
, rflags
);
806 patline
= patline
->next
;
810 add_fake_first_role(&ctmp
, 0, rflags
);
812 if(first_line
&& !*first_line
)
813 (*first_line
) = ctmp
;
816 for(; patline
; patline
= patline
->next
)
817 add_patline_to_display(ps
, &ctmp
, 0, first_line
, NULL
, patline
, rflags
);
820 * If there are no actual patterns so far, we need to have an Add line
821 * for the cursor to be on. This would happen if all of the patlines
822 * were File includes and none of the files contained patterns.
824 if(!first_pattern(role_global_pstate
) ||
825 ((inherit
=first_pattern(role_global_pstate
)->inherit
) &&
826 !next_pattern(role_global_pstate
))){
829 * Find the start and prepend the fake first role.
831 while(ctmp
&& ctmp
->prev
)
835 add_fake_first_role(&ctmp
, inherit
? 0 : 1, rflags
);
836 if(first_line
&& !*first_line
)
837 (*first_line
) = ctmp
;
844 add_patline_to_display(struct pine
*ps
, CONF_S
**ctmp
, int before
, CONF_S
**first_line
, CONF_S
**top_line
, PAT_LINE_S
*patline
, long int rflags
)
847 int len
, firstitem
, wid
;
849 char buf
[6*MAX_SCREEN_COLS
+1];
851 /* put dashed line around file contents */
852 if(patline
->type
== File
){
857 * New_confline appends ctmp after old current instead of inserting
858 * it, so we have to adjust. We have
859 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
862 CONF_S
*a
, *b
, *c
, *p
;
867 a
= b
? b
->prev
: NULL
;
883 if(top_line
&& *top_line
== NULL
)
886 len
= strlen(patline
->filename
) + 100;
888 q
= (char *) fs_get((len
+ 1) * sizeof(char));
889 snprintf(q
, len
+1, "From file %s%s", patline
->filename
,
890 patline
->readonly
? " (ReadOnly)" : "");
893 if((wid
=utf8_width(q
)) > ps
->ttyo
->screen_cols
-2)
894 utf8_snprintf(buf
, sizeof(buf
), "--%.*w", ps
->ttyo
->screen_cols
-2, q
);
896 snprintf(buf
, sizeof(buf
), "--%s%s", q
, repeat_char(ps
->ttyo
->screen_cols
-2-wid
, '-'));
898 (*ctmp
)->value
= cpystr(buf
);
900 fs_give((void **)&q
);
901 (*ctmp
)->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
902 (*ctmp
)->d
.r
.patline
= patline
;
908 for(pat
= patline
->first
; pat
; pat
= pat
->next
){
910 /* Check that pattern has a role and is of right type */
913 (((rflags
& ROLE_DO_ROLES
) && pat
->action
->is_a_role
) ||
914 ((rflags
& ROLE_DO_INCOLS
) && pat
->action
->is_a_incol
) ||
915 ((rflags
& ROLE_DO_SRCH
) && pat
->action
->is_a_srch
) ||
916 ((rflags
& ROLE_DO_OTHER
) && pat
->action
->is_a_other
) ||
917 ((rflags
& ROLE_DO_SCORES
) && pat
->action
->is_a_score
) ||
918 ((rflags
& ROLE_DO_FILTER
) && pat
->action
->is_a_filter
)))){
919 add_role_to_display(ctmp
, patline
, pat
, 0,
920 (first_line
&& *first_line
== NULL
)
922 (top_line
&& *top_line
== NULL
)
926 if(top_line
&& *top_line
== NULL
&& first_line
)
927 *top_line
= *first_line
;
932 if(patline
->type
== File
){
934 len
= strlen(patline
->filename
) + 100;
936 q
= (char *) fs_get((len
+ 1) * sizeof(char));
937 snprintf(q
, len
+1, "End of Rules from %s", patline
->filename
);
940 if((wid
=utf8_width(q
)) > ps
->ttyo
->screen_cols
-2)
941 utf8_snprintf(buf
, sizeof(buf
), "--%.*w", ps
->ttyo
->screen_cols
-2, q
);
943 snprintf(buf
, sizeof(buf
), "--%s%s", q
, repeat_char(ps
->ttyo
->screen_cols
-2-wid
, '-'));
945 (*ctmp
)->value
= cpystr(buf
);
947 fs_give((void **)&q
);
948 (*ctmp
)->flags
|= CF_NOSELECT
;
949 (*ctmp
)->d
.r
.patline
= patline
;
955 add_role_to_display(CONF_S
**ctmp
, PAT_LINE_S
*patline
, PAT_S
*pat
, int before
, CONF_S
**first_line
, int firstitem
, long int rflags
)
959 if(!(pat
&& (pat
->action
|| pat
->inherit
)))
963 if(first_line
&& !pat
->inherit
)
968 * New_confline appends ctmp after old current instead of inserting
969 * it, so we have to adjust. We have
970 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
973 CONF_S
*a
, *b
, *c
, *p
;
978 a
= b
? b
->prev
: NULL
;
994 role_type_print(title
, sizeof(title
), _("HELP FOR %sRULE CONFIGURATION"), rflags
);
997 (*ctmp
)->flags
|= ((firstitem
? CF_STARTITEM
: 0) |
998 CF_NOSELECT
| CF_INHERIT
);
1001 (*ctmp
)->flags
|= (firstitem
? CF_STARTITEM
: 0);
1002 (*ctmp
)->value
= cpystr((pat
&& pat
->patgrp
&& pat
->patgrp
->nick
)
1003 ? pat
->patgrp
->nick
: "?");
1006 (*ctmp
)->d
.r
.patline
= patline
;
1007 (*ctmp
)->d
.r
.pat
= pat
;
1008 (*ctmp
)->keymenu
= &role_conf_km
;
1009 (*ctmp
)->help
= (rflags
& ROLE_DO_INCOLS
) ? h_rules_incols
:
1010 (rflags
& ROLE_DO_OTHER
) ? h_rules_other
:
1011 (rflags
& ROLE_DO_FILTER
) ? h_rules_filter
:
1012 (rflags
& ROLE_DO_SCORES
) ? h_rules_score
:
1013 (rflags
& ROLE_DO_ROLES
) ? h_rules_roles
:
1014 (rflags
& ROLE_DO_SRCH
) ? h_rules_srch
:
1016 (*ctmp
)->help_title
= title
;
1017 (*ctmp
)->tool
= role_config_tool
;
1018 (*ctmp
)->valoffset
= 4;
1023 add_fake_first_role(CONF_S
**ctmp
, int before
, long int rflags
)
1032 * New_confline appends ctmp after old current instead of inserting
1033 * it, so we have to adjust. We have
1034 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
1037 CONF_S
*a
, *b
, *c
, *p
;
1042 a
= b
? b
->prev
: NULL
;
1058 role_type_print(title
, sizeof(title
), _("HELP FOR %sRULE CONFIGURATION"), rflags
);
1059 role_type_print(add
, sizeof(add
), _("Use Add to add a %sRule"), rflags
);
1061 (*ctmp
)->value
= cpystr(add
);
1062 (*ctmp
)->keymenu
= &role_conf_km
;
1063 (*ctmp
)->help
= (rflags
& ROLE_DO_INCOLS
) ? h_rules_incols
:
1064 (rflags
& ROLE_DO_OTHER
) ? h_rules_other
:
1065 (rflags
& ROLE_DO_FILTER
) ? h_rules_filter
:
1066 (rflags
& ROLE_DO_SCORES
) ? h_rules_score
:
1067 (rflags
& ROLE_DO_ROLES
) ? h_rules_roles
:
1068 (rflags
& ROLE_DO_SRCH
) ? h_rules_srch
:
1070 (*ctmp
)->help_title
= title
;
1071 (*ctmp
)->tool
= role_config_tool
;
1072 (*ctmp
)->flags
|= CF_STARTITEM
;
1073 (*ctmp
)->valoffset
= 4;
1078 role_config_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
1080 int first_one
= 0, rv
= 0;
1084 if(!(pat
= first_pattern(role_global_pstate
)) ||
1085 (pat
->inherit
&& !next_pattern(role_global_pstate
)))
1091 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1092 _("Nothing to Delete, use Add"));
1094 rv
= role_config_del(ps
, cl
, role_global_flags
);
1099 rv
= role_config_add(ps
, cl
, role_global_flags
);
1104 rv
= role_config_add(ps
, cl
, role_global_flags
);
1106 rv
= role_config_edit(ps
, cl
, role_global_flags
);
1112 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1113 _("Nothing to Shuffle, use Add"));
1115 rv
= role_config_shuffle(ps
, cl
);
1120 role_type_print(exitpmt
, sizeof(exitpmt
), "%sRule Setup", role_global_flags
);
1121 rv
= screen_exit_cmd(flags
, exitpmt
);
1125 rv
= role_config_addfile(ps
, cl
, role_global_flags
);
1129 rv
= role_config_delfile(ps
, cl
, role_global_flags
);
1134 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1135 _("Nothing to Replicate, use Add"));
1137 rv
= role_config_replicate(ps
, cl
, role_global_flags
);
1153 * Returns 1 -- There were changes
1157 role_config_add(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1159 int rv
= 0, first_pat
= 0;
1160 PAT_S
*new_pat
= NULL
, *cur_pat
;
1161 PAT_LINE_S
*new_patline
= NULL
, *cur_patline
;
1165 if((*cl
)->d
.r
.patline
&&
1166 (*cl
)->d
.r
.patline
->readonly
1167 && (*cl
)->d
.r
.patline
->type
== File
){
1168 q_status_message(SM_ORDER
, 0, 3, _("Can't add rule to ReadOnly file"));
1172 role_type_print(title
, sizeof(title
), "ADD A %sRULE", rflags
);
1174 if(role_config_edit_screen(ps
, NULL
, title
, rflags
,
1175 &new_pat
) == 1 && new_pat
){
1176 if(ps
->never_allow_changing_from
&&
1178 new_pat
->action
->from
)
1179 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1180 _("Site policy doesn't allow changing From address so From is ignored"));
1182 if(rflags
& ROLE_DO_ROLES
&&
1184 new_pat
->patgrp
->nick
&&
1185 nonempty_patterns(ROLE_DO_ROLES
, &pstate
)){
1188 for(pat
= first_pattern(&pstate
);
1190 pat
= next_pattern(&pstate
)){
1191 if(pat
->patgrp
&& pat
->patgrp
->nick
&&
1192 !strucmp(pat
->patgrp
->nick
, new_pat
->patgrp
->nick
)){
1193 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of the new role is already in use."));
1200 cur_pat
= (*cl
)->d
.r
.pat
;
1204 set_pathandle(rflags
);
1205 cur_patline
= first_pat
? (*cur_pat_h
)->patlinehead
: cur_pat
->patline
;
1207 /* need a new pat_line */
1208 if(first_pat
|| (cur_patline
&& cur_patline
->type
== Literal
)){
1209 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
1210 memset((void *)new_patline
, 0, sizeof(*new_patline
));
1211 new_patline
->type
= Literal
;
1212 (*cur_pat_h
)->dirtypinerc
= 1;
1216 if(first_pat
|| cur_patline
->type
== Literal
){
1217 new_patline
->prev
= cur_patline
;
1218 new_patline
->next
= cur_patline
->next
;
1219 if(cur_patline
->next
)
1220 cur_patline
->next
->prev
= new_patline
;
1222 cur_patline
->next
= new_patline
;
1224 /* tie new patline and new pat together */
1225 new_pat
->patline
= new_patline
;
1226 new_patline
->first
= new_patline
->last
= new_pat
;
1228 else if(cur_patline
->type
== File
){ /* don't need a new pat_line */
1230 new_pat
->patline
= cur_patline
;
1231 cur_patline
->dirty
= 1;
1233 /* Splice new_pat after cur_pat */
1234 new_pat
->prev
= cur_pat
;
1235 new_pat
->next
= cur_pat
->next
;
1237 cur_pat
->next
->prev
= new_pat
;
1239 cur_patline
->last
= new_pat
;
1241 cur_pat
->next
= new_pat
;
1245 /* tie new first patline and pat together */
1246 new_pat
->patline
= new_patline
;
1247 new_patline
->first
= new_patline
->last
= new_pat
;
1249 /* set head of list */
1250 (*cur_pat_h
)->patlinehead
= new_patline
;
1254 * If this is the first role, we replace the "Use Add" fake role
1255 * with this real one.
1258 /* Adjust conf_scroll_screen variables */
1259 (*cl
)->d
.r
.pat
= new_pat
;
1260 (*cl
)->d
.r
.patline
= new_pat
->patline
;
1262 fs_give((void **)&(*cl
)->value
);
1264 (*cl
)->value
= cpystr((new_pat
&& new_pat
->patgrp
&&
1265 new_pat
->patgrp
->nick
)
1266 ? new_pat
->patgrp
->nick
: "?");
1268 /* Else we are inserting a new role after the cur role */
1270 add_role_to_display(cl
, new_pat
->patline
, new_pat
, 0, NULL
,
1281 * Returns 1 -- There were changes
1285 role_config_replicate(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1287 int rv
= 0, first_pat
= 0;
1288 PAT_S
*new_pat
= NULL
, *cur_pat
, *defpat
= NULL
;
1289 PAT_LINE_S
*new_patline
= NULL
, *cur_patline
;
1293 if((*cl
)->d
.r
.patline
&&
1294 (*cl
)->d
.r
.patline
->readonly
1295 && (*cl
)->d
.r
.patline
->type
== File
){
1296 q_status_message(SM_ORDER
, 0, 3, _("Can't add rule to ReadOnly file"));
1300 if((*cl
)->d
.r
.pat
&& (defpat
= copy_pat((*cl
)->d
.r
.pat
))){
1301 /* change nickname */
1302 if(defpat
->patgrp
&& defpat
->patgrp
->nick
){
1303 #define CLONEWORD " Copy"
1304 char *oldnick
= defpat
->patgrp
->nick
;
1307 len
= strlen(oldnick
)+strlen(CLONEWORD
);
1308 defpat
->patgrp
->nick
= (char *)fs_get((len
+1) * sizeof(char));
1309 strncpy(defpat
->patgrp
->nick
, oldnick
, len
);
1310 defpat
->patgrp
->nick
[len
] = '\0';
1311 strncat(defpat
->patgrp
->nick
, CLONEWORD
,
1312 len
+1-1-strlen(defpat
->patgrp
->nick
));
1313 fs_give((void **)&oldnick
);
1315 if(defpat
->action
->nick
)
1316 fs_give((void **)&defpat
->action
->nick
);
1318 defpat
->action
->nick
= cpystr(defpat
->patgrp
->nick
);
1322 /* set this so that even if we don't edit at all, we'll be asked */
1323 rflags
|= ROLE_CHANGES
;
1325 role_type_print(title
, sizeof(title
), "CHANGE THIS %sRULE", rflags
);
1327 if(role_config_edit_screen(ps
, defpat
, title
, rflags
,
1328 &new_pat
) == 1 && new_pat
){
1330 if(ps
->never_allow_changing_from
&&
1332 new_pat
->action
->from
)
1333 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1334 _("Site policy doesn't allow changing From address so From is ignored"));
1336 if(rflags
& ROLE_DO_ROLES
&&
1338 new_pat
->patgrp
->nick
&&
1339 nonempty_patterns(ROLE_DO_ROLES
, &pstate
)){
1342 for(pat
= first_pattern(&pstate
);
1344 pat
= next_pattern(&pstate
)){
1345 if(pat
->patgrp
&& pat
->patgrp
->nick
&&
1346 !strucmp(pat
->patgrp
->nick
, new_pat
->patgrp
->nick
)){
1347 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of the new role is already in use."));
1354 cur_pat
= (*cl
)->d
.r
.pat
;
1358 set_pathandle(rflags
);
1359 cur_patline
= first_pat
? (*cur_pat_h
)->patlinehead
: cur_pat
->patline
;
1361 /* need a new pat_line */
1362 if(first_pat
|| (cur_patline
&& cur_patline
->type
== Literal
)){
1363 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
1364 memset((void *)new_patline
, 0, sizeof(*new_patline
));
1365 new_patline
->type
= Literal
;
1366 (*cur_pat_h
)->dirtypinerc
= 1;
1370 if(first_pat
|| cur_patline
->type
== Literal
){
1371 new_patline
->prev
= cur_patline
;
1372 new_patline
->next
= cur_patline
->next
;
1373 if(cur_patline
->next
)
1374 cur_patline
->next
->prev
= new_patline
;
1376 cur_patline
->next
= new_patline
;
1378 /* tie new patline and new pat together */
1379 new_pat
->patline
= new_patline
;
1380 new_patline
->first
= new_patline
->last
= new_pat
;
1382 else if(cur_patline
->type
== File
){ /* don't need a new pat_line */
1384 new_pat
->patline
= cur_patline
;
1385 cur_patline
->dirty
= 1;
1387 /* Splice new_pat after cur_pat */
1388 new_pat
->prev
= cur_pat
;
1389 new_pat
->next
= cur_pat
->next
;
1391 cur_pat
->next
->prev
= new_pat
;
1393 cur_patline
->last
= new_pat
;
1395 cur_pat
->next
= new_pat
;
1399 /* tie new first patline and pat together */
1400 new_pat
->patline
= new_patline
;
1401 new_patline
->first
= new_patline
->last
= new_pat
;
1403 /* set head of list */
1404 (*cur_pat_h
)->patlinehead
= new_patline
;
1408 * If this is the first role, we replace the "Use Add" fake role
1409 * with this real one.
1412 /* Adjust conf_scroll_screen variables */
1413 (*cl
)->d
.r
.pat
= new_pat
;
1414 (*cl
)->d
.r
.patline
= new_pat
->patline
;
1416 fs_give((void **)&(*cl
)->value
);
1418 (*cl
)->value
= cpystr((new_pat
&& new_pat
->patgrp
&&
1419 new_pat
->patgrp
->nick
)
1420 ? new_pat
->patgrp
->nick
: "?");
1422 /* Else we are inserting a new role after the cur role */
1424 add_role_to_display(cl
, new_pat
->patline
, new_pat
, 0, NULL
,
1437 * Change the current role.
1439 * Returns 1 -- There were changes
1443 role_config_edit(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1446 PAT_S
*new_pat
= NULL
, *cur_pat
;
1449 if((*cl
)->d
.r
.patline
->readonly
){
1450 q_status_message(SM_ORDER
, 0, 3, _("Can't change ReadOnly rule"));
1454 cur_pat
= (*cl
)->d
.r
.pat
;
1456 role_type_print(title
, sizeof(title
), "CHANGE THIS %sRULE", rflags
);
1458 if(role_config_edit_screen(ps
, cur_pat
, title
,
1459 rflags
, &new_pat
) == 1 && new_pat
){
1461 if(ps
->never_allow_changing_from
&&
1463 new_pat
->action
->from
)
1464 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1465 _("Site policy doesn't allow changing From address so From is ignored"));
1467 if(rflags
& ROLE_DO_ROLES
&& new_pat
->patgrp
&& new_pat
->patgrp
->nick
){
1470 for(pat
= first_pattern(role_global_pstate
);
1472 pat
= next_pattern(role_global_pstate
)){
1473 if(pat
->patgrp
&& pat
->patgrp
->nick
&& pat
!= cur_pat
&&
1474 !strucmp(pat
->patgrp
->nick
, new_pat
->patgrp
->nick
)){
1475 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of this role is also used for another role."));
1484 * Splice in new_pat in place of cur_pat
1488 cur_pat
->prev
->next
= new_pat
;
1491 cur_pat
->next
->prev
= new_pat
;
1493 new_pat
->prev
= cur_pat
->prev
;
1494 new_pat
->next
= cur_pat
->next
;
1496 /* tie together patline and pat (new_pat gets patline in editor) */
1497 if(new_pat
->patline
->first
== cur_pat
)
1498 new_pat
->patline
->first
= new_pat
;
1500 if(new_pat
->patline
->last
== cur_pat
)
1501 new_pat
->patline
->last
= new_pat
;
1503 if(new_pat
->patline
->type
== Literal
){
1504 set_pathandle(rflags
);
1506 (*cur_pat_h
)->dirtypinerc
= 1;
1509 new_pat
->patline
->dirty
= 1;
1511 cur_pat
->next
= NULL
;
1514 /* Adjust conf_scroll_screen variables */
1515 (*cl
)->d
.r
.pat
= new_pat
;
1516 (*cl
)->d
.r
.patline
= new_pat
->patline
;
1518 fs_give((void **)&(*cl
)->value
);
1520 (*cl
)->value
= cpystr((new_pat
->patgrp
&& new_pat
->patgrp
->nick
)
1521 ? new_pat
->patgrp
->nick
: "?");
1531 * Returns 1 -- There were changes
1535 role_config_del(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1541 if((*cl
)->d
.r
.patline
->readonly
){
1542 q_status_message(SM_ORDER
, 0, 3, _("Can't delete ReadOnly rule"));
1546 role_type_print(msg
, sizeof(msg
), _("Really delete %srule"), rflags
);
1547 snprintf(prompt
, sizeof(prompt
), "%s \"%s\" ", msg
, (*cl
)->value
);
1548 prompt
[sizeof(prompt
)-1] = '\0';
1550 ps
->mangled_footer
= 1;
1551 if(want_to(prompt
,'n','n',h_config_role_del
, WT_FLUSH_IN
) == 'y'){
1552 rv
= ps
->mangled_body
= 1;
1553 delete_a_role(cl
, rflags
);
1556 q_status_message(SM_ORDER
, 0, 3, _("Rule not deleted"));
1563 delete_a_role(CONF_S
**cl
, long int rflags
)
1567 PAT_LINE_S
*cur_patline
;
1570 cur_pat
= (*cl
)->d
.r
.pat
;
1571 cur_patline
= (*cl
)->d
.r
.patline
;
1573 if(cur_patline
->type
== Literal
){ /* delete patline */
1574 set_pathandle(rflags
);
1575 if(cur_patline
->prev
)
1576 cur_patline
->prev
->next
= cur_patline
->next
;
1578 if(*cur_pat_h
) /* this has to be true */
1579 (*cur_pat_h
)->patlinehead
= cur_patline
->next
;
1582 if(cur_patline
->next
)
1583 cur_patline
->next
->prev
= cur_patline
->prev
;
1585 if(*cur_pat_h
) /* this has to be true */
1586 (*cur_pat_h
)->dirtypinerc
= 1;
1588 cur_patline
->next
= NULL
;
1589 free_patline(&cur_patline
);
1591 else if(cur_patline
->type
== File
){ /* or delete pat */
1593 cur_pat
->prev
->next
= cur_pat
->next
;
1595 cur_patline
->first
= cur_pat
->next
;
1598 cur_pat
->next
->prev
= cur_pat
->prev
;
1600 cur_patline
->last
= cur_pat
->prev
;
1602 cur_patline
->dirty
= 1;
1604 cur_pat
->next
= NULL
;
1608 /* delete the conf line */
1610 /* deleting last real rule */
1611 if(!first_pattern(role_global_pstate
) ||
1612 ((inherit
=first_pattern(role_global_pstate
)->inherit
) &&
1613 !next_pattern(role_global_pstate
))){
1618 * Find the start and prepend the fake first role.
1620 while(*cl
&& (*cl
)->prev
)
1623 add_fake_first_role(cl
, inherit
? 0 : 1, rflags
);
1625 opt_screen
->top_line
= (*cl
);
1626 opt_screen
->current
= (*cl
);
1629 /* find next selectable line */
1630 for(cp
= (*cl
)->next
;
1631 cp
&& (cp
->flags
& CF_NOSELECT
);
1635 if(!cp
){ /* no next selectable, find previous selectable */
1636 if(*cl
== opt_screen
->top_line
)
1637 opt_screen
->top_line
= (*cl
)->prev
;
1639 for(cp
= (*cl
)->prev
;
1640 cp
&& (cp
->flags
& CF_NOSELECT
);
1644 else if(*cl
== opt_screen
->top_line
)
1645 opt_screen
->top_line
= (*cl
)->next
;
1655 * Shuffle the current role up or down.
1657 * Returns 1 -- There were changes
1661 role_config_shuffle(struct pine
*ps
, CONF_S
**cl
)
1663 int rv
= 0, deefault
, i
;
1664 int readonlyabove
= 0, readonlybelow
= 0;
1669 PAT_TYPE curtype
, prevtype
, nexttype
;
1671 if(!((*cl
)->prev
|| (*cl
)->next
)){
1672 q_status_message(SM_ORDER
, 0, 3,
1673 _("Shuffle only makes sense when there is more than one rule defined"));
1677 /* Move it up or down? */
1682 opts
[i
++].label
= N_("Up");
1687 opts
[i
++].label
= N_("Down");
1692 opts
[i
++].label
= N_("Before File");
1697 opts
[i
++].label
= N_("After File");
1702 curtype
= ((*cl
)->d
.r
.patline
) ? (*cl
)->d
.r
.patline
->type
: TypeNotSet
;
1704 prevtype
= ((*cl
)->prev
&& (*cl
)->prev
->d
.r
.patline
)
1705 ? (*cl
)->prev
->d
.r
.patline
->type
: TypeNotSet
;
1706 if(curtype
== File
&& prevtype
== File
&& (*cl
)->prev
->d
.r
.pat
== NULL
)
1707 prevtype
= TypeNotSet
;
1709 nexttype
= ((*cl
)->next
&& (*cl
)->next
->d
.r
.patline
)
1710 ? (*cl
)->next
->d
.r
.patline
->type
: TypeNotSet
;
1711 if(curtype
== File
&& nexttype
== File
&& (*cl
)->next
->d
.r
.pat
== NULL
)
1712 nexttype
= TypeNotSet
;
1715 if(curtype
== Literal
){
1716 if(prevtype
== TypeNotSet
||
1717 prevtype
== Inherit
){ /* no up, at top */
1722 else if(prevtype
== Literal
){ /* regular up */
1725 else if(prevtype
== File
){ /* file above us */
1726 if((*cl
)->prev
->d
.r
.patline
->readonly
)
1730 if(nexttype
== TypeNotSet
){ /* no down, at bottom */
1734 else if(nexttype
== Literal
){ /* regular down */
1737 else if(nexttype
== File
){ /* file below us */
1738 if((*cl
)->next
->d
.r
.patline
->readonly
)
1742 else if(curtype
== File
){
1743 if((*cl
)->d
.r
.patline
&& (*cl
)->d
.r
.patline
->readonly
){
1744 q_status_message(SM_ORDER
, 0, 3, _("Can't change ReadOnly file"));
1752 q_status_message(SM_ORDER
, 0, 3,
1753 "Programming Error: unknown line type in role_shuffle");
1757 snprintf(tmp
, sizeof(tmp
), "Shuffle \"%s\" %s%s%s%s%s%s%s ? ",
1759 (opts
[0].ch
!= -2) ? N_("UP") : "",
1760 (opts
[0].ch
!= -2 && opts
[1].ch
!= -2) ? " or " : "",
1761 (opts
[1].ch
!= -2) ? N_("DOWN") : "",
1762 ((opts
[0].ch
!= -2 ||
1763 opts
[1].ch
!= -2) && opts
[2].ch
!= -2) ? " or " : "",
1764 (opts
[2].ch
!= -2) ? N_("BEFORE") : "",
1765 ((opts
[0].ch
!= -2 ||
1767 opts
[2].ch
!= -2) && opts
[3].ch
!= -2) ? " or " : "",
1768 (opts
[3].ch
!= -2) ? N_("AFTER") : "");
1769 tmp
[sizeof(tmp
)-1] = '\0';
1771 help
= (opts
[0].ch
== -2) ? h_role_shuf_down
1772 : (opts
[1].ch
== -2) ? h_role_shuf_up
1775 rv
= radio_buttons(tmp
, -FOOTER_ROWS(ps
), opts
, deefault
, 'x',
1779 cmd_cancelled("Shuffle");
1783 if((readonlyabove
&& rv
== 'u' && curtype
!= prevtype
) ||
1784 (readonlybelow
&& rv
== 'd' && curtype
!= nexttype
)){
1785 q_status_message(SM_ORDER
, 0, 3, _("Can't shuffle into ReadOnly file"));
1789 if(rv
== 'u' && curtype
== Literal
&& prevtype
== Literal
){
1793 if(a
== opt_screen
->top_line
)
1794 opt_screen
->top_line
= b
;
1796 swap_literal_roles(a
, b
);
1797 ps
->mangled_body
= 1;
1799 else if(rv
== 'd' && curtype
== Literal
&& nexttype
== Literal
){
1803 if(a
== opt_screen
->top_line
)
1804 opt_screen
->top_line
= b
;
1806 swap_literal_roles(a
, b
);
1807 ps
->mangled_body
= 1;
1809 else if(rv
== 'u' && curtype
== File
&& prevtype
== File
){
1813 if(a
== opt_screen
->top_line
)
1814 opt_screen
->top_line
= b
;
1816 swap_file_roles(a
, b
);
1817 ps
->mangled_body
= 1;
1819 else if(rv
== 'u' && curtype
== File
){
1821 move_role_outof_file(cl
, 1);
1822 ps
->mangled_body
= 1;
1824 else if(rv
== 'd' && curtype
== File
&& nexttype
== File
){
1828 if(a
== opt_screen
->top_line
)
1829 opt_screen
->top_line
= b
;
1831 swap_file_roles(a
, b
);
1832 ps
->mangled_body
= 1;
1834 else if(rv
== 'd' && curtype
== File
){
1836 if(*cl
== opt_screen
->top_line
)
1837 opt_screen
->top_line
= (*cl
)->next
;
1839 move_role_outof_file(cl
, 0);
1840 ps
->mangled_body
= 1;
1842 else if(rv
== 'u' && curtype
== Literal
&& prevtype
== File
){
1844 move_role_into_file(cl
, 1);
1845 ps
->mangled_body
= 1;
1847 else if(rv
== 'd' && curtype
== Literal
&& nexttype
== File
){
1849 if(*cl
== opt_screen
->top_line
)
1850 opt_screen
->top_line
= (*cl
)->next
;
1852 move_role_into_file(cl
, 0);
1853 ps
->mangled_body
= 1;
1857 move_role_around_file(cl
, 1);
1858 ps
->mangled_body
= 1;
1862 if(*cl
== opt_screen
->top_line
)
1863 opt_screen
->top_line
= (*cl
)->next
;
1865 move_role_around_file(cl
, 0);
1866 ps
->mangled_body
= 1;
1874 role_config_addfile(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1876 char filename
[MAXPATH
+1], full_filename
[MAXPATH
+1];
1877 char dir2
[MAXPATH
+1], pdir
[MAXPATH
+1];
1878 char *lc
, *newfile
= NULL
;
1879 PAT_LINE_S
*file_patline
;
1880 int rv
= 0, len
= 0;
1882 HelpType help
= NO_HELP
;
1884 CONF_S
*first_line
= NULL
, *add_line
, *save_current
;
1885 struct variable
*vars
= ps
->vars
;
1888 q_status_message(SM_ORDER
, 0, 3, "Alpine demo can't read files");
1892 curtype
= ((*cl
)->d
.r
.patline
&& (*cl
)->d
.r
.patline
)
1893 ? (*cl
)->d
.r
.patline
->type
: TypeNotSet
;
1895 if(curtype
== File
){
1896 q_status_message(SM_ORDER
, 0, 3, _("Current rule is already part of a file. Move outside any files first."));
1901 * Parse_pattern_file uses signature_path to figure out where to look
1902 * for the file. In signature_path we read signature files relative
1903 * to the pinerc dir, so if user selects one that is in there we'll
1904 * use relative instead of absolute, so it looks nicer.
1908 strncpy(pdir
, VAR_OPER_DIR
, sizeof(pdir
)-1);
1909 pdir
[sizeof(pdir
)-1] = '\0';
1910 len
= strlen(pdir
) + 1;
1912 else if((lc
= last_cmpnt(ps
->pinerc
)) != NULL
){
1913 strncpy(pdir
, ps
->pinerc
, MIN(sizeof(pdir
)-1,lc
-ps
->pinerc
));
1914 pdir
[MIN(sizeof(pdir
)-1, lc
-ps
->pinerc
)] = '\0';
1918 strncpy(dir2
, pdir
, sizeof(dir2
)-1);
1919 dir2
[sizeof(dir2
)-1] = '\0';
1921 full_filename
[0] = '\0';
1922 ps
->mangled_footer
= 1;
1925 flags
= OE_APPEND_CURRENT
;
1926 r
= optionally_enter(filename
, -FOOTER_ROWS(ps
), 0, sizeof(filename
),
1927 "Name of file to be added to rules: ",
1928 NULL
, help
, &flags
);
1931 help
= (help
== NO_HELP
) ? h_config_role_addfile
: NO_HELP
;
1934 else if(r
== 10 || r
== 11){ /* Browser or File Completion */
1937 else if(r
== 1 || (r
== 0 && filename
[0] == '\0')){
1938 cmd_cancelled("IncludeFile");
1949 removing_leading_and_trailing_white_space(filename
);
1950 if(is_absolute_path(filename
))
1951 newfile
= cpystr(filename
);
1953 build_path(full_filename
, dir2
, filename
, sizeof(full_filename
));
1954 removing_leading_and_trailing_white_space(full_filename
);
1955 if(!strncmp(full_filename
, pdir
, strlen(pdir
)))
1956 newfile
= cpystr(full_filename
+ len
);
1958 newfile
= cpystr(full_filename
);
1961 if(newfile
&& *newfile
)
1968 set_pathandle(rflags
);
1970 if((file_patline
= parse_pat_file(newfile
)) != NULL
){
1972 * Insert the file after the current line.
1974 PAT_LINE_S
*cur_patline
;
1977 rv
= ps
->mangled_screen
= 1;
1978 first_pat
= !(*cl
)->d
.r
.pat
;
1979 cur_patline
= (*cl
)->d
.r
.patline
? (*cl
)->d
.r
.patline
:
1980 (*cur_pat_h
) ? (*cur_pat_h
)->patlinehead
: NULL
;
1983 (*cur_pat_h
)->dirtypinerc
= 1;
1985 file_patline
->dirty
= 1;
1988 file_patline
->prev
= cur_patline
;
1989 file_patline
->next
= cur_patline
->next
;
1990 if(cur_patline
->next
)
1991 cur_patline
->next
->prev
= file_patline
;
1993 cur_patline
->next
= file_patline
;
1996 /* set head of list */
1998 (*cur_pat_h
)->patlinehead
= file_patline
;
2002 if(file_patline
->first
){
2003 /* get rid of Fake Add line */
2005 opt_screen
->top_line
= NULL
;
2006 add_patline_to_display(ps
, cl
, 0, &first_line
,
2007 &opt_screen
->top_line
, file_patline
,
2009 opt_screen
->current
= first_line
;
2010 snip_confline(&add_line
);
2013 /* we're _appending_ to the Fake Add line */
2014 save_current
= opt_screen
->current
;
2015 add_patline_to_display(ps
, cl
, 0, NULL
, NULL
, file_patline
,
2017 opt_screen
->current
= save_current
;
2021 opt_screen
->top_line
= NULL
;
2022 save_current
= opt_screen
->current
;
2023 add_patline_to_display(ps
, cl
, 0, &first_line
,
2024 &opt_screen
->top_line
, file_patline
,
2027 opt_screen
->current
= first_line
;
2029 opt_screen
->current
= save_current
;
2034 fs_give((void **)&newfile
);
2041 role_config_delfile(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
2044 PAT_LINE_S
*cur_patline
;
2047 if(!(cur_patline
= (*cl
)->d
.r
.patline
)){
2048 q_status_message(SM_ORDER
, 0, 3,
2049 "Unknown problem in role_config_delfile");
2053 if(cur_patline
->type
!= File
){
2054 q_status_message(SM_ORDER
, 0, 3, _("Current rule is not part of a file. Use Delete to remove current rule"));
2058 snprintf(prompt
, sizeof(prompt
), _("Really remove rule file \"%s\" from rules config "),
2059 cur_patline
->filename
);
2060 prompt
[sizeof(prompt
)-1] = '\0';
2062 ps
->mangled_footer
= 1;
2063 if(want_to(prompt
,'n','n',h_config_role_delfile
, WT_FLUSH_IN
) == 'y'){
2066 set_pathandle(rflags
);
2067 rv
= ps
->mangled_screen
= 1;
2069 (*cur_pat_h
)->dirtypinerc
= 1;
2071 if(cur_patline
->prev
)
2072 cur_patline
->prev
->next
= cur_patline
->next
;
2075 (*cur_pat_h
)->patlinehead
= cur_patline
->next
;
2078 if(cur_patline
->next
)
2079 cur_patline
->next
->prev
= cur_patline
->prev
;
2081 /* delete the conf lines */
2083 /* find the first one associated with this file */
2085 ctmp
&& ctmp
->prev
&& ctmp
->prev
->d
.r
.patline
== cur_patline
;
2089 if(ctmp
->prev
) /* this file wasn't the first thing in config */
2091 else{ /* this file was first in config */
2092 for(cp
= ctmp
; cp
&& cp
->next
; cp
= cp
->next
)
2095 if(cp
->d
.r
.patline
== cur_patline
)
2101 /* delete lines from the file */
2102 while(ctmp
&& ctmp
->d
.r
.patline
== cur_patline
){
2108 /* deleting last real rule */
2109 if(!first_pattern(role_global_pstate
)){
2111 * Find the start and prepend the fake first role
2114 while(*cl
&& (*cl
)->prev
)
2117 add_fake_first_role(cl
, 1, rflags
);
2119 else if(first_pattern(role_global_pstate
)->inherit
&&
2120 !next_pattern(role_global_pstate
)){
2121 while(*cl
&& (*cl
)->prev
)
2124 /* append fake first after inherit */
2125 add_fake_first_role(cl
, 0, rflags
);
2128 opt_screen
->top_line
= first_confline(*cl
);
2129 opt_screen
->current
= first_sel_confline(opt_screen
->top_line
);
2131 cur_patline
->next
= NULL
;
2132 free_patline(&cur_patline
);
2135 q_status_message(SM_ORDER
, 0, 3, _("Rule file not removed"));
2142 * Swap from a, b to b, a.
2145 swap_literal_roles(CONF_S
*a
, CONF_S
*b
)
2147 PAT_LINE_S
*patline_a
, *patline_b
;
2149 patline_a
= a
->d
.r
.patline
;
2150 patline_b
= b
->d
.r
.patline
;
2152 set_pathandle(role_global_flags
);
2154 (*cur_pat_h
)->dirtypinerc
= 1;
2156 /* first swap the patlines */
2157 if(patline_a
->next
== patline_b
){
2158 patline_b
->prev
= patline_a
->prev
;
2160 patline_a
->prev
->next
= patline_b
;
2162 patline_a
->next
= patline_b
->next
;
2164 patline_b
->next
->prev
= patline_a
;
2166 patline_b
->next
= patline_a
;
2167 patline_a
->prev
= patline_b
;
2170 PAT_LINE_S
*new_a_prev
, *new_a_next
;
2172 new_a_prev
= patline_b
->prev
;
2173 new_a_next
= patline_b
->next
;
2175 patline_b
->prev
= patline_a
->prev
;
2176 patline_b
->next
= patline_a
->next
;
2178 patline_b
->prev
->next
= patline_b
;
2180 patline_b
->next
->prev
= patline_b
;
2182 patline_a
->prev
= new_a_prev
;
2183 patline_a
->next
= new_a_next
;
2185 patline_a
->prev
->next
= patline_a
;
2187 patline_a
->next
->prev
= patline_a
;
2191 * If patline_b is now the first one in the list, we need to fix the
2192 * head of the list to point to this new role.
2194 if(patline_b
->prev
== NULL
&& *cur_pat_h
)
2195 (*cur_pat_h
)->patlinehead
= patline_b
;
2198 /* and then swap the conf lines */
2214 * Swap from a, b to b, a.
2217 swap_file_roles(CONF_S
*a
, CONF_S
*b
)
2219 PAT_S
*pat_a
, *pat_b
;
2220 PAT_LINE_S
*patline
;
2224 patline
= pat_a
->patline
;
2228 /* first swap the pats */
2229 if(pat_a
->next
== pat_b
){
2230 pat_b
->prev
= pat_a
->prev
;
2232 pat_a
->prev
->next
= pat_b
;
2234 pat_a
->next
= pat_b
->next
;
2236 pat_b
->next
->prev
= pat_a
;
2238 pat_b
->next
= pat_a
;
2239 pat_a
->prev
= pat_b
;
2242 PAT_S
*new_a_prev
, *new_a_next
;
2244 new_a_prev
= pat_b
->prev
;
2245 new_a_next
= pat_b
->next
;
2247 pat_b
->prev
= pat_a
->prev
;
2248 pat_b
->next
= pat_a
->next
;
2250 pat_b
->prev
->next
= pat_b
;
2252 pat_b
->next
->prev
= pat_b
;
2254 pat_a
->prev
= new_a_prev
;
2255 pat_a
->next
= new_a_next
;
2257 pat_a
->prev
->next
= pat_a
;
2259 pat_a
->next
->prev
= pat_a
;
2263 * Fix the first and last pointers.
2265 if(patline
->first
== pat_a
)
2266 patline
->first
= pat_b
;
2267 if(patline
->last
== pat_b
)
2268 patline
->last
= pat_a
;
2270 /* and then swap the conf lines */
2288 move_role_into_file(CONF_S
**cl
, int up
)
2290 PAT_LINE_S
*cur_patline
, *file_patline
;
2294 cur_patline
= (*cl
)->d
.r
.patline
;
2297 file_patline
= (*cl
)->prev
->d
.r
.patline
;
2300 b
->d
.r
.patline
= file_patline
;
2303 file_patline
= (*cl
)->next
->d
.r
.patline
;
2306 a
->d
.r
.patline
= file_patline
;
2309 set_pathandle(role_global_flags
);
2311 (*cur_pat_h
)->dirtypinerc
= 1;
2313 file_patline
->dirty
= 1;
2315 pat
= cur_patline
->first
;
2317 if(!up
&& *cur_pat_h
&& cur_patline
== (*cur_pat_h
)->patlinehead
)
2318 (*cur_pat_h
)->patlinehead
= (*cur_pat_h
)->patlinehead
->next
;
2320 if(file_patline
->first
){
2322 file_patline
->last
->next
= pat
;
2323 pat
->prev
= file_patline
->last
;
2324 file_patline
->last
= pat
;
2327 file_patline
->first
->prev
= pat
;
2328 pat
->next
= file_patline
->first
;
2329 file_patline
->first
= pat
;
2332 else /* will be only role in file */
2333 file_patline
->first
= file_patline
->last
= pat
;
2335 pat
->patline
= file_patline
;
2337 /* delete the now unused cur_patline */
2338 cur_patline
->first
= cur_patline
->last
= NULL
;
2339 if(cur_patline
->prev
)
2340 cur_patline
->prev
->next
= cur_patline
->next
;
2341 if(cur_patline
->next
)
2342 cur_patline
->next
->prev
= cur_patline
->prev
;
2344 cur_patline
->next
= NULL
;
2345 free_patline(&cur_patline
);
2347 /* and then swap the conf lines */
2365 move_role_outof_file(CONF_S
**cl
, int up
)
2367 PAT_LINE_S
*file_patline
, *new_patline
;
2371 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
2372 memset((void *)new_patline
, 0, sizeof(*new_patline
));
2373 new_patline
->type
= Literal
;
2375 file_patline
= (*cl
)->d
.r
.patline
;
2376 pat
= (*cl
)->d
.r
.pat
;
2383 pat
->prev
->next
= pat
->next
;
2385 file_patline
->first
= pat
->next
;
2388 pat
->next
->prev
= pat
->prev
;
2390 file_patline
->last
= pat
->prev
;
2392 if(file_patline
->first
)
2393 file_patline
->first
->prev
= NULL
;
2395 if(file_patline
->last
)
2396 file_patline
->last
->next
= NULL
;
2398 if(file_patline
->prev
)
2399 file_patline
->prev
->next
= new_patline
;
2401 new_patline
->prev
= file_patline
->prev
;
2402 new_patline
->next
= file_patline
;
2403 file_patline
->prev
= new_patline
;
2404 b
->d
.r
.patline
= new_patline
;
2411 pat
->prev
->next
= pat
->next
;
2413 file_patline
->first
= pat
->next
;
2416 pat
->next
->prev
= pat
->prev
;
2418 file_patline
->last
= pat
->prev
;
2420 if(file_patline
->first
)
2421 file_patline
->first
->prev
= NULL
;
2423 if(file_patline
->last
)
2424 file_patline
->last
->next
= NULL
;
2426 if(file_patline
->next
)
2427 file_patline
->next
->prev
= new_patline
;
2429 new_patline
->next
= file_patline
->next
;
2430 new_patline
->prev
= file_patline
;
2431 file_patline
->next
= new_patline
;
2432 a
->d
.r
.patline
= new_patline
;
2435 set_pathandle(role_global_flags
);
2437 (*cur_pat_h
)->dirtypinerc
= 1;
2439 file_patline
->dirty
= 1;
2441 new_patline
->first
= new_patline
->last
= pat
;
2442 pat
->patline
= new_patline
;
2443 pat
->prev
= pat
->next
= NULL
;
2445 if(up
&& *cur_pat_h
&& file_patline
== (*cur_pat_h
)->patlinehead
)
2446 (*cur_pat_h
)->patlinehead
= new_patline
;
2448 /* and then swap the conf lines */
2464 * This is a move of a literal role from before a file to after a file,
2468 move_role_around_file(CONF_S
**cl
, int up
)
2470 PAT_LINE_S
*file_patline
, *lit_patline
;
2473 set_pathandle(role_global_flags
);
2474 lit_patline
= (*cl
)->d
.r
.patline
;
2476 file_patline
= (*cl
)->prev
->d
.r
.patline
;
2478 if(*cur_pat_h
&& lit_patline
== (*cur_pat_h
)->patlinehead
)
2479 (*cur_pat_h
)->patlinehead
= (*cur_pat_h
)->patlinehead
->next
;
2481 file_patline
= (*cl
)->next
->d
.r
.patline
;
2485 (*cur_pat_h
)->dirtypinerc
= 1;
2487 /* remove the lit_patline from the list */
2488 if(lit_patline
->prev
)
2489 lit_patline
->prev
->next
= lit_patline
->next
;
2490 if(lit_patline
->next
)
2491 lit_patline
->next
->prev
= lit_patline
->prev
;
2493 /* and reinsert it on the other side of the file */
2495 if(*cur_pat_h
&& file_patline
== (*cur_pat_h
)->patlinehead
)
2496 (*cur_pat_h
)->patlinehead
= lit_patline
;
2498 lit_patline
->prev
= file_patline
->prev
;
2499 lit_patline
->next
= file_patline
;
2501 if(file_patline
->prev
)
2502 file_patline
->prev
->next
= lit_patline
;
2504 file_patline
->prev
= lit_patline
;
2507 lit_patline
->next
= file_patline
->next
;
2508 lit_patline
->prev
= file_patline
;
2510 if(file_patline
->next
)
2511 file_patline
->next
->prev
= lit_patline
;
2513 file_patline
->next
= lit_patline
;
2517 * And then move the conf line around the file conf lines.
2520 /* find it's new home */
2523 cp
&& cp
->prev
&& cp
->prev
->d
.r
.patline
== file_patline
;
2524 cp
= prev_confline(cp
))
2528 cp
&& cp
->next
&& cp
->next
->d
.r
.patline
== file_patline
;
2529 cp
= next_confline(cp
))
2532 /* remove it from where it is */
2534 (*cl
)->prev
->next
= (*cl
)->next
;
2536 (*cl
)->next
->prev
= (*cl
)->prev
;
2538 /* cp points to top or bottom of the file lines */
2540 (*cl
)->prev
= cp
->prev
;
2542 cp
->prev
->next
= (*cl
);
2548 (*cl
)->next
= cp
->next
;
2550 cp
->next
->prev
= (*cl
);
2558 #define SETUP_PAT_STATUS(ctmp,svar,val,htitle,hval) \
2559 {char tmp[MAXPATH+1]; \
2564 new_confline(&ctmp); \
2565 ctmp->flags |= CF_NOSELECT | CF_B_LINE; \
2567 new_confline(&ctmp); \
2568 ctmp->var = &svar; \
2569 ctmp->keymenu = &config_radiobutton_keymenu; \
2570 ctmp->help = NO_HELP; \
2571 ctmp->tool = NULL; \
2572 snprintf(tmp, sizeof(tmp), "%-s =", svar.name); \
2573 tmp[sizeof(tmp)-1] = '\0'; \
2574 ctmp->varname = cpystr(tmp); \
2575 ctmp->varnamep = ctmpb = ctmp; \
2576 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); \
2578 new_confline(&ctmp); \
2580 ctmp->valoffset = rindent; \
2581 ctmp->keymenu = &config_radiobutton_keymenu; \
2582 ctmp->help = NO_HELP; \
2583 ctmp->tool = NULL; \
2584 ctmp->varnamep = ctmpb; \
2585 ctmp->flags |= CF_NOSELECT; \
2586 ctmp->value = cpystr("Set Choose One"); \
2588 new_confline(&ctmp); \
2590 ctmp->valoffset = rindent; \
2591 ctmp->keymenu = &config_radiobutton_keymenu; \
2592 ctmp->help = NO_HELP; \
2593 ctmp->tool = radio_tool; \
2594 ctmp->varnamep = ctmpb; \
2595 ctmp->flags |= CF_NOSELECT; \
2596 ctmp->value = cpystr(set_choose); \
2598 /* find longest value's name */ \
2599 for(lv = 0, i = 0; (f = role_status_types(i)); i++) \
2600 if(lv < (j = utf8_width(f->name))) \
2603 lv = MIN(lv, 100); \
2605 for(i = 0; (f = role_status_types(i)); i++){ \
2606 new_confline(&ctmp); \
2607 ctmp->help_title= htitle; \
2608 ctmp->var = &svar; \
2609 ctmp->valoffset = rindent; \
2610 ctmp->keymenu = &config_radiobutton_keymenu; \
2611 ctmp->help = hval; \
2613 ctmp->tool = radio_tool; \
2614 ctmp->varnamep = ctmpb; \
2615 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!(def && def->patgrp) || \
2617 f->value == PAT_STAT_EITHER) || \
2618 (def && def->patgrp && \
2622 tmp[sizeof(tmp)-1] = '\0'; \
2623 ctmp->value = cpystr(tmp); \
2627 #define SETUP_MSG_STATE(ctmp,svar,val,htitle,hval) \
2628 {char tmp[MAXPATH+1]; \
2633 new_confline(&ctmp); \
2634 ctmp->flags |= CF_NOSELECT | CF_B_LINE; \
2636 new_confline(&ctmp); \
2637 ctmp->var = &svar; \
2638 ctmp->keymenu = &config_radiobutton_keymenu; \
2639 ctmp->help = NO_HELP; \
2640 ctmp->tool = NULL; \
2641 snprintf(tmp, sizeof(tmp), "%-s =", svar.name); \
2642 tmp[sizeof(tmp)-1] = '\0'; \
2643 ctmp->varname = cpystr(tmp); \
2644 ctmp->varnamep = ctmpb = ctmp; \
2645 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); \
2647 new_confline(&ctmp); \
2649 ctmp->valoffset = rindent; \
2650 ctmp->keymenu = &config_radiobutton_keymenu; \
2651 ctmp->help = NO_HELP; \
2652 ctmp->tool = NULL; \
2653 ctmp->varnamep = ctmpb; \
2654 ctmp->flags |= CF_NOSELECT; \
2655 ctmp->value = cpystr("Set Choose One"); \
2657 new_confline(&ctmp); \
2659 ctmp->valoffset = rindent; \
2660 ctmp->keymenu = &config_radiobutton_keymenu; \
2661 ctmp->help = NO_HELP; \
2662 ctmp->tool = radio_tool; \
2663 ctmp->varnamep = ctmpb; \
2664 ctmp->flags |= CF_NOSELECT; \
2665 ctmp->value = cpystr(set_choose); \
2667 /* find longest value's name */ \
2668 for(lv = 0, i = 0; (f = msg_state_types(i)); i++) \
2669 if(lv < (j = utf8_width(f->name))) \
2672 lv = MIN(lv, 100); \
2674 for(i = 0; (f = msg_state_types(i)); i++){ \
2675 new_confline(&ctmp); \
2676 ctmp->help_title= htitle; \
2677 ctmp->var = &svar; \
2678 ctmp->valoffset = rindent; \
2679 ctmp->keymenu = &config_radiobutton_keymenu; \
2680 ctmp->help = hval; \
2682 ctmp->tool = radio_tool; \
2683 ctmp->varnamep = ctmpb; \
2684 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (f->value == val) \
2687 tmp[sizeof(tmp)-1] = '\0'; \
2688 ctmp->value = cpystr(tmp); \
2693 #define FEAT_SENTDATE 0
2694 #define FEAT_IFNOTDEL 1
2695 #define FEAT_NONTERM 2
2696 bitmap_t feat_option_list
;
2698 #define INABOOK_FROM 0
2699 #define INABOOK_REPLYTO 1
2700 #define INABOOK_SENDER 2
2701 #define INABOOK_TO 3
2702 #define INABOOK_CC 4
2703 bitmap_t inabook_type_list
;
2706 #define INICK_INICK_CONF 0
2707 #define INICK_FROM_CONF 1
2708 #define INICK_REPLYTO_CONF 2
2709 #define INICK_FCC_CONF 3
2710 #define INICK_LITSIG_CONF 4 /* this needs to come before SIG_CONF */
2711 #define INICK_SIG_CONF 5
2712 #define INICK_TEMPL_CONF 6
2713 #define INICK_CSTM_CONF 7
2714 #define INICK_SMTP_CONF 8
2715 #define INICK_NNTP_CONF 9
2716 CONF_S
*inick_confs
[INICK_NNTP_CONF
+1];
2720 * Screen for editing configuration of a role.
2722 * Args ps -- pine struct
2723 * def -- default role values to start with
2724 * title -- part of title at top of screen
2725 * rflags -- which parts of role to edit
2726 * result -- This is the returned PAT_S, freed by caller.
2728 * Returns: 0 if no change
2729 * 1 if user requested a change
2730 * (change is stored in raw_server and hasn't been acted upon yet)
2731 * 10 user says abort
2734 role_config_edit_screen(struct pine
*ps
, PAT_S
*def
, char *title
, long int rflags
, PAT_S
**result
)
2736 OPT_SCREEN_S screen
, *saved_screen
;
2737 CONF_S
*ctmp
= NULL
, *ctmpb
, *first_line
= NULL
;
2738 struct variable nick_var
, to_pat_var
, from_pat_var
,
2740 sender_pat_var
, cc_pat_var
, recip_pat_var
, news_pat_var
,
2741 subj_pat_var
, inick_var
, fldr_type_var
, folder_pat_var
,
2742 abook_type_var
, abook_pat_var
,
2743 alltext_pat_var
, scorei_pat_var
, partic_pat_var
,
2744 bodytext_pat_var
, age_pat_var
, size_pat_var
,
2745 keyword_pat_var
, charset_pat_var
,
2746 stat_new_var
, stat_del_var
, stat_imp_var
, stat_ans_var
,
2747 stat_rec_var
, stat_8bit_var
,
2748 stat_bom_var
, stat_boy_var
,
2749 cat_cmd_var
, cati_var
, cat_lim_var
,
2750 from_act_var
, replyto_act_var
, fcc_act_var
,
2751 sig_act_var
, litsig_act_var
, templ_act_var
,
2752 cstm_act_var
, smtp_act_var
, nntp_act_var
,
2753 sort_act_var
, iform_act_var
, startup_var
,
2754 repl_type_var
, forw_type_var
, comp_type_var
, score_act_var
,
2756 rolecolor_vars
[2], filter_type_var
, folder_act_var
,
2757 keyword_set_var
, keyword_clr_var
,
2758 filt_new_var
, filt_del_var
, filt_imp_var
, filt_ans_var
;
2759 struct variable
*v
, *varlist
[65], opt_var
, inabook_type_var
;
2760 char *nick
= NULL
, *inick
= NULL
, *fldr_type_pat
= NULL
,
2762 *scorei_pat
= NULL
, *age_pat
= NULL
, *size_pat
= NULL
,
2763 *abook_type_pat
= NULL
,
2764 *stat_new
= NULL
, *stat_del
= NULL
, *stat_imp
= NULL
,
2765 *stat_rec
= NULL
, *stat_ans
= NULL
, *stat_8bit
= NULL
,
2766 *stat_bom
= NULL
, *stat_boy
= NULL
,
2767 *filt_new
= NULL
, *filt_del
= NULL
, *filt_imp
= NULL
,
2768 *filt_ans
= NULL
, *cati
= NULL
, *cat_lim
= NULL
,
2769 *from_act
= NULL
, *replyto_act
= NULL
, *fcc_act
= NULL
,
2770 *sig_act
= NULL
, *litsig_act
= NULL
, *sort_act
= NULL
,
2771 *templ_act
= NULL
, *repl_type
= NULL
, *forw_type
= NULL
,
2772 *comp_type
= NULL
, *rc_fg
= NULL
, *rc_bg
= NULL
,
2773 *score_act
= NULL
, *filter_type
= NULL
,
2775 *iform_act
= NULL
, *startup_act
= NULL
,
2776 *old_fg
= NULL
, *old_bg
= NULL
;
2777 char **to_pat
= NULL
, **from_pat
= NULL
, **sender_pat
= NULL
,
2778 **cc_pat
= NULL
, **news_pat
= NULL
, **recip_pat
= NULL
,
2779 **partic_pat
= NULL
, **subj_pat
= NULL
,
2780 **alltext_pat
= NULL
, **bodytext_pat
= NULL
,
2781 **keyword_pat
= NULL
, **folder_pat
= NULL
,
2782 **charset_pat
= NULL
,
2783 **abook_pat
= NULL
, **folder_act
= NULL
,
2784 **keyword_set
= NULL
, **keyword_clr
= NULL
,
2785 **cat_cmd
= NULL
, **cstm_act
= NULL
, **smtp_act
= NULL
,
2786 **nntp_act
= NULL
, **spat
;
2787 char tmp
[MAXPATH
+1], **apval
, **lval
, ***alval
, *p
;
2788 /* TRANSLATORS: These next 4 are subheading for sections of a configuration screen. */
2789 char *fstr
= _(" CURRENT FOLDER CONDITIONS BEGIN HERE ");
2791 char *astr
= _(" ACTIONS BEGIN HERE ");
2792 char *ustr
= _(" USES BEGIN HERE ");
2793 char *ostr
= _(" OPTIONS BEGIN HERE ");
2794 char *s_p_v_n
= _("Subject pattern"); /* longest one of these */
2795 char *u_s_s
= _("Use SMTP Server"); /* ditto */
2796 char *c_v_n
= _("Exit Status Interval"); /* ditto */
2800 EARB_S
*earb
= NULL
, *ea
;
2801 int rv
, i
, j
, lv
, pindent
, maxpindent
, rindent
,
2802 scoreval
= 0, edit_role
, wid
,
2803 edit_incol
, edit_score
, edit_filter
, edit_other
, edit_srch
,
2804 dval
, ival
, nval
, aval
, fval
,
2805 per_folder_only
, need_uses
, need_options
;
2806 int (*radio_tool
)(struct pine
*, int, CONF_S
**, unsigned);
2807 int (*addhdr_tool
)(struct pine
*, int, CONF_S
**, unsigned);
2808 int (*t_tool
)(struct pine
*, int, CONF_S
**, unsigned);
2811 dprint((4, "role_config_edit_screen()\n"));
2812 edit_role
= rflags
& ROLE_DO_ROLES
;
2813 edit_incol
= rflags
& ROLE_DO_INCOLS
;
2814 edit_score
= rflags
& ROLE_DO_SCORES
;
2815 edit_filter
= rflags
& ROLE_DO_FILTER
;
2816 edit_other
= rflags
& ROLE_DO_OTHER
;
2817 edit_srch
= rflags
& ROLE_DO_SRCH
;
2819 per_folder_only
= (edit_other
&&
2820 !(edit_role
|| edit_incol
|| edit_score
|| edit_filter
|| edit_srch
));
2821 need_uses
= edit_role
;
2822 need_options
= !per_folder_only
;
2824 radio_tool
= edit_filter
? role_filt_radiobutton_tool
2825 : role_radiobutton_tool
;
2826 t_tool
= edit_filter
? role_filt_text_tool
: role_text_tool
;
2827 addhdr_tool
= edit_filter
? role_filt_addhdr_tool
: role_addhdr_tool
;
2829 rindent
= 12; /* radio indent */
2832 * We edit by making a nested call to conf_scroll_screen.
2833 * We use some fake struct variables to get back the results in, and
2834 * so we can use the existing tools from the config screen.
2836 varlist
[j
= 0] = &nick_var
;
2837 varlist
[++j
] = &comment_var
;
2838 varlist
[++j
] = &to_pat_var
;
2839 varlist
[++j
] = &from_pat_var
;
2840 varlist
[++j
] = &sender_pat_var
;
2841 varlist
[++j
] = &cc_pat_var
;
2842 varlist
[++j
] = &recip_pat_var
;
2843 varlist
[++j
] = &partic_pat_var
;
2844 varlist
[++j
] = &news_pat_var
;
2845 varlist
[++j
] = &subj_pat_var
;
2846 varlist
[++j
] = &alltext_pat_var
;
2847 varlist
[++j
] = &bodytext_pat_var
;
2848 varlist
[++j
] = &keyword_pat_var
;
2849 varlist
[++j
] = &charset_pat_var
;
2850 varlist
[++j
] = &age_pat_var
;
2851 varlist
[++j
] = &size_pat_var
;
2852 varlist
[++j
] = &scorei_pat_var
;
2853 varlist
[++j
] = &stat_new_var
;
2854 varlist
[++j
] = &stat_rec_var
;
2855 varlist
[++j
] = &stat_del_var
;
2856 varlist
[++j
] = &stat_imp_var
;
2857 varlist
[++j
] = &stat_ans_var
;
2858 varlist
[++j
] = &stat_8bit_var
;
2859 varlist
[++j
] = &stat_bom_var
;
2860 varlist
[++j
] = &stat_boy_var
;
2861 varlist
[++j
] = &cat_cmd_var
;
2862 varlist
[++j
] = &cati_var
;
2863 varlist
[++j
] = &cat_lim_var
;
2864 varlist
[++j
] = &inick_var
;
2865 varlist
[++j
] = &fldr_type_var
;
2866 varlist
[++j
] = &folder_pat_var
;
2867 varlist
[++j
] = &abook_type_var
;
2868 varlist
[++j
] = &abook_pat_var
;
2869 varlist
[++j
] = &from_act_var
;
2870 varlist
[++j
] = &replyto_act_var
;
2871 varlist
[++j
] = &fcc_act_var
;
2872 varlist
[++j
] = &sig_act_var
;
2873 varlist
[++j
] = &litsig_act_var
;
2874 varlist
[++j
] = &sort_act_var
;
2875 varlist
[++j
] = &iform_act_var
;
2876 varlist
[++j
] = &startup_var
;
2877 varlist
[++j
] = &templ_act_var
;
2878 varlist
[++j
] = &cstm_act_var
;
2879 varlist
[++j
] = &smtp_act_var
;
2880 varlist
[++j
] = &nntp_act_var
;
2881 varlist
[++j
] = &score_act_var
;
2882 varlist
[++j
] = &hdrtok_act_var
;
2883 varlist
[++j
] = &repl_type_var
;
2884 varlist
[++j
] = &forw_type_var
;
2885 varlist
[++j
] = &comp_type_var
;
2886 varlist
[++j
] = &rolecolor_vars
[0];
2887 varlist
[++j
] = &rolecolor_vars
[1];
2888 varlist
[++j
] = &filter_type_var
;
2889 varlist
[++j
] = &folder_act_var
;
2890 varlist
[++j
] = &keyword_set_var
;
2891 varlist
[++j
] = &keyword_clr_var
;
2892 varlist
[++j
] = &filt_new_var
;
2893 varlist
[++j
] = &filt_del_var
;
2894 varlist
[++j
] = &filt_imp_var
;
2895 varlist
[++j
] = &filt_ans_var
;
2896 varlist
[++j
] = &opt_var
;
2897 varlist
[++j
] = &inabook_type_var
;
2898 varlist
[++j
] = NULL
;
2899 for(j
= 0; varlist
[j
]; j
++)
2900 memset(varlist
[j
], 0, sizeof(struct variable
));
2902 if(def
&& ((def
->patgrp
&& def
->patgrp
->bogus
) || (def
->action
&& def
->action
->bogus
))){
2903 char msg
[MAX_SCREEN_COLS
+1];
2905 snprintf(msg
, sizeof(msg
),
2906 _("Rule contains unknown %s element, possibly from newer Alpine"),
2907 (def
->patgrp
&& def
->patgrp
->bogus
) ? "pattern" : "action");
2908 msg
[sizeof(msg
)-1] = '\0';
2909 q_status_message(SM_ORDER
| SM_DING
, 7, 7, msg
);
2910 q_status_message(SM_ORDER
| SM_DING
, 7, 7,
2911 _("Editing with this version of Alpine will destroy information"));
2912 flush_status_messages(0);
2915 role_forw_ptr
= role_repl_ptr
= role_fldr_ptr
= role_filt_ptr
= NULL
;
2916 role_status1_ptr
= role_status2_ptr
= role_status3_ptr
= NULL
;
2917 role_status4_ptr
= role_status5_ptr
= role_status6_ptr
= NULL
;
2918 role_status7_ptr
= NULL
; role_status8_ptr
= NULL
;
2919 msg_state1_ptr
= msg_state2_ptr
= NULL
;
2920 msg_state3_ptr
= msg_state4_ptr
= NULL
;
2921 role_afrom_ptr
= startup_ptr
= NULL
;
2922 role_comment_ptr
= NULL
;
2924 nick_var
.name
= cpystr(_("Nickname"));
2925 nick_var
.is_used
= 1;
2926 nick_var
.is_user
= 1;
2927 apval
= APVAL(&nick_var
, ew
);
2928 *apval
= (def
&& def
->patgrp
&& def
->patgrp
->nick
)
2929 ? cpystr(def
->patgrp
->nick
) : NULL
;
2931 nick_var
.global_val
.p
= cpystr(edit_role
2936 ? "Index Color Rule"
2939 : "Filter Rule"))));
2940 set_current_val(&nick_var
, FALSE
, FALSE
);
2942 role_comment_ptr
= &comment_var
; /* so radiobuttons can tell */
2943 comment_var
.name
= cpystr(_("Comment"));
2944 comment_var
.is_used
= 1;
2945 comment_var
.is_user
= 1;
2946 apval
= APVAL(&comment_var
, ew
);
2947 *apval
= (def
&& def
->patgrp
&& def
->patgrp
->comment
)
2948 ? cpystr(def
->patgrp
->comment
) : NULL
;
2949 set_current_val(&comment_var
, FALSE
, FALSE
);
2951 /* TRANSLATORS: Quite a few of the translations to follow are from the
2952 rules editing screens. These are mostly headings of individual categories
2953 of criteria which can be set in a rule. */
2954 setup_dummy_pattern_var(&to_pat_var
, _("To pattern"),
2955 (def
&& def
->patgrp
) ? def
->patgrp
->to
: NULL
);
2956 setup_dummy_pattern_var(&from_pat_var
, _("From pattern"),
2957 (def
&& def
->patgrp
) ? def
->patgrp
->from
: NULL
);
2958 setup_dummy_pattern_var(&sender_pat_var
, _("Sender pattern"),
2959 (def
&& def
->patgrp
) ? def
->patgrp
->sender
: NULL
);
2960 setup_dummy_pattern_var(&cc_pat_var
, _("Cc pattern"),
2961 (def
&& def
->patgrp
) ? def
->patgrp
->cc
: NULL
);
2962 setup_dummy_pattern_var(&news_pat_var
, _("News pattern"),
2963 (def
&& def
->patgrp
) ? def
->patgrp
->news
: NULL
);
2964 setup_dummy_pattern_var(&subj_pat_var
, s_p_v_n
,
2965 (def
&& def
->patgrp
) ? def
->patgrp
->subj
: NULL
);
2966 /* TRANSLATORS: Recip is an abbreviation for Recipients which stands for
2967 all of the recipients of a message. */
2968 setup_dummy_pattern_var(&recip_pat_var
, _("Recip pattern"),
2969 (def
&& def
->patgrp
) ? def
->patgrp
->recip
: NULL
);
2970 /* TRANSLATORS: Partic is an abbreviation for Participants which stands for
2971 all of the recipients plus the sender of a message. */
2972 setup_dummy_pattern_var(&partic_pat_var
, _("Partic pattern"),
2973 (def
&& def
->patgrp
) ? def
->patgrp
->partic
: NULL
);
2974 /* TRANSLATORS: AllText means all of the text of a message */
2975 setup_dummy_pattern_var(&alltext_pat_var
, _("AllText pattern"),
2976 (def
&& def
->patgrp
) ? def
->patgrp
->alltext
: NULL
);
2977 /* TRANSLATORS: BdyText means the text of a message but not the text in the headers */
2978 setup_dummy_pattern_var(&bodytext_pat_var
, _("BdyText pattern"),
2979 (def
&& def
->patgrp
) ? def
->patgrp
->bodytext
: NULL
);
2981 setup_dummy_pattern_var(&keyword_pat_var
, _("Keyword pattern"),
2982 (def
&& def
->patgrp
) ? def
->patgrp
->keyword
: NULL
);
2983 setup_dummy_pattern_var(&charset_pat_var
, _("Charset pattern"),
2984 (def
&& def
->patgrp
) ? def
->patgrp
->charsets
: NULL
);
2986 age_pat_global_ptr
= &age_pat_var
;
2987 /* TRANSLATORS: Age interval is a setting for how old the message is. */
2988 age_pat_var
.name
= cpystr(_("Age interval"));
2989 age_pat_var
.is_used
= 1;
2990 age_pat_var
.is_user
= 1;
2991 if(def
&& def
->patgrp
&& def
->patgrp
->do_age
){
2992 apval
= APVAL(&age_pat_var
, ew
);
2993 *apval
= stringform_of_intvl(def
->patgrp
->age
);
2996 set_current_val(&age_pat_var
, FALSE
, FALSE
);
2998 size_pat_global_ptr
= &size_pat_var
;
2999 size_pat_var
.name
= cpystr(_("Size interval"));
3000 size_pat_var
.is_used
= 1;
3001 size_pat_var
.is_user
= 1;
3002 if(def
&& def
->patgrp
&& def
->patgrp
->do_size
){
3003 apval
= APVAL(&size_pat_var
, ew
);
3004 *apval
= stringform_of_intvl(def
->patgrp
->size
);
3007 set_current_val(&size_pat_var
, FALSE
, FALSE
);
3009 scorei_pat_global_ptr
= &scorei_pat_var
;
3010 /* TRANSLATORS: Score is an alpine concept where the score can be kept for a
3011 message to see if it is a message you want to look at. */
3012 scorei_pat_var
.name
= cpystr(_("Score interval"));
3013 scorei_pat_var
.is_used
= 1;
3014 scorei_pat_var
.is_user
= 1;
3015 if(def
&& def
->patgrp
&& def
->patgrp
->do_score
){
3016 apval
= APVAL(&scorei_pat_var
, ew
);
3017 *apval
= stringform_of_intvl(def
->patgrp
->score
);
3020 set_current_val(&scorei_pat_var
, FALSE
, FALSE
);
3022 role_status1_ptr
= &stat_del_var
; /* so radiobuttons can tell */
3023 stat_del_var
.name
= cpystr(_("Message is Deleted?"));
3024 stat_del_var
.is_used
= 1;
3025 stat_del_var
.is_user
= 1;
3026 apval
= APVAL(&stat_del_var
, ew
);
3027 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_del
: -1)) ? cpystr(f
->name
) : NULL
;
3028 set_current_val(&stat_del_var
, FALSE
, FALSE
);
3030 role_status2_ptr
= &stat_new_var
; /* so radiobuttons can tell */
3031 stat_new_var
.name
= cpystr(_("Message is New (Unseen)?"));
3032 stat_new_var
.is_used
= 1;
3033 stat_new_var
.is_user
= 1;
3034 apval
= APVAL(&stat_new_var
, ew
);
3035 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_new
: -1)) ? cpystr(f
->name
) : NULL
;
3036 set_current_val(&stat_new_var
, FALSE
, FALSE
);
3038 role_status3_ptr
= &stat_imp_var
; /* so radiobuttons can tell */
3039 stat_imp_var
.name
= cpystr(_("Message is Important?"));
3040 stat_imp_var
.is_used
= 1;
3041 stat_imp_var
.is_user
= 1;
3042 apval
= APVAL(&stat_imp_var
, ew
);
3043 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_imp
: -1)) ? cpystr(f
->name
) : NULL
;
3044 set_current_val(&stat_imp_var
, FALSE
, FALSE
);
3046 role_status4_ptr
= &stat_ans_var
; /* so radiobuttons can tell */
3047 stat_ans_var
.name
= cpystr(_("Message is Answered?"));
3048 stat_ans_var
.is_used
= 1;
3049 stat_ans_var
.is_user
= 1;
3050 apval
= APVAL(&stat_ans_var
, ew
);
3051 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_ans
: -1)) ? cpystr(f
->name
) : NULL
;
3052 set_current_val(&stat_ans_var
, FALSE
, FALSE
);
3054 role_status5_ptr
= &stat_8bit_var
; /* so radiobuttons can tell */
3055 stat_8bit_var
.name
= cpystr(_("Subject contains raw 8-bit?"));
3056 stat_8bit_var
.is_used
= 1;
3057 stat_8bit_var
.is_user
= 1;
3058 apval
= APVAL(&stat_8bit_var
, ew
);
3059 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_8bitsubj
: -1)) ? cpystr(f
->name
) : NULL
;
3060 set_current_val(&stat_8bit_var
, FALSE
, FALSE
);
3062 role_status6_ptr
= &stat_rec_var
; /* so radiobuttons can tell */
3063 stat_rec_var
.name
= cpystr(_("Message is Recent?"));
3064 stat_rec_var
.is_used
= 1;
3065 stat_rec_var
.is_user
= 1;
3066 apval
= APVAL(&stat_rec_var
, ew
);
3067 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_rec
: -1)) ? cpystr(f
->name
) : NULL
;
3068 set_current_val(&stat_rec_var
, FALSE
, FALSE
);
3070 role_status7_ptr
= &stat_bom_var
; /* so radiobuttons can tell */
3071 stat_bom_var
.name
= cpystr(_("Beginning of Month?"));
3072 stat_bom_var
.is_used
= 1;
3073 stat_bom_var
.is_user
= 1;
3074 apval
= APVAL(&stat_bom_var
, ew
);
3075 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_bom
: -1)) ? cpystr(f
->name
) : NULL
;
3076 set_current_val(&stat_bom_var
, FALSE
, FALSE
);
3078 role_status8_ptr
= &stat_boy_var
; /* so radiobuttons can tell */
3079 stat_boy_var
.name
= cpystr(_("Beginning of Year?"));
3080 stat_boy_var
.is_used
= 1;
3081 stat_boy_var
.is_user
= 1;
3082 apval
= APVAL(&stat_boy_var
, ew
);
3083 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_boy
: -1)) ? cpystr(f
->name
) : NULL
;
3084 set_current_val(&stat_boy_var
, FALSE
, FALSE
);
3088 convert_statebits_to_vals((def
&& def
->action
) ? def
->action
->state_setting_bits
: 0L, &dval
, &aval
, &ival
, &nval
);
3089 msg_state1_ptr
= &filt_del_var
; /* so radiobuttons can tell */
3090 /* TRANSLATORS: these are actions that might be taken by the rule */
3091 filt_del_var
.name
= cpystr(_("Set Deleted Status"));
3092 filt_del_var
.is_used
= 1;
3093 filt_del_var
.is_user
= 1;
3094 apval
= APVAL(&filt_del_var
, ew
);
3095 *apval
= (f
=msg_state_types(dval
)) ? cpystr(f
->name
) : NULL
;
3096 set_current_val(&filt_del_var
, FALSE
, FALSE
);
3098 msg_state2_ptr
= &filt_new_var
; /* so radiobuttons can tell */
3099 filt_new_var
.name
= cpystr(_("Set New Status"));
3100 filt_new_var
.is_used
= 1;
3101 filt_new_var
.is_user
= 1;
3102 apval
= APVAL(&filt_new_var
, ew
);
3103 *apval
= (f
=msg_state_types(nval
)) ? cpystr(f
->name
) : NULL
;
3104 set_current_val(&filt_new_var
, FALSE
, FALSE
);
3106 msg_state3_ptr
= &filt_imp_var
; /* so radiobuttons can tell */
3107 filt_imp_var
.name
= cpystr(_("Set Important Status"));
3108 filt_imp_var
.is_used
= 1;
3109 filt_imp_var
.is_user
= 1;
3110 apval
= APVAL(&filt_imp_var
, ew
);
3111 *apval
= (f
=msg_state_types(ival
)) ? cpystr(f
->name
) : NULL
;
3112 set_current_val(&filt_imp_var
, FALSE
, FALSE
);
3114 msg_state4_ptr
= &filt_ans_var
; /* so radiobuttons can tell */
3115 filt_ans_var
.name
= cpystr(_("Set Answered Status"));
3116 filt_ans_var
.is_used
= 1;
3117 filt_ans_var
.is_user
= 1;
3118 apval
= APVAL(&filt_ans_var
, ew
);
3119 *apval
= (f
=msg_state_types(aval
)) ? cpystr(f
->name
) : NULL
;
3120 set_current_val(&filt_ans_var
, FALSE
, FALSE
);
3122 inick_var
.name
= cpystr(_("Initialize settings using role"));
3123 inick_var
.is_used
= 1;
3124 inick_var
.is_user
= 1;
3125 apval
= APVAL(&inick_var
, ew
);
3126 *apval
= (def
&& def
->action
&& def
->action
->inherit_nick
&&
3127 def
->action
->inherit_nick
[0])
3128 ? cpystr(def
->action
->inherit_nick
) : NULL
;
3130 role_fldr_ptr
= &fldr_type_var
; /* so radiobuttons can tell */
3131 fldr_type_var
.name
= cpystr(_("Current Folder Type"));
3132 fldr_type_var
.is_used
= 1;
3133 fldr_type_var
.is_user
= 1;
3134 apval
= APVAL(&fldr_type_var
, ew
);
3135 *apval
= (f
=pat_fldr_types((def
&& def
->patgrp
) ? def
->patgrp
->fldr_type
: (!def
&& edit_filter
) ? FLDR_SPECIFIC
: FLDR_DEFL
)) ? cpystr(f
->name
) : NULL
;
3136 set_current_val(&fldr_type_var
, FALSE
, FALSE
);
3138 setup_dummy_pattern_var(&folder_pat_var
, _("Folder List"),
3139 (def
&& def
->patgrp
) ? def
->patgrp
->folder
: NULL
);
3140 /* special default for folder_pat */
3141 alval
= ALVAL(&folder_pat_var
, ew
);
3142 if(alval
&& !*alval
&& !def
&& edit_filter
){
3145 ltmp
= (char **) fs_get(2 * sizeof(*ltmp
));
3146 ltmp
[0] = cpystr(ps_global
->inbox_name
);
3149 set_current_val(&folder_pat_var
, FALSE
, FALSE
);
3152 role_afrom_ptr
= &abook_type_var
; /* so radiobuttons can tell */
3153 abook_type_var
.name
= cpystr(_("Address in address book?"));
3154 abook_type_var
.is_used
= 1;
3155 abook_type_var
.is_user
= 1;
3156 apval
= APVAL(&abook_type_var
, ew
);
3157 *apval
= (f
=inabook_fldr_types((def
&& def
->patgrp
) ? def
->patgrp
->inabook
: IAB_EITHER
)) ? cpystr(f
->name
) : NULL
;
3158 set_current_val(&abook_type_var
, FALSE
, FALSE
);
3160 /* TRANSLATORS: Abook is an abbreviation for Address Book */
3161 setup_dummy_pattern_var(&abook_pat_var
, _("Abook List"),
3162 (def
&& def
->patgrp
) ? def
->patgrp
->abooks
: NULL
);
3165 * This is a little different from some of the other patterns. Tt is
3166 * actually a char ** in the struct instead of a PATTERN_S.
3168 cat_cmd_global_ptr
= &cat_cmd_var
;
3169 cat_cmd_var
.name
= cpystr(_("External Categorizer Commands"));
3170 cat_cmd_var
.is_used
= 1;
3171 cat_cmd_var
.is_user
= 1;
3172 cat_cmd_var
.is_list
= 1;
3173 alval
= ALVAL(&cat_cmd_var
, ew
);
3174 *alval
= (def
&& def
->patgrp
&& def
->patgrp
->category_cmd
&&
3175 def
->patgrp
->category_cmd
[0])
3176 ? copy_list_array(def
->patgrp
->category_cmd
) : NULL
;
3177 set_current_val(&cat_cmd_var
, FALSE
, FALSE
);
3179 cati_global_ptr
= &cati_var
;
3180 cati_var
.name
= cpystr(c_v_n
);
3181 cati_var
.is_used
= 1;
3182 cati_var
.is_user
= 1;
3183 if(def
&& def
->patgrp
&& def
->patgrp
->do_cat
&& def
->patgrp
->category_cmd
&&
3184 def
->patgrp
->category_cmd
[0]){
3185 apval
= APVAL(&cati_var
, ew
);
3186 *apval
= stringform_of_intvl(def
->patgrp
->cat
);
3189 set_current_val(&cati_var
, FALSE
, FALSE
);
3191 cat_lim_global_ptr
= &cat_lim_var
;
3192 cat_lim_var
.name
= cpystr(_("Character Limit"));
3193 cat_lim_var
.is_used
= 1;
3194 cat_lim_var
.is_user
= 1;
3195 cat_lim_var
.global_val
.p
= cpystr("-1");
3196 apval
= APVAL(&cat_lim_var
, ew
);
3197 if(def
&& def
->patgrp
&& def
->patgrp
->category_cmd
&&
3198 def
->patgrp
->category_cmd
[0] && def
->patgrp
->cat_lim
!= -1){
3199 *apval
= (char *) fs_get(20 * sizeof(char));
3200 snprintf(*apval
, 20, "%ld", def
->patgrp
->cat_lim
);
3201 (*apval
)[20-1] = '\0';
3204 set_current_val(&cat_lim_var
, FALSE
, FALSE
);
3206 from_act_var
.name
= cpystr(_("Set From"));
3207 from_act_var
.is_used
= 1;
3208 from_act_var
.is_user
= 1;
3209 if(def
&& def
->action
&& def
->action
->from
){
3213 len
= est_size(def
->action
->from
);
3214 bufp
= (char *) fs_get(len
* sizeof(char));
3215 apval
= APVAL(&from_act_var
, ew
);
3216 *apval
= addr_string_mult(def
->action
->from
, bufp
, len
);
3219 apval
= APVAL(&from_act_var
, ew
);
3223 replyto_act_var
.name
= cpystr(_("Set Reply-To"));
3224 replyto_act_var
.is_used
= 1;
3225 replyto_act_var
.is_user
= 1;
3226 if(def
&& def
->action
&& def
->action
->replyto
){
3230 len
= est_size(def
->action
->replyto
);
3231 bufp
= (char *) fs_get(len
* sizeof(char));
3232 apval
= APVAL(&replyto_act_var
, ew
);
3233 *apval
= addr_string_mult(def
->action
->replyto
, bufp
, len
);
3236 apval
= APVAL(&replyto_act_var
, ew
);
3240 fcc_act_var
.name
= cpystr(_("Set Fcc"));
3241 fcc_act_var
.is_used
= 1;
3242 fcc_act_var
.is_user
= 1;
3243 apval
= APVAL(&fcc_act_var
, ew
);
3244 *apval
= (def
&& def
->action
&& def
->action
->fcc
)
3245 ? cpystr(def
->action
->fcc
) : NULL
;
3247 sort_act_var
.name
= cpystr(_("Set Sort Order"));
3248 sort_act_var
.is_used
= 1;
3249 sort_act_var
.is_user
= 1;
3250 apval
= APVAL(&sort_act_var
, ew
);
3251 if(def
&& def
->action
&& def
->action
->is_a_other
&&
3252 def
->action
->sort_is_set
){
3253 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def
->action
->sortorder
),
3254 (def
->action
->revsort
) ? "/Reverse" : "");
3255 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
3256 *apval
= cpystr(tmp_20k_buf
);
3261 iform_act_var
.name
= cpystr(_("Set Index Format"));
3262 iform_act_var
.is_used
= 1;
3263 iform_act_var
.is_user
= 1;
3264 apval
= APVAL(&iform_act_var
, ew
);
3265 *apval
= (def
&& def
->action
&& def
->action
->is_a_other
&&
3266 def
->action
->index_format
)
3267 ? cpystr(def
->action
->index_format
) : NULL
;
3268 if(ps_global
->VAR_INDEX_FORMAT
){
3269 iform_act_var
.global_val
.p
= cpystr(ps_global
->VAR_INDEX_FORMAT
);
3270 set_current_val(&iform_act_var
, FALSE
, FALSE
);
3273 startup_ptr
= &startup_var
;
3274 startup_var
.name
= cpystr(_("Set Startup Rule"));
3275 startup_var
.is_used
= 1;
3276 startup_var
.is_user
= 1;
3277 apval
= APVAL(&startup_var
, ew
);
3279 if(def
&& def
->action
&& def
->action
->is_a_other
){
3280 *apval
= (f
=startup_rules(def
->action
->startup_rule
))
3281 ? cpystr(f
->name
) : NULL
;
3282 set_current_val(&startup_var
, FALSE
, FALSE
);
3285 *apval
= (f
=startup_rules(IS_NOTSET
)) ? cpystr(f
->name
) : NULL
;
3286 set_current_val(&startup_var
, FALSE
, FALSE
);
3289 /* TRANSLATORS: LiteralSig is a way to keep the signature in the configuration
3290 file instead of in a separate Signature file. */
3291 litsig_act_var
.name
= cpystr(_("Set LiteralSig"));
3292 litsig_act_var
.is_used
= 1;
3293 litsig_act_var
.is_user
= 1;
3294 apval
= APVAL(&litsig_act_var
, ew
);
3295 *apval
= (def
&& def
->action
&& def
->action
->litsig
)
3296 ? cpystr(def
->action
->litsig
) : NULL
;
3298 sig_act_var
.name
= cpystr(_("Set Signature"));
3299 sig_act_var
.is_used
= 1;
3300 sig_act_var
.is_user
= 1;
3301 apval
= APVAL(&sig_act_var
, ew
);
3302 *apval
= (def
&& def
->action
&& def
->action
->sig
)
3303 ? cpystr(def
->action
->sig
) : NULL
;
3305 /* TRANSLATORS: A template is a skeleton of a message to be used
3306 for composing a new message */
3307 templ_act_var
.name
= cpystr(_("Set Template"));
3308 templ_act_var
.is_used
= 1;
3309 templ_act_var
.is_user
= 1;
3310 apval
= APVAL(&templ_act_var
, ew
);
3311 *apval
= (def
&& def
->action
&& def
->action
->template)
3312 ? cpystr(def
->action
->template) : NULL
;
3314 /* TRANSLATORS: Hdrs is an abbreviation for Headers */
3315 cstm_act_var
.name
= cpystr(_("Set Other Hdrs"));
3316 cstm_act_var
.is_used
= 1;
3317 cstm_act_var
.is_user
= 1;
3318 cstm_act_var
.is_list
= 1;
3319 alval
= ALVAL(&cstm_act_var
, ew
);
3320 *alval
= (def
&& def
->action
&& def
->action
->cstm
)
3321 ? copy_list_array(def
->action
->cstm
) : NULL
;
3323 smtp_act_var
.name
= cpystr(u_s_s
);
3324 smtp_act_var
.is_used
= 1;
3325 smtp_act_var
.is_user
= 1;
3326 smtp_act_var
.is_list
= 1;
3327 alval
= ALVAL(&smtp_act_var
, ew
);
3328 *alval
= (def
&& def
->action
&& def
->action
->smtp
)
3329 ? copy_list_array(def
->action
->smtp
) : NULL
;
3331 nntp_act_var
.name
= cpystr(_("Use NNTP Server"));
3332 nntp_act_var
.is_used
= 1;
3333 nntp_act_var
.is_user
= 1;
3334 nntp_act_var
.is_list
= 1;
3335 alval
= ALVAL(&nntp_act_var
, ew
);
3336 *alval
= (def
&& def
->action
&& def
->action
->nntp
)
3337 ? copy_list_array(def
->action
->nntp
) : NULL
;
3339 score_act_global_ptr
= &score_act_var
;
3340 score_act_var
.name
= cpystr(_("Score Value"));
3341 score_act_var
.is_used
= 1;
3342 score_act_var
.is_user
= 1;
3343 if(def
&& def
->action
&& def
->action
->scoreval
>= SCORE_MIN
&&
3344 def
->action
->scoreval
<= SCORE_MAX
)
3345 scoreval
= def
->action
->scoreval
;
3347 score_act_var
.global_val
.p
= cpystr("0");
3349 apval
= APVAL(&score_act_var
, ew
);
3350 *apval
= (char *)fs_get(20 * sizeof(char));
3351 snprintf(*apval
, 20, "%d", scoreval
);
3352 (*apval
)[20-1] = '\0';
3355 set_current_val(&score_act_var
, FALSE
, FALSE
);
3357 hdrtok_act_var
.name
= cpystr(_("Score From Header"));
3358 hdrtok_act_var
.is_used
= 1;
3359 hdrtok_act_var
.is_user
= 1;
3360 if(def
&& def
->action
&& def
->action
->scorevalhdrtok
){
3361 apval
= APVAL(&hdrtok_act_var
, ew
);
3362 *apval
= hdrtok_to_stringform(def
->action
->scorevalhdrtok
);
3365 set_current_val(&hdrtok_act_var
, FALSE
, FALSE
);
3367 role_repl_ptr
= &repl_type_var
; /* so radiobuttons can tell */
3368 /* TRANSLATORS: For these, Use is a now. This part of the rule describes how
3369 it will be used when Replying so it is the Reply Use */
3370 repl_type_var
.name
= cpystr(_("Reply Use"));
3371 repl_type_var
.is_used
= 1;
3372 repl_type_var
.is_user
= 1;
3373 apval
= APVAL(&repl_type_var
, ew
);
3374 *apval
= (f
=role_repl_types((def
&& def
->action
) ? def
->action
->repl_type
: -1)) ? cpystr(f
->name
) : NULL
;
3375 set_current_val(&repl_type_var
, FALSE
, FALSE
);
3377 role_forw_ptr
= &forw_type_var
; /* so radiobuttons can tell */
3378 forw_type_var
.name
= cpystr(_("Forward Use"));
3379 forw_type_var
.is_used
= 1;
3380 forw_type_var
.is_user
= 1;
3381 apval
= APVAL(&forw_type_var
, ew
);
3382 *apval
= (f
=role_forw_types((def
&& def
->action
) ? def
->action
->forw_type
: -1)) ? cpystr(f
->name
) : NULL
;
3383 set_current_val(&forw_type_var
, FALSE
, FALSE
);
3385 comp_type_var
.name
= cpystr(_("Compose Use"));
3386 comp_type_var
.is_used
= 1;
3387 comp_type_var
.is_user
= 1;
3388 apval
= APVAL(&comp_type_var
, ew
);
3389 *apval
= (f
=role_comp_types((def
&& def
->action
) ? def
->action
->comp_type
: -1)) ? cpystr(f
->name
) : NULL
;
3390 set_current_val(&comp_type_var
, FALSE
, FALSE
);
3392 rolecolor_vars
[0].is_used
= 1;
3393 rolecolor_vars
[0].is_user
= 1;
3394 apval
= APVAL(&rolecolor_vars
[0], ew
);
3395 *apval
= (def
&& def
->action
&& def
->action
->incol
&&
3396 def
->action
->incol
->fg
[0])
3397 ? cpystr(def
->action
->incol
->fg
) : NULL
;
3398 rolecolor_vars
[1].is_used
= 1;
3399 rolecolor_vars
[1].is_user
= 1;
3400 rolecolor_vars
[0].name
= cpystr("ic-foreground-color");
3401 rolecolor_vars
[1].name
= cpystr("ic-background-color");
3402 apval
= APVAL(&rolecolor_vars
[1], ew
);
3403 *apval
= (def
&& def
->action
&& def
->action
->incol
&&
3404 def
->action
->incol
->bg
[0])
3405 ? cpystr(def
->action
->incol
->bg
) : NULL
;
3406 set_current_val(&rolecolor_vars
[0], FALSE
, FALSE
);
3407 set_current_val(&rolecolor_vars
[1], FALSE
, FALSE
);
3408 old_fg
= PVAL(&rolecolor_vars
[0], ew
) ? cpystr(PVAL(&rolecolor_vars
[0], ew
))
3410 old_bg
= PVAL(&rolecolor_vars
[1], ew
) ? cpystr(PVAL(&rolecolor_vars
[1], ew
))
3414 /* save the old opt_screen before calling scroll screen again */
3415 saved_screen
= opt_screen
;
3417 pindent
= utf8_width(s_p_v_n
); /* the longest one */
3418 maxpindent
= pindent
+ 6;
3419 for(a
= (def
&& def
->patgrp
) ? def
->patgrp
->arbhdr
: NULL
; a
; a
= a
->next
)
3420 if((lv
=utf8_width(a
->field
? a
->field
: "")+utf8_width(" pattern")) > pindent
)
3423 pindent
= MIN(pindent
, maxpindent
);
3425 pindent
+= NOTLEN
; /* width of `! ' */
3427 pindent
+= 3; /* width of ` = ' */
3430 new_confline(&ctmp
);
3431 ctmp
->help_title
= _("HELP FOR NICKNAME");
3432 ctmp
->var
= &nick_var
;
3433 ctmp
->valoffset
= pindent
;
3434 ctmp
->keymenu
= &config_role_keymenu
;
3435 ctmp
->help
= edit_role
? h_config_role_nick
:
3436 edit_incol
? h_config_incol_nick
:
3437 edit_score
? h_config_score_nick
:
3438 edit_other
? h_config_other_nick
3439 : h_config_filt_nick
;
3440 ctmp
->tool
= t_tool
;
3441 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, nick_var
.name
);
3442 tmp
[sizeof(tmp
)-1] = '\0';
3443 ctmp
->varname
= cpystr(tmp
);
3444 ctmp
->varnamep
= ctmp
;
3445 ctmp
->value
= pretty_value(ps
, ctmp
);
3449 if(rflags
& ROLE_CHANGES
)
3450 first_line
->flags
|= CF_CHANGES
;
3453 new_confline(&ctmp
);
3454 ctmp
->help_title
= _("HELP FOR COMMENT");
3455 ctmp
->var
= &comment_var
;
3456 ctmp
->valoffset
= pindent
;
3457 ctmp
->keymenu
= &config_role_keymenu
;
3458 ctmp
->help
= h_config_role_comment
;
3459 ctmp
->tool
= role_litsig_text_tool
;
3460 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, comment_var
.name
);
3461 tmp
[sizeof(tmp
)-1] = '\0';
3462 ctmp
->varname
= cpystr(tmp
);
3463 ctmp
->varnamep
= ctmp
;
3464 ctmp
->value
= pretty_value(ps
, ctmp
);
3468 new_confline(&ctmp
);
3469 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3471 new_confline(&ctmp
);
3472 ctmp
->flags
|= CF_NOSELECT
;
3473 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(fstr
)) + 4){
3476 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
3477 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
3478 fstr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
3479 ctmp
->value
= cpystr(tmp_20k_buf
);
3482 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
3485 new_confline(&ctmp
);
3486 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3489 new_confline(&ctmp
);
3490 ctmp
->var
= &fldr_type_var
;
3491 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3492 ctmp
->help
= NO_HELP
;
3494 snprintf(tmp
, sizeof(tmp
), "%s =", fldr_type_var
.name
);
3495 tmp
[sizeof(tmp
)-1] = '\0';
3496 ctmp
->varname
= cpystr(tmp
);
3497 ctmp
->varnamep
= ctmpb
= ctmp
;
3498 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3500 new_confline(&ctmp
);
3502 ctmp
->valoffset
= rindent
;
3503 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3504 ctmp
->help
= NO_HELP
;
3506 ctmp
->varnamep
= ctmpb
;
3507 ctmp
->flags
|= CF_NOSELECT
;
3508 ctmp
->value
= cpystr("Set Choose One");
3510 new_confline(&ctmp
);
3512 ctmp
->valoffset
= rindent
;
3513 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3514 ctmp
->help
= NO_HELP
;
3515 ctmp
->tool
= radio_tool
;
3516 ctmp
->varnamep
= ctmpb
;
3517 ctmp
->flags
|= CF_NOSELECT
;
3518 ctmp
->value
= cpystr(set_choose
); \
3520 /* find longest value's name */
3521 for(lv
= 0, i
= 0; (f
= pat_fldr_types(i
)); i
++)
3522 if(lv
< (j
= utf8_width(f
->name
)))
3528 for(i
= 0; (f
= pat_fldr_types(i
)); i
++){
3529 new_confline(&ctmp
);
3530 ctmp
->help_title
= _("HELP FOR CURRENT FOLDER TYPE");
3531 ctmp
->var
= &fldr_type_var
;
3532 ctmp
->valoffset
= rindent
;
3533 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3534 ctmp
->help
= edit_role
? h_config_role_fldr_type
:
3535 edit_incol
? h_config_incol_fldr_type
:
3536 edit_score
? h_config_score_fldr_type
:
3537 edit_other
? h_config_other_fldr_type
3538 : h_config_filt_fldr_type
;
3540 ctmp
->tool
= radio_tool
;
3541 ctmp
->varnamep
= ctmpb
;
3543 if((PVAL(&fldr_type_var
, ew
) &&
3544 !strucmp(PVAL(&fldr_type_var
, ew
), f
->name
))
3545 || (!PVAL(&fldr_type_var
, ew
) && f
->value
== FLDR_DEFL
))
3548 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w",
3549 (fval
== f
->value
) ? R_SELD
: ' ',
3551 tmp
[sizeof(tmp
)-1] = '\0';
3552 ctmp
->value
= cpystr(tmp
);
3556 /* 5 is the width of `(*) ' */
3557 setup_role_pat_alt(ps
, &ctmp
, &folder_pat_var
,
3558 edit_role
? h_config_role_fldr_type
:
3559 edit_incol
? h_config_incol_fldr_type
:
3560 edit_score
? h_config_score_fldr_type
:
3561 edit_other
? h_config_other_fldr_type
3562 : h_config_filt_fldr_type
,
3563 _("HELP FOR FOLDER LIST"),
3564 &config_role_patfolder_keymenu
, t_tool
, rindent
+5,
3565 !(fval
== FLDR_SPECIFIC
));
3567 if(!per_folder_only
){ /* sorry about that indent */
3570 new_confline(&ctmp
);
3571 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3573 new_confline(&ctmp
);
3574 ctmp
->flags
|= CF_NOSELECT
;
3576 /* TRANSLATORS: The %s is replaced with one of the 4 or 5 words below, CURRENT,
3577 SCORED, and so on. */
3578 snprintf(mstr
, sizeof(mstr
), _(" %s MESSAGE CONDITIONS BEGIN HERE "),
3579 edit_role
? _("CURRENT") :
3580 edit_score
? _("SCORED") :
3581 edit_incol
? _("COLORED") :
3582 edit_filter
? _("FILTERED") : _("CURRENT"));
3583 mstr
[sizeof(mstr
)-1] = '\0';
3585 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(mstr
)) + 4){
3588 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
3589 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
3590 mstr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
3591 ctmp
->value
= cpystr(tmp_20k_buf
);
3594 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
3597 new_confline(&ctmp
);
3598 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3600 setup_role_pat(ps
, &ctmp
, &to_pat_var
,
3601 edit_role
? h_config_role_topat
:
3602 edit_incol
? h_config_incol_topat
:
3603 edit_score
? h_config_score_topat
:
3604 edit_other
? h_config_other_topat
3605 : h_config_filt_topat
,
3606 _("HELP FOR TO PATTERN"),
3607 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3609 setup_role_pat(ps
, &ctmp
, &from_pat_var
, h_config_role_frompat
,
3610 _("HELP FOR FROM PATTERN"),
3611 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3613 setup_role_pat(ps
, &ctmp
, &sender_pat_var
, h_config_role_senderpat
,
3614 _("HELP FOR SENDER PATTERN"),
3615 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3617 setup_role_pat(ps
, &ctmp
, &cc_pat_var
, h_config_role_ccpat
,
3618 _("HELP FOR CC PATTERN"),
3619 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3621 setup_role_pat(ps
, &ctmp
, &news_pat_var
, h_config_role_newspat
,
3622 _("HELP FOR NEWS PATTERN"),
3623 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3625 setup_role_pat(ps
, &ctmp
, &subj_pat_var
, h_config_role_subjpat
,
3626 _("HELP FOR SUBJECT PATTERN"),
3627 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3629 setup_role_pat(ps
, &ctmp
, &recip_pat_var
, h_config_role_recippat
,
3630 _("HELP FOR RECIPIENT PATTERN"),
3631 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3633 setup_role_pat(ps
, &ctmp
, &partic_pat_var
, h_config_role_particpat
,
3634 _("HELP FOR PARTICIPANT PATTERN"),
3635 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3637 /* Arbitrary Patterns */
3639 for(j
= 0, a
= (def
&& def
->patgrp
) ? def
->patgrp
->arbhdr
: NULL
;
3642 char *fn
= (a
->field
) ? a
->field
: "";
3645 ea
->next
= (EARB_S
*)fs_get(sizeof(*ea
));
3649 earb
= (EARB_S
*)fs_get(sizeof(*ea
));
3653 memset((void *)ea
, 0, sizeof(*ea
));
3654 ea
->v
= (struct variable
*)fs_get(sizeof(struct variable
));
3655 memset((void *)ea
->v
, 0, sizeof(struct variable
));
3656 ea
->a
= (ARBHDR_S
*)fs_get(sizeof(ARBHDR_S
));
3657 memset((void *)ea
->a
, 0, sizeof(ARBHDR_S
));
3659 ea
->a
->field
= cpystr(fn
);
3661 p
= (char *) fs_get(strlen(fn
) + strlen(" pattern") + 1);
3662 snprintf(p
, strlen(fn
) + strlen(" pattern") + 1, "%s pattern", fn
);
3663 p
[strlen(fn
) + strlen(" pattern") + 1 - 1] = '\0';
3664 setup_dummy_pattern_var(ea
->v
, p
, a
->p
);
3665 fs_give((void **) &p
);
3666 setup_role_pat(ps
, &ctmp
, ea
->v
, h_config_role_arbpat
,
3667 ARB_HELP
, &config_role_xtrahdr_keymenu
,
3668 t_tool
, &earb
, pindent
);
3671 new_confline(&ctmp
);
3672 ctmp
->help_title
= _("HELP FOR EXTRA HEADERS");
3673 ctmp
->value
= cpystr(ADDXHDRS
);
3674 ctmp
->keymenu
= &config_role_keymenu_extra
;
3675 ctmp
->help
= h_config_role_arbpat
;
3676 ctmp
->tool
= addhdr_tool
;
3677 ctmp
->d
.earb
= &earb
;
3680 setup_role_pat(ps
, &ctmp
, &alltext_pat_var
, h_config_role_alltextpat
,
3681 _("HELP FOR ALL TEXT PATTERN"),
3682 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3684 setup_role_pat(ps
, &ctmp
, &bodytext_pat_var
, h_config_role_bodytextpat
,
3685 _("HELP FOR BODY TEXT PATTERN"),
3686 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3689 new_confline(&ctmp
);
3690 ctmp
->help_title
= _("HELP FOR AGE INTERVAL");
3691 ctmp
->var
= &age_pat_var
;
3692 ctmp
->valoffset
= pindent
;
3693 ctmp
->keymenu
= &config_text_keymenu
;
3694 ctmp
->help
= h_config_role_age
;
3695 ctmp
->tool
= t_tool
;
3696 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, age_pat_var
.name
);
3697 tmp
[sizeof(tmp
)-1] = '\0';
3698 ctmp
->varname
= cpystr(tmp
);
3699 ctmp
->varnamep
= ctmp
;
3700 ctmp
->value
= pretty_value(ps
, ctmp
);
3703 new_confline(&ctmp
);
3704 ctmp
->help_title
= _("HELP FOR SIZE INTERVAL");
3705 ctmp
->var
= &size_pat_var
;
3706 ctmp
->valoffset
= pindent
;
3707 ctmp
->keymenu
= &config_text_keymenu
;
3708 ctmp
->help
= h_config_role_size
;
3709 ctmp
->tool
= t_tool
;
3710 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, size_pat_var
.name
);
3711 tmp
[sizeof(tmp
)-1] = '\0';
3712 ctmp
->varname
= cpystr(tmp
);
3713 ctmp
->varnamep
= ctmp
;
3714 ctmp
->value
= pretty_value(ps
, ctmp
);
3717 /* Score Interval */
3718 new_confline(&ctmp
);
3719 ctmp
->help_title
= _("HELP FOR SCORE INTERVAL");
3720 ctmp
->var
= &scorei_pat_var
;
3721 ctmp
->valoffset
= pindent
;
3722 ctmp
->keymenu
= &config_text_keymenu
;
3723 ctmp
->help
= h_config_role_scorei
;
3724 ctmp
->tool
= t_tool
;
3725 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, scorei_pat_var
.name
);
3726 tmp
[sizeof(tmp
)-1] = '\0';
3727 ctmp
->varname
= cpystr(tmp
);
3728 ctmp
->varnamep
= ctmp
;
3729 ctmp
->value
= pretty_value(ps
, ctmp
);
3732 /* Keyword Pattern */
3733 setup_role_pat(ps
, &ctmp
, &keyword_pat_var
, h_config_role_keywordpat
,
3734 _("HELP FOR KEYWORD PATTERN"),
3735 &config_role_keyword_keymenu_not
, role_text_tool_kword
,
3738 /* Charset Pattern */
3739 setup_role_pat(ps
, &ctmp
, &charset_pat_var
, h_config_role_charsetpat
,
3740 _("HELP FOR CHARACTER SET PATTERN"),
3741 &config_role_charset_keymenu_not
, role_text_tool_charset
,
3744 /* Important Status */
3745 SETUP_PAT_STATUS(ctmp
, stat_imp_var
, def
->patgrp
->stat_imp
,
3746 _("HELP FOR IMPORTANT STATUS"), h_config_role_stat_imp
);
3748 SETUP_PAT_STATUS(ctmp
, stat_new_var
, def
->patgrp
->stat_new
,
3749 _("HELP FOR NEW STATUS"), h_config_role_stat_new
);
3751 SETUP_PAT_STATUS(ctmp
, stat_rec_var
, def
->patgrp
->stat_rec
,
3752 _("HELP FOR RECENT STATUS"), h_config_role_stat_recent
);
3753 /* Deleted Status */
3754 SETUP_PAT_STATUS(ctmp
, stat_del_var
, def
->patgrp
->stat_del
,
3755 _("HELP FOR DELETED STATUS"), h_config_role_stat_del
);
3756 /* Answered Status */
3757 SETUP_PAT_STATUS(ctmp
, stat_ans_var
, def
->patgrp
->stat_ans
,
3758 _("HELP FOR ANSWERED STATUS"), h_config_role_stat_ans
);
3760 SETUP_PAT_STATUS(ctmp
, stat_8bit_var
, def
->patgrp
->stat_8bitsubj
,
3761 _("HELP FOR 8-BIT SUBJECT"), h_config_role_stat_8bitsubj
);
3762 /* Beginning of month */
3763 SETUP_PAT_STATUS(ctmp
, stat_bom_var
, def
->patgrp
->stat_bom
,
3764 _("HELP FOR BEGINNING OF MONTH"), h_config_role_bom
);
3765 /* Beginning of year */
3766 SETUP_PAT_STATUS(ctmp
, stat_boy_var
, def
->patgrp
->stat_boy
,
3767 _("HELP FOR BEGINNING OF YEAR"), h_config_role_boy
);
3770 new_confline(&ctmp
);
3771 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3773 /* From in Addrbook */
3774 new_confline(&ctmp
);
3775 ctmp
->var
= &abook_type_var
;
3776 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3777 ctmp
->help
= NO_HELP
;
3779 snprintf(tmp
, sizeof(tmp
), "%s =", abook_type_var
.name
);
3780 tmp
[sizeof(tmp
)-1] = '\0';
3781 ctmp
->varname
= cpystr(tmp
);
3782 ctmp
->varnamep
= ctmpb
= ctmp
;
3783 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3785 new_confline(&ctmp
);
3787 ctmp
->valoffset
= rindent
;
3788 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3789 ctmp
->help
= NO_HELP
;
3791 ctmp
->varnamep
= ctmpb
;
3792 ctmp
->flags
|= CF_NOSELECT
;
3793 ctmp
->value
= cpystr("Set Choose One");
3795 new_confline(&ctmp
);
3797 ctmp
->valoffset
= rindent
;
3798 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3799 ctmp
->help
= NO_HELP
;
3800 ctmp
->tool
= radio_tool
;
3801 ctmp
->varnamep
= ctmpb
;
3802 ctmp
->flags
|= CF_NOSELECT
;
3803 ctmp
->value
= cpystr(set_choose
); \
3805 /* find longest value's name */
3806 for(lv
= 0, i
= 0; (f
= inabook_fldr_types(i
)); i
++)
3807 if(lv
< (j
= utf8_width(f
->name
)))
3813 for(i
= 0; (f
= inabook_fldr_types(i
)); i
++){
3814 new_confline(&ctmp
);
3815 ctmp
->help_title
= _("HELP FOR ADDRESS IN ADDRESS BOOK");
3816 ctmp
->var
= &abook_type_var
;
3817 ctmp
->valoffset
= rindent
;
3818 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3819 ctmp
->help
= h_config_role_abookfrom
;
3821 ctmp
->tool
= radio_tool
;
3822 ctmp
->varnamep
= ctmpb
;
3824 if((PVAL(&abook_type_var
, ew
) &&
3825 !strucmp(PVAL(&abook_type_var
, ew
), f
->name
))
3826 || (!PVAL(&abook_type_var
, ew
) && f
->value
== IAB_DEFL
))
3829 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w",
3830 (fval
== f
->value
) ? R_SELD
: ' ',
3832 tmp
[sizeof(tmp
)-1] = '\0';
3833 ctmp
->value
= cpystr(tmp
);
3836 /* Specific list of abooks */
3837 /* 5 is the width of `(*) ' */
3838 setup_role_pat_alt(ps
, &ctmp
, &abook_pat_var
, h_config_role_abookfrom
,
3839 _("HELP FOR ABOOK LIST"),
3840 &config_role_afrom_keymenu
, role_text_tool_afrom
, rindent
+5,
3841 !(fval
== IAB_SPEC_YES
|| fval
== IAB_SPEC_NO
));
3843 /* Which addresses to check for */
3844 inabook_type_var
.name
= cpystr(_("Types of addresses to check for in address book"));
3845 inabook_type_var
.is_used
= 1;
3846 inabook_type_var
.is_user
= 1;
3847 inabook_type_var
.is_list
= 1;
3848 clrbitmap(inabook_type_list
);
3849 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_FROM
)
3850 setbitn(INABOOK_FROM
, inabook_type_list
);
3851 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_REPLYTO
)
3852 setbitn(INABOOK_REPLYTO
, inabook_type_list
);
3853 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_SENDER
)
3854 setbitn(INABOOK_SENDER
, inabook_type_list
);
3855 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_TO
)
3856 setbitn(INABOOK_TO
, inabook_type_list
);
3857 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_CC
)
3858 setbitn(INABOOK_CC
, inabook_type_list
);
3860 /* default setting */
3861 if(!(bitnset(INABOOK_FROM
, inabook_type_list
)
3862 || bitnset(INABOOK_REPLYTO
, inabook_type_list
)
3863 || bitnset(INABOOK_SENDER
, inabook_type_list
)
3864 || bitnset(INABOOK_TO
, inabook_type_list
)
3865 || bitnset(INABOOK_CC
, inabook_type_list
))){
3866 setbitn(INABOOK_FROM
, inabook_type_list
);
3867 setbitn(INABOOK_REPLYTO
, inabook_type_list
);
3870 new_confline(&ctmp
);
3871 ctmp
->var
= &inabook_type_var
;
3872 ctmp
->varoffset
= 4;
3873 ctmp
->valoffset
= 23;
3874 ctmp
->keymenu
= &config_checkbox_keymenu
;
3875 ctmp
->help
= NO_HELP
;
3877 snprintf(tmp
, sizeof(tmp
), "%-20s =", inabook_type_var
.name
);
3878 tmp
[sizeof(tmp
)-1] = '\0';
3879 ctmp
->varname
= cpystr(tmp
);
3880 ctmp
->varnamep
= ctmpb
= ctmp
;
3881 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3883 new_confline(&ctmp
);
3885 ctmp
->valoffset
= rindent
;
3886 ctmp
->keymenu
= &config_checkbox_keymenu
;
3887 ctmp
->help
= NO_HELP
;
3888 ctmp
->tool
= inabook_checkbox_tool
;
3889 ctmp
->varnamep
= ctmpb
;
3890 ctmp
->flags
|= CF_NOSELECT
;
3891 ctmp
->value
= cpystr("Set Address types");
3893 new_confline(&ctmp
);
3895 ctmp
->valoffset
= rindent
;
3896 ctmp
->keymenu
= &config_checkbox_keymenu
;
3897 ctmp
->help
= NO_HELP
;
3898 ctmp
->tool
= inabook_checkbox_tool
;
3899 ctmp
->varnamep
= ctmpb
;
3900 ctmp
->flags
|= CF_NOSELECT
;
3901 ctmp
->value
= cpystr(set_choose
);
3903 /* find longest value's name */
3904 for(lv
= 0, i
= 0; (f
= inabook_feature_list(i
)); i
++){
3905 if(lv
< (j
= utf8_width(f
->name
)))
3911 for(i
= 0; (f
= inabook_feature_list(i
)); i
++){
3912 new_confline(&ctmp
);
3913 ctmp
->var
= &opt_var
;
3914 ctmp
->help_title
= _("HELP FOR ADDRESS TYPES");
3915 ctmp
->varnamep
= ctmpb
;
3916 ctmp
->keymenu
= &config_checkbox_keymenu
;
3919 ctmp
->help
= h_config_inabook_from
;
3921 case INABOOK_REPLYTO
:
3922 ctmp
->help
= h_config_inabook_replyto
;
3924 case INABOOK_SENDER
:
3925 ctmp
->help
= h_config_inabook_sender
;
3928 ctmp
->help
= h_config_inabook_to
;
3931 ctmp
->help
= h_config_inabook_cc
;
3935 ctmp
->tool
= inabook_checkbox_tool
;
3936 ctmp
->valoffset
= rindent
;
3938 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w",
3939 bitnset(f
->value
, inabook_type_list
) ? 'X' : ' ',
3941 tmp
[sizeof(tmp
)-1] = '\0';
3942 ctmp
->value
= cpystr(tmp
);
3946 new_confline(&ctmp
);
3947 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3949 /* 4 is indent of "Command", c_v_n is longest of these three, 3 is ` = ' */
3950 i
= 4 + utf8_width(c_v_n
) + 3;
3952 /* External Command Categorizer */
3953 new_confline(&ctmp
);
3954 ctmp
->var
= &cat_cmd_var
;
3955 ctmp
->keymenu
= &config_text_keymenu
;
3956 ctmp
->help
= NO_HELP
;
3958 snprintf(tmp
, sizeof(tmp
), "%s =", cat_cmd_var
.name
);
3959 tmp
[sizeof(tmp
)-1] = '\0';
3960 ctmp
->varname
= cpystr(tmp
);
3961 ctmp
->varnamep
= ctmpb
= ctmp
;
3962 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3965 new_confline(&ctmp
);
3966 ctmp
->help_title
= _("HELP FOR CATEGORIZER COMMAND");
3967 ctmp
->var
= &cat_cmd_var
;
3968 ctmp
->varoffset
= 4;
3969 ctmp
->valoffset
= i
;
3970 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
3971 ctmp
->help
= h_config_role_cat_cmd
;
3972 ctmp
->tool
= t_tool
;
3973 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", i
-4-3, i
-4-3, "Command");
3974 tmp
[sizeof(tmp
)-1] = '\0';
3975 ctmp
->varname
= cpystr(tmp
);
3976 ctmp
->varnamep
= ctmpb
= ctmp
;
3977 ctmp
->flags
= CF_STARTITEM
;
3979 if((lval
= LVAL(&cat_cmd_var
, ew
)) != NULL
&& lval
[0]){
3980 for(j
= 0; lval
[j
]; j
++){
3982 (void) new_confline(&ctmp
);
3984 ctmp
->var
= &cat_cmd_var
;
3986 ctmp
->valoffset
= i
;
3987 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
3988 ctmp
->help
= h_config_role_cat_cmd
;
3989 ctmp
->tool
= t_tool
;
3990 ctmp
->varnamep
= ctmp
;
3991 ctmp
->value
= pretty_value(ps
, ctmp
);
3995 ctmp
->value
= pretty_value(ps
, ctmp
);
3997 /* Exit status interval */
3998 new_confline(&ctmp
);
3999 ctmp
->help_title
= _("HELP FOR CATEGORIZER EXIT STATUS");
4000 ctmp
->var
= &cati_var
;
4001 ctmp
->varoffset
= 4;
4002 ctmp
->valoffset
= i
;
4003 ctmp
->keymenu
= &config_text_keymenu
;
4004 ctmp
->help
= h_config_role_cat_status
;
4005 ctmp
->tool
= t_tool
;
4006 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", i
-4-3, i
-4-3, cati_var
.name
);
4007 tmp
[sizeof(tmp
)-1] = '\0';
4008 ctmp
->varname
= cpystr(tmp
);
4009 ctmp
->varnamep
= ctmp
;
4010 ctmp
->value
= pretty_value(ps
, ctmp
);
4012 /* Character Limit */
4013 new_confline(&ctmp
);
4014 ctmp
->help_title
= _("HELP FOR CHARACTER LIMIT");
4015 ctmp
->var
= &cat_lim_var
;
4016 ctmp
->varoffset
= 4;
4017 ctmp
->valoffset
= i
;
4018 ctmp
->keymenu
= &config_text_keymenu
;
4019 ctmp
->help
= h_config_role_cat_limit
;
4020 ctmp
->tool
= t_tool
;
4021 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", i
-4-3, i
-4-3, cat_lim_var
.name
);
4022 tmp
[sizeof(tmp
)-1] = '\0';
4023 ctmp
->varname
= cpystr(tmp
);
4024 ctmp
->varnamep
= ctmp
;
4025 ctmp
->value
= pretty_value(ps
, ctmp
);
4026 ctmp
->flags
|= CF_NUMBER
;
4029 if(!edit_srch
){ /* sorry about that indent */
4033 new_confline(&ctmp
);
4034 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4036 new_confline(&ctmp
);
4037 ctmp
->flags
|= CF_NOSELECT
;
4038 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(astr
)) + 4){
4041 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
4042 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
4043 astr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
4044 ctmp
->value
= cpystr(tmp_20k_buf
);
4047 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
4052 roindent
= utf8_width(u_s_s
); /* the longest one */
4053 roindent
+= 3; /* width of ` = ' */
4056 new_confline(&ctmp
);
4057 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4059 /* Inherit Nickname */
4060 new_confline(&ctmp
);
4061 inick_confs
[INICK_INICK_CONF
] = ctmp
;
4062 ctmp
->help_title
= _("HELP FOR INITIAL SET NICKNAME");
4063 ctmp
->var
= &inick_var
;
4064 ctmp
->keymenu
= &config_role_inick_keymenu
;
4065 ctmp
->help
= h_config_role_inick
;
4066 ctmp
->tool
= role_text_tool_inick
;
4067 snprintf(tmp
, sizeof(tmp
), "%s :", inick_var
.name
);
4068 tmp
[sizeof(tmp
)-1] = '\0';
4069 ctmp
->valoffset
= utf8_width(tmp
)+1;
4070 ctmp
->varname
= cpystr(tmp
);
4071 ctmp
->varnamep
= ctmp
;
4074 new_confline(&ctmp
);
4075 inick_confs
[INICK_FROM_CONF
] = ctmp
;
4076 ctmp
->help_title
= _("HELP FOR SET FROM ACTION");
4077 ctmp
->var
= &from_act_var
;
4078 ctmp
->valoffset
= roindent
;
4079 ctmp
->keymenu
= &config_role_addr_act_keymenu
;
4080 ctmp
->help
= h_config_role_setfrom
;
4081 ctmp
->tool
= role_text_tool
;
4082 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, from_act_var
.name
);
4083 tmp
[sizeof(tmp
)-1] = '\0';
4084 ctmp
->varname
= cpystr(tmp
);
4085 ctmp
->varnamep
= ctmp
;
4087 /* Reply-To Action */
4088 new_confline(&ctmp
);
4089 inick_confs
[INICK_REPLYTO_CONF
] = ctmp
;
4090 ctmp
->help_title
= _("HELP FOR SET REPLY-TO ACTION");
4091 ctmp
->var
= &replyto_act_var
;
4092 ctmp
->valoffset
= roindent
;
4093 ctmp
->keymenu
= &config_role_addr_act_keymenu
;
4094 ctmp
->help
= h_config_role_setreplyto
;
4095 ctmp
->tool
= role_text_tool
;
4096 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, replyto_act_var
.name
);
4097 tmp
[sizeof(tmp
)-1] = '\0';
4098 ctmp
->varname
= cpystr(tmp
);
4099 ctmp
->varnamep
= ctmp
;
4102 new_confline(&ctmp
);
4103 inick_confs
[INICK_FCC_CONF
] = ctmp
;
4104 ctmp
->help_title
= _("HELP FOR SET FCC ACTION");
4105 ctmp
->var
= &fcc_act_var
;
4106 ctmp
->valoffset
= roindent
;
4107 ctmp
->keymenu
= &config_role_actionfolder_keymenu
;
4108 ctmp
->help
= h_config_role_setfcc
;
4109 ctmp
->tool
= role_text_tool
;
4110 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, fcc_act_var
.name
);
4111 tmp
[sizeof(tmp
)-1] = '\0';
4112 ctmp
->varname
= cpystr(tmp
);
4113 ctmp
->varnamep
= ctmp
;
4116 new_confline(&ctmp
);
4117 inick_confs
[INICK_LITSIG_CONF
] = ctmp
;
4118 ctmp
->help_title
= _("HELP FOR SET LITERAL SIGNATURE ACTION");
4119 ctmp
->var
= &litsig_act_var
;
4120 ctmp
->valoffset
= roindent
;
4121 ctmp
->keymenu
= &config_text_keymenu
;
4122 ctmp
->help
= h_config_role_setlitsig
;
4123 ctmp
->tool
= role_litsig_text_tool
;
4124 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, litsig_act_var
.name
);
4125 tmp
[sizeof(tmp
)-1] = '\0';
4126 ctmp
->varname
= cpystr(tmp
);
4127 ctmp
->varnamep
= ctmp
;
4130 new_confline(&ctmp
);
4131 inick_confs
[INICK_SIG_CONF
] = ctmp
;
4132 ctmp
->help_title
= _("HELP FOR SET SIGNATURE ACTION");
4133 ctmp
->var
= &sig_act_var
;
4134 ctmp
->valoffset
= roindent
;
4135 if(F_ON(F_DISABLE_ROLES_SIGEDIT
, ps_global
))
4136 ctmp
->keymenu
= &config_role_file_res_keymenu
;
4138 ctmp
->keymenu
= &config_role_file_keymenu
;
4140 ctmp
->help
= h_config_role_setsig
;
4141 ctmp
->tool
= role_text_tool
;
4142 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, sig_act_var
.name
);
4143 tmp
[sizeof(tmp
)-1] = '\0';
4144 ctmp
->varname
= cpystr(tmp
);
4145 ctmp
->varnamep
= ctmp
;
4147 /* Template Action */
4148 new_confline(&ctmp
);
4149 inick_confs
[INICK_TEMPL_CONF
] = ctmp
;
4150 ctmp
->help_title
= _("HELP FOR SET TEMPLATE ACTION");
4151 ctmp
->var
= &templ_act_var
;
4152 ctmp
->valoffset
= roindent
;
4153 if(F_ON(F_DISABLE_ROLES_TEMPLEDIT
, ps_global
))
4154 ctmp
->keymenu
= &config_role_file_res_keymenu
;
4156 ctmp
->keymenu
= &config_role_file_keymenu
;
4158 ctmp
->help
= h_config_role_settempl
;
4159 ctmp
->tool
= role_text_tool
;
4160 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, templ_act_var
.name
);
4161 tmp
[sizeof(tmp
)-1] = '\0';
4162 ctmp
->varname
= cpystr(tmp
);
4163 ctmp
->varnamep
= ctmp
;
4165 /* Other Headers Action */
4166 new_confline(&ctmp
);
4167 inick_confs
[INICK_CSTM_CONF
] = ctmp
;
4168 ctmp
->help_title
= _("HELP FOR SET OTHER HEADERS ACTION");
4169 ctmp
->var
= &cstm_act_var
;
4170 ctmp
->valoffset
= roindent
;
4171 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4172 ctmp
->help
= h_config_role_setotherhdr
;
4173 ctmp
->tool
= role_cstm_text_tool
;
4174 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, cstm_act_var
.name
);
4175 tmp
[sizeof(tmp
)-1] = '\0';
4176 ctmp
->varname
= cpystr(tmp
);
4177 ctmp
->varnamep
= ctmpb
= ctmp
;
4178 ctmp
->flags
= CF_STARTITEM
;
4180 if((lval
= LVAL(&cstm_act_var
, ew
)) != NULL
){
4181 for(i
= 0; lval
[i
]; i
++){
4183 (void)new_confline(&ctmp
);
4185 ctmp
->var
= &cstm_act_var
;
4187 ctmp
->valoffset
= roindent
;
4188 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4189 ctmp
->help
= h_config_role_setotherhdr
;
4190 ctmp
->tool
= role_cstm_text_tool
;
4191 ctmp
->varnamep
= ctmpb
;
4197 /* SMTP Server Action */
4198 new_confline(&ctmp
);
4199 inick_confs
[INICK_SMTP_CONF
] = ctmp
;
4200 ctmp
->help_title
= _("HELP FOR SMTP SERVER ACTION");
4201 ctmp
->var
= &smtp_act_var
;
4202 ctmp
->valoffset
= roindent
;
4203 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4204 ctmp
->help
= h_config_role_usesmtp
;
4205 ctmp
->tool
= t_tool
;
4206 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, smtp_act_var
.name
);
4207 tmp
[sizeof(tmp
)-1] = '\0';
4208 ctmp
->varname
= cpystr(tmp
);
4209 ctmp
->varnamep
= ctmpb
= ctmp
;
4210 ctmp
->flags
= CF_STARTITEM
;
4212 if((lval
= LVAL(&smtp_act_var
, ew
)) != NULL
){
4213 for(i
= 0; lval
[i
]; i
++){
4215 (void)new_confline(&ctmp
);
4217 ctmp
->var
= &smtp_act_var
;
4219 ctmp
->valoffset
= roindent
;
4220 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4221 ctmp
->help
= h_config_role_usesmtp
;
4222 ctmp
->tool
= t_tool
;
4223 ctmp
->varnamep
= ctmpb
;
4229 /* NNTP Server Action */
4230 new_confline(&ctmp
);
4231 inick_confs
[INICK_NNTP_CONF
] = ctmp
;
4232 ctmp
->help_title
= _("HELP FOR NNTP SERVER ACTION");
4233 ctmp
->var
= &nntp_act_var
;
4234 ctmp
->valoffset
= roindent
;
4235 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4236 ctmp
->help
= h_config_role_usenntp
;
4237 ctmp
->tool
= t_tool
;
4238 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, nntp_act_var
.name
);
4239 tmp
[sizeof(tmp
)-1] = '\0';
4240 ctmp
->varname
= cpystr(tmp
);
4241 ctmp
->varnamep
= ctmpb
= ctmp
;
4242 ctmp
->flags
= CF_STARTITEM
;
4244 if((lval
= LVAL(&nntp_act_var
, ew
)) != NULL
){
4245 for(i
= 0; lval
[i
]; i
++){
4247 (void)new_confline(&ctmp
);
4249 ctmp
->var
= &nntp_act_var
;
4251 ctmp
->valoffset
= roindent
;
4252 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4253 ctmp
->help
= h_config_role_usenntp
;
4254 ctmp
->tool
= t_tool
;
4255 ctmp
->varnamep
= ctmpb
;
4261 calculate_inick_stuff(ps
);
4264 inick_confs
[INICK_INICK_CONF
] = NULL
;
4269 sindent
= MAX(utf8_width(score_act_var
.name
),utf8_width(hdrtok_act_var
.name
)) + 3;
4272 new_confline(&ctmp
);
4273 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4275 /* Score Value -- This doesn't inherit from inick */
4276 new_confline(&ctmp
);
4277 ctmp
->help_title
= _("HELP FOR SCORE VALUE ACTION");
4278 ctmp
->var
= &score_act_var
;
4279 ctmp
->valoffset
= sindent
;
4280 ctmp
->keymenu
= &config_text_keymenu
;
4281 ctmp
->help
= h_config_role_scoreval
;
4282 ctmp
->tool
= text_tool
;
4283 ctmp
->flags
|= CF_NUMBER
;
4284 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", sindent
-3, sindent
-3, score_act_var
.name
);
4285 tmp
[sizeof(tmp
)-1] = '\0';
4286 ctmp
->varname
= cpystr(tmp
);
4287 ctmp
->varnamep
= ctmp
;
4288 ctmp
->value
= pretty_value(ps
, ctmp
);
4290 new_confline(&ctmp
);
4291 ctmp
->flags
|= CF_NOSELECT
;
4292 ctmp
->value
= cpystr(" OR");
4294 /* Score From Header */
4295 new_confline(&ctmp
);
4296 ctmp
->help_title
= _("HELP FOR SCORE VALUE FROM HEADER ACTION");
4297 ctmp
->var
= &hdrtok_act_var
;
4298 ctmp
->valoffset
= sindent
;
4299 ctmp
->keymenu
= &config_text_keymenu
;
4300 ctmp
->help
= h_config_role_scorehdrtok
;
4301 ctmp
->tool
= text_tool
;
4302 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", sindent
-3, sindent
-3, hdrtok_act_var
.name
);
4303 tmp
[sizeof(tmp
)-1] = '\0';
4304 ctmp
->varname
= cpystr(tmp
);
4305 ctmp
->varnamep
= ctmp
;
4306 ctmp
->value
= pretty_value(ps
, ctmp
);
4311 * Filtering got added in stages, so instead of simply having a
4312 * variable in action which is set to one of the three possible
4313 * values (FILTER_KILL, FILTER_STATE, FILTER_FOLDER) we infer
4314 * the value from other variables. (Perhaps it would still make
4315 * sense to change this.)
4316 * Action->kill is set iff the user checks Delete.
4317 * If the user checks the box that says Just Set State, then kill
4318 * is not set and action->folder is not set (and vice versa).
4319 * And finally, FILTER_FOLDER is set if !kill and action->folder is set.
4320 * (And it is set here as the default if there is no default
4321 * action and the user is required to fill in the Folder.)
4323 if(def
&& def
->action
&& def
->action
->kill
)
4325 else if(def
&& def
->action
&& !def
->action
->kill
&&
4326 !def
->action
->folder
)
4327 fval
= FILTER_STATE
;
4329 fval
= FILTER_FOLDER
;
4331 role_filt_ptr
= &filter_type_var
; /* so radiobuttons can tell */
4332 filter_type_var
.name
= cpystr(_("Filter Action"));
4333 filter_type_var
.is_used
= 1;
4334 filter_type_var
.is_user
= 1;
4335 apval
= APVAL(&filter_type_var
, ew
);
4336 *apval
= (f
=filter_types(fval
)) ? cpystr(f
->name
) : NULL
;
4337 set_current_val(&filter_type_var
, FALSE
, FALSE
);
4340 new_confline(&ctmp
);
4341 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4344 new_confline(&ctmp
);
4345 ctmp
->var
= &filter_type_var
;
4346 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4347 ctmp
->help
= NO_HELP
;
4349 snprintf(tmp
, sizeof(tmp
), "%s =", filter_type_var
.name
);
4350 tmp
[sizeof(tmp
)-1] = '\0';
4351 ctmp
->varname
= cpystr(tmp
);
4352 ctmp
->varnamep
= ctmpb
= ctmp
;
4353 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4355 new_confline(&ctmp
);
4357 ctmp
->valoffset
= rindent
;
4358 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4359 ctmp
->help
= NO_HELP
;
4361 ctmp
->varnamep
= ctmpb
;
4362 ctmp
->flags
|= CF_NOSELECT
;
4363 ctmp
->value
= cpystr("Set Choose One");
4365 new_confline(&ctmp
);
4367 ctmp
->valoffset
= rindent
;
4368 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4369 ctmp
->help
= NO_HELP
;
4370 ctmp
->tool
= radio_tool
;
4371 ctmp
->varnamep
= ctmpb
;
4372 ctmp
->flags
|= CF_NOSELECT
;
4373 ctmp
->value
= cpystr(set_choose
); \
4375 /* find longest value's name */
4376 for(lv
= 0, i
= 0; (f
= filter_types(i
)); i
++)
4377 if(lv
< (j
= utf8_width(f
->name
)))
4382 for(i
= 0; (f
= filter_types(i
)); i
++){
4383 new_confline(&ctmp
);
4384 ctmp
->help_title
= _("HELP FOR FILTER ACTION");
4385 ctmp
->var
= &filter_type_var
;
4386 ctmp
->valoffset
= rindent
;
4387 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4388 ctmp
->help
= h_config_filt_rule_type
;
4390 ctmp
->tool
= radio_tool
;
4391 ctmp
->varnamep
= ctmpb
;
4392 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (f
->value
== fval
) ? R_SELD
: ' ',
4394 tmp
[sizeof(tmp
)-1] = '\0';
4395 ctmp
->value
= cpystr(tmp
);
4398 /* Specific list of folders to copy to */
4399 setup_dummy_pattern_var(&folder_act_var
, _("Folder List"),
4400 (def
&& def
->action
)
4401 ? def
->action
->folder
: NULL
);
4403 /* 5 is the width of `(*) ' */
4404 setup_role_pat_alt(ps
, &ctmp
, &folder_act_var
, h_config_filter_folder
,
4405 _("HELP FOR FILTER FOLDER NAME"),
4406 &config_role_actionfolder_keymenu
, t_tool
, rindent
+5,
4407 !(fval
== FILTER_FOLDER
));
4409 SETUP_MSG_STATE(ctmp
, filt_imp_var
, ival
,
4410 _("HELP FOR SET IMPORTANT STATUS"), h_config_filt_stat_imp
);
4411 SETUP_MSG_STATE(ctmp
, filt_new_var
, nval
,
4412 _("HELP FOR SET NEW STATUS"), h_config_filt_stat_new
);
4413 SETUP_MSG_STATE(ctmp
, filt_del_var
, dval
,
4414 _("HELP FOR SET DELETED STATUS"), h_config_filt_stat_del
);
4415 SETUP_MSG_STATE(ctmp
, filt_ans_var
, aval
,
4416 _("HELP FOR SET ANSWERED STATUS"), h_config_filt_stat_ans
);
4419 new_confline(&ctmp
);
4420 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4422 /* Keywords to be Set */
4423 setup_dummy_pattern_var(&keyword_set_var
, _("Set These Keywords"),
4424 (def
&& def
->action
)
4425 ? def
->action
->keyword_set
: NULL
);
4426 setup_role_pat(ps
, &ctmp
, &keyword_set_var
, h_config_filter_kw_set
,
4427 _("HELP FOR KEYWORDS TO BE SET"),
4428 &config_role_keyword_keymenu
, role_text_tool_kword
,
4431 /* Keywords to be Cleared */
4432 setup_dummy_pattern_var(&keyword_clr_var
, _("Clear These Keywords"),
4433 (def
&& def
->action
)
4434 ? def
->action
->keyword_clr
: NULL
);
4435 setup_role_pat(ps
, &ctmp
, &keyword_clr_var
, h_config_filter_kw_clr
,
4436 _("HELP FOR KEYWORDS TO BE CLEARED"),
4437 &config_role_keyword_keymenu
, role_text_tool_kword
,
4446 new_confline(&ctmp
);
4447 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4449 new_confline(&ctmp
)->var
= NULL
;
4450 snprintf(tmp
, sizeof(tmp
), "%s =", sort_act_var
.name
);
4451 tmp
[sizeof(tmp
)-1] = '\0';
4452 ctmp
->varname
= cpystr(tmp
);
4453 ctmp
->varnamep
= ctmpb
= ctmp
;
4454 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4455 ctmp
->help
= NO_HELP
;
4456 ctmp
->tool
= role_sort_tool
;
4457 ctmp
->valoffset
= rindent
;
4458 ctmp
->flags
|= CF_NOSELECT
;
4460 new_confline(&ctmp
)->var
= NULL
;
4461 ctmp
->varnamep
= ctmpb
;
4462 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4463 ctmp
->help
= NO_HELP
;
4464 ctmp
->tool
= role_sort_tool
;
4465 ctmp
->valoffset
= rindent
;
4466 ctmp
->flags
|= CF_NOSELECT
;
4467 ctmp
->value
= cpystr("Set Sort Options");
4469 new_confline(&ctmp
)->var
= NULL
;
4470 ctmp
->varnamep
= ctmpb
;
4471 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4472 ctmp
->help
= NO_HELP
;
4473 ctmp
->tool
= role_sort_tool
;
4474 ctmp
->valoffset
= rindent
;
4475 ctmp
->flags
|= CF_NOSELECT
;
4476 ctmp
->value
= cpystr(set_choose
); \
4478 pval
= PVAL(&sort_act_var
, ew
);
4480 decode_sort(pval
, &def_sort
, &def_sort_rev
);
4482 /* allow user to set their default sort order */
4483 new_confline(&ctmp
)->var
= &sort_act_var
;
4484 ctmp
->varnamep
= ctmpb
;
4485 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4486 ctmp
->help
= h_config_perfolder_sort
;
4487 ctmp
->tool
= role_sort_tool
;
4488 ctmp
->valoffset
= rindent
;
4490 ctmp
->value
= generalized_sort_pretty_value(ps
, ctmp
, 0);
4492 for(j
= 0; j
< 2; j
++){
4493 for(i
= 0; ps
->sort_types
[i
] != EndofList
; i
++){
4494 new_confline(&ctmp
)->var
= &sort_act_var
;
4495 ctmp
->varnamep
= ctmpb
;
4496 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4497 ctmp
->help
= h_config_perfolder_sort
;
4498 ctmp
->tool
= role_sort_tool
;
4499 ctmp
->valoffset
= rindent
;
4500 ctmp
->varmem
= i
+ (j
* EndofList
);
4501 ctmp
->value
= generalized_sort_pretty_value(ps
, ctmp
,
4508 new_confline(&ctmp
);
4509 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4511 oindent
= utf8_width(iform_act_var
.name
) + 3;
4513 /* Index Format Action */
4514 new_confline(&ctmp
);
4515 ctmp
->help_title
= _("HELP FOR SET INDEX FORMAT ACTION");
4516 ctmp
->var
= &iform_act_var
;
4517 ctmp
->valoffset
= oindent
;
4518 ctmp
->keymenu
= &config_text_keymenu
;
4519 ctmp
->help
= h_config_set_index_format
;
4520 ctmp
->tool
= text_tool
;
4521 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", oindent
-3, oindent
-3, iform_act_var
.name
);
4522 tmp
[sizeof(tmp
)-1] = '\0';
4523 ctmp
->varname
= cpystr(tmp
);
4524 ctmp
->varnamep
= ctmp
;
4525 ctmp
->value
= pretty_value(ps
, ctmp
);
4528 new_confline(&ctmp
);
4529 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4531 new_confline(&ctmp
);
4532 ctmp
->flags
|= CF_STARTITEM
;
4533 utf8_snprintf(tmp
, sizeof(tmp
), "%s =", startup_var
.name
);
4534 tmp
[sizeof(tmp
)-1] = '\0';
4535 ctmp
->varname
= cpystr(tmp
);
4536 standard_radio_setup(ps
, &ctmp
, &startup_var
, NULL
);
4539 if(edit_incol
&& pico_usingcolor()){
4540 char *pval0
, *pval1
;
4544 new_confline(&ctmp
);
4545 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4547 new_confline(&ctmp
);
4548 ctmp
->var
= &rolecolor_vars
[0]; /* foreground */
4549 ctmp
->varname
= cpystr(_("Index Line Color ="));
4550 ctmp
->varnamep
= ctmpb
= ctmp
;
4551 ctmp
->flags
|= (CF_STARTITEM
| CF_NOSELECT
);
4552 ctmp
->keymenu
= &role_color_setting_keymenu
;
4554 pval0
= PVAL(&rolecolor_vars
[0], ew
);
4555 pval1
= PVAL(&rolecolor_vars
[1], ew
);
4557 def
= !(pval0
[0] && pval1
[1]);
4561 add_color_setting_disp(ps
, &ctmp
, &rolecolor_vars
[0], ctmpb
,
4562 &role_color_setting_keymenu
,
4563 &config_checkbox_keymenu
,
4566 def
? ps
->VAR_NORM_FORE_COLOR
4567 : PVAL(&rolecolor_vars
[0], ew
),
4568 def
? ps
->VAR_NORM_BACK_COLOR
4569 : PVAL(&rolecolor_vars
[1], ew
),
4578 new_confline(&ctmp
);
4579 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4581 new_confline(&ctmp
);
4582 ctmp
->flags
|= CF_NOSELECT
;
4583 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(ostr
)) + 4){
4586 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
4587 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
4588 ostr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
4589 ctmp
->value
= cpystr(tmp_20k_buf
);
4592 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
4595 new_confline(&ctmp
);
4596 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4598 opt_var
.name
= cpystr(_("Features"));
4599 opt_var
.is_used
= 1;
4600 opt_var
.is_user
= 1;
4601 opt_var
.is_list
= 1;
4602 clrbitmap(feat_option_list
);
4603 if(def
&& def
->patgrp
&& def
->patgrp
->age_uses_sentdate
)
4604 setbitn(FEAT_SENTDATE
, feat_option_list
);
4607 if(def
&& def
->action
&& def
->action
->move_only_if_not_deleted
)
4608 setbitn(FEAT_IFNOTDEL
, feat_option_list
);
4609 if(def
&& def
->action
&& def
->action
->non_terminating
)
4610 setbitn(FEAT_NONTERM
, feat_option_list
);
4614 new_confline(&ctmp
);
4615 ctmp
->var
= &opt_var
;
4616 ctmp
->valoffset
= 23;
4617 ctmp
->keymenu
= &config_checkbox_keymenu
;
4618 ctmp
->help
= NO_HELP
;
4620 snprintf(tmp
, sizeof(tmp
), "%-20s =", opt_var
.name
);
4621 tmp
[sizeof(tmp
)-1] = '\0';
4622 ctmp
->varname
= cpystr(tmp
);
4623 ctmp
->varnamep
= ctmpb
= ctmp
;
4624 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4626 new_confline(&ctmp
);
4628 ctmp
->valoffset
= rindent
;
4629 ctmp
->keymenu
= &config_checkbox_keymenu
;
4630 ctmp
->help
= NO_HELP
;
4631 ctmp
->tool
= feat_checkbox_tool
;
4632 ctmp
->varnamep
= ctmpb
;
4633 ctmp
->flags
|= CF_NOSELECT
;
4634 ctmp
->value
= cpystr("Set Feature Name");
4636 new_confline(&ctmp
);
4638 ctmp
->valoffset
= rindent
;
4639 ctmp
->keymenu
= &config_checkbox_keymenu
;
4640 ctmp
->help
= NO_HELP
;
4641 ctmp
->tool
= feat_checkbox_tool
;
4642 ctmp
->varnamep
= ctmpb
;
4643 ctmp
->flags
|= CF_NOSELECT
;
4644 ctmp
->value
= cpystr(set_choose
); \
4646 /* find longest value's name */
4647 for(lv
= 0, i
= 0; (f
= feat_feature_list(i
)); i
++){
4648 if(!edit_filter
&& (i
== FEAT_IFNOTDEL
|| i
== FEAT_NONTERM
))
4651 if(lv
< (j
= utf8_width(f
->name
)))
4657 for(i
= 0; (f
= feat_feature_list(i
)); i
++){
4658 if(!edit_filter
&& (i
== FEAT_IFNOTDEL
|| i
== FEAT_NONTERM
))
4661 new_confline(&ctmp
);
4662 ctmp
->var
= &opt_var
;
4663 ctmp
->help_title
= _("HELP FOR FILTER FEATURES");
4664 ctmp
->varnamep
= ctmpb
;
4665 ctmp
->keymenu
= &config_checkbox_keymenu
;
4668 ctmp
->help
= h_config_filt_opts_sentdate
;
4671 ctmp
->help
= h_config_filt_opts_notdel
;
4674 ctmp
->help
= h_config_filt_opts_nonterm
;
4678 ctmp
->tool
= feat_checkbox_tool
;
4679 ctmp
->valoffset
= rindent
;
4681 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w",
4682 bitnset(f
->value
, feat_option_list
) ? 'X' : ' ',
4684 tmp
[sizeof(tmp
)-1] = '\0';
4685 ctmp
->value
= cpystr(tmp
);
4693 new_confline(&ctmp
);
4694 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4696 new_confline(&ctmp
);
4697 ctmp
->flags
|= CF_NOSELECT
;
4698 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(ustr
)) + 4){
4701 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
4702 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
4703 ustr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
4704 ctmp
->value
= cpystr(tmp_20k_buf
);
4707 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
4710 new_confline(&ctmp
);
4711 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4714 new_confline(&ctmp
);
4715 ctmp
->var
= &repl_type_var
;
4716 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4717 ctmp
->help
= NO_HELP
;
4719 snprintf(tmp
, sizeof(tmp
), "%s =", repl_type_var
.name
);
4720 tmp
[sizeof(tmp
)-1] = '\0';
4721 ctmp
->varname
= cpystr(tmp
);
4722 ctmp
->varnamep
= ctmpb
= ctmp
;
4723 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4725 new_confline(&ctmp
);
4727 ctmp
->valoffset
= rindent
;
4728 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4729 ctmp
->help
= NO_HELP
;
4731 ctmp
->varnamep
= ctmpb
;
4732 ctmp
->flags
|= CF_NOSELECT
;
4733 ctmp
->value
= cpystr("Set Choose One");
4735 new_confline(&ctmp
);
4737 ctmp
->valoffset
= rindent
;
4738 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4739 ctmp
->help
= NO_HELP
;
4740 ctmp
->tool
= radio_tool
;
4741 ctmp
->varnamep
= ctmpb
;
4742 ctmp
->flags
|= CF_NOSELECT
;
4743 ctmp
->value
= cpystr(set_choose
); \
4745 /* find longest value's name */
4746 for(lv
= 0, i
= 0; (f
= role_repl_types(i
)); i
++)
4747 if(lv
< (j
= utf8_width(f
->name
)))
4752 for(i
= 0; (f
= role_repl_types(i
)); i
++){
4753 new_confline(&ctmp
);
4754 ctmp
->help_title
= _("HELP FOR ROLE REPLY USE");
4755 ctmp
->var
= &repl_type_var
;
4756 ctmp
->valoffset
= rindent
;
4757 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4758 ctmp
->help
= h_config_role_replyuse
;
4760 ctmp
->tool
= radio_tool
;
4761 ctmp
->varnamep
= ctmpb
;
4762 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (((!(def
&& def
->action
) ||
4763 def
->action
->repl_type
== -1) &&
4764 f
->value
== ROLE_REPL_DEFL
) ||
4765 (def
&& def
->action
&&
4766 f
->value
== def
->action
->repl_type
))
4769 tmp
[sizeof(tmp
)-1] = '\0';
4770 ctmp
->value
= cpystr(tmp
);
4774 new_confline(&ctmp
);
4775 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4778 new_confline(&ctmp
);
4779 ctmp
->var
= &forw_type_var
;
4780 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4781 ctmp
->help
= NO_HELP
;
4783 snprintf(tmp
, sizeof(tmp
), "%s =", forw_type_var
.name
);
4784 tmp
[sizeof(tmp
)-1] = '\0';
4785 ctmp
->varname
= cpystr(tmp
);
4786 ctmp
->varnamep
= ctmpb
= ctmp
;
4787 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4789 new_confline(&ctmp
);
4791 ctmp
->valoffset
= rindent
;
4792 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4793 ctmp
->help
= NO_HELP
;
4795 ctmp
->varnamep
= ctmpb
;
4796 ctmp
->flags
|= CF_NOSELECT
;
4797 ctmp
->value
= cpystr("Set Choose One");
4799 new_confline(&ctmp
);
4801 ctmp
->valoffset
= rindent
;
4802 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4803 ctmp
->help
= NO_HELP
;
4804 ctmp
->tool
= radio_tool
;
4805 ctmp
->varnamep
= ctmpb
;
4806 ctmp
->flags
|= CF_NOSELECT
;
4807 ctmp
->value
= cpystr(set_choose
); \
4809 /* find longest value's name */
4810 for(lv
= 0, i
= 0; (f
= role_forw_types(i
)); i
++)
4811 if(lv
< (j
= utf8_width(f
->name
)))
4816 for(i
= 0; (f
= role_forw_types(i
)); i
++){
4817 new_confline(&ctmp
);
4818 ctmp
->help_title
= _("HELP FOR ROLE FORWARD USE");
4819 ctmp
->var
= &forw_type_var
;
4820 ctmp
->valoffset
= rindent
;
4821 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4822 ctmp
->help
= h_config_role_forwarduse
;
4824 ctmp
->tool
= radio_tool
;
4825 ctmp
->varnamep
= ctmpb
;
4826 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (((!(def
&& def
->action
) ||
4827 def
->action
->forw_type
== -1) &&
4828 f
->value
== ROLE_FORW_DEFL
) ||
4829 (def
&& def
->action
&&
4830 f
->value
== def
->action
->forw_type
))
4833 tmp
[sizeof(tmp
)-1] = '\0';
4834 ctmp
->value
= cpystr(tmp
);
4838 new_confline(&ctmp
);
4839 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4842 new_confline(&ctmp
);
4843 ctmp
->var
= &comp_type_var
;
4844 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4845 ctmp
->help
= NO_HELP
;
4847 snprintf(tmp
, sizeof(tmp
), "%s =", comp_type_var
.name
);
4848 tmp
[sizeof(tmp
)-1] = '\0';
4849 ctmp
->varname
= cpystr(tmp
);
4850 ctmp
->varnamep
= ctmpb
= ctmp
;
4851 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4853 new_confline(&ctmp
);
4855 ctmp
->valoffset
= rindent
;
4856 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4857 ctmp
->help
= NO_HELP
;
4859 ctmp
->varnamep
= ctmpb
;
4860 ctmp
->flags
|= CF_NOSELECT
;
4861 ctmp
->value
= cpystr("Set Choose One");
4863 new_confline(&ctmp
);
4865 ctmp
->valoffset
= rindent
;
4866 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4867 ctmp
->help
= NO_HELP
;
4868 ctmp
->tool
= radio_tool
;
4869 ctmp
->varnamep
= ctmpb
;
4870 ctmp
->flags
|= CF_NOSELECT
;
4871 ctmp
->value
= cpystr(set_choose
); \
4873 /* find longest value's name */
4874 for(lv
= 0, i
= 0; (f
= role_comp_types(i
)); i
++)
4875 if(lv
< (j
= utf8_width(f
->name
)))
4880 for(i
= 0; (f
= role_comp_types(i
)); i
++){
4881 new_confline(&ctmp
);
4882 ctmp
->help_title
= _("HELP FOR ROLE COMPOSE USE");
4883 ctmp
->var
= &comp_type_var
;
4884 ctmp
->valoffset
= rindent
;
4885 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4886 ctmp
->help
= h_config_role_composeuse
;
4888 ctmp
->tool
= radio_tool
;
4889 ctmp
->varnamep
= ctmpb
;
4890 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (((!(def
&& def
->action
) ||
4891 def
->action
->comp_type
== -1) &&
4892 f
->value
== ROLE_COMP_DEFL
) ||
4893 (def
&& def
->action
&&
4894 f
->value
== def
->action
->comp_type
))
4897 tmp
[sizeof(tmp
)-1] = '\0';
4898 ctmp
->value
= cpystr(tmp
);
4902 memset(&screen
, 0, sizeof(screen
));
4903 screen
.ro_warning
= saved_screen
? saved_screen
->deferred_ro_warning
: 0;
4904 /* TRANSLATORS: Print something1 using something2.
4905 "roles" is something1 */
4906 rv
= conf_scroll_screen(ps
, &screen
, first_line
, title
, _("roles"),
4907 (edit_incol
&& pico_usingcolor()) ? 1 : 0, NULL
);
4910 * Now look at the fake variables and extract the information we
4914 if(rv
== 1 && result
){
4916 * We know these variables exist, so we don't have to check that
4917 * apval is nonnull before evaluating *apval.
4919 apval
= APVAL(&nick_var
, ew
);
4922 removing_leading_and_trailing_white_space(nick
);
4924 apval
= APVAL(&comment_var
, ew
);
4927 removing_leading_and_trailing_white_space(comment
);
4929 alval
= ALVAL(&to_pat_var
, ew
);
4933 alval
= ALVAL(&from_pat_var
, ew
);
4937 alval
= ALVAL(&sender_pat_var
, ew
);
4938 sender_pat
= *alval
;
4941 alval
= ALVAL(&cc_pat_var
, ew
);
4945 alval
= ALVAL(&recip_pat_var
, ew
);
4949 alval
= ALVAL(&partic_pat_var
, ew
);
4950 partic_pat
= *alval
;
4953 alval
= ALVAL(&news_pat_var
, ew
);
4957 alval
= ALVAL(&subj_pat_var
, ew
);
4961 alval
= ALVAL(&alltext_pat_var
, ew
);
4962 alltext_pat
= *alval
;
4965 alval
= ALVAL(&bodytext_pat_var
, ew
);
4966 bodytext_pat
= *alval
;
4969 alval
= ALVAL(&keyword_pat_var
, ew
);
4970 keyword_pat
= *alval
;
4973 alval
= ALVAL(&charset_pat_var
, ew
);
4974 charset_pat
= *alval
;
4977 apval
= APVAL(&age_pat_var
, ew
);
4980 removing_leading_and_trailing_white_space(age_pat
);
4982 apval
= APVAL(&size_pat_var
, ew
);
4985 removing_leading_and_trailing_white_space(size_pat
);
4987 apval
= APVAL(&scorei_pat_var
, ew
);
4988 scorei_pat
= *apval
;
4990 removing_leading_and_trailing_white_space(scorei_pat
);
4992 apval
= APVAL(&stat_del_var
, ew
);
4995 removing_leading_and_trailing_white_space(stat_del
);
4997 apval
= APVAL(&stat_new_var
, ew
);
5000 removing_leading_and_trailing_white_space(stat_new
);
5002 apval
= APVAL(&stat_rec_var
, ew
);
5005 removing_leading_and_trailing_white_space(stat_rec
);
5007 apval
= APVAL(&stat_imp_var
, ew
);
5010 removing_leading_and_trailing_white_space(stat_imp
);
5012 apval
= APVAL(&stat_ans_var
, ew
);
5015 removing_leading_and_trailing_white_space(stat_ans
);
5017 apval
= APVAL(&stat_8bit_var
, ew
);
5020 removing_leading_and_trailing_white_space(stat_8bit
);
5022 apval
= APVAL(&stat_bom_var
, ew
);
5025 removing_leading_and_trailing_white_space(stat_bom
);
5027 apval
= APVAL(&stat_boy_var
, ew
);
5030 removing_leading_and_trailing_white_space(stat_boy
);
5032 apval
= APVAL(&fldr_type_var
, ew
);
5033 fldr_type_pat
= *apval
;
5035 removing_leading_and_trailing_white_space(fldr_type_pat
);
5037 alval
= ALVAL(&folder_pat_var
, ew
);
5038 folder_pat
= *alval
;
5041 apval
= APVAL(&abook_type_var
, ew
);
5042 abook_type_pat
= *apval
;
5044 removing_leading_and_trailing_white_space(abook_type_pat
);
5046 alval
= ALVAL(&abook_pat_var
, ew
);
5050 apval
= APVAL(&cati_var
, ew
);
5053 removing_leading_and_trailing_white_space(cati
);
5055 apval
= APVAL(&cat_lim_var
, ew
);
5058 removing_leading_and_trailing_white_space(cat_lim
);
5060 apval
= APVAL(&inick_var
, ew
);
5063 removing_leading_and_trailing_white_space(inick
);
5065 apval
= APVAL(&from_act_var
, ew
);
5068 removing_leading_and_trailing_white_space(from_act
);
5070 apval
= APVAL(&replyto_act_var
, ew
);
5071 replyto_act
= *apval
;
5073 removing_leading_and_trailing_white_space(replyto_act
);
5075 apval
= APVAL(&fcc_act_var
, ew
);
5078 removing_leading_and_trailing_white_space(fcc_act
);
5080 apval
= APVAL(&litsig_act_var
, ew
);
5081 litsig_act
= *apval
;
5083 removing_leading_and_trailing_white_space(litsig_act
);
5085 apval
= APVAL(&sort_act_var
, ew
);
5088 removing_leading_and_trailing_white_space(sort_act
);
5090 apval
= APVAL(&iform_act_var
, ew
);
5093 removing_leading_and_trailing_white_space(iform_act
);
5095 apval
= APVAL(&startup_var
, ew
);
5096 startup_act
= *apval
;
5098 removing_leading_and_trailing_white_space(startup_act
);
5100 apval
= APVAL(&sig_act_var
, ew
);
5103 removing_leading_and_trailing_white_space(sig_act
);
5105 apval
= APVAL(&templ_act_var
, ew
);
5108 removing_leading_and_trailing_white_space(templ_act
);
5110 apval
= APVAL(&score_act_var
, ew
);
5113 removing_leading_and_trailing_white_space(score_act
);
5115 apval
= APVAL(&hdrtok_act_var
, ew
);
5116 hdrtok_act
= *apval
;
5118 removing_leading_and_trailing_white_space(hdrtok_act
);
5120 apval
= APVAL(&repl_type_var
, ew
);
5123 removing_leading_and_trailing_white_space(repl_type
);
5125 apval
= APVAL(&forw_type_var
, ew
);
5128 removing_leading_and_trailing_white_space(forw_type
);
5130 apval
= APVAL(&comp_type_var
, ew
);
5133 removing_leading_and_trailing_white_space(comp_type
);
5135 apval
= APVAL(&rolecolor_vars
[0], ew
);
5138 removing_leading_and_trailing_white_space(rc_fg
);
5140 apval
= APVAL(&rolecolor_vars
[1], ew
);
5143 removing_leading_and_trailing_white_space(rc_bg
);
5145 apval
= APVAL(&filter_type_var
, ew
);
5146 filter_type
= *apval
;
5148 removing_leading_and_trailing_white_space(filter_type
);
5150 alval
= ALVAL(&folder_act_var
, ew
);
5151 folder_act
= *alval
;
5154 alval
= ALVAL(&keyword_set_var
, ew
);
5155 keyword_set
= *alval
;
5158 alval
= ALVAL(&keyword_clr_var
, ew
);
5159 keyword_clr
= *alval
;
5162 apval
= APVAL(&filt_imp_var
, ew
);
5165 removing_leading_and_trailing_white_space(filt_imp
);
5167 apval
= APVAL(&filt_del_var
, ew
);
5170 removing_leading_and_trailing_white_space(filt_del
);
5172 apval
= APVAL(&filt_new_var
, ew
);
5175 removing_leading_and_trailing_white_space(filt_new
);
5177 apval
= APVAL(&filt_ans_var
, ew
);
5180 removing_leading_and_trailing_white_space(filt_ans
);
5183 alval
= ALVAL(&cat_cmd_var
, ew
);
5187 alval
= ALVAL(&cstm_act_var
, ew
);
5191 alval
= ALVAL(&smtp_act_var
, ew
);
5195 alval
= ALVAL(&nntp_act_var
, ew
);
5199 if(ps
->VAR_OPER_DIR
&& sig_act
&&
5200 is_absolute_path(sig_act
) &&
5201 !in_dir(ps
->VAR_OPER_DIR
, sig_act
)){
5202 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5203 _("Warning: Sig file can't be outside of %s"),
5207 if(ps
->VAR_OPER_DIR
&& templ_act
&&
5208 is_absolute_path(templ_act
) &&
5209 !in_dir(ps
->VAR_OPER_DIR
, templ_act
)){
5210 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5211 _("Warning: Template file can't be outside of %s"),
5215 if(ps
->VAR_OPER_DIR
&& folder_act
)
5216 for(i
= 0; folder_act
[i
]; i
++){
5217 if(folder_act
[i
][0] && is_absolute_path(folder_act
[i
]) &&
5218 !in_dir(ps
->VAR_OPER_DIR
, folder_act
[i
])){
5219 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5220 _("Warning: Folder can't be outside of %s"),
5225 *result
= (PAT_S
*)fs_get(sizeof(**result
));
5226 memset((void *)(*result
), 0, sizeof(**result
));
5228 (*result
)->patgrp
= (PATGRP_S
*)fs_get(sizeof(*(*result
)->patgrp
));
5229 memset((void *)(*result
)->patgrp
, 0, sizeof(*(*result
)->patgrp
));
5231 (*result
)->action
= (ACTION_S
*)fs_get(sizeof(*(*result
)->action
));
5232 memset((void *)(*result
)->action
, 0, sizeof(*(*result
)->action
));
5234 (*result
)->patline
= def
? def
->patline
: NULL
;
5237 (*result
)->patgrp
->nick
= nick
;
5241 (*result
)->patgrp
->nick
= cpystr(nick_var
.global_val
.p
);
5243 if(comment
&& *comment
){
5244 (*result
)->patgrp
->comment
= comment
;
5248 (*result
)->action
->nick
= cpystr((*result
)->patgrp
->nick
);
5250 (*result
)->action
->is_a_role
= edit_role
? 1 : 0;
5251 (*result
)->action
->is_a_incol
= edit_incol
? 1 : 0;
5252 (*result
)->action
->is_a_score
= edit_score
? 1 : 0;
5253 (*result
)->action
->is_a_filter
= edit_filter
? 1 : 0;
5254 (*result
)->action
->is_a_other
= edit_other
? 1 : 0;
5255 (*result
)->action
->is_a_srch
= edit_srch
? 1 : 0;
5257 (*result
)->patgrp
->to
= editlist_to_pattern(to_pat
);
5258 if((*result
)->patgrp
->to
&& !strncmp(to_pat_var
.name
, NOT
, NOTLEN
))
5259 (*result
)->patgrp
->to
->not = 1;
5261 (*result
)->patgrp
->from
= editlist_to_pattern(from_pat
);
5262 if((*result
)->patgrp
->from
&& !strncmp(from_pat_var
.name
, NOT
, NOTLEN
))
5263 (*result
)->patgrp
->from
->not = 1;
5265 (*result
)->patgrp
->sender
= editlist_to_pattern(sender_pat
);
5266 if((*result
)->patgrp
->sender
&&
5267 !strncmp(sender_pat_var
.name
, NOT
, NOTLEN
))
5268 (*result
)->patgrp
->sender
->not = 1;
5270 (*result
)->patgrp
->cc
= editlist_to_pattern(cc_pat
);
5271 if((*result
)->patgrp
->cc
&& !strncmp(cc_pat_var
.name
, NOT
, NOTLEN
))
5272 (*result
)->patgrp
->cc
->not = 1;
5274 (*result
)->patgrp
->recip
= editlist_to_pattern(recip_pat
);
5275 if((*result
)->patgrp
->recip
&&
5276 !strncmp(recip_pat_var
.name
, NOT
, NOTLEN
))
5277 (*result
)->patgrp
->recip
->not = 1;
5279 (*result
)->patgrp
->partic
= editlist_to_pattern(partic_pat
);
5280 if((*result
)->patgrp
->partic
&&
5281 !strncmp(partic_pat_var
.name
, NOT
, NOTLEN
))
5282 (*result
)->patgrp
->partic
->not = 1;
5284 (*result
)->patgrp
->news
= editlist_to_pattern(news_pat
);
5285 if((*result
)->patgrp
->news
&& !strncmp(news_pat_var
.name
, NOT
, NOTLEN
))
5286 (*result
)->patgrp
->news
->not = 1;
5288 (*result
)->patgrp
->subj
= editlist_to_pattern(subj_pat
);
5289 if((*result
)->patgrp
->subj
&& !strncmp(subj_pat_var
.name
, NOT
, NOTLEN
))
5290 (*result
)->patgrp
->subj
->not = 1;
5292 (*result
)->patgrp
->alltext
= editlist_to_pattern(alltext_pat
);
5293 if((*result
)->patgrp
->alltext
&&
5294 !strncmp(alltext_pat_var
.name
, NOT
, NOTLEN
))
5295 (*result
)->patgrp
->alltext
->not = 1;
5297 (*result
)->patgrp
->bodytext
= editlist_to_pattern(bodytext_pat
);
5298 if((*result
)->patgrp
->bodytext
&&
5299 !strncmp(bodytext_pat_var
.name
, NOT
, NOTLEN
))
5300 (*result
)->patgrp
->bodytext
->not = 1;
5302 (*result
)->patgrp
->keyword
= editlist_to_pattern(keyword_pat
);
5303 if((*result
)->patgrp
->keyword
&&
5304 !strncmp(keyword_pat_var
.name
, NOT
, NOTLEN
))
5305 (*result
)->patgrp
->keyword
->not = 1;
5307 (*result
)->patgrp
->charsets
= editlist_to_pattern(charset_pat
);
5308 if((*result
)->patgrp
->charsets
&&
5309 !strncmp(charset_pat_var
.name
, NOT
, NOTLEN
))
5310 (*result
)->patgrp
->charsets
->not = 1;
5312 (*result
)->patgrp
->age_uses_sentdate
=
5313 bitnset(FEAT_SENTDATE
, feat_option_list
) ? 1 : 0;
5316 if(((*result
)->patgrp
->age
= parse_intvl(age_pat
)) != NULL
)
5317 (*result
)->patgrp
->do_age
= 1;
5321 if(((*result
)->patgrp
->size
= parse_intvl(size_pat
)) != NULL
)
5322 (*result
)->patgrp
->do_size
= 1;
5326 if(((*result
)->patgrp
->score
= parse_intvl(scorei_pat
)) != NULL
)
5327 (*result
)->patgrp
->do_score
= 1;
5330 (*result
)->patgrp
->cat_lim
= -1L; /* default */
5333 fs_give((void **) &cat_cmd
);
5335 /* quick check for absolute paths */
5337 for(j
= 0; cat_cmd
[j
]; j
++)
5338 if(!is_absolute_path(cat_cmd
[j
]))
5339 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5340 _("Warning: command must be absolute path: \"%s\""),
5343 (*result
)->patgrp
->category_cmd
= cat_cmd
;
5347 if(((*result
)->patgrp
->cat
= parse_intvl(cati
)) != NULL
)
5348 (*result
)->patgrp
->do_cat
= 1;
5350 if(cat_lim
&& *cat_lim
)
5351 (*result
)->patgrp
->cat_lim
= atol(cat_lim
);
5354 if(stat_del
&& *stat_del
){
5355 for(j
= 0; (f
= role_status_types(j
)); j
++)
5356 if(!strucmp(stat_del
, f
->name
)){
5357 (*result
)->patgrp
->stat_del
= f
->value
;
5362 (*result
)->patgrp
->stat_del
= PAT_STAT_EITHER
;
5364 if(stat_new
&& *stat_new
){
5365 for(j
= 0; (f
= role_status_types(j
)); j
++)
5366 if(!strucmp(stat_new
, f
->name
)){
5367 (*result
)->patgrp
->stat_new
= f
->value
;
5372 (*result
)->patgrp
->stat_new
= PAT_STAT_EITHER
;
5374 if(stat_rec
&& *stat_rec
){
5375 for(j
= 0; (f
= role_status_types(j
)); j
++)
5376 if(!strucmp(stat_rec
, f
->name
)){
5377 (*result
)->patgrp
->stat_rec
= f
->value
;
5382 (*result
)->patgrp
->stat_rec
= PAT_STAT_EITHER
;
5384 if(stat_imp
&& *stat_imp
){
5385 for(j
= 0; (f
= role_status_types(j
)); j
++)
5386 if(!strucmp(stat_imp
, f
->name
)){
5387 (*result
)->patgrp
->stat_imp
= f
->value
;
5392 (*result
)->patgrp
->stat_imp
= PAT_STAT_EITHER
;
5394 if(stat_ans
&& *stat_ans
){
5395 for(j
= 0; (f
= role_status_types(j
)); j
++)
5396 if(!strucmp(stat_ans
, f
->name
)){
5397 (*result
)->patgrp
->stat_ans
= f
->value
;
5402 (*result
)->patgrp
->stat_ans
= PAT_STAT_EITHER
;
5404 if(stat_8bit
&& *stat_8bit
){
5405 for(j
= 0; (f
= role_status_types(j
)); j
++)
5406 if(!strucmp(stat_8bit
, f
->name
)){
5407 (*result
)->patgrp
->stat_8bitsubj
= f
->value
;
5412 (*result
)->patgrp
->stat_8bitsubj
= PAT_STAT_EITHER
;
5414 if(stat_bom
&& *stat_bom
){
5415 for(j
= 0; (f
= role_status_types(j
)); j
++)
5416 if(!strucmp(stat_bom
, f
->name
)){
5417 (*result
)->patgrp
->stat_bom
= f
->value
;
5422 (*result
)->patgrp
->stat_bom
= PAT_STAT_EITHER
;
5424 if(stat_boy
&& *stat_boy
){
5425 for(j
= 0; (f
= role_status_types(j
)); j
++)
5426 if(!strucmp(stat_boy
, f
->name
)){
5427 (*result
)->patgrp
->stat_boy
= f
->value
;
5432 (*result
)->patgrp
->stat_boy
= PAT_STAT_EITHER
;
5435 decode_sort(sort_act
, &def_sort
, &def_sort_rev
);
5436 (*result
)->action
->sort_is_set
= 1;
5437 (*result
)->action
->sortorder
= def_sort
;
5438 (*result
)->action
->revsort
= (def_sort_rev
? 1 : 0);
5440 * Don't try to re-sort until next open of folder. If user
5441 * $-sorted then it probably shouldn't change anyway. Why
5442 * bother keeping track of that?
5446 (*result
)->action
->index_format
= iform_act
;
5449 if(startup_act
&& *startup_act
){
5450 for(j
= 0; (f
= startup_rules(j
)); j
++)
5451 if(!strucmp(startup_act
, f
->name
)){
5452 (*result
)->action
->startup_rule
= f
->value
;
5457 (*result
)->action
->startup_rule
= IS_NOTSET
;
5460 for(ea
= earb
; ea
; ea
= ea
->next
){
5464 aa
->next
= (ARBHDR_S
*)fs_get(sizeof(*aa
));
5468 (*result
)->patgrp
->arbhdr
=
5469 (ARBHDR_S
*)fs_get(sizeof(ARBHDR_S
));
5470 aa
= (*result
)->patgrp
->arbhdr
;
5473 memset(aa
, 0, sizeof(*aa
));
5475 aa
->field
= cpystr((ea
->a
&& ea
->a
->field
) ? ea
->a
->field
: "");
5477 alval
= ALVAL(ea
->v
, ew
);
5480 aa
->p
= editlist_to_pattern(spat
);
5481 if(aa
->p
&& ea
->v
&& ea
->v
->name
&&
5482 !strncmp(ea
->v
->name
, NOT
, NOTLEN
))
5485 if((xyz
= pattern_to_string(aa
->p
)) != NULL
){
5489 fs_give((void **)&xyz
);
5493 if(fldr_type_pat
&& *fldr_type_pat
){
5494 for(j
= 0; (f
= pat_fldr_types(j
)); j
++)
5495 if(!strucmp(fldr_type_pat
, f
->name
)){
5496 (*result
)->patgrp
->fldr_type
= f
->value
;
5501 f
= pat_fldr_types(FLDR_DEFL
);
5503 (*result
)->patgrp
->fldr_type
= f
->value
;
5506 (*result
)->patgrp
->folder
= editlist_to_pattern(folder_pat
);
5508 if(abook_type_pat
&& *abook_type_pat
){
5509 for(j
= 0; (f
= inabook_fldr_types(j
)); j
++){
5510 if(!strucmp(abook_type_pat
, f
->name
)){
5511 (*result
)->patgrp
->inabook
= f
->value
;
5516 if(bitnset(INABOOK_FROM
, inabook_type_list
))
5517 (*result
)->patgrp
->inabook
|= IAB_FROM
;
5518 if(bitnset(INABOOK_REPLYTO
, inabook_type_list
))
5519 (*result
)->patgrp
->inabook
|= IAB_REPLYTO
;
5520 if(bitnset(INABOOK_SENDER
, inabook_type_list
))
5521 (*result
)->patgrp
->inabook
|= IAB_SENDER
;
5522 if(bitnset(INABOOK_TO
, inabook_type_list
))
5523 (*result
)->patgrp
->inabook
|= IAB_TO
;
5524 if(bitnset(INABOOK_CC
, inabook_type_list
))
5525 (*result
)->patgrp
->inabook
|= IAB_CC
;
5527 if(!((*result
)->patgrp
->inabook
& IAB_TYPE_MASK
))
5528 (*result
)->patgrp
->inabook
|= (IAB_FROM
| IAB_REPLYTO
);
5531 f
= inabook_fldr_types(IAB_DEFL
);
5533 (*result
)->patgrp
->inabook
= f
->value
;
5536 (*result
)->patgrp
->abooks
= editlist_to_pattern(abook_pat
);
5539 (*result
)->action
->inherit_nick
= inick
;
5541 (*result
)->action
->fcc
= fcc_act
;
5543 (*result
)->action
->litsig
= litsig_act
;
5545 (*result
)->action
->sig
= sig_act
;
5547 (*result
)->action
->template = templ_act
;
5552 * Check for From or Reply-To and eliminate them.
5554 for(i
= 0; cstm_act
[i
]; i
++){
5557 if((!struncmp(cstm_act
[i
],"from",4) &&
5558 (cstm_act
[i
][4] == ':' ||
5559 cstm_act
[i
][4] == '\0')) ||
5560 (!struncmp(cstm_act
[i
],"reply-to",8) &&
5561 (cstm_act
[i
][8] == ':' ||
5562 cstm_act
[i
][8] == '\0'))){
5563 free_this
= cstm_act
[i
];
5564 /* slide the rest up */
5565 for(j
= i
; cstm_act
[j
]; j
++)
5566 cstm_act
[j
] = cstm_act
[j
+1];
5568 fs_give((void **)&free_this
);
5569 i
--; /* recheck now that we've slid them up */
5575 fs_give((void **)&cstm_act
);
5577 (*result
)->action
->cstm
= cstm_act
;
5583 fs_give((void **)&smtp_act
);
5585 (*result
)->action
->smtp
= smtp_act
;
5591 fs_give((void **)&nntp_act
);
5593 (*result
)->action
->nntp
= nntp_act
;
5597 if(filter_type
&& *filter_type
){
5598 (*result
)->action
->non_terminating
=
5599 bitnset(FEAT_NONTERM
, feat_option_list
) ? 1 : 0;
5600 for(i
= 0; (f
= filter_types(i
)); i
++){
5601 if(!strucmp(filter_type
, f
->name
)){
5602 if(f
->value
== FILTER_FOLDER
){
5603 (*result
)->action
->folder
= editlist_to_pattern(folder_act
);
5604 (*result
)->action
->move_only_if_not_deleted
=
5605 bitnset(FEAT_IFNOTDEL
, feat_option_list
) ? 1 : 0;
5607 else if(f
->value
== FILTER_STATE
){
5608 (*result
)->action
->kill
= 0;
5610 else if(f
->value
== FILTER_KILL
){
5611 (*result
)->action
->kill
= 1;
5615 * This is indented an extra indent because we used to condition
5616 * this on !kill. We changed it so that you can set state bits
5617 * even if you're killing. This is marginally helpful if you
5618 * have another client running that doesn't know about this
5619 * filter, but you want to, for example, have the messages show
5620 * up now as deleted instead of having that deferred until we
5621 * exit. It is controlled by the user by setting the status
5622 * action bits along with the Delete.
5624 if(filt_imp
&& *filt_imp
){
5625 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5626 if(!strucmp(filt_imp
, f
->name
)){
5628 case ACT_STAT_LEAVE
:
5631 (*result
)->action
->state_setting_bits
|= F_FLAG
;
5633 case ACT_STAT_CLEAR
:
5634 (*result
)->action
->state_setting_bits
|= F_UNFLAG
;
5642 if(filt_del
&& *filt_del
){
5643 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5644 if(!strucmp(filt_del
, f
->name
)){
5646 case ACT_STAT_LEAVE
:
5649 (*result
)->action
->state_setting_bits
|= F_DEL
;
5651 case ACT_STAT_CLEAR
:
5652 (*result
)->action
->state_setting_bits
|= F_UNDEL
;
5660 if(filt_ans
&& *filt_ans
){
5661 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5662 if(!strucmp(filt_ans
, f
->name
)){
5664 case ACT_STAT_LEAVE
:
5667 (*result
)->action
->state_setting_bits
|= F_ANS
;
5669 case ACT_STAT_CLEAR
:
5670 (*result
)->action
->state_setting_bits
|= F_UNANS
;
5678 if(filt_new
&& *filt_new
){
5679 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5680 if(!strucmp(filt_new
, f
->name
)){
5682 case ACT_STAT_LEAVE
:
5685 (*result
)->action
->state_setting_bits
|= F_UNSEEN
;
5687 case ACT_STAT_CLEAR
:
5688 (*result
)->action
->state_setting_bits
|= F_SEEN
;
5696 (*result
)->action
->keyword_set
=
5697 editlist_to_pattern(keyword_set
);
5698 (*result
)->action
->keyword_clr
=
5699 editlist_to_pattern(keyword_clr
);
5706 if(from_act
&& *from_act
)
5707 rfc822_parse_adrlist(&(*result
)->action
->from
, from_act
,
5710 if(replyto_act
&& *replyto_act
)
5711 rfc822_parse_adrlist(&(*result
)->action
->replyto
, replyto_act
,
5714 if(score_act
&& (j
= atoi(score_act
)) >= SCORE_MIN
&& j
<= SCORE_MAX
)
5715 (*result
)->action
->scoreval
= (long) j
;
5718 (*result
)->action
->scorevalhdrtok
= stringform_to_hdrtok(hdrtok_act
);
5720 if(repl_type
&& *repl_type
){
5721 for(j
= 0; (f
= role_repl_types(j
)); j
++)
5722 if(!strucmp(repl_type
, f
->name
)){
5723 (*result
)->action
->repl_type
= f
->value
;
5728 f
= role_repl_types(ROLE_REPL_DEFL
);
5730 (*result
)->action
->repl_type
= f
->value
;
5733 if(forw_type
&& *forw_type
){
5734 for(j
= 0; (f
= role_forw_types(j
)); j
++)
5735 if(!strucmp(forw_type
, f
->name
)){
5736 (*result
)->action
->forw_type
= f
->value
;
5741 f
= role_forw_types(ROLE_FORW_DEFL
);
5743 (*result
)->action
->forw_type
= f
->value
;
5746 if(comp_type
&& *comp_type
){
5747 for(j
= 0; (f
= role_comp_types(j
)); j
++)
5748 if(!strucmp(comp_type
, f
->name
)){
5749 (*result
)->action
->comp_type
= f
->value
;
5754 f
= role_comp_types(ROLE_COMP_DEFL
);
5756 (*result
)->action
->comp_type
= f
->value
;
5759 if(rc_fg
&& *rc_fg
&& rc_bg
&& *rc_bg
){
5760 if(!old_fg
|| !old_bg
|| strucmp(old_fg
, rc_fg
) ||
5761 strucmp(old_bg
, rc_bg
))
5762 clear_index_cache(ps_global
->mail_stream
, 0);
5765 * If same as normal color, don't set it. This may or may
5766 * not surprise the user when they change the normal color.
5767 * This color will track the normal color instead of staying
5768 * the same as the old normal color, which is probably
5771 if(!ps_global
->VAR_NORM_FORE_COLOR
||
5772 !ps_global
->VAR_NORM_BACK_COLOR
||
5773 strucmp(ps_global
->VAR_NORM_FORE_COLOR
, rc_fg
) ||
5774 strucmp(ps_global
->VAR_NORM_BACK_COLOR
, rc_bg
))
5775 (*result
)->action
->incol
= new_color_pair(rc_fg
, rc_bg
);
5779 for(j
= 0; varlist
[j
]; j
++){
5781 free_variable_values(v
);
5783 fs_give((void **)&v
->name
);
5789 fs_give((void **)&nick
);
5791 fs_give((void **)&comment
);
5793 free_list_array(&to_pat
);
5795 free_list_array(&from_pat
);
5797 free_list_array(&sender_pat
);
5799 free_list_array(&cc_pat
);
5801 free_list_array(&recip_pat
);
5803 free_list_array(&partic_pat
);
5805 free_list_array(&news_pat
);
5807 free_list_array(&subj_pat
);
5809 free_list_array(&alltext_pat
);
5811 free_list_array(&bodytext_pat
);
5813 free_list_array(&keyword_pat
);
5815 free_list_array(&charset_pat
);
5817 fs_give((void **)&age_pat
);
5819 fs_give((void **)&size_pat
);
5821 fs_give((void **)&scorei_pat
);
5823 fs_give((void **)&cati
);
5825 fs_give((void **)&cat_lim
);
5827 fs_give((void **)&stat_del
);
5829 fs_give((void **)&stat_new
);
5831 fs_give((void **)&stat_rec
);
5833 fs_give((void **)&stat_imp
);
5835 fs_give((void **)&stat_ans
);
5837 fs_give((void **)&stat_8bit
);
5839 fs_give((void **)&stat_bom
);
5841 fs_give((void **)&stat_boy
);
5843 fs_give((void **)&fldr_type_pat
);
5845 free_list_array(&folder_pat
);
5847 fs_give((void **)&abook_type_pat
);
5849 free_list_array(&abook_pat
);
5851 fs_give((void **)&inick
);
5853 fs_give((void **)&from_act
);
5855 fs_give((void **)&replyto_act
);
5857 fs_give((void **)&fcc_act
);
5859 fs_give((void **)&litsig_act
);
5861 fs_give((void **)&sort_act
);
5863 fs_give((void **)&iform_act
);
5865 free_list_array(&keyword_set
);
5867 free_list_array(&keyword_clr
);
5869 fs_give((void **)&startup_act
);
5871 fs_give((void **)&sig_act
);
5873 fs_give((void **)&templ_act
);
5875 fs_give((void **)&score_act
);
5877 fs_give((void **)&hdrtok_act
);
5879 fs_give((void **)&repl_type
);
5881 fs_give((void **)&forw_type
);
5883 fs_give((void **)&comp_type
);
5885 fs_give((void **)&rc_fg
);
5887 fs_give((void **)&rc_bg
);
5889 fs_give((void **)&old_fg
);
5891 fs_give((void **)&old_bg
);
5893 fs_give((void **)&filt_del
);
5895 fs_give((void **)&filt_new
);
5897 fs_give((void **)&filt_ans
);
5899 fs_give((void **)&filt_imp
);
5901 free_list_array(&folder_act
);
5903 fs_give((void **)&filter_type
);
5906 free_list_array(&cat_cmd
);
5909 free_list_array(&cstm_act
);
5912 free_list_array(&smtp_act
);
5915 free_list_array(&nntp_act
);
5917 opt_screen
= saved_screen
;
5918 ps
->mangled_screen
= 1;
5924 setup_dummy_pattern_var(struct variable
*v
, char *name
, PATTERN_S
*defpat
)
5929 alpine_panic("setup_dummy_pattern_var");
5931 v
->name
= (char *) fs_get(strlen(name
)+NOTLEN
+1);
5932 snprintf(v
->name
, strlen(name
)+NOTLEN
+1, "%s%s", (defpat
&& defpat
->not) ? NOT
: "", name
);
5933 v
->name
[ strlen(name
)+NOTLEN
+1-1] = '\0';
5937 alval
= ALVAL(v
, ew
);
5938 *alval
= pattern_to_editlist(defpat
);
5939 set_current_val(v
, FALSE
, FALSE
);
5944 setup_role_pat(struct pine
*ps
, CONF_S
**ctmp
, struct variable
*v
, HelpType help
,
5945 char *help_title
, struct key_menu
*keymenu
,
5946 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
5947 EARB_S
**earb
, int indent
)
5949 char tmp
[MAXPATH
+1];
5955 (*ctmp
)->help_title
= help_title
;
5957 (*ctmp
)->valoffset
= indent
;
5958 (*ctmp
)->keymenu
= keymenu
;
5959 (*ctmp
)->help
= help
;
5960 (*ctmp
)->tool
= tool
;
5961 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", indent
-3, indent
-3, (v
&& v
->name
) ? v
->name
: "");
5962 tmp
[sizeof(tmp
)-1] = '\0';
5963 (*ctmp
)->varname
= cpystr(tmp
);
5964 (*ctmp
)->varnamep
= *ctmp
;
5965 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
5966 (*ctmp
)->d
.earb
= earb
;
5967 (*ctmp
)->varmem
= 0;
5968 (*ctmp
)->flags
= CF_STARTITEM
;
5974 for(i
= 0; lval
[i
]; i
++){
5979 (*ctmp
)->varmem
= i
;
5980 (*ctmp
)->valoffset
= indent
;
5981 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
5982 (*ctmp
)->d
.earb
= earb
;
5983 (*ctmp
)->keymenu
= keymenu
;
5984 (*ctmp
)->help
= help
;
5985 (*ctmp
)->tool
= tool
;
5986 (*ctmp
)->varnamep
= ctmpb
;
5993 * Watch out for polarity of nosel flag. Setting it means to turn on
5994 * the NOSELECT flag, which means to make that line unselectable.
5997 setup_role_pat_alt(struct pine
*ps
, CONF_S
**ctmp
, struct variable
*v
, HelpType help
,
5998 char *help_title
, struct key_menu
*keymenu
,
5999 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
6000 int voff
, int nosel
)
6002 char tmp
[MAXPATH
+1];
6008 (*ctmp
)->help_title
= help_title
;
6011 (*ctmp
)->varoffset
= voff
;
6012 k
= utf8_width(v
->name
);
6014 (*ctmp
)->valoffset
= j
;
6016 (*ctmp
)->keymenu
= keymenu
;
6017 (*ctmp
)->help
= help
;
6018 (*ctmp
)->tool
= tool
;
6020 utf8_snprintf(tmp
, sizeof(tmp
), "%*.*w =", k
, k
, v
->name
);
6021 tmp
[sizeof(tmp
)-1] = '\0';
6022 (*ctmp
)->varname
= cpystr(tmp
);
6024 (*ctmp
)->varnamep
= *ctmp
;
6025 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
6026 (*ctmp
)->varmem
= 0;
6028 (*ctmp
)->flags
= (nosel
? CF_NOSELECT
: 0);
6034 for(i
= 0; lval
[i
]; i
++){
6039 (*ctmp
)->varmem
= i
;
6040 (*ctmp
)->varoffset
= voff
;
6041 (*ctmp
)->valoffset
= j
;
6042 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
6043 (*ctmp
)->keymenu
= keymenu
;
6044 (*ctmp
)->help
= help
;
6045 (*ctmp
)->tool
= tool
;
6046 (*ctmp
)->varnamep
= ctmpb
;
6047 (*ctmp
)->flags
= (nosel
? CF_NOSELECT
: 0);
6054 free_earb(EARB_S
**ea
)
6057 free_earb(&(*ea
)->next
);
6059 free_variable_values((*ea
)->v
);
6061 fs_give((void **) &(*ea
)->v
->name
);
6063 fs_give((void **) &(*ea
)->v
);;
6066 free_arbhdr(&(*ea
)->a
);
6067 fs_give((void **) ea
);
6073 calculate_inick_stuff(struct pine
*ps
)
6075 ACTION_S
*role
, *irole
;
6076 CONF_S
*ctmp
, *ctmpa
;
6081 if(inick_confs
[INICK_INICK_CONF
] == NULL
)
6084 for(i
= INICK_FROM_CONF
; i
<= INICK_NNTP_CONF
; i
++){
6085 v
= inick_confs
[i
] ? inick_confs
[i
]->var
: NULL
;
6089 free_list_array(&v
->global_val
.l
);
6093 fs_give((void **)&v
->global_val
.p
);
6098 nick
= PVAL(inick_confs
[INICK_INICK_CONF
]->var
, ew
);
6102 * Use an empty role with inherit_nick set to nick and then use the
6103 * combine function to find the action values.
6105 role
= (ACTION_S
*)fs_get(sizeof(*role
));
6106 memset((void *)role
, 0, sizeof(*role
));
6107 role
->is_a_role
= 1;
6108 role
->inherit_nick
= cpystr(nick
);
6109 irole
= combine_inherited_role(role
);
6111 ctmp
= inick_confs
[INICK_FROM_CONF
];
6112 v
= ctmp
? ctmp
->var
: NULL
;
6114 if(irole
&& irole
->from
){
6118 len
= est_size(irole
->from
);
6119 bufp
= (char *) fs_get(len
* sizeof(char));
6120 v
->global_val
.p
= addr_string_mult(irole
->from
, bufp
, len
);
6123 ctmp
= inick_confs
[INICK_REPLYTO_CONF
];
6124 v
= ctmp
? ctmp
->var
: NULL
;
6126 if(irole
&& irole
->replyto
){
6130 len
= est_size(irole
->replyto
);
6131 bufp
= (char *) fs_get(len
* sizeof(char));
6132 v
->global_val
.p
= addr_string_mult(irole
->replyto
, bufp
, len
);
6135 ctmp
= inick_confs
[INICK_FCC_CONF
];
6136 v
= ctmp
? ctmp
->var
: NULL
;
6137 v
->global_val
.p
= (irole
&& irole
->fcc
) ? cpystr(irole
->fcc
) : NULL
;
6139 ctmp
= inick_confs
[INICK_LITSIG_CONF
];
6140 v
= ctmp
? ctmp
->var
: NULL
;
6141 v
->global_val
.p
= (irole
&& irole
->litsig
) ? cpystr(irole
->litsig
)
6144 ctmp
= inick_confs
[INICK_SIG_CONF
];
6145 v
= ctmp
? ctmp
->var
: NULL
;
6146 v
->global_val
.p
= (irole
&& irole
->sig
) ? cpystr(irole
->sig
) : NULL
;
6148 ctmp
= inick_confs
[INICK_TEMPL_CONF
];
6149 v
= ctmp
? ctmp
->var
: NULL
;
6150 v
->global_val
.p
= (irole
&& irole
->template)
6151 ? cpystr(irole
->template) : NULL
;
6153 ctmp
= inick_confs
[INICK_CSTM_CONF
];
6154 v
= ctmp
? ctmp
->var
: NULL
;
6155 v
->global_val
.l
= (irole
&& irole
->cstm
) ? copy_list_array(irole
->cstm
)
6158 ctmp
= inick_confs
[INICK_SMTP_CONF
];
6159 v
= ctmp
? ctmp
->var
: NULL
;
6160 v
->global_val
.l
= (irole
&& irole
->smtp
) ? copy_list_array(irole
->smtp
)
6163 ctmp
= inick_confs
[INICK_NNTP_CONF
];
6164 v
= ctmp
? ctmp
->var
: NULL
;
6165 v
->global_val
.l
= (irole
&& irole
->nntp
) ? copy_list_array(irole
->nntp
)
6169 free_action(&irole
);
6172 for(i
= INICK_INICK_CONF
; i
<= INICK_NNTP_CONF
; i
++){
6173 ctmp
= inick_confs
[i
];
6174 v
= ctmp
? ctmp
->var
: NULL
;
6176 * If we didn't set a global_val using the nick above, then
6177 * set one here for each variable that uses one.
6179 if(v
&& !v
->global_val
.p
){
6180 char *str
, *astr
, *lc
, pdir
[MAXPATH
+1];
6185 case INICK_FROM_CONF
:
6186 addr
= generate_from();
6187 astr
= addr_list_string(addr
, NULL
, 1);
6188 str
= (astr
&& astr
[0]) ? astr
: "?";
6189 v
->global_val
.p
= (char *)fs_get((strlen(str
) + 20) *
6191 snprintf(v
->global_val
.p
, strlen(str
) + 20, "%s%s)", DSTRING
, str
);
6192 v
->global_val
.p
[strlen(str
) + 20 - 1] = '\0';
6194 fs_give((void **)&astr
);
6197 mail_free_address(&addr
);
6201 case INICK_FCC_CONF
:
6202 v
->global_val
.p
= cpystr(VSTRING
);
6205 case INICK_LITSIG_CONF
:
6207 * This default works this way because of the ordering
6208 * of the choices in the detoken routine.
6210 if(ps
->VAR_LITERAL_SIG
){
6211 str
= ps
->VAR_LITERAL_SIG
;
6212 v
->global_val
.p
= (char *)fs_get((strlen(str
) + 20) *
6214 snprintf(v
->global_val
.p
, strlen(str
) + 20,
6215 "%s%s)", DSTRING
, str
);
6216 v
->global_val
.p
[strlen(str
) + 20 - 1] = '\0';
6221 case INICK_SIG_CONF
:
6223 if(ps_global
->VAR_OPER_DIR
){
6224 strncpy(pdir
, ps_global
->VAR_OPER_DIR
, MAXPATH
);
6225 pdir
[MAXPATH
] = '\0';
6226 len
= strlen(pdir
) + 1;
6228 else if((lc
= last_cmpnt(ps_global
->pinerc
)) != NULL
){
6229 strncpy(pdir
, ps_global
->pinerc
,
6230 MIN(MAXPATH
,lc
-ps_global
->pinerc
));
6231 pdir
[MIN(MAXPATH
, lc
-ps_global
->pinerc
)] = '\0';
6235 if(pdir
[0] && ps
->VAR_SIGNATURE_FILE
&&
6236 ps
->VAR_SIGNATURE_FILE
[0] &&
6237 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
6238 !strncmp(ps
->VAR_SIGNATURE_FILE
, pdir
, len
)){
6239 str
= ps
->VAR_SIGNATURE_FILE
+ len
;
6242 str
= (ps
->VAR_SIGNATURE_FILE
&& ps
->VAR_SIGNATURE_FILE
[0])
6243 ? ps
->VAR_SIGNATURE_FILE
: NULL
;
6245 v
->global_val
.p
= (char *)fs_get((strlen(str
) + 20) *
6247 snprintf(v
->global_val
.p
, strlen(str
) + 20, "%s%s)", DSTRING
, str
);
6248 v
->global_val
.p
[strlen(str
) + 20 - 1] = '\0';
6253 case INICK_INICK_CONF
:
6254 case INICK_REPLYTO_CONF
:
6255 case INICK_TEMPL_CONF
:
6256 case INICK_CSTM_CONF
:
6257 case INICK_SMTP_CONF
:
6258 case INICK_NNTP_CONF
:
6264 set_current_val(v
, FALSE
, FALSE
);
6267 CONF_S
*ctmpsig
= NULL
;
6268 struct variable
*vlsig
;
6271 ctmpa
&& ctmpa
->varnamep
== ctmp
;
6272 ctmpa
= ctmpa
->next
){
6274 fs_give((void **)&ctmpa
->value
);
6276 ctmpa
->value
= pretty_value(ps
, ctmpa
);
6279 if(i
== INICK_SIG_CONF
){
6281 * Turn off NOSELECT, but possibly turn it on again
6284 if((ctmpsig
= inick_confs
[INICK_SIG_CONF
]) != NULL
)
6285 ctmpsig
->flags
&= ~CF_NOSELECT
;
6287 if(inick_confs
[INICK_LITSIG_CONF
] &&
6288 (vlsig
= inick_confs
[INICK_LITSIG_CONF
]->var
) &&
6289 vlsig
->current_val
.p
&&
6290 vlsig
->current_val
.p
[0]){
6292 fs_give((void **)&ctmp
->value
);
6295 cpystr("<Ignored: using LiteralSig instead>");
6297 ctmp
->flags
|= CF_NOSELECT
;
6306 * lst: a list of folders
6307 * action: a 1 or 0 value which basically says that str is associated with
6308 * the filter action if true or the Current Folder type if false.
6310 * Returns 2 on success (user wants to exit) and 0 on failure.
6312 * This function cycles through a list of folders and checks whether or not each
6313 * folder exists. If they exist, return 2, if they don't exist, notify the user
6314 * or offer to create depending on whether or not it is a filter action or not.
6315 * With each of these prompts, the user can abort their desire to exit.
6318 check_role_folders(char **lst
, unsigned int action
)
6320 char *cur_fn
, wt_res
, prompt
[MAX_SCREEN_COLS
];
6322 CONTEXT_S
*cntxt
= NULL
;
6323 char nbuf1
[MAX_SCREEN_COLS
], nbuf2
[MAX_SCREEN_COLS
];
6324 int space
, w1
, w2
, exists
;
6328 q_status_message(SM_ORDER
, 3, 5,
6329 _("Set a valid Filter Action before Exiting"));
6331 q_status_message(SM_ORDER
, 3, 5,
6332 _("Set a valid Specific Folder before Exiting"));
6337 for(i
= 0; lst
[i
]; i
++){
6339 cur_fn
= detoken_src(lst
[i
], FOR_FILT
, NULL
, NULL
, NULL
, NULL
);
6343 removing_leading_and_trailing_white_space(cur_fn
);
6344 if(*cur_fn
!= '\0'){
6346 if(is_absolute_path(cur_fn
) || !context_isambig(cur_fn
))
6349 cntxt
= default_save_context(ps_global
->context_list
);
6351 if(!(exists
=folder_exists(cntxt
, cur_fn
))
6353 || (ps_global
->context_list
->use
& CNTXT_INCMNG
6354 && !folder_is_nick(cur_fn
,FOLDERS(ps_global
->context_list
), 0)))){
6355 if(cntxt
&& (action
== 1)){
6356 space
-= 37; /* for fixed part of prompt below */
6357 w1
= MAX(1,MIN(strlen(cur_fn
),space
/2));
6358 w2
= MIN(MAX(1,space
-w1
),strlen(cntxt
->nickname
));
6359 w1
+= MAX(0,space
-w1
-w2
);
6360 snprintf(prompt
, sizeof(prompt
),
6361 _("Folder \"%s\" in <%s> doesn't exist. Create"),
6362 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
),
6363 short_str(cntxt
->nickname
,nbuf2
,sizeof(nbuf2
),w2
,MidDots
));
6364 prompt
[sizeof(prompt
)-1] = '\0';
6366 else if(cntxt
&& (action
== 0)){
6367 space
-= 51; /* for fixed part of prompt below */
6368 w1
= MAX(1,MIN(strlen(cur_fn
),space
/2));
6369 w2
= MIN(MAX(1,space
-w1
),strlen(cntxt
->nickname
));
6370 w1
+= MAX(0,space
-w1
-w2
);
6371 snprintf(prompt
, sizeof(prompt
),
6372 _("Folder \"%s\" in <%s> doesn't exist. Exit and save anyway"),
6373 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
),
6374 short_str(cntxt
->nickname
,nbuf2
,sizeof(nbuf2
),w2
,MidDots
));
6375 prompt
[sizeof(prompt
)-1] = '\0';
6377 else if(!cntxt
&& (action
== 1)){
6378 space
-= 31; /* for fixed part of prompt below */
6380 snprintf(prompt
, sizeof(prompt
),
6381 _("Folder \"%s\" doesn't exist. Create"),
6382 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
));
6383 prompt
[sizeof(prompt
)-1] = '\0';
6385 else{ /*!cntxt && (action == 0) */
6386 space
-= 45; /* for fixed part of prompt below */
6388 snprintf(prompt
, sizeof(prompt
),
6389 _("Folder \"%s\" doesn't exist. Exit and save anyway"),
6390 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
));
6391 prompt
[sizeof(prompt
)-1] = '\0';
6394 wt_res
= want_to(prompt
, 'n', 'x', NO_HELP
, WT_NORM
);
6397 if(context_create(cntxt
, NULL
, cur_fn
)){
6398 q_status_message(SM_ORDER
,3,5,_("Folder created"));
6399 maybe_add_to_incoming(cntxt
, cur_fn
);
6402 /* No message to notify of changes being saved, we can't */
6403 /* assume that the role screen isn't exited yet */
6406 else if(wt_res
== 'n' && action
){
6408 q_status_message(SM_ORDER
,3,5,_("Folder not created"));
6411 q_status_message(SM_ORDER
,3,5,_("Exit cancelled"));
6417 if(exists
& FEX_ERROR
){
6418 if(ps_global
->mm_log_error
&& ps_global
->c_client_error
)
6419 q_status_message(SM_ORDER
,3,5,ps_global
->c_client_error
);
6421 q_status_message1(SM_ORDER
,3,5,"\"%s\": Trouble checking for folder existence", cur_fn
);
6427 else{ /* blank item in list of folders */
6428 if(action
&& lst
[i
+1] == NULL
)
6429 q_status_message(SM_ORDER
,3,5,_("Set a valid Filter Action before Exiting"));
6430 else /* !action && lst[i+1] == '\0' */
6431 q_status_message(SM_ORDER
,3,5,_("Set a valid Specific Folder before Exiting"));
6436 if(cur_fn
&& cur_fn
!= lst
[i
])
6437 fs_give((void **) &cur_fn
);
6445 maybe_add_to_incoming(CONTEXT_S
*cntxt
, char *cur_fn
)
6447 char name
[MAILTMPLEN
], nname
[32];
6448 char nbuf1
[MAX_SCREEN_COLS
], nbuf2
[MAX_SCREEN_COLS
];
6449 char prompt
[MAX_SCREEN_COLS
];
6451 int i
, found
, space
, w1
, w2
;
6454 if(ps_global
->context_list
->use
& CNTXT_INCMNG
&&
6455 ((alval
= ALVAL(&ps_global
->vars
[V_INCOMING_FOLDERS
], Main
)) != NULL
)){
6456 (void)context_apply(name
, cntxt
, cur_fn
, sizeof(name
));
6458 * Since the folder didn't exist it is very unlikely that it is
6459 * in the incoming-folders list already, but we're just checking
6460 * to be sure. We should really be canonicalizing both names
6461 * before comparing, but...
6463 for(found
= 0, i
= 0; *alval
&& (*alval
)[i
] && !found
; i
++){
6464 char *nickname
, *folder
;
6466 get_pair((*alval
)[i
], &nickname
, &folder
, 0, 0);
6467 if(folder
&& !strucmp((*alval
)[i
], folder
))
6471 fs_give((void **)&nickname
);
6473 fs_give((void **)&folder
);
6480 space
-= 15; /* for fixed part of prompt below */
6482 MIN(space
/2,MIN(strlen(ps_global
->context_list
->nickname
),20)));
6483 w1
= MAX(1,space
- w2
);
6484 snprintf(prompt
, sizeof(prompt
),
6485 "Add \"%s\" to %s list",
6486 short_str(name
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
),
6487 short_str(ps_global
->context_list
->nickname
,nbuf2
,sizeof(nbuf2
),w2
,MidDots
));
6488 prompt
[sizeof(prompt
)-1] = '\0';
6489 if(want_to(prompt
, 'n', 'x', NO_HELP
, WT_NORM
) == 'y'){
6496 snprintf(prompt
, sizeof(prompt
), "Nickname for folder \"%s\" : ",
6497 short_str(name
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
));
6498 prompt
[sizeof(prompt
)-1] = '\0';
6501 int flags
= OE_APPEND_CURRENT
;
6503 rc
= optionally_enter(nname
, -FOOTER_ROWS(ps_global
), 0,
6504 sizeof(nname
), prompt
, NULL
,
6506 removing_leading_and_trailing_white_space(nname
);
6507 if(rc
== 0 && *nname
){
6508 /* see if nickname already exists */
6510 if(!strucmp(ps_global
->inbox_name
, nname
))
6515 i
< folder_total(FOLDERS(ps_global
->context_list
));
6519 f
= folder_entry(i
, FOLDERS(ps_global
->context_list
));
6520 if(!strucmp(FLDR_NAME(f
), nname
))
6525 q_status_message1(SM_ORDER
| SM_DING
, 3, 5,
6526 _("Nickname \"%s\" is already in use"),
6534 q_status_message(SM_ORDER
, 0, 3, _("No help yet."));
6536 q_status_message1(SM_ORDER
, 0, 3,
6537 _("Not adding nickname to %s list"),
6538 ps_global
->context_list
->nickname
);
6543 pp
= put_pair(nname
, name
);
6544 f
= new_folder(name
, line_hash(pp
));
6545 f
->nickname
= cpystr(nname
);
6546 f
->name_len
= strlen(nname
);
6547 folder_insert(folder_total(FOLDERS(ps_global
->context_list
)), f
,
6548 FOLDERS(ps_global
->context_list
));
6552 *alval
= (char **)fs_get(2 * sizeof(char *));
6555 for(i
= 0; (*alval
)[i
]; i
++)
6558 fs_resize((void **)alval
, (i
+ 2) * sizeof(char *));
6562 (*alval
)[i
+1] = NULL
;
6563 set_current_val(&ps_global
->vars
[V_INCOMING_FOLDERS
], TRUE
, TRUE
);
6564 write_pinerc(ps_global
, ew
, WRP_NONE
);
6571 role_filt_exitcheck(CONF_S
**cl
, unsigned int flags
)
6574 char **to_folder
= NULL
, **spec_fldr
= NULL
;
6577 #define ACT_UNKNOWN 0
6580 #define ACT_MOVE_NOFOLDER 3
6584 * We have to locate the lines which define the Filter Action and
6585 * then check to see that it is set to something before allowing
6588 action
= ACT_UNKNOWN
;
6589 if(flags
& CF_CHANGES
&& role_filt_ptr
&& PVAL(role_filt_ptr
,ew
)){
6590 for(j
= 0; (f
= filter_types(j
)); j
++)
6591 if(!strucmp(PVAL(role_filt_ptr
,ew
), f
->name
))
6594 switch(f
? f
->value
: -1){
6605 * Check that the folder is set to something.
6608 action
= ACT_MOVE_NOFOLDER
;
6609 /* go to end of screen */
6612 ctmp
= next_confline(ctmp
))
6615 /* back up to start of Filter Action */
6618 !(ctmp
->flags
& CF_STARTITEM
&& ctmp
->var
== role_filt_ptr
);
6619 ctmp
= prev_confline(ctmp
))
6622 /* skip back past NOSELECTs */
6624 ctmp
&& (ctmp
->flags
& CF_NOSELECT
);
6625 ctmp
= next_confline(ctmp
))
6628 /* find line with new var (the Folder line) */
6630 ctmp
&& (ctmp
->var
== role_filt_ptr
);
6631 ctmp
= next_confline(ctmp
))
6634 /* ok, we're finally at the Folder line */
6635 if(ctmp
&& ctmp
->var
&& LVAL(ctmp
->var
,ew
)){
6636 to_folder
= copy_list_array(LVAL(ctmp
->var
,ew
));
6637 if(to_folder
&& to_folder
[0])
6645 "Can't happen, role_filt_ptr set to %s\n",
6646 PVAL(role_filt_ptr
,ew
) ? PVAL(role_filt_ptr
,ew
) : "?"));
6651 if(flags
& CF_CHANGES
){
6652 switch(want_to((action
== ACT_KILL
)
6653 ? _("Commit changes (\"Yes\" means matching messages will be deleted)")
6654 : EXIT_PMT
, 'y', 'x', h_config_undo
, WT_FLUSH_IN
)){
6658 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
6659 rv
= check_role_folders(spec_fldr
, 0);
6660 free_list_array(&spec_fldr
);
6662 q_status_message(SM_ORDER
,0,3,_("Ok, messages matching that Pattern will be deleted"));
6665 q_status_message(SM_ORDER
, 0, 3,
6666 _("Ok, messages matching that Pattern will be deleted"));
6672 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
6673 rv
= check_role_folders(spec_fldr
, 0);
6674 free_list_array(&spec_fldr
);
6675 if(to_folder
&& rv
== 2)
6676 rv
= check_role_folders(to_folder
, 1);
6679 rv
= check_role_folders(to_folder
, 1);
6683 case ACT_MOVE_NOFOLDER
:
6685 q_status_message(SM_ORDER
, 3, 5,
6686 _("Set a valid Filter Action before Exiting"));
6690 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
6691 rv
= check_role_folders(spec_fldr
, 0);
6692 free_list_array(&spec_fldr
);
6702 "This can't happen, role_filt_ptr or to_folder not set\n"));
6709 q_status_message(SM_ORDER
,3,5,_("No filter changes saved"));
6715 q_status_message(SM_ORDER
,3,5,_("Changes not yet saved"));
6724 free_list_array(&to_folder
);
6731 * Don't allow exit unless user has set the action to something.
6734 role_filt_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6740 rv
= role_filt_exitcheck(cl
, flags
);
6744 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6753 role_filt_addhdr_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6759 rv
= role_filt_exitcheck(cl
, flags
);
6763 rv
= role_addhdr_tool(ps
, cmd
, cl
, flags
);
6771 role_addhdr_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6778 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6790 * Don't allow exit unless user has set the action to something.
6793 role_filt_radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6799 rv
= role_filt_exitcheck(cl
, flags
);
6803 rv
= role_radiobutton_tool(ps
, cmd
, cl
, flags
);
6812 * simple radio-button style variable handler
6815 role_radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6818 CONF_S
*ctmp
, *spec_ctmp
= NULL
;
6823 case MC_CHOICE
: /* set/unset feature */
6825 /* back up to first line */
6827 ctmp
&& ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
);
6828 ctmp
= prev_confline(ctmp
))
6831 for(i
= 0; ctmp
&& (!(ctmp
->flags
& CF_NOSELECT
)
6832 || (*cl
)->var
== role_fldr_ptr
6833 || (*cl
)->var
== role_afrom_ptr
6834 || (*cl
)->var
== role_filt_ptr
);
6835 ctmp
= next_confline(ctmp
), i
++){
6836 if(((*cl
)->var
== role_fldr_ptr
) ||
6837 ((*cl
)->var
== role_afrom_ptr
) ||
6838 ((*cl
)->var
== role_filt_ptr
)){
6839 if((((*cl
)->var
== role_fldr_ptr
) && !pat_fldr_types(i
))
6840 || (((*cl
)->var
== role_afrom_ptr
)
6841 && !inabook_fldr_types(i
))
6842 || (((*cl
)->var
== role_filt_ptr
) && !filter_types(i
))){
6848 ctmp
->value
[1] = ' ';
6851 /* turn on current value */
6852 (*cl
)->value
[1] = R_SELD
;
6854 if((*cl
)->var
== role_fldr_ptr
){
6855 for(ctmp
= spec_ctmp
;
6856 ctmp
&& ctmp
->varnamep
== spec_ctmp
;
6857 ctmp
= next_confline(ctmp
))
6858 if((*cl
)->varmem
== FLDR_SPECIFIC
)
6859 ctmp
->flags
&= ~CF_NOSELECT
;
6861 ctmp
->flags
|= CF_NOSELECT
;
6863 rule
= pat_fldr_types((*cl
)->varmem
);
6865 else if((*cl
)->var
== role_afrom_ptr
){
6866 for(ctmp
= spec_ctmp
;
6867 ctmp
&& ctmp
->varnamep
== spec_ctmp
;
6868 ctmp
= next_confline(ctmp
))
6869 if(((*cl
)->varmem
== IAB_SPEC_YES
)
6870 || ((*cl
)->varmem
== IAB_SPEC_NO
))
6871 ctmp
->flags
&= ~CF_NOSELECT
;
6873 ctmp
->flags
|= CF_NOSELECT
;
6875 rule
= inabook_fldr_types((*cl
)->varmem
);
6877 else if((*cl
)->var
== role_filt_ptr
){
6878 for(ctmp
= spec_ctmp
;
6879 ctmp
&& ctmp
->varnamep
== spec_ctmp
;
6880 ctmp
= next_confline(ctmp
))
6881 if((*cl
)->varmem
== FILTER_FOLDER
)
6882 ctmp
->flags
&= ~CF_NOSELECT
;
6884 ctmp
->flags
|= CF_NOSELECT
;
6886 rule
= filter_types((*cl
)->varmem
);
6888 else if((*cl
)->var
== role_forw_ptr
)
6889 rule
= role_forw_types((*cl
)->varmem
);
6890 else if((*cl
)->var
== role_repl_ptr
)
6891 rule
= role_repl_types((*cl
)->varmem
);
6892 else if((*cl
)->var
== role_status1_ptr
||
6893 (*cl
)->var
== role_status2_ptr
||
6894 (*cl
)->var
== role_status3_ptr
||
6895 (*cl
)->var
== role_status4_ptr
||
6896 (*cl
)->var
== role_status5_ptr
||
6897 (*cl
)->var
== role_status6_ptr
||
6898 (*cl
)->var
== role_status7_ptr
||
6899 (*cl
)->var
== role_status8_ptr
)
6900 rule
= role_status_types((*cl
)->varmem
);
6901 else if((*cl
)->var
== msg_state1_ptr
||
6902 (*cl
)->var
== msg_state2_ptr
||
6903 (*cl
)->var
== msg_state3_ptr
||
6904 (*cl
)->var
== msg_state4_ptr
)
6905 rule
= msg_state_types((*cl
)->varmem
);
6907 rule
= role_comp_types((*cl
)->varmem
);
6909 apval
= APVAL((*cl
)->var
, ew
);
6911 fs_give((void **)apval
);
6914 *apval
= cpystr(rule
->name
);
6916 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
6921 case MC_EXIT
: /* exit */
6922 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6935 role_sort_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6943 apval
= APVAL((*cl
)->var
, ew
);
6946 case MC_CHOICE
: /* set/unset feature */
6948 if((*cl
)->varmem
>= 0){
6949 def_sort_rev
= (*cl
)->varmem
>= (short) EndofList
;
6950 def_sort
= (SortOrder
)((*cl
)->varmem
- (def_sort_rev
* EndofList
));
6952 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def_sort
),
6953 (def_sort_rev
) ? "/Reverse" : "");
6954 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
6959 fs_give((void **)apval
);
6961 if((*cl
)->varmem
>= 0)
6962 *apval
= cpystr(tmp_20k_buf
);
6965 /* back up to first line */
6967 ctmp
&& ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
);
6968 ctmp
= prev_confline(ctmp
))
6971 /* turn off all values */
6973 ctmp
&& !(ctmp
->flags
& CF_NOSELECT
);
6974 ctmp
= next_confline(ctmp
), i
++)
6975 ctmp
->value
[1] = ' ';
6977 /* turn on current value */
6978 (*cl
)->value
[1] = R_SELD
;
6980 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
6985 case MC_EXIT
: /* exit */
6986 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6998 * Return an allocated list of the Specific Folder list for
6999 * roles, or NULL if Current Folder type is not set to
7000 * to Specific Folder
7002 * WARNING, the method used in obtaining the specific folder is
7003 * VERY dependent on the order in which it is presented on the
7004 * screen. If the Current Folder radio buttons were changed,
7005 * this function would probably need to be fixed accordingly.
7008 get_role_specific_folder(CONF_S
**cl
)
7012 /* go to the first line */
7015 ctmp
= prev_confline(ctmp
))
7018 /* go to the current folder radio button list */
7019 while(ctmp
&& ctmp
->var
!= role_fldr_ptr
)
7020 ctmp
= next_confline(ctmp
);
7022 /* go to the specific folder button (caution) */
7023 while(ctmp
&& ctmp
->varmem
!= FLDR_SPECIFIC
)
7024 ctmp
= next_confline(ctmp
);
7026 /* check if selected (assumption of format "(*)" */
7027 if(ctmp
&& ctmp
->value
[1] == R_SELD
){
7028 /* go to next line, the start of the list */
7029 ctmp
= next_confline(ctmp
);
7030 if(LVAL(ctmp
->var
, ew
))
7031 return copy_list_array(LVAL(ctmp
->var
, ew
));
7036 * Need to allocate empty string so as not to confuse it
7037 * with the possibility that Specific Folder is not selected.
7039 ltmp
= (char **) fs_get(2 * sizeof(char *));
7040 ltmp
[0] = cpystr("");
7053 role_litsig_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7060 rv
= litsig_text_tool(ps
, cmd
, cl
, flags
);
7062 calculate_inick_stuff(ps
);
7067 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7078 role_cstm_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7084 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7088 rv
= text_tool(ps
, cmd
, cl
, flags
);
7089 if(rv
== 1 && (*cl
)->var
){
7092 lval
= LVAL((*cl
)->var
, ew
);
7093 if(lval
&& lval
[(*cl
)->varmem
] &&
7094 ((!struncmp(lval
[(*cl
)->varmem
],"from",4) &&
7095 (lval
[(*cl
)->varmem
][4] == ':' ||
7096 lval
[(*cl
)->varmem
][4] == '\0')) ||
7097 (!struncmp(lval
[(*cl
)->varmem
],"reply-to",8) &&
7098 (lval
[(*cl
)->varmem
][8] == ':' ||
7099 lval
[(*cl
)->varmem
][8] == '\0'))))
7100 q_status_message1(SM_ORDER
|SM_DING
, 5, 7,
7101 "Use \"Set %s\" instead, Change ignored",
7102 !struncmp(lval
[(*cl
)->varmem
],"from",4)
7103 ? "From" : "Reply-To");
7116 role_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7118 OPT_SCREEN_S
*saved_screen
;
7119 int rv
= -1, oeflags
, len
= 0, sig
, r
, i
, cancel
= 0;
7120 char *file
, *err
, title
[20], *newfile
, *lc
, *addr
, *fldr
= NULL
, *tmpfldr
;
7121 char dir2
[MAXPATH
+1], pdir
[MAXPATH
+1], *p
;
7122 char full_filename
[MAXPATH
+1], filename
[MAXPATH
+1];
7123 char tmp
[MAXPATH
+1], **spec_fldr
, **apval
;
7124 EARB_S
*earb
, *ea
, *eaprev
;
7125 CONF_S
*ctmp
, *ctmpb
, *newcp
, *ctend
;
7130 if(flags
& CF_CHANGES
){
7131 switch(want_to(EXIT_PMT
, 'y', 'x', h_config_role_undo
, WT_FLUSH_IN
)){
7133 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
7134 rv
= check_role_folders(spec_fldr
, 0);
7135 free_list_array(&spec_fldr
);
7142 q_status_message(SM_ORDER
,3,5,_("No changes saved"));
7147 q_status_message(SM_ORDER
,3,5,_("Changes not yet saved"));
7157 case MC_NOT
: /* toggle between !matching and matching */
7158 ctmp
= (*cl
)->varnamep
;
7159 if(ctmp
->varname
&& ctmp
->var
&& ctmp
->var
->name
){
7160 if(!strncmp(ctmp
->varname
, NOT
, NOTLEN
) &&
7161 !strncmp(ctmp
->var
->name
, NOT
, NOTLEN
)){
7162 rplstr(ctmp
->var
->name
, strlen(ctmp
->var
->name
)+1, NOTLEN
, "");
7163 rplstr(ctmp
->varname
, strlen(ctmp
->varname
)+1, NOTLEN
, "");
7164 strncpy(ctmp
->varname
+strlen(ctmp
->varname
)-1,
7165 repeat_char(NOTLEN
, ' '), NOTLEN
+1);
7166 strncat(ctmp
->varname
, "=", NOTLEN
);
7169 rplstr(ctmp
->var
->name
, strlen(ctmp
->var
->name
)+NOTLEN
+1, 0, NOT
);
7170 strncpy(ctmp
->varname
+strlen(ctmp
->varname
)-1-NOTLEN
, "=", NOTLEN
);
7171 rplstr(ctmp
->varname
, strlen(ctmp
->varname
)+NOTLEN
+1, 0, NOT
);
7179 case MC_CHOICE
: /* Choose a file */
7181 * In signature_path we read signature files relative to the pinerc
7182 * dir, so if user selects one that is in there we'll make it
7183 * relative instead of absolute, so it looks nicer.
7186 if(ps_global
->VAR_OPER_DIR
){
7187 strncpy(pdir
, ps_global
->VAR_OPER_DIR
, MAXPATH
);
7188 pdir
[MAXPATH
] = '\0';
7189 len
= strlen(pdir
) + 1;
7191 else if((lc
= last_cmpnt(ps_global
->pinerc
)) != NULL
){
7192 strncpy(pdir
, ps_global
->pinerc
, MIN(MAXPATH
,lc
-ps_global
->pinerc
));
7193 pdir
[MIN(MAXPATH
, lc
-ps_global
->pinerc
)] = '\0';
7197 strncpy(title
, "CHOOSE A", 15);
7198 strncpy(dir2
, pdir
, MAXPATH
);
7201 build_path(full_filename
, dir2
, filename
, sizeof(full_filename
));
7203 r
= file_lister(title
, dir2
, sizeof(dir2
), filename
, sizeof(filename
), TRUE
, FB_READ
);
7204 ps
->mangled_screen
= 1;
7207 build_path(full_filename
, dir2
, filename
, sizeof(full_filename
));
7208 removing_leading_and_trailing_white_space(full_filename
);
7209 if(!strncmp(full_filename
, pdir
, strlen(pdir
)))
7210 newfile
= cpystr(full_filename
+ len
);
7212 newfile
= cpystr(full_filename
);
7214 apval
= APVAL((*cl
)->var
, ew
);
7216 fs_give((void **)apval
);
7222 fs_give((void **)&((*cl
)->value
));
7224 (*cl
)->value
= pretty_value(ps
, *cl
);
7232 case MC_CHOICEB
: /* Choose Addresses, no full names */
7233 addr
= addr_book_multaddr_nf();
7234 ps
->mangled_screen
= 1;
7235 if(addr
&& (*cl
)->var
&& (*cl
)->var
->is_list
){
7240 for(tmp
= addr
; *tmp
; tmp
++)
7242 i
++; /* conservative count of ,'s */
7244 ltmp
= parse_list(addr
, i
+ 1, PL_COMMAQUOTE
, NULL
);
7245 fs_give((void **) &addr
);
7248 config_add_list(ps
, cl
, ltmp
, NULL
, 0);
7251 fs_give((void **) <mp
);
7254 fs_give((void **)&((*cl
)->value
));
7256 (*cl
)->value
= pretty_value(ps
, *cl
);
7264 case MC_CHOICEC
: /* Choose an Address, no full name */
7265 addr
= addr_book_oneaddr();
7266 ps
->mangled_screen
= 1;
7268 apval
= APVAL((*cl
)->var
, ew
);
7269 if(apval
&& *apval
) /* replace current value */
7270 fs_give((void **)apval
);
7276 fs_give((void **)&((*cl
)->value
));
7278 (*cl
)->value
= pretty_value(ps
, *cl
);
7286 case MC_CHOICED
: /* Choose a Folder */
7288 saved_screen
= opt_screen
;
7289 if(cmd
== MC_CHOICED
)
7290 tmpfldr
= folder_for_config(FOR_PATTERN
);
7292 tmpfldr
= folder_for_config(0);
7295 fldr
= add_comma_escapes(tmpfldr
);
7296 fs_give((void**) &tmpfldr
);
7299 opt_screen
= saved_screen
;
7301 ps
->mangled_screen
= 1;
7302 if(fldr
&& *fldr
&& (*cl
)->var
&& (*cl
)->var
->is_list
){
7305 ltmp
= (char **) fs_get(2 * sizeof(char *));
7311 config_add_list(ps
, cl
, ltmp
, NULL
, 0);
7314 fs_give((void **) <mp
);
7317 fs_give((void **) &((*cl
)->value
));
7319 (*cl
)->value
= pretty_value(ps
, *cl
);
7322 else if(fldr
&& *fldr
&& (*cl
)->var
&& !(*cl
)->var
->is_list
){
7323 apval
= APVAL((*cl
)->var
, ew
);
7324 if(apval
&& *apval
) /* replace current value */
7325 fs_give((void **)apval
);
7333 fs_give((void **) &((*cl
)->value
));
7335 (*cl
)->value
= pretty_value(ps
, *cl
);
7342 fs_give((void **) &fldr
);
7347 file
= ((*cl
)->var
&& PVAL((*cl
)->var
, ew
))
7348 ? cpystr(PVAL((*cl
)->var
, ew
)) : NULL
;
7350 removing_leading_and_trailing_white_space(file
);
7352 sig
= (srchstr((*cl
)->varname
, "signature") != NULL
);
7353 if(!file
|| !*file
){
7354 err
= (char *)fs_get(100 * sizeof(char));
7355 snprintf(err
, 100, "No %s file defined. First define a file name.",
7356 sig
? "signature" : "template");
7360 if(file
[len
=(strlen(file
)-1)] == '|')
7363 snprintf(title
, sizeof(title
), "%s EDITOR", sig
? "SIGNATURE" : "TEMPLATE");
7364 title
[sizeof(title
)-1] = '\0';
7365 err
= signature_edit(file
, title
);
7368 fs_give((void **)&file
);
7370 q_status_message1(SM_ORDER
, 3, 5, "%s", err
);
7371 fs_give((void **)&err
);
7375 ps
->mangled_screen
= 1;
7378 /* Add an arbitrary header to this role */
7381 /* make earb point to last one */
7382 for(earb
= *(*cl
)->d
.earb
; earb
&& earb
->next
; earb
= earb
->next
)
7385 /* Add new one to end of list */
7386 ea
= (EARB_S
*)fs_get(sizeof(*ea
));
7387 memset((void *)ea
, 0, sizeof(*ea
));
7388 ea
->v
= (struct variable
*)fs_get(sizeof(struct variable
));
7389 memset((void *)ea
->v
, 0, sizeof(struct variable
));
7390 ea
->a
= (ARBHDR_S
*)fs_get(sizeof(ARBHDR_S
));
7391 memset((void *)ea
->a
, 0, sizeof(ARBHDR_S
));
7393 /* get new header field name */
7397 i
= optionally_enter(tmp
, -FOOTER_ROWS(ps
), 0, sizeof(tmp
),
7398 _("Enter the name of the header field to be added: "),
7403 cmd_cancelled("eXtraHdr");
7408 help
= help
== NO_HELP
? h_config_add_pat_hdr
: NO_HELP
;
7415 ps
->mangled_footer
= 1;
7417 removing_leading_and_trailing_white_space(tmp
);
7418 if(tmp
[strlen(tmp
)-1] == ':') /* remove trailing colon */
7419 tmp
[strlen(tmp
)-1] = '\0';
7421 removing_trailing_white_space(tmp
);
7423 if(cancel
|| !tmp
[0])
7426 tmp
[0] = islower((unsigned char)tmp
[0]) ? toupper((unsigned char)tmp
[0])
7428 ea
->a
->field
= cpystr(tmp
);
7433 *((*cl
)->d
.earb
) = ea
;
7435 /* go to first line */
7436 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
7440 * Go to the Add Extra Headers line. We will put the
7441 * new header before this line.
7443 for(; ctmp
; ctmp
= next_confline(ctmp
))
7444 if(ctmp
->value
&& !strcmp(ctmp
->value
, ADDXHDRS
))
7449 ctmp
= prev_confline(ctmp
);
7452 * Add a new line after this point, which is after the last
7453 * extra header (if any) or after the Participant pattern, and
7454 * before the Add Extra Headers placeholder line.
7456 p
= (char *) fs_get(strlen(tmp
) + strlen(" pattern") + 1);
7457 snprintf(p
, strlen(tmp
) + strlen(" pattern") + 1, "%s pattern", tmp
);
7458 p
[strlen(tmp
) + strlen(" pattern") + 1 - 1] = '\0';
7459 setup_dummy_pattern_var(ea
->v
, p
, NULL
);
7460 fs_give((void **) &p
);
7462 /* find what indent should be */
7463 if(ctmp
&& ctmp
->varnamep
&& ctmp
->varnamep
->varname
)
7464 i
= MIN(MAX(utf8_width(ctmp
->varnamep
->varname
) + 1, 3), 200);
7468 setup_role_pat(ps
, &ctmp
, ea
->v
, h_config_role_arbpat
,
7469 ARB_HELP
, &config_role_xtrahdr_keymenu
,
7470 ctmp
->prev
->tool
, ctmp
->prev
->d
.earb
, i
);
7473 * move current line to new line
7478 /* check if new line comes before the top of the screen */
7479 ctmpb
= (opt_screen
&& opt_screen
->top_line
)
7480 ? opt_screen
->top_line
->prev
: NULL
;
7481 for(; ctmpb
; ctmpb
= prev_confline(ctmpb
))
7485 * Keep the right lines visible.
7486 * The if triggers if the new line is off the top of the screen, and
7487 * it makes the new line be the top line.
7488 * The else counts how many lines down the screen the new line is.
7493 opt_screen
->top_line
= newcp
;
7495 for(ctmp
= opt_screen
->top_line
; ctmp
&& ctmp
!= newcp
;
7496 i
++, ctmp
= next_confline(ctmp
))
7500 if(i
>= BODY_LINES(ps
)){ /* new line is off screen */
7501 /* move top line down this far */
7502 i
= i
+ 1 - BODY_LINES(ps
);
7503 for(ctmp
= opt_screen
->top_line
;
7505 i
--, ctmp
= next_confline(ctmp
))
7508 opt_screen
->top_line
= ctmp
;
7513 ps
->mangled_screen
= 1;
7517 /* Delete an arbitrary header from this role */
7520 * Find this one in earb list. We don't have a good way to locate
7521 * it so we match the ea->v->name with ctmp->varname.
7525 for(ea
= *(*cl
)->d
.earb
; ea
; ea
= ea
->next
){
7526 if((*cl
)->varnamep
&& (*cl
)->varnamep
->varname
7527 && ea
->v
&& ea
->v
->name
7528 && !strncmp((*cl
)->varnamep
->varname
,
7529 ea
->v
->name
, strlen(ea
->v
->name
)))
7535 snprintf(tmp
, sizeof(tmp
), _("Really remove \"%s\" pattern from this rule"),
7536 (ea
&& ea
->a
&& ea
->a
->field
) ? ea
->a
->field
: "this");
7537 tmp
[sizeof(tmp
)-1] = '\0';
7538 if(want_to(tmp
, 'y', 'n', NO_HELP
, WT_NORM
) != 'y'){
7539 cmd_cancelled("RemoveHdr");
7543 /* delete the earb element from the list */
7546 eaprev
->next
= ea
->next
;
7548 *(*cl
)->d
.earb
= ea
->next
;
7554 /* remember start of deleted header */
7555 ctmp
= (*cl
&& (*cl
)->varnamep
) ? (*cl
)->varnamep
: NULL
;
7557 /* and end of deleted header */
7558 for(ctend
= *cl
; ctend
; ctend
= next_confline(ctend
))
7559 if(!ctend
->next
|| ctend
->next
->varnamep
!= ctmp
)
7562 /* check if top line is one we're deleting */
7563 for(ctmpb
= ctmp
; ctmpb
; ctmpb
= next_confline(ctmpb
)){
7564 if(ctmpb
== opt_screen
->top_line
)
7571 if(ctmpb
== opt_screen
->top_line
)
7572 opt_screen
->top_line
= ctend
? ctend
->next
: NULL
;
7574 /* move current line after this header */
7575 *cl
= ctend
? ctend
->next
: NULL
;
7577 /* remove deleted header lines */
7579 /* remove from linked list */
7581 ctmp
->prev
->next
= ctend
->next
;
7584 ctend
->next
->prev
= ctmp
->prev
;
7587 ctmp
->prev
= ctend
->next
= NULL
;
7588 free_conflines(&ctmp
);
7591 ps
->mangled_body
= 1;
7596 if(((*cl
)->var
== scorei_pat_global_ptr
7597 || (*cl
)->var
== age_pat_global_ptr
7598 || (*cl
)->var
== size_pat_global_ptr
7599 || (*cl
)->var
== cati_global_ptr
)
7601 (cmd
== MC_EDIT
|| (cmd
== MC_ADD
&& !PVAL((*cl
)->var
, ew
)))){
7605 snprintf(prompt
, sizeof(prompt
), "%s the interval : ",
7606 PVAL((*cl
)->var
, ew
) ? "Change" : "Enter");
7607 prompt
[sizeof(prompt
)-1] = '\0';
7609 ps
->mangled_footer
= 1;
7612 snprintf(tmp
, sizeof(tmp
),
7613 "%s", PVAL((*cl
)->var
, ew
) ? PVAL((*cl
)->var
, ew
) : "");
7614 tmp
[sizeof(tmp
)-1] = '\0';
7616 oeflags
= OE_APPEND_CURRENT
;
7617 i
= optionally_enter(tmp
, -FOOTER_ROWS(ps
), 0, sizeof(tmp
),
7618 prompt
, NULL
, help
, &oeflags
);
7620 rv
= ps
->mangled_body
= 1;
7621 apval
= APVAL((*cl
)->var
, ew
);
7623 fs_give((void **)apval
);
7626 *apval
= cpystr(tmp
);
7628 fix_side_effects(ps
, (*cl
)->var
, 0);
7630 fs_give((void **)&(*cl
)->value
);
7632 (*cl
)->value
= pretty_value(ps
, *cl
);
7635 cmd_cancelled(cmd
== MC_ADD
? "Add" : "Change");
7637 help
= help
== NO_HELP
? h_config_edit_scorei
: NO_HELP
;
7647 if(cmd
== MC_ADD
&& (*cl
)->var
&& !(*cl
)->var
->is_list
)
7650 rv
= text_toolit(ps
, cmd
, cl
, flags
, 1);
7652 /* make sure the earb pointers are set */
7653 for(ctmp
= (*cl
)->varnamep
;
7654 ctmp
->next
&& ctmp
->next
->var
== ctmp
->var
;
7655 ctmp
= next_confline(ctmp
))
7656 ctmp
->next
->d
.earb
= ctmp
->d
.earb
;
7663 * If the inherit nickname changed, we have to re-calculate the
7664 * global_vals and values for the action variables.
7665 * We may have to do the same if literal sig changed, too.
7668 calculate_inick_stuff(ps
);
7677 role_text_tool_inick(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7684 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7687 case MC_CHOICE
: /* Choose a role nickname */
7688 {void (*prev_screen
)(struct pine
*) = ps
->prev_screen
,
7689 (*redraw
)(void) = ps
->redrawer
;
7690 OPT_SCREEN_S
*saved_screen
;
7693 ps
->redrawer
= NULL
;
7694 ps
->next_screen
= SCREEN_FUN_NULL
;
7696 saved_screen
= opt_screen
;
7697 if(role_select_screen(ps
, &role
, 0) == 0){
7698 apval
= APVAL((*cl
)->var
, ew
);
7700 fs_give((void **)apval
);
7703 *apval
= (role
&& role
->nick
) ? cpystr(role
->nick
) : NULL
;
7706 fs_give((void **)&((*cl
)->value
));
7708 (*cl
)->value
= pretty_value(ps
, *cl
);
7712 ps
->next_screen
= prev_screen
;
7713 ps
->redrawer
= redraw
;
7717 opt_screen
= saved_screen
;
7720 ps
->mangled_screen
= 1;
7726 rv
= text_tool(ps
, cmd
, cl
, flags
);
7727 ps
->mangled_screen
= 1;
7731 rv
= text_tool(ps
, cmd
, cl
, flags
);
7736 * If the inherit nickname changed, we have to re-calculate the
7737 * global_vals and values for the action variables.
7738 * We may have to do the same if literal sig changed, too.
7741 calculate_inick_stuff(ps
);
7750 role_text_tool_kword(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7756 case MC_CHOICE
: /* Choose keywords from list and add them */
7757 {void (*prev_screen
)(struct pine
*) = ps
->prev_screen
,
7758 (*redraw
)(void) = ps
->redrawer
;
7759 OPT_SCREEN_S
*saved_screen
;
7763 ps
->redrawer
= NULL
;
7764 ps
->next_screen
= SCREEN_FUN_NULL
;
7766 saved_screen
= opt_screen
;
7768 if((kw
=choose_list_of_keywords()) != NULL
){
7769 for(i
= 0; kw
[i
]; i
++){
7770 esc
= add_roletake_escapes(kw
[i
]);
7771 fs_give((void **) &kw
[i
]);
7775 /* eliminate duplicates before the add */
7776 lval
= LVAL((*cl
)->var
, ew
);
7778 for(i
= 0; kw
[i
]; ){
7779 /* if kw[i] is a dup, eliminate it */
7780 for(j
= 0; lval
[j
]; j
++)
7781 if(!strcmp(kw
[i
], lval
[j
]))
7784 if(lval
[j
]){ /* it is a dup */
7785 for(j
= i
; kw
[j
]; j
++)
7794 config_add_list(ps
, cl
, kw
, NULL
, 0);
7796 fs_give((void **) &kw
);
7799 fs_give((void **) &((*cl
)->value
));
7801 (*cl
)->value
= pretty_value(ps
, *cl
);
7805 ps
->next_screen
= prev_screen
;
7806 ps
->redrawer
= redraw
;
7810 opt_screen
= saved_screen
;
7813 ps
->mangled_screen
= 1;
7820 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7821 ps
->mangled_screen
= 1;
7826 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7837 role_text_tool_charset(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7843 case MC_CHOICE
: /* Choose charsets from list and add them */
7844 {void (*prev_screen
)(struct pine
*) = ps
->prev_screen
,
7845 (*redraw
)(void) = ps
->redrawer
;
7846 OPT_SCREEN_S
*saved_screen
;
7850 ps
->redrawer
= NULL
;
7851 ps
->next_screen
= SCREEN_FUN_NULL
;
7853 saved_screen
= opt_screen
;
7855 if((kw
=choose_list_of_charsets()) != NULL
){
7856 for(i
= 0; kw
[i
]; i
++){
7857 esc
= add_roletake_escapes(kw
[i
]);
7858 fs_give((void **) &kw
[i
]);
7862 /* eliminate duplicates before the add */
7863 lval
= LVAL((*cl
)->var
, ew
);
7865 for(i
= 0; kw
[i
]; ){
7866 /* if kw[i] is a dup, eliminate it */
7867 for(j
= 0; lval
[j
]; j
++)
7868 if(!strcmp(kw
[i
], lval
[j
]))
7871 if(lval
[j
]){ /* it is a dup */
7872 for(j
= i
; kw
[j
]; j
++)
7881 config_add_list(ps
, cl
, kw
, NULL
, 0);
7883 fs_give((void **) &kw
);
7886 fs_give((void **) &((*cl
)->value
));
7888 (*cl
)->value
= pretty_value(ps
, *cl
);
7892 ps
->next_screen
= prev_screen
;
7893 ps
->redrawer
= redraw
;
7897 opt_screen
= saved_screen
;
7900 ps
->mangled_screen
= 1;
7907 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7908 ps
->mangled_screen
= 1;
7913 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7922 * Choose an address book nickname
7925 role_text_tool_afrom(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7931 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7934 case MC_CHOICE
: /* Choose an addressbook */
7935 {OPT_SCREEN_S
*saved_screen
;
7936 char *abook
= NULL
, *abookesc
= NULL
;
7938 ps
->redrawer
= NULL
;
7939 ps
->next_screen
= SCREEN_FUN_NULL
;
7940 saved_screen
= opt_screen
;
7942 abook
= abook_select_screen(ps
);
7944 abookesc
= add_comma_escapes(abook
);
7945 fs_give((void**) &abook
);
7948 ps
->mangled_screen
= 1;
7949 if(abookesc
&& *abookesc
&& (*cl
)->var
&& (*cl
)->var
->is_list
){
7952 ltmp
= (char **) fs_get(2 * sizeof(char *));
7958 config_add_list(ps
, cl
, ltmp
, NULL
, 0);
7961 fs_give((void **) <mp
);
7964 fs_give((void **) &((*cl
)->value
));
7966 (*cl
)->value
= pretty_value(ps
, *cl
);
7973 fs_give((void **) &abookesc
);
7975 opt_screen
= saved_screen
;
7978 ps
->mangled_screen
= 1;
7982 rv
= text_tool(ps
, cmd
, cl
, flags
);
7983 ps
->mangled_screen
= 1;
7992 * Args fmt -- a printf style fmt string with a single %s
7993 * buf -- place to put result, assumed large enough (strlen(fmt)+11)
7994 * rflags -- controls what goes in buf
7996 * Returns -- pointer to buf
7999 role_type_print(char *buf
, size_t buflen
, char *fmt
, long int rflags
)
8001 #define CASE_MIXED 1
8002 #define CASE_UPPER 2
8003 #define CASE_LOWER 3
8004 int cas
= CASE_UPPER
;
8005 int prev_word_is_a
= 0;
8008 /* find %sRule to see what case */
8009 if((p
= srchstr(fmt
, "%srule")) != NULL
){
8021 (p
[-2] == 'a' || p
[-2] == 'A')
8026 if(cas
== CASE_UPPER
)
8027 q
= (rflags
& ROLE_DO_INCOLS
) ? "INDEX COLOR " :
8028 (rflags
& ROLE_DO_FILTER
) ? "FILTERING " :
8029 (rflags
& ROLE_DO_SCORES
) ? "SCORING " :
8030 (rflags
& ROLE_DO_OTHER
) ? "OTHER " :
8031 (rflags
& ROLE_DO_SRCH
) ? "SEARCH " :
8032 (rflags
& ROLE_DO_ROLES
) ? "ROLE " : "";
8033 else if(cas
== CASE_LOWER
)
8034 q
= (rflags
& ROLE_DO_INCOLS
) ? "index color " :
8035 (rflags
& ROLE_DO_FILTER
) ? "filtering " :
8036 (rflags
& ROLE_DO_SCORES
) ? "scoring " :
8037 (rflags
& ROLE_DO_OTHER
) ? "other " :
8038 (rflags
& ROLE_DO_OTHER
) ? "search " :
8039 (rflags
& ROLE_DO_ROLES
) ? "role " : "";
8041 q
= (rflags
& ROLE_DO_INCOLS
) ? "Index Color " :
8042 (rflags
& ROLE_DO_FILTER
) ? "Filtering " :
8043 (rflags
& ROLE_DO_SCORES
) ? "Scoring " :
8044 (rflags
& ROLE_DO_OTHER
) ? "Other " :
8045 (rflags
& ROLE_DO_OTHER
) ? "Search " :
8046 (rflags
& ROLE_DO_ROLES
) ? "Role " : "";
8048 /* it ain't right to say "a index" */
8049 if(prev_word_is_a
&& !struncmp(q
, "index", 5))
8052 snprintf(buf
, buflen
, fmt
, q
);
8053 buf
[buflen
-1] = '\0';
8059 * filter option list manipulation tool
8062 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
8065 feat_checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
8070 case MC_TOGGLE
: /* mark/unmark option */
8072 toggle_feat_option_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, (*cl
)->value
);
8075 case MC_EXIT
: /* exit */
8076 rv
= role_filt_exitcheck(cl
, flags
);
8089 toggle_feat_option_bit(struct pine
*ps
, int index
, struct variable
*var
, char *value
)
8093 f
= feat_feature_list(index
);
8096 if(bitnset(f
->value
, feat_option_list
))
8097 clrbitn(f
->value
, feat_option_list
);
8099 setbitn(f
->value
, feat_option_list
);
8102 value
[1] = bitnset(f
->value
, feat_option_list
) ? 'X' : ' ';
8107 feat_feature_list(int index
)
8109 static NAMEVAL_S opt_feat_list
[] = {
8110 {"use-date-header-for-age", NULL
, FEAT_SENTDATE
},
8111 {"move-only-if-not-deleted", NULL
, FEAT_IFNOTDEL
},
8112 {"dont-stop-even-if-rule-matches", NULL
, FEAT_NONTERM
}
8115 return((index
>= 0 &&
8116 index
< (sizeof(opt_feat_list
)/sizeof(opt_feat_list
[0])))
8117 ? &opt_feat_list
[index
] : NULL
);
8122 * address type list manipulation tool
8125 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
8128 inabook_checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
8133 case MC_TOGGLE
: /* mark/unmark option */
8135 toggle_inabook_type_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, (*cl
)->value
);
8138 case MC_EXIT
: /* exit */
8139 rv
= role_filt_exitcheck(cl
, flags
);
8152 toggle_inabook_type_bit(struct pine
*ps
, int index
, struct variable
*var
, char *value
)
8156 f
= inabook_feature_list(index
);
8159 if(bitnset(f
->value
, inabook_type_list
))
8160 clrbitn(f
->value
, inabook_type_list
);
8162 setbitn(f
->value
, inabook_type_list
);
8165 value
[1] = bitnset(f
->value
, inabook_type_list
) ? 'X' : ' ';
8170 inabook_feature_list(int index
)
8172 static NAMEVAL_S inabook_feat_list
[] = {
8173 {"From", NULL
, INABOOK_FROM
},
8174 {"Reply-To", NULL
, INABOOK_REPLYTO
},
8175 {"Sender", NULL
, INABOOK_SENDER
},
8176 {"To", NULL
, INABOOK_TO
},
8177 {"Cc", NULL
, INABOOK_CC
}
8180 return((index
>= 0 &&
8181 index
< (sizeof(inabook_feat_list
)/sizeof(inabook_feat_list
[0])))
8182 ? &inabook_feat_list
[index
] : NULL
);