#if !defined(lint) && !defined(DOS) static char rcsid[] = "$Id: roleconf.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $"; #endif /* * ======================================================================== * Copyright 2006-2008 University of Washington * Copyright 2013-2021 Eduardo Chappa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * ======================================================================== */ #include "headers.h" #include "roleconf.h" #include "colorconf.h" #include "conftype.h" #include "confscroll.h" #include "keymenu.h" #include "status.h" #include "radio.h" #include "reply.h" #include "folder.h" #include "addrbook.h" #include "mailcmd.h" #include "setup.h" #include "../pith/state.h" #include "../pith/conf.h" #include "../pith/msgno.h" #include "../pith/bitmap.h" #include "../pith/sort.h" #include "../pith/addrstring.h" #include "../pith/list.h" #include "../pith/flag.h" #include "../pith/bldaddr.h" #include "../pith/news.h" #include "../pith/util.h" #include "../pith/detoken.h" #include "../pith/icache.h" #include "../pith/ablookup.h" #include "../pith/pattern.h" #include "../pith/tempfile.h" #define NOT "! " #define NOTLEN 2 #define ARB_HELP _("HELP FOR ARBITRARY HEADER PATTERNS") #define ADDXHDRS _("Add Extra Headers") /* * Internal prototypes */ int role_select_tool(struct pine *, int, CONF_S **, unsigned); PATTERN_S *addrlst_to_pattern(ADDRESS *); void role_config_init_disp(struct pine *, CONF_S **, long, PAT_STATE *); void add_patline_to_display(struct pine *, CONF_S **, int, CONF_S **, CONF_S **, PAT_LINE_S *, long); void add_role_to_display(CONF_S **, PAT_LINE_S *, PAT_S *, int, CONF_S **, int, long); void add_fake_first_role(CONF_S **, int, long); int role_config_tool(struct pine *, int, CONF_S **, unsigned); int role_config_add(struct pine *, CONF_S **, long); int role_config_replicate(struct pine *, CONF_S **, long); int role_config_edit(struct pine *, CONF_S **, long); int role_config_del(struct pine *, CONF_S **, long); void delete_a_role(CONF_S **, long); int role_config_shuffle(struct pine *, CONF_S **); int role_config_addfile(struct pine *, CONF_S **, long); int role_config_delfile(struct pine *, CONF_S **, long); void swap_literal_roles(CONF_S *, CONF_S *); void swap_file_roles(CONF_S *, CONF_S *); void move_role_into_file(CONF_S **, int); void move_role_outof_file(CONF_S **, int); void move_role_around_file(CONF_S **, int); int role_config_edit_screen(struct pine *, PAT_S *, char *, long, PAT_S **); void setup_dummy_pattern_var(struct variable *, char *, PATTERN_S *); void setup_role_pat(struct pine *, CONF_S **, struct variable *, HelpType, char *, struct key_menu *, int (*tool)(struct pine *, int, CONF_S **, unsigned), EARB_S **, int); void setup_role_pat_alt(struct pine *, CONF_S **, struct variable *, HelpType, char *, struct key_menu *, int (*tool)(struct pine *, int, CONF_S **, unsigned), int, int); void free_earb(EARB_S **); void calculate_inick_stuff(struct pine *); int check_role_folders(char **, unsigned); void maybe_add_to_incoming(CONTEXT_S *, char *); int role_filt_exitcheck(CONF_S **, unsigned); int role_filt_text_tool(struct pine *, int, CONF_S **, unsigned); int role_filt_addhdr_tool(struct pine *, int, CONF_S **, unsigned); int role_addhdr_tool(struct pine *, int, CONF_S **, unsigned); int role_filt_radiobutton_tool(struct pine *, int, CONF_S **, unsigned); int role_sort_tool(struct pine *, int, CONF_S **, unsigned); char **get_role_specific_folder(CONF_S **); int role_litsig_text_tool(struct pine *, int, CONF_S **, unsigned); int role_cstm_text_tool(struct pine *, int, CONF_S **, unsigned); int role_text_tool(struct pine *, int, CONF_S **, unsigned); int role_text_tool_inick(struct pine *, int, CONF_S **, unsigned); int role_text_tool_kword(struct pine *, int, CONF_S **, unsigned); int role_text_tool_charset(struct pine *, int, CONF_S **, unsigned); int role_text_tool_afrom(struct pine *, int, CONF_S **, unsigned); char *role_type_print(char *, size_t, char *, long); int feat_checkbox_tool(struct pine *, int, CONF_S **, unsigned); void toggle_feat_option_bit(struct pine *, int, struct variable *, char *); NAMEVAL_S *feat_feature_list(int); int inabook_checkbox_tool(struct pine *, int, CONF_S **, unsigned); void toggle_inabook_type_bit(struct pine *, int, struct variable *, char *); NAMEVAL_S *inabook_feature_list(int); static char *set_choose = "--- --------------------"; static long role_global_flags; static PAT_STATE *role_global_pstate; int role_select_screen(struct pine *ps, ACTION_S **role, int alt_compose) { CONF_S *ctmp = NULL, *first_line = NULL; OPT_SCREEN_S screen; PAT_S *pat, *sel_pat = NULL; int ret = -1; int change_default = 0; long rflags = ROLE_DO_ROLES; char *helptitle; HelpType help; PAT_STATE pstate; if(!role) return(ret); *role = NULL; if(!(nonempty_patterns(rflags, &pstate) && first_pattern(&pstate))){ q_status_message(SM_ORDER, 3, 3, _("No roles available. Use Setup/Rules to add roles.")); return(ret); } if(alt_compose){ menu_init_binding(&role_select_km, alt_compose == MC_FORWARD ? 'F' : alt_compose == MC_REPLY ? 'R' : alt_compose == MC_COMPOSE ? 'C' : 'B', MC_CHOICE, alt_compose == MC_FORWARD ? "F" : alt_compose == MC_REPLY ? "R" : alt_compose == MC_COMPOSE ? "C" : "B", alt_compose == MC_FORWARD ? "[" N_("ForwardAs") "]" : alt_compose == MC_REPLY ? "[" N_("ReplyAs") "]" : alt_compose == MC_COMPOSE ? "[" N_("ComposeAs") "]" : "[" N_("BounceAs") "]", DEFAULT_KEY); menu_add_binding(&role_select_km, ctrl('J'), MC_CHOICE); menu_add_binding(&role_select_km, ctrl('M'), MC_CHOICE); } else{ menu_init_binding(&role_select_km, 'S', MC_CHOICE, "S", "[" N_("Select") "]", DEFAULT_KEY); menu_add_binding(&role_select_km, ctrl('J'), MC_CHOICE); menu_add_binding(&role_select_km, ctrl('M'), MC_CHOICE); } help = h_role_select; if(alt_compose == MC_BOUNCE) helptitle = _("HELP FOR SELECTING A ROLE TO BOUNCE AS"); else if(alt_compose) helptitle = _("HELP FOR SELECTING A ROLE TO COMPOSE AS"); else helptitle = _("HELP FOR SELECTING A ROLE"); menu_init_binding(&role_select_km, 'D', MC_TOGGLE, "D", "changeDef", CHANGEDEF_KEY); for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ new_confline(&ctmp); if(!first_line) first_line = ctmp; ctmp->value = cpystr((pat->patgrp && pat->patgrp->nick) ? pat->patgrp->nick : "?"); ctmp->d.r.selected = &sel_pat; ctmp->d.r.pat = pat; ctmp->d.r.change_def = &change_default; ctmp->keymenu = &role_select_km; ctmp->help = help; ctmp->help_title = helptitle; ctmp->tool = role_select_tool; ctmp->flags = CF_STARTITEM; ctmp->valoffset = 4; } memset(&screen, 0, sizeof(screen)); /* TRANSLATORS: Print something1 using something2. "roles" is something1 */ (void)conf_scroll_screen(ps, &screen, first_line, _("SELECT ROLE"), _("roles"), 0, NULL); if(sel_pat){ *role = sel_pat->action; if(change_default == 1) ps_global->default_role = *role; else if(change_default == 2) ps_global->default_role = NULL; ret = 0; } ps->mangled_screen = 1; return(ret); } int role_select_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int retval = 0, newval; switch(cmd){ case MC_CHOICE : *((*cl)->d.r.selected) = (*cl)->d.r.pat; retval = simple_exit_cmd(flags); break; case MC_TOGGLE : newval = (*((*cl)->d.r.change_def) + 1) % 3; *((*cl)->d.r.change_def) = newval; menu_init_binding((*cl)->keymenu, 'D', MC_TOGGLE, "D", (newval == 0) ? "changeDef" : (newval == 1) ? "removeDef" : "leaveDef", CHANGEDEF_KEY); if(newval == 1){ if(ps_global->default_role) q_status_message(SM_ORDER, 0, 3, _("Default role will be changed to the role you Select")); else q_status_message(SM_ORDER, 0, 3, _("Default role will be set to the role you Select")); } else if(newval == 2){ q_status_message(SM_ORDER, 0, 3, _("Default role will be unset")); } else{ /* newval == 0 */ if(ps_global->default_role) q_status_message(SM_ORDER, 0, 3, _("Default role will remain unchanged")); else q_status_message(SM_ORDER, 0, 3, _("Default role will remain unset")); } ps->mangled_footer = 1; retval = 0; break; case MC_EXIT : retval = simple_exit_cmd(flags); break; default: retval = -1; break; } if(retval > 0) ps->mangled_body = 1; return(retval); } void role_config_screen(struct pine *ps, long int rflags, int edit_exceptions) { CONF_S *first_line; OPT_SCREEN_S screen; char title[100]; int readonly_warning = 0; PAT_STATE pstate; struct variable *v = NULL; dprint((4, "role_config_screen()\n")); if(ps->fix_fixed_warning) offer_to_fix_pinerc(ps); ew = edit_exceptions ? ps_global->ew_for_except_vars : Main; if(ps->restricted) readonly_warning = 1; else{ PINERC_S *prc = NULL; switch(ew){ case Main: prc = ps->prc; rflags |= PAT_USE_MAIN; break; case Post: prc = ps->post_prc; rflags |= PAT_USE_POST; break; default: break; } readonly_warning = prc ? prc->readonly : 1; if(prc && prc->quit_to_edit){ quit_to_edit_msg(prc); return; } } if(!any_patterns(rflags, &pstate)) return; if(rflags & ROLE_DO_ROLES) v = &ps_global->vars[V_PAT_ROLES]; else if(rflags & ROLE_DO_INCOLS) v = &ps_global->vars[V_PAT_INCOLS]; else if(rflags & ROLE_DO_OTHER) v = &ps_global->vars[V_PAT_OTHER]; else if(rflags & ROLE_DO_SCORES) v = &ps_global->vars[V_PAT_SCORES]; else if(rflags & ROLE_DO_FILTER) v = &ps_global->vars[V_PAT_FILTS]; else if(rflags & ROLE_DO_SRCH) v = &ps_global->vars[V_PAT_SRCH]; if((ps_global->ew_for_except_vars != Main) && (ew == Main)){ char **lval; if((lval=LVAL(v, ps_global->ew_for_except_vars)) && lval[0] && strcmp(INHERIT, lval[0]) != 0){ role_type_print(title, sizeof(title), _("Warning: \"%sRules\" are overridden in your exceptions configuration"), rflags); q_status_message(SM_ORDER, 7, 7, title); } } role_type_print(title, sizeof(title), "%sRules", rflags); if(fixed_var(v, "change", title)) return; uh_oh: first_line = NULL; snprintf(title, sizeof(title), "SETUP%s ", edit_exceptions ? " EXCEPTIONAL" : ""); title[sizeof(title)-1] = '\0'; role_type_print(title+strlen(title), sizeof(title)-strlen(title), "%sRULES", rflags); role_global_flags = rflags; role_global_pstate = &pstate; role_config_init_disp(ps, &first_line, rflags, &pstate); if(!first_line){ role_global_flags = 0; ps->mangled_screen = 1; q_status_message(SM_ORDER,5,5, _("Unexpected problem: config file modified externally?")); q_status_message1(SM_ORDER,5,5, _("Perhaps a newer version of pine was used to set variable \"%s\"?"), v ? v->name : "?"); dprint((1, "Unexpected problem: config file modified externally?\nPerhaps by a newer pine? Variable \"%s\" has unexpected contents.\n", (v && v->name) ? v->name : "?")); return; } memset(&screen, 0, sizeof(screen)); screen.deferred_ro_warning = readonly_warning; /* TRANSLATORS: Print something1 using something2. "rules" is something1 */ switch(conf_scroll_screen(ps, &screen, first_line, title, _("rules"), 0, NULL)){ case 0: break; case 10: /* flush changes and re-read orig */ close_patterns(rflags); break; case 1: if(write_patterns(rflags)) goto uh_oh; /* * Flush out current_vals of anything we've possibly changed. */ if(ps_global->default_role){ q_status_message(SM_ORDER,0,3, "Default role is unset"); ps_global->default_role = NULL; } close_patterns((rflags & ROLE_MASK) | PAT_USE_CURRENT); /* scores may have changed */ if(rflags & ROLE_DO_SCORES){ int i; MAILSTREAM *m; for(i = 0; i < ps_global->s_pool.nstream; i++){ m = ps_global->s_pool.streams[i]; if(m){ clear_folder_scores(m); clear_index_cache(m, 0); } } if(mn_get_sort(sp_msgmap(ps_global->mail_stream)) == SortScore) refresh_sort(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), SRT_VRB); } /* recalculate need for scores */ scores_are_used(SCOREUSE_INVALID); /* we may want to fetch more or fewer headers each fetch */ calc_extra_hdrs(); if(get_extra_hdrs()) (void) mail_parameters(NULL, SET_IMAPEXTRAHEADERS, (void *) get_extra_hdrs()); if(rflags & ROLE_DO_INCOLS && pico_usingcolor()) clear_index_cache(ps_global->mail_stream, 0); if(rflags & ROLE_DO_FILTER) role_process_filters(); /* * ROLE_DO_OTHER is made up of a bunch of different variables * that may have changed. Assume they all changed and fix them. */ if(rflags & ROLE_DO_OTHER){ reset_index_format(); clear_index_cache(ps_global->mail_stream, 0); if(!mn_get_mansort(ps_global->msgmap)) reset_sort_order(SRT_VRB); } break; default: q_status_message(SM_ORDER,7,10, "conf_scroll_screen unexpected ret"); break; } role_global_flags = 0; ps->mangled_screen = 1; } /* * This is called from process_cmd to add a new pattern to the end of the * list of patterns. The pattern is seeded with values from the current * message. */ void role_take(struct pine *ps, MSGNO_S *msgmap, int rtype) { PAT_S *defpat, *newpat = NULL; PAT_LINE_S *new_patline, *patline; ENVELOPE *env = NULL; long rflags; char *s, title[100], specific_fldr[MAXPATH+1]; PAT_STATE pstate; EditWhich ew; dprint((4, "role_take()\n")); if(mn_get_cur(msgmap) > 0){ env = pine_mail_fetchstructure(ps->mail_stream, mn_m2raw(msgmap, mn_get_cur(msgmap)), NULL); if(!env){ q_status_message(SM_ORDER, 3, 7, _("problem getting addresses from message")); return; } } switch(rtype){ case 'r': rflags = ROLE_DO_ROLES; ew = ps_global->ew_for_role_take; break; case 's': rflags = ROLE_DO_SCORES; ew = ps_global->ew_for_score_take; break; case 'i': rflags = ROLE_DO_INCOLS; ew = ps_global->ew_for_incol_take; break; case 'f': rflags = ROLE_DO_FILTER; ew = ps_global->ew_for_filter_take; break; case 'o': rflags = ROLE_DO_OTHER; ew = ps_global->ew_for_other_take; break; case 'c': rflags = ROLE_DO_SRCH; ew = ps_global->ew_for_srch_take; break; default: cmd_cancelled(NULL); return; } switch(ew){ case Main: rflags |= PAT_USE_MAIN; break; case Post: rflags |= PAT_USE_POST; break; default: break; } if(!any_patterns(rflags, &pstate)){ q_status_message(SM_ORDER, 3, 7, _("problem accessing rules")); return; } /* set this so that even if we don't edit at all, we'll be asked */ rflags |= ROLE_CHANGES; /* * Make a pattern out of the information in the envelope and * use that as the default pattern we give to the role editor. * It will have a pattern but no actions set. */ defpat = (PAT_S *)fs_get(sizeof(*defpat)); memset((void *)defpat, 0, sizeof(*defpat)); defpat->patgrp = (PATGRP_S *)fs_get(sizeof(*defpat->patgrp)); memset((void *)defpat->patgrp, 0, sizeof(*defpat->patgrp)); if(env){ if(env->to) defpat->patgrp->to = addrlst_to_pattern(env->to); if(env->from) defpat->patgrp->from = addrlst_to_pattern(env->from); if(env->cc) defpat->patgrp->cc = addrlst_to_pattern(env->cc); if(env->sender && (!env->from || !address_is_same(env->sender, env->from))) defpat->patgrp->sender = addrlst_to_pattern(env->sender); /* * Env->newsgroups is already comma-separated and there shouldn't be * any commas or backslashes in newsgroup names, so we don't add the * roletake escapes. */ if(env->newsgroups) defpat->patgrp->news = string_to_pattern(env->newsgroups); /* * Subject may have commas or backslashes, so we add escapes. */ if(env->subject){ char *q, *t = NULL; /* * Mail_strip_subject not only strips the Re's and Fwd's but * it also canonicalizes to UTF-8. */ mail_strip_subject(env->subject, &q); if(q != NULL){ t = add_roletake_escapes(q); fs_give((void **)&q); } if(t){ defpat->patgrp->subj = string_to_pattern(t); fs_give((void **)&t); } } } if(IS_NEWS(ps->mail_stream)) defpat->patgrp->fldr_type = FLDR_NEWS; else defpat->patgrp->fldr_type = FLDR_EMAIL; specific_fldr[0] = specific_fldr[sizeof(specific_fldr)-1] = '\0'; if(sp_flagged(ps->mail_stream, SP_INBOX)) strncpy(specific_fldr, ps_global->inbox_name, sizeof(specific_fldr)-1); else if(ps->context_current && ps->context_current->use & CNTXT_INCMNG && folder_is_nick(ps->cur_folder, FOLDERS(ps->context_current), 0)) strncpy(specific_fldr, ps->cur_folder, sizeof(specific_fldr)-1); else context_apply(specific_fldr, ps->context_current, ps->cur_folder, sizeof(specific_fldr)); if(specific_fldr[0]){ s = add_comma_escapes(specific_fldr); if(s){ if(rtype == 'f') defpat->patgrp->fldr_type = FLDR_SPECIFIC; defpat->patgrp->folder = string_to_pattern(s); fs_give((void **)&s); } } role_type_print(title, sizeof(title), "ADD NEW %sRULE", rflags); /* * Role_config_edit_screen is sometimes called as a tool or a sub * routine called from a tool within conf_scroll_screen, but here it * is going to be at the top-level (we're not inside conf_scroll_screen * right now). It uses opt_screen to set the ro_warning bit. We need * to let it know that we're at the top, which we do by setting * opt_screen to NULL. Otherwise, the thing that opt_screen is pointing * to is just random stack stuff from some previous conf_scroll_screen * call which has already exited. */ opt_screen = NULL; if(role_config_edit_screen(ps, defpat, title, rflags, &newpat) == 1 && newpat){ if(ps->never_allow_changing_from && newpat->action && newpat->action->from) q_status_message(SM_ORDER|SM_DING, 3, 7, _("Site policy doesn't allow changing From address so From is ignored")); if(rflags & ROLE_DO_ROLES && newpat->patgrp && newpat->patgrp->nick){ PAT_S *pat; for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ if(pat->patgrp && pat->patgrp->nick && !strucmp(pat->patgrp->nick, newpat->patgrp->nick)){ q_status_message(SM_ORDER|SM_DING, 3, 7, _("Warning: The nickname of the new role is already in use.")); break; } } } set_pathandle(rflags); /* need a new patline */ new_patline = (PAT_LINE_S *)fs_get(sizeof(*new_patline)); memset((void *)new_patline, 0, sizeof(*new_patline)); new_patline->type = Literal; (*cur_pat_h)->dirtypinerc = 1; /* tie together with new pattern */ new_patline->first = new_patline->last = newpat; newpat->patline = new_patline; /* find last current patline */ for(patline = (*cur_pat_h)->patlinehead; patline && patline->next; patline = patline->next) ; /* add new patline to end of list */ if(patline){ patline->next = new_patline; new_patline->prev = patline; } else (*cur_pat_h)->patlinehead = new_patline; if(write_patterns(rflags) == 0){ char msg[60]; /* * Flush out current_vals of anything we've possibly changed. */ if(rflags & ROLE_DO_ROLES && ps_global->default_role){ q_status_message(SM_ORDER,0,3, "Default role is unset"); ps_global->default_role = NULL; } close_patterns(rflags | PAT_USE_CURRENT); role_type_print(msg, sizeof(msg), "New %srule saved", rflags); q_status_message(SM_ORDER, 0, 3, msg); /* scores may have changed */ if(rflags & ROLE_DO_SCORES){ int i; MAILSTREAM *m; for(i = 0; i < ps_global->s_pool.nstream; i++){ m = ps_global->s_pool.streams[i]; if(m){ clear_folder_scores(m); clear_index_cache(m, 0); } } /* We've already bound msgmap to global mail_stream * at the start of this function, but if we wanted to * we could clean this up. */ if(mn_get_sort(msgmap) == SortScore) refresh_sort(ps_global->mail_stream, msgmap, SRT_VRB); } if(rflags & ROLE_DO_FILTER) role_process_filters(); /* recalculate need for scores */ scores_are_used(SCOREUSE_INVALID); /* we may want to fetch more or fewer headers each fetch */ calc_extra_hdrs(); if(get_extra_hdrs()) (void) mail_parameters(NULL, SET_IMAPEXTRAHEADERS, (void *) get_extra_hdrs()); if(rflags & ROLE_DO_INCOLS && pico_usingcolor()) clear_index_cache(ps_global->mail_stream, 0); /* * ROLE_DO_OTHER is made up of a bunch of different variables * that may have changed. Assume they all changed and fix them. */ if(rflags & ROLE_DO_OTHER){ reset_index_format(); clear_index_cache(ps_global->mail_stream, 0); if(!mn_get_mansort(msgmap)) reset_sort_order(SRT_VRB); } } } else cmd_cancelled(NULL); free_pat(&defpat); ps->mangled_screen = 1; } PATTERN_S * addrlst_to_pattern(struct mail_address *addr) { char *s, *t, *u, *v; PATTERN_S *p = NULL; size_t l; if(addr){ l = est_size(addr); t = s = (char *) fs_get((l+1) * sizeof(char)); s[0] = '\0'; while(addr){ u = simple_addr_string(addr, tmp_20k_buf, SIZEOF_20KBUF); v = add_roletake_escapes(u); if(v){ if(*v && t != s) sstrncpy(&t, ",", l-(t-s)); sstrncpy(&t, v, l-(t-s)); fs_give((void **)&v); } addr = addr->next; } s[l] = '\0'; if(*s) p = string_to_pattern(s); fs_give((void **) &s); } return(p); } void role_config_init_disp(struct pine *ps, CONF_S **first_line, long int rflags, PAT_STATE *pstate) { PAT_LINE_S *patline; CONF_S *ctmp = NULL; int inherit = 0, added_fake = 0; if(first_line) *first_line = NULL; /* * Set cur_pat_h and manipulate directly. */ set_pathandle(rflags); patline = *cur_pat_h ? (*cur_pat_h)->patlinehead : NULL; if(patline && patline->type == Inherit){ add_patline_to_display(ps, &ctmp, 0, first_line, NULL, patline, rflags); patline = patline->next; } if(!patline){ add_fake_first_role(&ctmp, 0, rflags); added_fake++; if(first_line && !*first_line) (*first_line) = ctmp; } for(; patline; patline = patline->next) add_patline_to_display(ps, &ctmp, 0, first_line, NULL, patline, rflags); /* * If there are no actual patterns so far, we need to have an Add line * for the cursor to be on. This would happen if all of the patlines * were File includes and none of the files contained patterns. */ if(!first_pattern(role_global_pstate) || ((inherit=first_pattern(role_global_pstate)->inherit) && !next_pattern(role_global_pstate))){ /* * Find the start and prepend the fake first role. */ while(ctmp && ctmp->prev) ctmp = ctmp->prev; if(!added_fake){ add_fake_first_role(&ctmp, inherit ? 0 : 1, rflags); if(first_line && !*first_line) (*first_line) = ctmp; } } } void 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) { PAT_S *pat; int len, firstitem, wid; char *q; char buf[6*MAX_SCREEN_COLS+1]; /* put dashed line around file contents */ if(patline->type == File){ new_confline(ctmp); if(before){ /* * New_confline appends ctmp after old current instead of inserting * it, so we have to adjust. We have * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c -> */ CONF_S *a, *b, *c, *p; p = *ctmp; b = (*ctmp)->prev; c = (*ctmp)->next; a = b ? b->prev : NULL; if(a) a->next = p; if(b){ b->prev = p; b->next = c; } if(c) c->prev = b; p->prev = a; p->next = b; } if(top_line && *top_line == NULL) *top_line = (*ctmp); len = strlen(patline->filename) + 100; q = (char *) fs_get((len + 1) * sizeof(char)); snprintf(q, len+1, "From file %s%s", patline->filename, patline->readonly ? " (ReadOnly)" : ""); q[len-1] = '\0'; if((wid=utf8_width(q)) > ps->ttyo->screen_cols -2) utf8_snprintf(buf, sizeof(buf), "--%.*w", ps->ttyo->screen_cols -2, q); else snprintf(buf, sizeof(buf), "--%s%s", q, repeat_char(ps->ttyo->screen_cols -2-wid, '-')); (*ctmp)->value = cpystr(buf); fs_give((void **)&q); (*ctmp)->flags |= (CF_NOSELECT | CF_STARTITEM); (*ctmp)->d.r.patline = patline; firstitem = 0; } else firstitem = 1; for(pat = patline->first; pat; pat = pat->next){ /* Check that pattern has a role and is of right type */ if(pat->inherit || (pat->action && (((rflags & ROLE_DO_ROLES) && pat->action->is_a_role) || ((rflags & ROLE_DO_INCOLS) && pat->action->is_a_incol) || ((rflags & ROLE_DO_SRCH) && pat->action->is_a_srch) || ((rflags & ROLE_DO_OTHER) && pat->action->is_a_other) || ((rflags & ROLE_DO_SCORES) && pat->action->is_a_score) || ((rflags & ROLE_DO_FILTER) && pat->action->is_a_filter)))){ add_role_to_display(ctmp, patline, pat, 0, (first_line && *first_line == NULL) ? first_line : (top_line && *top_line == NULL) ? top_line : NULL, firstitem, rflags); firstitem = 1; if(top_line && *top_line == NULL && first_line) *top_line = *first_line; } } if(patline->type == File){ new_confline(ctmp); len = strlen(patline->filename) + 100; q = (char *) fs_get((len + 1) * sizeof(char)); snprintf(q, len+1, "End of Rules from %s", patline->filename); q[len-1] = '\0'; if((wid=utf8_width(q)) > ps->ttyo->screen_cols -2) utf8_snprintf(buf, sizeof(buf), "--%.*w", ps->ttyo->screen_cols -2, q); else snprintf(buf, sizeof(buf), "--%s%s", q, repeat_char(ps->ttyo->screen_cols -2-wid, '-')); (*ctmp)->value = cpystr(buf); fs_give((void **)&q); (*ctmp)->flags |= CF_NOSELECT; (*ctmp)->d.r.patline = patline; } } void 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) { char title[80]; if(!(pat && (pat->action || pat->inherit))) return; new_confline(ctmp); if(first_line && !pat->inherit) *first_line = *ctmp; if(before){ /* * New_confline appends ctmp after old current instead of inserting * it, so we have to adjust. We have * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c -> */ CONF_S *a, *b, *c, *p; p = *ctmp; b = (*ctmp)->prev; c = (*ctmp)->next; a = b ? b->prev : NULL; if(a) a->next = p; if(b){ b->prev = p; b->next = c; } if(c) c->prev = b; p->prev = a; p->next = b; } role_type_print(title, sizeof(title), _("HELP FOR %sRULE CONFIGURATION"), rflags); if(pat->inherit){ (*ctmp)->flags |= ((firstitem ? CF_STARTITEM : 0) | CF_NOSELECT | CF_INHERIT); } else{ (*ctmp)->flags |= (firstitem ? CF_STARTITEM : 0); (*ctmp)->value = cpystr((pat && pat->patgrp && pat->patgrp->nick) ? pat->patgrp->nick : "?"); } (*ctmp)->d.r.patline = patline; (*ctmp)->d.r.pat = pat; (*ctmp)->keymenu = &role_conf_km; (*ctmp)->help = (rflags & ROLE_DO_INCOLS) ? h_rules_incols : (rflags & ROLE_DO_OTHER) ? h_rules_other : (rflags & ROLE_DO_FILTER) ? h_rules_filter : (rflags & ROLE_DO_SCORES) ? h_rules_score : (rflags & ROLE_DO_ROLES) ? h_rules_roles : (rflags & ROLE_DO_SRCH) ? h_rules_srch : NO_HELP; (*ctmp)->help_title = title; (*ctmp)->tool = role_config_tool; (*ctmp)->valoffset = 4; } void add_fake_first_role(CONF_S **ctmp, int before, long int rflags) { char title[80]; char add[80]; new_confline(ctmp); if(before){ /* * New_confline appends ctmp after old current instead of inserting * it, so we have to adjust. We have * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c -> */ CONF_S *a, *b, *c, *p; p = *ctmp; b = (*ctmp)->prev; c = (*ctmp)->next; a = b ? b->prev : NULL; if(a) a->next = p; if(b){ b->prev = p; b->next = c; } if(c) c->prev = b; p->prev = a; p->next = b; } role_type_print(title, sizeof(title), _("HELP FOR %sRULE CONFIGURATION"), rflags); role_type_print(add, sizeof(add), _("Use Add to add a %sRule"), rflags); (*ctmp)->value = cpystr(add); (*ctmp)->keymenu = &role_conf_km; (*ctmp)->help = (rflags & ROLE_DO_INCOLS) ? h_rules_incols : (rflags & ROLE_DO_OTHER) ? h_rules_other : (rflags & ROLE_DO_FILTER) ? h_rules_filter : (rflags & ROLE_DO_SCORES) ? h_rules_score : (rflags & ROLE_DO_ROLES) ? h_rules_roles : (rflags & ROLE_DO_SRCH) ? h_rules_srch : NO_HELP; (*ctmp)->help_title = title; (*ctmp)->tool = role_config_tool; (*ctmp)->flags |= CF_STARTITEM; (*ctmp)->valoffset = 4; } int role_config_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int first_one = 0, rv = 0; char exitpmt[80]; PAT_S *pat; if(!(pat = first_pattern(role_global_pstate)) || (pat->inherit && !next_pattern(role_global_pstate))) first_one++; switch(cmd){ case MC_DELETE : if(first_one) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Nothing to Delete, use Add")); else rv = role_config_del(ps, cl, role_global_flags); break; case MC_ADD : rv = role_config_add(ps, cl, role_global_flags); break; case MC_EDIT : if(first_one) rv = role_config_add(ps, cl, role_global_flags); else rv = role_config_edit(ps, cl, role_global_flags); break; case MC_SHUFFLE : if(first_one) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Nothing to Shuffle, use Add")); else rv = role_config_shuffle(ps, cl); break; case MC_EXIT : role_type_print(exitpmt, sizeof(exitpmt), "%sRule Setup", role_global_flags); rv = screen_exit_cmd(flags, exitpmt); break; case MC_ADDFILE : rv = role_config_addfile(ps, cl, role_global_flags); break; case MC_DELFILE : rv = role_config_delfile(ps, cl, role_global_flags); break; case MC_COPY : if(first_one) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Nothing to Replicate, use Add")); else rv = role_config_replicate(ps, cl, role_global_flags); break; default: rv = -1; break; } return(rv); } /* * Add a new role. * * Returns 1 -- There were changes * 0 -- No changes */ int role_config_add(struct pine *ps, CONF_S **cl, long int rflags) { int rv = 0, first_pat = 0; PAT_S *new_pat = NULL, *cur_pat; PAT_LINE_S *new_patline = NULL, *cur_patline; PAT_STATE pstate; char title[80]; if((*cl)->d.r.patline && (*cl)->d.r.patline->readonly && (*cl)->d.r.patline->type == File){ q_status_message(SM_ORDER, 0, 3, _("Can't add rule to ReadOnly file")); return(rv); } role_type_print(title, sizeof(title), "ADD A %sRULE", rflags); if(role_config_edit_screen(ps, NULL, title, rflags, &new_pat) == 1 && new_pat){ if(ps->never_allow_changing_from && new_pat->action && new_pat->action->from) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Site policy doesn't allow changing From address so From is ignored")); if(rflags & ROLE_DO_ROLES && new_pat->patgrp && new_pat->patgrp->nick && nonempty_patterns(ROLE_DO_ROLES, &pstate)){ PAT_S *pat; for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ if(pat->patgrp && pat->patgrp->nick && !strucmp(pat->patgrp->nick, new_pat->patgrp->nick)){ q_status_message(SM_ORDER|SM_DING, 3, 7, _("Warning: The nickname of the new role is already in use.")); break; } } } rv = 1; cur_pat = (*cl)->d.r.pat; if(!cur_pat) first_pat++; set_pathandle(rflags); cur_patline = first_pat ? (*cur_pat_h)->patlinehead : cur_pat->patline; /* need a new pat_line */ if(first_pat || (cur_patline && cur_patline->type == Literal)){ new_patline = (PAT_LINE_S *)fs_get(sizeof(*new_patline)); memset((void *)new_patline, 0, sizeof(*new_patline)); new_patline->type = Literal; (*cur_pat_h)->dirtypinerc = 1; } if(cur_patline){ if(first_pat || cur_patline->type == Literal){ new_patline->prev = cur_patline; new_patline->next = cur_patline->next; if(cur_patline->next) cur_patline->next->prev = new_patline; cur_patline->next = new_patline; /* tie new patline and new pat together */ new_pat->patline = new_patline; new_patline->first = new_patline->last = new_pat; } else if(cur_patline->type == File){ /* don't need a new pat_line */ /* tie together */ new_pat->patline = cur_patline; cur_patline->dirty = 1; /* Splice new_pat after cur_pat */ new_pat->prev = cur_pat; new_pat->next = cur_pat->next; if(cur_pat->next) cur_pat->next->prev = new_pat; else cur_patline->last = new_pat; cur_pat->next = new_pat; } } else{ /* tie new first patline and pat together */ new_pat->patline = new_patline; new_patline->first = new_patline->last = new_pat; /* set head of list */ (*cur_pat_h)->patlinehead = new_patline; } /* * If this is the first role, we replace the "Use Add" fake role * with this real one. */ if(first_pat){ /* Adjust conf_scroll_screen variables */ (*cl)->d.r.pat = new_pat; (*cl)->d.r.patline = new_pat->patline; if((*cl)->value) fs_give((void **)&(*cl)->value); (*cl)->value = cpystr((new_pat && new_pat->patgrp && new_pat->patgrp->nick) ? new_pat->patgrp->nick : "?"); } /* Else we are inserting a new role after the cur role */ else add_role_to_display(cl, new_pat->patline, new_pat, 0, NULL, 1, rflags); } return(rv); } /* * Replicate a role. * * Returns 1 -- There were changes * 0 -- No changes */ int role_config_replicate(struct pine *ps, CONF_S **cl, long int rflags) { int rv = 0, first_pat = 0; PAT_S *new_pat = NULL, *cur_pat, *defpat = NULL; PAT_LINE_S *new_patline = NULL, *cur_patline; PAT_STATE pstate; char title[80]; if((*cl)->d.r.patline && (*cl)->d.r.patline->readonly && (*cl)->d.r.patline->type == File){ q_status_message(SM_ORDER, 0, 3, _("Can't add rule to ReadOnly file")); return(rv); } if((*cl)->d.r.pat && (defpat = copy_pat((*cl)->d.r.pat))){ /* change nickname */ if(defpat->patgrp && defpat->patgrp->nick){ #define CLONEWORD " Copy" char *oldnick = defpat->patgrp->nick; size_t len; len = strlen(oldnick)+strlen(CLONEWORD); defpat->patgrp->nick = (char *)fs_get((len+1) * sizeof(char)); strncpy(defpat->patgrp->nick, oldnick, len); defpat->patgrp->nick[len] = '\0'; strncat(defpat->patgrp->nick, CLONEWORD, len+1-1-strlen(defpat->patgrp->nick)); fs_give((void **)&oldnick); if(defpat->action){ if(defpat->action->nick) fs_give((void **)&defpat->action->nick); defpat->action->nick = cpystr(defpat->patgrp->nick); } } /* set this so that even if we don't edit at all, we'll be asked */ rflags |= ROLE_CHANGES; role_type_print(title, sizeof(title), "CHANGE THIS %sRULE", rflags); if(role_config_edit_screen(ps, defpat, title, rflags, &new_pat) == 1 && new_pat){ if(ps->never_allow_changing_from && new_pat->action && new_pat->action->from) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Site policy doesn't allow changing From address so From is ignored")); if(rflags & ROLE_DO_ROLES && new_pat->patgrp && new_pat->patgrp->nick && nonempty_patterns(ROLE_DO_ROLES, &pstate)){ PAT_S *pat; for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ if(pat->patgrp && pat->patgrp->nick && !strucmp(pat->patgrp->nick, new_pat->patgrp->nick)){ q_status_message(SM_ORDER|SM_DING, 3, 7, _("Warning: The nickname of the new role is already in use.")); break; } } } rv = 1; cur_pat = (*cl)->d.r.pat; if(!cur_pat) first_pat++; set_pathandle(rflags); cur_patline = first_pat ? (*cur_pat_h)->patlinehead : cur_pat->patline; /* need a new pat_line */ if(first_pat || (cur_patline && cur_patline->type == Literal)){ new_patline = (PAT_LINE_S *)fs_get(sizeof(*new_patline)); memset((void *)new_patline, 0, sizeof(*new_patline)); new_patline->type = Literal; (*cur_pat_h)->dirtypinerc = 1; } if(cur_patline){ if(first_pat || cur_patline->type == Literal){ new_patline->prev = cur_patline; new_patline->next = cur_patline->next; if(cur_patline->next) cur_patline->next->prev = new_patline; cur_patline->next = new_patline; /* tie new patline and new pat together */ new_pat->patline = new_patline; new_patline->first = new_patline->last = new_pat; } else if(cur_patline->type == File){ /* don't need a new pat_line */ /* tie together */ new_pat->patline = cur_patline; cur_patline->dirty = 1; /* Splice new_pat after cur_pat */ new_pat->prev = cur_pat; new_pat->next = cur_pat->next; if(cur_pat->next) cur_pat->next->prev = new_pat; else cur_patline->last = new_pat; cur_pat->next = new_pat; } } else{ /* tie new first patline and pat together */ new_pat->patline = new_patline; new_patline->first = new_patline->last = new_pat; /* set head of list */ (*cur_pat_h)->patlinehead = new_patline; } /* * If this is the first role, we replace the "Use Add" fake role * with this real one. */ if(first_pat){ /* Adjust conf_scroll_screen variables */ (*cl)->d.r.pat = new_pat; (*cl)->d.r.patline = new_pat->patline; if((*cl)->value) fs_give((void **)&(*cl)->value); (*cl)->value = cpystr((new_pat && new_pat->patgrp && new_pat->patgrp->nick) ? new_pat->patgrp->nick : "?"); } /* Else we are inserting a new role after the cur role */ else add_role_to_display(cl, new_pat->patline, new_pat, 0, NULL, 1, rflags); } } if(defpat) free_pat(&defpat); return(rv); } /* * Change the current role. * * Returns 1 -- There were changes * 0 -- No changes */ int role_config_edit(struct pine *ps, CONF_S **cl, long int rflags) { int rv = 0; PAT_S *new_pat = NULL, *cur_pat; char title[80]; if((*cl)->d.r.patline->readonly){ q_status_message(SM_ORDER, 0, 3, _("Can't change ReadOnly rule")); return(rv); } cur_pat = (*cl)->d.r.pat; role_type_print(title, sizeof(title), "CHANGE THIS %sRULE", rflags); if(role_config_edit_screen(ps, cur_pat, title, rflags, &new_pat) == 1 && new_pat){ if(ps->never_allow_changing_from && new_pat->action && new_pat->action->from) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Site policy doesn't allow changing From address so From is ignored")); if(rflags & ROLE_DO_ROLES && new_pat->patgrp && new_pat->patgrp->nick){ PAT_S *pat; for(pat = first_pattern(role_global_pstate); pat; pat = next_pattern(role_global_pstate)){ if(pat->patgrp && pat->patgrp->nick && pat != cur_pat && !strucmp(pat->patgrp->nick, new_pat->patgrp->nick)){ q_status_message(SM_ORDER|SM_DING, 3, 7, _("Warning: The nickname of this role is also used for another role.")); break; } } } rv = 1; /* * Splice in new_pat in place of cur_pat */ if(cur_pat->prev) cur_pat->prev->next = new_pat; if(cur_pat->next) cur_pat->next->prev = new_pat; new_pat->prev = cur_pat->prev; new_pat->next = cur_pat->next; /* tie together patline and pat (new_pat gets patline in editor) */ if(new_pat->patline->first == cur_pat) new_pat->patline->first = new_pat; if(new_pat->patline->last == cur_pat) new_pat->patline->last = new_pat; if(new_pat->patline->type == Literal){ set_pathandle(rflags); if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; } else new_pat->patline->dirty = 1; cur_pat->next = NULL; free_pat(&cur_pat); /* Adjust conf_scroll_screen variables */ (*cl)->d.r.pat = new_pat; (*cl)->d.r.patline = new_pat->patline; if((*cl)->value) fs_give((void **)&(*cl)->value); (*cl)->value = cpystr((new_pat->patgrp && new_pat->patgrp->nick) ? new_pat->patgrp->nick : "?"); } return(rv); } /* * Delete a role. * * Returns 1 -- There were changes * 0 -- No changes */ int role_config_del(struct pine *ps, CONF_S **cl, long int rflags) { int rv = 0; char msg[80]; char prompt[100]; if((*cl)->d.r.patline->readonly){ q_status_message(SM_ORDER, 0, 3, _("Can't delete ReadOnly rule")); return(rv); } role_type_print(msg, sizeof(msg), _("Really delete %srule"), rflags); snprintf(prompt, sizeof(prompt), "%s \"%s\" ", msg, (*cl)->value); prompt[sizeof(prompt)-1] = '\0'; ps->mangled_footer = 1; if(want_to(prompt,'n','n',h_config_role_del, WT_FLUSH_IN) == 'y'){ rv = ps->mangled_body = 1; delete_a_role(cl, rflags); } else q_status_message(SM_ORDER, 0, 3, _("Rule not deleted")); return(rv); } void delete_a_role(CONF_S **cl, long int rflags) { PAT_S *cur_pat; CONF_S *cp, *cq; PAT_LINE_S *cur_patline; int inherit = 0; cur_pat = (*cl)->d.r.pat; cur_patline = (*cl)->d.r.patline; if(cur_patline->type == Literal){ /* delete patline */ set_pathandle(rflags); if(cur_patline->prev) cur_patline->prev->next = cur_patline->next; else{ if(*cur_pat_h) /* this has to be true */ (*cur_pat_h)->patlinehead = cur_patline->next; } if(cur_patline->next) cur_patline->next->prev = cur_patline->prev; if(*cur_pat_h) /* this has to be true */ (*cur_pat_h)->dirtypinerc = 1; cur_patline->next = NULL; free_patline(&cur_patline); } else if(cur_patline->type == File){ /* or delete pat */ if(cur_pat->prev) cur_pat->prev->next = cur_pat->next; else cur_patline->first = cur_pat->next; if(cur_pat->next) cur_pat->next->prev = cur_pat->prev; else cur_patline->last = cur_pat->prev; cur_patline->dirty = 1; cur_pat->next = NULL; free_pat(&cur_pat); } /* delete the conf line */ /* deleting last real rule */ if(!first_pattern(role_global_pstate) || ((inherit=first_pattern(role_global_pstate)->inherit) && !next_pattern(role_global_pstate))){ cq = *cl; /* * Find the start and prepend the fake first role. */ while(*cl && (*cl)->prev) *cl = (*cl)->prev; add_fake_first_role(cl, inherit ? 0 : 1, rflags); snip_confline(&cq); opt_screen->top_line = (*cl); opt_screen->current = (*cl); } else{ /* find next selectable line */ for(cp = (*cl)->next; cp && (cp->flags & CF_NOSELECT); cp = cp->next) ; if(!cp){ /* no next selectable, find previous selectable */ if(*cl == opt_screen->top_line) opt_screen->top_line = (*cl)->prev; for(cp = (*cl)->prev; cp && (cp->flags & CF_NOSELECT); cp = cp->prev) ; } else if(*cl == opt_screen->top_line) opt_screen->top_line = (*cl)->next; cq = *cl; *cl = cp; snip_confline(&cq); } } /* * Shuffle the current role up or down. * * Returns 1 -- There were changes * 0 -- No changes */ int role_config_shuffle(struct pine *ps, CONF_S **cl) { int rv = 0, deefault, i; int readonlyabove = 0, readonlybelow = 0; ESCKEY_S opts[5]; HelpType help; char tmp[200]; CONF_S *a, *b; PAT_TYPE curtype, prevtype, nexttype; if(!((*cl)->prev || (*cl)->next)){ q_status_message(SM_ORDER, 0, 3, _("Shuffle only makes sense when there is more than one rule defined")); return(rv); } /* Move it up or down? */ i = 0; opts[i].ch = 'u'; opts[i].rval = 'u'; opts[i].name = "U"; opts[i++].label = N_("Up"); opts[i].ch = 'd'; opts[i].rval = 'd'; opts[i].name = "D"; opts[i++].label = N_("Down"); opts[i].ch = 'b'; opts[i].rval = 'b'; opts[i].name = "B"; opts[i++].label = N_("Before File"); opts[i].ch = 'a'; opts[i].rval = 'a'; opts[i].name = "A"; opts[i++].label = N_("After File"); opts[i].ch = -1; deefault = 'u'; curtype = ((*cl)->d.r.patline) ? (*cl)->d.r.patline->type : TypeNotSet; prevtype = ((*cl)->prev && (*cl)->prev->d.r.patline) ? (*cl)->prev->d.r.patline->type : TypeNotSet; if(curtype == File && prevtype == File && (*cl)->prev->d.r.pat == NULL) prevtype = TypeNotSet; nexttype = ((*cl)->next && (*cl)->next->d.r.patline) ? (*cl)->next->d.r.patline->type : TypeNotSet; if(curtype == File && nexttype == File && (*cl)->next->d.r.pat == NULL) nexttype = TypeNotSet; if(curtype == Literal){ if(prevtype == TypeNotSet || prevtype == Inherit){ /* no up, at top */ opts[0].ch = -2; opts[2].ch = -2; deefault = 'd'; } else if(prevtype == Literal){ /* regular up */ opts[2].ch = -2; } else if(prevtype == File){ /* file above us */ if((*cl)->prev->d.r.patline->readonly) readonlyabove++; } if(nexttype == TypeNotSet){ /* no down, at bottom */ opts[1].ch = -2; opts[3].ch = -2; } else if(nexttype == Literal){ /* regular down */ opts[3].ch = -2; } else if(nexttype == File){ /* file below us */ if((*cl)->next->d.r.patline->readonly) readonlybelow++; } } else if(curtype == File){ if((*cl)->d.r.patline && (*cl)->d.r.patline->readonly){ q_status_message(SM_ORDER, 0, 3, _("Can't change ReadOnly file")); return(0); } opts[2].ch = -2; opts[3].ch = -2; } else{ q_status_message(SM_ORDER, 0, 3, "Programming Error: unknown line type in role_shuffle"); return(rv); } snprintf(tmp, sizeof(tmp), "Shuffle \"%s\" %s%s%s%s%s%s%s ? ", (*cl)->value, (opts[0].ch != -2) ? N_("UP") : "", (opts[0].ch != -2 && opts[1].ch != -2) ? " or " : "", (opts[1].ch != -2) ? N_("DOWN") : "", ((opts[0].ch != -2 || opts[1].ch != -2) && opts[2].ch != -2) ? " or " : "", (opts[2].ch != -2) ? N_("BEFORE") : "", ((opts[0].ch != -2 || opts[1].ch != -2 || opts[2].ch != -2) && opts[3].ch != -2) ? " or " : "", (opts[3].ch != -2) ? N_("AFTER") : ""); tmp[sizeof(tmp)-1] = '\0'; help = (opts[0].ch == -2) ? h_role_shuf_down : (opts[1].ch == -2) ? h_role_shuf_up : h_role_shuf; rv = radio_buttons(tmp, -FOOTER_ROWS(ps), opts, deefault, 'x', help, RB_NORM); if(rv == 'x'){ cmd_cancelled("Shuffle"); return(0); } if((readonlyabove && rv == 'u' && curtype != prevtype) || (readonlybelow && rv == 'd' && curtype != nexttype)){ q_status_message(SM_ORDER, 0, 3, _("Can't shuffle into ReadOnly file")); return(0); } if(rv == 'u' && curtype == Literal && prevtype == Literal){ rv = 1; a = (*cl)->prev; b = (*cl); if(a == opt_screen->top_line) opt_screen->top_line = b; swap_literal_roles(a, b); ps->mangled_body = 1; } else if(rv == 'd' && curtype == Literal && nexttype == Literal){ rv = 1; a = (*cl); b = (*cl)->next; if(a == opt_screen->top_line) opt_screen->top_line = b; swap_literal_roles(a, b); ps->mangled_body = 1; } else if(rv == 'u' && curtype == File && prevtype == File){ rv = 1; a = (*cl)->prev; b = (*cl); if(a == opt_screen->top_line) opt_screen->top_line = b; swap_file_roles(a, b); ps->mangled_body = 1; } else if(rv == 'u' && curtype == File){ rv = 1; move_role_outof_file(cl, 1); ps->mangled_body = 1; } else if(rv == 'd' && curtype == File && nexttype == File){ rv = 1; a = (*cl); b = (*cl)->next; if(a == opt_screen->top_line) opt_screen->top_line = b; swap_file_roles(a, b); ps->mangled_body = 1; } else if(rv == 'd' && curtype == File){ rv = 1; if(*cl == opt_screen->top_line) opt_screen->top_line = (*cl)->next; move_role_outof_file(cl, 0); ps->mangled_body = 1; } else if(rv == 'u' && curtype == Literal && prevtype == File){ rv = 1; move_role_into_file(cl, 1); ps->mangled_body = 1; } else if(rv == 'd' && curtype == Literal && nexttype == File){ rv = 1; if(*cl == opt_screen->top_line) opt_screen->top_line = (*cl)->next; move_role_into_file(cl, 0); ps->mangled_body = 1; } else if(rv == 'b'){ rv = 1; move_role_around_file(cl, 1); ps->mangled_body = 1; } else if(rv == 'a'){ rv = 1; if(*cl == opt_screen->top_line) opt_screen->top_line = (*cl)->next; move_role_around_file(cl, 0); ps->mangled_body = 1; } return(rv); } int role_config_addfile(struct pine *ps, CONF_S **cl, long int rflags) { char filename[MAXPATH+1], full_filename[MAXPATH+1]; char dir2[MAXPATH+1], pdir[MAXPATH+1]; char *lc, *newfile = NULL; PAT_LINE_S *file_patline; int rv = 0, len = 0; int r = 1, flags; HelpType help = NO_HELP; PAT_TYPE curtype; CONF_S *first_line = NULL, *add_line, *save_current; struct variable *vars = ps->vars; if(ps->restricted){ q_status_message(SM_ORDER, 0, 3, "Alpine demo can't read files"); return(rv); } curtype = ((*cl)->d.r.patline && (*cl)->d.r.patline) ? (*cl)->d.r.patline->type : TypeNotSet; if(curtype == File){ q_status_message(SM_ORDER, 0, 3, _("Current rule is already part of a file. Move outside any files first.")); return(rv); } /* * Parse_pattern_file uses signature_path to figure out where to look * for the file. In signature_path we read signature files relative * to the pinerc dir, so if user selects one that is in there we'll * use relative instead of absolute, so it looks nicer. */ pdir[0] = '\0'; if(VAR_OPER_DIR){ strncpy(pdir, VAR_OPER_DIR, sizeof(pdir)-1); pdir[sizeof(pdir)-1] = '\0'; len = strlen(pdir) + 1; } else if((lc = last_cmpnt(ps->pinerc)) != NULL){ strncpy(pdir, ps->pinerc, MIN(sizeof(pdir)-1,lc-ps->pinerc)); pdir[MIN(sizeof(pdir)-1, lc-ps->pinerc)] = '\0'; len = strlen(pdir); } strncpy(dir2, pdir, sizeof(dir2)-1); dir2[sizeof(dir2)-1] = '\0'; filename[0] = '\0'; full_filename[0] = '\0'; ps->mangled_footer = 1; while(1){ flags = OE_APPEND_CURRENT; r = optionally_enter(filename, -FOOTER_ROWS(ps), 0, sizeof(filename), "Name of file to be added to rules: ", NULL, help, &flags); if(r == 3){ help = (help == NO_HELP) ? h_config_role_addfile : NO_HELP; continue; } else if(r == 10 || r == 11){ /* Browser or File Completion */ continue; } else if(r == 1 || (r == 0 && filename[0] == '\0')){ cmd_cancelled("IncludeFile"); return(rv); } else if(r == 4){ continue; } else if(r != 0){ Writechar(BELL, 0); continue; } removing_leading_and_trailing_white_space(filename); if(is_absolute_path(filename)) newfile = cpystr(filename); else{ build_path(full_filename, dir2, filename, sizeof(full_filename)); removing_leading_and_trailing_white_space(full_filename); if(!strncmp(full_filename, pdir, strlen(pdir))) newfile = cpystr(full_filename + len); else newfile = cpystr(full_filename); } if(newfile && *newfile) break; } if(!newfile) return(rv); set_pathandle(rflags); if((file_patline = parse_pat_file(newfile)) != NULL){ /* * Insert the file after the current line. */ PAT_LINE_S *cur_patline; int first_pat; rv = ps->mangled_screen = 1; first_pat = !(*cl)->d.r.pat; cur_patline = (*cl)->d.r.patline ? (*cl)->d.r.patline : (*cur_pat_h) ? (*cur_pat_h)->patlinehead : NULL; if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; file_patline->dirty = 1; if(cur_patline){ file_patline->prev = cur_patline; file_patline->next = cur_patline->next; if(cur_patline->next) cur_patline->next->prev = file_patline; cur_patline->next = file_patline; } else{ /* set head of list */ if(*cur_pat_h) (*cur_pat_h)->patlinehead = file_patline; } if(first_pat){ if(file_patline->first){ /* get rid of Fake Add line */ add_line = *cl; opt_screen->top_line = NULL; add_patline_to_display(ps, cl, 0, &first_line, &opt_screen->top_line, file_patline, rflags); opt_screen->current = first_line; snip_confline(&add_line); } else{ /* we're _appending_ to the Fake Add line */ save_current = opt_screen->current; add_patline_to_display(ps, cl, 0, NULL, NULL, file_patline, rflags); opt_screen->current = save_current; } } else{ opt_screen->top_line = NULL; save_current = opt_screen->current; add_patline_to_display(ps, cl, 0, &first_line, &opt_screen->top_line, file_patline, rflags); if(first_line) opt_screen->current = first_line; else opt_screen->current = save_current; } } if(newfile) fs_give((void **)&newfile); return(rv); } int role_config_delfile(struct pine *ps, CONF_S **cl, long int rflags) { int rv = 0; PAT_LINE_S *cur_patline; char prompt[100]; if(!(cur_patline = (*cl)->d.r.patline)){ q_status_message(SM_ORDER, 0, 3, "Unknown problem in role_config_delfile"); return(rv); } if(cur_patline->type != File){ q_status_message(SM_ORDER, 0, 3, _("Current rule is not part of a file. Use Delete to remove current rule")); return(rv); } snprintf(prompt, sizeof(prompt), _("Really remove rule file \"%s\" from rules config "), cur_patline->filename); prompt[sizeof(prompt)-1] = '\0'; ps->mangled_footer = 1; if(want_to(prompt,'n','n',h_config_role_delfile, WT_FLUSH_IN) == 'y'){ CONF_S *ctmp, *cp; set_pathandle(rflags); rv = ps->mangled_screen = 1; if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; if(cur_patline->prev) cur_patline->prev->next = cur_patline->next; else{ if(*cur_pat_h) (*cur_pat_h)->patlinehead = cur_patline->next; } if(cur_patline->next) cur_patline->next->prev = cur_patline->prev; /* delete the conf lines */ /* find the first one associated with this file */ for(ctmp = *cl; ctmp && ctmp->prev && ctmp->prev->d.r.patline == cur_patline; ctmp = ctmp->prev) ; if(ctmp->prev) /* this file wasn't the first thing in config */ *cl = ctmp->prev; else{ /* this file was first in config */ for(cp = ctmp; cp && cp->next; cp = cp->next) ; if(cp->d.r.patline == cur_patline) *cl = NULL; else *cl = cp; } /* delete lines from the file */ while(ctmp && ctmp->d.r.patline == cur_patline){ cp = ctmp; ctmp = ctmp->next; snip_confline(&cp); } /* deleting last real rule */ if(!first_pattern(role_global_pstate)){ /* * Find the start and prepend the fake first role * in there. */ while(*cl && (*cl)->prev) *cl = (*cl)->prev; add_fake_first_role(cl, 1, rflags); } else if(first_pattern(role_global_pstate)->inherit && !next_pattern(role_global_pstate)){ while(*cl && (*cl)->prev) *cl = (*cl)->prev; /* append fake first after inherit */ add_fake_first_role(cl, 0, rflags); } opt_screen->top_line = first_confline(*cl); opt_screen->current = first_sel_confline(opt_screen->top_line); cur_patline->next = NULL; free_patline(&cur_patline); } else q_status_message(SM_ORDER, 0, 3, _("Rule file not removed")); return(rv); } /* * Swap from a, b to b, a. */ void swap_literal_roles(CONF_S *a, CONF_S *b) { PAT_LINE_S *patline_a, *patline_b; patline_a = a->d.r.patline; patline_b = b->d.r.patline; set_pathandle(role_global_flags); if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; /* first swap the patlines */ if(patline_a->next == patline_b){ patline_b->prev = patline_a->prev; if(patline_a->prev) patline_a->prev->next = patline_b; patline_a->next = patline_b->next; if(patline_b->next) patline_b->next->prev = patline_a; patline_b->next = patline_a; patline_a->prev = patline_b; } else{ PAT_LINE_S *new_a_prev, *new_a_next; new_a_prev = patline_b->prev; new_a_next = patline_b->next; patline_b->prev = patline_a->prev; patline_b->next = patline_a->next; if(patline_b->prev) patline_b->prev->next = patline_b; if(patline_b->next) patline_b->next->prev = patline_b; patline_a->prev = new_a_prev; patline_a->next = new_a_next; if(patline_a->prev) patline_a->prev->next = patline_a; if(patline_a->next) patline_a->next->prev = patline_a; } /* * If patline_b is now the first one in the list, we need to fix the * head of the list to point to this new role. */ if(patline_b->prev == NULL && *cur_pat_h) (*cur_pat_h)->patlinehead = patline_b; /* and then swap the conf lines */ b->prev = a->prev; if(a->prev) a->prev->next = b; a->next = b->next; if(b->next) b->next->prev = a; b->next = a; a->prev = b; } /* * Swap from a, b to b, a. */ void swap_file_roles(CONF_S *a, CONF_S *b) { PAT_S *pat_a, *pat_b; PAT_LINE_S *patline; pat_a = a->d.r.pat; pat_b = b->d.r.pat; patline = pat_a->patline; patline->dirty = 1; /* first swap the pats */ if(pat_a->next == pat_b){ pat_b->prev = pat_a->prev; if(pat_a->prev) pat_a->prev->next = pat_b; pat_a->next = pat_b->next; if(pat_b->next) pat_b->next->prev = pat_a; pat_b->next = pat_a; pat_a->prev = pat_b; } else{ PAT_S *new_a_prev, *new_a_next; new_a_prev = pat_b->prev; new_a_next = pat_b->next; pat_b->prev = pat_a->prev; pat_b->next = pat_a->next; if(pat_b->prev) pat_b->prev->next = pat_b; if(pat_b->next) pat_b->next->prev = pat_b; pat_a->prev = new_a_prev; pat_a->next = new_a_next; if(pat_a->prev) pat_a->prev->next = pat_a; if(pat_a->next) pat_a->next->prev = pat_a; } /* * Fix the first and last pointers. */ if(patline->first == pat_a) patline->first = pat_b; if(patline->last == pat_b) patline->last = pat_a; /* and then swap the conf lines */ b->prev = a->prev; if(a->prev) a->prev->next = b; a->next = b->next; if(b->next) b->next->prev = a; b->next = a; a->prev = b; } /* */ void move_role_into_file(CONF_S **cl, int up) { PAT_LINE_S *cur_patline, *file_patline; PAT_S *pat; CONF_S *a, *b; cur_patline = (*cl)->d.r.patline; if(up){ file_patline = (*cl)->prev->d.r.patline; a = (*cl)->prev; b = (*cl); b->d.r.patline = file_patline; } else{ file_patline = (*cl)->next->d.r.patline; a = (*cl); b = (*cl)->next; a->d.r.patline = file_patline; } set_pathandle(role_global_flags); if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; file_patline->dirty = 1; pat = cur_patline->first; if(!up && *cur_pat_h && cur_patline == (*cur_pat_h)->patlinehead) (*cur_pat_h)->patlinehead = (*cur_pat_h)->patlinehead->next; if(file_patline->first){ if(up){ file_patline->last->next = pat; pat->prev = file_patline->last; file_patline->last = pat; } else{ file_patline->first->prev = pat; pat->next = file_patline->first; file_patline->first = pat; } } else /* will be only role in file */ file_patline->first = file_patline->last = pat; pat->patline = file_patline; /* delete the now unused cur_patline */ cur_patline->first = cur_patline->last = NULL; if(cur_patline->prev) cur_patline->prev->next = cur_patline->next; if(cur_patline->next) cur_patline->next->prev = cur_patline->prev; cur_patline->next = NULL; free_patline(&cur_patline); /* and then swap the conf lines */ b->prev = a->prev; if(a->prev) a->prev->next = b; a->next = b->next; if(b->next) b->next->prev = a; b->next = a; a->prev = b; } /* */ void move_role_outof_file(CONF_S **cl, int up) { PAT_LINE_S *file_patline, *new_patline; PAT_S *pat; CONF_S *a, *b; new_patline = (PAT_LINE_S *)fs_get(sizeof(*new_patline)); memset((void *)new_patline, 0, sizeof(*new_patline)); new_patline->type = Literal; file_patline = (*cl)->d.r.patline; pat = (*cl)->d.r.pat; if(up){ a = (*cl)->prev; b = (*cl); if(pat->prev) pat->prev->next = pat->next; else file_patline->first = pat->next; if(pat->next) pat->next->prev = pat->prev; else file_patline->last = pat->prev; if(file_patline->first) file_patline->first->prev = NULL; if(file_patline->last) file_patline->last->next = NULL; if(file_patline->prev) file_patline->prev->next = new_patline; new_patline->prev = file_patline->prev; new_patline->next = file_patline; file_patline->prev = new_patline; b->d.r.patline = new_patline; } else{ a = (*cl); b = (*cl)->next; if(pat->prev) pat->prev->next = pat->next; else file_patline->first = pat->next; if(pat->next) pat->next->prev = pat->prev; else file_patline->last = pat->prev; if(file_patline->first) file_patline->first->prev = NULL; if(file_patline->last) file_patline->last->next = NULL; if(file_patline->next) file_patline->next->prev = new_patline; new_patline->next = file_patline->next; new_patline->prev = file_patline; file_patline->next = new_patline; a->d.r.patline = new_patline; } set_pathandle(role_global_flags); if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; file_patline->dirty = 1; new_patline->first = new_patline->last = pat; pat->patline = new_patline; pat->prev = pat->next = NULL; if(up && *cur_pat_h && file_patline == (*cur_pat_h)->patlinehead) (*cur_pat_h)->patlinehead = new_patline; /* and then swap the conf lines */ b->prev = a->prev; if(a->prev) a->prev->next = b; a->next = b->next; if(b->next) b->next->prev = a; b->next = a; a->prev = b; } /* * This is a move of a literal role from before a file to after a file, * or vice versa. */ void move_role_around_file(CONF_S **cl, int up) { PAT_LINE_S *file_patline, *lit_patline; CONF_S *cp; set_pathandle(role_global_flags); lit_patline = (*cl)->d.r.patline; if(up) file_patline = (*cl)->prev->d.r.patline; else{ if(*cur_pat_h && lit_patline == (*cur_pat_h)->patlinehead) (*cur_pat_h)->patlinehead = (*cur_pat_h)->patlinehead->next; file_patline = (*cl)->next->d.r.patline; } if(*cur_pat_h) (*cur_pat_h)->dirtypinerc = 1; /* remove the lit_patline from the list */ if(lit_patline->prev) lit_patline->prev->next = lit_patline->next; if(lit_patline->next) lit_patline->next->prev = lit_patline->prev; /* and reinsert it on the other side of the file */ if(up){ if(*cur_pat_h && file_patline == (*cur_pat_h)->patlinehead) (*cur_pat_h)->patlinehead = lit_patline; lit_patline->prev = file_patline->prev; lit_patline->next = file_patline; if(file_patline->prev) file_patline->prev->next = lit_patline; file_patline->prev = lit_patline; } else{ lit_patline->next = file_patline->next; lit_patline->prev = file_patline; if(file_patline->next) file_patline->next->prev = lit_patline; file_patline->next = lit_patline; } /* * And then move the conf line around the file conf lines. */ /* find it's new home */ if(up) for(cp = (*cl); cp && cp->prev && cp->prev->d.r.patline == file_patline; cp = prev_confline(cp)) ; else for(cp = (*cl); cp && cp->next && cp->next->d.r.patline == file_patline; cp = next_confline(cp)) ; /* remove it from where it is */ if((*cl)->prev) (*cl)->prev->next = (*cl)->next; if((*cl)->next) (*cl)->next->prev = (*cl)->prev; /* cp points to top or bottom of the file lines */ if(up){ (*cl)->prev = cp->prev; if(cp->prev) cp->prev->next = (*cl); cp->prev = (*cl); (*cl)->next = cp; } else{ (*cl)->next = cp->next; if(cp->next) cp->next->prev = (*cl); cp->next = (*cl); (*cl)->prev = cp; } } #define SETUP_PAT_STATUS(ctmp,svar,val,htitle,hval) \ {char tmp[MAXPATH+1]; \ int i, j, lv; \ NAMEVAL_S *f; \ \ /* Blank line */ \ new_confline(&ctmp); \ ctmp->flags |= CF_NOSELECT | CF_B_LINE; \ \ new_confline(&ctmp); \ ctmp->var = &svar; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = NO_HELP; \ ctmp->tool = NULL; \ snprintf(tmp, sizeof(tmp), "%-s =", svar.name); \ tmp[sizeof(tmp)-1] = '\0'; \ ctmp->varname = cpystr(tmp); \ ctmp->varnamep = ctmpb = ctmp; \ ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); \ \ new_confline(&ctmp); \ ctmp->var = NULL; \ ctmp->valoffset = rindent; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = NO_HELP; \ ctmp->tool = NULL; \ ctmp->varnamep = ctmpb; \ ctmp->flags |= CF_NOSELECT; \ ctmp->value = cpystr("Set Choose One"); \ \ new_confline(&ctmp); \ ctmp->var = NULL; \ ctmp->valoffset = rindent; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = NO_HELP; \ ctmp->tool = radio_tool; \ ctmp->varnamep = ctmpb; \ ctmp->flags |= CF_NOSELECT; \ ctmp->value = cpystr(set_choose); \ \ /* find longest value's name */ \ for(lv = 0, i = 0; (f = role_status_types(i)); i++) \ if(lv < (j = utf8_width(f->name))) \ lv = j; \ \ lv = MIN(lv, 100); \ \ for(i = 0; (f = role_status_types(i)); i++){ \ new_confline(&ctmp); \ ctmp->help_title= htitle; \ ctmp->var = &svar; \ ctmp->valoffset = rindent; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = hval; \ ctmp->varmem = i; \ ctmp->tool = radio_tool; \ ctmp->varnamep = ctmpb; \ utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!(def && def->patgrp) || \ val == -1) && \ f->value == PAT_STAT_EITHER) || \ (def && def->patgrp && \ f->value == val)) \ ? R_SELD : ' ', \ lv, lv, f->name); \ tmp[sizeof(tmp)-1] = '\0'; \ ctmp->value = cpystr(tmp); \ } \ } #define SETUP_MSG_STATE(ctmp,svar,val,htitle,hval) \ {char tmp[MAXPATH+1]; \ int i, j, lv; \ NAMEVAL_S *f; \ \ /* Blank line */ \ new_confline(&ctmp); \ ctmp->flags |= CF_NOSELECT | CF_B_LINE; \ \ new_confline(&ctmp); \ ctmp->var = &svar; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = NO_HELP; \ ctmp->tool = NULL; \ snprintf(tmp, sizeof(tmp), "%-s =", svar.name); \ tmp[sizeof(tmp)-1] = '\0'; \ ctmp->varname = cpystr(tmp); \ ctmp->varnamep = ctmpb = ctmp; \ ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); \ \ new_confline(&ctmp); \ ctmp->var = NULL; \ ctmp->valoffset = rindent; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = NO_HELP; \ ctmp->tool = NULL; \ ctmp->varnamep = ctmpb; \ ctmp->flags |= CF_NOSELECT; \ ctmp->value = cpystr("Set Choose One"); \ \ new_confline(&ctmp); \ ctmp->var = NULL; \ ctmp->valoffset = rindent; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = NO_HELP; \ ctmp->tool = radio_tool; \ ctmp->varnamep = ctmpb; \ ctmp->flags |= CF_NOSELECT; \ ctmp->value = cpystr(set_choose); \ \ /* find longest value's name */ \ for(lv = 0, i = 0; (f = msg_state_types(i)); i++) \ if(lv < (j = utf8_width(f->name))) \ lv = j; \ \ lv = MIN(lv, 100); \ \ for(i = 0; (f = msg_state_types(i)); i++){ \ new_confline(&ctmp); \ ctmp->help_title= htitle; \ ctmp->var = &svar; \ ctmp->valoffset = rindent; \ ctmp->keymenu = &config_radiobutton_keymenu; \ ctmp->help = hval; \ ctmp->varmem = i; \ ctmp->tool = radio_tool; \ ctmp->varnamep = ctmpb; \ utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (f->value == val) \ ? R_SELD : ' ', \ lv, lv, f->name); \ tmp[sizeof(tmp)-1] = '\0'; \ ctmp->value = cpystr(tmp); \ } \ } #define FEAT_SENTDATE 0 #define FEAT_IFNOTDEL 1 #define FEAT_NONTERM 2 bitmap_t feat_option_list; #define INABOOK_FROM 0 #define INABOOK_REPLYTO 1 #define INABOOK_SENDER 2 #define INABOOK_TO 3 #define INABOOK_CC 4 bitmap_t inabook_type_list; #define INICK_INICK_CONF 0 #define INICK_FROM_CONF 1 #define INICK_REPLYTO_CONF 2 #define INICK_FCC_CONF 3 #define INICK_LITSIG_CONF 4 /* this needs to come before SIG_CONF */ #define INICK_SIG_CONF 5 #define INICK_TEMPL_CONF 6 #define INICK_CSTM_CONF 7 #define INICK_SMTP_CONF 8 #define INICK_NNTP_CONF 9 CONF_S *inick_confs[INICK_NNTP_CONF+1]; /* * Screen for editing configuration of a role. * * Args ps -- pine struct * def -- default role values to start with * title -- part of title at top of screen * rflags -- which parts of role to edit * result -- This is the returned PAT_S, freed by caller. * * Returns: 0 if no change * 1 if user requested a change * (change is stored in raw_server and hasn't been acted upon yet) * 10 user says abort */ int role_config_edit_screen(struct pine *ps, PAT_S *def, char *title, long int rflags, PAT_S **result) { OPT_SCREEN_S screen, *saved_screen; CONF_S *ctmp = NULL, *ctmpb, *first_line = NULL; struct variable nick_var, to_pat_var, from_pat_var, comment_var, sender_pat_var, cc_pat_var, recip_pat_var, news_pat_var, subj_pat_var, inick_var, fldr_type_var, folder_pat_var, abook_type_var, abook_pat_var, alltext_pat_var, scorei_pat_var, partic_pat_var, bodytext_pat_var, age_pat_var, size_pat_var, keyword_pat_var, charset_pat_var, stat_new_var, stat_del_var, stat_imp_var, stat_ans_var, stat_rec_var, stat_8bit_var, stat_bom_var, stat_boy_var, cat_cmd_var, cati_var, cat_lim_var, from_act_var, replyto_act_var, fcc_act_var, sig_act_var, litsig_act_var, templ_act_var, cstm_act_var, smtp_act_var, nntp_act_var, sort_act_var, iform_act_var, startup_var, repl_type_var, forw_type_var, comp_type_var, score_act_var, hdrtok_act_var, rolecolor_vars[2], filter_type_var, folder_act_var, keyword_set_var, keyword_clr_var, filt_new_var, filt_del_var, filt_imp_var, filt_ans_var; struct variable *v, *varlist[65], opt_var, inabook_type_var; char *nick = NULL, *inick = NULL, *fldr_type_pat = NULL, *comment = NULL, *scorei_pat = NULL, *age_pat = NULL, *size_pat = NULL, *abook_type_pat = NULL, *stat_new = NULL, *stat_del = NULL, *stat_imp = NULL, *stat_rec = NULL, *stat_ans = NULL, *stat_8bit = NULL, *stat_bom = NULL, *stat_boy = NULL, *filt_new = NULL, *filt_del = NULL, *filt_imp = NULL, *filt_ans = NULL, *cati = NULL, *cat_lim = NULL, *from_act = NULL, *replyto_act = NULL, *fcc_act = NULL, *sig_act = NULL, *litsig_act = NULL, *sort_act = NULL, *templ_act = NULL, *repl_type = NULL, *forw_type = NULL, *comp_type = NULL, *rc_fg = NULL, *rc_bg = NULL, *score_act = NULL, *filter_type = NULL, *hdrtok_act = NULL, *iform_act = NULL, *startup_act = NULL, *old_fg = NULL, *old_bg = NULL; char **to_pat = NULL, **from_pat = NULL, **sender_pat = NULL, **cc_pat = NULL, **news_pat = NULL, **recip_pat = NULL, **partic_pat = NULL, **subj_pat = NULL, **alltext_pat = NULL, **bodytext_pat = NULL, **keyword_pat = NULL, **folder_pat = NULL, **charset_pat = NULL, **abook_pat = NULL, **folder_act = NULL, **keyword_set = NULL, **keyword_clr = NULL, **cat_cmd = NULL, **cstm_act = NULL, **smtp_act = NULL, **nntp_act = NULL, **spat; char tmp[MAXPATH+1], **apval, **lval, ***alval, *p; /* TRANSLATORS: These next 4 are subheading for sections of a configuration screen. */ char *fstr = _(" CURRENT FOLDER CONDITIONS BEGIN HERE "); char mstr[50]; char *astr = _(" ACTIONS BEGIN HERE "); char *ustr = _(" USES BEGIN HERE "); char *ostr = _(" OPTIONS BEGIN HERE "); char *s_p_v_n = _("Subject pattern"); /* longest one of these */ char *u_s_s = _("Use SMTP Server"); /* ditto */ char *c_v_n = _("Exit Status Interval"); /* ditto */ SortOrder def_sort; int def_sort_rev; ARBHDR_S *aa, *a; EARB_S *earb = NULL, *ea; int rv, i, j, lv, pindent, maxpindent, rindent, scoreval = 0, edit_role, wid, edit_incol, edit_score, edit_filter, edit_other, edit_srch, dval, ival, nval, aval, fval, per_folder_only, need_uses, need_options; int (*radio_tool)(struct pine *, int, CONF_S **, unsigned); int (*addhdr_tool)(struct pine *, int, CONF_S **, unsigned); int (*t_tool)(struct pine *, int, CONF_S **, unsigned); NAMEVAL_S *f; dprint((4, "role_config_edit_screen()\n")); edit_role = rflags & ROLE_DO_ROLES; edit_incol = rflags & ROLE_DO_INCOLS; edit_score = rflags & ROLE_DO_SCORES; edit_filter = rflags & ROLE_DO_FILTER; edit_other = rflags & ROLE_DO_OTHER; edit_srch = rflags & ROLE_DO_SRCH; per_folder_only = (edit_other && !(edit_role || edit_incol || edit_score || edit_filter || edit_srch)); need_uses = edit_role; need_options = !per_folder_only; radio_tool = edit_filter ? role_filt_radiobutton_tool : role_radiobutton_tool; t_tool = edit_filter ? role_filt_text_tool : role_text_tool; addhdr_tool = edit_filter ? role_filt_addhdr_tool : role_addhdr_tool; rindent = 12; /* radio indent */ /* * We edit by making a nested call to conf_scroll_screen. * We use some fake struct variables to get back the results in, and * so we can use the existing tools from the config screen. */ varlist[j = 0] = &nick_var; varlist[++j] = &comment_var; varlist[++j] = &to_pat_var; varlist[++j] = &from_pat_var; varlist[++j] = &sender_pat_var; varlist[++j] = &cc_pat_var; varlist[++j] = &recip_pat_var; varlist[++j] = &partic_pat_var; varlist[++j] = &news_pat_var; varlist[++j] = &subj_pat_var; varlist[++j] = &alltext_pat_var; varlist[++j] = &bodytext_pat_var; varlist[++j] = &keyword_pat_var; varlist[++j] = &charset_pat_var; varlist[++j] = &age_pat_var; varlist[++j] = &size_pat_var; varlist[++j] = &scorei_pat_var; varlist[++j] = &stat_new_var; varlist[++j] = &stat_rec_var; varlist[++j] = &stat_del_var; varlist[++j] = &stat_imp_var; varlist[++j] = &stat_ans_var; varlist[++j] = &stat_8bit_var; varlist[++j] = &stat_bom_var; varlist[++j] = &stat_boy_var; varlist[++j] = &cat_cmd_var; varlist[++j] = &cati_var; varlist[++j] = &cat_lim_var; varlist[++j] = &inick_var; varlist[++j] = &fldr_type_var; varlist[++j] = &folder_pat_var; varlist[++j] = &abook_type_var; varlist[++j] = &abook_pat_var; varlist[++j] = &from_act_var; varlist[++j] = &replyto_act_var; varlist[++j] = &fcc_act_var; varlist[++j] = &sig_act_var; varlist[++j] = &litsig_act_var; varlist[++j] = &sort_act_var; varlist[++j] = &iform_act_var; varlist[++j] = &startup_var; varlist[++j] = &templ_act_var; varlist[++j] = &cstm_act_var; varlist[++j] = &smtp_act_var; varlist[++j] = &nntp_act_var; varlist[++j] = &score_act_var; varlist[++j] = &hdrtok_act_var; varlist[++j] = &repl_type_var; varlist[++j] = &forw_type_var; varlist[++j] = &comp_type_var; varlist[++j] = &rolecolor_vars[0]; varlist[++j] = &rolecolor_vars[1]; varlist[++j] = &filter_type_var; varlist[++j] = &folder_act_var; varlist[++j] = &keyword_set_var; varlist[++j] = &keyword_clr_var; varlist[++j] = &filt_new_var; varlist[++j] = &filt_del_var; varlist[++j] = &filt_imp_var; varlist[++j] = &filt_ans_var; varlist[++j] = &opt_var; varlist[++j] = &inabook_type_var; varlist[++j] = NULL; for(j = 0; varlist[j]; j++) memset(varlist[j], 0, sizeof(struct variable)); if(def && ((def->patgrp && def->patgrp->bogus) || (def->action && def->action->bogus))){ char msg[MAX_SCREEN_COLS+1]; snprintf(msg, sizeof(msg), _("Rule contains unknown %s element, possibly from newer Alpine"), (def->patgrp && def->patgrp->bogus) ? "pattern" : "action"); msg[sizeof(msg)-1] = '\0'; q_status_message(SM_ORDER | SM_DING, 7, 7, msg); q_status_message(SM_ORDER | SM_DING, 7, 7, _("Editing with this version of Alpine will destroy information")); flush_status_messages(0); } role_forw_ptr = role_repl_ptr = role_fldr_ptr = role_filt_ptr = NULL; role_status1_ptr = role_status2_ptr = role_status3_ptr = NULL; role_status4_ptr = role_status5_ptr = role_status6_ptr = NULL; role_status7_ptr = NULL; role_status8_ptr = NULL; msg_state1_ptr = msg_state2_ptr = NULL; msg_state3_ptr = msg_state4_ptr = NULL; role_afrom_ptr = startup_ptr = NULL; role_comment_ptr = NULL; nick_var.name = cpystr(_("Nickname")); nick_var.is_used = 1; nick_var.is_user = 1; apval = APVAL(&nick_var, ew); *apval = (def && def->patgrp && def->patgrp->nick) ? cpystr(def->patgrp->nick) : NULL; nick_var.global_val.p = cpystr(edit_role ? "Alternate Role" : (edit_other ? "Other Rule" : (edit_incol ? "Index Color Rule" : (edit_score ? "Score Rule" : "Filter Rule")))); set_current_val(&nick_var, FALSE, FALSE); role_comment_ptr = &comment_var; /* so radiobuttons can tell */ comment_var.name = cpystr(_("Comment")); comment_var.is_used = 1; comment_var.is_user = 1; apval = APVAL(&comment_var, ew); *apval = (def && def->patgrp && def->patgrp->comment) ? cpystr(def->patgrp->comment) : NULL; set_current_val(&comment_var, FALSE, FALSE); /* TRANSLATORS: Quite a few of the translations to follow are from the rules editing screens. These are mostly headings of individual categories of criteria which can be set in a rule. */ setup_dummy_pattern_var(&to_pat_var, _("To pattern"), (def && def->patgrp) ? def->patgrp->to : NULL); setup_dummy_pattern_var(&from_pat_var, _("From pattern"), (def && def->patgrp) ? def->patgrp->from : NULL); setup_dummy_pattern_var(&sender_pat_var, _("Sender pattern"), (def && def->patgrp) ? def->patgrp->sender : NULL); setup_dummy_pattern_var(&cc_pat_var, _("Cc pattern"), (def && def->patgrp) ? def->patgrp->cc : NULL); setup_dummy_pattern_var(&news_pat_var, _("News pattern"), (def && def->patgrp) ? def->patgrp->news : NULL); setup_dummy_pattern_var(&subj_pat_var, s_p_v_n, (def && def->patgrp) ? def->patgrp->subj : NULL); /* TRANSLATORS: Recip is an abbreviation for Recipients which stands for all of the recipients of a message. */ setup_dummy_pattern_var(&recip_pat_var, _("Recip pattern"), (def && def->patgrp) ? def->patgrp->recip : NULL); /* TRANSLATORS: Partic is an abbreviation for Participants which stands for all of the recipients plus the sender of a message. */ setup_dummy_pattern_var(&partic_pat_var, _("Partic pattern"), (def && def->patgrp) ? def->patgrp->partic : NULL); /* TRANSLATORS: AllText means all of the text of a message */ setup_dummy_pattern_var(&alltext_pat_var, _("AllText pattern"), (def && def->patgrp) ? def->patgrp->alltext : NULL); /* TRANSLATORS: BdyText means the text of a message but not the text in the headers */ setup_dummy_pattern_var(&bodytext_pat_var, _("BdyText pattern"), (def && def->patgrp) ? def->patgrp->bodytext : NULL); setup_dummy_pattern_var(&keyword_pat_var, _("Keyword pattern"), (def && def->patgrp) ? def->patgrp->keyword : NULL); setup_dummy_pattern_var(&charset_pat_var, _("Charset pattern"), (def && def->patgrp) ? def->patgrp->charsets : NULL); age_pat_global_ptr = &age_pat_var; /* TRANSLATORS: Age interval is a setting for how old the message is. */ age_pat_var.name = cpystr(_("Age interval")); age_pat_var.is_used = 1; age_pat_var.is_user = 1; if(def && def->patgrp && def->patgrp->do_age){ apval = APVAL(&age_pat_var, ew); *apval = stringform_of_intvl(def->patgrp->age); } set_current_val(&age_pat_var, FALSE, FALSE); size_pat_global_ptr = &size_pat_var; size_pat_var.name = cpystr(_("Size interval")); size_pat_var.is_used = 1; size_pat_var.is_user = 1; if(def && def->patgrp && def->patgrp->do_size){ apval = APVAL(&size_pat_var, ew); *apval = stringform_of_intvl(def->patgrp->size); } set_current_val(&size_pat_var, FALSE, FALSE); scorei_pat_global_ptr = &scorei_pat_var; /* TRANSLATORS: Score is an alpine concept where the score can be kept for a message to see if it is a message you want to look at. */ scorei_pat_var.name = cpystr(_("Score interval")); scorei_pat_var.is_used = 1; scorei_pat_var.is_user = 1; if(def && def->patgrp && def->patgrp->do_score){ apval = APVAL(&scorei_pat_var, ew); *apval = stringform_of_intvl(def->patgrp->score); } set_current_val(&scorei_pat_var, FALSE, FALSE); role_status1_ptr = &stat_del_var; /* so radiobuttons can tell */ stat_del_var.name = cpystr(_("Message is Deleted?")); stat_del_var.is_used = 1; stat_del_var.is_user = 1; apval = APVAL(&stat_del_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_del : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_del_var, FALSE, FALSE); role_status2_ptr = &stat_new_var; /* so radiobuttons can tell */ stat_new_var.name = cpystr(_("Message is New (Unseen)?")); stat_new_var.is_used = 1; stat_new_var.is_user = 1; apval = APVAL(&stat_new_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_new : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_new_var, FALSE, FALSE); role_status3_ptr = &stat_imp_var; /* so radiobuttons can tell */ stat_imp_var.name = cpystr(_("Message is Important?")); stat_imp_var.is_used = 1; stat_imp_var.is_user = 1; apval = APVAL(&stat_imp_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_imp : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_imp_var, FALSE, FALSE); role_status4_ptr = &stat_ans_var; /* so radiobuttons can tell */ stat_ans_var.name = cpystr(_("Message is Answered?")); stat_ans_var.is_used = 1; stat_ans_var.is_user = 1; apval = APVAL(&stat_ans_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_ans : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_ans_var, FALSE, FALSE); role_status5_ptr = &stat_8bit_var; /* so radiobuttons can tell */ stat_8bit_var.name = cpystr(_("Subject contains raw 8-bit?")); stat_8bit_var.is_used = 1; stat_8bit_var.is_user = 1; apval = APVAL(&stat_8bit_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_8bitsubj : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_8bit_var, FALSE, FALSE); role_status6_ptr = &stat_rec_var; /* so radiobuttons can tell */ stat_rec_var.name = cpystr(_("Message is Recent?")); stat_rec_var.is_used = 1; stat_rec_var.is_user = 1; apval = APVAL(&stat_rec_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_rec : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_rec_var, FALSE, FALSE); role_status7_ptr = &stat_bom_var; /* so radiobuttons can tell */ stat_bom_var.name = cpystr(_("Beginning of Month?")); stat_bom_var.is_used = 1; stat_bom_var.is_user = 1; apval = APVAL(&stat_bom_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_bom : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_bom_var, FALSE, FALSE); role_status8_ptr = &stat_boy_var; /* so radiobuttons can tell */ stat_boy_var.name = cpystr(_("Beginning of Year?")); stat_boy_var.is_used = 1; stat_boy_var.is_user = 1; apval = APVAL(&stat_boy_var, ew); *apval = (f=role_status_types((def && def->patgrp) ? def->patgrp->stat_boy : -1)) ? cpystr(f->name) : NULL; set_current_val(&stat_boy_var, FALSE, FALSE); convert_statebits_to_vals((def && def->action) ? def->action->state_setting_bits : 0L, &dval, &aval, &ival, &nval); msg_state1_ptr = &filt_del_var; /* so radiobuttons can tell */ /* TRANSLATORS: these are actions that might be taken by the rule */ filt_del_var.name = cpystr(_("Set Deleted Status")); filt_del_var.is_used = 1; filt_del_var.is_user = 1; apval = APVAL(&filt_del_var, ew); *apval = (f=msg_state_types(dval)) ? cpystr(f->name) : NULL; set_current_val(&filt_del_var, FALSE, FALSE); msg_state2_ptr = &filt_new_var; /* so radiobuttons can tell */ filt_new_var.name = cpystr(_("Set New Status")); filt_new_var.is_used = 1; filt_new_var.is_user = 1; apval = APVAL(&filt_new_var, ew); *apval = (f=msg_state_types(nval)) ? cpystr(f->name) : NULL; set_current_val(&filt_new_var, FALSE, FALSE); msg_state3_ptr = &filt_imp_var; /* so radiobuttons can tell */ filt_imp_var.name = cpystr(_("Set Important Status")); filt_imp_var.is_used = 1; filt_imp_var.is_user = 1; apval = APVAL(&filt_imp_var, ew); *apval = (f=msg_state_types(ival)) ? cpystr(f->name) : NULL; set_current_val(&filt_imp_var, FALSE, FALSE); msg_state4_ptr = &filt_ans_var; /* so radiobuttons can tell */ filt_ans_var.name = cpystr(_("Set Answered Status")); filt_ans_var.is_used = 1; filt_ans_var.is_user = 1; apval = APVAL(&filt_ans_var, ew); *apval = (f=msg_state_types(aval)) ? cpystr(f->name) : NULL; set_current_val(&filt_ans_var, FALSE, FALSE); inick_var.name = cpystr(_("Initialize settings using role")); inick_var.is_used = 1; inick_var.is_user = 1; apval = APVAL(&inick_var, ew); *apval = (def && def->action && def->action->inherit_nick && def->action->inherit_nick[0]) ? cpystr(def->action->inherit_nick) : NULL; role_fldr_ptr = &fldr_type_var; /* so radiobuttons can tell */ fldr_type_var.name = cpystr(_("Current Folder Type")); fldr_type_var.is_used = 1; fldr_type_var.is_user = 1; apval = APVAL(&fldr_type_var, ew); *apval = (f=pat_fldr_types((def && def->patgrp) ? def->patgrp->fldr_type : (!def && edit_filter) ? FLDR_SPECIFIC : FLDR_DEFL)) ? cpystr(f->name) : NULL; set_current_val(&fldr_type_var, FALSE, FALSE); setup_dummy_pattern_var(&folder_pat_var, _("Folder List"), (def && def->patgrp) ? def->patgrp->folder : NULL); /* special default for folder_pat */ alval = ALVAL(&folder_pat_var, ew); if(alval && !*alval && !def && edit_filter){ char **ltmp; ltmp = (char **) fs_get(2 * sizeof(*ltmp)); ltmp[0] = cpystr(ps_global->inbox_name); ltmp[1] = NULL; *alval = ltmp; set_current_val(&folder_pat_var, FALSE, FALSE); } role_afrom_ptr = &abook_type_var; /* so radiobuttons can tell */ abook_type_var.name = cpystr(_("Address in address book?")); abook_type_var.is_used = 1; abook_type_var.is_user = 1; apval = APVAL(&abook_type_var, ew); *apval = (f=inabook_fldr_types((def && def->patgrp) ? def->patgrp->inabook : IAB_EITHER)) ? cpystr(f->name) : NULL; set_current_val(&abook_type_var, FALSE, FALSE); /* TRANSLATORS: Abook is an abbreviation for Address Book */ setup_dummy_pattern_var(&abook_pat_var, _("Abook List"), (def && def->patgrp) ? def->patgrp->abooks : NULL); /* * This is a little different from some of the other patterns. Tt is * actually a char ** in the struct instead of a PATTERN_S. */ cat_cmd_global_ptr = &cat_cmd_var; cat_cmd_var.name = cpystr(_("External Categorizer Commands")); cat_cmd_var.is_used = 1; cat_cmd_var.is_user = 1; cat_cmd_var.is_list = 1; alval = ALVAL(&cat_cmd_var, ew); *alval = (def && def->patgrp && def->patgrp->category_cmd && def->patgrp->category_cmd[0]) ? copy_list_array(def->patgrp->category_cmd) : NULL; set_current_val(&cat_cmd_var, FALSE, FALSE); cati_global_ptr = &cati_var; cati_var.name = cpystr(c_v_n); cati_var.is_used = 1; cati_var.is_user = 1; if(def && def->patgrp && def->patgrp->do_cat && def->patgrp->category_cmd && def->patgrp->category_cmd[0]){ apval = APVAL(&cati_var, ew); *apval = stringform_of_intvl(def->patgrp->cat); } set_current_val(&cati_var, FALSE, FALSE); cat_lim_global_ptr = &cat_lim_var; cat_lim_var.name = cpystr(_("Character Limit")); cat_lim_var.is_used = 1; cat_lim_var.is_user = 1; cat_lim_var.global_val.p = cpystr("-1"); apval = APVAL(&cat_lim_var, ew); if(def && def->patgrp && def->patgrp->category_cmd && def->patgrp->category_cmd[0] && def->patgrp->cat_lim != -1){ *apval = (char *) fs_get(20 * sizeof(char)); snprintf(*apval, 20, "%ld", def->patgrp->cat_lim); (*apval)[20-1] = '\0'; } set_current_val(&cat_lim_var, FALSE, FALSE); from_act_var.name = cpystr(_("Set From")); from_act_var.is_used = 1; from_act_var.is_user = 1; if(def && def->action && def->action->from){ char *bufp; size_t len; len = est_size(def->action->from); bufp = (char *) fs_get(len * sizeof(char)); apval = APVAL(&from_act_var, ew); *apval = addr_string_mult(def->action->from, bufp, len); } else{ apval = APVAL(&from_act_var, ew); *apval = NULL; } replyto_act_var.name = cpystr(_("Set Reply-To")); replyto_act_var.is_used = 1; replyto_act_var.is_user = 1; if(def && def->action && def->action->replyto){ char *bufp; size_t len; len = est_size(def->action->replyto); bufp = (char *) fs_get(len * sizeof(char)); apval = APVAL(&replyto_act_var, ew); *apval = addr_string_mult(def->action->replyto, bufp, len); } else{ apval = APVAL(&replyto_act_var, ew); *apval = NULL; } fcc_act_var.name = cpystr(_("Set Fcc")); fcc_act_var.is_used = 1; fcc_act_var.is_user = 1; apval = APVAL(&fcc_act_var, ew); *apval = (def && def->action && def->action->fcc) ? cpystr(def->action->fcc) : NULL; sort_act_var.name = cpystr(_("Set Sort Order")); sort_act_var.is_used = 1; sort_act_var.is_user = 1; apval = APVAL(&sort_act_var, ew); if(def && def->action && def->action->is_a_other && def->action->sort_is_set){ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s", sort_name(def->action->sortorder), (def->action->revsort) ? "/Reverse" : ""); tmp_20k_buf[SIZEOF_20KBUF-1] = '\0'; *apval = cpystr(tmp_20k_buf); } else *apval = NULL; iform_act_var.name = cpystr(_("Set Index Format")); iform_act_var.is_used = 1; iform_act_var.is_user = 1; apval = APVAL(&iform_act_var, ew); *apval = (def && def->action && def->action->is_a_other && def->action->index_format) ? cpystr(def->action->index_format) : NULL; if(ps_global->VAR_INDEX_FORMAT){ iform_act_var.global_val.p = cpystr(ps_global->VAR_INDEX_FORMAT); set_current_val(&iform_act_var, FALSE, FALSE); } startup_ptr = &startup_var; startup_var.name = cpystr(_("Set Startup Rule")); startup_var.is_used = 1; startup_var.is_user = 1; apval = APVAL(&startup_var, ew); *apval = NULL; if(def && def->action && def->action->is_a_other){ *apval = (f=startup_rules(def->action->startup_rule)) ? cpystr(f->name) : NULL; set_current_val(&startup_var, FALSE, FALSE); } if(!*apval){ *apval = (f=startup_rules(IS_NOTSET)) ? cpystr(f->name) : NULL; set_current_val(&startup_var, FALSE, FALSE); } /* TRANSLATORS: LiteralSig is a way to keep the signature in the configuration file instead of in a separate Signature file. */ litsig_act_var.name = cpystr(_("Set LiteralSig")); litsig_act_var.is_used = 1; litsig_act_var.is_user = 1; apval = APVAL(&litsig_act_var, ew); *apval = (def && def->action && def->action->litsig) ? cpystr(def->action->litsig) : NULL; sig_act_var.name = cpystr(_("Set Signature")); sig_act_var.is_used = 1; sig_act_var.is_user = 1; apval = APVAL(&sig_act_var, ew); *apval = (def && def->action && def->action->sig) ? cpystr(def->action->sig) : NULL; /* TRANSLATORS: A template is a skeleton of a message to be used for composing a new message */ templ_act_var.name = cpystr(_("Set Template")); templ_act_var.is_used = 1; templ_act_var.is_user = 1; apval = APVAL(&templ_act_var, ew); *apval = (def && def->action && def->action->template) ? cpystr(def->action->template) : NULL; /* TRANSLATORS: Hdrs is an abbreviation for Headers */ cstm_act_var.name = cpystr(_("Set Other Hdrs")); cstm_act_var.is_used = 1; cstm_act_var.is_user = 1; cstm_act_var.is_list = 1; alval = ALVAL(&cstm_act_var, ew); *alval = (def && def->action && def->action->cstm) ? copy_list_array(def->action->cstm) : NULL; smtp_act_var.name = cpystr(u_s_s); smtp_act_var.is_used = 1; smtp_act_var.is_user = 1; smtp_act_var.is_list = 1; alval = ALVAL(&smtp_act_var, ew); *alval = (def && def->action && def->action->smtp) ? copy_list_array(def->action->smtp) : NULL; nntp_act_var.name = cpystr(_("Use NNTP Server")); nntp_act_var.is_used = 1; nntp_act_var.is_user = 1; nntp_act_var.is_list = 1; alval = ALVAL(&nntp_act_var, ew); *alval = (def && def->action && def->action->nntp) ? copy_list_array(def->action->nntp) : NULL; score_act_global_ptr = &score_act_var; score_act_var.name = cpystr(_("Score Value")); score_act_var.is_used = 1; score_act_var.is_user = 1; if(def && def->action && def->action->scoreval >= SCORE_MIN && def->action->scoreval <= SCORE_MAX) scoreval = def->action->scoreval; score_act_var.global_val.p = cpystr("0"); if(scoreval != 0){ apval = APVAL(&score_act_var, ew); *apval = (char *)fs_get(20 * sizeof(char)); snprintf(*apval, 20, "%d", scoreval); (*apval)[20-1] = '\0'; } set_current_val(&score_act_var, FALSE, FALSE); hdrtok_act_var.name = cpystr(_("Score From Header")); hdrtok_act_var.is_used = 1; hdrtok_act_var.is_user = 1; if(def && def->action && def->action->scorevalhdrtok){ apval = APVAL(&hdrtok_act_var, ew); *apval = hdrtok_to_stringform(def->action->scorevalhdrtok); } set_current_val(&hdrtok_act_var, FALSE, FALSE); role_repl_ptr = &repl_type_var; /* so radiobuttons can tell */ /* TRANSLATORS: For these, Use is a now. This part of the rule describes how it will be used when Replying so it is the Reply Use */ repl_type_var.name = cpystr(_("Reply Use")); repl_type_var.is_used = 1; repl_type_var.is_user = 1; apval = APVAL(&repl_type_var, ew); *apval = (f=role_repl_types((def && def->action) ? def->action->repl_type : -1)) ? cpystr(f->name) : NULL; set_current_val(&repl_type_var, FALSE, FALSE); role_forw_ptr = &forw_type_var; /* so radiobuttons can tell */ forw_type_var.name = cpystr(_("Forward Use")); forw_type_var.is_used = 1; forw_type_var.is_user = 1; apval = APVAL(&forw_type_var, ew); *apval = (f=role_forw_types((def && def->action) ? def->action->forw_type : -1)) ? cpystr(f->name) : NULL; set_current_val(&forw_type_var, FALSE, FALSE); comp_type_var.name = cpystr(_("Compose Use")); comp_type_var.is_used = 1; comp_type_var.is_user = 1; apval = APVAL(&comp_type_var, ew); *apval = (f=role_comp_types((def && def->action) ? def->action->comp_type : -1)) ? cpystr(f->name) : NULL; set_current_val(&comp_type_var, FALSE, FALSE); rolecolor_vars[0].is_used = 1; rolecolor_vars[0].is_user = 1; apval = APVAL(&rolecolor_vars[0], ew); *apval = (def && def->action && def->action->incol && def->action->incol->fg[0]) ? cpystr(def->action->incol->fg) : NULL; rolecolor_vars[1].is_used = 1; rolecolor_vars[1].is_user = 1; rolecolor_vars[0].name = cpystr("ic-foreground-color"); rolecolor_vars[1].name = cpystr(rolecolor_vars[0].name); strncpy(rolecolor_vars[1].name + 3, "back", 4); apval = APVAL(&rolecolor_vars[1], ew); *apval = (def && def->action && def->action->incol && def->action->incol->bg[0]) ? cpystr(def->action->incol->bg) : NULL; set_current_val(&rolecolor_vars[0], FALSE, FALSE); set_current_val(&rolecolor_vars[1], FALSE, FALSE); old_fg = PVAL(&rolecolor_vars[0], ew) ? cpystr(PVAL(&rolecolor_vars[0], ew)) : NULL; old_bg = PVAL(&rolecolor_vars[1], ew) ? cpystr(PVAL(&rolecolor_vars[1], ew)) : NULL; /* save the old opt_screen before calling scroll screen again */ saved_screen = opt_screen; pindent = utf8_width(s_p_v_n); /* the longest one */ maxpindent = pindent + 6; for(a = (def && def->patgrp) ? def->patgrp->arbhdr : NULL; a; a = a->next) if((lv=utf8_width(a->field ? a->field : "")+utf8_width(" pattern")) > pindent) pindent = lv; pindent = MIN(pindent, maxpindent); pindent += NOTLEN; /* width of `! ' */ pindent += 3; /* width of ` = ' */ /* Nickname */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR NICKNAME"); ctmp->var = &nick_var; ctmp->valoffset = pindent; ctmp->keymenu = &config_role_keymenu; ctmp->help = edit_role ? h_config_role_nick : edit_incol ? h_config_incol_nick : edit_score ? h_config_score_nick : edit_other ? h_config_other_nick : h_config_filt_nick; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", pindent-3, pindent-3, nick_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); ctmp->varmem = -1; first_line = ctmp; if(rflags & ROLE_CHANGES) first_line->flags |= CF_CHANGES; /* Comment */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR COMMENT"); ctmp->var = &comment_var; ctmp->valoffset = pindent; ctmp->keymenu = &config_role_keymenu; ctmp->help = h_config_role_comment; ctmp->tool = role_litsig_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", pindent-3, pindent-3, comment_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); ctmp->varmem = -1; /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->flags |= CF_NOSELECT; if(ps->ttyo->screen_cols >= (wid=utf8_width(fstr)) + 4){ int dashes; dashes = (ps->ttyo->screen_cols - wid)/2; snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s", repeat_char(dashes, '='), fstr, repeat_char(ps->ttyo->screen_cols-wid-dashes, '=')); ctmp->value = cpystr(tmp_20k_buf); } else ctmp->value = cpystr(repeat_char(ps->ttyo->screen_cols, '=')); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Folder Type */ new_confline(&ctmp); ctmp->var = &fldr_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", fldr_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Choose One"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = pat_fldr_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); fval = -1; for(i = 0; (f = pat_fldr_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR CURRENT FOLDER TYPE"); ctmp->var = &fldr_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = edit_role ? h_config_role_fldr_type : edit_incol ? h_config_incol_fldr_type : edit_score ? h_config_score_fldr_type : edit_other ? h_config_other_fldr_type : h_config_filt_fldr_type; ctmp->varmem = i; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; if((PVAL(&fldr_type_var, ew) && !strucmp(PVAL(&fldr_type_var, ew), f->name)) || (!PVAL(&fldr_type_var, ew) && f->value == FLDR_DEFL)) fval = f->value; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (fval == f->value) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Folder */ /* 5 is the width of `(*) ' */ setup_role_pat_alt(ps, &ctmp, &folder_pat_var, edit_role ? h_config_role_fldr_type : edit_incol ? h_config_incol_fldr_type : edit_score ? h_config_score_fldr_type : edit_other ? h_config_other_fldr_type : h_config_filt_fldr_type, _("HELP FOR FOLDER LIST"), &config_role_patfolder_keymenu, t_tool, rindent+5, !(fval == FLDR_SPECIFIC)); if(!per_folder_only){ /* sorry about that indent */ /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->flags |= CF_NOSELECT; /* TRANSLATORS: The %s is replaced with one of the 4 or 5 words below, CURRENT, SCORED, and so on. */ snprintf(mstr, sizeof(mstr), _(" %s MESSAGE CONDITIONS BEGIN HERE "), edit_role ? _("CURRENT") : edit_score ? _("SCORED") : edit_incol ? _("COLORED") : edit_filter ? _("FILTERED") : _("CURRENT")); mstr[sizeof(mstr)-1] = '\0'; if(ps->ttyo->screen_cols >= (wid=utf8_width(mstr)) + 4){ int dashes; dashes = (ps->ttyo->screen_cols - wid)/2; snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s", repeat_char(dashes, '='), mstr, repeat_char(ps->ttyo->screen_cols-wid-dashes, '=')); ctmp->value = cpystr(tmp_20k_buf); } else ctmp->value = cpystr(repeat_char(ps->ttyo->screen_cols, '=')); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; setup_role_pat(ps, &ctmp, &to_pat_var, edit_role ? h_config_role_topat : edit_incol ? h_config_incol_topat : edit_score ? h_config_score_topat : edit_other ? h_config_other_topat : h_config_filt_topat, _("HELP FOR TO PATTERN"), &config_role_addr_pat_keymenu, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &from_pat_var, h_config_role_frompat, _("HELP FOR FROM PATTERN"), &config_role_addr_pat_keymenu, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &sender_pat_var, h_config_role_senderpat, _("HELP FOR SENDER PATTERN"), &config_role_addr_pat_keymenu, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &cc_pat_var, h_config_role_ccpat, _("HELP FOR CC PATTERN"), &config_role_addr_pat_keymenu, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &news_pat_var, h_config_role_newspat, _("HELP FOR NEWS PATTERN"), &config_role_keymenu_not, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &subj_pat_var, h_config_role_subjpat, _("HELP FOR SUBJECT PATTERN"), &config_role_keymenu_not, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &recip_pat_var, h_config_role_recippat, _("HELP FOR RECIPIENT PATTERN"), &config_role_addr_pat_keymenu, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &partic_pat_var, h_config_role_particpat, _("HELP FOR PARTICIPANT PATTERN"), &config_role_addr_pat_keymenu, t_tool, &earb, pindent); /* Arbitrary Patterns */ ea = NULL; for(j = 0, a = (def && def->patgrp) ? def->patgrp->arbhdr : NULL; a; j++, a = a->next){ char *fn = (a->field) ? a->field : ""; if(ea){ ea->next = (EARB_S *)fs_get(sizeof(*ea)); ea = ea->next; } else{ earb = (EARB_S *)fs_get(sizeof(*ea)); ea = earb; } memset((void *)ea, 0, sizeof(*ea)); ea->v = (struct variable *)fs_get(sizeof(struct variable)); memset((void *)ea->v, 0, sizeof(struct variable)); ea->a = (ARBHDR_S *)fs_get(sizeof(ARBHDR_S)); memset((void *)ea->a, 0, sizeof(ARBHDR_S)); ea->a->field = cpystr(fn); p = (char *) fs_get(strlen(fn) + strlen(" pattern") + 1); snprintf(p, strlen(fn) + strlen(" pattern") + 1, "%s pattern", fn); p[strlen(fn) + strlen(" pattern") + 1 - 1] = '\0'; setup_dummy_pattern_var(ea->v, p, a->p); fs_give((void **) &p); setup_role_pat(ps, &ctmp, ea->v, h_config_role_arbpat, ARB_HELP, &config_role_xtrahdr_keymenu, t_tool, &earb, pindent); } new_confline(&ctmp); ctmp->help_title = _("HELP FOR EXTRA HEADERS"); ctmp->value = cpystr(ADDXHDRS); ctmp->keymenu = &config_role_keymenu_extra; ctmp->help = h_config_role_arbpat; ctmp->tool = addhdr_tool; ctmp->d.earb = &earb; ctmp->varmem = -1; setup_role_pat(ps, &ctmp, &alltext_pat_var, h_config_role_alltextpat, _("HELP FOR ALL TEXT PATTERN"), &config_role_keymenu_not, t_tool, &earb, pindent); setup_role_pat(ps, &ctmp, &bodytext_pat_var, h_config_role_bodytextpat, _("HELP FOR BODY TEXT PATTERN"), &config_role_keymenu_not, t_tool, &earb, pindent); /* Age Interval */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR AGE INTERVAL"); ctmp->var = &age_pat_var; ctmp->valoffset = pindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_age; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", pindent-3, pindent-3, age_pat_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Size Interval */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SIZE INTERVAL"); ctmp->var = &size_pat_var; ctmp->valoffset = pindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_size; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", pindent-3, pindent-3, size_pat_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); if(!edit_score){ /* Score Interval */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SCORE INTERVAL"); ctmp->var = &scorei_pat_var; ctmp->valoffset = pindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_scorei; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", pindent-3, pindent-3, scorei_pat_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); } /* Keyword Pattern */ setup_role_pat(ps, &ctmp, &keyword_pat_var, h_config_role_keywordpat, _("HELP FOR KEYWORD PATTERN"), &config_role_keyword_keymenu_not, role_text_tool_kword, NULL, pindent); /* Charset Pattern */ setup_role_pat(ps, &ctmp, &charset_pat_var, h_config_role_charsetpat, _("HELP FOR CHARACTER SET PATTERN"), &config_role_charset_keymenu_not, role_text_tool_charset, NULL, pindent); /* Important Status */ SETUP_PAT_STATUS(ctmp, stat_imp_var, def->patgrp->stat_imp, _("HELP FOR IMPORTANT STATUS"), h_config_role_stat_imp); /* New Status */ SETUP_PAT_STATUS(ctmp, stat_new_var, def->patgrp->stat_new, _("HELP FOR NEW STATUS"), h_config_role_stat_new); /* Recent Status */ SETUP_PAT_STATUS(ctmp, stat_rec_var, def->patgrp->stat_rec, _("HELP FOR RECENT STATUS"), h_config_role_stat_recent); /* Deleted Status */ SETUP_PAT_STATUS(ctmp, stat_del_var, def->patgrp->stat_del, _("HELP FOR DELETED STATUS"), h_config_role_stat_del); /* Answered Status */ SETUP_PAT_STATUS(ctmp, stat_ans_var, def->patgrp->stat_ans, _("HELP FOR ANSWERED STATUS"), h_config_role_stat_ans); /* 8-bit Subject */ SETUP_PAT_STATUS(ctmp, stat_8bit_var, def->patgrp->stat_8bitsubj, _("HELP FOR 8-BIT SUBJECT"), h_config_role_stat_8bitsubj); /* Beginning of month */ SETUP_PAT_STATUS(ctmp, stat_bom_var, def->patgrp->stat_bom, _("HELP FOR BEGINNING OF MONTH"), h_config_role_bom); /* Beginning of year */ SETUP_PAT_STATUS(ctmp, stat_boy_var, def->patgrp->stat_boy, _("HELP FOR BEGINNING OF YEAR"), h_config_role_boy); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* From in Addrbook */ new_confline(&ctmp); ctmp->var = &abook_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", abook_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Choose One"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = inabook_fldr_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); fval = -1; for(i = 0; (f = inabook_fldr_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR ADDRESS IN ADDRESS BOOK"); ctmp->var = &abook_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_role_abookfrom; ctmp->varmem = i; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; if((PVAL(&abook_type_var, ew) && !strucmp(PVAL(&abook_type_var, ew), f->name)) || (!PVAL(&abook_type_var, ew) && f->value == IAB_DEFL)) fval = f->value; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (fval == f->value) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Specific list of abooks */ /* 5 is the width of `(*) ' */ setup_role_pat_alt(ps, &ctmp, &abook_pat_var, h_config_role_abookfrom, _("HELP FOR ABOOK LIST"), &config_role_afrom_keymenu, role_text_tool_afrom, rindent+5, !(fval == IAB_SPEC_YES || fval == IAB_SPEC_NO)); /* Which addresses to check for */ inabook_type_var.name = cpystr(_("Types of addresses to check for in address book")); inabook_type_var.is_used = 1; inabook_type_var.is_user = 1; inabook_type_var.is_list = 1; clrbitmap(inabook_type_list); if(def && def->patgrp && def->patgrp->inabook & IAB_FROM) setbitn(INABOOK_FROM, inabook_type_list); if(def && def->patgrp && def->patgrp->inabook & IAB_REPLYTO) setbitn(INABOOK_REPLYTO, inabook_type_list); if(def && def->patgrp && def->patgrp->inabook & IAB_SENDER) setbitn(INABOOK_SENDER, inabook_type_list); if(def && def->patgrp && def->patgrp->inabook & IAB_TO) setbitn(INABOOK_TO, inabook_type_list); if(def && def->patgrp && def->patgrp->inabook & IAB_CC) setbitn(INABOOK_CC, inabook_type_list); /* default setting */ if(!(bitnset(INABOOK_FROM, inabook_type_list) || bitnset(INABOOK_REPLYTO, inabook_type_list) || bitnset(INABOOK_SENDER, inabook_type_list) || bitnset(INABOOK_TO, inabook_type_list) || bitnset(INABOOK_CC, inabook_type_list))){ setbitn(INABOOK_FROM, inabook_type_list); setbitn(INABOOK_REPLYTO, inabook_type_list); } new_confline(&ctmp); ctmp->var = &inabook_type_var; ctmp->varoffset = 4; ctmp->valoffset = 23; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%-20s =", inabook_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = inabook_checkbox_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Address types"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = inabook_checkbox_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); /* find longest value's name */ for(lv = 0, i = 0; (f = inabook_feature_list(i)); i++){ if(lv < (j = utf8_width(f->name))) lv = j; } lv = MIN(lv, 100); for(i = 0; (f = inabook_feature_list(i)); i++){ new_confline(&ctmp); ctmp->var = &opt_var; ctmp->help_title= _("HELP FOR ADDRESS TYPES"); ctmp->varnamep = ctmpb; ctmp->keymenu = &config_checkbox_keymenu; switch(i){ case INABOOK_FROM: ctmp->help = h_config_inabook_from; break; case INABOOK_REPLYTO: ctmp->help = h_config_inabook_replyto; break; case INABOOK_SENDER: ctmp->help = h_config_inabook_sender; break; case INABOOK_TO: ctmp->help = h_config_inabook_to; break; case INABOOK_CC: ctmp->help = h_config_inabook_cc; break; } ctmp->tool = inabook_checkbox_tool; ctmp->valoffset = rindent; ctmp->varmem = i; utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w", bitnset(f->value, inabook_type_list) ? 'X' : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* 4 is indent of "Command", c_v_n is longest of these three, 3 is ` = ' */ i = 4 + utf8_width(c_v_n) + 3; /* External Command Categorizer */ new_confline(&ctmp); ctmp->var = &cat_cmd_var; ctmp->keymenu = &config_text_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", cat_cmd_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); /* Commands */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR CATEGORIZER COMMAND"); ctmp->var = &cat_cmd_var; ctmp->varoffset = 4; ctmp->valoffset = i; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_cat_cmd; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", i-4-3, i-4-3, "Command"); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags = CF_STARTITEM; if((lval = LVAL(&cat_cmd_var, ew)) != NULL && lval[0]){ for(j = 0; lval[j]; j++){ if(j) (void) new_confline(&ctmp); ctmp->var = &cat_cmd_var; ctmp->varmem = j; ctmp->valoffset = i; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_cat_cmd; ctmp->tool = t_tool; ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); } } else ctmp->value = pretty_value(ps, ctmp); /* Exit status interval */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR CATEGORIZER EXIT STATUS"); ctmp->var = &cati_var; ctmp->varoffset = 4; ctmp->valoffset = i; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_cat_status; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", i-4-3, i-4-3, cati_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Character Limit */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR CHARACTER LIMIT"); ctmp->var = &cat_lim_var; ctmp->varoffset = 4; ctmp->valoffset = i; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_cat_limit; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", i-4-3, i-4-3, cat_lim_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); ctmp->flags |= CF_NUMBER; } if(!edit_srch){ /* sorry about that indent */ /* Actions */ /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->flags |= CF_NOSELECT; if(ps->ttyo->screen_cols >= (wid=utf8_width(astr)) + 4){ int dashes; dashes = (ps->ttyo->screen_cols - wid)/2; snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s", repeat_char(dashes, '='), astr, repeat_char(ps->ttyo->screen_cols-wid-dashes, '=')); ctmp->value = cpystr(tmp_20k_buf); } else ctmp->value = cpystr(repeat_char(ps->ttyo->screen_cols, '=')); if(edit_role){ int roindent; roindent = utf8_width(u_s_s); /* the longest one */ roindent += 3; /* width of ` = ' */ /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Inherit Nickname */ new_confline(&ctmp); inick_confs[INICK_INICK_CONF] = ctmp; ctmp->help_title= _("HELP FOR INITIAL SET NICKNAME"); ctmp->var = &inick_var; ctmp->keymenu = &config_role_inick_keymenu; ctmp->help = h_config_role_inick; ctmp->tool = role_text_tool_inick; snprintf(tmp, sizeof(tmp), "%s :", inick_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->valoffset = utf8_width(tmp)+1; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* From Action */ new_confline(&ctmp); inick_confs[INICK_FROM_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET FROM ACTION"); ctmp->var = &from_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_role_addr_act_keymenu; ctmp->help = h_config_role_setfrom; ctmp->tool = role_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, from_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* Reply-To Action */ new_confline(&ctmp); inick_confs[INICK_REPLYTO_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET REPLY-TO ACTION"); ctmp->var = &replyto_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_role_addr_act_keymenu; ctmp->help = h_config_role_setreplyto; ctmp->tool = role_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, replyto_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* Fcc Action */ new_confline(&ctmp); inick_confs[INICK_FCC_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET FCC ACTION"); ctmp->var = &fcc_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_role_actionfolder_keymenu; ctmp->help = h_config_role_setfcc; ctmp->tool = role_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, fcc_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* LitSig Action */ new_confline(&ctmp); inick_confs[INICK_LITSIG_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET LITERAL SIGNATURE ACTION"); ctmp->var = &litsig_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_setlitsig; ctmp->tool = role_litsig_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, litsig_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* Sig Action */ new_confline(&ctmp); inick_confs[INICK_SIG_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET SIGNATURE ACTION"); ctmp->var = &sig_act_var; ctmp->valoffset = roindent; if(F_ON(F_DISABLE_ROLES_SIGEDIT, ps_global)) ctmp->keymenu = &config_role_file_res_keymenu; else ctmp->keymenu = &config_role_file_keymenu; ctmp->help = h_config_role_setsig; ctmp->tool = role_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, sig_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* Template Action */ new_confline(&ctmp); inick_confs[INICK_TEMPL_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET TEMPLATE ACTION"); ctmp->var = &templ_act_var; ctmp->valoffset = roindent; if(F_ON(F_DISABLE_ROLES_TEMPLEDIT, ps_global)) ctmp->keymenu = &config_role_file_res_keymenu; else ctmp->keymenu = &config_role_file_keymenu; ctmp->help = h_config_role_settempl; ctmp->tool = role_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, templ_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; /* Other Headers Action */ new_confline(&ctmp); inick_confs[INICK_CSTM_CONF] = ctmp; ctmp->help_title= _("HELP FOR SET OTHER HEADERS ACTION"); ctmp->var = &cstm_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_setotherhdr; ctmp->tool = role_cstm_text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, cstm_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags = CF_STARTITEM; if((lval = LVAL(&cstm_act_var, ew)) != NULL){ for(i = 0; lval[i]; i++){ if(i) (void)new_confline(&ctmp); ctmp->var = &cstm_act_var; ctmp->varmem = i; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_setotherhdr; ctmp->tool = role_cstm_text_tool; ctmp->varnamep = ctmpb; } } else ctmp->varmem = 0; /* SMTP Server Action */ new_confline(&ctmp); inick_confs[INICK_SMTP_CONF] = ctmp; ctmp->help_title= _("HELP FOR SMTP SERVER ACTION"); ctmp->var = &smtp_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_usesmtp; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, smtp_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags = CF_STARTITEM; if((lval = LVAL(&smtp_act_var, ew)) != NULL){ for(i = 0; lval[i]; i++){ if(i) (void)new_confline(&ctmp); ctmp->var = &smtp_act_var; ctmp->varmem = i; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_usesmtp; ctmp->tool = t_tool; ctmp->varnamep = ctmpb; } } else ctmp->varmem = 0; /* NNTP Server Action */ new_confline(&ctmp); inick_confs[INICK_NNTP_CONF] = ctmp; ctmp->help_title= _("HELP FOR NNTP SERVER ACTION"); ctmp->var = &nntp_act_var; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_usenntp; ctmp->tool = t_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", roindent-3, roindent-3, nntp_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags = CF_STARTITEM; if((lval = LVAL(&nntp_act_var, ew)) != NULL){ for(i = 0; lval[i]; i++){ if(i) (void)new_confline(&ctmp); ctmp->var = &nntp_act_var; ctmp->varmem = i; ctmp->valoffset = roindent; ctmp->keymenu = &config_text_wshuf_keymenu; ctmp->help = h_config_role_usenntp; ctmp->tool = t_tool; ctmp->varnamep = ctmpb; } } else ctmp->varmem = 0; calculate_inick_stuff(ps); } else inick_confs[INICK_INICK_CONF] = NULL; if(edit_score){ int sindent; sindent = MAX(utf8_width(score_act_var.name),utf8_width(hdrtok_act_var.name)) + 3; /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Score Value -- This doesn't inherit from inick */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SCORE VALUE ACTION"); ctmp->var = &score_act_var; ctmp->valoffset = sindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_scoreval; ctmp->tool = text_tool; ctmp->flags |= CF_NUMBER; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", sindent-3, sindent-3, score_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); new_confline(&ctmp); ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(" OR"); /* Score From Header */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SCORE VALUE FROM HEADER ACTION"); ctmp->var = &hdrtok_act_var; ctmp->valoffset = sindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_role_scorehdrtok; ctmp->tool = text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", sindent-3, sindent-3, hdrtok_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); } if(edit_filter){ /* * Filtering got added in stages, so instead of simply having a * variable in action which is set to one of the three possible * values (FILTER_KILL, FILTER_STATE, FILTER_FOLDER) we infer * the value from other variables. (Perhaps it would still make * sense to change this.) * Action->kill is set iff the user checks Delete. * If the user checks the box that says Just Set State, then kill * is not set and action->folder is not set (and vice versa). * And finally, FILTER_FOLDER is set if !kill and action->folder is set. * (And it is set here as the default if there is no default * action and the user is required to fill in the Folder.) */ if(def && def->action && def->action->kill) fval = FILTER_KILL; else if(def && def->action && !def->action->kill && !def->action->folder) fval = FILTER_STATE; else fval = FILTER_FOLDER; role_filt_ptr = &filter_type_var; /* so radiobuttons can tell */ filter_type_var.name = cpystr(_("Filter Action")); filter_type_var.is_used = 1; filter_type_var.is_user = 1; apval = APVAL(&filter_type_var, ew); *apval = (f=filter_types(fval)) ? cpystr(f->name) : NULL; set_current_val(&filter_type_var, FALSE, FALSE); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Filter Type */ new_confline(&ctmp); ctmp->var = &filter_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", filter_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Choose One"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = filter_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); for(i = 0; (f = filter_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR FILTER ACTION"); ctmp->var = &filter_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_filt_rule_type; ctmp->varmem = i; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (f->value == fval) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Specific list of folders to copy to */ setup_dummy_pattern_var(&folder_act_var, _("Folder List"), (def && def->action) ? def->action->folder : NULL); /* 5 is the width of `(*) ' */ setup_role_pat_alt(ps, &ctmp, &folder_act_var, h_config_filter_folder, _("HELP FOR FILTER FOLDER NAME"), &config_role_actionfolder_keymenu, t_tool, rindent+5, !(fval == FILTER_FOLDER)); SETUP_MSG_STATE(ctmp, filt_imp_var, ival, _("HELP FOR SET IMPORTANT STATUS"), h_config_filt_stat_imp); SETUP_MSG_STATE(ctmp, filt_new_var, nval, _("HELP FOR SET NEW STATUS"), h_config_filt_stat_new); SETUP_MSG_STATE(ctmp, filt_del_var, dval, _("HELP FOR SET DELETED STATUS"), h_config_filt_stat_del); SETUP_MSG_STATE(ctmp, filt_ans_var, aval, _("HELP FOR SET ANSWERED STATUS"), h_config_filt_stat_ans); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Keywords to be Set */ setup_dummy_pattern_var(&keyword_set_var, _("Set These Keywords"), (def && def->action) ? def->action->keyword_set : NULL); setup_role_pat(ps, &ctmp, &keyword_set_var, h_config_filter_kw_set, _("HELP FOR KEYWORDS TO BE SET"), &config_role_keyword_keymenu, role_text_tool_kword, NULL, 23); /* Keywords to be Cleared */ setup_dummy_pattern_var(&keyword_clr_var, _("Clear These Keywords"), (def && def->action) ? def->action->keyword_clr : NULL); setup_role_pat(ps, &ctmp, &keyword_clr_var, h_config_filter_kw_clr, _("HELP FOR KEYWORDS TO BE CLEARED"), &config_role_keyword_keymenu, role_text_tool_kword, NULL, 23); } if(edit_other){ char *pval; int oindent; /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp)->var = NULL; snprintf(tmp, sizeof(tmp), "%s =", sort_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->flags |= CF_NOSELECT; new_confline(&ctmp)->var = NULL; ctmp->varnamep = ctmpb; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Sort Options"); new_confline(&ctmp)->var = NULL; ctmp->varnamep = ctmpb; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ pval = PVAL(&sort_act_var, ew); if(pval) decode_sort(pval, &def_sort, &def_sort_rev); /* allow user to set their default sort order */ new_confline(&ctmp)->var = &sort_act_var; ctmp->varnamep = ctmpb; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_perfolder_sort; ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->varmem = -1; ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0); for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ new_confline(&ctmp)->var = &sort_act_var; ctmp->varnamep = ctmpb; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_perfolder_sort; ctmp->tool = role_sort_tool; ctmp->valoffset = rindent; ctmp->varmem = i + (j * EndofList); ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0); } } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; oindent = utf8_width(iform_act_var.name) + 3; /* Index Format Action */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SET INDEX FORMAT ACTION"); ctmp->var = &iform_act_var; ctmp->valoffset = oindent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_set_index_format; ctmp->tool = text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", oindent-3, oindent-3, iform_act_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->flags |= CF_STARTITEM; utf8_snprintf(tmp, sizeof(tmp), "%s =", startup_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); standard_radio_setup(ps, &ctmp, &startup_var, NULL); } if(edit_incol && pico_usingcolor()){ char *pval0, *pval1; int def; /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->var = &rolecolor_vars[0]; /* foreground */ ctmp->varname = cpystr(_("Index Line Color =")); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_STARTITEM | CF_NOSELECT); ctmp->keymenu = &role_color_setting_keymenu; pval0 = PVAL(&rolecolor_vars[0], ew); pval1 = PVAL(&rolecolor_vars[1], ew); if(pval0 && pval1) def = !(pval0[0] && pval1[1]); else def = 1; add_color_setting_disp(ps, &ctmp, &rolecolor_vars[0], ctmpb, &role_color_setting_keymenu, &config_checkbox_keymenu, h_config_incol, rindent, 0, def ? ps->VAR_NORM_FORE_COLOR : PVAL(&rolecolor_vars[0], ew), def ? ps->VAR_NORM_BACK_COLOR : PVAL(&rolecolor_vars[1], ew), def); } } if(need_options){ /* Options */ /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->flags |= CF_NOSELECT; if(ps->ttyo->screen_cols >= (wid=utf8_width(ostr)) + 4){ int dashes; dashes = (ps->ttyo->screen_cols - wid)/2; snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s", repeat_char(dashes, '='), ostr, repeat_char(ps->ttyo->screen_cols-wid-dashes, '=')); ctmp->value = cpystr(tmp_20k_buf); } else ctmp->value = cpystr(repeat_char(ps->ttyo->screen_cols, '=')); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; opt_var.name = cpystr(_("Features")); opt_var.is_used = 1; opt_var.is_user = 1; opt_var.is_list = 1; clrbitmap(feat_option_list); if(def && def->patgrp && def->patgrp->age_uses_sentdate) setbitn(FEAT_SENTDATE, feat_option_list); if(edit_filter){ if(def && def->action && def->action->move_only_if_not_deleted) setbitn(FEAT_IFNOTDEL, feat_option_list); if(def && def->action && def->action->non_terminating) setbitn(FEAT_NONTERM, feat_option_list); } /* Options */ new_confline(&ctmp); ctmp->var = &opt_var; ctmp->valoffset = 23; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%-20s =", opt_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = feat_checkbox_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Feature Name"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = feat_checkbox_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = feat_feature_list(i)); i++){ if(!edit_filter && (i == FEAT_IFNOTDEL || i == FEAT_NONTERM)) continue; if(lv < (j = utf8_width(f->name))) lv = j; } lv = MIN(lv, 100); for(i = 0; (f = feat_feature_list(i)); i++){ if(!edit_filter && (i == FEAT_IFNOTDEL || i == FEAT_NONTERM)) continue; new_confline(&ctmp); ctmp->var = &opt_var; ctmp->help_title= _("HELP FOR FILTER FEATURES"); ctmp->varnamep = ctmpb; ctmp->keymenu = &config_checkbox_keymenu; switch(i){ case FEAT_SENTDATE: ctmp->help = h_config_filt_opts_sentdate; break; case FEAT_IFNOTDEL: ctmp->help = h_config_filt_opts_notdel; break; case FEAT_NONTERM: ctmp->help = h_config_filt_opts_nonterm; break; } ctmp->tool = feat_checkbox_tool; ctmp->valoffset = rindent; ctmp->varmem = i; utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w", bitnset(f->value, feat_option_list) ? 'X' : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } } if(need_uses){ /* Uses */ /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmp); ctmp->flags |= CF_NOSELECT; if(ps->ttyo->screen_cols >= (wid=utf8_width(ustr)) + 4){ int dashes; dashes = (ps->ttyo->screen_cols - wid)/2; snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s", repeat_char(dashes, '='), ustr, repeat_char(ps->ttyo->screen_cols-wid-dashes, '=')); ctmp->value = cpystr(tmp_20k_buf); } else ctmp->value = cpystr(repeat_char(ps->ttyo->screen_cols, '=')); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Reply Type */ new_confline(&ctmp); ctmp->var = &repl_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", repl_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Choose One"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = role_repl_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); for(i = 0; (f = role_repl_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR ROLE REPLY USE"); ctmp->var = &repl_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_role_replyuse; ctmp->varmem = i; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!(def && def->action) || def->action->repl_type == -1) && f->value == ROLE_REPL_DEFL) || (def && def->action && f->value == def->action->repl_type)) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Forward Type */ new_confline(&ctmp); ctmp->var = &forw_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", forw_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Choose One"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = role_forw_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); for(i = 0; (f = role_forw_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR ROLE FORWARD USE"); ctmp->var = &forw_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_role_forwarduse; ctmp->varmem = i; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!(def && def->action) || def->action->forw_type == -1) && f->value == ROLE_FORW_DEFL) || (def && def->action && f->value == def->action->forw_type)) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Compose Type */ new_confline(&ctmp); ctmp->var = &comp_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", comp_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Choose One"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); \ /* find longest value's name */ for(lv = 0, i = 0; (f = role_comp_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); for(i = 0; (f = role_comp_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR ROLE COMPOSE USE"); ctmp->var = &comp_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_role_composeuse; ctmp->varmem = i; ctmp->tool = radio_tool; ctmp->varnamep = ctmpb; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!(def && def->action) || def->action->comp_type == -1) && f->value == ROLE_COMP_DEFL) || (def && def->action && f->value == def->action->comp_type)) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } } memset(&screen, 0, sizeof(screen)); screen.ro_warning = saved_screen ? saved_screen->deferred_ro_warning : 0; /* TRANSLATORS: Print something1 using something2. "roles" is something1 */ rv = conf_scroll_screen(ps, &screen, first_line, title, _("roles"), (edit_incol && pico_usingcolor()) ? 1 : 0, NULL); /* * Now look at the fake variables and extract the information we * want from them. */ if(rv == 1 && result){ /* * We know these variables exist, so we don't have to check that * apval is nonnull before evaluating *apval. */ apval = APVAL(&nick_var, ew); nick = *apval; *apval = NULL; removing_leading_and_trailing_white_space(nick); apval = APVAL(&comment_var, ew); comment = *apval; *apval = NULL; removing_leading_and_trailing_white_space(comment); alval = ALVAL(&to_pat_var, ew); to_pat = *alval; *alval = NULL; alval = ALVAL(&from_pat_var, ew); from_pat = *alval; *alval = NULL; alval = ALVAL(&sender_pat_var, ew); sender_pat = *alval; *alval = NULL; alval = ALVAL(&cc_pat_var, ew); cc_pat = *alval; *alval = NULL; alval = ALVAL(&recip_pat_var, ew); recip_pat = *alval; *alval = NULL; alval = ALVAL(&partic_pat_var, ew); partic_pat = *alval; *alval = NULL; alval = ALVAL(&news_pat_var, ew); news_pat = *alval; *alval = NULL; alval = ALVAL(&subj_pat_var, ew); subj_pat = *alval; *alval = NULL; alval = ALVAL(&alltext_pat_var, ew); alltext_pat = *alval; *alval = NULL; alval = ALVAL(&bodytext_pat_var, ew); bodytext_pat = *alval; *alval = NULL; alval = ALVAL(&keyword_pat_var, ew); keyword_pat = *alval; *alval = NULL; alval = ALVAL(&charset_pat_var, ew); charset_pat = *alval; *alval = NULL; apval = APVAL(&age_pat_var, ew); age_pat = *apval; *apval = NULL; removing_leading_and_trailing_white_space(age_pat); apval = APVAL(&size_pat_var, ew); size_pat = *apval; *apval = NULL; removing_leading_and_trailing_white_space(size_pat); apval = APVAL(&scorei_pat_var, ew); scorei_pat = *apval; *apval = NULL; removing_leading_and_trailing_white_space(scorei_pat); apval = APVAL(&stat_del_var, ew); stat_del = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_del); apval = APVAL(&stat_new_var, ew); stat_new = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_new); apval = APVAL(&stat_rec_var, ew); stat_rec = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_rec); apval = APVAL(&stat_imp_var, ew); stat_imp = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_imp); apval = APVAL(&stat_ans_var, ew); stat_ans = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_ans); apval = APVAL(&stat_8bit_var, ew); stat_8bit = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_8bit); apval = APVAL(&stat_bom_var, ew); stat_bom = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_bom); apval = APVAL(&stat_boy_var, ew); stat_boy = *apval; *apval = NULL; removing_leading_and_trailing_white_space(stat_boy); apval = APVAL(&fldr_type_var, ew); fldr_type_pat = *apval; *apval = NULL; removing_leading_and_trailing_white_space(fldr_type_pat); alval = ALVAL(&folder_pat_var, ew); folder_pat = *alval; *alval = NULL; apval = APVAL(&abook_type_var, ew); abook_type_pat = *apval; *apval = NULL; removing_leading_and_trailing_white_space(abook_type_pat); alval = ALVAL(&abook_pat_var, ew); abook_pat = *alval; *alval = NULL; apval = APVAL(&cati_var, ew); cati = *apval; *apval = NULL; removing_leading_and_trailing_white_space(cati); apval = APVAL(&cat_lim_var, ew); cat_lim = *apval; *apval = NULL; removing_leading_and_trailing_white_space(cat_lim); apval = APVAL(&inick_var, ew); inick = *apval; *apval = NULL; removing_leading_and_trailing_white_space(inick); apval = APVAL(&from_act_var, ew); from_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(from_act); apval = APVAL(&replyto_act_var, ew); replyto_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(replyto_act); apval = APVAL(&fcc_act_var, ew); fcc_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(fcc_act); apval = APVAL(&litsig_act_var, ew); litsig_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(litsig_act); apval = APVAL(&sort_act_var, ew); sort_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(sort_act); apval = APVAL(&iform_act_var, ew); iform_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(iform_act); apval = APVAL(&startup_var, ew); startup_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(startup_act); apval = APVAL(&sig_act_var, ew); sig_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(sig_act); apval = APVAL(&templ_act_var, ew); templ_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(templ_act); apval = APVAL(&score_act_var, ew); score_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(score_act); apval = APVAL(&hdrtok_act_var, ew); hdrtok_act = *apval; *apval = NULL; removing_leading_and_trailing_white_space(hdrtok_act); apval = APVAL(&repl_type_var, ew); repl_type = *apval; *apval = NULL; removing_leading_and_trailing_white_space(repl_type); apval = APVAL(&forw_type_var, ew); forw_type = *apval; *apval = NULL; removing_leading_and_trailing_white_space(forw_type); apval = APVAL(&comp_type_var, ew); comp_type = *apval; *apval = NULL; removing_leading_and_trailing_white_space(comp_type); apval = APVAL(&rolecolor_vars[0], ew); rc_fg = *apval; *apval = NULL; removing_leading_and_trailing_white_space(rc_fg); apval = APVAL(&rolecolor_vars[1], ew); rc_bg = *apval; *apval = NULL; removing_leading_and_trailing_white_space(rc_bg); apval = APVAL(&filter_type_var, ew); filter_type = *apval; *apval = NULL; removing_leading_and_trailing_white_space(filter_type); alval = ALVAL(&folder_act_var, ew); folder_act = *alval; *alval = NULL; alval = ALVAL(&keyword_set_var, ew); keyword_set = *alval; *alval = NULL; alval = ALVAL(&keyword_clr_var, ew); keyword_clr = *alval; *alval = NULL; apval = APVAL(&filt_imp_var, ew); filt_imp = *apval; *apval = NULL; removing_leading_and_trailing_white_space(filt_imp); apval = APVAL(&filt_del_var, ew); filt_del = *apval; *apval = NULL; removing_leading_and_trailing_white_space(filt_del); apval = APVAL(&filt_new_var, ew); filt_new = *apval; *apval = NULL; removing_leading_and_trailing_white_space(filt_new); apval = APVAL(&filt_ans_var, ew); filt_ans = *apval; *apval = NULL; removing_leading_and_trailing_white_space(filt_ans); alval = ALVAL(&cat_cmd_var, ew); cat_cmd = *alval; *alval = NULL; alval = ALVAL(&cstm_act_var, ew); cstm_act = *alval; *alval = NULL; alval = ALVAL(&smtp_act_var, ew); smtp_act = *alval; *alval = NULL; alval = ALVAL(&nntp_act_var, ew); nntp_act = *alval; *alval = NULL; if(ps->VAR_OPER_DIR && sig_act && is_absolute_path(sig_act) && !in_dir(ps->VAR_OPER_DIR, sig_act)){ q_status_message1(SM_ORDER | SM_DING, 3, 4, _("Warning: Sig file can't be outside of %s"), ps->VAR_OPER_DIR); } if(ps->VAR_OPER_DIR && templ_act && is_absolute_path(templ_act) && !in_dir(ps->VAR_OPER_DIR, templ_act)){ q_status_message1(SM_ORDER | SM_DING, 3, 4, _("Warning: Template file can't be outside of %s"), ps->VAR_OPER_DIR); } if(ps->VAR_OPER_DIR && folder_act) for(i = 0; folder_act[i]; i++){ if(folder_act[i][0] && is_absolute_path(folder_act[i]) && !in_dir(ps->VAR_OPER_DIR, folder_act[i])){ q_status_message1(SM_ORDER | SM_DING, 3, 4, _("Warning: Folder can't be outside of %s"), ps->VAR_OPER_DIR); } } *result = (PAT_S *)fs_get(sizeof(**result)); memset((void *)(*result), 0, sizeof(**result)); (*result)->patgrp = (PATGRP_S *)fs_get(sizeof(*(*result)->patgrp)); memset((void *)(*result)->patgrp, 0, sizeof(*(*result)->patgrp)); (*result)->action = (ACTION_S *)fs_get(sizeof(*(*result)->action)); memset((void *)(*result)->action, 0, sizeof(*(*result)->action)); (*result)->patline = def ? def->patline : NULL; if(nick && *nick){ (*result)->patgrp->nick = nick; nick = NULL; } else (*result)->patgrp->nick = cpystr(nick_var.global_val.p); if(comment && *comment){ (*result)->patgrp->comment = comment; comment = NULL; } (*result)->action->nick = cpystr((*result)->patgrp->nick); (*result)->action->is_a_role = edit_role ? 1 : 0; (*result)->action->is_a_incol = edit_incol ? 1 : 0; (*result)->action->is_a_score = edit_score ? 1 : 0; (*result)->action->is_a_filter = edit_filter ? 1 : 0; (*result)->action->is_a_other = edit_other ? 1 : 0; (*result)->action->is_a_srch = edit_srch ? 1 : 0; (*result)->patgrp->to = editlist_to_pattern(to_pat); if((*result)->patgrp->to && !strncmp(to_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->to->not = 1; (*result)->patgrp->from = editlist_to_pattern(from_pat); if((*result)->patgrp->from && !strncmp(from_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->from->not = 1; (*result)->patgrp->sender = editlist_to_pattern(sender_pat); if((*result)->patgrp->sender && !strncmp(sender_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->sender->not = 1; (*result)->patgrp->cc = editlist_to_pattern(cc_pat); if((*result)->patgrp->cc && !strncmp(cc_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->cc->not = 1; (*result)->patgrp->recip = editlist_to_pattern(recip_pat); if((*result)->patgrp->recip && !strncmp(recip_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->recip->not = 1; (*result)->patgrp->partic = editlist_to_pattern(partic_pat); if((*result)->patgrp->partic && !strncmp(partic_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->partic->not = 1; (*result)->patgrp->news = editlist_to_pattern(news_pat); if((*result)->patgrp->news && !strncmp(news_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->news->not = 1; (*result)->patgrp->subj = editlist_to_pattern(subj_pat); if((*result)->patgrp->subj && !strncmp(subj_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->subj->not = 1; (*result)->patgrp->alltext = editlist_to_pattern(alltext_pat); if((*result)->patgrp->alltext && !strncmp(alltext_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->alltext->not = 1; (*result)->patgrp->bodytext = editlist_to_pattern(bodytext_pat); if((*result)->patgrp->bodytext && !strncmp(bodytext_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->bodytext->not = 1; (*result)->patgrp->keyword = editlist_to_pattern(keyword_pat); if((*result)->patgrp->keyword && !strncmp(keyword_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->keyword->not = 1; (*result)->patgrp->charsets = editlist_to_pattern(charset_pat); if((*result)->patgrp->charsets && !strncmp(charset_pat_var.name, NOT, NOTLEN)) (*result)->patgrp->charsets->not = 1; (*result)->patgrp->age_uses_sentdate = bitnset(FEAT_SENTDATE, feat_option_list) ? 1 : 0; if(age_pat){ if(((*result)->patgrp->age = parse_intvl(age_pat)) != NULL) (*result)->patgrp->do_age = 1; } if(size_pat){ if(((*result)->patgrp->size = parse_intvl(size_pat)) != NULL) (*result)->patgrp->do_size = 1; } if(scorei_pat){ if(((*result)->patgrp->score = parse_intvl(scorei_pat)) != NULL) (*result)->patgrp->do_score = 1; } (*result)->patgrp->cat_lim = -1L; /* default */ if(cat_cmd){ if(!cat_cmd[0]) fs_give((void **) &cat_cmd); /* quick check for absolute paths */ if(cat_cmd) for(j = 0; cat_cmd[j]; j++) if(!is_absolute_path(cat_cmd[j])) q_status_message1(SM_ORDER | SM_DING, 3, 4, _("Warning: command must be absolute path: \"%s\""), cat_cmd[j]); (*result)->patgrp->category_cmd = cat_cmd; cat_cmd = NULL; if(cati){ if(((*result)->patgrp->cat = parse_intvl(cati)) != NULL) (*result)->patgrp->do_cat = 1; } if(cat_lim && *cat_lim) (*result)->patgrp->cat_lim = atol(cat_lim); } if(stat_del && *stat_del){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_del, f->name)){ (*result)->patgrp->stat_del = f->value; break; } } else (*result)->patgrp->stat_del = PAT_STAT_EITHER; if(stat_new && *stat_new){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_new, f->name)){ (*result)->patgrp->stat_new = f->value; break; } } else (*result)->patgrp->stat_new = PAT_STAT_EITHER; if(stat_rec && *stat_rec){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_rec, f->name)){ (*result)->patgrp->stat_rec = f->value; break; } } else (*result)->patgrp->stat_rec = PAT_STAT_EITHER; if(stat_imp && *stat_imp){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_imp, f->name)){ (*result)->patgrp->stat_imp = f->value; break; } } else (*result)->patgrp->stat_imp = PAT_STAT_EITHER; if(stat_ans && *stat_ans){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_ans, f->name)){ (*result)->patgrp->stat_ans = f->value; break; } } else (*result)->patgrp->stat_ans = PAT_STAT_EITHER; if(stat_8bit && *stat_8bit){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_8bit, f->name)){ (*result)->patgrp->stat_8bitsubj = f->value; break; } } else (*result)->patgrp->stat_8bitsubj = PAT_STAT_EITHER; if(stat_bom && *stat_bom){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_bom, f->name)){ (*result)->patgrp->stat_bom = f->value; break; } } else (*result)->patgrp->stat_bom = PAT_STAT_EITHER; if(stat_boy && *stat_boy){ for(j = 0; (f = role_status_types(j)); j++) if(!strucmp(stat_boy, f->name)){ (*result)->patgrp->stat_boy = f->value; break; } } else (*result)->patgrp->stat_boy = PAT_STAT_EITHER; if(sort_act){ decode_sort(sort_act, &def_sort, &def_sort_rev); (*result)->action->sort_is_set = 1; (*result)->action->sortorder = def_sort; (*result)->action->revsort = (def_sort_rev ? 1 : 0); /* * Don't try to re-sort until next open of folder. If user * $-sorted then it probably shouldn't change anyway. Why * bother keeping track of that? */ } (*result)->action->index_format = iform_act; iform_act = NULL; if(startup_act && *startup_act){ for(j = 0; (f = startup_rules(j)); j++) if(!strucmp(startup_act, f->name)){ (*result)->action->startup_rule = f->value; break; } } else (*result)->action->startup_rule = IS_NOTSET; aa = NULL; for(ea = earb; ea; ea = ea->next){ char *xyz; if(aa){ aa->next = (ARBHDR_S *)fs_get(sizeof(*aa)); aa = aa->next; } else{ (*result)->patgrp->arbhdr = (ARBHDR_S *)fs_get(sizeof(ARBHDR_S)); aa = (*result)->patgrp->arbhdr; } memset(aa, 0, sizeof(*aa)); aa->field = cpystr((ea->a && ea->a->field) ? ea->a->field : ""); alval = ALVAL(ea->v, ew); spat = *alval; *alval = NULL; aa->p = editlist_to_pattern(spat); if(aa->p && ea->v && ea->v->name && !strncmp(ea->v->name, NOT, NOTLEN)) aa->p->not = 1; if((xyz = pattern_to_string(aa->p)) != NULL){ if(!*xyz) aa->isemptyval = 1; fs_give((void **)&xyz); } } if(fldr_type_pat && *fldr_type_pat){ for(j = 0; (f = pat_fldr_types(j)); j++) if(!strucmp(fldr_type_pat, f->name)){ (*result)->patgrp->fldr_type = f->value; break; } } else{ f = pat_fldr_types(FLDR_DEFL); if(f) (*result)->patgrp->fldr_type = f->value; } (*result)->patgrp->folder = editlist_to_pattern(folder_pat); if(abook_type_pat && *abook_type_pat){ for(j = 0; (f = inabook_fldr_types(j)); j++){ if(!strucmp(abook_type_pat, f->name)){ (*result)->patgrp->inabook = f->value; break; } } if(bitnset(INABOOK_FROM, inabook_type_list)) (*result)->patgrp->inabook |= IAB_FROM; if(bitnset(INABOOK_REPLYTO, inabook_type_list)) (*result)->patgrp->inabook |= IAB_REPLYTO; if(bitnset(INABOOK_SENDER, inabook_type_list)) (*result)->patgrp->inabook |= IAB_SENDER; if(bitnset(INABOOK_TO, inabook_type_list)) (*result)->patgrp->inabook |= IAB_TO; if(bitnset(INABOOK_CC, inabook_type_list)) (*result)->patgrp->inabook |= IAB_CC; if(!((*result)->patgrp->inabook & IAB_TYPE_MASK)) (*result)->patgrp->inabook |= (IAB_FROM | IAB_REPLYTO); } else{ f = inabook_fldr_types(IAB_DEFL); if(f) (*result)->patgrp->inabook = f->value; } (*result)->patgrp->abooks = editlist_to_pattern(abook_pat); (*result)->action->inherit_nick = inick; inick = NULL; (*result)->action->fcc = fcc_act; fcc_act = NULL; (*result)->action->litsig = litsig_act; litsig_act = NULL; (*result)->action->sig = sig_act; sig_act = NULL; (*result)->action->template = templ_act; templ_act = NULL; if(cstm_act){ /* * Check for From or Reply-To and eliminate them. */ for(i = 0; cstm_act[i]; i++){ char *free_this; if((!struncmp(cstm_act[i],"from",4) && (cstm_act[i][4] == ':' || cstm_act[i][4] == '\0')) || (!struncmp(cstm_act[i],"reply-to",8) && (cstm_act[i][8] == ':' || cstm_act[i][8] == '\0'))){ free_this = cstm_act[i]; /* slide the rest up */ for(j = i; cstm_act[j]; j++) cstm_act[j] = cstm_act[j+1]; fs_give((void **)&free_this); i--; /* recheck now that we've slid them up */ } } /* nothing left */ if(!cstm_act[0]) fs_give((void **)&cstm_act); (*result)->action->cstm = cstm_act; cstm_act = NULL; } if(smtp_act){ if(!smtp_act[0]) fs_give((void **)&smtp_act); (*result)->action->smtp = smtp_act; smtp_act = NULL; } if(nntp_act){ if(!nntp_act[0]) fs_give((void **)&nntp_act); (*result)->action->nntp = nntp_act; nntp_act = NULL; } if(filter_type && *filter_type){ (*result)->action->non_terminating = bitnset(FEAT_NONTERM, feat_option_list) ? 1 : 0; for(i = 0; (f = filter_types(i)); i++){ if(!strucmp(filter_type, f->name)){ if(f->value == FILTER_FOLDER){ (*result)->action->folder = editlist_to_pattern(folder_act); (*result)->action->move_only_if_not_deleted = bitnset(FEAT_IFNOTDEL, feat_option_list) ? 1 : 0; } else if(f->value == FILTER_STATE){ (*result)->action->kill = 0; } else if(f->value == FILTER_KILL){ (*result)->action->kill = 1; } /* * This is indented an extra indent because we used to condition * this on !kill. We changed it so that you can set state bits * even if you're killing. This is marginally helpful if you * have another client running that doesn't know about this * filter, but you want to, for example, have the messages show * up now as deleted instead of having that deferred until we * exit. It is controlled by the user by setting the status * action bits along with the Delete. */ if(filt_imp && *filt_imp){ for(j = 0; (f = msg_state_types(j)); j++){ if(!strucmp(filt_imp, f->name)){ switch(f->value){ case ACT_STAT_LEAVE: break; case ACT_STAT_SET: (*result)->action->state_setting_bits |= F_FLAG; break; case ACT_STAT_CLEAR: (*result)->action->state_setting_bits |= F_UNFLAG; break; } break; } } } if(filt_del && *filt_del){ for(j = 0; (f = msg_state_types(j)); j++){ if(!strucmp(filt_del, f->name)){ switch(f->value){ case ACT_STAT_LEAVE: break; case ACT_STAT_SET: (*result)->action->state_setting_bits |= F_DEL; break; case ACT_STAT_CLEAR: (*result)->action->state_setting_bits |= F_UNDEL; break; } break; } } } if(filt_ans && *filt_ans){ for(j = 0; (f = msg_state_types(j)); j++){ if(!strucmp(filt_ans, f->name)){ switch(f->value){ case ACT_STAT_LEAVE: break; case ACT_STAT_SET: (*result)->action->state_setting_bits |= F_ANS; break; case ACT_STAT_CLEAR: (*result)->action->state_setting_bits |= F_UNANS; break; } break; } } } if(filt_new && *filt_new){ for(j = 0; (f = msg_state_types(j)); j++){ if(!strucmp(filt_new, f->name)){ switch(f->value){ case ACT_STAT_LEAVE: break; case ACT_STAT_SET: (*result)->action->state_setting_bits |= F_UNSEEN; break; case ACT_STAT_CLEAR: (*result)->action->state_setting_bits |= F_SEEN; break; } break; } } } (*result)->action->keyword_set = editlist_to_pattern(keyword_set); (*result)->action->keyword_clr = editlist_to_pattern(keyword_clr); break; } } } if(from_act && *from_act) rfc822_parse_adrlist(&(*result)->action->from, from_act, ps->maildomain); if(replyto_act && *replyto_act) rfc822_parse_adrlist(&(*result)->action->replyto, replyto_act, ps->maildomain); if(score_act && (j = atoi(score_act)) >= SCORE_MIN && j <= SCORE_MAX) (*result)->action->scoreval = (long) j; if(hdrtok_act) (*result)->action->scorevalhdrtok = stringform_to_hdrtok(hdrtok_act); if(repl_type && *repl_type){ for(j = 0; (f = role_repl_types(j)); j++) if(!strucmp(repl_type, f->name)){ (*result)->action->repl_type = f->value; break; } } else{ f = role_repl_types(ROLE_REPL_DEFL); if(f) (*result)->action->repl_type = f->value; } if(forw_type && *forw_type){ for(j = 0; (f = role_forw_types(j)); j++) if(!strucmp(forw_type, f->name)){ (*result)->action->forw_type = f->value; break; } } else{ f = role_forw_types(ROLE_FORW_DEFL); if(f) (*result)->action->forw_type = f->value; } if(comp_type && *comp_type){ for(j = 0; (f = role_comp_types(j)); j++) if(!strucmp(comp_type, f->name)){ (*result)->action->comp_type = f->value; break; } } else{ f = role_comp_types(ROLE_COMP_DEFL); if(f) (*result)->action->comp_type = f->value; } if(rc_fg && *rc_fg && rc_bg && *rc_bg){ if(!old_fg || !old_bg || strucmp(old_fg, rc_fg) || strucmp(old_bg, rc_bg)) clear_index_cache(ps_global->mail_stream, 0); /* * If same as normal color, don't set it. This may or may * not surprise the user when they change the normal color. * This color will track the normal color instead of staying * the same as the old normal color, which is probably * what they want. */ if(!ps_global->VAR_NORM_FORE_COLOR || !ps_global->VAR_NORM_BACK_COLOR || strucmp(ps_global->VAR_NORM_FORE_COLOR, rc_fg) || strucmp(ps_global->VAR_NORM_BACK_COLOR, rc_bg)) (*result)->action->incol = new_color_pair(rc_fg, rc_bg); } } for(j = 0; varlist[j]; j++){ v = varlist[j]; free_variable_values(v); if(v->name) fs_give((void **)&v->name); } if(earb) free_earb(&earb); if(nick) fs_give((void **)&nick); if(comment) fs_give((void **)&comment); if(to_pat) free_list_array(&to_pat); if(from_pat) free_list_array(&from_pat); if(sender_pat) free_list_array(&sender_pat); if(cc_pat) free_list_array(&cc_pat); if(recip_pat) free_list_array(&recip_pat); if(partic_pat) free_list_array(&partic_pat); if(news_pat) free_list_array(&news_pat); if(subj_pat) free_list_array(&subj_pat); if(alltext_pat) free_list_array(&alltext_pat); if(bodytext_pat) free_list_array(&bodytext_pat); if(keyword_pat) free_list_array(&keyword_pat); if(charset_pat) free_list_array(&charset_pat); if(age_pat) fs_give((void **)&age_pat); if(size_pat) fs_give((void **)&size_pat); if(scorei_pat) fs_give((void **)&scorei_pat); if(cati) fs_give((void **)&cati); if(cat_lim) fs_give((void **)&cat_lim); if(stat_del) fs_give((void **)&stat_del); if(stat_new) fs_give((void **)&stat_new); if(stat_rec) fs_give((void **)&stat_rec); if(stat_imp) fs_give((void **)&stat_imp); if(stat_ans) fs_give((void **)&stat_ans); if(stat_8bit) fs_give((void **)&stat_8bit); if(stat_bom) fs_give((void **)&stat_bom); if(stat_boy) fs_give((void **)&stat_boy); if(fldr_type_pat) fs_give((void **)&fldr_type_pat); if(folder_pat) free_list_array(&folder_pat); if(abook_type_pat) fs_give((void **)&abook_type_pat); if(abook_pat) free_list_array(&abook_pat); if(inick) fs_give((void **)&inick); if(from_act) fs_give((void **)&from_act); if(replyto_act) fs_give((void **)&replyto_act); if(fcc_act) fs_give((void **)&fcc_act); if(litsig_act) fs_give((void **)&litsig_act); if(sort_act) fs_give((void **)&sort_act); if(iform_act) fs_give((void **)&iform_act); if(keyword_set) free_list_array(&keyword_set); if(keyword_clr) free_list_array(&keyword_clr); if(startup_act) fs_give((void **)&startup_act); if(sig_act) fs_give((void **)&sig_act); if(templ_act) fs_give((void **)&templ_act); if(score_act) fs_give((void **)&score_act); if(hdrtok_act) fs_give((void **)&hdrtok_act); if(repl_type) fs_give((void **)&repl_type); if(forw_type) fs_give((void **)&forw_type); if(comp_type) fs_give((void **)&comp_type); if(rc_fg) fs_give((void **)&rc_fg); if(rc_bg) fs_give((void **)&rc_bg); if(old_fg) fs_give((void **)&old_fg); if(old_bg) fs_give((void **)&old_bg); if(filt_del) fs_give((void **)&filt_del); if(filt_new) fs_give((void **)&filt_new); if(filt_ans) fs_give((void **)&filt_ans); if(filt_imp) fs_give((void **)&filt_imp); if(folder_act) free_list_array(&folder_act); if(filter_type) fs_give((void **)&filter_type); if(cat_cmd) free_list_array(&cat_cmd); if(cstm_act) free_list_array(&cstm_act); if(smtp_act) free_list_array(&smtp_act); if(nntp_act) free_list_array(&nntp_act); opt_screen = saved_screen; ps->mangled_screen = 1; return(rv); } void setup_dummy_pattern_var(struct variable *v, char *name, PATTERN_S *defpat) { char ***alval; if(!(v && name)) alpine_panic("setup_dummy_pattern_var"); v->name = (char *) fs_get(strlen(name)+NOTLEN+1); snprintf(v->name, strlen(name)+NOTLEN+1, "%s%s", (defpat && defpat->not) ? NOT : "", name); v->name[ strlen(name)+NOTLEN+1-1] = '\0'; v->is_used = 1; v->is_user = 1; v->is_list = 1; alval = ALVAL(v, ew); *alval = pattern_to_editlist(defpat); set_current_val(v, FALSE, FALSE); } void setup_role_pat(struct pine *ps, CONF_S **ctmp, struct variable *v, HelpType help, char *help_title, struct key_menu *keymenu, int (*tool)(struct pine *, int, CONF_S **, unsigned), EARB_S **earb, int indent) { char tmp[MAXPATH+1]; char **lval; int i; CONF_S *ctmpb; new_confline(ctmp); (*ctmp)->help_title = help_title; (*ctmp)->var = v; (*ctmp)->valoffset = indent; (*ctmp)->keymenu = keymenu; (*ctmp)->help = help; (*ctmp)->tool = tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3, indent-3, (v && v->name) ? v->name : ""); tmp[sizeof(tmp)-1] = '\0'; (*ctmp)->varname = cpystr(tmp); (*ctmp)->varnamep = *ctmp; (*ctmp)->value = pretty_value(ps, *ctmp); (*ctmp)->d.earb = earb; (*ctmp)->varmem = 0; (*ctmp)->flags = CF_STARTITEM; ctmpb = (*ctmp); lval = LVAL(v, ew); if(lval){ for(i = 0; lval[i]; i++){ if(i) new_confline(ctmp); (*ctmp)->var = v; (*ctmp)->varmem = i; (*ctmp)->valoffset = indent; (*ctmp)->value = pretty_value(ps, *ctmp); (*ctmp)->d.earb = earb; (*ctmp)->keymenu = keymenu; (*ctmp)->help = help; (*ctmp)->tool = tool; (*ctmp)->varnamep = ctmpb; } } } /* * Watch out for polarity of nosel flag. Setting it means to turn on * the NOSELECT flag, which means to make that line unselectable. */ void setup_role_pat_alt(struct pine *ps, CONF_S **ctmp, struct variable *v, HelpType help, char *help_title, struct key_menu *keymenu, int (*tool)(struct pine *, int, CONF_S **, unsigned), int voff, int nosel) { char tmp[MAXPATH+1]; char **lval; int i, j, k; CONF_S *ctmpb; new_confline(ctmp); (*ctmp)->help_title = help_title; (*ctmp)->var = v; (*ctmp)->varoffset = voff; k = utf8_width(v->name); j = voff+k+3; (*ctmp)->valoffset = j; (*ctmp)->keymenu = keymenu; (*ctmp)->help = help; (*ctmp)->tool = tool; utf8_snprintf(tmp, sizeof(tmp), "%*.*w =", k, k, v->name); tmp[sizeof(tmp)-1] = '\0'; (*ctmp)->varname = cpystr(tmp); (*ctmp)->varnamep = *ctmp; (*ctmp)->value = pretty_value(ps, *ctmp); (*ctmp)->varmem = 0; (*ctmp)->flags = (nosel ? CF_NOSELECT : 0); ctmpb = (*ctmp); lval = LVAL(v, ew); if(lval){ for(i = 0; lval[i]; i++){ if(i) new_confline(ctmp); (*ctmp)->var = v; (*ctmp)->varmem = i; (*ctmp)->varoffset = voff; (*ctmp)->valoffset = j; (*ctmp)->value = pretty_value(ps, *ctmp); (*ctmp)->keymenu = keymenu; (*ctmp)->help = help; (*ctmp)->tool = tool; (*ctmp)->varnamep = ctmpb; (*ctmp)->flags = (nosel ? CF_NOSELECT : 0); } } } void free_earb(EARB_S **ea) { if(ea && *ea){ free_earb(&(*ea)->next); if((*ea)->v){ free_variable_values((*ea)->v); if((*ea)->v->name) fs_give((void **) &(*ea)->v->name); fs_give((void **) &(*ea)->v);; } free_arbhdr(&(*ea)->a); fs_give((void **) ea); } } void calculate_inick_stuff(struct pine *ps) { ACTION_S *role, *irole; CONF_S *ctmp, *ctmpa; struct variable *v; int i; char *nick; if(inick_confs[INICK_INICK_CONF] == NULL) return; for(i = INICK_FROM_CONF; i <= INICK_NNTP_CONF; i++){ v = inick_confs[i] ? inick_confs[i]->var : NULL; if(v){ if(v->is_list){ if(v->global_val.l) free_list_array(&v->global_val.l); } else{ if(v->global_val.p) fs_give((void **)&v->global_val.p); } } } nick = PVAL(inick_confs[INICK_INICK_CONF]->var, ew); if(nick){ /* * Use an empty role with inherit_nick set to nick and then use the * combine function to find the action values. */ role = (ACTION_S *)fs_get(sizeof(*role)); memset((void *)role, 0, sizeof(*role)); role->is_a_role = 1; role->inherit_nick = cpystr(nick); irole = combine_inherited_role(role); ctmp = inick_confs[INICK_FROM_CONF]; v = ctmp ? ctmp->var : NULL; if(irole && irole->from){ char *bufp; size_t len; len = est_size(irole->from); bufp = (char *) fs_get(len * sizeof(char)); v->global_val.p = addr_string_mult(irole->from, bufp, len); } ctmp = inick_confs[INICK_REPLYTO_CONF]; v = ctmp ? ctmp->var : NULL; if(irole && irole->replyto){ char *bufp; size_t len; len = est_size(irole->replyto); bufp = (char *) fs_get(len * sizeof(char)); v->global_val.p = addr_string_mult(irole->replyto, bufp, len); } ctmp = inick_confs[INICK_FCC_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.p = (irole && irole->fcc) ? cpystr(irole->fcc) : NULL; ctmp = inick_confs[INICK_LITSIG_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.p = (irole && irole->litsig) ? cpystr(irole->litsig) : NULL; ctmp = inick_confs[INICK_SIG_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.p = (irole && irole->sig) ? cpystr(irole->sig) : NULL; ctmp = inick_confs[INICK_TEMPL_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.p = (irole && irole->template) ? cpystr(irole->template) : NULL; ctmp = inick_confs[INICK_CSTM_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.l = (irole && irole->cstm) ? copy_list_array(irole->cstm) : NULL; ctmp = inick_confs[INICK_SMTP_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.l = (irole && irole->smtp) ? copy_list_array(irole->smtp) : NULL; ctmp = inick_confs[INICK_NNTP_CONF]; v = ctmp ? ctmp->var : NULL; v->global_val.l = (irole && irole->nntp) ? copy_list_array(irole->nntp) : NULL; free_action(&role); free_action(&irole); } for(i = INICK_INICK_CONF; i <= INICK_NNTP_CONF; i++){ ctmp = inick_confs[i]; v = ctmp ? ctmp->var : NULL; /* * If we didn't set a global_val using the nick above, then * set one here for each variable that uses one. */ if(v && !v->global_val.p){ char *str, *astr, *lc, pdir[MAXPATH+1]; ADDRESS *addr; int len = 0; switch(i){ case INICK_FROM_CONF: addr = generate_from(); astr = addr_list_string(addr, NULL, 1); str = (astr && astr[0]) ? astr : "?"; v->global_val.p = (char *)fs_get((strlen(str) + 20) * sizeof(char)); snprintf(v->global_val.p, strlen(str) + 20, "%s%s)", DSTRING, str); v->global_val.p[strlen(str) + 20 - 1] = '\0'; if(astr) fs_give((void **)&astr); if(addr) mail_free_address(&addr); break; case INICK_FCC_CONF: v->global_val.p = cpystr(VSTRING); break; case INICK_LITSIG_CONF: /* * This default works this way because of the ordering * of the choices in the detoken routine. */ if(ps->VAR_LITERAL_SIG){ str = ps->VAR_LITERAL_SIG; v->global_val.p = (char *)fs_get((strlen(str) + 20) * sizeof(char)); snprintf(v->global_val.p, strlen(str) + 20, "%s%s)", DSTRING, str); v->global_val.p[strlen(str) + 20 - 1] = '\0'; } break; case INICK_SIG_CONF: pdir[0] = '\0'; if(ps_global->VAR_OPER_DIR){ strncpy(pdir, ps_global->VAR_OPER_DIR, MAXPATH); pdir[MAXPATH] = '\0'; len = strlen(pdir) + 1; } else if((lc = last_cmpnt(ps_global->pinerc)) != NULL){ strncpy(pdir, ps_global->pinerc, MIN(MAXPATH,lc-ps_global->pinerc)); pdir[MIN(MAXPATH, lc-ps_global->pinerc)] = '\0'; len = strlen(pdir); } if(pdir[0] && ps->VAR_SIGNATURE_FILE && ps->VAR_SIGNATURE_FILE[0] && is_absolute_path(ps->VAR_SIGNATURE_FILE) && !strncmp(ps->VAR_SIGNATURE_FILE, pdir, len)){ str = ps->VAR_SIGNATURE_FILE + len; } else str = (ps->VAR_SIGNATURE_FILE && ps->VAR_SIGNATURE_FILE[0]) ? ps->VAR_SIGNATURE_FILE : NULL; if(str){ v->global_val.p = (char *)fs_get((strlen(str) + 20) * sizeof(char)); snprintf(v->global_val.p, strlen(str) + 20, "%s%s)", DSTRING, str); v->global_val.p[strlen(str) + 20 - 1] = '\0'; } break; case INICK_INICK_CONF: case INICK_REPLYTO_CONF: case INICK_TEMPL_CONF: case INICK_CSTM_CONF: case INICK_SMTP_CONF: case INICK_NNTP_CONF: break; } } if(v) set_current_val(v, FALSE, FALSE); if(ctmp){ CONF_S *ctmpsig = NULL; struct variable *vlsig; for(ctmpa = ctmp; ctmpa && ctmpa->varnamep == ctmp; ctmpa = ctmpa->next){ if(ctmpa->value) fs_give((void **)&ctmpa->value); ctmpa->value = pretty_value(ps, ctmpa); } if(i == INICK_SIG_CONF){ /* * Turn off NOSELECT, but possibly turn it on again * in next line. */ if((ctmpsig = inick_confs[INICK_SIG_CONF]) != NULL) ctmpsig->flags &= ~CF_NOSELECT; if(inick_confs[INICK_LITSIG_CONF] && (vlsig = inick_confs[INICK_LITSIG_CONF]->var) && vlsig->current_val.p && vlsig->current_val.p[0]){ if(ctmp->value) fs_give((void **)&ctmp->value); ctmp->value = cpystr(""); ctmp->flags |= CF_NOSELECT; } } } } } /* Arguments: * lst: a list of folders * action: a 1 or 0 value which basically says that str is associated with * the filter action if true or the Current Folder type if false. * Return: * Returns 2 on success (user wants to exit) and 0 on failure. * * This function cycles through a list of folders and checks whether or not each * folder exists. If they exist, return 2, if they don't exist, notify the user * or offer to create depending on whether or not it is a filter action or not. * With each of these prompts, the user can abort their desire to exit. */ int check_role_folders(char **lst, unsigned int action) { char *cur_fn, wt_res, prompt[MAX_SCREEN_COLS]; int i, rv = 2; CONTEXT_S *cntxt = NULL; char nbuf1[MAX_SCREEN_COLS], nbuf2[MAX_SCREEN_COLS]; int space, w1, w2, exists; if(!(lst && *lst)){ if(action) q_status_message(SM_ORDER, 3, 5, _("Set a valid Filter Action before Exiting")); else q_status_message(SM_ORDER, 3, 5, _("Set a valid Specific Folder before Exiting")); rv = 0; return rv; } for(i = 0; lst[i]; i++){ if(action) cur_fn = detoken_src(lst[i], FOR_FILT, NULL, NULL, NULL, NULL); else cur_fn = lst[i]; removing_leading_and_trailing_white_space(cur_fn); if(*cur_fn != '\0'){ space = MAXPROMPT; if(is_absolute_path(cur_fn) || !context_isambig(cur_fn)) cntxt = NULL; else cntxt = default_save_context(ps_global->context_list); if(!(exists=folder_exists(cntxt, cur_fn)) && (action || (ps_global->context_list->use & CNTXT_INCMNG && !folder_is_nick(cur_fn,FOLDERS(ps_global->context_list), 0)))){ if(cntxt && (action == 1)){ space -= 37; /* for fixed part of prompt below */ w1 = MAX(1,MIN(strlen(cur_fn),space/2)); w2 = MIN(MAX(1,space-w1),strlen(cntxt->nickname)); w1 += MAX(0,space-w1-w2); snprintf(prompt, sizeof(prompt), _("Folder \"%s\" in <%s> doesn't exist. Create"), short_str(cur_fn,nbuf1,sizeof(nbuf1),w1,MidDots), short_str(cntxt->nickname,nbuf2,sizeof(nbuf2),w2,MidDots)); prompt[sizeof(prompt)-1] = '\0'; } else if(cntxt && (action == 0)){ space -= 51; /* for fixed part of prompt below */ w1 = MAX(1,MIN(strlen(cur_fn),space/2)); w2 = MIN(MAX(1,space-w1),strlen(cntxt->nickname)); w1 += MAX(0,space-w1-w2); snprintf(prompt, sizeof(prompt), _("Folder \"%s\" in <%s> doesn't exist. Exit and save anyway"), short_str(cur_fn,nbuf1,sizeof(nbuf1),w1,MidDots), short_str(cntxt->nickname,nbuf2,sizeof(nbuf2),w2,MidDots)); prompt[sizeof(prompt)-1] = '\0'; } else if(!cntxt && (action == 1)){ space -= 31; /* for fixed part of prompt below */ w1 = MAX(1,space); snprintf(prompt, sizeof(prompt), _("Folder \"%s\" doesn't exist. Create"), short_str(cur_fn,nbuf1,sizeof(nbuf1),w1,MidDots)); prompt[sizeof(prompt)-1] = '\0'; } else{ /*!cntxt && (action == 0) */ space -= 45; /* for fixed part of prompt below */ w1 = MAX(1,space); snprintf(prompt, sizeof(prompt), _("Folder \"%s\" doesn't exist. Exit and save anyway"), short_str(cur_fn,nbuf1,sizeof(nbuf1),w1,MidDots)); prompt[sizeof(prompt)-1] = '\0'; } wt_res = want_to(prompt, 'n', 'x', NO_HELP, WT_NORM); if(wt_res == 'y'){ if(action){ if(context_create(cntxt, NULL, cur_fn)){ q_status_message(SM_ORDER,3,5,_("Folder created")); maybe_add_to_incoming(cntxt, cur_fn); } } /* No message to notify of changes being saved, we can't */ /* assume that the role screen isn't exited yet */ rv = 2; } else if(wt_res == 'n' && action){ rv = 2; q_status_message(SM_ORDER,3,5,_("Folder not created")); } else{ q_status_message(SM_ORDER,3,5,_("Exit cancelled")); rv = 0; break; } } else{ if(exists & FEX_ERROR){ if(ps_global->mm_log_error && ps_global->c_client_error) q_status_message(SM_ORDER,3,5,ps_global->c_client_error); else q_status_message1(SM_ORDER,3,5,"\"%s\": Trouble checking for folder existence", cur_fn); } rv = 2; } } else{ /* blank item in list of folders */ if(action && lst[i+1] == NULL) q_status_message(SM_ORDER,3,5,_("Set a valid Filter Action before Exiting")); else /* !action && lst[i+1] == '\0' */ q_status_message(SM_ORDER,3,5,_("Set a valid Specific Folder before Exiting")); rv = 0; break; } if(cur_fn && cur_fn != lst[i]) fs_give((void **) &cur_fn); } return(rv); } void maybe_add_to_incoming(CONTEXT_S *cntxt, char *cur_fn) { char name[MAILTMPLEN], nname[32]; char nbuf1[MAX_SCREEN_COLS], nbuf2[MAX_SCREEN_COLS]; char prompt[MAX_SCREEN_COLS]; char ***alval; int i, found, space, w1, w2; FOLDER_S *f; if(ps_global->context_list->use & CNTXT_INCMNG && ((alval = ALVAL(&ps_global->vars[V_INCOMING_FOLDERS], Main)) != NULL)){ (void)context_apply(name, cntxt, cur_fn, sizeof(name)); /* * Since the folder didn't exist it is very unlikely that it is * in the incoming-folders list already, but we're just checking * to be sure. We should really be canonicalizing both names * before comparing, but... */ for(found = 0, i = 0; *alval && (*alval)[i] && !found; i++){ char *nickname, *folder; get_pair((*alval)[i], &nickname, &folder, 0, 0); if(folder && !strucmp((*alval)[i], folder)) found++; if(nickname) fs_give((void **)&nickname); if(folder) fs_give((void **)&folder); } if(found) return; space = MAXPROMPT; space -= 15; /* for fixed part of prompt below */ w2 = MAX(1, MIN(space/2,MIN(strlen(ps_global->context_list->nickname),20))); w1 = MAX(1,space - w2); snprintf(prompt, sizeof(prompt), "Add \"%s\" to %s list", short_str(name,nbuf1,sizeof(nbuf1),w1,MidDots), short_str(ps_global->context_list->nickname,nbuf2,sizeof(nbuf2),w2,MidDots)); prompt[sizeof(prompt)-1] = '\0'; if(want_to(prompt, 'n', 'x', NO_HELP, WT_NORM) == 'y'){ char *pp; nname[0] = '\0'; space = MAXPROMPT; space -= 25; w1 = MAX(1, space); snprintf(prompt, sizeof(prompt), "Nickname for folder \"%s\" : ", short_str(name,nbuf1,sizeof(nbuf1),w1,MidDots)); prompt[sizeof(prompt)-1] = '\0'; while(1){ int rc; int flags = OE_APPEND_CURRENT; rc = optionally_enter(nname, -FOOTER_ROWS(ps_global), 0, sizeof(nname), prompt, NULL, NO_HELP, &flags); removing_leading_and_trailing_white_space(nname); if(rc == 0 && *nname){ /* see if nickname already exists */ found = 0; if(!strucmp(ps_global->inbox_name, nname)) found++; for(i = 0; !found && i < folder_total(FOLDERS(ps_global->context_list)); i++){ FOLDER_S *f; f = folder_entry(i, FOLDERS(ps_global->context_list)); if(!strucmp(FLDR_NAME(f), nname)) found++; } if(found){ q_status_message1(SM_ORDER | SM_DING, 3, 5, _("Nickname \"%s\" is already in use"), nname); continue; } break; } else if(rc == 3) q_status_message(SM_ORDER, 0, 3, _("No help yet.")); else if(rc == 1){ q_status_message1(SM_ORDER, 0, 3, _("Not adding nickname to %s list"), ps_global->context_list->nickname); return; } } pp = put_pair(nname, name); f = new_folder(name, line_hash(pp)); f->nickname = cpystr(nname); f->name_len = strlen(nname); folder_insert(folder_total(FOLDERS(ps_global->context_list)), f, FOLDERS(ps_global->context_list)); if(!*alval){ i = 0; *alval = (char **)fs_get(2 * sizeof(char *)); } else{ for(i = 0; (*alval)[i]; i++) ; fs_resize((void **)alval, (i + 2) * sizeof(char *)); } (*alval)[i] = pp; (*alval)[i+1] = NULL; set_current_val(&ps_global->vars[V_INCOMING_FOLDERS], TRUE, TRUE); write_pinerc(ps_global, ew, WRP_NONE); } } } int role_filt_exitcheck(CONF_S **cl, unsigned int flags) { int rv, j, action; char **to_folder = NULL, **spec_fldr = NULL; CONF_S *ctmp; NAMEVAL_S *f; #define ACT_UNKNOWN 0 #define ACT_KILL 1 #define ACT_MOVE 2 #define ACT_MOVE_NOFOLDER 3 #define ACT_STATE 4 /* * We have to locate the lines which define the Filter Action and * then check to see that it is set to something before allowing * user to Exit. */ action = ACT_UNKNOWN; if(flags & CF_CHANGES && role_filt_ptr && PVAL(role_filt_ptr,ew)){ for(j = 0; (f = filter_types(j)); j++) if(!strucmp(PVAL(role_filt_ptr,ew), f->name)) break; switch(f ? f->value : -1){ case FILTER_KILL: action = ACT_KILL; break; case FILTER_STATE: action = ACT_STATE; break; case FILTER_FOLDER: /* * Check that the folder is set to something. */ action = ACT_MOVE_NOFOLDER; /* go to end of screen */ for(ctmp = (*cl); ctmp && ctmp->next; ctmp = next_confline(ctmp)) ; /* back up to start of Filter Action */ for(; ctmp && !(ctmp->flags & CF_STARTITEM && ctmp->var == role_filt_ptr); ctmp = prev_confline(ctmp)) ; /* skip back past NOSELECTs */ for(; ctmp && (ctmp->flags & CF_NOSELECT); ctmp = next_confline(ctmp)) ; /* find line with new var (the Folder line) */ for(; ctmp && (ctmp->var == role_filt_ptr); ctmp = next_confline(ctmp)) ; /* ok, we're finally at the Folder line */ if(ctmp && ctmp->var && LVAL(ctmp->var,ew)){ to_folder = copy_list_array(LVAL(ctmp->var,ew)); if(to_folder && to_folder[0]) action = ACT_MOVE; } break; default: dprint((1, "Can't happen, role_filt_ptr set to %s\n", PVAL(role_filt_ptr,ew) ? PVAL(role_filt_ptr,ew) : "?")); break; } } if(flags & CF_CHANGES){ switch(want_to((action == ACT_KILL) ? _("Commit changes (\"Yes\" means matching messages will be deleted)") : EXIT_PMT, 'y', 'x', h_config_undo, WT_FLUSH_IN)){ case 'y': switch(action){ case ACT_KILL: if((spec_fldr = get_role_specific_folder(cl)) != NULL){ rv = check_role_folders(spec_fldr, 0); free_list_array(&spec_fldr); if(rv == 2) q_status_message(SM_ORDER,0,3,_("Ok, messages matching that Pattern will be deleted")); } else{ q_status_message(SM_ORDER, 0, 3, _("Ok, messages matching that Pattern will be deleted")); rv = 2; } break; case ACT_MOVE: if((spec_fldr = get_role_specific_folder(cl)) != NULL){ rv = check_role_folders(spec_fldr, 0); free_list_array(&spec_fldr); if(to_folder && rv == 2) rv = check_role_folders(to_folder, 1); } else rv = check_role_folders(to_folder, 1); break; case ACT_MOVE_NOFOLDER: rv = 0; q_status_message(SM_ORDER, 3, 5, _("Set a valid Filter Action before Exiting")); break; case ACT_STATE: if((spec_fldr = get_role_specific_folder(cl)) != NULL){ rv = check_role_folders(spec_fldr, 0); free_list_array(&spec_fldr); } else rv = 2; break; default: rv = 2; dprint((1, "This can't happen, role_filt_ptr or to_folder not set\n")); break; } break; case 'n': q_status_message(SM_ORDER,3,5,_("No filter changes saved")); rv = 10; break; case 'x': /* ^C */ default : q_status_message(SM_ORDER,3,5,_("Changes not yet saved")); rv = 0; break; } } else rv = 2; if(to_folder) free_list_array(&to_folder); return(rv); } /* * Don't allow exit unless user has set the action to something. */ int role_filt_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv; switch(cmd){ case MC_EXIT: rv = role_filt_exitcheck(cl, flags); break; default: rv = role_text_tool(ps, cmd, cl, flags); break; } return(rv); } int role_filt_addhdr_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv; switch(cmd){ case MC_EXIT: rv = role_filt_exitcheck(cl, flags); break; default: rv = role_addhdr_tool(ps, cmd, cl, flags); break; } return rv; } int role_addhdr_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv; switch(cmd){ case MC_ADDHDR: case MC_EXIT: rv = role_text_tool(ps, cmd, cl, flags); break; default: rv = -1; break; } return rv; } /* * Don't allow exit unless user has set the action to something. */ int role_filt_radiobutton_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv; switch(cmd){ case MC_EXIT: rv = role_filt_exitcheck(cl, flags); break; default: rv = role_radiobutton_tool(ps, cmd, cl, flags); break; } return(rv); } /* * simple radio-button style variable handler */ int role_radiobutton_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0, i; CONF_S *ctmp, *spec_ctmp = NULL; NAMEVAL_S *rule; char **apval; switch(cmd){ case MC_CHOICE : /* set/unset feature */ /* back up to first line */ for(ctmp = (*cl); ctmp && ctmp->prev && !(ctmp->prev->flags & CF_NOSELECT); ctmp = prev_confline(ctmp)) ; for(i = 0; ctmp && (!(ctmp->flags & CF_NOSELECT) || (*cl)->var == role_fldr_ptr || (*cl)->var == role_afrom_ptr || (*cl)->var == role_filt_ptr); ctmp = next_confline(ctmp), i++){ if(((*cl)->var == role_fldr_ptr) || ((*cl)->var == role_afrom_ptr) || ((*cl)->var == role_filt_ptr)){ if((((*cl)->var == role_fldr_ptr) && !pat_fldr_types(i)) || (((*cl)->var == role_afrom_ptr) && !inabook_fldr_types(i)) || (((*cl)->var == role_filt_ptr) && !filter_types(i))){ spec_ctmp = ctmp; break; } } ctmp->value[1] = ' '; } /* turn on current value */ (*cl)->value[1] = R_SELD; if((*cl)->var == role_fldr_ptr){ for(ctmp = spec_ctmp; ctmp && ctmp->varnamep == spec_ctmp; ctmp = next_confline(ctmp)) if((*cl)->varmem == FLDR_SPECIFIC) ctmp->flags &= ~CF_NOSELECT; else ctmp->flags |= CF_NOSELECT; rule = pat_fldr_types((*cl)->varmem); } else if((*cl)->var == role_afrom_ptr){ for(ctmp = spec_ctmp; ctmp && ctmp->varnamep == spec_ctmp; ctmp = next_confline(ctmp)) if(((*cl)->varmem == IAB_SPEC_YES) || ((*cl)->varmem == IAB_SPEC_NO)) ctmp->flags &= ~CF_NOSELECT; else ctmp->flags |= CF_NOSELECT; rule = inabook_fldr_types((*cl)->varmem); } else if((*cl)->var == role_filt_ptr){ for(ctmp = spec_ctmp; ctmp && ctmp->varnamep == spec_ctmp; ctmp = next_confline(ctmp)) if((*cl)->varmem == FILTER_FOLDER) ctmp->flags &= ~CF_NOSELECT; else ctmp->flags |= CF_NOSELECT; rule = filter_types((*cl)->varmem); } else if((*cl)->var == role_forw_ptr) rule = role_forw_types((*cl)->varmem); else if((*cl)->var == role_repl_ptr) rule = role_repl_types((*cl)->varmem); else if((*cl)->var == role_status1_ptr || (*cl)->var == role_status2_ptr || (*cl)->var == role_status3_ptr || (*cl)->var == role_status4_ptr || (*cl)->var == role_status5_ptr || (*cl)->var == role_status6_ptr || (*cl)->var == role_status7_ptr || (*cl)->var == role_status8_ptr) rule = role_status_types((*cl)->varmem); else if((*cl)->var == msg_state1_ptr || (*cl)->var == msg_state2_ptr || (*cl)->var == msg_state3_ptr || (*cl)->var == msg_state4_ptr) rule = msg_state_types((*cl)->varmem); else rule = role_comp_types((*cl)->varmem); apval = APVAL((*cl)->var, ew); if(apval && *apval) fs_give((void **)apval); if(apval) *apval = cpystr(rule->name); ps->mangled_body = 1; /* BUG: redraw it all for now? */ rv = 1; break; case MC_EXIT: /* exit */ rv = role_text_tool(ps, cmd, cl, flags); break; default : rv = -1; break; } return(rv); } int role_sort_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0, i; CONF_S *ctmp; char **apval; SortOrder def_sort; int def_sort_rev; apval = APVAL((*cl)->var, ew); switch(cmd){ case MC_CHOICE : /* set/unset feature */ if((*cl)->varmem >= 0){ def_sort_rev = (*cl)->varmem >= (short) EndofList; def_sort = (SortOrder)((*cl)->varmem - (def_sort_rev * EndofList)); snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s", sort_name(def_sort), (def_sort_rev) ? "/Reverse" : ""); tmp_20k_buf[SIZEOF_20KBUF-1] = '\0'; } if(apval){ if(*apval) fs_give((void **)apval); if((*cl)->varmem >= 0) *apval = cpystr(tmp_20k_buf); } /* back up to first line */ for(ctmp = (*cl); ctmp && ctmp->prev && !(ctmp->prev->flags & CF_NOSELECT); ctmp = prev_confline(ctmp)) ; /* turn off all values */ for(i = 0; ctmp && !(ctmp->flags & CF_NOSELECT); ctmp = next_confline(ctmp), i++) ctmp->value[1] = ' '; /* turn on current value */ (*cl)->value[1] = R_SELD; ps->mangled_body = 1; /* BUG: redraw it all for now? */ rv = 1; break; case MC_EXIT: /* exit */ rv = role_text_tool(ps, cmd, cl, flags); break; default : rv = -1; break; } return(rv); } /* * Return an allocated list of the Specific Folder list for * roles, or NULL if Current Folder type is not set to * to Specific Folder * * WARNING, the method used in obtaining the specific folder is * VERY dependent on the order in which it is presented on the * screen. If the Current Folder radio buttons were changed, * this function would probably need to be fixed accordingly. */ char ** get_role_specific_folder(CONF_S **cl) { CONF_S *ctmp; /* go to the first line */ for(ctmp = *cl; ctmp && ctmp->prev; ctmp = prev_confline(ctmp)) ; /* go to the current folder radio button list */ while(ctmp && ctmp->var != role_fldr_ptr) ctmp = next_confline(ctmp); /* go to the specific folder button (caution) */ while(ctmp && ctmp->varmem != FLDR_SPECIFIC) ctmp = next_confline(ctmp); /* check if selected (assumption of format "(*)" */ if(ctmp && ctmp->value[1] == R_SELD){ /* go to next line, the start of the list */ ctmp = next_confline(ctmp); if(LVAL(ctmp->var, ew)) return copy_list_array(LVAL(ctmp->var, ew)); else{ char **ltmp; /* * Need to allocate empty string so as not to confuse it * with the possibility that Specific Folder is not selected. */ ltmp = (char **) fs_get(2 * sizeof(char *)); ltmp[0] = cpystr(""); ltmp[1] = NULL; return(ltmp); } } else return NULL; } /* */ int role_litsig_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv; switch(cmd){ case MC_ADD : case MC_EDIT : rv = litsig_text_tool(ps, cmd, cl, flags); if(rv) calculate_inick_stuff(ps); break; default : rv = role_text_tool(ps, cmd, cl, flags); break; } return(rv); } /* */ int role_cstm_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv; switch(cmd){ case MC_EXIT : rv = role_text_tool(ps, cmd, cl, flags); break; default : rv = text_tool(ps, cmd, cl, flags); if(rv == 1 && (*cl)->var){ char **lval; lval = LVAL((*cl)->var, ew); if(lval && lval[(*cl)->varmem] && ((!struncmp(lval[(*cl)->varmem],"from",4) && (lval[(*cl)->varmem][4] == ':' || lval[(*cl)->varmem][4] == '\0')) || (!struncmp(lval[(*cl)->varmem],"reply-to",8) && (lval[(*cl)->varmem][8] == ':' || lval[(*cl)->varmem][8] == '\0')))) q_status_message1(SM_ORDER|SM_DING, 5, 7, "Use \"Set %s\" instead, Change ignored", !struncmp(lval[(*cl)->varmem],"from",4) ? "From" : "Reply-To"); } break; } return(rv); } /* */ int role_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { OPT_SCREEN_S *saved_screen; int rv = -1, oeflags, len = 0, sig, r, i, cancel = 0; char *file, *err, title[20], *newfile, *lc, *addr, *fldr = NULL, *tmpfldr; char dir2[MAXPATH+1], pdir[MAXPATH+1], *p; char full_filename[MAXPATH+1], filename[MAXPATH+1]; char tmp[MAXPATH+1], **spec_fldr, **apval; EARB_S *earb, *ea, *eaprev; CONF_S *ctmp, *ctmpb, *newcp, *ctend; HelpType help; switch(cmd){ case MC_EXIT : if(flags & CF_CHANGES){ switch(want_to(EXIT_PMT, 'y', 'x', h_config_role_undo, WT_FLUSH_IN)){ case 'y': if((spec_fldr = get_role_specific_folder(cl)) != NULL){ rv = check_role_folders(spec_fldr, 0); free_list_array(&spec_fldr); } else rv = 2; break; case 'n': q_status_message(SM_ORDER,3,5,_("No changes saved")); rv = 10; break; case 'x': /* ^C */ q_status_message(SM_ORDER,3,5,_("Changes not yet saved")); rv = 0; break; } } else rv = 2; break; case MC_NOT : /* toggle between !matching and matching */ ctmp = (*cl)->varnamep; if(ctmp->varname && ctmp->var && ctmp->var->name){ if(!strncmp(ctmp->varname, NOT, NOTLEN) && !strncmp(ctmp->var->name, NOT, NOTLEN)){ rplstr(ctmp->var->name, strlen(ctmp->var->name)+1, NOTLEN, ""); rplstr(ctmp->varname, strlen(ctmp->varname)+1, NOTLEN, ""); strncpy(ctmp->varname+strlen(ctmp->varname)-1, repeat_char(NOTLEN, ' '), NOTLEN+1); strncat(ctmp->varname, "=", NOTLEN); } else{ rplstr(ctmp->var->name, strlen(ctmp->var->name)+NOTLEN+1, 0, NOT); strncpy(ctmp->varname+strlen(ctmp->varname)-1-NOTLEN, "=", NOTLEN); rplstr(ctmp->varname, strlen(ctmp->varname)+NOTLEN+1, 0, NOT); } rv = 1; } break; case MC_CHOICE : /* Choose a file */ /* * In signature_path we read signature files relative to the pinerc * dir, so if user selects one that is in there we'll make it * relative instead of absolute, so it looks nicer. */ pdir[0] = '\0'; if(ps_global->VAR_OPER_DIR){ strncpy(pdir, ps_global->VAR_OPER_DIR, MAXPATH); pdir[MAXPATH] = '\0'; len = strlen(pdir) + 1; } else if((lc = last_cmpnt(ps_global->pinerc)) != NULL){ strncpy(pdir, ps_global->pinerc, MIN(MAXPATH,lc-ps_global->pinerc)); pdir[MIN(MAXPATH, lc-ps_global->pinerc)] = '\0'; len = strlen(pdir); } strncpy(title, "CHOOSE A", 15); strncpy(dir2, pdir, MAXPATH); filename[0] = '\0'; build_path(full_filename, dir2, filename, sizeof(full_filename)); r = file_lister(title, dir2, sizeof(dir2), filename, sizeof(filename), TRUE, FB_READ); ps->mangled_screen = 1; if(r == 1){ build_path(full_filename, dir2, filename, sizeof(full_filename)); removing_leading_and_trailing_white_space(full_filename); if(!strncmp(full_filename, pdir, strlen(pdir))) newfile = cpystr(full_filename + len); else newfile = cpystr(full_filename); apval = APVAL((*cl)->var, ew); if(apval && *apval) fs_give((void **)apval); if(apval) *apval = newfile; if((*cl)->value) fs_give((void **)&((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else rv = 0; break; case MC_CHOICEB : /* Choose Addresses, no full names */ addr = addr_book_multaddr_nf(); ps->mangled_screen = 1; if(addr && (*cl)->var && (*cl)->var->is_list){ char **ltmp, *tmp; int i; i = 0; for(tmp = addr; *tmp; tmp++) if(*tmp == ',') i++; /* conservative count of ,'s */ ltmp = parse_list(addr, i + 1, PL_COMMAQUOTE, NULL); fs_give((void **) &addr); if(ltmp && ltmp[0]) config_add_list(ps, cl, ltmp, NULL, 0); if(ltmp) fs_give((void **) <mp); if((*cl)->value) fs_give((void **)&((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else rv = 0; break; case MC_CHOICEC : /* Choose an Address, no full name */ addr = addr_book_oneaddr(); ps->mangled_screen = 1; if(addr){ apval = APVAL((*cl)->var, ew); if(apval && *apval) /* replace current value */ fs_give((void **)apval); if(apval) *apval = addr; if((*cl)->value) fs_give((void **)&((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else rv = 0; break; case MC_CHOICED : /* Choose a Folder */ case MC_CHOICEE : saved_screen = opt_screen; if(cmd == MC_CHOICED) tmpfldr = folder_for_config(FOR_PATTERN); else tmpfldr = folder_for_config(0); if(tmpfldr){ fldr = add_comma_escapes(tmpfldr); fs_give((void**) &tmpfldr); } opt_screen = saved_screen; ps->mangled_screen = 1; if(fldr && *fldr && (*cl)->var && (*cl)->var->is_list){ char **ltmp; ltmp = (char **) fs_get(2 * sizeof(char *)); ltmp[0] = fldr; ltmp[1] = NULL; fldr = NULL; if(ltmp && ltmp[0]) config_add_list(ps, cl, ltmp, NULL, 0); if(ltmp) fs_give((void **) <mp); if((*cl)->value) fs_give((void **) &((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else if(fldr && *fldr && (*cl)->var && !(*cl)->var->is_list){ apval = APVAL((*cl)->var, ew); if(apval && *apval) /* replace current value */ fs_give((void **)apval); if(apval){ *apval = fldr; fldr = NULL; } if((*cl)->value) fs_give((void **) &((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else rv = 0; if(fldr) fs_give((void **) &fldr); break; case MC_EDITFILE : file = ((*cl)->var && PVAL((*cl)->var, ew)) ? cpystr(PVAL((*cl)->var, ew)) : NULL; if(file) removing_leading_and_trailing_white_space(file); sig = (srchstr((*cl)->varname, "signature") != NULL); if(!file || !*file){ err = (char *)fs_get(100 * sizeof(char)); snprintf(err, 100, "No %s file defined. First define a file name.", sig ? "signature" : "template"); err[100-1] = '\0'; } else{ if(file[len=(strlen(file)-1)] == '|') file[len] = '\0'; snprintf(title, sizeof(title), "%s EDITOR", sig ? "SIGNATURE" : "TEMPLATE"); title[sizeof(title)-1] = '\0'; err = signature_edit(file, title); } fs_give((void **)&file); if(err){ q_status_message1(SM_ORDER, 3, 5, "%s", err); fs_give((void **)&err); } rv = 0; ps->mangled_screen = 1; break; /* Add an arbitrary header to this role */ case MC_ADDHDR : rv = 0; /* make earb point to last one */ for(earb = *(*cl)->d.earb; earb && earb->next; earb = earb->next) ; /* Add new one to end of list */ ea = (EARB_S *)fs_get(sizeof(*ea)); memset((void *)ea, 0, sizeof(*ea)); ea->v = (struct variable *)fs_get(sizeof(struct variable)); memset((void *)ea->v, 0, sizeof(struct variable)); ea->a = (ARBHDR_S *)fs_get(sizeof(ARBHDR_S)); memset((void *)ea->a, 0, sizeof(ARBHDR_S)); /* get new header field name */ help = NO_HELP; tmp[0] = '\0'; while(1){ i = optionally_enter(tmp, -FOOTER_ROWS(ps), 0, sizeof(tmp), _("Enter the name of the header field to be added: "), NULL, help, NULL); if(i == 0) break; else if(i == 1){ cmd_cancelled("eXtraHdr"); cancel = 1; break; } else if(i == 3){ help = help == NO_HELP ? h_config_add_pat_hdr : NO_HELP; continue; } else break; } ps->mangled_footer = 1; removing_leading_and_trailing_white_space(tmp); if(tmp[strlen(tmp)-1] == ':') /* remove trailing colon */ tmp[strlen(tmp)-1] = '\0'; removing_trailing_white_space(tmp); if(cancel || !tmp[0]) break; tmp[0] = islower((unsigned char)tmp[0]) ? toupper((unsigned char)tmp[0]) : tmp[0]; ea->a->field = cpystr(tmp); if(earb) earb->next = ea; else *((*cl)->d.earb) = ea; /* go to first line */ for(ctmp = *cl; prev_confline(ctmp); ctmp = prev_confline(ctmp)) ; /* * Go to the Add Extra Headers line. We will put the * new header before this line. */ for(; ctmp; ctmp = next_confline(ctmp)) if(ctmp->value && !strcmp(ctmp->value, ADDXHDRS)) break; /* move back one */ if(ctmp) ctmp = prev_confline(ctmp); /* * Add a new line after this point, which is after the last * extra header (if any) or after the Participant pattern, and * before the Add Extra Headers placeholder line. */ p = (char *) fs_get(strlen(tmp) + strlen(" pattern") + 1); snprintf(p, strlen(tmp) + strlen(" pattern") + 1, "%s pattern", tmp); p[strlen(tmp) + strlen(" pattern") + 1 - 1] = '\0'; setup_dummy_pattern_var(ea->v, p, NULL); fs_give((void **) &p); /* find what indent should be */ if(ctmp && ctmp->varnamep && ctmp->varnamep->varname) i = MIN(MAX(utf8_width(ctmp->varnamep->varname) + 1, 3), 200); else i = 20; setup_role_pat(ps, &ctmp, ea->v, h_config_role_arbpat, ARB_HELP, &config_role_xtrahdr_keymenu, ctmp->prev->tool, ctmp->prev->d.earb, i); /* * move current line to new line */ newcp = ctmp; /* check if new line comes before the top of the screen */ ctmpb = (opt_screen && opt_screen->top_line) ? opt_screen->top_line->prev : NULL; for(; ctmpb; ctmpb = prev_confline(ctmpb)) if(ctmpb == newcp) break; /* * Keep the right lines visible. * The if triggers if the new line is off the top of the screen, and * it makes the new line be the top line. * The else counts how many lines down the screen the new line is. */ i = 0; if(ctmpb == newcp) opt_screen->top_line = newcp; else{ for(ctmp = opt_screen->top_line; ctmp && ctmp != newcp; i++, ctmp = next_confline(ctmp)) ; } if(i >= BODY_LINES(ps)){ /* new line is off screen */ /* move top line down this far */ i = i + 1 - BODY_LINES(ps); for(ctmp = opt_screen->top_line; i > 0; i--, ctmp = next_confline(ctmp)) ; opt_screen->top_line = ctmp; } *cl = newcp; ps->mangled_screen = 1; rv = 1; break; /* Delete an arbitrary header from this role */ case MC_DELHDR : /* * Find this one in earb list. We don't have a good way to locate * it so we match the ea->v->name with ctmp->varname. */ rv = 0; eaprev = NULL; for(ea = *(*cl)->d.earb; ea; ea = ea->next){ if((*cl)->varnamep && (*cl)->varnamep->varname && ea->v && ea->v->name && !strncmp((*cl)->varnamep->varname, ea->v->name, strlen(ea->v->name))) break; eaprev = ea; } snprintf(tmp, sizeof(tmp), _("Really remove \"%s\" pattern from this rule"), (ea && ea->a && ea->a->field) ? ea->a->field : "this"); tmp[sizeof(tmp)-1] = '\0'; if(want_to(tmp, 'y', 'n', NO_HELP, WT_NORM) != 'y'){ cmd_cancelled("RemoveHdr"); return(rv); } /* delete the earb element from the list */ if(ea){ if(eaprev) eaprev->next = ea->next; else *(*cl)->d.earb = ea->next; ea->next = NULL; free_earb(&ea); } /* remember start of deleted header */ ctmp = (*cl && (*cl)->varnamep) ? (*cl)->varnamep : NULL; /* and end of deleted header */ for(ctend = *cl; ctend; ctend = next_confline(ctend)) if(!ctend->next || ctend->next->varnamep != ctmp) break; /* check if top line is one we're deleting */ for(ctmpb = ctmp; ctmpb; ctmpb = next_confline(ctmpb)){ if(ctmpb == opt_screen->top_line) break; if(ctmpb == (*cl)) break; } if(ctmpb == opt_screen->top_line) opt_screen->top_line = ctend ? ctend->next : NULL; /* move current line after this header */ *cl = ctend ? ctend->next : NULL; /* remove deleted header lines */ if(ctmp && ctend){ /* remove from linked list */ if(ctmp->prev) ctmp->prev->next = ctend->next; if(ctend->next) ctend->next->prev = ctmp->prev; /* free memory */ ctmp->prev = ctend->next = NULL; free_conflines(&ctmp); } ps->mangled_body = 1; rv = 1; break; default : if(((*cl)->var == scorei_pat_global_ptr || (*cl)->var == age_pat_global_ptr || (*cl)->var == size_pat_global_ptr || (*cl)->var == cati_global_ptr) && (cmd == MC_EDIT || (cmd == MC_ADD && !PVAL((*cl)->var, ew)))){ char prompt[60]; rv = 0; snprintf(prompt, sizeof(prompt), "%s the interval : ", PVAL((*cl)->var, ew) ? "Change" : "Enter"); prompt[sizeof(prompt)-1] = '\0'; ps->mangled_footer = 1; help = NO_HELP; tmp[0] = '\0'; snprintf(tmp, sizeof(tmp), "%s", PVAL((*cl)->var, ew) ? PVAL((*cl)->var, ew) : ""); tmp[sizeof(tmp)-1] = '\0'; while(1){ oeflags = OE_APPEND_CURRENT; i = optionally_enter(tmp, -FOOTER_ROWS(ps), 0, sizeof(tmp), prompt, NULL, help, &oeflags); if(i == 0){ rv = ps->mangled_body = 1; apval = APVAL((*cl)->var, ew); if(apval && *apval) fs_give((void **)apval); if(apval && tmp[0]) *apval = cpystr(tmp); fix_side_effects(ps, (*cl)->var, 0); if((*cl)->value) fs_give((void **)&(*cl)->value); (*cl)->value = pretty_value(ps, *cl); } else if(i == 1) cmd_cancelled(cmd == MC_ADD ? "Add" : "Change"); else if(i == 3){ help = help == NO_HELP ? h_config_edit_scorei : NO_HELP; continue; } else if(i == 4) continue; break; } } else{ if(cmd == MC_ADD && (*cl)->var && !(*cl)->var->is_list) cmd = MC_EDIT; rv = text_toolit(ps, cmd, cl, flags, 1); /* make sure the earb pointers are set */ for(ctmp = (*cl)->varnamep; ctmp->next && ctmp->next->var == ctmp->var; ctmp = next_confline(ctmp)) ctmp->next->d.earb = ctmp->d.earb; } break; } /* * If the inherit nickname changed, we have to re-calculate the * global_vals and values for the action variables. * We may have to do the same if literal sig changed, too. */ if(rv) calculate_inick_stuff(ps); return(rv); } /* */ int role_text_tool_inick(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = -1; char **apval; switch(cmd){ case MC_EXIT : rv = role_text_tool(ps, cmd, cl, flags); break; case MC_CHOICE : /* Choose a role nickname */ {void (*prev_screen)(struct pine *) = ps->prev_screen, (*redraw)(void) = ps->redrawer; OPT_SCREEN_S *saved_screen; ACTION_S *role; ps->redrawer = NULL; ps->next_screen = SCREEN_FUN_NULL; saved_screen = opt_screen; if(role_select_screen(ps, &role, 0) == 0){ apval = APVAL((*cl)->var, ew); if(apval && *apval) fs_give((void **)apval); if(apval) *apval = (role && role->nick) ? cpystr(role->nick) : NULL; if((*cl)->value) fs_give((void **)&((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else{ ps->next_screen = prev_screen; ps->redrawer = redraw; rv = 0; } opt_screen = saved_screen; } ps->mangled_screen = 1; break; case MC_EDIT : case MC_ADD : case MC_DELETE : rv = text_tool(ps, cmd, cl, flags); ps->mangled_screen = 1; break; default : rv = text_tool(ps, cmd, cl, flags); break; } /* * If the inherit nickname changed, we have to re-calculate the * global_vals and values for the action variables. * We may have to do the same if literal sig changed, too. */ if(rv) calculate_inick_stuff(ps); return(rv); } /* */ int role_text_tool_kword(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int i, j, rv = -1; char **lval; switch(cmd){ case MC_CHOICE : /* Choose keywords from list and add them */ {void (*prev_screen)(struct pine *) = ps->prev_screen, (*redraw)(void) = ps->redrawer; OPT_SCREEN_S *saved_screen; char *esc; char **kw; ps->redrawer = NULL; ps->next_screen = SCREEN_FUN_NULL; saved_screen = opt_screen; if((kw=choose_list_of_keywords()) != NULL){ for(i = 0; kw[i]; i++){ esc = add_roletake_escapes(kw[i]); fs_give((void **) &kw[i]); kw[i] = esc; } /* eliminate duplicates before the add */ lval = LVAL((*cl)->var, ew); if(lval && *lval){ for(i = 0; kw[i]; ){ /* if kw[i] is a dup, eliminate it */ for(j = 0; lval[j]; j++) if(!strcmp(kw[i], lval[j])) break; if(lval[j]){ /* it is a dup */ for(j = i; kw[j]; j++) kw[j] = kw[j+1]; } else i++; } } if(kw[0]) config_add_list(ps, cl, kw, NULL, 0); fs_give((void **) &kw); if((*cl)->value) fs_give((void **) &((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else{ ps->next_screen = prev_screen; ps->redrawer = redraw; rv = 0; } opt_screen = saved_screen; } ps->mangled_screen = 1; break; case MC_EDIT : case MC_ADD : case MC_DELETE : case MC_NOT : rv = role_text_tool(ps, cmd, cl, flags); ps->mangled_screen = 1; break; case MC_EXIT : default : rv = role_text_tool(ps, cmd, cl, flags); break; } return(rv); } /* */ int role_text_tool_charset(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int i, j, rv = -1; char **lval; switch(cmd){ case MC_CHOICE : /* Choose charsets from list and add them */ {void (*prev_screen)(struct pine *) = ps->prev_screen, (*redraw)(void) = ps->redrawer; OPT_SCREEN_S *saved_screen; char *esc; char **kw; ps->redrawer = NULL; ps->next_screen = SCREEN_FUN_NULL; saved_screen = opt_screen; if((kw=choose_list_of_charsets()) != NULL){ for(i = 0; kw[i]; i++){ esc = add_roletake_escapes(kw[i]); fs_give((void **) &kw[i]); kw[i] = esc; } /* eliminate duplicates before the add */ lval = LVAL((*cl)->var, ew); if(lval && *lval){ for(i = 0; kw[i]; ){ /* if kw[i] is a dup, eliminate it */ for(j = 0; lval[j]; j++) if(!strcmp(kw[i], lval[j])) break; if(lval[j]){ /* it is a dup */ for(j = i; kw[j]; j++) kw[j] = kw[j+1]; } else i++; } } if(kw[0]) config_add_list(ps, cl, kw, NULL, 0); fs_give((void **) &kw); if((*cl)->value) fs_give((void **) &((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else{ ps->next_screen = prev_screen; ps->redrawer = redraw; rv = 0; } opt_screen = saved_screen; } ps->mangled_screen = 1; break; case MC_EDIT : case MC_ADD : case MC_DELETE : case MC_NOT : rv = role_text_tool(ps, cmd, cl, flags); ps->mangled_screen = 1; break; case MC_EXIT : default : rv = role_text_tool(ps, cmd, cl, flags); break; } return(rv); } /* * Choose an address book nickname */ int role_text_tool_afrom(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = -1; switch(cmd){ case MC_EXIT : rv = role_text_tool(ps, cmd, cl, flags); break; case MC_CHOICE : /* Choose an addressbook */ {OPT_SCREEN_S *saved_screen; char *abook = NULL, *abookesc = NULL; ps->redrawer = NULL; ps->next_screen = SCREEN_FUN_NULL; saved_screen = opt_screen; abook = abook_select_screen(ps); if(abook){ abookesc = add_comma_escapes(abook); fs_give((void**) &abook); } ps->mangled_screen = 1; if(abookesc && *abookesc && (*cl)->var && (*cl)->var->is_list){ char **ltmp; ltmp = (char **) fs_get(2 * sizeof(char *)); ltmp[0] = abookesc; ltmp[1] = NULL; abookesc = NULL; if(ltmp && ltmp[0]) config_add_list(ps, cl, ltmp, NULL, 0); if(ltmp) fs_give((void **) <mp); if((*cl)->value) fs_give((void **) &((*cl)->value)); (*cl)->value = pretty_value(ps, *cl); rv = 1; } else rv = 0; if(abookesc) fs_give((void **) &abookesc); opt_screen = saved_screen; } ps->mangled_screen = 1; break; default : rv = text_tool(ps, cmd, cl, flags); ps->mangled_screen = 1; break; } return(rv); } /* * Args fmt -- a printf style fmt string with a single %s * buf -- place to put result, assumed large enough (strlen(fmt)+11) * rflags -- controls what goes in buf * * Returns -- pointer to buf */ char * role_type_print(char *buf, size_t buflen, char *fmt, long int rflags) { #define CASE_MIXED 1 #define CASE_UPPER 2 #define CASE_LOWER 3 int cas = CASE_UPPER; int prev_word_is_a = 0; char *q, *p; /* find %sRule to see what case */ if((p = srchstr(fmt, "%srule")) != NULL){ if(p[2] == 'R'){ if(p[3] == 'U') cas = CASE_UPPER; else cas = CASE_MIXED; } else cas = CASE_LOWER; if(p-3 >= fmt && p[-1] == SPACE && (p[-2] == 'a' || p[-2] == 'A') && p[-3] == SPACE) prev_word_is_a++; } if(cas == CASE_UPPER) q = (rflags & ROLE_DO_INCOLS) ? "INDEX COLOR " : (rflags & ROLE_DO_FILTER) ? "FILTERING " : (rflags & ROLE_DO_SCORES) ? "SCORING " : (rflags & ROLE_DO_OTHER) ? "OTHER " : (rflags & ROLE_DO_SRCH) ? "SEARCH " : (rflags & ROLE_DO_ROLES) ? "ROLE " : ""; else if(cas == CASE_LOWER) q = (rflags & ROLE_DO_INCOLS) ? "index color " : (rflags & ROLE_DO_FILTER) ? "filtering " : (rflags & ROLE_DO_SCORES) ? "scoring " : (rflags & ROLE_DO_OTHER) ? "other " : (rflags & ROLE_DO_OTHER) ? "search " : (rflags & ROLE_DO_ROLES) ? "role " : ""; else q = (rflags & ROLE_DO_INCOLS) ? "Index Color " : (rflags & ROLE_DO_FILTER) ? "Filtering " : (rflags & ROLE_DO_SCORES) ? "Scoring " : (rflags & ROLE_DO_OTHER) ? "Other " : (rflags & ROLE_DO_OTHER) ? "Search " : (rflags & ROLE_DO_ROLES) ? "Role " : ""; /* it ain't right to say "a index" */ if(prev_word_is_a && !struncmp(q, "index", 5)) q += 6; snprintf(buf, buflen, fmt, q); buf[buflen-1] = '\0'; return(buf); } /* * filter option list manipulation tool * * * returns: -1 on unrecognized cmd, 0 if no change, 1 if change */ int feat_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0; switch(cmd){ case MC_TOGGLE: /* mark/unmark option */ rv = 1; toggle_feat_option_bit(ps, (*cl)->varmem, (*cl)->var, (*cl)->value); break; case MC_EXIT: /* exit */ rv = role_filt_exitcheck(cl, flags); break; default : rv = -1; break; } return(rv); } void toggle_feat_option_bit(struct pine *ps, int index, struct variable *var, char *value) { NAMEVAL_S *f; f = feat_feature_list(index); /* flip the bit */ if(bitnset(f->value, feat_option_list)) clrbitn(f->value, feat_option_list); else setbitn(f->value, feat_option_list); if(value) value[1] = bitnset(f->value, feat_option_list) ? 'X' : ' '; } NAMEVAL_S * feat_feature_list(int index) { static NAMEVAL_S opt_feat_list[] = { {"use-date-header-for-age", NULL, FEAT_SENTDATE}, {"move-only-if-not-deleted", NULL, FEAT_IFNOTDEL}, {"dont-stop-even-if-rule-matches", NULL, FEAT_NONTERM} }; return((index >= 0 && index < (sizeof(opt_feat_list)/sizeof(opt_feat_list[0]))) ? &opt_feat_list[index] : NULL); } /* * address type list manipulation tool * * * returns: -1 on unrecognized cmd, 0 if no change, 1 if change */ int inabook_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0; switch(cmd){ case MC_TOGGLE: /* mark/unmark option */ rv = 1; toggle_inabook_type_bit(ps, (*cl)->varmem, (*cl)->var, (*cl)->value); break; case MC_EXIT: /* exit */ rv = role_filt_exitcheck(cl, flags); break; default : rv = -1; break; } return(rv); } void toggle_inabook_type_bit(struct pine *ps, int index, struct variable *var, char *value) { NAMEVAL_S *f; f = inabook_feature_list(index); /* flip the bit */ if(bitnset(f->value, inabook_type_list)) clrbitn(f->value, inabook_type_list); else setbitn(f->value, inabook_type_list); if(value) value[1] = bitnset(f->value, inabook_type_list) ? 'X' : ' '; } NAMEVAL_S * inabook_feature_list(int index) { static NAMEVAL_S inabook_feat_list[] = { {"From", NULL, INABOOK_FROM}, {"Reply-To", NULL, INABOOK_REPLYTO}, {"Sender", NULL, INABOOK_SENDER}, {"To", NULL, INABOOK_TO}, {"Cc", NULL, INABOOK_CC} }; return((index >= 0 && index < (sizeof(inabook_feat_list)/sizeof(inabook_feat_list[0]))) ? &inabook_feat_list[index] : NULL); }