1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: roleconf.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2020 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
21 #include "colorconf.h"
23 #include "confscroll.h"
32 #include "../pith/state.h"
33 #include "../pith/conf.h"
34 #include "../pith/msgno.h"
35 #include "../pith/bitmap.h"
36 #include "../pith/sort.h"
37 #include "../pith/addrstring.h"
38 #include "../pith/list.h"
39 #include "../pith/flag.h"
40 #include "../pith/bldaddr.h"
41 #include "../pith/news.h"
42 #include "../pith/util.h"
43 #include "../pith/detoken.h"
44 #include "../pith/icache.h"
45 #include "../pith/ablookup.h"
46 #include "../pith/pattern.h"
47 #include "../pith/tempfile.h"
54 #define ARB_HELP _("HELP FOR ARBITRARY HEADER PATTERNS")
55 #define ADDXHDRS _("Add Extra Headers")
61 int role_select_tool(struct pine
*, int, CONF_S
**, unsigned);
62 PATTERN_S
*addrlst_to_pattern(ADDRESS
*);
63 void role_config_init_disp(struct pine
*, CONF_S
**, long, PAT_STATE
*);
64 void add_patline_to_display(struct pine
*, CONF_S
**, int, CONF_S
**, CONF_S
**, PAT_LINE_S
*, long);
65 void add_role_to_display(CONF_S
**, PAT_LINE_S
*, PAT_S
*, int, CONF_S
**, int, long);
66 void add_fake_first_role(CONF_S
**, int, long);
67 int role_config_tool(struct pine
*, int, CONF_S
**, unsigned);
68 int role_config_add(struct pine
*, CONF_S
**, long);
69 int role_config_replicate(struct pine
*, CONF_S
**, long);
70 int role_config_edit(struct pine
*, CONF_S
**, long);
71 int role_config_del(struct pine
*, CONF_S
**, long);
72 void delete_a_role(CONF_S
**, long);
73 int role_config_shuffle(struct pine
*, CONF_S
**);
74 int role_config_addfile(struct pine
*, CONF_S
**, long);
75 int role_config_delfile(struct pine
*, CONF_S
**, long);
76 void swap_literal_roles(CONF_S
*, CONF_S
*);
77 void swap_file_roles(CONF_S
*, CONF_S
*);
78 void move_role_into_file(CONF_S
**, int);
79 void move_role_outof_file(CONF_S
**, int);
80 void move_role_around_file(CONF_S
**, int);
81 int role_config_edit_screen(struct pine
*, PAT_S
*, char *, long, PAT_S
**);
82 void setup_dummy_pattern_var(struct variable
*, char *, PATTERN_S
*);
83 void setup_role_pat(struct pine
*, CONF_S
**, struct variable
*, HelpType
, char *,
85 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
87 void setup_role_pat_alt(struct pine
*, CONF_S
**, struct variable
*, HelpType
, char *,
89 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
91 void free_earb(EARB_S
**);
92 void calculate_inick_stuff(struct pine
*);
93 int check_role_folders(char **, unsigned);
94 void maybe_add_to_incoming(CONTEXT_S
*, char *);
95 int role_filt_exitcheck(CONF_S
**, unsigned);
96 int role_filt_text_tool(struct pine
*, int, CONF_S
**, unsigned);
97 int role_filt_addhdr_tool(struct pine
*, int, CONF_S
**, unsigned);
98 int role_addhdr_tool(struct pine
*, int, CONF_S
**, unsigned);
99 int role_filt_radiobutton_tool(struct pine
*, int, CONF_S
**, unsigned);
100 int role_sort_tool(struct pine
*, int, CONF_S
**, unsigned);
101 char **get_role_specific_folder(CONF_S
**);
102 int role_litsig_text_tool(struct pine
*, int, CONF_S
**, unsigned);
103 int role_cstm_text_tool(struct pine
*, int, CONF_S
**, unsigned);
104 int role_text_tool(struct pine
*, int, CONF_S
**, unsigned);
105 int role_text_tool_inick(struct pine
*, int, CONF_S
**, unsigned);
106 int role_text_tool_kword(struct pine
*, int, CONF_S
**, unsigned);
107 int role_text_tool_charset(struct pine
*, int, CONF_S
**, unsigned);
108 int role_text_tool_afrom(struct pine
*, int, CONF_S
**, unsigned);
109 char *role_type_print(char *, size_t, char *, long);
110 int feat_checkbox_tool(struct pine
*, int, CONF_S
**, unsigned);
111 void toggle_feat_option_bit(struct pine
*, int, struct variable
*, char *);
112 NAMEVAL_S
*feat_feature_list(int);
113 int inabook_checkbox_tool(struct pine
*, int, CONF_S
**, unsigned);
114 void toggle_inabook_type_bit(struct pine
*, int, struct variable
*, char *);
115 NAMEVAL_S
*inabook_feature_list(int);
118 static char *set_choose
= "--- --------------------";
119 static long role_global_flags
;
120 static PAT_STATE
*role_global_pstate
;
124 role_select_screen(struct pine
*ps
, ACTION_S
**role
, int alt_compose
)
126 CONF_S
*ctmp
= NULL
, *first_line
= NULL
;
128 PAT_S
*pat
, *sel_pat
= NULL
;
130 int change_default
= 0;
131 long rflags
= ROLE_DO_ROLES
;
141 if(!(nonempty_patterns(rflags
, &pstate
) &&
142 first_pattern(&pstate
))){
143 q_status_message(SM_ORDER
, 3, 3,
144 _("No roles available. Use Setup/Rules to add roles."));
150 menu_init_binding(&role_select_km
,
151 alt_compose
== MC_FORWARD
? 'F' :
152 alt_compose
== MC_REPLY
? 'R' :
153 alt_compose
== MC_COMPOSE
? 'C' : 'B',
155 alt_compose
== MC_FORWARD
? "F" :
156 alt_compose
== MC_REPLY
? "R" :
157 alt_compose
== MC_COMPOSE
? "C" : "B",
158 alt_compose
== MC_FORWARD
? "[" N_("ForwardAs") "]" :
159 alt_compose
== MC_REPLY
? "[" N_("ReplyAs") "]" :
160 alt_compose
== MC_COMPOSE
? "[" N_("ComposeAs") "]" : "[" N_("BounceAs") "]",
162 menu_add_binding(&role_select_km
, ctrl('J'), MC_CHOICE
);
163 menu_add_binding(&role_select_km
, ctrl('M'), MC_CHOICE
);
166 menu_init_binding(&role_select_km
, 'S', MC_CHOICE
, "S", "[" N_("Select") "]",
168 menu_add_binding(&role_select_km
, ctrl('J'), MC_CHOICE
);
169 menu_add_binding(&role_select_km
, ctrl('M'), MC_CHOICE
);
172 help
= h_role_select
;
173 if(alt_compose
== MC_BOUNCE
)
174 helptitle
= _("HELP FOR SELECTING A ROLE TO BOUNCE AS");
176 helptitle
= _("HELP FOR SELECTING A ROLE TO COMPOSE AS");
178 helptitle
= _("HELP FOR SELECTING A ROLE");
180 menu_init_binding(&role_select_km
, 'D', MC_TOGGLE
, "D", "changeDef", CHANGEDEF_KEY
);
182 for(pat
= first_pattern(&pstate
);
184 pat
= next_pattern(&pstate
)){
189 ctmp
->value
= cpystr((pat
->patgrp
&& pat
->patgrp
->nick
)
190 ? pat
->patgrp
->nick
: "?");
191 ctmp
->d
.r
.selected
= &sel_pat
;
193 ctmp
->d
.r
.change_def
= &change_default
;
194 ctmp
->keymenu
= &role_select_km
;
196 ctmp
->help_title
= helptitle
;
197 ctmp
->tool
= role_select_tool
;
198 ctmp
->flags
= CF_STARTITEM
;
202 memset(&screen
, 0, sizeof(screen
));
203 /* TRANSLATORS: Print something1 using something2.
204 "roles" is something1 */
205 (void)conf_scroll_screen(ps
, &screen
, first_line
, _("SELECT ROLE"),
206 _("roles"), 0, NULL
);
209 *role
= sel_pat
->action
;
210 if(change_default
== 1)
211 ps_global
->default_role
= *role
;
212 else if(change_default
== 2)
213 ps_global
->default_role
= NULL
;
218 ps
->mangled_screen
= 1;
224 role_select_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
226 int retval
= 0, newval
;
230 *((*cl
)->d
.r
.selected
) = (*cl
)->d
.r
.pat
;
231 retval
= simple_exit_cmd(flags
);
235 newval
= (*((*cl
)->d
.r
.change_def
) + 1) % 3;
236 *((*cl
)->d
.r
.change_def
) = newval
;
237 menu_init_binding((*cl
)->keymenu
, 'D', MC_TOGGLE
, "D",
238 (newval
== 0) ? "changeDef" : (newval
== 1) ? "removeDef" : "leaveDef",
241 if(ps_global
->default_role
)
242 q_status_message(SM_ORDER
, 0, 3,
243 _("Default role will be changed to the role you Select"));
245 q_status_message(SM_ORDER
, 0, 3,
246 _("Default role will be set to the role you Select"));
248 else if(newval
== 2){
249 q_status_message(SM_ORDER
, 0, 3, _("Default role will be unset"));
251 else{ /* newval == 0 */
252 if(ps_global
->default_role
)
253 q_status_message(SM_ORDER
, 0, 3, _("Default role will remain unchanged"));
255 q_status_message(SM_ORDER
, 0, 3, _("Default role will remain unset"));
258 ps
->mangled_footer
= 1;
263 retval
= simple_exit_cmd(flags
);
272 ps
->mangled_body
= 1;
279 role_config_screen(struct pine
*ps
, long int rflags
, int edit_exceptions
)
284 int readonly_warning
= 0;
286 struct variable
*v
= NULL
;
288 dprint((4, "role_config_screen()\n"));
290 if(ps
->fix_fixed_warning
)
291 offer_to_fix_pinerc(ps
);
293 ew
= edit_exceptions
? ps_global
->ew_for_except_vars
: Main
;
296 readonly_warning
= 1;
298 PINERC_S
*prc
= NULL
;
303 rflags
|= PAT_USE_MAIN
;
307 rflags
|= PAT_USE_POST
;
313 readonly_warning
= prc
? prc
->readonly
: 1;
314 if(prc
&& prc
->quit_to_edit
){
315 quit_to_edit_msg(prc
);
320 if(!any_patterns(rflags
, &pstate
))
323 if(rflags
& ROLE_DO_ROLES
)
324 v
= &ps_global
->vars
[V_PAT_ROLES
];
325 else if(rflags
& ROLE_DO_INCOLS
)
326 v
= &ps_global
->vars
[V_PAT_INCOLS
];
327 else if(rflags
& ROLE_DO_OTHER
)
328 v
= &ps_global
->vars
[V_PAT_OTHER
];
329 else if(rflags
& ROLE_DO_SCORES
)
330 v
= &ps_global
->vars
[V_PAT_SCORES
];
331 else if(rflags
& ROLE_DO_FILTER
)
332 v
= &ps_global
->vars
[V_PAT_FILTS
];
333 else if(rflags
& ROLE_DO_SRCH
)
334 v
= &ps_global
->vars
[V_PAT_SRCH
];
336 if((ps_global
->ew_for_except_vars
!= Main
) && (ew
== Main
)){
339 if((lval
=LVAL(v
, ps_global
->ew_for_except_vars
)) &&
340 lval
[0] && strcmp(INHERIT
, lval
[0]) != 0){
341 role_type_print(title
, sizeof(title
), _("Warning: \"%sRules\" are overridden in your exceptions configuration"), rflags
);
342 q_status_message(SM_ORDER
, 7, 7, title
);
346 role_type_print(title
, sizeof(title
), "%sRules", rflags
);
347 if(fixed_var(v
, "change", title
))
353 snprintf(title
, sizeof(title
), "SETUP%s ", edit_exceptions
? " EXCEPTIONAL" : "");
354 title
[sizeof(title
)-1] = '\0';
355 role_type_print(title
+strlen(title
), sizeof(title
)-strlen(title
), "%sRULES", rflags
);
356 role_global_flags
= rflags
;
357 role_global_pstate
= &pstate
;
358 role_config_init_disp(ps
, &first_line
, rflags
, &pstate
);
361 role_global_flags
= 0;
362 ps
->mangled_screen
= 1;
363 q_status_message(SM_ORDER
,5,5,
364 _("Unexpected problem: config file modified externally?"));
365 q_status_message1(SM_ORDER
,5,5,
366 _("Perhaps a newer version of pine was used to set variable \"%s\"?"),
368 dprint((1, "Unexpected problem: config file modified externally?\nPerhaps by a newer pine? Variable \"%s\" has unexpected contents.\n",
369 (v
&& v
->name
) ? v
->name
: "?"));
373 memset(&screen
, 0, sizeof(screen
));
374 screen
.deferred_ro_warning
= readonly_warning
;
375 /* TRANSLATORS: Print something1 using something2.
376 "rules" is something1 */
377 switch(conf_scroll_screen(ps
, &screen
, first_line
, title
, _("rules"), 0, NULL
)){
382 /* flush changes and re-read orig */
383 close_patterns(rflags
);
387 if(write_patterns(rflags
))
391 * Flush out current_vals of anything we've possibly changed.
394 if(ps_global
->default_role
){
395 q_status_message(SM_ORDER
,0,3, "Default role is unset");
396 ps_global
->default_role
= NULL
;
399 close_patterns((rflags
& ROLE_MASK
) | PAT_USE_CURRENT
);
401 /* scores may have changed */
402 if(rflags
& ROLE_DO_SCORES
){
406 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
407 m
= ps_global
->s_pool
.streams
[i
];
409 clear_folder_scores(m
);
410 clear_index_cache(m
, 0);
414 if(mn_get_sort(sp_msgmap(ps_global
->mail_stream
)) == SortScore
)
415 refresh_sort(ps_global
->mail_stream
,
416 sp_msgmap(ps_global
->mail_stream
), SRT_VRB
);
419 /* recalculate need for scores */
420 scores_are_used(SCOREUSE_INVALID
);
422 /* we may want to fetch more or fewer headers each fetch */
425 (void) mail_parameters(NULL
, SET_IMAPEXTRAHEADERS
,
426 (void *) get_extra_hdrs());
428 if(rflags
& ROLE_DO_INCOLS
&& pico_usingcolor())
429 clear_index_cache(ps_global
->mail_stream
, 0);
431 if(rflags
& ROLE_DO_FILTER
)
432 role_process_filters();
435 * ROLE_DO_OTHER is made up of a bunch of different variables
436 * that may have changed. Assume they all changed and fix them.
438 if(rflags
& ROLE_DO_OTHER
){
439 reset_index_format();
440 clear_index_cache(ps_global
->mail_stream
, 0);
441 if(!mn_get_mansort(ps_global
->msgmap
))
442 reset_sort_order(SRT_VRB
);
448 q_status_message(SM_ORDER
,7,10, "conf_scroll_screen unexpected ret");
452 role_global_flags
= 0;
453 ps
->mangled_screen
= 1;
458 * This is called from process_cmd to add a new pattern to the end of the
459 * list of patterns. The pattern is seeded with values from the current
463 role_take(struct pine
*ps
, MSGNO_S
*msgmap
, int rtype
)
465 PAT_S
*defpat
, *newpat
= NULL
;
466 PAT_LINE_S
*new_patline
, *patline
;
467 ENVELOPE
*env
= NULL
;
469 char *s
, title
[100], specific_fldr
[MAXPATH
+1];
473 dprint((4, "role_take()\n"));
475 if(mn_get_cur(msgmap
) > 0){
476 env
= pine_mail_fetchstructure(ps
->mail_stream
,
477 mn_m2raw(msgmap
, mn_get_cur(msgmap
)),
481 q_status_message(SM_ORDER
, 3, 7,
482 _("problem getting addresses from message"));
489 rflags
= ROLE_DO_ROLES
;
490 ew
= ps_global
->ew_for_role_take
;
493 rflags
= ROLE_DO_SCORES
;
494 ew
= ps_global
->ew_for_score_take
;
497 rflags
= ROLE_DO_INCOLS
;
498 ew
= ps_global
->ew_for_incol_take
;
501 rflags
= ROLE_DO_FILTER
;
502 ew
= ps_global
->ew_for_filter_take
;
505 rflags
= ROLE_DO_OTHER
;
506 ew
= ps_global
->ew_for_other_take
;
509 rflags
= ROLE_DO_SRCH
;
510 ew
= ps_global
->ew_for_srch_take
;
520 rflags
|= PAT_USE_MAIN
;
523 rflags
|= PAT_USE_POST
;
529 if(!any_patterns(rflags
, &pstate
)){
530 q_status_message(SM_ORDER
, 3, 7, _("problem accessing rules"));
534 /* set this so that even if we don't edit at all, we'll be asked */
535 rflags
|= ROLE_CHANGES
;
538 * Make a pattern out of the information in the envelope and
539 * use that as the default pattern we give to the role editor.
540 * It will have a pattern but no actions set.
542 defpat
= (PAT_S
*)fs_get(sizeof(*defpat
));
543 memset((void *)defpat
, 0, sizeof(*defpat
));
545 defpat
->patgrp
= (PATGRP_S
*)fs_get(sizeof(*defpat
->patgrp
));
546 memset((void *)defpat
->patgrp
, 0, sizeof(*defpat
->patgrp
));
550 defpat
->patgrp
->to
= addrlst_to_pattern(env
->to
);
553 defpat
->patgrp
->from
= addrlst_to_pattern(env
->from
);
556 defpat
->patgrp
->cc
= addrlst_to_pattern(env
->cc
);
559 (!env
->from
|| !address_is_same(env
->sender
, env
->from
)))
560 defpat
->patgrp
->sender
= addrlst_to_pattern(env
->sender
);
563 * Env->newsgroups is already comma-separated and there shouldn't be
564 * any commas or backslashes in newsgroup names, so we don't add the
568 defpat
->patgrp
->news
= string_to_pattern(env
->newsgroups
);
571 * Subject may have commas or backslashes, so we add escapes.
577 * Mail_strip_subject not only strips the Re's and Fwd's but
578 * it also canonicalizes to UTF-8.
580 mail_strip_subject(env
->subject
, &q
);
582 t
= add_roletake_escapes(q
);
583 fs_give((void **)&q
);
587 defpat
->patgrp
->subj
= string_to_pattern(t
);
588 fs_give((void **)&t
);
593 if(IS_NEWS(ps
->mail_stream
))
594 defpat
->patgrp
->fldr_type
= FLDR_NEWS
;
596 defpat
->patgrp
->fldr_type
= FLDR_EMAIL
;
598 specific_fldr
[0] = specific_fldr
[sizeof(specific_fldr
)-1] = '\0';
599 if(sp_flagged(ps
->mail_stream
, SP_INBOX
))
600 strncpy(specific_fldr
, ps_global
->inbox_name
, sizeof(specific_fldr
)-1);
601 else if(ps
->context_current
602 && ps
->context_current
->use
& CNTXT_INCMNG
&&
603 folder_is_nick(ps
->cur_folder
, FOLDERS(ps
->context_current
), 0))
604 strncpy(specific_fldr
, ps
->cur_folder
, sizeof(specific_fldr
)-1);
606 context_apply(specific_fldr
, ps
->context_current
, ps
->cur_folder
,
607 sizeof(specific_fldr
));
609 if(specific_fldr
[0]){
610 s
= add_comma_escapes(specific_fldr
);
613 defpat
->patgrp
->fldr_type
= FLDR_SPECIFIC
;
615 defpat
->patgrp
->folder
= string_to_pattern(s
);
616 fs_give((void **)&s
);
620 role_type_print(title
, sizeof(title
), "ADD NEW %sRULE", rflags
);
623 * Role_config_edit_screen is sometimes called as a tool or a sub
624 * routine called from a tool within conf_scroll_screen, but here it
625 * is going to be at the top-level (we're not inside conf_scroll_screen
626 * right now). It uses opt_screen to set the ro_warning bit. We need
627 * to let it know that we're at the top, which we do by setting
628 * opt_screen to NULL. Otherwise, the thing that opt_screen is pointing
629 * to is just random stack stuff from some previous conf_scroll_screen
630 * call which has already exited.
634 if(role_config_edit_screen(ps
, defpat
, title
, rflags
,
635 &newpat
) == 1 && newpat
){
637 if(ps
->never_allow_changing_from
&& newpat
->action
&&
638 newpat
->action
->from
)
639 q_status_message(SM_ORDER
|SM_DING
, 3, 7,
640 _("Site policy doesn't allow changing From address so From is ignored"));
642 if(rflags
& ROLE_DO_ROLES
&& newpat
->patgrp
&& newpat
->patgrp
->nick
){
645 for(pat
= first_pattern(&pstate
);
647 pat
= next_pattern(&pstate
)){
648 if(pat
->patgrp
&& pat
->patgrp
->nick
&&
649 !strucmp(pat
->patgrp
->nick
, newpat
->patgrp
->nick
)){
650 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of the new role is already in use."));
657 set_pathandle(rflags
);
659 /* need a new patline */
660 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
661 memset((void *)new_patline
, 0, sizeof(*new_patline
));
662 new_patline
->type
= Literal
;
663 (*cur_pat_h
)->dirtypinerc
= 1;
665 /* tie together with new pattern */
666 new_patline
->first
= new_patline
->last
= newpat
;
667 newpat
->patline
= new_patline
;
669 /* find last current patline */
670 for(patline
= (*cur_pat_h
)->patlinehead
;
671 patline
&& patline
->next
;
672 patline
= patline
->next
)
675 /* add new patline to end of list */
677 patline
->next
= new_patline
;
678 new_patline
->prev
= patline
;
681 (*cur_pat_h
)->patlinehead
= new_patline
;
683 if(write_patterns(rflags
) == 0){
687 * Flush out current_vals of anything we've possibly changed.
690 if(rflags
& ROLE_DO_ROLES
&& ps_global
->default_role
){
691 q_status_message(SM_ORDER
,0,3, "Default role is unset");
692 ps_global
->default_role
= NULL
;
695 close_patterns(rflags
| PAT_USE_CURRENT
);
697 role_type_print(msg
, sizeof(msg
), "New %srule saved", rflags
);
698 q_status_message(SM_ORDER
, 0, 3, msg
);
700 /* scores may have changed */
701 if(rflags
& ROLE_DO_SCORES
){
705 for(i
= 0; i
< ps_global
->s_pool
.nstream
; i
++){
706 m
= ps_global
->s_pool
.streams
[i
];
708 clear_folder_scores(m
);
709 clear_index_cache(m
, 0);
713 /* We've already bound msgmap to global mail_stream
714 * at the start of this function, but if we wanted to
715 * we could clean this up.
717 if(mn_get_sort(msgmap
) == SortScore
)
718 refresh_sort(ps_global
->mail_stream
, msgmap
, SRT_VRB
);
721 if(rflags
& ROLE_DO_FILTER
)
722 role_process_filters();
724 /* recalculate need for scores */
725 scores_are_used(SCOREUSE_INVALID
);
727 /* we may want to fetch more or fewer headers each fetch */
730 (void) mail_parameters(NULL
, SET_IMAPEXTRAHEADERS
,
731 (void *) get_extra_hdrs());
733 if(rflags
& ROLE_DO_INCOLS
&& pico_usingcolor())
734 clear_index_cache(ps_global
->mail_stream
, 0);
737 * ROLE_DO_OTHER is made up of a bunch of different variables
738 * that may have changed. Assume they all changed and fix them.
740 if(rflags
& ROLE_DO_OTHER
){
741 reset_index_format();
742 clear_index_cache(ps_global
->mail_stream
, 0);
743 if(!mn_get_mansort(msgmap
))
744 reset_sort_order(SRT_VRB
);
752 ps
->mangled_screen
= 1;
757 addrlst_to_pattern(struct mail_address
*addr
)
765 t
= s
= (char *) fs_get((l
+1) * sizeof(char));
768 u
= simple_addr_string(addr
, tmp_20k_buf
, SIZEOF_20KBUF
);
769 v
= add_roletake_escapes(u
);
772 sstrncpy(&t
, ",", l
-(t
-s
));
774 sstrncpy(&t
, v
, l
-(t
-s
));
775 fs_give((void **)&v
);
784 p
= string_to_pattern(s
);
786 fs_give((void **) &s
);
794 role_config_init_disp(struct pine
*ps
, CONF_S
**first_line
, long int rflags
, PAT_STATE
*pstate
)
798 int inherit
= 0, added_fake
= 0;
804 * Set cur_pat_h and manipulate directly.
806 set_pathandle(rflags
);
807 patline
= *cur_pat_h
? (*cur_pat_h
)->patlinehead
: NULL
;
808 if(patline
&& patline
->type
== Inherit
){
809 add_patline_to_display(ps
, &ctmp
, 0, first_line
, NULL
, patline
, rflags
);
810 patline
= patline
->next
;
814 add_fake_first_role(&ctmp
, 0, rflags
);
816 if(first_line
&& !*first_line
)
817 (*first_line
) = ctmp
;
820 for(; patline
; patline
= patline
->next
)
821 add_patline_to_display(ps
, &ctmp
, 0, first_line
, NULL
, patline
, rflags
);
824 * If there are no actual patterns so far, we need to have an Add line
825 * for the cursor to be on. This would happen if all of the patlines
826 * were File includes and none of the files contained patterns.
828 if(!first_pattern(role_global_pstate
) ||
829 ((inherit
=first_pattern(role_global_pstate
)->inherit
) &&
830 !next_pattern(role_global_pstate
))){
833 * Find the start and prepend the fake first role.
835 while(ctmp
&& ctmp
->prev
)
839 add_fake_first_role(&ctmp
, inherit
? 0 : 1, rflags
);
840 if(first_line
&& !*first_line
)
841 (*first_line
) = ctmp
;
848 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
)
851 int len
, firstitem
, wid
;
853 char buf
[6*MAX_SCREEN_COLS
+1];
855 /* put dashed line around file contents */
856 if(patline
->type
== File
){
861 * New_confline appends ctmp after old current instead of inserting
862 * it, so we have to adjust. We have
863 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
866 CONF_S
*a
, *b
, *c
, *p
;
871 a
= b
? b
->prev
: NULL
;
887 if(top_line
&& *top_line
== NULL
)
890 len
= strlen(patline
->filename
) + 100;
892 q
= (char *) fs_get((len
+ 1) * sizeof(char));
893 snprintf(q
, len
+1, "From file %s%s", patline
->filename
,
894 patline
->readonly
? " (ReadOnly)" : "");
897 if((wid
=utf8_width(q
)) > ps
->ttyo
->screen_cols
-2)
898 utf8_snprintf(buf
, sizeof(buf
), "--%.*w", ps
->ttyo
->screen_cols
-2, q
);
900 snprintf(buf
, sizeof(buf
), "--%s%s", q
, repeat_char(ps
->ttyo
->screen_cols
-2-wid
, '-'));
902 (*ctmp
)->value
= cpystr(buf
);
904 fs_give((void **)&q
);
905 (*ctmp
)->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
906 (*ctmp
)->d
.r
.patline
= patline
;
912 for(pat
= patline
->first
; pat
; pat
= pat
->next
){
914 /* Check that pattern has a role and is of right type */
917 (((rflags
& ROLE_DO_ROLES
) && pat
->action
->is_a_role
) ||
918 ((rflags
& ROLE_DO_INCOLS
) && pat
->action
->is_a_incol
) ||
919 ((rflags
& ROLE_DO_SRCH
) && pat
->action
->is_a_srch
) ||
920 ((rflags
& ROLE_DO_OTHER
) && pat
->action
->is_a_other
) ||
921 ((rflags
& ROLE_DO_SCORES
) && pat
->action
->is_a_score
) ||
922 ((rflags
& ROLE_DO_FILTER
) && pat
->action
->is_a_filter
)))){
923 add_role_to_display(ctmp
, patline
, pat
, 0,
924 (first_line
&& *first_line
== NULL
)
926 (top_line
&& *top_line
== NULL
)
930 if(top_line
&& *top_line
== NULL
&& first_line
)
931 *top_line
= *first_line
;
936 if(patline
->type
== File
){
938 len
= strlen(patline
->filename
) + 100;
940 q
= (char *) fs_get((len
+ 1) * sizeof(char));
941 snprintf(q
, len
+1, "End of Rules from %s", patline
->filename
);
944 if((wid
=utf8_width(q
)) > ps
->ttyo
->screen_cols
-2)
945 utf8_snprintf(buf
, sizeof(buf
), "--%.*w", ps
->ttyo
->screen_cols
-2, q
);
947 snprintf(buf
, sizeof(buf
), "--%s%s", q
, repeat_char(ps
->ttyo
->screen_cols
-2-wid
, '-'));
949 (*ctmp
)->value
= cpystr(buf
);
951 fs_give((void **)&q
);
952 (*ctmp
)->flags
|= CF_NOSELECT
;
953 (*ctmp
)->d
.r
.patline
= patline
;
959 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
)
963 if(!(pat
&& (pat
->action
|| pat
->inherit
)))
967 if(first_line
&& !pat
->inherit
)
972 * New_confline appends ctmp after old current instead of inserting
973 * it, so we have to adjust. We have
974 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
977 CONF_S
*a
, *b
, *c
, *p
;
982 a
= b
? b
->prev
: NULL
;
998 role_type_print(title
, sizeof(title
), _("HELP FOR %sRULE CONFIGURATION"), rflags
);
1001 (*ctmp
)->flags
|= ((firstitem
? CF_STARTITEM
: 0) |
1002 CF_NOSELECT
| CF_INHERIT
);
1005 (*ctmp
)->flags
|= (firstitem
? CF_STARTITEM
: 0);
1006 (*ctmp
)->value
= cpystr((pat
&& pat
->patgrp
&& pat
->patgrp
->nick
)
1007 ? pat
->patgrp
->nick
: "?");
1010 (*ctmp
)->d
.r
.patline
= patline
;
1011 (*ctmp
)->d
.r
.pat
= pat
;
1012 (*ctmp
)->keymenu
= &role_conf_km
;
1013 (*ctmp
)->help
= (rflags
& ROLE_DO_INCOLS
) ? h_rules_incols
:
1014 (rflags
& ROLE_DO_OTHER
) ? h_rules_other
:
1015 (rflags
& ROLE_DO_FILTER
) ? h_rules_filter
:
1016 (rflags
& ROLE_DO_SCORES
) ? h_rules_score
:
1017 (rflags
& ROLE_DO_ROLES
) ? h_rules_roles
:
1018 (rflags
& ROLE_DO_SRCH
) ? h_rules_srch
:
1020 (*ctmp
)->help_title
= title
;
1021 (*ctmp
)->tool
= role_config_tool
;
1022 (*ctmp
)->valoffset
= 4;
1027 add_fake_first_role(CONF_S
**ctmp
, int before
, long int rflags
)
1036 * New_confline appends ctmp after old current instead of inserting
1037 * it, so we have to adjust. We have
1038 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
1041 CONF_S
*a
, *b
, *c
, *p
;
1046 a
= b
? b
->prev
: NULL
;
1062 role_type_print(title
, sizeof(title
), _("HELP FOR %sRULE CONFIGURATION"), rflags
);
1063 role_type_print(add
, sizeof(add
), _("Use Add to add a %sRule"), rflags
);
1065 (*ctmp
)->value
= cpystr(add
);
1066 (*ctmp
)->keymenu
= &role_conf_km
;
1067 (*ctmp
)->help
= (rflags
& ROLE_DO_INCOLS
) ? h_rules_incols
:
1068 (rflags
& ROLE_DO_OTHER
) ? h_rules_other
:
1069 (rflags
& ROLE_DO_FILTER
) ? h_rules_filter
:
1070 (rflags
& ROLE_DO_SCORES
) ? h_rules_score
:
1071 (rflags
& ROLE_DO_ROLES
) ? h_rules_roles
:
1072 (rflags
& ROLE_DO_SRCH
) ? h_rules_srch
:
1074 (*ctmp
)->help_title
= title
;
1075 (*ctmp
)->tool
= role_config_tool
;
1076 (*ctmp
)->flags
|= CF_STARTITEM
;
1077 (*ctmp
)->valoffset
= 4;
1082 role_config_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
1084 int first_one
= 0, rv
= 0;
1088 if(!(pat
= first_pattern(role_global_pstate
)) ||
1089 (pat
->inherit
&& !next_pattern(role_global_pstate
)))
1095 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1096 _("Nothing to Delete, use Add"));
1098 rv
= role_config_del(ps
, cl
, role_global_flags
);
1103 rv
= role_config_add(ps
, cl
, role_global_flags
);
1108 rv
= role_config_add(ps
, cl
, role_global_flags
);
1110 rv
= role_config_edit(ps
, cl
, role_global_flags
);
1116 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1117 _("Nothing to Shuffle, use Add"));
1119 rv
= role_config_shuffle(ps
, cl
);
1124 role_type_print(exitpmt
, sizeof(exitpmt
), "%sRule Setup", role_global_flags
);
1125 rv
= screen_exit_cmd(flags
, exitpmt
);
1129 rv
= role_config_addfile(ps
, cl
, role_global_flags
);
1133 rv
= role_config_delfile(ps
, cl
, role_global_flags
);
1138 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1139 _("Nothing to Replicate, use Add"));
1141 rv
= role_config_replicate(ps
, cl
, role_global_flags
);
1157 * Returns 1 -- There were changes
1161 role_config_add(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1163 int rv
= 0, first_pat
= 0;
1164 PAT_S
*new_pat
= NULL
, *cur_pat
;
1165 PAT_LINE_S
*new_patline
, *cur_patline
;
1169 if((*cl
)->d
.r
.patline
&&
1170 (*cl
)->d
.r
.patline
->readonly
1171 && (*cl
)->d
.r
.patline
->type
== File
){
1172 q_status_message(SM_ORDER
, 0, 3, _("Can't add rule to ReadOnly file"));
1176 role_type_print(title
, sizeof(title
), "ADD A %sRULE", rflags
);
1178 if(role_config_edit_screen(ps
, NULL
, title
, rflags
,
1179 &new_pat
) == 1 && new_pat
){
1180 if(ps
->never_allow_changing_from
&&
1182 new_pat
->action
->from
)
1183 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1184 _("Site policy doesn't allow changing From address so From is ignored"));
1186 if(rflags
& ROLE_DO_ROLES
&&
1188 new_pat
->patgrp
->nick
&&
1189 nonempty_patterns(ROLE_DO_ROLES
, &pstate
)){
1192 for(pat
= first_pattern(&pstate
);
1194 pat
= next_pattern(&pstate
)){
1195 if(pat
->patgrp
&& pat
->patgrp
->nick
&&
1196 !strucmp(pat
->patgrp
->nick
, new_pat
->patgrp
->nick
)){
1197 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of the new role is already in use."));
1204 cur_pat
= (*cl
)->d
.r
.pat
;
1208 set_pathandle(rflags
);
1209 cur_patline
= first_pat
? (*cur_pat_h
)->patlinehead
: cur_pat
->patline
;
1211 /* need a new pat_line */
1212 if(first_pat
|| (cur_patline
&& cur_patline
->type
== Literal
)){
1213 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
1214 memset((void *)new_patline
, 0, sizeof(*new_patline
));
1215 new_patline
->type
= Literal
;
1216 (*cur_pat_h
)->dirtypinerc
= 1;
1220 if(first_pat
|| cur_patline
->type
== Literal
){
1221 new_patline
->prev
= cur_patline
;
1222 new_patline
->next
= cur_patline
->next
;
1223 if(cur_patline
->next
)
1224 cur_patline
->next
->prev
= new_patline
;
1226 cur_patline
->next
= new_patline
;
1228 /* tie new patline and new pat together */
1229 new_pat
->patline
= new_patline
;
1230 new_patline
->first
= new_patline
->last
= new_pat
;
1232 else if(cur_patline
->type
== File
){ /* don't need a new pat_line */
1234 new_pat
->patline
= cur_patline
;
1235 cur_patline
->dirty
= 1;
1237 /* Splice new_pat after cur_pat */
1238 new_pat
->prev
= cur_pat
;
1239 new_pat
->next
= cur_pat
->next
;
1241 cur_pat
->next
->prev
= new_pat
;
1243 cur_patline
->last
= new_pat
;
1245 cur_pat
->next
= new_pat
;
1249 /* tie new first patline and pat together */
1250 new_pat
->patline
= new_patline
;
1251 new_patline
->first
= new_patline
->last
= new_pat
;
1253 /* set head of list */
1254 (*cur_pat_h
)->patlinehead
= new_patline
;
1258 * If this is the first role, we replace the "Use Add" fake role
1259 * with this real one.
1262 /* Adjust conf_scroll_screen variables */
1263 (*cl
)->d
.r
.pat
= new_pat
;
1264 (*cl
)->d
.r
.patline
= new_pat
->patline
;
1266 fs_give((void **)&(*cl
)->value
);
1268 (*cl
)->value
= cpystr((new_pat
&& new_pat
->patgrp
&&
1269 new_pat
->patgrp
->nick
)
1270 ? new_pat
->patgrp
->nick
: "?");
1272 /* Else we are inserting a new role after the cur role */
1274 add_role_to_display(cl
, new_pat
->patline
, new_pat
, 0, NULL
,
1285 * Returns 1 -- There were changes
1289 role_config_replicate(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1291 int rv
= 0, first_pat
= 0;
1292 PAT_S
*new_pat
= NULL
, *cur_pat
, *defpat
= NULL
;
1293 PAT_LINE_S
*new_patline
, *cur_patline
;
1297 if((*cl
)->d
.r
.patline
&&
1298 (*cl
)->d
.r
.patline
->readonly
1299 && (*cl
)->d
.r
.patline
->type
== File
){
1300 q_status_message(SM_ORDER
, 0, 3, _("Can't add rule to ReadOnly file"));
1304 if((*cl
)->d
.r
.pat
&& (defpat
= copy_pat((*cl
)->d
.r
.pat
))){
1305 /* change nickname */
1306 if(defpat
->patgrp
&& defpat
->patgrp
->nick
){
1307 #define CLONEWORD " Copy"
1308 char *oldnick
= defpat
->patgrp
->nick
;
1311 len
= strlen(oldnick
)+strlen(CLONEWORD
);
1312 defpat
->patgrp
->nick
= (char *)fs_get((len
+1) * sizeof(char));
1313 strncpy(defpat
->patgrp
->nick
, oldnick
, len
);
1314 defpat
->patgrp
->nick
[len
] = '\0';
1315 strncat(defpat
->patgrp
->nick
, CLONEWORD
,
1316 len
+1-1-strlen(defpat
->patgrp
->nick
));
1317 fs_give((void **)&oldnick
);
1319 if(defpat
->action
->nick
)
1320 fs_give((void **)&defpat
->action
->nick
);
1322 defpat
->action
->nick
= cpystr(defpat
->patgrp
->nick
);
1326 /* set this so that even if we don't edit at all, we'll be asked */
1327 rflags
|= ROLE_CHANGES
;
1329 role_type_print(title
, sizeof(title
), "CHANGE THIS %sRULE", rflags
);
1331 if(role_config_edit_screen(ps
, defpat
, title
, rflags
,
1332 &new_pat
) == 1 && new_pat
){
1334 if(ps
->never_allow_changing_from
&&
1336 new_pat
->action
->from
)
1337 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1338 _("Site policy doesn't allow changing From address so From is ignored"));
1340 if(rflags
& ROLE_DO_ROLES
&&
1342 new_pat
->patgrp
->nick
&&
1343 nonempty_patterns(ROLE_DO_ROLES
, &pstate
)){
1346 for(pat
= first_pattern(&pstate
);
1348 pat
= next_pattern(&pstate
)){
1349 if(pat
->patgrp
&& pat
->patgrp
->nick
&&
1350 !strucmp(pat
->patgrp
->nick
, new_pat
->patgrp
->nick
)){
1351 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of the new role is already in use."));
1358 cur_pat
= (*cl
)->d
.r
.pat
;
1362 set_pathandle(rflags
);
1363 cur_patline
= first_pat
? (*cur_pat_h
)->patlinehead
: cur_pat
->patline
;
1365 /* need a new pat_line */
1366 if(first_pat
|| (cur_patline
&& cur_patline
->type
== Literal
)){
1367 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
1368 memset((void *)new_patline
, 0, sizeof(*new_patline
));
1369 new_patline
->type
= Literal
;
1370 (*cur_pat_h
)->dirtypinerc
= 1;
1374 if(first_pat
|| cur_patline
->type
== Literal
){
1375 new_patline
->prev
= cur_patline
;
1376 new_patline
->next
= cur_patline
->next
;
1377 if(cur_patline
->next
)
1378 cur_patline
->next
->prev
= new_patline
;
1380 cur_patline
->next
= new_patline
;
1382 /* tie new patline and new pat together */
1383 new_pat
->patline
= new_patline
;
1384 new_patline
->first
= new_patline
->last
= new_pat
;
1386 else if(cur_patline
->type
== File
){ /* don't need a new pat_line */
1388 new_pat
->patline
= cur_patline
;
1389 cur_patline
->dirty
= 1;
1391 /* Splice new_pat after cur_pat */
1392 new_pat
->prev
= cur_pat
;
1393 new_pat
->next
= cur_pat
->next
;
1395 cur_pat
->next
->prev
= new_pat
;
1397 cur_patline
->last
= new_pat
;
1399 cur_pat
->next
= new_pat
;
1403 /* tie new first patline and pat together */
1404 new_pat
->patline
= new_patline
;
1405 new_patline
->first
= new_patline
->last
= new_pat
;
1407 /* set head of list */
1408 (*cur_pat_h
)->patlinehead
= new_patline
;
1412 * If this is the first role, we replace the "Use Add" fake role
1413 * with this real one.
1416 /* Adjust conf_scroll_screen variables */
1417 (*cl
)->d
.r
.pat
= new_pat
;
1418 (*cl
)->d
.r
.patline
= new_pat
->patline
;
1420 fs_give((void **)&(*cl
)->value
);
1422 (*cl
)->value
= cpystr((new_pat
&& new_pat
->patgrp
&&
1423 new_pat
->patgrp
->nick
)
1424 ? new_pat
->patgrp
->nick
: "?");
1426 /* Else we are inserting a new role after the cur role */
1428 add_role_to_display(cl
, new_pat
->patline
, new_pat
, 0, NULL
,
1441 * Change the current role.
1443 * Returns 1 -- There were changes
1447 role_config_edit(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1450 PAT_S
*new_pat
= NULL
, *cur_pat
;
1453 if((*cl
)->d
.r
.patline
->readonly
){
1454 q_status_message(SM_ORDER
, 0, 3, _("Can't change ReadOnly rule"));
1458 cur_pat
= (*cl
)->d
.r
.pat
;
1460 role_type_print(title
, sizeof(title
), "CHANGE THIS %sRULE", rflags
);
1462 if(role_config_edit_screen(ps
, cur_pat
, title
,
1463 rflags
, &new_pat
) == 1 && new_pat
){
1465 if(ps
->never_allow_changing_from
&&
1467 new_pat
->action
->from
)
1468 q_status_message(SM_ORDER
|SM_DING
, 0, 3,
1469 _("Site policy doesn't allow changing From address so From is ignored"));
1471 if(rflags
& ROLE_DO_ROLES
&& new_pat
->patgrp
&& new_pat
->patgrp
->nick
){
1474 for(pat
= first_pattern(role_global_pstate
);
1476 pat
= next_pattern(role_global_pstate
)){
1477 if(pat
->patgrp
&& pat
->patgrp
->nick
&& pat
!= cur_pat
&&
1478 !strucmp(pat
->patgrp
->nick
, new_pat
->patgrp
->nick
)){
1479 q_status_message(SM_ORDER
|SM_DING
, 3, 7, _("Warning: The nickname of this role is also used for another role."));
1488 * Splice in new_pat in place of cur_pat
1492 cur_pat
->prev
->next
= new_pat
;
1495 cur_pat
->next
->prev
= new_pat
;
1497 new_pat
->prev
= cur_pat
->prev
;
1498 new_pat
->next
= cur_pat
->next
;
1500 /* tie together patline and pat (new_pat gets patline in editor) */
1501 if(new_pat
->patline
->first
== cur_pat
)
1502 new_pat
->patline
->first
= new_pat
;
1504 if(new_pat
->patline
->last
== cur_pat
)
1505 new_pat
->patline
->last
= new_pat
;
1507 if(new_pat
->patline
->type
== Literal
){
1508 set_pathandle(rflags
);
1510 (*cur_pat_h
)->dirtypinerc
= 1;
1513 new_pat
->patline
->dirty
= 1;
1515 cur_pat
->next
= NULL
;
1518 /* Adjust conf_scroll_screen variables */
1519 (*cl
)->d
.r
.pat
= new_pat
;
1520 (*cl
)->d
.r
.patline
= new_pat
->patline
;
1522 fs_give((void **)&(*cl
)->value
);
1524 (*cl
)->value
= cpystr((new_pat
->patgrp
&& new_pat
->patgrp
->nick
)
1525 ? new_pat
->patgrp
->nick
: "?");
1535 * Returns 1 -- There were changes
1539 role_config_del(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1545 if((*cl
)->d
.r
.patline
->readonly
){
1546 q_status_message(SM_ORDER
, 0, 3, _("Can't delete ReadOnly rule"));
1550 role_type_print(msg
, sizeof(msg
), _("Really delete %srule"), rflags
);
1551 snprintf(prompt
, sizeof(prompt
), "%s \"%s\" ", msg
, (*cl
)->value
);
1552 prompt
[sizeof(prompt
)-1] = '\0';
1554 ps
->mangled_footer
= 1;
1555 if(want_to(prompt
,'n','n',h_config_role_del
, WT_FLUSH_IN
) == 'y'){
1556 rv
= ps
->mangled_body
= 1;
1557 delete_a_role(cl
, rflags
);
1560 q_status_message(SM_ORDER
, 0, 3, _("Rule not deleted"));
1567 delete_a_role(CONF_S
**cl
, long int rflags
)
1571 PAT_LINE_S
*cur_patline
;
1574 cur_pat
= (*cl
)->d
.r
.pat
;
1575 cur_patline
= (*cl
)->d
.r
.patline
;
1577 if(cur_patline
->type
== Literal
){ /* delete patline */
1578 set_pathandle(rflags
);
1579 if(cur_patline
->prev
)
1580 cur_patline
->prev
->next
= cur_patline
->next
;
1582 if(*cur_pat_h
) /* this has to be true */
1583 (*cur_pat_h
)->patlinehead
= cur_patline
->next
;
1586 if(cur_patline
->next
)
1587 cur_patline
->next
->prev
= cur_patline
->prev
;
1589 if(*cur_pat_h
) /* this has to be true */
1590 (*cur_pat_h
)->dirtypinerc
= 1;
1592 cur_patline
->next
= NULL
;
1593 free_patline(&cur_patline
);
1595 else if(cur_patline
->type
== File
){ /* or delete pat */
1597 cur_pat
->prev
->next
= cur_pat
->next
;
1599 cur_patline
->first
= cur_pat
->next
;
1602 cur_pat
->next
->prev
= cur_pat
->prev
;
1604 cur_patline
->last
= cur_pat
->prev
;
1606 cur_patline
->dirty
= 1;
1608 cur_pat
->next
= NULL
;
1612 /* delete the conf line */
1614 /* deleting last real rule */
1615 if(!first_pattern(role_global_pstate
) ||
1616 ((inherit
=first_pattern(role_global_pstate
)->inherit
) &&
1617 !next_pattern(role_global_pstate
))){
1622 * Find the start and prepend the fake first role.
1624 while(*cl
&& (*cl
)->prev
)
1627 add_fake_first_role(cl
, inherit
? 0 : 1, rflags
);
1629 opt_screen
->top_line
= (*cl
);
1630 opt_screen
->current
= (*cl
);
1633 /* find next selectable line */
1634 for(cp
= (*cl
)->next
;
1635 cp
&& (cp
->flags
& CF_NOSELECT
);
1639 if(!cp
){ /* no next selectable, find previous selectable */
1640 if(*cl
== opt_screen
->top_line
)
1641 opt_screen
->top_line
= (*cl
)->prev
;
1643 for(cp
= (*cl
)->prev
;
1644 cp
&& (cp
->flags
& CF_NOSELECT
);
1648 else if(*cl
== opt_screen
->top_line
)
1649 opt_screen
->top_line
= (*cl
)->next
;
1659 * Shuffle the current role up or down.
1661 * Returns 1 -- There were changes
1665 role_config_shuffle(struct pine
*ps
, CONF_S
**cl
)
1667 int rv
= 0, deefault
, i
;
1668 int readonlyabove
= 0, readonlybelow
= 0;
1673 PAT_TYPE curtype
, prevtype
, nexttype
;
1675 if(!((*cl
)->prev
|| (*cl
)->next
)){
1676 q_status_message(SM_ORDER
, 0, 3,
1677 _("Shuffle only makes sense when there is more than one rule defined"));
1681 /* Move it up or down? */
1686 opts
[i
++].label
= N_("Up");
1691 opts
[i
++].label
= N_("Down");
1696 opts
[i
++].label
= N_("Before File");
1701 opts
[i
++].label
= N_("After File");
1706 curtype
= ((*cl
)->d
.r
.patline
) ? (*cl
)->d
.r
.patline
->type
: TypeNotSet
;
1708 prevtype
= ((*cl
)->prev
&& (*cl
)->prev
->d
.r
.patline
)
1709 ? (*cl
)->prev
->d
.r
.patline
->type
: TypeNotSet
;
1710 if(curtype
== File
&& prevtype
== File
&& (*cl
)->prev
->d
.r
.pat
== NULL
)
1711 prevtype
= TypeNotSet
;
1713 nexttype
= ((*cl
)->next
&& (*cl
)->next
->d
.r
.patline
)
1714 ? (*cl
)->next
->d
.r
.patline
->type
: TypeNotSet
;
1715 if(curtype
== File
&& nexttype
== File
&& (*cl
)->next
->d
.r
.pat
== NULL
)
1716 nexttype
= TypeNotSet
;
1719 if(curtype
== Literal
){
1720 if(prevtype
== TypeNotSet
||
1721 prevtype
== Inherit
){ /* no up, at top */
1726 else if(prevtype
== Literal
){ /* regular up */
1729 else if(prevtype
== File
){ /* file above us */
1730 if((*cl
)->prev
->d
.r
.patline
->readonly
)
1734 if(nexttype
== TypeNotSet
){ /* no down, at bottom */
1738 else if(nexttype
== Literal
){ /* regular down */
1741 else if(nexttype
== File
){ /* file below us */
1742 if((*cl
)->next
->d
.r
.patline
->readonly
)
1746 else if(curtype
== File
){
1747 if((*cl
)->d
.r
.patline
&& (*cl
)->d
.r
.patline
->readonly
){
1748 q_status_message(SM_ORDER
, 0, 3, _("Can't change ReadOnly file"));
1756 q_status_message(SM_ORDER
, 0, 3,
1757 "Programming Error: unknown line type in role_shuffle");
1761 snprintf(tmp
, sizeof(tmp
), "Shuffle \"%s\" %s%s%s%s%s%s%s ? ",
1763 (opts
[0].ch
!= -2) ? N_("UP") : "",
1764 (opts
[0].ch
!= -2 && opts
[1].ch
!= -2) ? " or " : "",
1765 (opts
[1].ch
!= -2) ? N_("DOWN") : "",
1766 ((opts
[0].ch
!= -2 ||
1767 opts
[1].ch
!= -2) && opts
[2].ch
!= -2) ? " or " : "",
1768 (opts
[2].ch
!= -2) ? N_("BEFORE") : "",
1769 ((opts
[0].ch
!= -2 ||
1771 opts
[2].ch
!= -2) && opts
[3].ch
!= -2) ? " or " : "",
1772 (opts
[3].ch
!= -2) ? N_("AFTER") : "");
1773 tmp
[sizeof(tmp
)-1] = '\0';
1775 help
= (opts
[0].ch
== -2) ? h_role_shuf_down
1776 : (opts
[1].ch
== -2) ? h_role_shuf_up
1779 rv
= radio_buttons(tmp
, -FOOTER_ROWS(ps
), opts
, deefault
, 'x',
1783 cmd_cancelled("Shuffle");
1787 if((readonlyabove
&& rv
== 'u' && curtype
!= prevtype
) ||
1788 (readonlybelow
&& rv
== 'd' && curtype
!= nexttype
)){
1789 q_status_message(SM_ORDER
, 0, 3, _("Can't shuffle into ReadOnly file"));
1793 if(rv
== 'u' && curtype
== Literal
&& prevtype
== Literal
){
1797 if(a
== opt_screen
->top_line
)
1798 opt_screen
->top_line
= b
;
1800 swap_literal_roles(a
, b
);
1801 ps
->mangled_body
= 1;
1803 else if(rv
== 'd' && curtype
== Literal
&& nexttype
== Literal
){
1807 if(a
== opt_screen
->top_line
)
1808 opt_screen
->top_line
= b
;
1810 swap_literal_roles(a
, b
);
1811 ps
->mangled_body
= 1;
1813 else if(rv
== 'u' && curtype
== File
&& prevtype
== File
){
1817 if(a
== opt_screen
->top_line
)
1818 opt_screen
->top_line
= b
;
1820 swap_file_roles(a
, b
);
1821 ps
->mangled_body
= 1;
1823 else if(rv
== 'u' && curtype
== File
){
1825 move_role_outof_file(cl
, 1);
1826 ps
->mangled_body
= 1;
1828 else if(rv
== 'd' && curtype
== File
&& nexttype
== File
){
1832 if(a
== opt_screen
->top_line
)
1833 opt_screen
->top_line
= b
;
1835 swap_file_roles(a
, b
);
1836 ps
->mangled_body
= 1;
1838 else if(rv
== 'd' && curtype
== File
){
1840 if(*cl
== opt_screen
->top_line
)
1841 opt_screen
->top_line
= (*cl
)->next
;
1843 move_role_outof_file(cl
, 0);
1844 ps
->mangled_body
= 1;
1846 else if(rv
== 'u' && curtype
== Literal
&& prevtype
== File
){
1848 move_role_into_file(cl
, 1);
1849 ps
->mangled_body
= 1;
1851 else if(rv
== 'd' && curtype
== Literal
&& nexttype
== File
){
1853 if(*cl
== opt_screen
->top_line
)
1854 opt_screen
->top_line
= (*cl
)->next
;
1856 move_role_into_file(cl
, 0);
1857 ps
->mangled_body
= 1;
1861 move_role_around_file(cl
, 1);
1862 ps
->mangled_body
= 1;
1866 if(*cl
== opt_screen
->top_line
)
1867 opt_screen
->top_line
= (*cl
)->next
;
1869 move_role_around_file(cl
, 0);
1870 ps
->mangled_body
= 1;
1878 role_config_addfile(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
1880 char filename
[MAXPATH
+1], full_filename
[MAXPATH
+1];
1881 char dir2
[MAXPATH
+1], pdir
[MAXPATH
+1];
1882 char *lc
, *newfile
= NULL
;
1883 PAT_LINE_S
*file_patline
;
1886 HelpType help
= NO_HELP
;
1888 CONF_S
*first_line
= NULL
, *add_line
, *save_current
;
1889 struct variable
*vars
= ps
->vars
;
1892 q_status_message(SM_ORDER
, 0, 3, "Alpine demo can't read files");
1896 curtype
= ((*cl
)->d
.r
.patline
&& (*cl
)->d
.r
.patline
)
1897 ? (*cl
)->d
.r
.patline
->type
: TypeNotSet
;
1899 if(curtype
== File
){
1900 q_status_message(SM_ORDER
, 0, 3, _("Current rule is already part of a file. Move outside any files first."));
1905 * Parse_pattern_file uses signature_path to figure out where to look
1906 * for the file. In signature_path we read signature files relative
1907 * to the pinerc dir, so if user selects one that is in there we'll
1908 * use relative instead of absolute, so it looks nicer.
1912 strncpy(pdir
, VAR_OPER_DIR
, sizeof(pdir
)-1);
1913 pdir
[sizeof(pdir
)-1] = '\0';
1914 len
= strlen(pdir
) + 1;
1916 else if((lc
= last_cmpnt(ps
->pinerc
)) != NULL
){
1917 strncpy(pdir
, ps
->pinerc
, MIN(sizeof(pdir
)-1,lc
-ps
->pinerc
));
1918 pdir
[MIN(sizeof(pdir
)-1, lc
-ps
->pinerc
)] = '\0';
1922 strncpy(dir2
, pdir
, sizeof(dir2
)-1);
1923 dir2
[sizeof(dir2
)-1] = '\0';
1925 full_filename
[0] = '\0';
1926 ps
->mangled_footer
= 1;
1929 flags
= OE_APPEND_CURRENT
;
1930 r
= optionally_enter(filename
, -FOOTER_ROWS(ps
), 0, sizeof(filename
),
1931 "Name of file to be added to rules: ",
1932 NULL
, help
, &flags
);
1935 help
= (help
== NO_HELP
) ? h_config_role_addfile
: NO_HELP
;
1938 else if(r
== 10 || r
== 11){ /* Browser or File Completion */
1941 else if(r
== 1 || (r
== 0 && filename
[0] == '\0')){
1942 cmd_cancelled("IncludeFile");
1953 removing_leading_and_trailing_white_space(filename
);
1954 if(is_absolute_path(filename
))
1955 newfile
= cpystr(filename
);
1957 build_path(full_filename
, dir2
, filename
, sizeof(full_filename
));
1958 removing_leading_and_trailing_white_space(full_filename
);
1959 if(!strncmp(full_filename
, pdir
, strlen(pdir
)))
1960 newfile
= cpystr(full_filename
+ len
);
1962 newfile
= cpystr(full_filename
);
1965 if(newfile
&& *newfile
)
1972 set_pathandle(rflags
);
1974 if((file_patline
= parse_pat_file(newfile
)) != NULL
){
1976 * Insert the file after the current line.
1978 PAT_LINE_S
*cur_patline
;
1981 rv
= ps
->mangled_screen
= 1;
1982 first_pat
= !(*cl
)->d
.r
.pat
;
1983 cur_patline
= (*cl
)->d
.r
.patline
? (*cl
)->d
.r
.patline
:
1984 (*cur_pat_h
) ? (*cur_pat_h
)->patlinehead
: NULL
;
1987 (*cur_pat_h
)->dirtypinerc
= 1;
1989 file_patline
->dirty
= 1;
1992 file_patline
->prev
= cur_patline
;
1993 file_patline
->next
= cur_patline
->next
;
1994 if(cur_patline
->next
)
1995 cur_patline
->next
->prev
= file_patline
;
1997 cur_patline
->next
= file_patline
;
2000 /* set head of list */
2002 (*cur_pat_h
)->patlinehead
= file_patline
;
2006 if(file_patline
->first
){
2007 /* get rid of Fake Add line */
2009 opt_screen
->top_line
= NULL
;
2010 add_patline_to_display(ps
, cl
, 0, &first_line
,
2011 &opt_screen
->top_line
, file_patline
,
2013 opt_screen
->current
= first_line
;
2014 snip_confline(&add_line
);
2017 /* we're _appending_ to the Fake Add line */
2018 save_current
= opt_screen
->current
;
2019 add_patline_to_display(ps
, cl
, 0, NULL
, NULL
, file_patline
,
2021 opt_screen
->current
= save_current
;
2025 opt_screen
->top_line
= NULL
;
2026 save_current
= opt_screen
->current
;
2027 add_patline_to_display(ps
, cl
, 0, &first_line
,
2028 &opt_screen
->top_line
, file_patline
,
2031 opt_screen
->current
= first_line
;
2033 opt_screen
->current
= save_current
;
2038 fs_give((void **)&newfile
);
2045 role_config_delfile(struct pine
*ps
, CONF_S
**cl
, long int rflags
)
2048 PAT_LINE_S
*cur_patline
;
2051 if(!(cur_patline
= (*cl
)->d
.r
.patline
)){
2052 q_status_message(SM_ORDER
, 0, 3,
2053 "Unknown problem in role_config_delfile");
2057 if(cur_patline
->type
!= File
){
2058 q_status_message(SM_ORDER
, 0, 3, _("Current rule is not part of a file. Use Delete to remove current rule"));
2062 snprintf(prompt
, sizeof(prompt
), _("Really remove rule file \"%s\" from rules config "),
2063 cur_patline
->filename
);
2064 prompt
[sizeof(prompt
)-1] = '\0';
2066 ps
->mangled_footer
= 1;
2067 if(want_to(prompt
,'n','n',h_config_role_delfile
, WT_FLUSH_IN
) == 'y'){
2070 set_pathandle(rflags
);
2071 rv
= ps
->mangled_screen
= 1;
2073 (*cur_pat_h
)->dirtypinerc
= 1;
2075 if(cur_patline
->prev
)
2076 cur_patline
->prev
->next
= cur_patline
->next
;
2079 (*cur_pat_h
)->patlinehead
= cur_patline
->next
;
2082 if(cur_patline
->next
)
2083 cur_patline
->next
->prev
= cur_patline
->prev
;
2085 /* delete the conf lines */
2087 /* find the first one associated with this file */
2089 ctmp
&& ctmp
->prev
&& ctmp
->prev
->d
.r
.patline
== cur_patline
;
2093 if(ctmp
->prev
) /* this file wasn't the first thing in config */
2095 else{ /* this file was first in config */
2096 for(cp
= ctmp
; cp
&& cp
->next
; cp
= cp
->next
)
2099 if(cp
->d
.r
.patline
== cur_patline
)
2105 /* delete lines from the file */
2106 while(ctmp
&& ctmp
->d
.r
.patline
== cur_patline
){
2112 /* deleting last real rule */
2113 if(!first_pattern(role_global_pstate
)){
2115 * Find the start and prepend the fake first role
2118 while(*cl
&& (*cl
)->prev
)
2121 add_fake_first_role(cl
, 1, rflags
);
2123 else if(first_pattern(role_global_pstate
)->inherit
&&
2124 !next_pattern(role_global_pstate
)){
2125 while(*cl
&& (*cl
)->prev
)
2128 /* append fake first after inherit */
2129 add_fake_first_role(cl
, 0, rflags
);
2132 opt_screen
->top_line
= first_confline(*cl
);
2133 opt_screen
->current
= first_sel_confline(opt_screen
->top_line
);
2135 cur_patline
->next
= NULL
;
2136 free_patline(&cur_patline
);
2139 q_status_message(SM_ORDER
, 0, 3, _("Rule file not removed"));
2146 * Swap from a, b to b, a.
2149 swap_literal_roles(CONF_S
*a
, CONF_S
*b
)
2151 PAT_LINE_S
*patline_a
, *patline_b
;
2153 patline_a
= a
->d
.r
.patline
;
2154 patline_b
= b
->d
.r
.patline
;
2156 set_pathandle(role_global_flags
);
2158 (*cur_pat_h
)->dirtypinerc
= 1;
2160 /* first swap the patlines */
2161 if(patline_a
->next
== patline_b
){
2162 patline_b
->prev
= patline_a
->prev
;
2164 patline_a
->prev
->next
= patline_b
;
2166 patline_a
->next
= patline_b
->next
;
2168 patline_b
->next
->prev
= patline_a
;
2170 patline_b
->next
= patline_a
;
2171 patline_a
->prev
= patline_b
;
2174 PAT_LINE_S
*new_a_prev
, *new_a_next
;
2176 new_a_prev
= patline_b
->prev
;
2177 new_a_next
= patline_b
->next
;
2179 patline_b
->prev
= patline_a
->prev
;
2180 patline_b
->next
= patline_a
->next
;
2182 patline_b
->prev
->next
= patline_b
;
2184 patline_b
->next
->prev
= patline_b
;
2186 patline_a
->prev
= new_a_prev
;
2187 patline_a
->next
= new_a_next
;
2189 patline_a
->prev
->next
= patline_a
;
2191 patline_a
->next
->prev
= patline_a
;
2195 * If patline_b is now the first one in the list, we need to fix the
2196 * head of the list to point to this new role.
2198 if(patline_b
->prev
== NULL
&& *cur_pat_h
)
2199 (*cur_pat_h
)->patlinehead
= patline_b
;
2202 /* and then swap the conf lines */
2218 * Swap from a, b to b, a.
2221 swap_file_roles(CONF_S
*a
, CONF_S
*b
)
2223 PAT_S
*pat_a
, *pat_b
;
2224 PAT_LINE_S
*patline
;
2228 patline
= pat_a
->patline
;
2232 /* first swap the pats */
2233 if(pat_a
->next
== pat_b
){
2234 pat_b
->prev
= pat_a
->prev
;
2236 pat_a
->prev
->next
= pat_b
;
2238 pat_a
->next
= pat_b
->next
;
2240 pat_b
->next
->prev
= pat_a
;
2242 pat_b
->next
= pat_a
;
2243 pat_a
->prev
= pat_b
;
2246 PAT_S
*new_a_prev
, *new_a_next
;
2248 new_a_prev
= pat_b
->prev
;
2249 new_a_next
= pat_b
->next
;
2251 pat_b
->prev
= pat_a
->prev
;
2252 pat_b
->next
= pat_a
->next
;
2254 pat_b
->prev
->next
= pat_b
;
2256 pat_b
->next
->prev
= pat_b
;
2258 pat_a
->prev
= new_a_prev
;
2259 pat_a
->next
= new_a_next
;
2261 pat_a
->prev
->next
= pat_a
;
2263 pat_a
->next
->prev
= pat_a
;
2267 * Fix the first and last pointers.
2269 if(patline
->first
== pat_a
)
2270 patline
->first
= pat_b
;
2271 if(patline
->last
== pat_b
)
2272 patline
->last
= pat_a
;
2274 /* and then swap the conf lines */
2292 move_role_into_file(CONF_S
**cl
, int up
)
2294 PAT_LINE_S
*cur_patline
, *file_patline
;
2298 cur_patline
= (*cl
)->d
.r
.patline
;
2301 file_patline
= (*cl
)->prev
->d
.r
.patline
;
2304 b
->d
.r
.patline
= file_patline
;
2307 file_patline
= (*cl
)->next
->d
.r
.patline
;
2310 a
->d
.r
.patline
= file_patline
;
2313 set_pathandle(role_global_flags
);
2315 (*cur_pat_h
)->dirtypinerc
= 1;
2317 file_patline
->dirty
= 1;
2319 pat
= cur_patline
->first
;
2321 if(!up
&& *cur_pat_h
&& cur_patline
== (*cur_pat_h
)->patlinehead
)
2322 (*cur_pat_h
)->patlinehead
= (*cur_pat_h
)->patlinehead
->next
;
2324 if(file_patline
->first
){
2326 file_patline
->last
->next
= pat
;
2327 pat
->prev
= file_patline
->last
;
2328 file_patline
->last
= pat
;
2331 file_patline
->first
->prev
= pat
;
2332 pat
->next
= file_patline
->first
;
2333 file_patline
->first
= pat
;
2336 else /* will be only role in file */
2337 file_patline
->first
= file_patline
->last
= pat
;
2339 pat
->patline
= file_patline
;
2341 /* delete the now unused cur_patline */
2342 cur_patline
->first
= cur_patline
->last
= NULL
;
2343 if(cur_patline
->prev
)
2344 cur_patline
->prev
->next
= cur_patline
->next
;
2345 if(cur_patline
->next
)
2346 cur_patline
->next
->prev
= cur_patline
->prev
;
2348 cur_patline
->next
= NULL
;
2349 free_patline(&cur_patline
);
2351 /* and then swap the conf lines */
2369 move_role_outof_file(CONF_S
**cl
, int up
)
2371 PAT_LINE_S
*file_patline
, *new_patline
;
2375 new_patline
= (PAT_LINE_S
*)fs_get(sizeof(*new_patline
));
2376 memset((void *)new_patline
, 0, sizeof(*new_patline
));
2377 new_patline
->type
= Literal
;
2379 file_patline
= (*cl
)->d
.r
.patline
;
2380 pat
= (*cl
)->d
.r
.pat
;
2387 pat
->prev
->next
= pat
->next
;
2389 file_patline
->first
= pat
->next
;
2392 pat
->next
->prev
= pat
->prev
;
2394 file_patline
->last
= pat
->prev
;
2396 if(file_patline
->first
)
2397 file_patline
->first
->prev
= NULL
;
2399 if(file_patline
->last
)
2400 file_patline
->last
->next
= NULL
;
2402 if(file_patline
->prev
)
2403 file_patline
->prev
->next
= new_patline
;
2405 new_patline
->prev
= file_patline
->prev
;
2406 new_patline
->next
= file_patline
;
2407 file_patline
->prev
= new_patline
;
2408 b
->d
.r
.patline
= new_patline
;
2415 pat
->prev
->next
= pat
->next
;
2417 file_patline
->first
= pat
->next
;
2420 pat
->next
->prev
= pat
->prev
;
2422 file_patline
->last
= pat
->prev
;
2424 if(file_patline
->first
)
2425 file_patline
->first
->prev
= NULL
;
2427 if(file_patline
->last
)
2428 file_patline
->last
->next
= NULL
;
2430 if(file_patline
->next
)
2431 file_patline
->next
->prev
= new_patline
;
2433 new_patline
->next
= file_patline
->next
;
2434 new_patline
->prev
= file_patline
;
2435 file_patline
->next
= new_patline
;
2436 a
->d
.r
.patline
= new_patline
;
2439 set_pathandle(role_global_flags
);
2441 (*cur_pat_h
)->dirtypinerc
= 1;
2443 file_patline
->dirty
= 1;
2445 new_patline
->first
= new_patline
->last
= pat
;
2446 pat
->patline
= new_patline
;
2447 pat
->prev
= pat
->next
= NULL
;
2449 if(up
&& *cur_pat_h
&& file_patline
== (*cur_pat_h
)->patlinehead
)
2450 (*cur_pat_h
)->patlinehead
= new_patline
;
2452 /* and then swap the conf lines */
2468 * This is a move of a literal role from before a file to after a file,
2472 move_role_around_file(CONF_S
**cl
, int up
)
2474 PAT_LINE_S
*file_patline
, *lit_patline
;
2477 set_pathandle(role_global_flags
);
2478 lit_patline
= (*cl
)->d
.r
.patline
;
2480 file_patline
= (*cl
)->prev
->d
.r
.patline
;
2482 if(*cur_pat_h
&& lit_patline
== (*cur_pat_h
)->patlinehead
)
2483 (*cur_pat_h
)->patlinehead
= (*cur_pat_h
)->patlinehead
->next
;
2485 file_patline
= (*cl
)->next
->d
.r
.patline
;
2489 (*cur_pat_h
)->dirtypinerc
= 1;
2491 /* remove the lit_patline from the list */
2492 if(lit_patline
->prev
)
2493 lit_patline
->prev
->next
= lit_patline
->next
;
2494 if(lit_patline
->next
)
2495 lit_patline
->next
->prev
= lit_patline
->prev
;
2497 /* and reinsert it on the other side of the file */
2499 if(*cur_pat_h
&& file_patline
== (*cur_pat_h
)->patlinehead
)
2500 (*cur_pat_h
)->patlinehead
= lit_patline
;
2502 lit_patline
->prev
= file_patline
->prev
;
2503 lit_patline
->next
= file_patline
;
2505 if(file_patline
->prev
)
2506 file_patline
->prev
->next
= lit_patline
;
2508 file_patline
->prev
= lit_patline
;
2511 lit_patline
->next
= file_patline
->next
;
2512 lit_patline
->prev
= file_patline
;
2514 if(file_patline
->next
)
2515 file_patline
->next
->prev
= lit_patline
;
2517 file_patline
->next
= lit_patline
;
2521 * And then move the conf line around the file conf lines.
2524 /* find it's new home */
2527 cp
&& cp
->prev
&& cp
->prev
->d
.r
.patline
== file_patline
;
2528 cp
= prev_confline(cp
))
2532 cp
&& cp
->next
&& cp
->next
->d
.r
.patline
== file_patline
;
2533 cp
= next_confline(cp
))
2536 /* remove it from where it is */
2538 (*cl
)->prev
->next
= (*cl
)->next
;
2540 (*cl
)->next
->prev
= (*cl
)->prev
;
2542 /* cp points to top or bottom of the file lines */
2544 (*cl
)->prev
= cp
->prev
;
2546 cp
->prev
->next
= (*cl
);
2552 (*cl
)->next
= cp
->next
;
2554 cp
->next
->prev
= (*cl
);
2562 #define SETUP_PAT_STATUS(ctmp,svar,val,htitle,hval) \
2563 {char tmp[MAXPATH+1]; \
2568 new_confline(&ctmp); \
2569 ctmp->flags |= CF_NOSELECT | CF_B_LINE; \
2571 new_confline(&ctmp); \
2572 ctmp->var = &svar; \
2573 ctmp->keymenu = &config_radiobutton_keymenu; \
2574 ctmp->help = NO_HELP; \
2575 ctmp->tool = NULL; \
2576 snprintf(tmp, sizeof(tmp), "%-s =", svar.name); \
2577 tmp[sizeof(tmp)-1] = '\0'; \
2578 ctmp->varname = cpystr(tmp); \
2579 ctmp->varnamep = ctmpb = ctmp; \
2580 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); \
2582 new_confline(&ctmp); \
2584 ctmp->valoffset = rindent; \
2585 ctmp->keymenu = &config_radiobutton_keymenu; \
2586 ctmp->help = NO_HELP; \
2587 ctmp->tool = NULL; \
2588 ctmp->varnamep = ctmpb; \
2589 ctmp->flags |= CF_NOSELECT; \
2590 ctmp->value = cpystr("Set Choose One"); \
2592 new_confline(&ctmp); \
2594 ctmp->valoffset = rindent; \
2595 ctmp->keymenu = &config_radiobutton_keymenu; \
2596 ctmp->help = NO_HELP; \
2597 ctmp->tool = radio_tool; \
2598 ctmp->varnamep = ctmpb; \
2599 ctmp->flags |= CF_NOSELECT; \
2600 ctmp->value = cpystr(set_choose); \
2602 /* find longest value's name */ \
2603 for(lv = 0, i = 0; (f = role_status_types(i)); i++) \
2604 if(lv < (j = utf8_width(f->name))) \
2607 lv = MIN(lv, 100); \
2609 for(i = 0; (f = role_status_types(i)); i++){ \
2610 new_confline(&ctmp); \
2611 ctmp->help_title= htitle; \
2612 ctmp->var = &svar; \
2613 ctmp->valoffset = rindent; \
2614 ctmp->keymenu = &config_radiobutton_keymenu; \
2615 ctmp->help = hval; \
2617 ctmp->tool = radio_tool; \
2618 ctmp->varnamep = ctmpb; \
2619 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!(def && def->patgrp) || \
2621 f->value == PAT_STAT_EITHER) || \
2622 (def && def->patgrp && \
2626 tmp[sizeof(tmp)-1] = '\0'; \
2627 ctmp->value = cpystr(tmp); \
2631 #define SETUP_MSG_STATE(ctmp,svar,val,htitle,hval) \
2632 {char tmp[MAXPATH+1]; \
2637 new_confline(&ctmp); \
2638 ctmp->flags |= CF_NOSELECT | CF_B_LINE; \
2640 new_confline(&ctmp); \
2641 ctmp->var = &svar; \
2642 ctmp->keymenu = &config_radiobutton_keymenu; \
2643 ctmp->help = NO_HELP; \
2644 ctmp->tool = NULL; \
2645 snprintf(tmp, sizeof(tmp), "%-s =", svar.name); \
2646 tmp[sizeof(tmp)-1] = '\0'; \
2647 ctmp->varname = cpystr(tmp); \
2648 ctmp->varnamep = ctmpb = ctmp; \
2649 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); \
2651 new_confline(&ctmp); \
2653 ctmp->valoffset = rindent; \
2654 ctmp->keymenu = &config_radiobutton_keymenu; \
2655 ctmp->help = NO_HELP; \
2656 ctmp->tool = NULL; \
2657 ctmp->varnamep = ctmpb; \
2658 ctmp->flags |= CF_NOSELECT; \
2659 ctmp->value = cpystr("Set Choose One"); \
2661 new_confline(&ctmp); \
2663 ctmp->valoffset = rindent; \
2664 ctmp->keymenu = &config_radiobutton_keymenu; \
2665 ctmp->help = NO_HELP; \
2666 ctmp->tool = radio_tool; \
2667 ctmp->varnamep = ctmpb; \
2668 ctmp->flags |= CF_NOSELECT; \
2669 ctmp->value = cpystr(set_choose); \
2671 /* find longest value's name */ \
2672 for(lv = 0, i = 0; (f = msg_state_types(i)); i++) \
2673 if(lv < (j = utf8_width(f->name))) \
2676 lv = MIN(lv, 100); \
2678 for(i = 0; (f = msg_state_types(i)); i++){ \
2679 new_confline(&ctmp); \
2680 ctmp->help_title= htitle; \
2681 ctmp->var = &svar; \
2682 ctmp->valoffset = rindent; \
2683 ctmp->keymenu = &config_radiobutton_keymenu; \
2684 ctmp->help = hval; \
2686 ctmp->tool = radio_tool; \
2687 ctmp->varnamep = ctmpb; \
2688 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (f->value == val) \
2691 tmp[sizeof(tmp)-1] = '\0'; \
2692 ctmp->value = cpystr(tmp); \
2697 #define FEAT_SENTDATE 0
2698 #define FEAT_IFNOTDEL 1
2699 #define FEAT_NONTERM 2
2700 bitmap_t feat_option_list
;
2702 #define INABOOK_FROM 0
2703 #define INABOOK_REPLYTO 1
2704 #define INABOOK_SENDER 2
2705 #define INABOOK_TO 3
2706 #define INABOOK_CC 4
2707 bitmap_t inabook_type_list
;
2710 #define INICK_INICK_CONF 0
2711 #define INICK_FROM_CONF 1
2712 #define INICK_REPLYTO_CONF 2
2713 #define INICK_FCC_CONF 3
2714 #define INICK_LITSIG_CONF 4 /* this needs to come before SIG_CONF */
2715 #define INICK_SIG_CONF 5
2716 #define INICK_TEMPL_CONF 6
2717 #define INICK_CSTM_CONF 7
2718 #define INICK_SMTP_CONF 8
2719 #define INICK_NNTP_CONF 9
2720 CONF_S
*inick_confs
[INICK_NNTP_CONF
+1];
2724 * Screen for editing configuration of a role.
2726 * Args ps -- pine struct
2727 * def -- default role values to start with
2728 * title -- part of title at top of screen
2729 * rflags -- which parts of role to edit
2730 * result -- This is the returned PAT_S, freed by caller.
2732 * Returns: 0 if no change
2733 * 1 if user requested a change
2734 * (change is stored in raw_server and hasn't been acted upon yet)
2735 * 10 user says abort
2738 role_config_edit_screen(struct pine
*ps
, PAT_S
*def
, char *title
, long int rflags
, PAT_S
**result
)
2740 OPT_SCREEN_S screen
, *saved_screen
;
2741 CONF_S
*ctmp
= NULL
, *ctmpb
, *first_line
= NULL
;
2742 struct variable nick_var
, to_pat_var
, from_pat_var
,
2744 sender_pat_var
, cc_pat_var
, recip_pat_var
, news_pat_var
,
2745 subj_pat_var
, inick_var
, fldr_type_var
, folder_pat_var
,
2746 abook_type_var
, abook_pat_var
,
2747 alltext_pat_var
, scorei_pat_var
, partic_pat_var
,
2748 bodytext_pat_var
, age_pat_var
, size_pat_var
,
2749 keyword_pat_var
, charset_pat_var
,
2750 stat_new_var
, stat_del_var
, stat_imp_var
, stat_ans_var
,
2751 stat_rec_var
, stat_8bit_var
,
2752 stat_bom_var
, stat_boy_var
,
2753 cat_cmd_var
, cati_var
, cat_lim_var
,
2754 from_act_var
, replyto_act_var
, fcc_act_var
,
2755 sig_act_var
, litsig_act_var
, templ_act_var
,
2756 cstm_act_var
, smtp_act_var
, nntp_act_var
,
2757 sort_act_var
, iform_act_var
, startup_var
,
2758 repl_type_var
, forw_type_var
, comp_type_var
, score_act_var
,
2760 rolecolor_vars
[2], filter_type_var
, folder_act_var
,
2761 keyword_set_var
, keyword_clr_var
,
2762 filt_new_var
, filt_del_var
, filt_imp_var
, filt_ans_var
;
2763 struct variable
*v
, *varlist
[65], opt_var
, inabook_type_var
;
2764 char *nick
= NULL
, *inick
= NULL
, *fldr_type_pat
= NULL
,
2766 *scorei_pat
= NULL
, *age_pat
= NULL
, *size_pat
= NULL
,
2767 *abook_type_pat
= NULL
,
2768 *stat_new
= NULL
, *stat_del
= NULL
, *stat_imp
= NULL
,
2769 *stat_rec
= NULL
, *stat_ans
= NULL
, *stat_8bit
= NULL
,
2770 *stat_bom
= NULL
, *stat_boy
= NULL
,
2771 *filt_new
= NULL
, *filt_del
= NULL
, *filt_imp
= NULL
,
2772 *filt_ans
= NULL
, *cati
= NULL
, *cat_lim
= NULL
,
2773 *from_act
= NULL
, *replyto_act
= NULL
, *fcc_act
= NULL
,
2774 *sig_act
= NULL
, *litsig_act
= NULL
, *sort_act
= NULL
,
2775 *templ_act
= NULL
, *repl_type
= NULL
, *forw_type
= NULL
,
2776 *comp_type
= NULL
, *rc_fg
= NULL
, *rc_bg
= NULL
,
2777 *score_act
= NULL
, *filter_type
= NULL
,
2779 *iform_act
= NULL
, *startup_act
= NULL
,
2780 *old_fg
= NULL
, *old_bg
= NULL
;
2781 char **to_pat
= NULL
, **from_pat
= NULL
, **sender_pat
= NULL
,
2782 **cc_pat
= NULL
, **news_pat
= NULL
, **recip_pat
= NULL
,
2783 **partic_pat
= NULL
, **subj_pat
= NULL
,
2784 **alltext_pat
= NULL
, **bodytext_pat
= NULL
,
2785 **keyword_pat
= NULL
, **folder_pat
= NULL
,
2786 **charset_pat
= NULL
,
2787 **abook_pat
= NULL
, **folder_act
= NULL
,
2788 **keyword_set
= NULL
, **keyword_clr
= NULL
,
2789 **cat_cmd
= NULL
, **cstm_act
= NULL
, **smtp_act
= NULL
,
2790 **nntp_act
= NULL
, **spat
;
2791 char tmp
[MAXPATH
+1], **apval
, **lval
, ***alval
, *p
;
2792 /* TRANSLATORS: These next 4 are subheading for sections of a configuration screen. */
2793 char *fstr
= _(" CURRENT FOLDER CONDITIONS BEGIN HERE ");
2795 char *astr
= _(" ACTIONS BEGIN HERE ");
2796 char *ustr
= _(" USES BEGIN HERE ");
2797 char *ostr
= _(" OPTIONS BEGIN HERE ");
2798 char *s_p_v_n
= _("Subject pattern"); /* longest one of these */
2799 char *u_s_s
= _("Use SMTP Server"); /* ditto */
2800 char *c_v_n
= _("Exit Status Interval"); /* ditto */
2804 EARB_S
*earb
= NULL
, *ea
;
2805 int rv
, i
, j
, lv
, pindent
, maxpindent
, rindent
,
2806 scoreval
= 0, edit_role
, wid
,
2807 edit_incol
, edit_score
, edit_filter
, edit_other
, edit_srch
,
2808 dval
, ival
, nval
, aval
, fval
,
2809 per_folder_only
, need_uses
, need_options
;
2810 int (*radio_tool
)(struct pine
*, int, CONF_S
**, unsigned);
2811 int (*addhdr_tool
)(struct pine
*, int, CONF_S
**, unsigned);
2812 int (*t_tool
)(struct pine
*, int, CONF_S
**, unsigned);
2815 dprint((4, "role_config_edit_screen()\n"));
2816 edit_role
= rflags
& ROLE_DO_ROLES
;
2817 edit_incol
= rflags
& ROLE_DO_INCOLS
;
2818 edit_score
= rflags
& ROLE_DO_SCORES
;
2819 edit_filter
= rflags
& ROLE_DO_FILTER
;
2820 edit_other
= rflags
& ROLE_DO_OTHER
;
2821 edit_srch
= rflags
& ROLE_DO_SRCH
;
2823 per_folder_only
= (edit_other
&&
2824 !(edit_role
|| edit_incol
|| edit_score
|| edit_filter
|| edit_srch
));
2825 need_uses
= edit_role
;
2826 need_options
= !per_folder_only
;
2828 radio_tool
= edit_filter
? role_filt_radiobutton_tool
2829 : role_radiobutton_tool
;
2830 t_tool
= edit_filter
? role_filt_text_tool
: role_text_tool
;
2831 addhdr_tool
= edit_filter
? role_filt_addhdr_tool
: role_addhdr_tool
;
2833 rindent
= 12; /* radio indent */
2836 * We edit by making a nested call to conf_scroll_screen.
2837 * We use some fake struct variables to get back the results in, and
2838 * so we can use the existing tools from the config screen.
2840 varlist
[j
= 0] = &nick_var
;
2841 varlist
[++j
] = &comment_var
;
2842 varlist
[++j
] = &to_pat_var
;
2843 varlist
[++j
] = &from_pat_var
;
2844 varlist
[++j
] = &sender_pat_var
;
2845 varlist
[++j
] = &cc_pat_var
;
2846 varlist
[++j
] = &recip_pat_var
;
2847 varlist
[++j
] = &partic_pat_var
;
2848 varlist
[++j
] = &news_pat_var
;
2849 varlist
[++j
] = &subj_pat_var
;
2850 varlist
[++j
] = &alltext_pat_var
;
2851 varlist
[++j
] = &bodytext_pat_var
;
2852 varlist
[++j
] = &keyword_pat_var
;
2853 varlist
[++j
] = &charset_pat_var
;
2854 varlist
[++j
] = &age_pat_var
;
2855 varlist
[++j
] = &size_pat_var
;
2856 varlist
[++j
] = &scorei_pat_var
;
2857 varlist
[++j
] = &stat_new_var
;
2858 varlist
[++j
] = &stat_rec_var
;
2859 varlist
[++j
] = &stat_del_var
;
2860 varlist
[++j
] = &stat_imp_var
;
2861 varlist
[++j
] = &stat_ans_var
;
2862 varlist
[++j
] = &stat_8bit_var
;
2863 varlist
[++j
] = &stat_bom_var
;
2864 varlist
[++j
] = &stat_boy_var
;
2865 varlist
[++j
] = &cat_cmd_var
;
2866 varlist
[++j
] = &cati_var
;
2867 varlist
[++j
] = &cat_lim_var
;
2868 varlist
[++j
] = &inick_var
;
2869 varlist
[++j
] = &fldr_type_var
;
2870 varlist
[++j
] = &folder_pat_var
;
2871 varlist
[++j
] = &abook_type_var
;
2872 varlist
[++j
] = &abook_pat_var
;
2873 varlist
[++j
] = &from_act_var
;
2874 varlist
[++j
] = &replyto_act_var
;
2875 varlist
[++j
] = &fcc_act_var
;
2876 varlist
[++j
] = &sig_act_var
;
2877 varlist
[++j
] = &litsig_act_var
;
2878 varlist
[++j
] = &sort_act_var
;
2879 varlist
[++j
] = &iform_act_var
;
2880 varlist
[++j
] = &startup_var
;
2881 varlist
[++j
] = &templ_act_var
;
2882 varlist
[++j
] = &cstm_act_var
;
2883 varlist
[++j
] = &smtp_act_var
;
2884 varlist
[++j
] = &nntp_act_var
;
2885 varlist
[++j
] = &score_act_var
;
2886 varlist
[++j
] = &hdrtok_act_var
;
2887 varlist
[++j
] = &repl_type_var
;
2888 varlist
[++j
] = &forw_type_var
;
2889 varlist
[++j
] = &comp_type_var
;
2890 varlist
[++j
] = &rolecolor_vars
[0];
2891 varlist
[++j
] = &rolecolor_vars
[1];
2892 varlist
[++j
] = &filter_type_var
;
2893 varlist
[++j
] = &folder_act_var
;
2894 varlist
[++j
] = &keyword_set_var
;
2895 varlist
[++j
] = &keyword_clr_var
;
2896 varlist
[++j
] = &filt_new_var
;
2897 varlist
[++j
] = &filt_del_var
;
2898 varlist
[++j
] = &filt_imp_var
;
2899 varlist
[++j
] = &filt_ans_var
;
2900 varlist
[++j
] = &opt_var
;
2901 varlist
[++j
] = &inabook_type_var
;
2902 varlist
[++j
] = NULL
;
2903 for(j
= 0; varlist
[j
]; j
++)
2904 memset(varlist
[j
], 0, sizeof(struct variable
));
2906 if(def
&& ((def
->patgrp
&& def
->patgrp
->bogus
) || (def
->action
&& def
->action
->bogus
))){
2907 char msg
[MAX_SCREEN_COLS
+1];
2909 snprintf(msg
, sizeof(msg
),
2910 _("Rule contains unknown %s element, possibly from newer Alpine"),
2911 (def
->patgrp
&& def
->patgrp
->bogus
) ? "pattern" : "action");
2912 msg
[sizeof(msg
)-1] = '\0';
2913 q_status_message(SM_ORDER
| SM_DING
, 7, 7, msg
);
2914 q_status_message(SM_ORDER
| SM_DING
, 7, 7,
2915 _("Editing with this version of Alpine will destroy information"));
2916 flush_status_messages(0);
2919 role_forw_ptr
= role_repl_ptr
= role_fldr_ptr
= role_filt_ptr
= NULL
;
2920 role_status1_ptr
= role_status2_ptr
= role_status3_ptr
= NULL
;
2921 role_status4_ptr
= role_status5_ptr
= role_status6_ptr
= NULL
;
2922 role_status7_ptr
= NULL
; role_status8_ptr
= NULL
;
2923 msg_state1_ptr
= msg_state2_ptr
= NULL
;
2924 msg_state3_ptr
= msg_state4_ptr
= NULL
;
2925 role_afrom_ptr
= startup_ptr
= NULL
;
2926 role_comment_ptr
= NULL
;
2928 nick_var
.name
= cpystr(_("Nickname"));
2929 nick_var
.is_used
= 1;
2930 nick_var
.is_user
= 1;
2931 apval
= APVAL(&nick_var
, ew
);
2932 *apval
= (def
&& def
->patgrp
&& def
->patgrp
->nick
)
2933 ? cpystr(def
->patgrp
->nick
) : NULL
;
2935 nick_var
.global_val
.p
= cpystr(edit_role
2940 ? "Index Color Rule"
2943 : "Filter Rule"))));
2944 set_current_val(&nick_var
, FALSE
, FALSE
);
2946 role_comment_ptr
= &comment_var
; /* so radiobuttons can tell */
2947 comment_var
.name
= cpystr(_("Comment"));
2948 comment_var
.is_used
= 1;
2949 comment_var
.is_user
= 1;
2950 apval
= APVAL(&comment_var
, ew
);
2951 *apval
= (def
&& def
->patgrp
&& def
->patgrp
->comment
)
2952 ? cpystr(def
->patgrp
->comment
) : NULL
;
2953 set_current_val(&comment_var
, FALSE
, FALSE
);
2955 /* TRANSLATORS: Quite a few of the translations to follow are from the
2956 rules editing screens. These are mostly headings of individual categories
2957 of criteria which can be set in a rule. */
2958 setup_dummy_pattern_var(&to_pat_var
, _("To pattern"),
2959 (def
&& def
->patgrp
) ? def
->patgrp
->to
: NULL
);
2960 setup_dummy_pattern_var(&from_pat_var
, _("From pattern"),
2961 (def
&& def
->patgrp
) ? def
->patgrp
->from
: NULL
);
2962 setup_dummy_pattern_var(&sender_pat_var
, _("Sender pattern"),
2963 (def
&& def
->patgrp
) ? def
->patgrp
->sender
: NULL
);
2964 setup_dummy_pattern_var(&cc_pat_var
, _("Cc pattern"),
2965 (def
&& def
->patgrp
) ? def
->patgrp
->cc
: NULL
);
2966 setup_dummy_pattern_var(&news_pat_var
, _("News pattern"),
2967 (def
&& def
->patgrp
) ? def
->patgrp
->news
: NULL
);
2968 setup_dummy_pattern_var(&subj_pat_var
, s_p_v_n
,
2969 (def
&& def
->patgrp
) ? def
->patgrp
->subj
: NULL
);
2970 /* TRANSLATORS: Recip is an abbreviation for Recipients which stands for
2971 all of the recipients of a message. */
2972 setup_dummy_pattern_var(&recip_pat_var
, _("Recip pattern"),
2973 (def
&& def
->patgrp
) ? def
->patgrp
->recip
: NULL
);
2974 /* TRANSLATORS: Partic is an abbreviation for Participants which stands for
2975 all of the recipients plus the sender of a message. */
2976 setup_dummy_pattern_var(&partic_pat_var
, _("Partic pattern"),
2977 (def
&& def
->patgrp
) ? def
->patgrp
->partic
: NULL
);
2978 /* TRANSLATORS: AllText means all of the text of a message */
2979 setup_dummy_pattern_var(&alltext_pat_var
, _("AllText pattern"),
2980 (def
&& def
->patgrp
) ? def
->patgrp
->alltext
: NULL
);
2981 /* TRANSLATORS: BdyText means the text of a message but not the text in the headers */
2982 setup_dummy_pattern_var(&bodytext_pat_var
, _("BdyText pattern"),
2983 (def
&& def
->patgrp
) ? def
->patgrp
->bodytext
: NULL
);
2985 setup_dummy_pattern_var(&keyword_pat_var
, _("Keyword pattern"),
2986 (def
&& def
->patgrp
) ? def
->patgrp
->keyword
: NULL
);
2987 setup_dummy_pattern_var(&charset_pat_var
, _("Charset pattern"),
2988 (def
&& def
->patgrp
) ? def
->patgrp
->charsets
: NULL
);
2990 age_pat_global_ptr
= &age_pat_var
;
2991 /* TRANSLATORS: Age interval is a setting for how old the message is. */
2992 age_pat_var
.name
= cpystr(_("Age interval"));
2993 age_pat_var
.is_used
= 1;
2994 age_pat_var
.is_user
= 1;
2995 if(def
&& def
->patgrp
&& def
->patgrp
->do_age
){
2996 apval
= APVAL(&age_pat_var
, ew
);
2997 *apval
= stringform_of_intvl(def
->patgrp
->age
);
3000 set_current_val(&age_pat_var
, FALSE
, FALSE
);
3002 size_pat_global_ptr
= &size_pat_var
;
3003 size_pat_var
.name
= cpystr(_("Size interval"));
3004 size_pat_var
.is_used
= 1;
3005 size_pat_var
.is_user
= 1;
3006 if(def
&& def
->patgrp
&& def
->patgrp
->do_size
){
3007 apval
= APVAL(&size_pat_var
, ew
);
3008 *apval
= stringform_of_intvl(def
->patgrp
->size
);
3011 set_current_val(&size_pat_var
, FALSE
, FALSE
);
3013 scorei_pat_global_ptr
= &scorei_pat_var
;
3014 /* TRANSLATORS: Score is an alpine concept where the score can be kept for a
3015 message to see if it is a message you want to look at. */
3016 scorei_pat_var
.name
= cpystr(_("Score interval"));
3017 scorei_pat_var
.is_used
= 1;
3018 scorei_pat_var
.is_user
= 1;
3019 if(def
&& def
->patgrp
&& def
->patgrp
->do_score
){
3020 apval
= APVAL(&scorei_pat_var
, ew
);
3021 *apval
= stringform_of_intvl(def
->patgrp
->score
);
3024 set_current_val(&scorei_pat_var
, FALSE
, FALSE
);
3026 role_status1_ptr
= &stat_del_var
; /* so radiobuttons can tell */
3027 stat_del_var
.name
= cpystr(_("Message is Deleted?"));
3028 stat_del_var
.is_used
= 1;
3029 stat_del_var
.is_user
= 1;
3030 apval
= APVAL(&stat_del_var
, ew
);
3031 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_del
: -1)) ? cpystr(f
->name
) : NULL
;
3032 set_current_val(&stat_del_var
, FALSE
, FALSE
);
3034 role_status2_ptr
= &stat_new_var
; /* so radiobuttons can tell */
3035 stat_new_var
.name
= cpystr(_("Message is New (Unseen)?"));
3036 stat_new_var
.is_used
= 1;
3037 stat_new_var
.is_user
= 1;
3038 apval
= APVAL(&stat_new_var
, ew
);
3039 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_new
: -1)) ? cpystr(f
->name
) : NULL
;
3040 set_current_val(&stat_new_var
, FALSE
, FALSE
);
3042 role_status3_ptr
= &stat_imp_var
; /* so radiobuttons can tell */
3043 stat_imp_var
.name
= cpystr(_("Message is Important?"));
3044 stat_imp_var
.is_used
= 1;
3045 stat_imp_var
.is_user
= 1;
3046 apval
= APVAL(&stat_imp_var
, ew
);
3047 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_imp
: -1)) ? cpystr(f
->name
) : NULL
;
3048 set_current_val(&stat_imp_var
, FALSE
, FALSE
);
3050 role_status4_ptr
= &stat_ans_var
; /* so radiobuttons can tell */
3051 stat_ans_var
.name
= cpystr(_("Message is Answered?"));
3052 stat_ans_var
.is_used
= 1;
3053 stat_ans_var
.is_user
= 1;
3054 apval
= APVAL(&stat_ans_var
, ew
);
3055 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_ans
: -1)) ? cpystr(f
->name
) : NULL
;
3056 set_current_val(&stat_ans_var
, FALSE
, FALSE
);
3058 role_status5_ptr
= &stat_8bit_var
; /* so radiobuttons can tell */
3059 stat_8bit_var
.name
= cpystr(_("Subject contains raw 8-bit?"));
3060 stat_8bit_var
.is_used
= 1;
3061 stat_8bit_var
.is_user
= 1;
3062 apval
= APVAL(&stat_8bit_var
, ew
);
3063 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_8bitsubj
: -1)) ? cpystr(f
->name
) : NULL
;
3064 set_current_val(&stat_8bit_var
, FALSE
, FALSE
);
3066 role_status6_ptr
= &stat_rec_var
; /* so radiobuttons can tell */
3067 stat_rec_var
.name
= cpystr(_("Message is Recent?"));
3068 stat_rec_var
.is_used
= 1;
3069 stat_rec_var
.is_user
= 1;
3070 apval
= APVAL(&stat_rec_var
, ew
);
3071 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_rec
: -1)) ? cpystr(f
->name
) : NULL
;
3072 set_current_val(&stat_rec_var
, FALSE
, FALSE
);
3074 role_status7_ptr
= &stat_bom_var
; /* so radiobuttons can tell */
3075 stat_bom_var
.name
= cpystr(_("Beginning of Month?"));
3076 stat_bom_var
.is_used
= 1;
3077 stat_bom_var
.is_user
= 1;
3078 apval
= APVAL(&stat_bom_var
, ew
);
3079 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_bom
: -1)) ? cpystr(f
->name
) : NULL
;
3080 set_current_val(&stat_bom_var
, FALSE
, FALSE
);
3082 role_status8_ptr
= &stat_boy_var
; /* so radiobuttons can tell */
3083 stat_boy_var
.name
= cpystr(_("Beginning of Year?"));
3084 stat_boy_var
.is_used
= 1;
3085 stat_boy_var
.is_user
= 1;
3086 apval
= APVAL(&stat_boy_var
, ew
);
3087 *apval
= (f
=role_status_types((def
&& def
->patgrp
) ? def
->patgrp
->stat_boy
: -1)) ? cpystr(f
->name
) : NULL
;
3088 set_current_val(&stat_boy_var
, FALSE
, FALSE
);
3092 convert_statebits_to_vals((def
&& def
->action
) ? def
->action
->state_setting_bits
: 0L, &dval
, &aval
, &ival
, &nval
);
3093 msg_state1_ptr
= &filt_del_var
; /* so radiobuttons can tell */
3094 /* TRANSLATORS: these are actions that might be taken by the rule */
3095 filt_del_var
.name
= cpystr(_("Set Deleted Status"));
3096 filt_del_var
.is_used
= 1;
3097 filt_del_var
.is_user
= 1;
3098 apval
= APVAL(&filt_del_var
, ew
);
3099 *apval
= (f
=msg_state_types(dval
)) ? cpystr(f
->name
) : NULL
;
3100 set_current_val(&filt_del_var
, FALSE
, FALSE
);
3102 msg_state2_ptr
= &filt_new_var
; /* so radiobuttons can tell */
3103 filt_new_var
.name
= cpystr(_("Set New Status"));
3104 filt_new_var
.is_used
= 1;
3105 filt_new_var
.is_user
= 1;
3106 apval
= APVAL(&filt_new_var
, ew
);
3107 *apval
= (f
=msg_state_types(nval
)) ? cpystr(f
->name
) : NULL
;
3108 set_current_val(&filt_new_var
, FALSE
, FALSE
);
3110 msg_state3_ptr
= &filt_imp_var
; /* so radiobuttons can tell */
3111 filt_imp_var
.name
= cpystr(_("Set Important Status"));
3112 filt_imp_var
.is_used
= 1;
3113 filt_imp_var
.is_user
= 1;
3114 apval
= APVAL(&filt_imp_var
, ew
);
3115 *apval
= (f
=msg_state_types(ival
)) ? cpystr(f
->name
) : NULL
;
3116 set_current_val(&filt_imp_var
, FALSE
, FALSE
);
3118 msg_state4_ptr
= &filt_ans_var
; /* so radiobuttons can tell */
3119 filt_ans_var
.name
= cpystr(_("Set Answered Status"));
3120 filt_ans_var
.is_used
= 1;
3121 filt_ans_var
.is_user
= 1;
3122 apval
= APVAL(&filt_ans_var
, ew
);
3123 *apval
= (f
=msg_state_types(aval
)) ? cpystr(f
->name
) : NULL
;
3124 set_current_val(&filt_ans_var
, FALSE
, FALSE
);
3126 inick_var
.name
= cpystr(_("Initialize settings using role"));
3127 inick_var
.is_used
= 1;
3128 inick_var
.is_user
= 1;
3129 apval
= APVAL(&inick_var
, ew
);
3130 *apval
= (def
&& def
->action
&& def
->action
->inherit_nick
&&
3131 def
->action
->inherit_nick
[0])
3132 ? cpystr(def
->action
->inherit_nick
) : NULL
;
3134 role_fldr_ptr
= &fldr_type_var
; /* so radiobuttons can tell */
3135 fldr_type_var
.name
= cpystr(_("Current Folder Type"));
3136 fldr_type_var
.is_used
= 1;
3137 fldr_type_var
.is_user
= 1;
3138 apval
= APVAL(&fldr_type_var
, ew
);
3139 *apval
= (f
=pat_fldr_types((def
&& def
->patgrp
) ? def
->patgrp
->fldr_type
: (!def
&& edit_filter
) ? FLDR_SPECIFIC
: FLDR_DEFL
)) ? cpystr(f
->name
) : NULL
;
3140 set_current_val(&fldr_type_var
, FALSE
, FALSE
);
3142 setup_dummy_pattern_var(&folder_pat_var
, _("Folder List"),
3143 (def
&& def
->patgrp
) ? def
->patgrp
->folder
: NULL
);
3144 /* special default for folder_pat */
3145 alval
= ALVAL(&folder_pat_var
, ew
);
3146 if(alval
&& !*alval
&& !def
&& edit_filter
){
3149 ltmp
= (char **) fs_get(2 * sizeof(*ltmp
));
3150 ltmp
[0] = cpystr(ps_global
->inbox_name
);
3153 set_current_val(&folder_pat_var
, FALSE
, FALSE
);
3156 role_afrom_ptr
= &abook_type_var
; /* so radiobuttons can tell */
3157 abook_type_var
.name
= cpystr(_("Address in address book?"));
3158 abook_type_var
.is_used
= 1;
3159 abook_type_var
.is_user
= 1;
3160 apval
= APVAL(&abook_type_var
, ew
);
3161 *apval
= (f
=inabook_fldr_types((def
&& def
->patgrp
) ? def
->patgrp
->inabook
: IAB_EITHER
)) ? cpystr(f
->name
) : NULL
;
3162 set_current_val(&abook_type_var
, FALSE
, FALSE
);
3164 /* TRANSLATORS: Abook is an abbreviation for Address Book */
3165 setup_dummy_pattern_var(&abook_pat_var
, _("Abook List"),
3166 (def
&& def
->patgrp
) ? def
->patgrp
->abooks
: NULL
);
3169 * This is a little different from some of the other patterns. Tt is
3170 * actually a char ** in the struct instead of a PATTERN_S.
3172 cat_cmd_global_ptr
= &cat_cmd_var
;
3173 cat_cmd_var
.name
= cpystr(_("External Categorizer Commands"));
3174 cat_cmd_var
.is_used
= 1;
3175 cat_cmd_var
.is_user
= 1;
3176 cat_cmd_var
.is_list
= 1;
3177 alval
= ALVAL(&cat_cmd_var
, ew
);
3178 *alval
= (def
&& def
->patgrp
&& def
->patgrp
->category_cmd
&&
3179 def
->patgrp
->category_cmd
[0])
3180 ? copy_list_array(def
->patgrp
->category_cmd
) : NULL
;
3181 set_current_val(&cat_cmd_var
, FALSE
, FALSE
);
3183 cati_global_ptr
= &cati_var
;
3184 cati_var
.name
= cpystr(c_v_n
);
3185 cati_var
.is_used
= 1;
3186 cati_var
.is_user
= 1;
3187 if(def
&& def
->patgrp
&& def
->patgrp
->do_cat
&& def
->patgrp
->category_cmd
&&
3188 def
->patgrp
->category_cmd
[0]){
3189 apval
= APVAL(&cati_var
, ew
);
3190 *apval
= stringform_of_intvl(def
->patgrp
->cat
);
3193 set_current_val(&cati_var
, FALSE
, FALSE
);
3195 cat_lim_global_ptr
= &cat_lim_var
;
3196 cat_lim_var
.name
= cpystr(_("Character Limit"));
3197 cat_lim_var
.is_used
= 1;
3198 cat_lim_var
.is_user
= 1;
3199 cat_lim_var
.global_val
.p
= cpystr("-1");
3200 apval
= APVAL(&cat_lim_var
, ew
);
3201 if(def
&& def
->patgrp
&& def
->patgrp
->category_cmd
&&
3202 def
->patgrp
->category_cmd
[0] && def
->patgrp
->cat_lim
!= -1){
3203 *apval
= (char *) fs_get(20 * sizeof(char));
3204 snprintf(*apval
, 20, "%ld", def
->patgrp
->cat_lim
);
3205 (*apval
)[20-1] = '\0';
3208 set_current_val(&cat_lim_var
, FALSE
, FALSE
);
3210 from_act_var
.name
= cpystr(_("Set From"));
3211 from_act_var
.is_used
= 1;
3212 from_act_var
.is_user
= 1;
3213 if(def
&& def
->action
&& def
->action
->from
){
3217 len
= est_size(def
->action
->from
);
3218 bufp
= (char *) fs_get(len
* sizeof(char));
3219 apval
= APVAL(&from_act_var
, ew
);
3220 *apval
= addr_string_mult(def
->action
->from
, bufp
, len
);
3223 apval
= APVAL(&from_act_var
, ew
);
3227 replyto_act_var
.name
= cpystr(_("Set Reply-To"));
3228 replyto_act_var
.is_used
= 1;
3229 replyto_act_var
.is_user
= 1;
3230 if(def
&& def
->action
&& def
->action
->replyto
){
3234 len
= est_size(def
->action
->replyto
);
3235 bufp
= (char *) fs_get(len
* sizeof(char));
3236 apval
= APVAL(&replyto_act_var
, ew
);
3237 *apval
= addr_string_mult(def
->action
->replyto
, bufp
, len
);
3240 apval
= APVAL(&replyto_act_var
, ew
);
3244 fcc_act_var
.name
= cpystr(_("Set Fcc"));
3245 fcc_act_var
.is_used
= 1;
3246 fcc_act_var
.is_user
= 1;
3247 apval
= APVAL(&fcc_act_var
, ew
);
3248 *apval
= (def
&& def
->action
&& def
->action
->fcc
)
3249 ? cpystr(def
->action
->fcc
) : NULL
;
3251 sort_act_var
.name
= cpystr(_("Set Sort Order"));
3252 sort_act_var
.is_used
= 1;
3253 sort_act_var
.is_user
= 1;
3254 apval
= APVAL(&sort_act_var
, ew
);
3255 if(def
&& def
->action
&& def
->action
->is_a_other
&&
3256 def
->action
->sort_is_set
){
3257 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def
->action
->sortorder
),
3258 (def
->action
->revsort
) ? "/Reverse" : "");
3259 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
3260 *apval
= cpystr(tmp_20k_buf
);
3265 iform_act_var
.name
= cpystr(_("Set Index Format"));
3266 iform_act_var
.is_used
= 1;
3267 iform_act_var
.is_user
= 1;
3268 apval
= APVAL(&iform_act_var
, ew
);
3269 *apval
= (def
&& def
->action
&& def
->action
->is_a_other
&&
3270 def
->action
->index_format
)
3271 ? cpystr(def
->action
->index_format
) : NULL
;
3272 if(ps_global
->VAR_INDEX_FORMAT
){
3273 iform_act_var
.global_val
.p
= cpystr(ps_global
->VAR_INDEX_FORMAT
);
3274 set_current_val(&iform_act_var
, FALSE
, FALSE
);
3277 startup_ptr
= &startup_var
;
3278 startup_var
.name
= cpystr(_("Set Startup Rule"));
3279 startup_var
.is_used
= 1;
3280 startup_var
.is_user
= 1;
3281 apval
= APVAL(&startup_var
, ew
);
3283 if(def
&& def
->action
&& def
->action
->is_a_other
){
3284 *apval
= (f
=startup_rules(def
->action
->startup_rule
))
3285 ? cpystr(f
->name
) : NULL
;
3286 set_current_val(&startup_var
, FALSE
, FALSE
);
3289 *apval
= (f
=startup_rules(IS_NOTSET
)) ? cpystr(f
->name
) : NULL
;
3290 set_current_val(&startup_var
, FALSE
, FALSE
);
3293 /* TRANSLATORS: LiteralSig is a way to keep the signature in the configuration
3294 file instead of in a separate Signature file. */
3295 litsig_act_var
.name
= cpystr(_("Set LiteralSig"));
3296 litsig_act_var
.is_used
= 1;
3297 litsig_act_var
.is_user
= 1;
3298 apval
= APVAL(&litsig_act_var
, ew
);
3299 *apval
= (def
&& def
->action
&& def
->action
->litsig
)
3300 ? cpystr(def
->action
->litsig
) : NULL
;
3302 sig_act_var
.name
= cpystr(_("Set Signature"));
3303 sig_act_var
.is_used
= 1;
3304 sig_act_var
.is_user
= 1;
3305 apval
= APVAL(&sig_act_var
, ew
);
3306 *apval
= (def
&& def
->action
&& def
->action
->sig
)
3307 ? cpystr(def
->action
->sig
) : NULL
;
3309 /* TRANSLATORS: A template is a skeleton of a message to be used
3310 for composing a new message */
3311 templ_act_var
.name
= cpystr(_("Set Template"));
3312 templ_act_var
.is_used
= 1;
3313 templ_act_var
.is_user
= 1;
3314 apval
= APVAL(&templ_act_var
, ew
);
3315 *apval
= (def
&& def
->action
&& def
->action
->template)
3316 ? cpystr(def
->action
->template) : NULL
;
3318 /* TRANSLATORS: Hdrs is an abbreviation for Headers */
3319 cstm_act_var
.name
= cpystr(_("Set Other Hdrs"));
3320 cstm_act_var
.is_used
= 1;
3321 cstm_act_var
.is_user
= 1;
3322 cstm_act_var
.is_list
= 1;
3323 alval
= ALVAL(&cstm_act_var
, ew
);
3324 *alval
= (def
&& def
->action
&& def
->action
->cstm
)
3325 ? copy_list_array(def
->action
->cstm
) : NULL
;
3327 smtp_act_var
.name
= cpystr(u_s_s
);
3328 smtp_act_var
.is_used
= 1;
3329 smtp_act_var
.is_user
= 1;
3330 smtp_act_var
.is_list
= 1;
3331 alval
= ALVAL(&smtp_act_var
, ew
);
3332 *alval
= (def
&& def
->action
&& def
->action
->smtp
)
3333 ? copy_list_array(def
->action
->smtp
) : NULL
;
3335 nntp_act_var
.name
= cpystr(_("Use NNTP Server"));
3336 nntp_act_var
.is_used
= 1;
3337 nntp_act_var
.is_user
= 1;
3338 nntp_act_var
.is_list
= 1;
3339 alval
= ALVAL(&nntp_act_var
, ew
);
3340 *alval
= (def
&& def
->action
&& def
->action
->nntp
)
3341 ? copy_list_array(def
->action
->nntp
) : NULL
;
3343 score_act_global_ptr
= &score_act_var
;
3344 score_act_var
.name
= cpystr(_("Score Value"));
3345 score_act_var
.is_used
= 1;
3346 score_act_var
.is_user
= 1;
3347 if(def
&& def
->action
&& def
->action
->scoreval
>= SCORE_MIN
&&
3348 def
->action
->scoreval
<= SCORE_MAX
)
3349 scoreval
= def
->action
->scoreval
;
3351 score_act_var
.global_val
.p
= cpystr("0");
3353 apval
= APVAL(&score_act_var
, ew
);
3354 *apval
= (char *)fs_get(20 * sizeof(char));
3355 snprintf(*apval
, 20, "%d", scoreval
);
3356 (*apval
)[20-1] = '\0';
3359 set_current_val(&score_act_var
, FALSE
, FALSE
);
3361 hdrtok_act_var
.name
= cpystr(_("Score From Header"));
3362 hdrtok_act_var
.is_used
= 1;
3363 hdrtok_act_var
.is_user
= 1;
3364 if(def
&& def
->action
&& def
->action
->scorevalhdrtok
){
3365 apval
= APVAL(&hdrtok_act_var
, ew
);
3366 *apval
= hdrtok_to_stringform(def
->action
->scorevalhdrtok
);
3369 set_current_val(&hdrtok_act_var
, FALSE
, FALSE
);
3371 role_repl_ptr
= &repl_type_var
; /* so radiobuttons can tell */
3372 /* TRANSLATORS: For these, Use is a now. This part of the rule describes how
3373 it will be used when Replying so it is the Reply Use */
3374 repl_type_var
.name
= cpystr(_("Reply Use"));
3375 repl_type_var
.is_used
= 1;
3376 repl_type_var
.is_user
= 1;
3377 apval
= APVAL(&repl_type_var
, ew
);
3378 *apval
= (f
=role_repl_types((def
&& def
->action
) ? def
->action
->repl_type
: -1)) ? cpystr(f
->name
) : NULL
;
3379 set_current_val(&repl_type_var
, FALSE
, FALSE
);
3381 role_forw_ptr
= &forw_type_var
; /* so radiobuttons can tell */
3382 forw_type_var
.name
= cpystr(_("Forward Use"));
3383 forw_type_var
.is_used
= 1;
3384 forw_type_var
.is_user
= 1;
3385 apval
= APVAL(&forw_type_var
, ew
);
3386 *apval
= (f
=role_forw_types((def
&& def
->action
) ? def
->action
->forw_type
: -1)) ? cpystr(f
->name
) : NULL
;
3387 set_current_val(&forw_type_var
, FALSE
, FALSE
);
3389 comp_type_var
.name
= cpystr(_("Compose Use"));
3390 comp_type_var
.is_used
= 1;
3391 comp_type_var
.is_user
= 1;
3392 apval
= APVAL(&comp_type_var
, ew
);
3393 *apval
= (f
=role_comp_types((def
&& def
->action
) ? def
->action
->comp_type
: -1)) ? cpystr(f
->name
) : NULL
;
3394 set_current_val(&comp_type_var
, FALSE
, FALSE
);
3396 rolecolor_vars
[0].is_used
= 1;
3397 rolecolor_vars
[0].is_user
= 1;
3398 apval
= APVAL(&rolecolor_vars
[0], ew
);
3399 *apval
= (def
&& def
->action
&& def
->action
->incol
&&
3400 def
->action
->incol
->fg
[0])
3401 ? cpystr(def
->action
->incol
->fg
) : NULL
;
3402 rolecolor_vars
[1].is_used
= 1;
3403 rolecolor_vars
[1].is_user
= 1;
3404 rolecolor_vars
[0].name
= cpystr("ic-foreground-color");
3405 rolecolor_vars
[1].name
= cpystr(rolecolor_vars
[0].name
);
3406 strncpy(rolecolor_vars
[1].name
+ 3, "back", 4);
3407 apval
= APVAL(&rolecolor_vars
[1], ew
);
3408 *apval
= (def
&& def
->action
&& def
->action
->incol
&&
3409 def
->action
->incol
->bg
[0])
3410 ? cpystr(def
->action
->incol
->bg
) : NULL
;
3411 set_current_val(&rolecolor_vars
[0], FALSE
, FALSE
);
3412 set_current_val(&rolecolor_vars
[1], FALSE
, FALSE
);
3413 old_fg
= PVAL(&rolecolor_vars
[0], ew
) ? cpystr(PVAL(&rolecolor_vars
[0], ew
))
3415 old_bg
= PVAL(&rolecolor_vars
[1], ew
) ? cpystr(PVAL(&rolecolor_vars
[1], ew
))
3419 /* save the old opt_screen before calling scroll screen again */
3420 saved_screen
= opt_screen
;
3422 pindent
= utf8_width(s_p_v_n
); /* the longest one */
3423 maxpindent
= pindent
+ 6;
3424 for(a
= (def
&& def
->patgrp
) ? def
->patgrp
->arbhdr
: NULL
; a
; a
= a
->next
)
3425 if((lv
=utf8_width(a
->field
? a
->field
: "")+utf8_width(" pattern")) > pindent
)
3428 pindent
= MIN(pindent
, maxpindent
);
3430 pindent
+= NOTLEN
; /* width of `! ' */
3432 pindent
+= 3; /* width of ` = ' */
3435 new_confline(&ctmp
);
3436 ctmp
->help_title
= _("HELP FOR NICKNAME");
3437 ctmp
->var
= &nick_var
;
3438 ctmp
->valoffset
= pindent
;
3439 ctmp
->keymenu
= &config_role_keymenu
;
3440 ctmp
->help
= edit_role
? h_config_role_nick
:
3441 edit_incol
? h_config_incol_nick
:
3442 edit_score
? h_config_score_nick
:
3443 edit_other
? h_config_other_nick
3444 : h_config_filt_nick
;
3445 ctmp
->tool
= t_tool
;
3446 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, nick_var
.name
);
3447 tmp
[sizeof(tmp
)-1] = '\0';
3448 ctmp
->varname
= cpystr(tmp
);
3449 ctmp
->varnamep
= ctmp
;
3450 ctmp
->value
= pretty_value(ps
, ctmp
);
3454 if(rflags
& ROLE_CHANGES
)
3455 first_line
->flags
|= CF_CHANGES
;
3458 new_confline(&ctmp
);
3459 ctmp
->help_title
= _("HELP FOR COMMENT");
3460 ctmp
->var
= &comment_var
;
3461 ctmp
->valoffset
= pindent
;
3462 ctmp
->keymenu
= &config_role_keymenu
;
3463 ctmp
->help
= h_config_role_comment
;
3464 ctmp
->tool
= role_litsig_text_tool
;
3465 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, comment_var
.name
);
3466 tmp
[sizeof(tmp
)-1] = '\0';
3467 ctmp
->varname
= cpystr(tmp
);
3468 ctmp
->varnamep
= ctmp
;
3469 ctmp
->value
= pretty_value(ps
, ctmp
);
3473 new_confline(&ctmp
);
3474 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3476 new_confline(&ctmp
);
3477 ctmp
->flags
|= CF_NOSELECT
;
3478 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(fstr
)) + 4){
3481 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
3482 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
3483 fstr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
3484 ctmp
->value
= cpystr(tmp_20k_buf
);
3487 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
3490 new_confline(&ctmp
);
3491 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3494 new_confline(&ctmp
);
3495 ctmp
->var
= &fldr_type_var
;
3496 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3497 ctmp
->help
= NO_HELP
;
3499 snprintf(tmp
, sizeof(tmp
), "%s =", fldr_type_var
.name
);
3500 tmp
[sizeof(tmp
)-1] = '\0';
3501 ctmp
->varname
= cpystr(tmp
);
3502 ctmp
->varnamep
= ctmpb
= ctmp
;
3503 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3505 new_confline(&ctmp
);
3507 ctmp
->valoffset
= rindent
;
3508 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3509 ctmp
->help
= NO_HELP
;
3511 ctmp
->varnamep
= ctmpb
;
3512 ctmp
->flags
|= CF_NOSELECT
;
3513 ctmp
->value
= cpystr("Set Choose One");
3515 new_confline(&ctmp
);
3517 ctmp
->valoffset
= rindent
;
3518 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3519 ctmp
->help
= NO_HELP
;
3520 ctmp
->tool
= radio_tool
;
3521 ctmp
->varnamep
= ctmpb
;
3522 ctmp
->flags
|= CF_NOSELECT
;
3523 ctmp
->value
= cpystr(set_choose
); \
3525 /* find longest value's name */
3526 for(lv
= 0, i
= 0; (f
= pat_fldr_types(i
)); i
++)
3527 if(lv
< (j
= utf8_width(f
->name
)))
3533 for(i
= 0; (f
= pat_fldr_types(i
)); i
++){
3534 new_confline(&ctmp
);
3535 ctmp
->help_title
= _("HELP FOR CURRENT FOLDER TYPE");
3536 ctmp
->var
= &fldr_type_var
;
3537 ctmp
->valoffset
= rindent
;
3538 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3539 ctmp
->help
= edit_role
? h_config_role_fldr_type
:
3540 edit_incol
? h_config_incol_fldr_type
:
3541 edit_score
? h_config_score_fldr_type
:
3542 edit_other
? h_config_other_fldr_type
3543 : h_config_filt_fldr_type
;
3545 ctmp
->tool
= radio_tool
;
3546 ctmp
->varnamep
= ctmpb
;
3548 if((PVAL(&fldr_type_var
, ew
) &&
3549 !strucmp(PVAL(&fldr_type_var
, ew
), f
->name
))
3550 || (!PVAL(&fldr_type_var
, ew
) && f
->value
== FLDR_DEFL
))
3553 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w",
3554 (fval
== f
->value
) ? R_SELD
: ' ',
3556 tmp
[sizeof(tmp
)-1] = '\0';
3557 ctmp
->value
= cpystr(tmp
);
3561 /* 5 is the width of `(*) ' */
3562 setup_role_pat_alt(ps
, &ctmp
, &folder_pat_var
,
3563 edit_role
? h_config_role_fldr_type
:
3564 edit_incol
? h_config_incol_fldr_type
:
3565 edit_score
? h_config_score_fldr_type
:
3566 edit_other
? h_config_other_fldr_type
3567 : h_config_filt_fldr_type
,
3568 _("HELP FOR FOLDER LIST"),
3569 &config_role_patfolder_keymenu
, t_tool
, rindent
+5,
3570 !(fval
== FLDR_SPECIFIC
));
3572 if(!per_folder_only
){ /* sorry about that indent */
3575 new_confline(&ctmp
);
3576 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3578 new_confline(&ctmp
);
3579 ctmp
->flags
|= CF_NOSELECT
;
3581 /* TRANSLATORS: The %s is replaced with one of the 4 or 5 words below, CURRENT,
3582 SCORED, and so on. */
3583 snprintf(mstr
, sizeof(mstr
), _(" %s MESSAGE CONDITIONS BEGIN HERE "),
3584 edit_role
? _("CURRENT") :
3585 edit_score
? _("SCORED") :
3586 edit_incol
? _("COLORED") :
3587 edit_filter
? _("FILTERED") : _("CURRENT"));
3588 mstr
[sizeof(mstr
)-1] = '\0';
3590 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(mstr
)) + 4){
3593 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
3594 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
3595 mstr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
3596 ctmp
->value
= cpystr(tmp_20k_buf
);
3599 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
3602 new_confline(&ctmp
);
3603 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3605 setup_role_pat(ps
, &ctmp
, &to_pat_var
,
3606 edit_role
? h_config_role_topat
:
3607 edit_incol
? h_config_incol_topat
:
3608 edit_score
? h_config_score_topat
:
3609 edit_other
? h_config_other_topat
3610 : h_config_filt_topat
,
3611 _("HELP FOR TO PATTERN"),
3612 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3614 setup_role_pat(ps
, &ctmp
, &from_pat_var
, h_config_role_frompat
,
3615 _("HELP FOR FROM PATTERN"),
3616 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3618 setup_role_pat(ps
, &ctmp
, &sender_pat_var
, h_config_role_senderpat
,
3619 _("HELP FOR SENDER PATTERN"),
3620 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3622 setup_role_pat(ps
, &ctmp
, &cc_pat_var
, h_config_role_ccpat
,
3623 _("HELP FOR CC PATTERN"),
3624 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3626 setup_role_pat(ps
, &ctmp
, &news_pat_var
, h_config_role_newspat
,
3627 _("HELP FOR NEWS PATTERN"),
3628 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3630 setup_role_pat(ps
, &ctmp
, &subj_pat_var
, h_config_role_subjpat
,
3631 _("HELP FOR SUBJECT PATTERN"),
3632 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3634 setup_role_pat(ps
, &ctmp
, &recip_pat_var
, h_config_role_recippat
,
3635 _("HELP FOR RECIPIENT PATTERN"),
3636 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3638 setup_role_pat(ps
, &ctmp
, &partic_pat_var
, h_config_role_particpat
,
3639 _("HELP FOR PARTICIPANT PATTERN"),
3640 &config_role_addr_pat_keymenu
, t_tool
, &earb
, pindent
);
3642 /* Arbitrary Patterns */
3644 for(j
= 0, a
= (def
&& def
->patgrp
) ? def
->patgrp
->arbhdr
: NULL
;
3647 char *fn
= (a
->field
) ? a
->field
: "";
3650 ea
->next
= (EARB_S
*)fs_get(sizeof(*ea
));
3654 earb
= (EARB_S
*)fs_get(sizeof(*ea
));
3658 memset((void *)ea
, 0, sizeof(*ea
));
3659 ea
->v
= (struct variable
*)fs_get(sizeof(struct variable
));
3660 memset((void *)ea
->v
, 0, sizeof(struct variable
));
3661 ea
->a
= (ARBHDR_S
*)fs_get(sizeof(ARBHDR_S
));
3662 memset((void *)ea
->a
, 0, sizeof(ARBHDR_S
));
3664 ea
->a
->field
= cpystr(fn
);
3666 p
= (char *) fs_get(strlen(fn
) + strlen(" pattern") + 1);
3667 snprintf(p
, strlen(fn
) + strlen(" pattern") + 1, "%s pattern", fn
);
3668 p
[strlen(fn
) + strlen(" pattern") + 1 - 1] = '\0';
3669 setup_dummy_pattern_var(ea
->v
, p
, a
->p
);
3670 fs_give((void **) &p
);
3671 setup_role_pat(ps
, &ctmp
, ea
->v
, h_config_role_arbpat
,
3672 ARB_HELP
, &config_role_xtrahdr_keymenu
,
3673 t_tool
, &earb
, pindent
);
3676 new_confline(&ctmp
);
3677 ctmp
->help_title
= _("HELP FOR EXTRA HEADERS");
3678 ctmp
->value
= cpystr(ADDXHDRS
);
3679 ctmp
->keymenu
= &config_role_keymenu_extra
;
3680 ctmp
->help
= h_config_role_arbpat
;
3681 ctmp
->tool
= addhdr_tool
;
3682 ctmp
->d
.earb
= &earb
;
3685 setup_role_pat(ps
, &ctmp
, &alltext_pat_var
, h_config_role_alltextpat
,
3686 _("HELP FOR ALL TEXT PATTERN"),
3687 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3689 setup_role_pat(ps
, &ctmp
, &bodytext_pat_var
, h_config_role_bodytextpat
,
3690 _("HELP FOR BODY TEXT PATTERN"),
3691 &config_role_keymenu_not
, t_tool
, &earb
, pindent
);
3694 new_confline(&ctmp
);
3695 ctmp
->help_title
= _("HELP FOR AGE INTERVAL");
3696 ctmp
->var
= &age_pat_var
;
3697 ctmp
->valoffset
= pindent
;
3698 ctmp
->keymenu
= &config_text_keymenu
;
3699 ctmp
->help
= h_config_role_age
;
3700 ctmp
->tool
= t_tool
;
3701 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, age_pat_var
.name
);
3702 tmp
[sizeof(tmp
)-1] = '\0';
3703 ctmp
->varname
= cpystr(tmp
);
3704 ctmp
->varnamep
= ctmp
;
3705 ctmp
->value
= pretty_value(ps
, ctmp
);
3708 new_confline(&ctmp
);
3709 ctmp
->help_title
= _("HELP FOR SIZE INTERVAL");
3710 ctmp
->var
= &size_pat_var
;
3711 ctmp
->valoffset
= pindent
;
3712 ctmp
->keymenu
= &config_text_keymenu
;
3713 ctmp
->help
= h_config_role_size
;
3714 ctmp
->tool
= t_tool
;
3715 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, size_pat_var
.name
);
3716 tmp
[sizeof(tmp
)-1] = '\0';
3717 ctmp
->varname
= cpystr(tmp
);
3718 ctmp
->varnamep
= ctmp
;
3719 ctmp
->value
= pretty_value(ps
, ctmp
);
3722 /* Score Interval */
3723 new_confline(&ctmp
);
3724 ctmp
->help_title
= _("HELP FOR SCORE INTERVAL");
3725 ctmp
->var
= &scorei_pat_var
;
3726 ctmp
->valoffset
= pindent
;
3727 ctmp
->keymenu
= &config_text_keymenu
;
3728 ctmp
->help
= h_config_role_scorei
;
3729 ctmp
->tool
= t_tool
;
3730 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", pindent
-3, pindent
-3, scorei_pat_var
.name
);
3731 tmp
[sizeof(tmp
)-1] = '\0';
3732 ctmp
->varname
= cpystr(tmp
);
3733 ctmp
->varnamep
= ctmp
;
3734 ctmp
->value
= pretty_value(ps
, ctmp
);
3737 /* Keyword Pattern */
3738 setup_role_pat(ps
, &ctmp
, &keyword_pat_var
, h_config_role_keywordpat
,
3739 _("HELP FOR KEYWORD PATTERN"),
3740 &config_role_keyword_keymenu_not
, role_text_tool_kword
,
3743 /* Charset Pattern */
3744 setup_role_pat(ps
, &ctmp
, &charset_pat_var
, h_config_role_charsetpat
,
3745 _("HELP FOR CHARACTER SET PATTERN"),
3746 &config_role_charset_keymenu_not
, role_text_tool_charset
,
3749 /* Important Status */
3750 SETUP_PAT_STATUS(ctmp
, stat_imp_var
, def
->patgrp
->stat_imp
,
3751 _("HELP FOR IMPORTANT STATUS"), h_config_role_stat_imp
);
3753 SETUP_PAT_STATUS(ctmp
, stat_new_var
, def
->patgrp
->stat_new
,
3754 _("HELP FOR NEW STATUS"), h_config_role_stat_new
);
3756 SETUP_PAT_STATUS(ctmp
, stat_rec_var
, def
->patgrp
->stat_rec
,
3757 _("HELP FOR RECENT STATUS"), h_config_role_stat_recent
);
3758 /* Deleted Status */
3759 SETUP_PAT_STATUS(ctmp
, stat_del_var
, def
->patgrp
->stat_del
,
3760 _("HELP FOR DELETED STATUS"), h_config_role_stat_del
);
3761 /* Answered Status */
3762 SETUP_PAT_STATUS(ctmp
, stat_ans_var
, def
->patgrp
->stat_ans
,
3763 _("HELP FOR ANSWERED STATUS"), h_config_role_stat_ans
);
3765 SETUP_PAT_STATUS(ctmp
, stat_8bit_var
, def
->patgrp
->stat_8bitsubj
,
3766 _("HELP FOR 8-BIT SUBJECT"), h_config_role_stat_8bitsubj
);
3767 /* Beginning of month */
3768 SETUP_PAT_STATUS(ctmp
, stat_bom_var
, def
->patgrp
->stat_bom
,
3769 _("HELP FOR BEGINNING OF MONTH"), h_config_role_bom
);
3770 /* Beginning of year */
3771 SETUP_PAT_STATUS(ctmp
, stat_boy_var
, def
->patgrp
->stat_boy
,
3772 _("HELP FOR BEGINNING OF YEAR"), h_config_role_boy
);
3775 new_confline(&ctmp
);
3776 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3778 /* From in Addrbook */
3779 new_confline(&ctmp
);
3780 ctmp
->var
= &abook_type_var
;
3781 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3782 ctmp
->help
= NO_HELP
;
3784 snprintf(tmp
, sizeof(tmp
), "%s =", abook_type_var
.name
);
3785 tmp
[sizeof(tmp
)-1] = '\0';
3786 ctmp
->varname
= cpystr(tmp
);
3787 ctmp
->varnamep
= ctmpb
= ctmp
;
3788 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3790 new_confline(&ctmp
);
3792 ctmp
->valoffset
= rindent
;
3793 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3794 ctmp
->help
= NO_HELP
;
3796 ctmp
->varnamep
= ctmpb
;
3797 ctmp
->flags
|= CF_NOSELECT
;
3798 ctmp
->value
= cpystr("Set Choose One");
3800 new_confline(&ctmp
);
3802 ctmp
->valoffset
= rindent
;
3803 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3804 ctmp
->help
= NO_HELP
;
3805 ctmp
->tool
= radio_tool
;
3806 ctmp
->varnamep
= ctmpb
;
3807 ctmp
->flags
|= CF_NOSELECT
;
3808 ctmp
->value
= cpystr(set_choose
); \
3810 /* find longest value's name */
3811 for(lv
= 0, i
= 0; (f
= inabook_fldr_types(i
)); i
++)
3812 if(lv
< (j
= utf8_width(f
->name
)))
3818 for(i
= 0; (f
= inabook_fldr_types(i
)); i
++){
3819 new_confline(&ctmp
);
3820 ctmp
->help_title
= _("HELP FOR ADDRESS IN ADDRESS BOOK");
3821 ctmp
->var
= &abook_type_var
;
3822 ctmp
->valoffset
= rindent
;
3823 ctmp
->keymenu
= &config_radiobutton_keymenu
;
3824 ctmp
->help
= h_config_role_abookfrom
;
3826 ctmp
->tool
= radio_tool
;
3827 ctmp
->varnamep
= ctmpb
;
3829 if((PVAL(&abook_type_var
, ew
) &&
3830 !strucmp(PVAL(&abook_type_var
, ew
), f
->name
))
3831 || (!PVAL(&abook_type_var
, ew
) && f
->value
== IAB_DEFL
))
3834 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w",
3835 (fval
== f
->value
) ? R_SELD
: ' ',
3837 tmp
[sizeof(tmp
)-1] = '\0';
3838 ctmp
->value
= cpystr(tmp
);
3841 /* Specific list of abooks */
3842 /* 5 is the width of `(*) ' */
3843 setup_role_pat_alt(ps
, &ctmp
, &abook_pat_var
, h_config_role_abookfrom
,
3844 _("HELP FOR ABOOK LIST"),
3845 &config_role_afrom_keymenu
, role_text_tool_afrom
, rindent
+5,
3846 !(fval
== IAB_SPEC_YES
|| fval
== IAB_SPEC_NO
));
3848 /* Which addresses to check for */
3849 inabook_type_var
.name
= cpystr(_("Types of addresses to check for in address book"));
3850 inabook_type_var
.is_used
= 1;
3851 inabook_type_var
.is_user
= 1;
3852 inabook_type_var
.is_list
= 1;
3853 clrbitmap(inabook_type_list
);
3854 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_FROM
)
3855 setbitn(INABOOK_FROM
, inabook_type_list
);
3856 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_REPLYTO
)
3857 setbitn(INABOOK_REPLYTO
, inabook_type_list
);
3858 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_SENDER
)
3859 setbitn(INABOOK_SENDER
, inabook_type_list
);
3860 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_TO
)
3861 setbitn(INABOOK_TO
, inabook_type_list
);
3862 if(def
&& def
->patgrp
&& def
->patgrp
->inabook
& IAB_CC
)
3863 setbitn(INABOOK_CC
, inabook_type_list
);
3865 /* default setting */
3866 if(!(bitnset(INABOOK_FROM
, inabook_type_list
)
3867 || bitnset(INABOOK_REPLYTO
, inabook_type_list
)
3868 || bitnset(INABOOK_SENDER
, inabook_type_list
)
3869 || bitnset(INABOOK_TO
, inabook_type_list
)
3870 || bitnset(INABOOK_CC
, inabook_type_list
))){
3871 setbitn(INABOOK_FROM
, inabook_type_list
);
3872 setbitn(INABOOK_REPLYTO
, inabook_type_list
);
3875 new_confline(&ctmp
);
3876 ctmp
->var
= &inabook_type_var
;
3877 ctmp
->varoffset
= 4;
3878 ctmp
->valoffset
= 23;
3879 ctmp
->keymenu
= &config_checkbox_keymenu
;
3880 ctmp
->help
= NO_HELP
;
3882 snprintf(tmp
, sizeof(tmp
), "%-20s =", inabook_type_var
.name
);
3883 tmp
[sizeof(tmp
)-1] = '\0';
3884 ctmp
->varname
= cpystr(tmp
);
3885 ctmp
->varnamep
= ctmpb
= ctmp
;
3886 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3888 new_confline(&ctmp
);
3890 ctmp
->valoffset
= rindent
;
3891 ctmp
->keymenu
= &config_checkbox_keymenu
;
3892 ctmp
->help
= NO_HELP
;
3893 ctmp
->tool
= inabook_checkbox_tool
;
3894 ctmp
->varnamep
= ctmpb
;
3895 ctmp
->flags
|= CF_NOSELECT
;
3896 ctmp
->value
= cpystr("Set Address types");
3898 new_confline(&ctmp
);
3900 ctmp
->valoffset
= rindent
;
3901 ctmp
->keymenu
= &config_checkbox_keymenu
;
3902 ctmp
->help
= NO_HELP
;
3903 ctmp
->tool
= inabook_checkbox_tool
;
3904 ctmp
->varnamep
= ctmpb
;
3905 ctmp
->flags
|= CF_NOSELECT
;
3906 ctmp
->value
= cpystr(set_choose
);
3908 /* find longest value's name */
3909 for(lv
= 0, i
= 0; (f
= inabook_feature_list(i
)); i
++){
3910 if(lv
< (j
= utf8_width(f
->name
)))
3916 for(i
= 0; (f
= inabook_feature_list(i
)); i
++){
3917 new_confline(&ctmp
);
3918 ctmp
->var
= &opt_var
;
3919 ctmp
->help_title
= _("HELP FOR ADDRESS TYPES");
3920 ctmp
->varnamep
= ctmpb
;
3921 ctmp
->keymenu
= &config_checkbox_keymenu
;
3924 ctmp
->help
= h_config_inabook_from
;
3926 case INABOOK_REPLYTO
:
3927 ctmp
->help
= h_config_inabook_replyto
;
3929 case INABOOK_SENDER
:
3930 ctmp
->help
= h_config_inabook_sender
;
3933 ctmp
->help
= h_config_inabook_to
;
3936 ctmp
->help
= h_config_inabook_cc
;
3940 ctmp
->tool
= inabook_checkbox_tool
;
3941 ctmp
->valoffset
= rindent
;
3943 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w",
3944 bitnset(f
->value
, inabook_type_list
) ? 'X' : ' ',
3946 tmp
[sizeof(tmp
)-1] = '\0';
3947 ctmp
->value
= cpystr(tmp
);
3951 new_confline(&ctmp
);
3952 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
3954 /* 4 is indent of "Command", c_v_n is longest of these three, 3 is ` = ' */
3955 i
= 4 + utf8_width(c_v_n
) + 3;
3957 /* External Command Categorizer */
3958 new_confline(&ctmp
);
3959 ctmp
->var
= &cat_cmd_var
;
3960 ctmp
->keymenu
= &config_text_keymenu
;
3961 ctmp
->help
= NO_HELP
;
3963 snprintf(tmp
, sizeof(tmp
), "%s =", cat_cmd_var
.name
);
3964 tmp
[sizeof(tmp
)-1] = '\0';
3965 ctmp
->varname
= cpystr(tmp
);
3966 ctmp
->varnamep
= ctmpb
= ctmp
;
3967 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
3970 new_confline(&ctmp
);
3971 ctmp
->help_title
= _("HELP FOR CATEGORIZER COMMAND");
3972 ctmp
->var
= &cat_cmd_var
;
3973 ctmp
->varoffset
= 4;
3974 ctmp
->valoffset
= i
;
3975 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
3976 ctmp
->help
= h_config_role_cat_cmd
;
3977 ctmp
->tool
= t_tool
;
3978 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", i
-4-3, i
-4-3, "Command");
3979 tmp
[sizeof(tmp
)-1] = '\0';
3980 ctmp
->varname
= cpystr(tmp
);
3981 ctmp
->varnamep
= ctmpb
= ctmp
;
3982 ctmp
->flags
= CF_STARTITEM
;
3984 if((lval
= LVAL(&cat_cmd_var
, ew
)) != NULL
&& lval
[0]){
3985 for(j
= 0; lval
[j
]; j
++){
3987 (void) new_confline(&ctmp
);
3989 ctmp
->var
= &cat_cmd_var
;
3991 ctmp
->valoffset
= i
;
3992 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
3993 ctmp
->help
= h_config_role_cat_cmd
;
3994 ctmp
->tool
= t_tool
;
3995 ctmp
->varnamep
= ctmp
;
3996 ctmp
->value
= pretty_value(ps
, ctmp
);
4000 ctmp
->value
= pretty_value(ps
, ctmp
);
4002 /* Exit status interval */
4003 new_confline(&ctmp
);
4004 ctmp
->help_title
= _("HELP FOR CATEGORIZER EXIT STATUS");
4005 ctmp
->var
= &cati_var
;
4006 ctmp
->varoffset
= 4;
4007 ctmp
->valoffset
= i
;
4008 ctmp
->keymenu
= &config_text_keymenu
;
4009 ctmp
->help
= h_config_role_cat_status
;
4010 ctmp
->tool
= t_tool
;
4011 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", i
-4-3, i
-4-3, cati_var
.name
);
4012 tmp
[sizeof(tmp
)-1] = '\0';
4013 ctmp
->varname
= cpystr(tmp
);
4014 ctmp
->varnamep
= ctmp
;
4015 ctmp
->value
= pretty_value(ps
, ctmp
);
4017 /* Character Limit */
4018 new_confline(&ctmp
);
4019 ctmp
->help_title
= _("HELP FOR CHARACTER LIMIT");
4020 ctmp
->var
= &cat_lim_var
;
4021 ctmp
->varoffset
= 4;
4022 ctmp
->valoffset
= i
;
4023 ctmp
->keymenu
= &config_text_keymenu
;
4024 ctmp
->help
= h_config_role_cat_limit
;
4025 ctmp
->tool
= t_tool
;
4026 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", i
-4-3, i
-4-3, cat_lim_var
.name
);
4027 tmp
[sizeof(tmp
)-1] = '\0';
4028 ctmp
->varname
= cpystr(tmp
);
4029 ctmp
->varnamep
= ctmp
;
4030 ctmp
->value
= pretty_value(ps
, ctmp
);
4031 ctmp
->flags
|= CF_NUMBER
;
4034 if(!edit_srch
){ /* sorry about that indent */
4038 new_confline(&ctmp
);
4039 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4041 new_confline(&ctmp
);
4042 ctmp
->flags
|= CF_NOSELECT
;
4043 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(astr
)) + 4){
4046 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
4047 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
4048 astr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
4049 ctmp
->value
= cpystr(tmp_20k_buf
);
4052 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
4057 roindent
= utf8_width(u_s_s
); /* the longest one */
4058 roindent
+= 3; /* width of ` = ' */
4061 new_confline(&ctmp
);
4062 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4064 /* Inherit Nickname */
4065 new_confline(&ctmp
);
4066 inick_confs
[INICK_INICK_CONF
] = ctmp
;
4067 ctmp
->help_title
= _("HELP FOR INITIAL SET NICKNAME");
4068 ctmp
->var
= &inick_var
;
4069 ctmp
->keymenu
= &config_role_inick_keymenu
;
4070 ctmp
->help
= h_config_role_inick
;
4071 ctmp
->tool
= role_text_tool_inick
;
4072 snprintf(tmp
, sizeof(tmp
), "%s :", inick_var
.name
);
4073 tmp
[sizeof(tmp
)-1] = '\0';
4074 ctmp
->valoffset
= utf8_width(tmp
)+1;
4075 ctmp
->varname
= cpystr(tmp
);
4076 ctmp
->varnamep
= ctmp
;
4079 new_confline(&ctmp
);
4080 inick_confs
[INICK_FROM_CONF
] = ctmp
;
4081 ctmp
->help_title
= _("HELP FOR SET FROM ACTION");
4082 ctmp
->var
= &from_act_var
;
4083 ctmp
->valoffset
= roindent
;
4084 ctmp
->keymenu
= &config_role_addr_act_keymenu
;
4085 ctmp
->help
= h_config_role_setfrom
;
4086 ctmp
->tool
= role_text_tool
;
4087 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, from_act_var
.name
);
4088 tmp
[sizeof(tmp
)-1] = '\0';
4089 ctmp
->varname
= cpystr(tmp
);
4090 ctmp
->varnamep
= ctmp
;
4092 /* Reply-To Action */
4093 new_confline(&ctmp
);
4094 inick_confs
[INICK_REPLYTO_CONF
] = ctmp
;
4095 ctmp
->help_title
= _("HELP FOR SET REPLY-TO ACTION");
4096 ctmp
->var
= &replyto_act_var
;
4097 ctmp
->valoffset
= roindent
;
4098 ctmp
->keymenu
= &config_role_addr_act_keymenu
;
4099 ctmp
->help
= h_config_role_setreplyto
;
4100 ctmp
->tool
= role_text_tool
;
4101 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, replyto_act_var
.name
);
4102 tmp
[sizeof(tmp
)-1] = '\0';
4103 ctmp
->varname
= cpystr(tmp
);
4104 ctmp
->varnamep
= ctmp
;
4107 new_confline(&ctmp
);
4108 inick_confs
[INICK_FCC_CONF
] = ctmp
;
4109 ctmp
->help_title
= _("HELP FOR SET FCC ACTION");
4110 ctmp
->var
= &fcc_act_var
;
4111 ctmp
->valoffset
= roindent
;
4112 ctmp
->keymenu
= &config_role_actionfolder_keymenu
;
4113 ctmp
->help
= h_config_role_setfcc
;
4114 ctmp
->tool
= role_text_tool
;
4115 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, fcc_act_var
.name
);
4116 tmp
[sizeof(tmp
)-1] = '\0';
4117 ctmp
->varname
= cpystr(tmp
);
4118 ctmp
->varnamep
= ctmp
;
4121 new_confline(&ctmp
);
4122 inick_confs
[INICK_LITSIG_CONF
] = ctmp
;
4123 ctmp
->help_title
= _("HELP FOR SET LITERAL SIGNATURE ACTION");
4124 ctmp
->var
= &litsig_act_var
;
4125 ctmp
->valoffset
= roindent
;
4126 ctmp
->keymenu
= &config_text_keymenu
;
4127 ctmp
->help
= h_config_role_setlitsig
;
4128 ctmp
->tool
= role_litsig_text_tool
;
4129 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, litsig_act_var
.name
);
4130 tmp
[sizeof(tmp
)-1] = '\0';
4131 ctmp
->varname
= cpystr(tmp
);
4132 ctmp
->varnamep
= ctmp
;
4135 new_confline(&ctmp
);
4136 inick_confs
[INICK_SIG_CONF
] = ctmp
;
4137 ctmp
->help_title
= _("HELP FOR SET SIGNATURE ACTION");
4138 ctmp
->var
= &sig_act_var
;
4139 ctmp
->valoffset
= roindent
;
4140 if(F_ON(F_DISABLE_ROLES_SIGEDIT
, ps_global
))
4141 ctmp
->keymenu
= &config_role_file_res_keymenu
;
4143 ctmp
->keymenu
= &config_role_file_keymenu
;
4145 ctmp
->help
= h_config_role_setsig
;
4146 ctmp
->tool
= role_text_tool
;
4147 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, sig_act_var
.name
);
4148 tmp
[sizeof(tmp
)-1] = '\0';
4149 ctmp
->varname
= cpystr(tmp
);
4150 ctmp
->varnamep
= ctmp
;
4152 /* Template Action */
4153 new_confline(&ctmp
);
4154 inick_confs
[INICK_TEMPL_CONF
] = ctmp
;
4155 ctmp
->help_title
= _("HELP FOR SET TEMPLATE ACTION");
4156 ctmp
->var
= &templ_act_var
;
4157 ctmp
->valoffset
= roindent
;
4158 if(F_ON(F_DISABLE_ROLES_TEMPLEDIT
, ps_global
))
4159 ctmp
->keymenu
= &config_role_file_res_keymenu
;
4161 ctmp
->keymenu
= &config_role_file_keymenu
;
4163 ctmp
->help
= h_config_role_settempl
;
4164 ctmp
->tool
= role_text_tool
;
4165 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, templ_act_var
.name
);
4166 tmp
[sizeof(tmp
)-1] = '\0';
4167 ctmp
->varname
= cpystr(tmp
);
4168 ctmp
->varnamep
= ctmp
;
4170 /* Other Headers Action */
4171 new_confline(&ctmp
);
4172 inick_confs
[INICK_CSTM_CONF
] = ctmp
;
4173 ctmp
->help_title
= _("HELP FOR SET OTHER HEADERS ACTION");
4174 ctmp
->var
= &cstm_act_var
;
4175 ctmp
->valoffset
= roindent
;
4176 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4177 ctmp
->help
= h_config_role_setotherhdr
;
4178 ctmp
->tool
= role_cstm_text_tool
;
4179 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, cstm_act_var
.name
);
4180 tmp
[sizeof(tmp
)-1] = '\0';
4181 ctmp
->varname
= cpystr(tmp
);
4182 ctmp
->varnamep
= ctmpb
= ctmp
;
4183 ctmp
->flags
= CF_STARTITEM
;
4185 if((lval
= LVAL(&cstm_act_var
, ew
)) != NULL
){
4186 for(i
= 0; lval
[i
]; i
++){
4188 (void)new_confline(&ctmp
);
4190 ctmp
->var
= &cstm_act_var
;
4192 ctmp
->valoffset
= roindent
;
4193 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4194 ctmp
->help
= h_config_role_setotherhdr
;
4195 ctmp
->tool
= role_cstm_text_tool
;
4196 ctmp
->varnamep
= ctmpb
;
4202 /* SMTP Server Action */
4203 new_confline(&ctmp
);
4204 inick_confs
[INICK_SMTP_CONF
] = ctmp
;
4205 ctmp
->help_title
= _("HELP FOR SMTP SERVER ACTION");
4206 ctmp
->var
= &smtp_act_var
;
4207 ctmp
->valoffset
= roindent
;
4208 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4209 ctmp
->help
= h_config_role_usesmtp
;
4210 ctmp
->tool
= t_tool
;
4211 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, smtp_act_var
.name
);
4212 tmp
[sizeof(tmp
)-1] = '\0';
4213 ctmp
->varname
= cpystr(tmp
);
4214 ctmp
->varnamep
= ctmpb
= ctmp
;
4215 ctmp
->flags
= CF_STARTITEM
;
4217 if((lval
= LVAL(&smtp_act_var
, ew
)) != NULL
){
4218 for(i
= 0; lval
[i
]; i
++){
4220 (void)new_confline(&ctmp
);
4222 ctmp
->var
= &smtp_act_var
;
4224 ctmp
->valoffset
= roindent
;
4225 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4226 ctmp
->help
= h_config_role_usesmtp
;
4227 ctmp
->tool
= t_tool
;
4228 ctmp
->varnamep
= ctmpb
;
4234 /* NNTP Server Action */
4235 new_confline(&ctmp
);
4236 inick_confs
[INICK_NNTP_CONF
] = ctmp
;
4237 ctmp
->help_title
= _("HELP FOR NNTP SERVER ACTION");
4238 ctmp
->var
= &nntp_act_var
;
4239 ctmp
->valoffset
= roindent
;
4240 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4241 ctmp
->help
= h_config_role_usenntp
;
4242 ctmp
->tool
= t_tool
;
4243 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", roindent
-3, roindent
-3, nntp_act_var
.name
);
4244 tmp
[sizeof(tmp
)-1] = '\0';
4245 ctmp
->varname
= cpystr(tmp
);
4246 ctmp
->varnamep
= ctmpb
= ctmp
;
4247 ctmp
->flags
= CF_STARTITEM
;
4249 if((lval
= LVAL(&nntp_act_var
, ew
)) != NULL
){
4250 for(i
= 0; lval
[i
]; i
++){
4252 (void)new_confline(&ctmp
);
4254 ctmp
->var
= &nntp_act_var
;
4256 ctmp
->valoffset
= roindent
;
4257 ctmp
->keymenu
= &config_text_wshuf_keymenu
;
4258 ctmp
->help
= h_config_role_usenntp
;
4259 ctmp
->tool
= t_tool
;
4260 ctmp
->varnamep
= ctmpb
;
4266 calculate_inick_stuff(ps
);
4269 inick_confs
[INICK_INICK_CONF
] = NULL
;
4274 sindent
= MAX(utf8_width(score_act_var
.name
),utf8_width(hdrtok_act_var
.name
)) + 3;
4277 new_confline(&ctmp
);
4278 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4280 /* Score Value -- This doesn't inherit from inick */
4281 new_confline(&ctmp
);
4282 ctmp
->help_title
= _("HELP FOR SCORE VALUE ACTION");
4283 ctmp
->var
= &score_act_var
;
4284 ctmp
->valoffset
= sindent
;
4285 ctmp
->keymenu
= &config_text_keymenu
;
4286 ctmp
->help
= h_config_role_scoreval
;
4287 ctmp
->tool
= text_tool
;
4288 ctmp
->flags
|= CF_NUMBER
;
4289 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", sindent
-3, sindent
-3, score_act_var
.name
);
4290 tmp
[sizeof(tmp
)-1] = '\0';
4291 ctmp
->varname
= cpystr(tmp
);
4292 ctmp
->varnamep
= ctmp
;
4293 ctmp
->value
= pretty_value(ps
, ctmp
);
4295 new_confline(&ctmp
);
4296 ctmp
->flags
|= CF_NOSELECT
;
4297 ctmp
->value
= cpystr(" OR");
4299 /* Score From Header */
4300 new_confline(&ctmp
);
4301 ctmp
->help_title
= _("HELP FOR SCORE VALUE FROM HEADER ACTION");
4302 ctmp
->var
= &hdrtok_act_var
;
4303 ctmp
->valoffset
= sindent
;
4304 ctmp
->keymenu
= &config_text_keymenu
;
4305 ctmp
->help
= h_config_role_scorehdrtok
;
4306 ctmp
->tool
= text_tool
;
4307 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", sindent
-3, sindent
-3, hdrtok_act_var
.name
);
4308 tmp
[sizeof(tmp
)-1] = '\0';
4309 ctmp
->varname
= cpystr(tmp
);
4310 ctmp
->varnamep
= ctmp
;
4311 ctmp
->value
= pretty_value(ps
, ctmp
);
4316 * Filtering got added in stages, so instead of simply having a
4317 * variable in action which is set to one of the three possible
4318 * values (FILTER_KILL, FILTER_STATE, FILTER_FOLDER) we infer
4319 * the value from other variables. (Perhaps it would still make
4320 * sense to change this.)
4321 * Action->kill is set iff the user checks Delete.
4322 * If the user checks the box that says Just Set State, then kill
4323 * is not set and action->folder is not set (and vice versa).
4324 * And finally, FILTER_FOLDER is set if !kill and action->folder is set.
4325 * (And it is set here as the default if there is no default
4326 * action and the user is required to fill in the Folder.)
4328 if(def
&& def
->action
&& def
->action
->kill
)
4330 else if(def
&& def
->action
&& !def
->action
->kill
&&
4331 !def
->action
->folder
)
4332 fval
= FILTER_STATE
;
4334 fval
= FILTER_FOLDER
;
4336 role_filt_ptr
= &filter_type_var
; /* so radiobuttons can tell */
4337 filter_type_var
.name
= cpystr(_("Filter Action"));
4338 filter_type_var
.is_used
= 1;
4339 filter_type_var
.is_user
= 1;
4340 apval
= APVAL(&filter_type_var
, ew
);
4341 *apval
= (f
=filter_types(fval
)) ? cpystr(f
->name
) : NULL
;
4342 set_current_val(&filter_type_var
, FALSE
, FALSE
);
4345 new_confline(&ctmp
);
4346 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4349 new_confline(&ctmp
);
4350 ctmp
->var
= &filter_type_var
;
4351 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4352 ctmp
->help
= NO_HELP
;
4354 snprintf(tmp
, sizeof(tmp
), "%s =", filter_type_var
.name
);
4355 tmp
[sizeof(tmp
)-1] = '\0';
4356 ctmp
->varname
= cpystr(tmp
);
4357 ctmp
->varnamep
= ctmpb
= ctmp
;
4358 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4360 new_confline(&ctmp
);
4362 ctmp
->valoffset
= rindent
;
4363 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4364 ctmp
->help
= NO_HELP
;
4366 ctmp
->varnamep
= ctmpb
;
4367 ctmp
->flags
|= CF_NOSELECT
;
4368 ctmp
->value
= cpystr("Set Choose One");
4370 new_confline(&ctmp
);
4372 ctmp
->valoffset
= rindent
;
4373 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4374 ctmp
->help
= NO_HELP
;
4375 ctmp
->tool
= radio_tool
;
4376 ctmp
->varnamep
= ctmpb
;
4377 ctmp
->flags
|= CF_NOSELECT
;
4378 ctmp
->value
= cpystr(set_choose
); \
4380 /* find longest value's name */
4381 for(lv
= 0, i
= 0; (f
= filter_types(i
)); i
++)
4382 if(lv
< (j
= utf8_width(f
->name
)))
4387 for(i
= 0; (f
= filter_types(i
)); i
++){
4388 new_confline(&ctmp
);
4389 ctmp
->help_title
= _("HELP FOR FILTER ACTION");
4390 ctmp
->var
= &filter_type_var
;
4391 ctmp
->valoffset
= rindent
;
4392 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4393 ctmp
->help
= h_config_filt_rule_type
;
4395 ctmp
->tool
= radio_tool
;
4396 ctmp
->varnamep
= ctmpb
;
4397 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (f
->value
== fval
) ? R_SELD
: ' ',
4399 tmp
[sizeof(tmp
)-1] = '\0';
4400 ctmp
->value
= cpystr(tmp
);
4403 /* Specific list of folders to copy to */
4404 setup_dummy_pattern_var(&folder_act_var
, _("Folder List"),
4405 (def
&& def
->action
)
4406 ? def
->action
->folder
: NULL
);
4408 /* 5 is the width of `(*) ' */
4409 setup_role_pat_alt(ps
, &ctmp
, &folder_act_var
, h_config_filter_folder
,
4410 _("HELP FOR FILTER FOLDER NAME"),
4411 &config_role_actionfolder_keymenu
, t_tool
, rindent
+5,
4412 !(fval
== FILTER_FOLDER
));
4414 SETUP_MSG_STATE(ctmp
, filt_imp_var
, ival
,
4415 _("HELP FOR SET IMPORTANT STATUS"), h_config_filt_stat_imp
);
4416 SETUP_MSG_STATE(ctmp
, filt_new_var
, nval
,
4417 _("HELP FOR SET NEW STATUS"), h_config_filt_stat_new
);
4418 SETUP_MSG_STATE(ctmp
, filt_del_var
, dval
,
4419 _("HELP FOR SET DELETED STATUS"), h_config_filt_stat_del
);
4420 SETUP_MSG_STATE(ctmp
, filt_ans_var
, aval
,
4421 _("HELP FOR SET ANSWERED STATUS"), h_config_filt_stat_ans
);
4424 new_confline(&ctmp
);
4425 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4427 /* Keywords to be Set */
4428 setup_dummy_pattern_var(&keyword_set_var
, _("Set These Keywords"),
4429 (def
&& def
->action
)
4430 ? def
->action
->keyword_set
: NULL
);
4431 setup_role_pat(ps
, &ctmp
, &keyword_set_var
, h_config_filter_kw_set
,
4432 _("HELP FOR KEYWORDS TO BE SET"),
4433 &config_role_keyword_keymenu
, role_text_tool_kword
,
4436 /* Keywords to be Cleared */
4437 setup_dummy_pattern_var(&keyword_clr_var
, _("Clear These Keywords"),
4438 (def
&& def
->action
)
4439 ? def
->action
->keyword_clr
: NULL
);
4440 setup_role_pat(ps
, &ctmp
, &keyword_clr_var
, h_config_filter_kw_clr
,
4441 _("HELP FOR KEYWORDS TO BE CLEARED"),
4442 &config_role_keyword_keymenu
, role_text_tool_kword
,
4451 new_confline(&ctmp
);
4452 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4454 new_confline(&ctmp
)->var
= NULL
;
4455 snprintf(tmp
, sizeof(tmp
), "%s =", sort_act_var
.name
);
4456 tmp
[sizeof(tmp
)-1] = '\0';
4457 ctmp
->varname
= cpystr(tmp
);
4458 ctmp
->varnamep
= ctmpb
= ctmp
;
4459 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4460 ctmp
->help
= NO_HELP
;
4461 ctmp
->tool
= role_sort_tool
;
4462 ctmp
->valoffset
= rindent
;
4463 ctmp
->flags
|= CF_NOSELECT
;
4465 new_confline(&ctmp
)->var
= NULL
;
4466 ctmp
->varnamep
= ctmpb
;
4467 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4468 ctmp
->help
= NO_HELP
;
4469 ctmp
->tool
= role_sort_tool
;
4470 ctmp
->valoffset
= rindent
;
4471 ctmp
->flags
|= CF_NOSELECT
;
4472 ctmp
->value
= cpystr("Set Sort Options");
4474 new_confline(&ctmp
)->var
= NULL
;
4475 ctmp
->varnamep
= ctmpb
;
4476 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4477 ctmp
->help
= NO_HELP
;
4478 ctmp
->tool
= role_sort_tool
;
4479 ctmp
->valoffset
= rindent
;
4480 ctmp
->flags
|= CF_NOSELECT
;
4481 ctmp
->value
= cpystr(set_choose
); \
4483 pval
= PVAL(&sort_act_var
, ew
);
4485 decode_sort(pval
, &def_sort
, &def_sort_rev
);
4487 /* allow user to set their default sort order */
4488 new_confline(&ctmp
)->var
= &sort_act_var
;
4489 ctmp
->varnamep
= ctmpb
;
4490 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4491 ctmp
->help
= h_config_perfolder_sort
;
4492 ctmp
->tool
= role_sort_tool
;
4493 ctmp
->valoffset
= rindent
;
4495 ctmp
->value
= generalized_sort_pretty_value(ps
, ctmp
, 0);
4497 for(j
= 0; j
< 2; j
++){
4498 for(i
= 0; ps
->sort_types
[i
] != EndofList
; i
++){
4499 new_confline(&ctmp
)->var
= &sort_act_var
;
4500 ctmp
->varnamep
= ctmpb
;
4501 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4502 ctmp
->help
= h_config_perfolder_sort
;
4503 ctmp
->tool
= role_sort_tool
;
4504 ctmp
->valoffset
= rindent
;
4505 ctmp
->varmem
= i
+ (j
* EndofList
);
4506 ctmp
->value
= generalized_sort_pretty_value(ps
, ctmp
,
4513 new_confline(&ctmp
);
4514 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4516 oindent
= utf8_width(iform_act_var
.name
) + 3;
4518 /* Index Format Action */
4519 new_confline(&ctmp
);
4520 ctmp
->help_title
= _("HELP FOR SET INDEX FORMAT ACTION");
4521 ctmp
->var
= &iform_act_var
;
4522 ctmp
->valoffset
= oindent
;
4523 ctmp
->keymenu
= &config_text_keymenu
;
4524 ctmp
->help
= h_config_set_index_format
;
4525 ctmp
->tool
= text_tool
;
4526 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", oindent
-3, oindent
-3, iform_act_var
.name
);
4527 tmp
[sizeof(tmp
)-1] = '\0';
4528 ctmp
->varname
= cpystr(tmp
);
4529 ctmp
->varnamep
= ctmp
;
4530 ctmp
->value
= pretty_value(ps
, ctmp
);
4533 new_confline(&ctmp
);
4534 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4536 new_confline(&ctmp
);
4537 ctmp
->flags
|= CF_STARTITEM
;
4538 utf8_snprintf(tmp
, sizeof(tmp
), "%s =", startup_var
.name
);
4539 tmp
[sizeof(tmp
)-1] = '\0';
4540 ctmp
->varname
= cpystr(tmp
);
4541 standard_radio_setup(ps
, &ctmp
, &startup_var
, NULL
);
4544 if(edit_incol
&& pico_usingcolor()){
4545 char *pval0
, *pval1
;
4549 new_confline(&ctmp
);
4550 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4552 new_confline(&ctmp
);
4553 ctmp
->var
= &rolecolor_vars
[0]; /* foreground */
4554 ctmp
->varname
= cpystr(_("Index Line Color ="));
4555 ctmp
->varnamep
= ctmpb
= ctmp
;
4556 ctmp
->flags
|= (CF_STARTITEM
| CF_NOSELECT
);
4557 ctmp
->keymenu
= &role_color_setting_keymenu
;
4559 pval0
= PVAL(&rolecolor_vars
[0], ew
);
4560 pval1
= PVAL(&rolecolor_vars
[1], ew
);
4562 def
= !(pval0
[0] && pval1
[1]);
4566 add_color_setting_disp(ps
, &ctmp
, &rolecolor_vars
[0], ctmpb
,
4567 &role_color_setting_keymenu
,
4568 &config_checkbox_keymenu
,
4571 def
? ps
->VAR_NORM_FORE_COLOR
4572 : PVAL(&rolecolor_vars
[0], ew
),
4573 def
? ps
->VAR_NORM_BACK_COLOR
4574 : PVAL(&rolecolor_vars
[1], ew
),
4583 new_confline(&ctmp
);
4584 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4586 new_confline(&ctmp
);
4587 ctmp
->flags
|= CF_NOSELECT
;
4588 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(ostr
)) + 4){
4591 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
4592 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
4593 ostr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
4594 ctmp
->value
= cpystr(tmp_20k_buf
);
4597 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
4600 new_confline(&ctmp
);
4601 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4603 opt_var
.name
= cpystr(_("Features"));
4604 opt_var
.is_used
= 1;
4605 opt_var
.is_user
= 1;
4606 opt_var
.is_list
= 1;
4607 clrbitmap(feat_option_list
);
4608 if(def
&& def
->patgrp
&& def
->patgrp
->age_uses_sentdate
)
4609 setbitn(FEAT_SENTDATE
, feat_option_list
);
4612 if(def
&& def
->action
&& def
->action
->move_only_if_not_deleted
)
4613 setbitn(FEAT_IFNOTDEL
, feat_option_list
);
4614 if(def
&& def
->action
&& def
->action
->non_terminating
)
4615 setbitn(FEAT_NONTERM
, feat_option_list
);
4619 new_confline(&ctmp
);
4620 ctmp
->var
= &opt_var
;
4621 ctmp
->valoffset
= 23;
4622 ctmp
->keymenu
= &config_checkbox_keymenu
;
4623 ctmp
->help
= NO_HELP
;
4625 snprintf(tmp
, sizeof(tmp
), "%-20s =", opt_var
.name
);
4626 tmp
[sizeof(tmp
)-1] = '\0';
4627 ctmp
->varname
= cpystr(tmp
);
4628 ctmp
->varnamep
= ctmpb
= ctmp
;
4629 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4631 new_confline(&ctmp
);
4633 ctmp
->valoffset
= rindent
;
4634 ctmp
->keymenu
= &config_checkbox_keymenu
;
4635 ctmp
->help
= NO_HELP
;
4636 ctmp
->tool
= feat_checkbox_tool
;
4637 ctmp
->varnamep
= ctmpb
;
4638 ctmp
->flags
|= CF_NOSELECT
;
4639 ctmp
->value
= cpystr("Set Feature Name");
4641 new_confline(&ctmp
);
4643 ctmp
->valoffset
= rindent
;
4644 ctmp
->keymenu
= &config_checkbox_keymenu
;
4645 ctmp
->help
= NO_HELP
;
4646 ctmp
->tool
= feat_checkbox_tool
;
4647 ctmp
->varnamep
= ctmpb
;
4648 ctmp
->flags
|= CF_NOSELECT
;
4649 ctmp
->value
= cpystr(set_choose
); \
4651 /* find longest value's name */
4652 for(lv
= 0, i
= 0; (f
= feat_feature_list(i
)); i
++){
4653 if(!edit_filter
&& (i
== FEAT_IFNOTDEL
|| i
== FEAT_NONTERM
))
4656 if(lv
< (j
= utf8_width(f
->name
)))
4662 for(i
= 0; (f
= feat_feature_list(i
)); i
++){
4663 if(!edit_filter
&& (i
== FEAT_IFNOTDEL
|| i
== FEAT_NONTERM
))
4666 new_confline(&ctmp
);
4667 ctmp
->var
= &opt_var
;
4668 ctmp
->help_title
= _("HELP FOR FILTER FEATURES");
4669 ctmp
->varnamep
= ctmpb
;
4670 ctmp
->keymenu
= &config_checkbox_keymenu
;
4673 ctmp
->help
= h_config_filt_opts_sentdate
;
4676 ctmp
->help
= h_config_filt_opts_notdel
;
4679 ctmp
->help
= h_config_filt_opts_nonterm
;
4683 ctmp
->tool
= feat_checkbox_tool
;
4684 ctmp
->valoffset
= rindent
;
4686 utf8_snprintf(tmp
, sizeof(tmp
), "[%c] %-*.*w",
4687 bitnset(f
->value
, feat_option_list
) ? 'X' : ' ',
4689 tmp
[sizeof(tmp
)-1] = '\0';
4690 ctmp
->value
= cpystr(tmp
);
4698 new_confline(&ctmp
);
4699 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4701 new_confline(&ctmp
);
4702 ctmp
->flags
|= CF_NOSELECT
;
4703 if(ps
->ttyo
->screen_cols
>= (wid
=utf8_width(ustr
)) + 4){
4706 dashes
= (ps
->ttyo
->screen_cols
- wid
)/2;
4707 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s", repeat_char(dashes
, '='),
4708 ustr
, repeat_char(ps
->ttyo
->screen_cols
-wid
-dashes
, '='));
4709 ctmp
->value
= cpystr(tmp_20k_buf
);
4712 ctmp
->value
= cpystr(repeat_char(ps
->ttyo
->screen_cols
, '='));
4715 new_confline(&ctmp
);
4716 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4719 new_confline(&ctmp
);
4720 ctmp
->var
= &repl_type_var
;
4721 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4722 ctmp
->help
= NO_HELP
;
4724 snprintf(tmp
, sizeof(tmp
), "%s =", repl_type_var
.name
);
4725 tmp
[sizeof(tmp
)-1] = '\0';
4726 ctmp
->varname
= cpystr(tmp
);
4727 ctmp
->varnamep
= ctmpb
= ctmp
;
4728 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4730 new_confline(&ctmp
);
4732 ctmp
->valoffset
= rindent
;
4733 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4734 ctmp
->help
= NO_HELP
;
4736 ctmp
->varnamep
= ctmpb
;
4737 ctmp
->flags
|= CF_NOSELECT
;
4738 ctmp
->value
= cpystr("Set Choose One");
4740 new_confline(&ctmp
);
4742 ctmp
->valoffset
= rindent
;
4743 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4744 ctmp
->help
= NO_HELP
;
4745 ctmp
->tool
= radio_tool
;
4746 ctmp
->varnamep
= ctmpb
;
4747 ctmp
->flags
|= CF_NOSELECT
;
4748 ctmp
->value
= cpystr(set_choose
); \
4750 /* find longest value's name */
4751 for(lv
= 0, i
= 0; (f
= role_repl_types(i
)); i
++)
4752 if(lv
< (j
= utf8_width(f
->name
)))
4757 for(i
= 0; (f
= role_repl_types(i
)); i
++){
4758 new_confline(&ctmp
);
4759 ctmp
->help_title
= _("HELP FOR ROLE REPLY USE");
4760 ctmp
->var
= &repl_type_var
;
4761 ctmp
->valoffset
= rindent
;
4762 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4763 ctmp
->help
= h_config_role_replyuse
;
4765 ctmp
->tool
= radio_tool
;
4766 ctmp
->varnamep
= ctmpb
;
4767 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (((!(def
&& def
->action
) ||
4768 def
->action
->repl_type
== -1) &&
4769 f
->value
== ROLE_REPL_DEFL
) ||
4770 (def
&& def
->action
&&
4771 f
->value
== def
->action
->repl_type
))
4774 tmp
[sizeof(tmp
)-1] = '\0';
4775 ctmp
->value
= cpystr(tmp
);
4779 new_confline(&ctmp
);
4780 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4783 new_confline(&ctmp
);
4784 ctmp
->var
= &forw_type_var
;
4785 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4786 ctmp
->help
= NO_HELP
;
4788 snprintf(tmp
, sizeof(tmp
), "%s =", forw_type_var
.name
);
4789 tmp
[sizeof(tmp
)-1] = '\0';
4790 ctmp
->varname
= cpystr(tmp
);
4791 ctmp
->varnamep
= ctmpb
= ctmp
;
4792 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4794 new_confline(&ctmp
);
4796 ctmp
->valoffset
= rindent
;
4797 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4798 ctmp
->help
= NO_HELP
;
4800 ctmp
->varnamep
= ctmpb
;
4801 ctmp
->flags
|= CF_NOSELECT
;
4802 ctmp
->value
= cpystr("Set Choose One");
4804 new_confline(&ctmp
);
4806 ctmp
->valoffset
= rindent
;
4807 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4808 ctmp
->help
= NO_HELP
;
4809 ctmp
->tool
= radio_tool
;
4810 ctmp
->varnamep
= ctmpb
;
4811 ctmp
->flags
|= CF_NOSELECT
;
4812 ctmp
->value
= cpystr(set_choose
); \
4814 /* find longest value's name */
4815 for(lv
= 0, i
= 0; (f
= role_forw_types(i
)); i
++)
4816 if(lv
< (j
= utf8_width(f
->name
)))
4821 for(i
= 0; (f
= role_forw_types(i
)); i
++){
4822 new_confline(&ctmp
);
4823 ctmp
->help_title
= _("HELP FOR ROLE FORWARD USE");
4824 ctmp
->var
= &forw_type_var
;
4825 ctmp
->valoffset
= rindent
;
4826 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4827 ctmp
->help
= h_config_role_forwarduse
;
4829 ctmp
->tool
= radio_tool
;
4830 ctmp
->varnamep
= ctmpb
;
4831 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (((!(def
&& def
->action
) ||
4832 def
->action
->forw_type
== -1) &&
4833 f
->value
== ROLE_FORW_DEFL
) ||
4834 (def
&& def
->action
&&
4835 f
->value
== def
->action
->forw_type
))
4838 tmp
[sizeof(tmp
)-1] = '\0';
4839 ctmp
->value
= cpystr(tmp
);
4843 new_confline(&ctmp
);
4844 ctmp
->flags
|= CF_NOSELECT
| CF_B_LINE
;
4847 new_confline(&ctmp
);
4848 ctmp
->var
= &comp_type_var
;
4849 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4850 ctmp
->help
= NO_HELP
;
4852 snprintf(tmp
, sizeof(tmp
), "%s =", comp_type_var
.name
);
4853 tmp
[sizeof(tmp
)-1] = '\0';
4854 ctmp
->varname
= cpystr(tmp
);
4855 ctmp
->varnamep
= ctmpb
= ctmp
;
4856 ctmp
->flags
|= (CF_NOSELECT
| CF_STARTITEM
);
4858 new_confline(&ctmp
);
4860 ctmp
->valoffset
= rindent
;
4861 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4862 ctmp
->help
= NO_HELP
;
4864 ctmp
->varnamep
= ctmpb
;
4865 ctmp
->flags
|= CF_NOSELECT
;
4866 ctmp
->value
= cpystr("Set Choose One");
4868 new_confline(&ctmp
);
4870 ctmp
->valoffset
= rindent
;
4871 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4872 ctmp
->help
= NO_HELP
;
4873 ctmp
->tool
= radio_tool
;
4874 ctmp
->varnamep
= ctmpb
;
4875 ctmp
->flags
|= CF_NOSELECT
;
4876 ctmp
->value
= cpystr(set_choose
); \
4878 /* find longest value's name */
4879 for(lv
= 0, i
= 0; (f
= role_comp_types(i
)); i
++)
4880 if(lv
< (j
= utf8_width(f
->name
)))
4885 for(i
= 0; (f
= role_comp_types(i
)); i
++){
4886 new_confline(&ctmp
);
4887 ctmp
->help_title
= _("HELP FOR ROLE COMPOSE USE");
4888 ctmp
->var
= &comp_type_var
;
4889 ctmp
->valoffset
= rindent
;
4890 ctmp
->keymenu
= &config_radiobutton_keymenu
;
4891 ctmp
->help
= h_config_role_composeuse
;
4893 ctmp
->tool
= radio_tool
;
4894 ctmp
->varnamep
= ctmpb
;
4895 utf8_snprintf(tmp
, sizeof(tmp
), "(%c) %-*.*w", (((!(def
&& def
->action
) ||
4896 def
->action
->comp_type
== -1) &&
4897 f
->value
== ROLE_COMP_DEFL
) ||
4898 (def
&& def
->action
&&
4899 f
->value
== def
->action
->comp_type
))
4902 tmp
[sizeof(tmp
)-1] = '\0';
4903 ctmp
->value
= cpystr(tmp
);
4907 memset(&screen
, 0, sizeof(screen
));
4908 screen
.ro_warning
= saved_screen
? saved_screen
->deferred_ro_warning
: 0;
4909 /* TRANSLATORS: Print something1 using something2.
4910 "roles" is something1 */
4911 rv
= conf_scroll_screen(ps
, &screen
, first_line
, title
, _("roles"),
4912 (edit_incol
&& pico_usingcolor()) ? 1 : 0, NULL
);
4915 * Now look at the fake variables and extract the information we
4919 if(rv
== 1 && result
){
4921 * We know these variables exist, so we don't have to check that
4922 * apval is nonnull before evaluating *apval.
4924 apval
= APVAL(&nick_var
, ew
);
4927 removing_leading_and_trailing_white_space(nick
);
4929 apval
= APVAL(&comment_var
, ew
);
4932 removing_leading_and_trailing_white_space(comment
);
4934 alval
= ALVAL(&to_pat_var
, ew
);
4938 alval
= ALVAL(&from_pat_var
, ew
);
4942 alval
= ALVAL(&sender_pat_var
, ew
);
4943 sender_pat
= *alval
;
4946 alval
= ALVAL(&cc_pat_var
, ew
);
4950 alval
= ALVAL(&recip_pat_var
, ew
);
4954 alval
= ALVAL(&partic_pat_var
, ew
);
4955 partic_pat
= *alval
;
4958 alval
= ALVAL(&news_pat_var
, ew
);
4962 alval
= ALVAL(&subj_pat_var
, ew
);
4966 alval
= ALVAL(&alltext_pat_var
, ew
);
4967 alltext_pat
= *alval
;
4970 alval
= ALVAL(&bodytext_pat_var
, ew
);
4971 bodytext_pat
= *alval
;
4974 alval
= ALVAL(&keyword_pat_var
, ew
);
4975 keyword_pat
= *alval
;
4978 alval
= ALVAL(&charset_pat_var
, ew
);
4979 charset_pat
= *alval
;
4982 apval
= APVAL(&age_pat_var
, ew
);
4985 removing_leading_and_trailing_white_space(age_pat
);
4987 apval
= APVAL(&size_pat_var
, ew
);
4990 removing_leading_and_trailing_white_space(size_pat
);
4992 apval
= APVAL(&scorei_pat_var
, ew
);
4993 scorei_pat
= *apval
;
4995 removing_leading_and_trailing_white_space(scorei_pat
);
4997 apval
= APVAL(&stat_del_var
, ew
);
5000 removing_leading_and_trailing_white_space(stat_del
);
5002 apval
= APVAL(&stat_new_var
, ew
);
5005 removing_leading_and_trailing_white_space(stat_new
);
5007 apval
= APVAL(&stat_rec_var
, ew
);
5010 removing_leading_and_trailing_white_space(stat_rec
);
5012 apval
= APVAL(&stat_imp_var
, ew
);
5015 removing_leading_and_trailing_white_space(stat_imp
);
5017 apval
= APVAL(&stat_ans_var
, ew
);
5020 removing_leading_and_trailing_white_space(stat_ans
);
5022 apval
= APVAL(&stat_8bit_var
, ew
);
5025 removing_leading_and_trailing_white_space(stat_8bit
);
5027 apval
= APVAL(&stat_bom_var
, ew
);
5030 removing_leading_and_trailing_white_space(stat_bom
);
5032 apval
= APVAL(&stat_boy_var
, ew
);
5035 removing_leading_and_trailing_white_space(stat_boy
);
5037 apval
= APVAL(&fldr_type_var
, ew
);
5038 fldr_type_pat
= *apval
;
5040 removing_leading_and_trailing_white_space(fldr_type_pat
);
5042 alval
= ALVAL(&folder_pat_var
, ew
);
5043 folder_pat
= *alval
;
5046 apval
= APVAL(&abook_type_var
, ew
);
5047 abook_type_pat
= *apval
;
5049 removing_leading_and_trailing_white_space(abook_type_pat
);
5051 alval
= ALVAL(&abook_pat_var
, ew
);
5055 apval
= APVAL(&cati_var
, ew
);
5058 removing_leading_and_trailing_white_space(cati
);
5060 apval
= APVAL(&cat_lim_var
, ew
);
5063 removing_leading_and_trailing_white_space(cat_lim
);
5065 apval
= APVAL(&inick_var
, ew
);
5068 removing_leading_and_trailing_white_space(inick
);
5070 apval
= APVAL(&from_act_var
, ew
);
5073 removing_leading_and_trailing_white_space(from_act
);
5075 apval
= APVAL(&replyto_act_var
, ew
);
5076 replyto_act
= *apval
;
5078 removing_leading_and_trailing_white_space(replyto_act
);
5080 apval
= APVAL(&fcc_act_var
, ew
);
5083 removing_leading_and_trailing_white_space(fcc_act
);
5085 apval
= APVAL(&litsig_act_var
, ew
);
5086 litsig_act
= *apval
;
5088 removing_leading_and_trailing_white_space(litsig_act
);
5090 apval
= APVAL(&sort_act_var
, ew
);
5093 removing_leading_and_trailing_white_space(sort_act
);
5095 apval
= APVAL(&iform_act_var
, ew
);
5098 removing_leading_and_trailing_white_space(iform_act
);
5100 apval
= APVAL(&startup_var
, ew
);
5101 startup_act
= *apval
;
5103 removing_leading_and_trailing_white_space(startup_act
);
5105 apval
= APVAL(&sig_act_var
, ew
);
5108 removing_leading_and_trailing_white_space(sig_act
);
5110 apval
= APVAL(&templ_act_var
, ew
);
5113 removing_leading_and_trailing_white_space(templ_act
);
5115 apval
= APVAL(&score_act_var
, ew
);
5118 removing_leading_and_trailing_white_space(score_act
);
5120 apval
= APVAL(&hdrtok_act_var
, ew
);
5121 hdrtok_act
= *apval
;
5123 removing_leading_and_trailing_white_space(hdrtok_act
);
5125 apval
= APVAL(&repl_type_var
, ew
);
5128 removing_leading_and_trailing_white_space(repl_type
);
5130 apval
= APVAL(&forw_type_var
, ew
);
5133 removing_leading_and_trailing_white_space(forw_type
);
5135 apval
= APVAL(&comp_type_var
, ew
);
5138 removing_leading_and_trailing_white_space(comp_type
);
5140 apval
= APVAL(&rolecolor_vars
[0], ew
);
5143 removing_leading_and_trailing_white_space(rc_fg
);
5145 apval
= APVAL(&rolecolor_vars
[1], ew
);
5148 removing_leading_and_trailing_white_space(rc_bg
);
5150 apval
= APVAL(&filter_type_var
, ew
);
5151 filter_type
= *apval
;
5153 removing_leading_and_trailing_white_space(filter_type
);
5155 alval
= ALVAL(&folder_act_var
, ew
);
5156 folder_act
= *alval
;
5159 alval
= ALVAL(&keyword_set_var
, ew
);
5160 keyword_set
= *alval
;
5163 alval
= ALVAL(&keyword_clr_var
, ew
);
5164 keyword_clr
= *alval
;
5167 apval
= APVAL(&filt_imp_var
, ew
);
5170 removing_leading_and_trailing_white_space(filt_imp
);
5172 apval
= APVAL(&filt_del_var
, ew
);
5175 removing_leading_and_trailing_white_space(filt_del
);
5177 apval
= APVAL(&filt_new_var
, ew
);
5180 removing_leading_and_trailing_white_space(filt_new
);
5182 apval
= APVAL(&filt_ans_var
, ew
);
5185 removing_leading_and_trailing_white_space(filt_ans
);
5188 alval
= ALVAL(&cat_cmd_var
, ew
);
5192 alval
= ALVAL(&cstm_act_var
, ew
);
5196 alval
= ALVAL(&smtp_act_var
, ew
);
5200 alval
= ALVAL(&nntp_act_var
, ew
);
5204 if(ps
->VAR_OPER_DIR
&& sig_act
&&
5205 is_absolute_path(sig_act
) &&
5206 !in_dir(ps
->VAR_OPER_DIR
, sig_act
)){
5207 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5208 _("Warning: Sig file can't be outside of %s"),
5212 if(ps
->VAR_OPER_DIR
&& templ_act
&&
5213 is_absolute_path(templ_act
) &&
5214 !in_dir(ps
->VAR_OPER_DIR
, templ_act
)){
5215 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5216 _("Warning: Template file can't be outside of %s"),
5220 if(ps
->VAR_OPER_DIR
&& folder_act
)
5221 for(i
= 0; folder_act
[i
]; i
++){
5222 if(folder_act
[i
][0] && is_absolute_path(folder_act
[i
]) &&
5223 !in_dir(ps
->VAR_OPER_DIR
, folder_act
[i
])){
5224 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5225 _("Warning: Folder can't be outside of %s"),
5230 *result
= (PAT_S
*)fs_get(sizeof(**result
));
5231 memset((void *)(*result
), 0, sizeof(**result
));
5233 (*result
)->patgrp
= (PATGRP_S
*)fs_get(sizeof(*(*result
)->patgrp
));
5234 memset((void *)(*result
)->patgrp
, 0, sizeof(*(*result
)->patgrp
));
5236 (*result
)->action
= (ACTION_S
*)fs_get(sizeof(*(*result
)->action
));
5237 memset((void *)(*result
)->action
, 0, sizeof(*(*result
)->action
));
5239 (*result
)->patline
= def
? def
->patline
: NULL
;
5242 (*result
)->patgrp
->nick
= nick
;
5246 (*result
)->patgrp
->nick
= cpystr(nick_var
.global_val
.p
);
5248 if(comment
&& *comment
){
5249 (*result
)->patgrp
->comment
= comment
;
5253 (*result
)->action
->nick
= cpystr((*result
)->patgrp
->nick
);
5255 (*result
)->action
->is_a_role
= edit_role
? 1 : 0;
5256 (*result
)->action
->is_a_incol
= edit_incol
? 1 : 0;
5257 (*result
)->action
->is_a_score
= edit_score
? 1 : 0;
5258 (*result
)->action
->is_a_filter
= edit_filter
? 1 : 0;
5259 (*result
)->action
->is_a_other
= edit_other
? 1 : 0;
5260 (*result
)->action
->is_a_srch
= edit_srch
? 1 : 0;
5262 (*result
)->patgrp
->to
= editlist_to_pattern(to_pat
);
5263 if((*result
)->patgrp
->to
&& !strncmp(to_pat_var
.name
, NOT
, NOTLEN
))
5264 (*result
)->patgrp
->to
->not = 1;
5266 (*result
)->patgrp
->from
= editlist_to_pattern(from_pat
);
5267 if((*result
)->patgrp
->from
&& !strncmp(from_pat_var
.name
, NOT
, NOTLEN
))
5268 (*result
)->patgrp
->from
->not = 1;
5270 (*result
)->patgrp
->sender
= editlist_to_pattern(sender_pat
);
5271 if((*result
)->patgrp
->sender
&&
5272 !strncmp(sender_pat_var
.name
, NOT
, NOTLEN
))
5273 (*result
)->patgrp
->sender
->not = 1;
5275 (*result
)->patgrp
->cc
= editlist_to_pattern(cc_pat
);
5276 if((*result
)->patgrp
->cc
&& !strncmp(cc_pat_var
.name
, NOT
, NOTLEN
))
5277 (*result
)->patgrp
->cc
->not = 1;
5279 (*result
)->patgrp
->recip
= editlist_to_pattern(recip_pat
);
5280 if((*result
)->patgrp
->recip
&&
5281 !strncmp(recip_pat_var
.name
, NOT
, NOTLEN
))
5282 (*result
)->patgrp
->recip
->not = 1;
5284 (*result
)->patgrp
->partic
= editlist_to_pattern(partic_pat
);
5285 if((*result
)->patgrp
->partic
&&
5286 !strncmp(partic_pat_var
.name
, NOT
, NOTLEN
))
5287 (*result
)->patgrp
->partic
->not = 1;
5289 (*result
)->patgrp
->news
= editlist_to_pattern(news_pat
);
5290 if((*result
)->patgrp
->news
&& !strncmp(news_pat_var
.name
, NOT
, NOTLEN
))
5291 (*result
)->patgrp
->news
->not = 1;
5293 (*result
)->patgrp
->subj
= editlist_to_pattern(subj_pat
);
5294 if((*result
)->patgrp
->subj
&& !strncmp(subj_pat_var
.name
, NOT
, NOTLEN
))
5295 (*result
)->patgrp
->subj
->not = 1;
5297 (*result
)->patgrp
->alltext
= editlist_to_pattern(alltext_pat
);
5298 if((*result
)->patgrp
->alltext
&&
5299 !strncmp(alltext_pat_var
.name
, NOT
, NOTLEN
))
5300 (*result
)->patgrp
->alltext
->not = 1;
5302 (*result
)->patgrp
->bodytext
= editlist_to_pattern(bodytext_pat
);
5303 if((*result
)->patgrp
->bodytext
&&
5304 !strncmp(bodytext_pat_var
.name
, NOT
, NOTLEN
))
5305 (*result
)->patgrp
->bodytext
->not = 1;
5307 (*result
)->patgrp
->keyword
= editlist_to_pattern(keyword_pat
);
5308 if((*result
)->patgrp
->keyword
&&
5309 !strncmp(keyword_pat_var
.name
, NOT
, NOTLEN
))
5310 (*result
)->patgrp
->keyword
->not = 1;
5312 (*result
)->patgrp
->charsets
= editlist_to_pattern(charset_pat
);
5313 if((*result
)->patgrp
->charsets
&&
5314 !strncmp(charset_pat_var
.name
, NOT
, NOTLEN
))
5315 (*result
)->patgrp
->charsets
->not = 1;
5317 (*result
)->patgrp
->age_uses_sentdate
=
5318 bitnset(FEAT_SENTDATE
, feat_option_list
) ? 1 : 0;
5321 if(((*result
)->patgrp
->age
= parse_intvl(age_pat
)) != NULL
)
5322 (*result
)->patgrp
->do_age
= 1;
5326 if(((*result
)->patgrp
->size
= parse_intvl(size_pat
)) != NULL
)
5327 (*result
)->patgrp
->do_size
= 1;
5331 if(((*result
)->patgrp
->score
= parse_intvl(scorei_pat
)) != NULL
)
5332 (*result
)->patgrp
->do_score
= 1;
5335 (*result
)->patgrp
->cat_lim
= -1L; /* default */
5338 fs_give((void **) &cat_cmd
);
5340 /* quick check for absolute paths */
5342 for(j
= 0; cat_cmd
[j
]; j
++)
5343 if(!is_absolute_path(cat_cmd
[j
]))
5344 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
5345 _("Warning: command must be absolute path: \"%s\""),
5348 (*result
)->patgrp
->category_cmd
= cat_cmd
;
5352 if(((*result
)->patgrp
->cat
= parse_intvl(cati
)) != NULL
)
5353 (*result
)->patgrp
->do_cat
= 1;
5355 if(cat_lim
&& *cat_lim
)
5356 (*result
)->patgrp
->cat_lim
= atol(cat_lim
);
5359 if(stat_del
&& *stat_del
){
5360 for(j
= 0; (f
= role_status_types(j
)); j
++)
5361 if(!strucmp(stat_del
, f
->name
)){
5362 (*result
)->patgrp
->stat_del
= f
->value
;
5367 (*result
)->patgrp
->stat_del
= PAT_STAT_EITHER
;
5369 if(stat_new
&& *stat_new
){
5370 for(j
= 0; (f
= role_status_types(j
)); j
++)
5371 if(!strucmp(stat_new
, f
->name
)){
5372 (*result
)->patgrp
->stat_new
= f
->value
;
5377 (*result
)->patgrp
->stat_new
= PAT_STAT_EITHER
;
5379 if(stat_rec
&& *stat_rec
){
5380 for(j
= 0; (f
= role_status_types(j
)); j
++)
5381 if(!strucmp(stat_rec
, f
->name
)){
5382 (*result
)->patgrp
->stat_rec
= f
->value
;
5387 (*result
)->patgrp
->stat_rec
= PAT_STAT_EITHER
;
5389 if(stat_imp
&& *stat_imp
){
5390 for(j
= 0; (f
= role_status_types(j
)); j
++)
5391 if(!strucmp(stat_imp
, f
->name
)){
5392 (*result
)->patgrp
->stat_imp
= f
->value
;
5397 (*result
)->patgrp
->stat_imp
= PAT_STAT_EITHER
;
5399 if(stat_ans
&& *stat_ans
){
5400 for(j
= 0; (f
= role_status_types(j
)); j
++)
5401 if(!strucmp(stat_ans
, f
->name
)){
5402 (*result
)->patgrp
->stat_ans
= f
->value
;
5407 (*result
)->patgrp
->stat_ans
= PAT_STAT_EITHER
;
5409 if(stat_8bit
&& *stat_8bit
){
5410 for(j
= 0; (f
= role_status_types(j
)); j
++)
5411 if(!strucmp(stat_8bit
, f
->name
)){
5412 (*result
)->patgrp
->stat_8bitsubj
= f
->value
;
5417 (*result
)->patgrp
->stat_8bitsubj
= PAT_STAT_EITHER
;
5419 if(stat_bom
&& *stat_bom
){
5420 for(j
= 0; (f
= role_status_types(j
)); j
++)
5421 if(!strucmp(stat_bom
, f
->name
)){
5422 (*result
)->patgrp
->stat_bom
= f
->value
;
5427 (*result
)->patgrp
->stat_bom
= PAT_STAT_EITHER
;
5429 if(stat_boy
&& *stat_boy
){
5430 for(j
= 0; (f
= role_status_types(j
)); j
++)
5431 if(!strucmp(stat_boy
, f
->name
)){
5432 (*result
)->patgrp
->stat_boy
= f
->value
;
5437 (*result
)->patgrp
->stat_boy
= PAT_STAT_EITHER
;
5440 decode_sort(sort_act
, &def_sort
, &def_sort_rev
);
5441 (*result
)->action
->sort_is_set
= 1;
5442 (*result
)->action
->sortorder
= def_sort
;
5443 (*result
)->action
->revsort
= (def_sort_rev
? 1 : 0);
5445 * Don't try to re-sort until next open of folder. If user
5446 * $-sorted then it probably shouldn't change anyway. Why
5447 * bother keeping track of that?
5451 (*result
)->action
->index_format
= iform_act
;
5454 if(startup_act
&& *startup_act
){
5455 for(j
= 0; (f
= startup_rules(j
)); j
++)
5456 if(!strucmp(startup_act
, f
->name
)){
5457 (*result
)->action
->startup_rule
= f
->value
;
5462 (*result
)->action
->startup_rule
= IS_NOTSET
;
5465 for(ea
= earb
; ea
; ea
= ea
->next
){
5469 aa
->next
= (ARBHDR_S
*)fs_get(sizeof(*aa
));
5473 (*result
)->patgrp
->arbhdr
=
5474 (ARBHDR_S
*)fs_get(sizeof(ARBHDR_S
));
5475 aa
= (*result
)->patgrp
->arbhdr
;
5478 memset(aa
, 0, sizeof(*aa
));
5480 aa
->field
= cpystr((ea
->a
&& ea
->a
->field
) ? ea
->a
->field
: "");
5482 alval
= ALVAL(ea
->v
, ew
);
5485 aa
->p
= editlist_to_pattern(spat
);
5486 if(aa
->p
&& ea
->v
&& ea
->v
->name
&&
5487 !strncmp(ea
->v
->name
, NOT
, NOTLEN
))
5490 if((xyz
= pattern_to_string(aa
->p
)) != NULL
){
5494 fs_give((void **)&xyz
);
5498 if(fldr_type_pat
&& *fldr_type_pat
){
5499 for(j
= 0; (f
= pat_fldr_types(j
)); j
++)
5500 if(!strucmp(fldr_type_pat
, f
->name
)){
5501 (*result
)->patgrp
->fldr_type
= f
->value
;
5506 f
= pat_fldr_types(FLDR_DEFL
);
5508 (*result
)->patgrp
->fldr_type
= f
->value
;
5511 (*result
)->patgrp
->folder
= editlist_to_pattern(folder_pat
);
5513 if(abook_type_pat
&& *abook_type_pat
){
5514 for(j
= 0; (f
= inabook_fldr_types(j
)); j
++)
5515 if(!strucmp(abook_type_pat
, f
->name
)){
5516 (*result
)->patgrp
->inabook
= f
->value
;
5520 if(bitnset(INABOOK_FROM
, inabook_type_list
))
5521 (*result
)->patgrp
->inabook
|= IAB_FROM
;
5522 if(bitnset(INABOOK_REPLYTO
, inabook_type_list
))
5523 (*result
)->patgrp
->inabook
|= IAB_REPLYTO
;
5524 if(bitnset(INABOOK_SENDER
, inabook_type_list
))
5525 (*result
)->patgrp
->inabook
|= IAB_SENDER
;
5526 if(bitnset(INABOOK_TO
, inabook_type_list
))
5527 (*result
)->patgrp
->inabook
|= IAB_TO
;
5528 if(bitnset(INABOOK_CC
, inabook_type_list
))
5529 (*result
)->patgrp
->inabook
|= IAB_CC
;
5531 if(!((*result
)->patgrp
->inabook
& IAB_TYPE_MASK
))
5532 (*result
)->patgrp
->inabook
|= (IAB_FROM
| IAB_REPLYTO
);
5535 f
= inabook_fldr_types(IAB_DEFL
);
5537 (*result
)->patgrp
->inabook
= f
->value
;
5540 (*result
)->patgrp
->abooks
= editlist_to_pattern(abook_pat
);
5543 (*result
)->action
->inherit_nick
= inick
;
5545 (*result
)->action
->fcc
= fcc_act
;
5547 (*result
)->action
->litsig
= litsig_act
;
5549 (*result
)->action
->sig
= sig_act
;
5551 (*result
)->action
->template = templ_act
;
5556 * Check for From or Reply-To and eliminate them.
5558 for(i
= 0; cstm_act
[i
]; i
++){
5561 if((!struncmp(cstm_act
[i
],"from",4) &&
5562 (cstm_act
[i
][4] == ':' ||
5563 cstm_act
[i
][4] == '\0')) ||
5564 (!struncmp(cstm_act
[i
],"reply-to",8) &&
5565 (cstm_act
[i
][8] == ':' ||
5566 cstm_act
[i
][8] == '\0'))){
5567 free_this
= cstm_act
[i
];
5568 /* slide the rest up */
5569 for(j
= i
; cstm_act
[j
]; j
++)
5570 cstm_act
[j
] = cstm_act
[j
+1];
5572 fs_give((void **)&free_this
);
5573 i
--; /* recheck now that we've slid them up */
5579 fs_give((void **)&cstm_act
);
5581 (*result
)->action
->cstm
= cstm_act
;
5587 fs_give((void **)&smtp_act
);
5589 (*result
)->action
->smtp
= smtp_act
;
5595 fs_give((void **)&nntp_act
);
5597 (*result
)->action
->nntp
= nntp_act
;
5601 if(filter_type
&& *filter_type
){
5602 (*result
)->action
->non_terminating
=
5603 bitnset(FEAT_NONTERM
, feat_option_list
) ? 1 : 0;
5604 for(i
= 0; (f
= filter_types(i
)); i
++){
5605 if(!strucmp(filter_type
, f
->name
)){
5606 if(f
->value
== FILTER_FOLDER
){
5607 (*result
)->action
->folder
= editlist_to_pattern(folder_act
);
5608 (*result
)->action
->move_only_if_not_deleted
=
5609 bitnset(FEAT_IFNOTDEL
, feat_option_list
) ? 1 : 0;
5611 else if(f
->value
== FILTER_STATE
){
5612 (*result
)->action
->kill
= 0;
5614 else if(f
->value
== FILTER_KILL
){
5615 (*result
)->action
->kill
= 1;
5619 * This is indented an extra indent because we used to condition
5620 * this on !kill. We changed it so that you can set state bits
5621 * even if you're killing. This is marginally helpful if you
5622 * have another client running that doesn't know about this
5623 * filter, but you want to, for example, have the messages show
5624 * up now as deleted instead of having that deferred until we
5625 * exit. It is controlled by the user by setting the status
5626 * action bits along with the Delete.
5628 if(filt_imp
&& *filt_imp
){
5629 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5630 if(!strucmp(filt_imp
, f
->name
)){
5632 case ACT_STAT_LEAVE
:
5635 (*result
)->action
->state_setting_bits
|= F_FLAG
;
5637 case ACT_STAT_CLEAR
:
5638 (*result
)->action
->state_setting_bits
|= F_UNFLAG
;
5646 if(filt_del
&& *filt_del
){
5647 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5648 if(!strucmp(filt_del
, f
->name
)){
5650 case ACT_STAT_LEAVE
:
5653 (*result
)->action
->state_setting_bits
|= F_DEL
;
5655 case ACT_STAT_CLEAR
:
5656 (*result
)->action
->state_setting_bits
|= F_UNDEL
;
5664 if(filt_ans
&& *filt_ans
){
5665 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5666 if(!strucmp(filt_ans
, f
->name
)){
5668 case ACT_STAT_LEAVE
:
5671 (*result
)->action
->state_setting_bits
|= F_ANS
;
5673 case ACT_STAT_CLEAR
:
5674 (*result
)->action
->state_setting_bits
|= F_UNANS
;
5682 if(filt_new
&& *filt_new
){
5683 for(j
= 0; (f
= msg_state_types(j
)); j
++){
5684 if(!strucmp(filt_new
, f
->name
)){
5686 case ACT_STAT_LEAVE
:
5689 (*result
)->action
->state_setting_bits
|= F_UNSEEN
;
5691 case ACT_STAT_CLEAR
:
5692 (*result
)->action
->state_setting_bits
|= F_SEEN
;
5700 (*result
)->action
->keyword_set
=
5701 editlist_to_pattern(keyword_set
);
5702 (*result
)->action
->keyword_clr
=
5703 editlist_to_pattern(keyword_clr
);
5710 if(from_act
&& *from_act
)
5711 rfc822_parse_adrlist(&(*result
)->action
->from
, from_act
,
5714 if(replyto_act
&& *replyto_act
)
5715 rfc822_parse_adrlist(&(*result
)->action
->replyto
, replyto_act
,
5718 if(score_act
&& (j
= atoi(score_act
)) >= SCORE_MIN
&& j
<= SCORE_MAX
)
5719 (*result
)->action
->scoreval
= (long) j
;
5722 (*result
)->action
->scorevalhdrtok
= stringform_to_hdrtok(hdrtok_act
);
5724 if(repl_type
&& *repl_type
){
5725 for(j
= 0; (f
= role_repl_types(j
)); j
++)
5726 if(!strucmp(repl_type
, f
->name
)){
5727 (*result
)->action
->repl_type
= f
->value
;
5732 f
= role_repl_types(ROLE_REPL_DEFL
);
5734 (*result
)->action
->repl_type
= f
->value
;
5737 if(forw_type
&& *forw_type
){
5738 for(j
= 0; (f
= role_forw_types(j
)); j
++)
5739 if(!strucmp(forw_type
, f
->name
)){
5740 (*result
)->action
->forw_type
= f
->value
;
5745 f
= role_forw_types(ROLE_FORW_DEFL
);
5747 (*result
)->action
->forw_type
= f
->value
;
5750 if(comp_type
&& *comp_type
){
5751 for(j
= 0; (f
= role_comp_types(j
)); j
++)
5752 if(!strucmp(comp_type
, f
->name
)){
5753 (*result
)->action
->comp_type
= f
->value
;
5758 f
= role_comp_types(ROLE_COMP_DEFL
);
5760 (*result
)->action
->comp_type
= f
->value
;
5763 if(rc_fg
&& *rc_fg
&& rc_bg
&& *rc_bg
){
5764 if(!old_fg
|| !old_bg
|| strucmp(old_fg
, rc_fg
) ||
5765 strucmp(old_bg
, rc_bg
))
5766 clear_index_cache(ps_global
->mail_stream
, 0);
5769 * If same as normal color, don't set it. This may or may
5770 * not surprise the user when they change the normal color.
5771 * This color will track the normal color instead of staying
5772 * the same as the old normal color, which is probably
5775 if(!ps_global
->VAR_NORM_FORE_COLOR
||
5776 !ps_global
->VAR_NORM_BACK_COLOR
||
5777 strucmp(ps_global
->VAR_NORM_FORE_COLOR
, rc_fg
) ||
5778 strucmp(ps_global
->VAR_NORM_BACK_COLOR
, rc_bg
))
5779 (*result
)->action
->incol
= new_color_pair(rc_fg
, rc_bg
);
5783 for(j
= 0; varlist
[j
]; j
++){
5785 free_variable_values(v
);
5787 fs_give((void **)&v
->name
);
5793 fs_give((void **)&nick
);
5795 fs_give((void **)&comment
);
5797 free_list_array(&to_pat
);
5799 free_list_array(&from_pat
);
5801 free_list_array(&sender_pat
);
5803 free_list_array(&cc_pat
);
5805 free_list_array(&recip_pat
);
5807 free_list_array(&partic_pat
);
5809 free_list_array(&news_pat
);
5811 free_list_array(&subj_pat
);
5813 free_list_array(&alltext_pat
);
5815 free_list_array(&bodytext_pat
);
5817 free_list_array(&keyword_pat
);
5819 free_list_array(&charset_pat
);
5821 fs_give((void **)&age_pat
);
5823 fs_give((void **)&size_pat
);
5825 fs_give((void **)&scorei_pat
);
5827 fs_give((void **)&cati
);
5829 fs_give((void **)&cat_lim
);
5831 fs_give((void **)&stat_del
);
5833 fs_give((void **)&stat_new
);
5835 fs_give((void **)&stat_rec
);
5837 fs_give((void **)&stat_imp
);
5839 fs_give((void **)&stat_ans
);
5841 fs_give((void **)&stat_8bit
);
5843 fs_give((void **)&stat_bom
);
5845 fs_give((void **)&stat_boy
);
5847 fs_give((void **)&fldr_type_pat
);
5849 free_list_array(&folder_pat
);
5851 fs_give((void **)&abook_type_pat
);
5853 free_list_array(&abook_pat
);
5855 fs_give((void **)&inick
);
5857 fs_give((void **)&from_act
);
5859 fs_give((void **)&replyto_act
);
5861 fs_give((void **)&fcc_act
);
5863 fs_give((void **)&litsig_act
);
5865 fs_give((void **)&sort_act
);
5867 fs_give((void **)&iform_act
);
5869 free_list_array(&keyword_set
);
5871 free_list_array(&keyword_clr
);
5873 fs_give((void **)&startup_act
);
5875 fs_give((void **)&sig_act
);
5877 fs_give((void **)&templ_act
);
5879 fs_give((void **)&score_act
);
5881 fs_give((void **)&hdrtok_act
);
5883 fs_give((void **)&repl_type
);
5885 fs_give((void **)&forw_type
);
5887 fs_give((void **)&comp_type
);
5889 fs_give((void **)&rc_fg
);
5891 fs_give((void **)&rc_bg
);
5893 fs_give((void **)&old_fg
);
5895 fs_give((void **)&old_bg
);
5897 fs_give((void **)&filt_del
);
5899 fs_give((void **)&filt_new
);
5901 fs_give((void **)&filt_ans
);
5903 fs_give((void **)&filt_imp
);
5905 free_list_array(&folder_act
);
5907 fs_give((void **)&filter_type
);
5910 free_list_array(&cat_cmd
);
5913 free_list_array(&cstm_act
);
5916 free_list_array(&smtp_act
);
5919 free_list_array(&nntp_act
);
5921 opt_screen
= saved_screen
;
5922 ps
->mangled_screen
= 1;
5928 setup_dummy_pattern_var(struct variable
*v
, char *name
, PATTERN_S
*defpat
)
5933 alpine_panic("setup_dummy_pattern_var");
5935 v
->name
= (char *) fs_get(strlen(name
)+NOTLEN
+1);
5936 snprintf(v
->name
, strlen(name
)+NOTLEN
+1, "%s%s", (defpat
&& defpat
->not) ? NOT
: "", name
);
5937 v
->name
[ strlen(name
)+NOTLEN
+1-1] = '\0';
5941 alval
= ALVAL(v
, ew
);
5942 *alval
= pattern_to_editlist(defpat
);
5943 set_current_val(v
, FALSE
, FALSE
);
5948 setup_role_pat(struct pine
*ps
, CONF_S
**ctmp
, struct variable
*v
, HelpType help
,
5949 char *help_title
, struct key_menu
*keymenu
,
5950 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
5951 EARB_S
**earb
, int indent
)
5953 char tmp
[MAXPATH
+1];
5959 (*ctmp
)->help_title
= help_title
;
5961 (*ctmp
)->valoffset
= indent
;
5962 (*ctmp
)->keymenu
= keymenu
;
5963 (*ctmp
)->help
= help
;
5964 (*ctmp
)->tool
= tool
;
5965 utf8_snprintf(tmp
, sizeof(tmp
), "%-*.*w =", indent
-3, indent
-3, (v
&& v
->name
) ? v
->name
: "");
5966 tmp
[sizeof(tmp
)-1] = '\0';
5967 (*ctmp
)->varname
= cpystr(tmp
);
5968 (*ctmp
)->varnamep
= *ctmp
;
5969 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
5970 (*ctmp
)->d
.earb
= earb
;
5971 (*ctmp
)->varmem
= 0;
5972 (*ctmp
)->flags
= CF_STARTITEM
;
5978 for(i
= 0; lval
[i
]; i
++){
5983 (*ctmp
)->varmem
= i
;
5984 (*ctmp
)->valoffset
= indent
;
5985 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
5986 (*ctmp
)->d
.earb
= earb
;
5987 (*ctmp
)->keymenu
= keymenu
;
5988 (*ctmp
)->help
= help
;
5989 (*ctmp
)->tool
= tool
;
5990 (*ctmp
)->varnamep
= ctmpb
;
5997 * Watch out for polarity of nosel flag. Setting it means to turn on
5998 * the NOSELECT flag, which means to make that line unselectable.
6001 setup_role_pat_alt(struct pine
*ps
, CONF_S
**ctmp
, struct variable
*v
, HelpType help
,
6002 char *help_title
, struct key_menu
*keymenu
,
6003 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned),
6004 int voff
, int nosel
)
6006 char tmp
[MAXPATH
+1];
6012 (*ctmp
)->help_title
= help_title
;
6015 (*ctmp
)->varoffset
= voff
;
6016 k
= utf8_width(v
->name
);
6018 (*ctmp
)->valoffset
= j
;
6020 (*ctmp
)->keymenu
= keymenu
;
6021 (*ctmp
)->help
= help
;
6022 (*ctmp
)->tool
= tool
;
6024 utf8_snprintf(tmp
, sizeof(tmp
), "%*.*w =", k
, k
, v
->name
);
6025 tmp
[sizeof(tmp
)-1] = '\0';
6026 (*ctmp
)->varname
= cpystr(tmp
);
6028 (*ctmp
)->varnamep
= *ctmp
;
6029 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
6030 (*ctmp
)->varmem
= 0;
6032 (*ctmp
)->flags
= (nosel
? CF_NOSELECT
: 0);
6038 for(i
= 0; lval
[i
]; i
++){
6043 (*ctmp
)->varmem
= i
;
6044 (*ctmp
)->varoffset
= voff
;
6045 (*ctmp
)->valoffset
= j
;
6046 (*ctmp
)->value
= pretty_value(ps
, *ctmp
);
6047 (*ctmp
)->keymenu
= keymenu
;
6048 (*ctmp
)->help
= help
;
6049 (*ctmp
)->tool
= tool
;
6050 (*ctmp
)->varnamep
= ctmpb
;
6051 (*ctmp
)->flags
= (nosel
? CF_NOSELECT
: 0);
6058 free_earb(EARB_S
**ea
)
6061 free_earb(&(*ea
)->next
);
6063 free_variable_values((*ea
)->v
);
6065 fs_give((void **) &(*ea
)->v
->name
);
6067 fs_give((void **) &(*ea
)->v
);;
6070 free_arbhdr(&(*ea
)->a
);
6071 fs_give((void **) ea
);
6077 calculate_inick_stuff(struct pine
*ps
)
6079 ACTION_S
*role
, *irole
;
6080 CONF_S
*ctmp
, *ctmpa
;
6085 if(inick_confs
[INICK_INICK_CONF
] == NULL
)
6088 for(i
= INICK_FROM_CONF
; i
<= INICK_NNTP_CONF
; i
++){
6089 v
= inick_confs
[i
] ? inick_confs
[i
]->var
: NULL
;
6093 free_list_array(&v
->global_val
.l
);
6097 fs_give((void **)&v
->global_val
.p
);
6102 nick
= PVAL(inick_confs
[INICK_INICK_CONF
]->var
, ew
);
6106 * Use an empty role with inherit_nick set to nick and then use the
6107 * combine function to find the action values.
6109 role
= (ACTION_S
*)fs_get(sizeof(*role
));
6110 memset((void *)role
, 0, sizeof(*role
));
6111 role
->is_a_role
= 1;
6112 role
->inherit_nick
= cpystr(nick
);
6113 irole
= combine_inherited_role(role
);
6115 ctmp
= inick_confs
[INICK_FROM_CONF
];
6116 v
= ctmp
? ctmp
->var
: NULL
;
6118 if(irole
&& irole
->from
){
6122 len
= est_size(irole
->from
);
6123 bufp
= (char *) fs_get(len
* sizeof(char));
6124 v
->global_val
.p
= addr_string_mult(irole
->from
, bufp
, len
);
6127 ctmp
= inick_confs
[INICK_REPLYTO_CONF
];
6128 v
= ctmp
? ctmp
->var
: NULL
;
6130 if(irole
&& irole
->replyto
){
6134 len
= est_size(irole
->replyto
);
6135 bufp
= (char *) fs_get(len
* sizeof(char));
6136 v
->global_val
.p
= addr_string_mult(irole
->replyto
, bufp
, len
);
6139 ctmp
= inick_confs
[INICK_FCC_CONF
];
6140 v
= ctmp
? ctmp
->var
: NULL
;
6141 v
->global_val
.p
= (irole
&& irole
->fcc
) ? cpystr(irole
->fcc
) : NULL
;
6143 ctmp
= inick_confs
[INICK_LITSIG_CONF
];
6144 v
= ctmp
? ctmp
->var
: NULL
;
6145 v
->global_val
.p
= (irole
&& irole
->litsig
) ? cpystr(irole
->litsig
)
6148 ctmp
= inick_confs
[INICK_SIG_CONF
];
6149 v
= ctmp
? ctmp
->var
: NULL
;
6150 v
->global_val
.p
= (irole
&& irole
->sig
) ? cpystr(irole
->sig
) : NULL
;
6152 ctmp
= inick_confs
[INICK_TEMPL_CONF
];
6153 v
= ctmp
? ctmp
->var
: NULL
;
6154 v
->global_val
.p
= (irole
&& irole
->template)
6155 ? cpystr(irole
->template) : NULL
;
6157 ctmp
= inick_confs
[INICK_CSTM_CONF
];
6158 v
= ctmp
? ctmp
->var
: NULL
;
6159 v
->global_val
.l
= (irole
&& irole
->cstm
) ? copy_list_array(irole
->cstm
)
6162 ctmp
= inick_confs
[INICK_SMTP_CONF
];
6163 v
= ctmp
? ctmp
->var
: NULL
;
6164 v
->global_val
.l
= (irole
&& irole
->smtp
) ? copy_list_array(irole
->smtp
)
6167 ctmp
= inick_confs
[INICK_NNTP_CONF
];
6168 v
= ctmp
? ctmp
->var
: NULL
;
6169 v
->global_val
.l
= (irole
&& irole
->nntp
) ? copy_list_array(irole
->nntp
)
6173 free_action(&irole
);
6176 for(i
= INICK_INICK_CONF
; i
<= INICK_NNTP_CONF
; i
++){
6177 ctmp
= inick_confs
[i
];
6178 v
= ctmp
? ctmp
->var
: NULL
;
6180 * If we didn't set a global_val using the nick above, then
6181 * set one here for each variable that uses one.
6183 if(v
&& !v
->global_val
.p
){
6184 char *str
, *astr
, *lc
, pdir
[MAXPATH
+1];
6189 case INICK_FROM_CONF
:
6190 addr
= generate_from();
6191 astr
= addr_list_string(addr
, NULL
, 1);
6192 str
= (astr
&& astr
[0]) ? astr
: "?";
6193 v
->global_val
.p
= (char *)fs_get((strlen(str
) + 20) *
6195 snprintf(v
->global_val
.p
, strlen(str
) + 20, "%s%s)", DSTRING
, str
);
6196 v
->global_val
.p
[strlen(str
) + 20 - 1] = '\0';
6198 fs_give((void **)&astr
);
6201 mail_free_address(&addr
);
6205 case INICK_FCC_CONF
:
6206 v
->global_val
.p
= cpystr(VSTRING
);
6209 case INICK_LITSIG_CONF
:
6211 * This default works this way because of the ordering
6212 * of the choices in the detoken routine.
6214 if(ps
->VAR_LITERAL_SIG
){
6215 str
= ps
->VAR_LITERAL_SIG
;
6216 v
->global_val
.p
= (char *)fs_get((strlen(str
) + 20) *
6218 snprintf(v
->global_val
.p
, strlen(str
) + 20,
6219 "%s%s)", DSTRING
, str
);
6220 v
->global_val
.p
[strlen(str
) + 20 - 1] = '\0';
6225 case INICK_SIG_CONF
:
6227 if(ps_global
->VAR_OPER_DIR
){
6228 strncpy(pdir
, ps_global
->VAR_OPER_DIR
, MAXPATH
);
6229 pdir
[MAXPATH
] = '\0';
6230 len
= strlen(pdir
) + 1;
6232 else if((lc
= last_cmpnt(ps_global
->pinerc
)) != NULL
){
6233 strncpy(pdir
, ps_global
->pinerc
,
6234 MIN(MAXPATH
,lc
-ps_global
->pinerc
));
6235 pdir
[MIN(MAXPATH
, lc
-ps_global
->pinerc
)] = '\0';
6239 if(pdir
[0] && ps
->VAR_SIGNATURE_FILE
&&
6240 ps
->VAR_SIGNATURE_FILE
[0] &&
6241 is_absolute_path(ps
->VAR_SIGNATURE_FILE
) &&
6242 !strncmp(ps
->VAR_SIGNATURE_FILE
, pdir
, len
)){
6243 str
= ps
->VAR_SIGNATURE_FILE
+ len
;
6246 str
= (ps
->VAR_SIGNATURE_FILE
&& ps
->VAR_SIGNATURE_FILE
[0])
6247 ? ps
->VAR_SIGNATURE_FILE
: NULL
;
6249 v
->global_val
.p
= (char *)fs_get((strlen(str
) + 20) *
6251 snprintf(v
->global_val
.p
, strlen(str
) + 20, "%s%s)", DSTRING
, str
);
6252 v
->global_val
.p
[strlen(str
) + 20 - 1] = '\0';
6257 case INICK_INICK_CONF
:
6258 case INICK_REPLYTO_CONF
:
6259 case INICK_TEMPL_CONF
:
6260 case INICK_CSTM_CONF
:
6261 case INICK_SMTP_CONF
:
6262 case INICK_NNTP_CONF
:
6268 set_current_val(v
, FALSE
, FALSE
);
6271 CONF_S
*ctmpsig
= NULL
;
6272 struct variable
*vlsig
;
6275 ctmpa
&& ctmpa
->varnamep
== ctmp
;
6276 ctmpa
= ctmpa
->next
){
6278 fs_give((void **)&ctmpa
->value
);
6280 ctmpa
->value
= pretty_value(ps
, ctmpa
);
6283 if(i
== INICK_SIG_CONF
){
6285 * Turn off NOSELECT, but possibly turn it on again
6288 if((ctmpsig
= inick_confs
[INICK_SIG_CONF
]) != NULL
)
6289 ctmpsig
->flags
&= ~CF_NOSELECT
;
6291 if(inick_confs
[INICK_LITSIG_CONF
] &&
6292 (vlsig
= inick_confs
[INICK_LITSIG_CONF
]->var
) &&
6293 vlsig
->current_val
.p
&&
6294 vlsig
->current_val
.p
[0]){
6296 fs_give((void **)&ctmp
->value
);
6299 cpystr("<Ignored: using LiteralSig instead>");
6301 ctmp
->flags
|= CF_NOSELECT
;
6310 * lst: a list of folders
6311 * action: a 1 or 0 value which basically says that str is associated with
6312 * the filter action if true or the Current Folder type if false.
6314 * Returns 2 on success (user wants to exit) and 0 on failure.
6316 * This function cycles through a list of folders and checks whether or not each
6317 * folder exists. If they exist, return 2, if they don't exist, notify the user
6318 * or offer to create depending on whether or not it is a filter action or not.
6319 * With each of these prompts, the user can abort their desire to exit.
6322 check_role_folders(char **lst
, unsigned int action
)
6324 char *cur_fn
, wt_res
, prompt
[MAX_SCREEN_COLS
];
6326 CONTEXT_S
*cntxt
= NULL
;
6327 char nbuf1
[MAX_SCREEN_COLS
], nbuf2
[MAX_SCREEN_COLS
];
6328 int space
, w1
, w2
, exists
;
6332 q_status_message(SM_ORDER
, 3, 5,
6333 _("Set a valid Filter Action before Exiting"));
6335 q_status_message(SM_ORDER
, 3, 5,
6336 _("Set a valid Specific Folder before Exiting"));
6341 for(i
= 0; lst
[i
]; i
++){
6343 cur_fn
= detoken_src(lst
[i
], FOR_FILT
, NULL
, NULL
, NULL
, NULL
);
6347 removing_leading_and_trailing_white_space(cur_fn
);
6348 if(*cur_fn
!= '\0'){
6350 if(is_absolute_path(cur_fn
) || !context_isambig(cur_fn
))
6353 cntxt
= default_save_context(ps_global
->context_list
);
6355 if(!(exists
=folder_exists(cntxt
, cur_fn
))
6357 || (ps_global
->context_list
->use
& CNTXT_INCMNG
6358 && !folder_is_nick(cur_fn
,FOLDERS(ps_global
->context_list
), 0)))){
6359 if(cntxt
&& (action
== 1)){
6360 space
-= 37; /* for fixed part of prompt below */
6361 w1
= MAX(1,MIN(strlen(cur_fn
),space
/2));
6362 w2
= MIN(MAX(1,space
-w1
),strlen(cntxt
->nickname
));
6363 w1
+= MAX(0,space
-w1
-w2
);
6364 snprintf(prompt
, sizeof(prompt
),
6365 _("Folder \"%s\" in <%s> doesn't exist. Create"),
6366 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
),
6367 short_str(cntxt
->nickname
,nbuf2
,sizeof(nbuf2
),w2
,MidDots
));
6368 prompt
[sizeof(prompt
)-1] = '\0';
6370 else if(cntxt
&& (action
== 0)){
6371 space
-= 51; /* for fixed part of prompt below */
6372 w1
= MAX(1,MIN(strlen(cur_fn
),space
/2));
6373 w2
= MIN(MAX(1,space
-w1
),strlen(cntxt
->nickname
));
6374 w1
+= MAX(0,space
-w1
-w2
);
6375 snprintf(prompt
, sizeof(prompt
),
6376 _("Folder \"%s\" in <%s> doesn't exist. Exit and save anyway"),
6377 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
),
6378 short_str(cntxt
->nickname
,nbuf2
,sizeof(nbuf2
),w2
,MidDots
));
6379 prompt
[sizeof(prompt
)-1] = '\0';
6381 else if(!cntxt
&& (action
== 1)){
6382 space
-= 31; /* for fixed part of prompt below */
6384 snprintf(prompt
, sizeof(prompt
),
6385 _("Folder \"%s\" doesn't exist. Create"),
6386 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
));
6387 prompt
[sizeof(prompt
)-1] = '\0';
6389 else{ /*!cntxt && (action == 0) */
6390 space
-= 45; /* for fixed part of prompt below */
6392 snprintf(prompt
, sizeof(prompt
),
6393 _("Folder \"%s\" doesn't exist. Exit and save anyway"),
6394 short_str(cur_fn
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
));
6395 prompt
[sizeof(prompt
)-1] = '\0';
6398 wt_res
= want_to(prompt
, 'n', 'x', NO_HELP
, WT_NORM
);
6401 if(context_create(cntxt
, NULL
, cur_fn
)){
6402 q_status_message(SM_ORDER
,3,5,_("Folder created"));
6403 maybe_add_to_incoming(cntxt
, cur_fn
);
6406 /* No message to notify of changes being saved, we can't */
6407 /* assume that the role screen isn't exited yet */
6410 else if(wt_res
== 'n' && action
){
6412 q_status_message(SM_ORDER
,3,5,_("Folder not created"));
6415 q_status_message(SM_ORDER
,3,5,_("Exit cancelled"));
6421 if(exists
& FEX_ERROR
){
6422 if(ps_global
->mm_log_error
&& ps_global
->c_client_error
)
6423 q_status_message(SM_ORDER
,3,5,ps_global
->c_client_error
);
6425 q_status_message1(SM_ORDER
,3,5,"\"%s\": Trouble checking for folder existence", cur_fn
);
6431 else{ /* blank item in list of folders */
6432 if(action
&& lst
[i
+1] == NULL
)
6433 q_status_message(SM_ORDER
,3,5,_("Set a valid Filter Action before Exiting"));
6434 else /* !action && lst[i+1] == '\0' */
6435 q_status_message(SM_ORDER
,3,5,_("Set a valid Specific Folder before Exiting"));
6440 if(cur_fn
&& cur_fn
!= lst
[i
])
6441 fs_give((void **) &cur_fn
);
6449 maybe_add_to_incoming(CONTEXT_S
*cntxt
, char *cur_fn
)
6451 char name
[MAILTMPLEN
], nname
[32];
6452 char nbuf1
[MAX_SCREEN_COLS
], nbuf2
[MAX_SCREEN_COLS
];
6453 char prompt
[MAX_SCREEN_COLS
];
6455 int i
, found
, space
, w1
, w2
;
6458 if(ps_global
->context_list
->use
& CNTXT_INCMNG
&&
6459 ((alval
= ALVAL(&ps_global
->vars
[V_INCOMING_FOLDERS
], Main
)) != NULL
)){
6460 (void)context_apply(name
, cntxt
, cur_fn
, sizeof(name
));
6462 * Since the folder didn't exist it is very unlikely that it is
6463 * in the incoming-folders list already, but we're just checking
6464 * to be sure. We should really be canonicalizing both names
6465 * before comparing, but...
6467 for(found
= 0, i
= 0; *alval
&& (*alval
)[i
] && !found
; i
++){
6468 char *nickname
, *folder
;
6470 get_pair((*alval
)[i
], &nickname
, &folder
, 0, 0);
6471 if(folder
&& !strucmp((*alval
)[i
], folder
))
6475 fs_give((void **)&nickname
);
6477 fs_give((void **)&folder
);
6484 space
-= 15; /* for fixed part of prompt below */
6486 MIN(space
/2,MIN(strlen(ps_global
->context_list
->nickname
),20)));
6487 w1
= MAX(1,space
- w2
);
6488 snprintf(prompt
, sizeof(prompt
),
6489 "Add \"%s\" to %s list",
6490 short_str(name
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
),
6491 short_str(ps_global
->context_list
->nickname
,nbuf2
,sizeof(nbuf2
),w2
,MidDots
));
6492 prompt
[sizeof(prompt
)-1] = '\0';
6493 if(want_to(prompt
, 'n', 'x', NO_HELP
, WT_NORM
) == 'y'){
6500 snprintf(prompt
, sizeof(prompt
), "Nickname for folder \"%s\" : ",
6501 short_str(name
,nbuf1
,sizeof(nbuf1
),w1
,MidDots
));
6502 prompt
[sizeof(prompt
)-1] = '\0';
6505 int flags
= OE_APPEND_CURRENT
;
6507 rc
= optionally_enter(nname
, -FOOTER_ROWS(ps_global
), 0,
6508 sizeof(nname
), prompt
, NULL
,
6510 removing_leading_and_trailing_white_space(nname
);
6511 if(rc
== 0 && *nname
){
6512 /* see if nickname already exists */
6514 if(!strucmp(ps_global
->inbox_name
, nname
))
6519 i
< folder_total(FOLDERS(ps_global
->context_list
));
6523 f
= folder_entry(i
, FOLDERS(ps_global
->context_list
));
6524 if(!strucmp(FLDR_NAME(f
), nname
))
6529 q_status_message1(SM_ORDER
| SM_DING
, 3, 5,
6530 _("Nickname \"%s\" is already in use"),
6538 q_status_message(SM_ORDER
, 0, 3, _("No help yet."));
6540 q_status_message1(SM_ORDER
, 0, 3,
6541 _("Not adding nickname to %s list"),
6542 ps_global
->context_list
->nickname
);
6547 pp
= put_pair(nname
, name
);
6548 f
= new_folder(name
, line_hash(pp
));
6549 f
->nickname
= cpystr(nname
);
6550 f
->name_len
= strlen(nname
);
6551 folder_insert(folder_total(FOLDERS(ps_global
->context_list
)), f
,
6552 FOLDERS(ps_global
->context_list
));
6556 *alval
= (char **)fs_get(2 * sizeof(char *));
6559 for(i
= 0; (*alval
)[i
]; i
++)
6562 fs_resize((void **)alval
, (i
+ 2) * sizeof(char *));
6566 (*alval
)[i
+1] = NULL
;
6567 set_current_val(&ps_global
->vars
[V_INCOMING_FOLDERS
], TRUE
, TRUE
);
6568 write_pinerc(ps_global
, ew
, WRP_NONE
);
6575 role_filt_exitcheck(CONF_S
**cl
, unsigned int flags
)
6578 char **to_folder
= NULL
, **spec_fldr
= NULL
;
6581 #define ACT_UNKNOWN 0
6584 #define ACT_MOVE_NOFOLDER 3
6588 * We have to locate the lines which define the Filter Action and
6589 * then check to see that it is set to something before allowing
6592 action
= ACT_UNKNOWN
;
6593 if(flags
& CF_CHANGES
&& role_filt_ptr
&& PVAL(role_filt_ptr
,ew
)){
6594 for(j
= 0; (f
= filter_types(j
)); j
++)
6595 if(!strucmp(PVAL(role_filt_ptr
,ew
), f
->name
))
6598 switch(f
? f
->value
: -1){
6609 * Check that the folder is set to something.
6612 action
= ACT_MOVE_NOFOLDER
;
6613 /* go to end of screen */
6616 ctmp
= next_confline(ctmp
))
6619 /* back up to start of Filter Action */
6622 !(ctmp
->flags
& CF_STARTITEM
&& ctmp
->var
== role_filt_ptr
);
6623 ctmp
= prev_confline(ctmp
))
6626 /* skip back past NOSELECTs */
6628 ctmp
&& (ctmp
->flags
& CF_NOSELECT
);
6629 ctmp
= next_confline(ctmp
))
6632 /* find line with new var (the Folder line) */
6634 ctmp
&& (ctmp
->var
== role_filt_ptr
);
6635 ctmp
= next_confline(ctmp
))
6638 /* ok, we're finally at the Folder line */
6639 if(ctmp
&& ctmp
->var
&& LVAL(ctmp
->var
,ew
)){
6640 to_folder
= copy_list_array(LVAL(ctmp
->var
,ew
));
6641 if(to_folder
&& to_folder
[0])
6649 "Can't happen, role_filt_ptr set to %s\n",
6650 PVAL(role_filt_ptr
,ew
) ? PVAL(role_filt_ptr
,ew
) : "?"));
6655 if(flags
& CF_CHANGES
){
6656 switch(want_to((action
== ACT_KILL
)
6657 ? _("Commit changes (\"Yes\" means matching messages will be deleted)")
6658 : EXIT_PMT
, 'y', 'x', h_config_undo
, WT_FLUSH_IN
)){
6662 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
6663 rv
= check_role_folders(spec_fldr
, 0);
6664 free_list_array(&spec_fldr
);
6666 q_status_message(SM_ORDER
,0,3,_("Ok, messages matching that Pattern will be deleted"));
6669 q_status_message(SM_ORDER
, 0, 3,
6670 _("Ok, messages matching that Pattern will be deleted"));
6676 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
6677 rv
= check_role_folders(spec_fldr
, 0);
6678 free_list_array(&spec_fldr
);
6679 if(to_folder
&& rv
== 2)
6680 rv
= check_role_folders(to_folder
, 1);
6683 rv
= check_role_folders(to_folder
, 1);
6687 case ACT_MOVE_NOFOLDER
:
6689 q_status_message(SM_ORDER
, 3, 5,
6690 _("Set a valid Filter Action before Exiting"));
6694 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
6695 rv
= check_role_folders(spec_fldr
, 0);
6696 free_list_array(&spec_fldr
);
6706 "This can't happen, role_filt_ptr or to_folder not set\n"));
6713 q_status_message(SM_ORDER
,3,5,_("No filter changes saved"));
6719 q_status_message(SM_ORDER
,3,5,_("Changes not yet saved"));
6728 free_list_array(&to_folder
);
6735 * Don't allow exit unless user has set the action to something.
6738 role_filt_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6744 rv
= role_filt_exitcheck(cl
, flags
);
6748 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6757 role_filt_addhdr_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6763 rv
= role_filt_exitcheck(cl
, flags
);
6767 rv
= role_addhdr_tool(ps
, cmd
, cl
, flags
);
6775 role_addhdr_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6782 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6794 * Don't allow exit unless user has set the action to something.
6797 role_filt_radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6803 rv
= role_filt_exitcheck(cl
, flags
);
6807 rv
= role_radiobutton_tool(ps
, cmd
, cl
, flags
);
6816 * simple radio-button style variable handler
6819 role_radiobutton_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6822 CONF_S
*ctmp
, *spec_ctmp
= NULL
;
6827 case MC_CHOICE
: /* set/unset feature */
6829 /* back up to first line */
6831 ctmp
&& ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
);
6832 ctmp
= prev_confline(ctmp
))
6835 for(i
= 0; ctmp
&& (!(ctmp
->flags
& CF_NOSELECT
)
6836 || (*cl
)->var
== role_fldr_ptr
6837 || (*cl
)->var
== role_afrom_ptr
6838 || (*cl
)->var
== role_filt_ptr
);
6839 ctmp
= next_confline(ctmp
), i
++){
6840 if(((*cl
)->var
== role_fldr_ptr
) ||
6841 ((*cl
)->var
== role_afrom_ptr
) ||
6842 ((*cl
)->var
== role_filt_ptr
)){
6843 if((((*cl
)->var
== role_fldr_ptr
) && !pat_fldr_types(i
))
6844 || (((*cl
)->var
== role_afrom_ptr
)
6845 && !inabook_fldr_types(i
))
6846 || (((*cl
)->var
== role_filt_ptr
) && !filter_types(i
))){
6852 ctmp
->value
[1] = ' ';
6855 /* turn on current value */
6856 (*cl
)->value
[1] = R_SELD
;
6858 if((*cl
)->var
== role_fldr_ptr
){
6859 for(ctmp
= spec_ctmp
;
6860 ctmp
&& ctmp
->varnamep
== spec_ctmp
;
6861 ctmp
= next_confline(ctmp
))
6862 if((*cl
)->varmem
== FLDR_SPECIFIC
)
6863 ctmp
->flags
&= ~CF_NOSELECT
;
6865 ctmp
->flags
|= CF_NOSELECT
;
6867 rule
= pat_fldr_types((*cl
)->varmem
);
6869 else if((*cl
)->var
== role_afrom_ptr
){
6870 for(ctmp
= spec_ctmp
;
6871 ctmp
&& ctmp
->varnamep
== spec_ctmp
;
6872 ctmp
= next_confline(ctmp
))
6873 if(((*cl
)->varmem
== IAB_SPEC_YES
)
6874 || ((*cl
)->varmem
== IAB_SPEC_NO
))
6875 ctmp
->flags
&= ~CF_NOSELECT
;
6877 ctmp
->flags
|= CF_NOSELECT
;
6879 rule
= inabook_fldr_types((*cl
)->varmem
);
6881 else if((*cl
)->var
== role_filt_ptr
){
6882 for(ctmp
= spec_ctmp
;
6883 ctmp
&& ctmp
->varnamep
== spec_ctmp
;
6884 ctmp
= next_confline(ctmp
))
6885 if((*cl
)->varmem
== FILTER_FOLDER
)
6886 ctmp
->flags
&= ~CF_NOSELECT
;
6888 ctmp
->flags
|= CF_NOSELECT
;
6890 rule
= filter_types((*cl
)->varmem
);
6892 else if((*cl
)->var
== role_forw_ptr
)
6893 rule
= role_forw_types((*cl
)->varmem
);
6894 else if((*cl
)->var
== role_repl_ptr
)
6895 rule
= role_repl_types((*cl
)->varmem
);
6896 else if((*cl
)->var
== role_status1_ptr
||
6897 (*cl
)->var
== role_status2_ptr
||
6898 (*cl
)->var
== role_status3_ptr
||
6899 (*cl
)->var
== role_status4_ptr
||
6900 (*cl
)->var
== role_status5_ptr
||
6901 (*cl
)->var
== role_status6_ptr
||
6902 (*cl
)->var
== role_status7_ptr
||
6903 (*cl
)->var
== role_status8_ptr
)
6904 rule
= role_status_types((*cl
)->varmem
);
6905 else if((*cl
)->var
== msg_state1_ptr
||
6906 (*cl
)->var
== msg_state2_ptr
||
6907 (*cl
)->var
== msg_state3_ptr
||
6908 (*cl
)->var
== msg_state4_ptr
)
6909 rule
= msg_state_types((*cl
)->varmem
);
6911 rule
= role_comp_types((*cl
)->varmem
);
6913 apval
= APVAL((*cl
)->var
, ew
);
6915 fs_give((void **)apval
);
6918 *apval
= cpystr(rule
->name
);
6920 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
6925 case MC_EXIT
: /* exit */
6926 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
6939 role_sort_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
6947 apval
= APVAL((*cl
)->var
, ew
);
6950 case MC_CHOICE
: /* set/unset feature */
6952 if((*cl
)->varmem
>= 0){
6953 def_sort_rev
= (*cl
)->varmem
>= (short) EndofList
;
6954 def_sort
= (SortOrder
)((*cl
)->varmem
- (def_sort_rev
* EndofList
));
6956 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s", sort_name(def_sort
),
6957 (def_sort_rev
) ? "/Reverse" : "");
6958 tmp_20k_buf
[SIZEOF_20KBUF
-1] = '\0';
6963 fs_give((void **)apval
);
6965 if((*cl
)->varmem
>= 0)
6966 *apval
= cpystr(tmp_20k_buf
);
6969 /* back up to first line */
6971 ctmp
&& ctmp
->prev
&& !(ctmp
->prev
->flags
& CF_NOSELECT
);
6972 ctmp
= prev_confline(ctmp
))
6975 /* turn off all values */
6977 ctmp
&& !(ctmp
->flags
& CF_NOSELECT
);
6978 ctmp
= next_confline(ctmp
), i
++)
6979 ctmp
->value
[1] = ' ';
6981 /* turn on current value */
6982 (*cl
)->value
[1] = R_SELD
;
6984 ps
->mangled_body
= 1; /* BUG: redraw it all for now? */
6989 case MC_EXIT
: /* exit */
6990 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7002 * Return an allocated list of the Specific Folder list for
7003 * roles, or NULL if Current Folder type is not set to
7004 * to Specific Folder
7006 * WARNING, the method used in obtaining the specific folder is
7007 * VERY dependent on the order in which it is presented on the
7008 * screen. If the Current Folder radio buttons were changed,
7009 * this function would probably need to be fixed accordingly.
7012 get_role_specific_folder(CONF_S
**cl
)
7016 /* go to the first line */
7019 ctmp
= prev_confline(ctmp
))
7022 /* go to the current folder radio button list */
7023 while(ctmp
&& ctmp
->var
!= role_fldr_ptr
)
7024 ctmp
= next_confline(ctmp
);
7026 /* go to the specific folder button (caution) */
7027 while(ctmp
&& ctmp
->varmem
!= FLDR_SPECIFIC
)
7028 ctmp
= next_confline(ctmp
);
7030 /* check if selected (assumption of format "(*)" */
7031 if(ctmp
&& ctmp
->value
[1] == R_SELD
){
7032 /* go to next line, the start of the list */
7033 ctmp
= next_confline(ctmp
);
7034 if(LVAL(ctmp
->var
, ew
))
7035 return copy_list_array(LVAL(ctmp
->var
, ew
));
7040 * Need to allocate empty string so as not to confuse it
7041 * with the possibility that Specific Folder is not selected.
7043 ltmp
= (char **) fs_get(2 * sizeof(char *));
7044 ltmp
[0] = cpystr("");
7057 role_litsig_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7064 rv
= litsig_text_tool(ps
, cmd
, cl
, flags
);
7066 calculate_inick_stuff(ps
);
7071 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7082 role_cstm_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7088 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7092 rv
= text_tool(ps
, cmd
, cl
, flags
);
7093 if(rv
== 1 && (*cl
)->var
){
7096 lval
= LVAL((*cl
)->var
, ew
);
7097 if(lval
&& lval
[(*cl
)->varmem
] &&
7098 ((!struncmp(lval
[(*cl
)->varmem
],"from",4) &&
7099 (lval
[(*cl
)->varmem
][4] == ':' ||
7100 lval
[(*cl
)->varmem
][4] == '\0')) ||
7101 (!struncmp(lval
[(*cl
)->varmem
],"reply-to",8) &&
7102 (lval
[(*cl
)->varmem
][8] == ':' ||
7103 lval
[(*cl
)->varmem
][8] == '\0'))))
7104 q_status_message1(SM_ORDER
|SM_DING
, 5, 7,
7105 "Use \"Set %s\" instead, Change ignored",
7106 !struncmp(lval
[(*cl
)->varmem
],"from",4)
7107 ? "From" : "Reply-To");
7120 role_text_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7122 OPT_SCREEN_S
*saved_screen
;
7123 int rv
= -1, oeflags
, len
, sig
, r
, i
, cancel
= 0;
7124 char *file
, *err
, title
[20], *newfile
, *lc
, *addr
, *fldr
= NULL
, *tmpfldr
;
7125 char dir2
[MAXPATH
+1], pdir
[MAXPATH
+1], *p
;
7126 char full_filename
[MAXPATH
+1], filename
[MAXPATH
+1];
7127 char tmp
[MAXPATH
+1], **spec_fldr
, **apval
;
7128 EARB_S
*earb
, *ea
, *eaprev
;
7129 CONF_S
*ctmp
, *ctmpb
, *newcp
, *ctend
;
7134 if(flags
& CF_CHANGES
){
7135 switch(want_to(EXIT_PMT
, 'y', 'x', h_config_role_undo
, WT_FLUSH_IN
)){
7137 if((spec_fldr
= get_role_specific_folder(cl
)) != NULL
){
7138 rv
= check_role_folders(spec_fldr
, 0);
7139 free_list_array(&spec_fldr
);
7146 q_status_message(SM_ORDER
,3,5,_("No changes saved"));
7151 q_status_message(SM_ORDER
,3,5,_("Changes not yet saved"));
7161 case MC_NOT
: /* toggle between !matching and matching */
7162 ctmp
= (*cl
)->varnamep
;
7163 if(ctmp
->varname
&& ctmp
->var
&& ctmp
->var
->name
){
7164 if(!strncmp(ctmp
->varname
, NOT
, NOTLEN
) &&
7165 !strncmp(ctmp
->var
->name
, NOT
, NOTLEN
)){
7166 rplstr(ctmp
->var
->name
, strlen(ctmp
->var
->name
)+1, NOTLEN
, "");
7167 rplstr(ctmp
->varname
, strlen(ctmp
->varname
)+1, NOTLEN
, "");
7168 strncpy(ctmp
->varname
+strlen(ctmp
->varname
)-1,
7169 repeat_char(NOTLEN
, ' '), NOTLEN
+1);
7170 strncat(ctmp
->varname
, "=", NOTLEN
);
7173 rplstr(ctmp
->var
->name
, strlen(ctmp
->var
->name
)+NOTLEN
+1, 0, NOT
);
7174 strncpy(ctmp
->varname
+strlen(ctmp
->varname
)-1-NOTLEN
, "=", NOTLEN
);
7175 rplstr(ctmp
->varname
, strlen(ctmp
->varname
)+NOTLEN
+1, 0, NOT
);
7183 case MC_CHOICE
: /* Choose a file */
7185 * In signature_path we read signature files relative to the pinerc
7186 * dir, so if user selects one that is in there we'll make it
7187 * relative instead of absolute, so it looks nicer.
7190 if(ps_global
->VAR_OPER_DIR
){
7191 strncpy(pdir
, ps_global
->VAR_OPER_DIR
, MAXPATH
);
7192 pdir
[MAXPATH
] = '\0';
7193 len
= strlen(pdir
) + 1;
7195 else if((lc
= last_cmpnt(ps_global
->pinerc
)) != NULL
){
7196 strncpy(pdir
, ps_global
->pinerc
, MIN(MAXPATH
,lc
-ps_global
->pinerc
));
7197 pdir
[MIN(MAXPATH
, lc
-ps_global
->pinerc
)] = '\0';
7201 strncpy(title
, "CHOOSE A", 15);
7202 strncpy(dir2
, pdir
, MAXPATH
);
7205 build_path(full_filename
, dir2
, filename
, sizeof(full_filename
));
7207 r
= file_lister(title
, dir2
, sizeof(dir2
), filename
, sizeof(filename
), TRUE
, FB_READ
);
7208 ps
->mangled_screen
= 1;
7211 build_path(full_filename
, dir2
, filename
, sizeof(full_filename
));
7212 removing_leading_and_trailing_white_space(full_filename
);
7213 if(!strncmp(full_filename
, pdir
, strlen(pdir
)))
7214 newfile
= cpystr(full_filename
+ len
);
7216 newfile
= cpystr(full_filename
);
7218 apval
= APVAL((*cl
)->var
, ew
);
7220 fs_give((void **)apval
);
7226 fs_give((void **)&((*cl
)->value
));
7228 (*cl
)->value
= pretty_value(ps
, *cl
);
7236 case MC_CHOICEB
: /* Choose Addresses, no full names */
7237 addr
= addr_book_multaddr_nf();
7238 ps
->mangled_screen
= 1;
7239 if(addr
&& (*cl
)->var
&& (*cl
)->var
->is_list
){
7244 for(tmp
= addr
; *tmp
; tmp
++)
7246 i
++; /* conservative count of ,'s */
7248 ltmp
= parse_list(addr
, i
+ 1, PL_COMMAQUOTE
, NULL
);
7249 fs_give((void **) &addr
);
7252 config_add_list(ps
, cl
, ltmp
, NULL
, 0);
7255 fs_give((void **) <mp
);
7258 fs_give((void **)&((*cl
)->value
));
7260 (*cl
)->value
= pretty_value(ps
, *cl
);
7268 case MC_CHOICEC
: /* Choose an Address, no full name */
7269 addr
= addr_book_oneaddr();
7270 ps
->mangled_screen
= 1;
7272 apval
= APVAL((*cl
)->var
, ew
);
7273 if(apval
&& *apval
) /* replace current value */
7274 fs_give((void **)apval
);
7280 fs_give((void **)&((*cl
)->value
));
7282 (*cl
)->value
= pretty_value(ps
, *cl
);
7290 case MC_CHOICED
: /* Choose a Folder */
7292 saved_screen
= opt_screen
;
7293 if(cmd
== MC_CHOICED
)
7294 tmpfldr
= folder_for_config(FOR_PATTERN
);
7296 tmpfldr
= folder_for_config(0);
7299 fldr
= add_comma_escapes(tmpfldr
);
7300 fs_give((void**) &tmpfldr
);
7303 opt_screen
= saved_screen
;
7305 ps
->mangled_screen
= 1;
7306 if(fldr
&& *fldr
&& (*cl
)->var
&& (*cl
)->var
->is_list
){
7309 ltmp
= (char **) fs_get(2 * sizeof(char *));
7315 config_add_list(ps
, cl
, ltmp
, NULL
, 0);
7318 fs_give((void **) <mp
);
7321 fs_give((void **) &((*cl
)->value
));
7323 (*cl
)->value
= pretty_value(ps
, *cl
);
7326 else if(fldr
&& *fldr
&& (*cl
)->var
&& !(*cl
)->var
->is_list
){
7327 apval
= APVAL((*cl
)->var
, ew
);
7328 if(apval
&& *apval
) /* replace current value */
7329 fs_give((void **)apval
);
7337 fs_give((void **) &((*cl
)->value
));
7339 (*cl
)->value
= pretty_value(ps
, *cl
);
7346 fs_give((void **) &fldr
);
7351 file
= ((*cl
)->var
&& PVAL((*cl
)->var
, ew
))
7352 ? cpystr(PVAL((*cl
)->var
, ew
)) : NULL
;
7354 removing_leading_and_trailing_white_space(file
);
7356 sig
= (srchstr((*cl
)->varname
, "signature") != NULL
);
7357 if(!file
|| !*file
){
7358 err
= (char *)fs_get(100 * sizeof(char));
7359 snprintf(err
, 100, "No %s file defined. First define a file name.",
7360 sig
? "signature" : "template");
7364 if(file
[len
=(strlen(file
)-1)] == '|')
7367 snprintf(title
, sizeof(title
), "%s EDITOR", sig
? "SIGNATURE" : "TEMPLATE");
7368 title
[sizeof(title
)-1] = '\0';
7369 err
= signature_edit(file
, title
);
7372 fs_give((void **)&file
);
7374 q_status_message1(SM_ORDER
, 3, 5, "%s", err
);
7375 fs_give((void **)&err
);
7379 ps
->mangled_screen
= 1;
7382 /* Add an arbitrary header to this role */
7385 /* make earb point to last one */
7386 for(earb
= *(*cl
)->d
.earb
; earb
&& earb
->next
; earb
= earb
->next
)
7389 /* Add new one to end of list */
7390 ea
= (EARB_S
*)fs_get(sizeof(*ea
));
7391 memset((void *)ea
, 0, sizeof(*ea
));
7392 ea
->v
= (struct variable
*)fs_get(sizeof(struct variable
));
7393 memset((void *)ea
->v
, 0, sizeof(struct variable
));
7394 ea
->a
= (ARBHDR_S
*)fs_get(sizeof(ARBHDR_S
));
7395 memset((void *)ea
->a
, 0, sizeof(ARBHDR_S
));
7397 /* get new header field name */
7401 i
= optionally_enter(tmp
, -FOOTER_ROWS(ps
), 0, sizeof(tmp
),
7402 _("Enter the name of the header field to be added: "),
7407 cmd_cancelled("eXtraHdr");
7412 help
= help
== NO_HELP
? h_config_add_pat_hdr
: NO_HELP
;
7419 ps
->mangled_footer
= 1;
7421 removing_leading_and_trailing_white_space(tmp
);
7422 if(tmp
[strlen(tmp
)-1] == ':') /* remove trailing colon */
7423 tmp
[strlen(tmp
)-1] = '\0';
7425 removing_trailing_white_space(tmp
);
7427 if(cancel
|| !tmp
[0])
7430 tmp
[0] = islower((unsigned char)tmp
[0]) ? toupper((unsigned char)tmp
[0])
7432 ea
->a
->field
= cpystr(tmp
);
7437 *((*cl
)->d
.earb
) = ea
;
7439 /* go to first line */
7440 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
7444 * Go to the Add Extra Headers line. We will put the
7445 * new header before this line.
7447 for(; ctmp
; ctmp
= next_confline(ctmp
))
7448 if(ctmp
->value
&& !strcmp(ctmp
->value
, ADDXHDRS
))
7453 ctmp
= prev_confline(ctmp
);
7456 * Add a new line after this point, which is after the last
7457 * extra header (if any) or after the Participant pattern, and
7458 * before the Add Extra Headers placeholder line.
7460 p
= (char *) fs_get(strlen(tmp
) + strlen(" pattern") + 1);
7461 snprintf(p
, strlen(tmp
) + strlen(" pattern") + 1, "%s pattern", tmp
);
7462 p
[strlen(tmp
) + strlen(" pattern") + 1 - 1] = '\0';
7463 setup_dummy_pattern_var(ea
->v
, p
, NULL
);
7464 fs_give((void **) &p
);
7466 /* find what indent should be */
7467 if(ctmp
&& ctmp
->varnamep
&& ctmp
->varnamep
->varname
)
7468 i
= MIN(MAX(utf8_width(ctmp
->varnamep
->varname
) + 1, 3), 200);
7472 setup_role_pat(ps
, &ctmp
, ea
->v
, h_config_role_arbpat
,
7473 ARB_HELP
, &config_role_xtrahdr_keymenu
,
7474 ctmp
->prev
->tool
, ctmp
->prev
->d
.earb
, i
);
7477 * move current line to new line
7482 /* check if new line comes before the top of the screen */
7483 ctmpb
= (opt_screen
&& opt_screen
->top_line
)
7484 ? opt_screen
->top_line
->prev
: NULL
;
7485 for(; ctmpb
; ctmpb
= prev_confline(ctmpb
))
7489 * Keep the right lines visible.
7490 * The if triggers if the new line is off the top of the screen, and
7491 * it makes the new line be the top line.
7492 * The else counts how many lines down the screen the new line is.
7497 opt_screen
->top_line
= newcp
;
7499 for(ctmp
= opt_screen
->top_line
; ctmp
&& ctmp
!= newcp
;
7500 i
++, ctmp
= next_confline(ctmp
))
7504 if(i
>= BODY_LINES(ps
)){ /* new line is off screen */
7505 /* move top line down this far */
7506 i
= i
+ 1 - BODY_LINES(ps
);
7507 for(ctmp
= opt_screen
->top_line
;
7509 i
--, ctmp
= next_confline(ctmp
))
7512 opt_screen
->top_line
= ctmp
;
7517 ps
->mangled_screen
= 1;
7521 /* Delete an arbitrary header from this role */
7524 * Find this one in earb list. We don't have a good way to locate
7525 * it so we match the ea->v->name with ctmp->varname.
7529 for(ea
= *(*cl
)->d
.earb
; ea
; ea
= ea
->next
){
7530 if((*cl
)->varnamep
&& (*cl
)->varnamep
->varname
7531 && ea
->v
&& ea
->v
->name
7532 && !strncmp((*cl
)->varnamep
->varname
,
7533 ea
->v
->name
, strlen(ea
->v
->name
)))
7539 snprintf(tmp
, sizeof(tmp
), _("Really remove \"%s\" pattern from this rule"),
7540 (ea
&& ea
->a
&& ea
->a
->field
) ? ea
->a
->field
: "this");
7541 tmp
[sizeof(tmp
)-1] = '\0';
7542 if(want_to(tmp
, 'y', 'n', NO_HELP
, WT_NORM
) != 'y'){
7543 cmd_cancelled("RemoveHdr");
7547 /* delete the earb element from the list */
7550 eaprev
->next
= ea
->next
;
7552 *(*cl
)->d
.earb
= ea
->next
;
7558 /* remember start of deleted header */
7559 ctmp
= (*cl
&& (*cl
)->varnamep
) ? (*cl
)->varnamep
: NULL
;
7561 /* and end of deleted header */
7562 for(ctend
= *cl
; ctend
; ctend
= next_confline(ctend
))
7563 if(!ctend
->next
|| ctend
->next
->varnamep
!= ctmp
)
7566 /* check if top line is one we're deleting */
7567 for(ctmpb
= ctmp
; ctmpb
; ctmpb
= next_confline(ctmpb
)){
7568 if(ctmpb
== opt_screen
->top_line
)
7575 if(ctmpb
== opt_screen
->top_line
)
7576 opt_screen
->top_line
= ctend
? ctend
->next
: NULL
;
7578 /* move current line after this header */
7579 *cl
= ctend
? ctend
->next
: NULL
;
7581 /* remove deleted header lines */
7583 /* remove from linked list */
7585 ctmp
->prev
->next
= ctend
->next
;
7588 ctend
->next
->prev
= ctmp
->prev
;
7591 ctmp
->prev
= ctend
->next
= NULL
;
7592 free_conflines(&ctmp
);
7595 ps
->mangled_body
= 1;
7600 if(((*cl
)->var
== scorei_pat_global_ptr
7601 || (*cl
)->var
== age_pat_global_ptr
7602 || (*cl
)->var
== size_pat_global_ptr
7603 || (*cl
)->var
== cati_global_ptr
)
7605 (cmd
== MC_EDIT
|| (cmd
== MC_ADD
&& !PVAL((*cl
)->var
, ew
)))){
7609 snprintf(prompt
, sizeof(prompt
), "%s the interval : ",
7610 PVAL((*cl
)->var
, ew
) ? "Change" : "Enter");
7611 prompt
[sizeof(prompt
)-1] = '\0';
7613 ps
->mangled_footer
= 1;
7616 snprintf(tmp
, sizeof(tmp
),
7617 "%s", PVAL((*cl
)->var
, ew
) ? PVAL((*cl
)->var
, ew
) : "");
7618 tmp
[sizeof(tmp
)-1] = '\0';
7620 oeflags
= OE_APPEND_CURRENT
;
7621 i
= optionally_enter(tmp
, -FOOTER_ROWS(ps
), 0, sizeof(tmp
),
7622 prompt
, NULL
, help
, &oeflags
);
7624 rv
= ps
->mangled_body
= 1;
7625 apval
= APVAL((*cl
)->var
, ew
);
7627 fs_give((void **)apval
);
7630 *apval
= cpystr(tmp
);
7632 fix_side_effects(ps
, (*cl
)->var
, 0);
7634 fs_give((void **)&(*cl
)->value
);
7636 (*cl
)->value
= pretty_value(ps
, *cl
);
7639 cmd_cancelled(cmd
== MC_ADD
? "Add" : "Change");
7641 help
= help
== NO_HELP
? h_config_edit_scorei
: NO_HELP
;
7651 if(cmd
== MC_ADD
&& (*cl
)->var
&& !(*cl
)->var
->is_list
)
7654 rv
= text_toolit(ps
, cmd
, cl
, flags
, 1);
7656 /* make sure the earb pointers are set */
7657 for(ctmp
= (*cl
)->varnamep
;
7658 ctmp
->next
&& ctmp
->next
->var
== ctmp
->var
;
7659 ctmp
= next_confline(ctmp
))
7660 ctmp
->next
->d
.earb
= ctmp
->d
.earb
;
7667 * If the inherit nickname changed, we have to re-calculate the
7668 * global_vals and values for the action variables.
7669 * We may have to do the same if literal sig changed, too.
7672 calculate_inick_stuff(ps
);
7681 role_text_tool_inick(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7688 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7691 case MC_CHOICE
: /* Choose a role nickname */
7692 {void (*prev_screen
)(struct pine
*) = ps
->prev_screen
,
7693 (*redraw
)(void) = ps
->redrawer
;
7694 OPT_SCREEN_S
*saved_screen
;
7697 ps
->redrawer
= NULL
;
7698 ps
->next_screen
= SCREEN_FUN_NULL
;
7700 saved_screen
= opt_screen
;
7701 if(role_select_screen(ps
, &role
, 0) == 0){
7702 apval
= APVAL((*cl
)->var
, ew
);
7704 fs_give((void **)apval
);
7707 *apval
= (role
&& role
->nick
) ? cpystr(role
->nick
) : NULL
;
7710 fs_give((void **)&((*cl
)->value
));
7712 (*cl
)->value
= pretty_value(ps
, *cl
);
7716 ps
->next_screen
= prev_screen
;
7717 ps
->redrawer
= redraw
;
7721 opt_screen
= saved_screen
;
7724 ps
->mangled_screen
= 1;
7730 rv
= text_tool(ps
, cmd
, cl
, flags
);
7731 ps
->mangled_screen
= 1;
7735 rv
= text_tool(ps
, cmd
, cl
, flags
);
7740 * If the inherit nickname changed, we have to re-calculate the
7741 * global_vals and values for the action variables.
7742 * We may have to do the same if literal sig changed, too.
7745 calculate_inick_stuff(ps
);
7754 role_text_tool_kword(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7760 case MC_CHOICE
: /* Choose keywords from list and add them */
7761 {void (*prev_screen
)(struct pine
*) = ps
->prev_screen
,
7762 (*redraw
)(void) = ps
->redrawer
;
7763 OPT_SCREEN_S
*saved_screen
;
7767 ps
->redrawer
= NULL
;
7768 ps
->next_screen
= SCREEN_FUN_NULL
;
7770 saved_screen
= opt_screen
;
7772 if((kw
=choose_list_of_keywords()) != NULL
){
7773 for(i
= 0; kw
[i
]; i
++){
7774 esc
= add_roletake_escapes(kw
[i
]);
7775 fs_give((void **) &kw
[i
]);
7779 /* eliminate duplicates before the add */
7780 lval
= LVAL((*cl
)->var
, ew
);
7782 for(i
= 0; kw
[i
]; ){
7783 /* if kw[i] is a dup, eliminate it */
7784 for(j
= 0; lval
[j
]; j
++)
7785 if(!strcmp(kw
[i
], lval
[j
]))
7788 if(lval
[j
]){ /* it is a dup */
7789 for(j
= i
; kw
[j
]; j
++)
7798 config_add_list(ps
, cl
, kw
, NULL
, 0);
7800 fs_give((void **) &kw
);
7803 fs_give((void **) &((*cl
)->value
));
7805 (*cl
)->value
= pretty_value(ps
, *cl
);
7809 ps
->next_screen
= prev_screen
;
7810 ps
->redrawer
= redraw
;
7814 opt_screen
= saved_screen
;
7817 ps
->mangled_screen
= 1;
7824 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7825 ps
->mangled_screen
= 1;
7830 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7841 role_text_tool_charset(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7847 case MC_CHOICE
: /* Choose charsets from list and add them */
7848 {void (*prev_screen
)(struct pine
*) = ps
->prev_screen
,
7849 (*redraw
)(void) = ps
->redrawer
;
7850 OPT_SCREEN_S
*saved_screen
;
7854 ps
->redrawer
= NULL
;
7855 ps
->next_screen
= SCREEN_FUN_NULL
;
7857 saved_screen
= opt_screen
;
7859 if((kw
=choose_list_of_charsets()) != NULL
){
7860 for(i
= 0; kw
[i
]; i
++){
7861 esc
= add_roletake_escapes(kw
[i
]);
7862 fs_give((void **) &kw
[i
]);
7866 /* eliminate duplicates before the add */
7867 lval
= LVAL((*cl
)->var
, ew
);
7869 for(i
= 0; kw
[i
]; ){
7870 /* if kw[i] is a dup, eliminate it */
7871 for(j
= 0; lval
[j
]; j
++)
7872 if(!strcmp(kw
[i
], lval
[j
]))
7875 if(lval
[j
]){ /* it is a dup */
7876 for(j
= i
; kw
[j
]; j
++)
7885 config_add_list(ps
, cl
, kw
, NULL
, 0);
7887 fs_give((void **) &kw
);
7890 fs_give((void **) &((*cl
)->value
));
7892 (*cl
)->value
= pretty_value(ps
, *cl
);
7896 ps
->next_screen
= prev_screen
;
7897 ps
->redrawer
= redraw
;
7901 opt_screen
= saved_screen
;
7904 ps
->mangled_screen
= 1;
7911 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7912 ps
->mangled_screen
= 1;
7917 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7926 * Choose an address book nickname
7929 role_text_tool_afrom(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
7935 rv
= role_text_tool(ps
, cmd
, cl
, flags
);
7938 case MC_CHOICE
: /* Choose an addressbook */
7939 {OPT_SCREEN_S
*saved_screen
;
7940 char *abook
= NULL
, *abookesc
= NULL
;
7942 ps
->redrawer
= NULL
;
7943 ps
->next_screen
= SCREEN_FUN_NULL
;
7944 saved_screen
= opt_screen
;
7946 abook
= abook_select_screen(ps
);
7948 abookesc
= add_comma_escapes(abook
);
7949 fs_give((void**) &abook
);
7952 ps
->mangled_screen
= 1;
7953 if(abookesc
&& *abookesc
&& (*cl
)->var
&& (*cl
)->var
->is_list
){
7956 ltmp
= (char **) fs_get(2 * sizeof(char *));
7962 config_add_list(ps
, cl
, ltmp
, NULL
, 0);
7965 fs_give((void **) <mp
);
7968 fs_give((void **) &((*cl
)->value
));
7970 (*cl
)->value
= pretty_value(ps
, *cl
);
7977 fs_give((void **) &abookesc
);
7979 opt_screen
= saved_screen
;
7982 ps
->mangled_screen
= 1;
7986 rv
= text_tool(ps
, cmd
, cl
, flags
);
7987 ps
->mangled_screen
= 1;
7996 * Args fmt -- a printf style fmt string with a single %s
7997 * buf -- place to put result, assumed large enough (strlen(fmt)+11)
7998 * rflags -- controls what goes in buf
8000 * Returns -- pointer to buf
8003 role_type_print(char *buf
, size_t buflen
, char *fmt
, long int rflags
)
8005 #define CASE_MIXED 1
8006 #define CASE_UPPER 2
8007 #define CASE_LOWER 3
8008 int cas
= CASE_UPPER
;
8009 int prev_word_is_a
= 0;
8012 /* find %sRule to see what case */
8013 if((p
= srchstr(fmt
, "%srule")) != NULL
){
8025 (p
[-2] == 'a' || p
[-2] == 'A')
8030 if(cas
== CASE_UPPER
)
8031 q
= (rflags
& ROLE_DO_INCOLS
) ? "INDEX COLOR " :
8032 (rflags
& ROLE_DO_FILTER
) ? "FILTERING " :
8033 (rflags
& ROLE_DO_SCORES
) ? "SCORING " :
8034 (rflags
& ROLE_DO_OTHER
) ? "OTHER " :
8035 (rflags
& ROLE_DO_SRCH
) ? "SEARCH " :
8036 (rflags
& ROLE_DO_ROLES
) ? "ROLE " : "";
8037 else if(cas
== CASE_LOWER
)
8038 q
= (rflags
& ROLE_DO_INCOLS
) ? "index color " :
8039 (rflags
& ROLE_DO_FILTER
) ? "filtering " :
8040 (rflags
& ROLE_DO_SCORES
) ? "scoring " :
8041 (rflags
& ROLE_DO_OTHER
) ? "other " :
8042 (rflags
& ROLE_DO_OTHER
) ? "search " :
8043 (rflags
& ROLE_DO_ROLES
) ? "role " : "";
8045 q
= (rflags
& ROLE_DO_INCOLS
) ? "Index Color " :
8046 (rflags
& ROLE_DO_FILTER
) ? "Filtering " :
8047 (rflags
& ROLE_DO_SCORES
) ? "Scoring " :
8048 (rflags
& ROLE_DO_OTHER
) ? "Other " :
8049 (rflags
& ROLE_DO_OTHER
) ? "Search " :
8050 (rflags
& ROLE_DO_ROLES
) ? "Role " : "";
8052 /* it ain't right to say "a index" */
8053 if(prev_word_is_a
&& !struncmp(q
, "index", 5))
8056 snprintf(buf
, buflen
, fmt
, q
);
8057 buf
[buflen
-1] = '\0';
8063 * filter option list manipulation tool
8066 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
8069 feat_checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
8074 case MC_TOGGLE
: /* mark/unmark option */
8076 toggle_feat_option_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, (*cl
)->value
);
8079 case MC_EXIT
: /* exit */
8080 rv
= role_filt_exitcheck(cl
, flags
);
8093 toggle_feat_option_bit(struct pine
*ps
, int index
, struct variable
*var
, char *value
)
8097 f
= feat_feature_list(index
);
8100 if(bitnset(f
->value
, feat_option_list
))
8101 clrbitn(f
->value
, feat_option_list
);
8103 setbitn(f
->value
, feat_option_list
);
8106 value
[1] = bitnset(f
->value
, feat_option_list
) ? 'X' : ' ';
8111 feat_feature_list(int index
)
8113 static NAMEVAL_S opt_feat_list
[] = {
8114 {"use-date-header-for-age", NULL
, FEAT_SENTDATE
},
8115 {"move-only-if-not-deleted", NULL
, FEAT_IFNOTDEL
},
8116 {"dont-stop-even-if-rule-matches", NULL
, FEAT_NONTERM
}
8119 return((index
>= 0 &&
8120 index
< (sizeof(opt_feat_list
)/sizeof(opt_feat_list
[0])))
8121 ? &opt_feat_list
[index
] : NULL
);
8126 * address type list manipulation tool
8129 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
8132 inabook_checkbox_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
8137 case MC_TOGGLE
: /* mark/unmark option */
8139 toggle_inabook_type_bit(ps
, (*cl
)->varmem
, (*cl
)->var
, (*cl
)->value
);
8142 case MC_EXIT
: /* exit */
8143 rv
= role_filt_exitcheck(cl
, flags
);
8156 toggle_inabook_type_bit(struct pine
*ps
, int index
, struct variable
*var
, char *value
)
8160 f
= inabook_feature_list(index
);
8163 if(bitnset(f
->value
, inabook_type_list
))
8164 clrbitn(f
->value
, inabook_type_list
);
8166 setbitn(f
->value
, inabook_type_list
);
8169 value
[1] = bitnset(f
->value
, inabook_type_list
) ? 'X' : ' ';
8174 inabook_feature_list(int index
)
8176 static NAMEVAL_S inabook_feat_list
[] = {
8177 {"From", NULL
, INABOOK_FROM
},
8178 {"Reply-To", NULL
, INABOOK_REPLYTO
},
8179 {"Sender", NULL
, INABOOK_SENDER
},
8180 {"To", NULL
, INABOOK_TO
},
8181 {"Cc", NULL
, INABOOK_CC
}
8184 return((index
>= 0 &&
8185 index
< (sizeof(inabook_feat_list
)/sizeof(inabook_feat_list
[0])))
8186 ? &inabook_feat_list
[index
] : NULL
);