/* * This is intended to be a generic tool to select strings from a list * of strings. * * Args lsel -- the items as well as the answer are contained in this list * flags -- There is some inconsistent flags usage. Notice that the * flag SFL_ALLOW_LISTMODE is a flag passed in the flags * argument whereas the flag SFL_NOSELECT is a per item * (that is, per LIST_SEL_S) flag. * title -- passed to conf_scroll_screen * pdesc -- passed to conf_scroll_screen * help -- passed to conf_scroll_screen * helptitle -- passed to conf_scroll_screen * * You have screen width - 4 columns to work with. If you want to overflow to * a second (or third or fourth) line for an item just send another item * in the list but with the SFL_NOSELECT flag set. Only the selectable lines * will be highlighted, which is kind of a crock, but it looked like a lot * of work to fix that. * * Returns 0 on successful choice * -1 if cancelled */ int select_from_list_screen(LIST_SEL_S *lsel, long unsigned int flags, char *title, char *pdesc, HelpType help, char *htitle, LIST_SEL_S *starting_val) { CONF_S *ctmp = NULL, *first_line = NULL; OPT_SCREEN_S screen; int j, lv, ret = -1; LIST_SEL_S *p; char *display; size_t l; ScreenMode listmode = SingleMode; int (*tool)(struct pine *, int, CONF_S **, unsigned); if(!lsel) return(ret); /* find longest value's length */ for(lv = 0, p = lsel; p; p = p->next){ if(!(p->flags & SFL_NOSELECT)){ display = p->display_item ? p->display_item : p->item ? p->item : ""; if(lv < (j = utf8_width(display))) lv = j; } } lv = MIN(lv, ps_global->ttyo->screen_cols - 4); tool = (flags & SFL_CTRLC) ? select_from_list_tool_allow_noselections : select_from_list_tool; /* * Convert the passed in list to conf_scroll lines. */ if(flags & SFL_ALLOW_LISTMODE){ if(flags & SFL_ONLY_LISTMODE) {assert(flags & SFL_STARTIN_LISTMODE);} for(p = lsel; p; p = p->next){ display = p->display_item ? p->display_item : p->item ? p->item : ""; new_confline(&ctmp); if(!first_line && !(p->flags & SFL_NOSELECT)) first_line = ctmp; if(!first_line && !(p->flags & SFL_NOSELECT)) if(!starting_val || (starting_val == p)) first_line = ctmp; /* generous allocation */ l = lv + 4 + strlen(display); ctmp->value = (char *) fs_get((l + 1) * sizeof(char)); utf8_snprintf(ctmp->value, l+1, " %-*.*w", lv, lv, display); ctmp->value[l] = '\0'; ctmp->d.l.lsel = p; ctmp->d.l.listmode = &listmode; if(flags & SFL_ONLY_LISTMODE){ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_olm_ctrlc; else ctmp->keymenu = &sel_from_list_olm; } else{ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_sm_ctrlc; else ctmp->keymenu = &sel_from_list_sm; } ctmp->help = help; ctmp->help_title = htitle; ctmp->tool = tool; ctmp->flags = CF_STARTITEM | ((p->flags & SFL_NOSELECT) ? CF_NOSELECT : 0); } } else{ assert(!(flags & SFL_ONLY_LISTMODE)); assert(!(flags & SFL_STARTIN_LISTMODE)); for(p = lsel; p; p = p->next){ display = p->display_item ? p->display_item : p->item ? p->item : ""; new_confline(&ctmp); if(!first_line && !(p->flags & SFL_NOSELECT)) if(!starting_val || (starting_val == p)) first_line = ctmp; l = lv + strlen(display); ctmp->value = (char *) fs_get((l + 1) * sizeof(char)); utf8_snprintf(ctmp->value, l+1, "%-*.*w", lv, lv, display); ctmp->value[l] = '\0'; ctmp->d.l.lsel = p; ctmp->d.l.listmode = &listmode; if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_ctrlc; else ctmp->keymenu = &sel_from_list; ctmp->help = help; ctmp->help_title = htitle; ctmp->tool = tool; ctmp->flags = CF_STARTITEM | ((p->flags & SFL_NOSELECT) ? CF_NOSELECT : 0); ctmp->valoffset = 4; } } /* just convert to start in listmode after the fact, easier that way */ if(flags & SFL_STARTIN_LISTMODE){ listmode = ListMode; for(ctmp = first_line; ctmp; ctmp = next_confline(ctmp)) if(!(ctmp->flags & CF_NOSELECT) && ctmp->value){ ctmp->value[0] = '['; ctmp->value[1] = ctmp->d.l.lsel->selected ? 'X' : SPACE; ctmp->value[2] = ']'; if(flags & SFL_ONLY_LISTMODE){ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_olm_ctrlc; else ctmp->keymenu = &sel_from_list_olm; } else{ if(flags & SFL_CTRLC) ctmp->keymenu = &sel_from_list_lm_ctrlc; else ctmp->keymenu = &sel_from_list_lm; } } } memset(&screen, 0, sizeof(screen)); switch(conf_scroll_screen(ps_global, &screen, first_line, title, pdesc, 0)){ case 1: ret = 0; break; default: break; } ps_global->mangled_screen = 1; return(ret); }
/*---------------------------------------------------------------------- Present pinerc data for manipulation Args: None Result: help edit certain pinerc fields. ---*/ void option_screen(struct pine *ps, int edit_exceptions) { char tmp[MAXPATH+1], *pval, **lval; int i, j, ln = 0, readonly_warning = 0; struct variable *vtmp; CONF_S *ctmpa = NULL, *ctmpb, *first_line = NULL; FEATURE_S *feature; PINERC_S *prc = NULL; SAVED_CONFIG_S *vsave; OPT_SCREEN_S screen; int expose_hidden_config, add_hidden_vars_title = 0; dprint((3, "-- option_screen --\n")); expose_hidden_config = F_ON(F_EXPOSE_HIDDEN_CONFIG, ps_global); treat_color_vars_as_text = expose_hidden_config; ew = edit_exceptions ? ps_global->ew_for_except_vars : Main; if(ps->restricted) readonly_warning = 1; else{ switch(ew){ case Main: prc = ps->prc; break; case Post: prc = ps->post_prc; break; default: break; } readonly_warning = prc ? prc->readonly : 1; if(prc && prc->quit_to_edit){ quit_to_edit_msg(prc); treat_color_vars_as_text = 0; return; } } ps->next_screen = SCREEN_FUN_NULL; mailcap_free(); /* free resources we won't be using for a while */ if(ps->fix_fixed_warning) offer_to_fix_pinerc(ps); /* * First, find longest variable name */ for(vtmp = ps->vars; vtmp->name; vtmp++){ if(exclude_config_var(ps, vtmp, expose_hidden_config)) continue; if((i = utf8_width(pretty_var_name(vtmp->name))) > ln) ln = i; } dprint((9, "initialize config list\n")); /* * Next, allocate and initialize config line list... */ for(vtmp = ps->vars; vtmp->name; vtmp++){ /* * INCOMING_FOLDERS is currently the first of the normally * hidden variables. Should probably invent a more robust way * to keep this up to date. */ if(expose_hidden_config && vtmp == &ps->vars[V_INCOMING_FOLDERS]) add_hidden_vars_title = 1; if(exclude_config_var(ps, vtmp, expose_hidden_config)) continue; if(add_hidden_vars_title){ add_hidden_vars_title = 0; new_confline(&ctmpa); /* Blank line */ ctmpa->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmpa)->var = NULL; ctmpa->help = NO_HELP; ctmpa->valoffset = 2; ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- [ Normally hidden configuration options ] ---"); new_confline(&ctmpa); /* Blank line */ ctmpa->flags |= CF_NOSELECT | CF_B_LINE; } if(vtmp->is_list) lval = LVAL(vtmp, ew); else pval = PVAL(vtmp, ew); new_confline(&ctmpa)->var = vtmp; if(!first_line) first_line = ctmpa; ctmpa->valoffset = ln + 3; if(vtmp->is_list) ctmpa->keymenu = &config_text_wshuf_keymenu; else ctmpa->keymenu = &config_text_keymenu; ctmpa->help = config_help(vtmp - ps->vars, 0); ctmpa->tool = text_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.100w =", ln, pretty_var_name(vtmp->name)); tmp[sizeof(tmp)-1] = '\0'; ctmpa->varname = cpystr(tmp); ctmpa->varnamep = ctmpb = ctmpa; ctmpa->flags |= CF_STARTITEM; if(vtmp == &ps->vars[V_FEATURE_LIST]){ /* special checkbox case */ char *this_sect, *new_sect; ctmpa->flags |= CF_NOSELECT; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->tool = NULL; /* put a nice delimiter before list */ new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = checkbox_tool; ctmpa->valoffset = feature_indent(); ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("Set Feature Name"); new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = checkbox_tool; ctmpa->valoffset = feature_indent(); ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- ----------------------"); for(i = 0, this_sect = NULL; (feature = feature_list(i)); i++) if((new_sect = feature_list_section(feature)) && (strcmp(new_sect, HIDDEN_PREF) != 0)){ if(this_sect != new_sect){ new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = checkbox_tool; ctmpa->valoffset = 2; ctmpa->flags |= (CF_NOSELECT | CF_STARTITEM); snprintf(tmp, sizeof(tmp), "[ %s ]", this_sect = new_sect); tmp[sizeof(tmp)-1] = '\0'; ctmpa->value = cpystr(tmp); } new_confline(&ctmpa)->var = vtmp; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = config_help(vtmp-ps->vars, feature->id); ctmpa->tool = checkbox_tool; ctmpa->valoffset = feature_indent(); ctmpa->varmem = i; ctmpa->value = pretty_value(ps, ctmpa); } } else if(standard_radio_var(ps, vtmp)){ standard_radio_setup(ps, &ctmpa, vtmp, NULL); } else if(vtmp == &ps->vars[V_SORT_KEY]){ /* radio case */ SortOrder def_sort; int def_sort_rev; ctmpa->flags |= CF_NOSELECT; ctmpa->keymenu = &config_radiobutton_keymenu; ctmpa->tool = NULL; /* put a nice delimiter before list */ new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_radiobutton_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = radiobutton_tool; ctmpa->valoffset = 12; ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("Set Sort Options"); new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_radiobutton_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = radiobutton_tool; ctmpa->valoffset = 12; ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- ----------------------"); decode_sort(pval, &def_sort, &def_sort_rev); for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ new_confline(&ctmpa)->var = vtmp; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_radiobutton_keymenu; ctmpa->help = config_help(vtmp - ps->vars, 0); ctmpa->tool = radiobutton_tool; ctmpa->valoffset = 12; ctmpa->varmem = i + (j * EndofList); ctmpa->value = pretty_value(ps, ctmpa); } } } else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */ ctmpa->keymenu = &config_yesno_keymenu; ctmpa->tool = yesno_tool; ctmpa->value = pretty_value(ps, ctmpa); } else if(vtmp == &ps->vars[V_LITERAL_SIG]){ ctmpa->tool = litsig_text_tool; ctmpa->value = pretty_value(ps, ctmpa); } else if(vtmp == &ps->vars[V_INBOX_PATH]){ ctmpa->tool = inbox_path_text_tool; ctmpa->value = pretty_value(ps, ctmpa); } else if(vtmp == &ps->vars[V_POST_CHAR_SET] #ifndef _WINDOWS || vtmp == &ps->vars[V_CHAR_SET] || vtmp == &ps->vars[V_KEY_CHAR_SET] #endif /* !_WINDOWS */ || vtmp == &ps->vars[V_UNK_CHAR_SET]){ ctmpa->keymenu = &config_text_to_charsets_keymenu; ctmpa->tool = to_charsets_text_tool; ctmpa->value = pretty_value(ps, ctmpa); } else if(vtmp->is_list){ int (*t_tool)(struct pine *, int, CONF_S **, unsigned); struct key_menu *km; t_tool = NULL; km = NULL; if(vtmp == &ps->vars[V_INCCHECKLIST]){ t_tool = incoming_monitoring_list_tool; km = &config_text_keymenu; } else if(vtmp == &ps->vars[V_PERMLOCKED]){ t_tool = stayopen_list_tool; km = &config_text_wshufandfldr_keymenu; } if(lval){ for(i = 0; lval[i]; i++){ if(i) (void)new_confline(&ctmpa); ctmpa->var = vtmp; ctmpa->varmem = i; ctmpa->valoffset = ln + 3; ctmpa->value = pretty_value(ps, ctmpa); ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu; ctmpa->help = config_help(vtmp - ps->vars, 0); ctmpa->tool = t_tool ? t_tool : text_tool; ctmpa->varnamep = ctmpb; } } else{ ctmpa->varmem = 0; ctmpa->value = pretty_value(ps, ctmpa); ctmpa->tool = t_tool ? t_tool : text_tool; ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu; } } else{ if(vtmp == &ps->vars[V_FILLCOL] || vtmp == &ps->vars[V_SLEEP] || vtmp == &ps->vars[V_QUOTE_SUPPRESSION] || vtmp == &ps->vars[V_OVERLAP] || vtmp == &ps->vars[V_MAXREMSTREAM] || vtmp == &ps->vars[V_MARGIN] || vtmp == &ps->vars[V_DEADLETS] || vtmp == &ps->vars[V_NMW_WIDTH] || vtmp == &ps->vars[V_STATUS_MSG_DELAY] || vtmp == &ps->vars[V_ACTIVE_MSG_INTERVAL] || vtmp == &ps->vars[V_MAILCHECK] || vtmp == &ps->vars[V_MAILCHECKNONCURR] || vtmp == &ps->vars[V_MAILDROPCHECK] || vtmp == &ps->vars[V_NNTPRANGE] || vtmp == &ps->vars[V_TCPOPENTIMEO] || vtmp == &ps->vars[V_TCPREADWARNTIMEO] || vtmp == &ps->vars[V_TCPWRITEWARNTIMEO] || vtmp == &ps->vars[V_TCPQUERYTIMEO] || vtmp == &ps->vars[V_RSHOPENTIMEO] || vtmp == &ps->vars[V_SSHOPENTIMEO] || vtmp == &ps->vars[V_INCCHECKTIMEO] || vtmp == &ps->vars[V_INCCHECKINTERVAL] || vtmp == &ps->vars[V_INC2NDCHECKINTERVAL] || vtmp == &ps->vars[V_USERINPUTTIMEO] || vtmp == &ps->vars[V_REMOTE_ABOOK_VALIDITY] || vtmp == &ps->vars[V_REMOTE_ABOOK_HISTORY]) ctmpa->flags |= CF_NUMBER; ctmpa->value = pretty_value(ps, ctmpa); } } dprint((9, "add hidden features\n")); /* add the hidden features */ if(expose_hidden_config){ char *new_sect; new_confline(&ctmpa); /* Blank line */ ctmpa->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmpa)->var = NULL; ctmpa->help = NO_HELP; ctmpa->valoffset = 2; ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- [ Normally hidden configuration features ] ---"); new_confline(&ctmpa); /* Blank line */ ctmpa->flags |= CF_NOSELECT | CF_B_LINE; vtmp = &ps->vars[V_FEATURE_LIST]; ctmpa->flags |= CF_NOSELECT; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->tool = NULL; /* put a nice delimiter before list */ new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = checkbox_tool; ctmpa->valoffset = feature_indent(); ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("Set Feature Name"); new_confline(&ctmpa)->var = NULL; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = checkbox_tool; ctmpa->valoffset = feature_indent(); ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr("--- ----------------------"); for(i = 0; (feature = feature_list(i)); i++) if((new_sect = feature_list_section(feature)) && (strcmp(new_sect, HIDDEN_PREF) == 0)){ new_confline(&ctmpa)->var = vtmp; ctmpa->varnamep = ctmpb; ctmpa->keymenu = &config_checkbox_keymenu; ctmpa->help = config_help(vtmp-ps->vars, feature->id); ctmpa->tool = checkbox_tool; ctmpa->valoffset = feature_indent(); ctmpa->varmem = i; ctmpa->value = pretty_value(ps, ctmpa); } } vsave = save_config_vars(ps, expose_hidden_config); first_line = first_sel_confline(first_line); memset(&screen, 0, sizeof(screen)); screen.ro_warning = readonly_warning; /* TRANSLATORS: Print something1 using something2. "configuration" is something1 */ switch(conf_scroll_screen(ps, &screen, first_line, edit_exceptions ? CONFIG_SCREEN_TITLE_EXC : CONFIG_SCREEN_TITLE, _("configuration"), 0)){ case 0: break; case 1: write_pinerc(ps, ew, WRP_NONE); break; case 10: revert_to_saved_config(ps, vsave, expose_hidden_config); if(prc) prc->outstanding_pinerc_changes = 0; break; default: q_status_message(SM_ORDER,7,10, "conf_scroll_screen bad ret, not supposed to happen"); break; } pval = PVAL(&ps->vars[V_SORT_KEY], ew); if(vsave[V_SORT_KEY].saved_user_val.p && pval && strcmp(vsave[V_SORT_KEY].saved_user_val.p, pval)){ if(!mn_get_mansort(ps_global->msgmap)){ clear_index_cache(ps_global->mail_stream, 0); reset_sort_order(SRT_VRB); } } treat_color_vars_as_text = 0; free_saved_config(ps, &vsave, expose_hidden_config); #ifdef _WINDOWS mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global)); #endif }
/* * Setup CollectionLists. Build a context list on the fly from the config * variable and edit it. This won't include Incoming-Folders because that * is a pseudo collection, but that's ok since we can't do the operations * on it, anyway. Reset real config list at the end. */ void context_config_screen(struct pine *ps, CONT_SCR_S *cs, int edit_exceptions) { CONTEXT_S *top, **clist, *cp; CONF_S *ctmpa, *first_line, *heading; OPT_SCREEN_S screen; int i, readonly_warning, some_defined, ret; int reinit_contexts = 0, prime; char **lval, **lval1, **lval2, ***alval; struct variable fake_fspec_var, fake_nspec_var; struct variable *fake_fspec, *fake_nspec; 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; break; case Post: prc = ps->post_prc; break; default: break; } readonly_warning = prc ? prc->readonly : 1; if(prc && prc->quit_to_edit){ quit_to_edit_msg(prc); return; } } go_again: top = NULL; ctmpa = NULL; first_line = NULL; some_defined = 0, prime = 0; fake_fspec = &fake_fspec_var; fake_nspec = &fake_nspec_var; memset((void *)fake_fspec, 0, sizeof(*fake_fspec)); memset((void *)fake_nspec, 0, sizeof(*fake_nspec)); /* so fixed_var() will work right */ fake_fspec->is_list = 1; fake_nspec->is_list = 1; if((ps->vars[V_FOLDER_SPEC]).is_fixed){ fake_fspec->is_fixed = 1; if((ps->vars[V_FOLDER_SPEC]).fixed_val.l && (ps->vars[V_FOLDER_SPEC]).fixed_val.l[0]){ fake_fspec->fixed_val.l = (char **) fs_get(2 * sizeof(char *)); fake_fspec->fixed_val.l[0] = cpystr((ps->vars[V_FOLDER_SPEC]).fixed_val.l[0]); fake_fspec->fixed_val.l[1] = NULL; } } if((ps->vars[V_NEWS_SPEC]).is_fixed){ fake_nspec->is_fixed = 1; if((ps->vars[V_NEWS_SPEC]).fixed_val.l && (ps->vars[V_NEWS_SPEC]).fixed_val.l[0]){ fake_nspec->fixed_val.l = (char **) fs_get(2 * sizeof(char *)); fake_nspec->fixed_val.l[0] = cpystr(INHERIT); fake_nspec->fixed_val.l[0] = cpystr((ps->vars[V_NEWS_SPEC]).fixed_val.l[0]); fake_nspec->fixed_val.l[1] = NULL; } } clist = ⊤ lval1 = LVAL(&ps->vars[V_FOLDER_SPEC], ew); lval2 = LVAL(&ps->vars[V_NEWS_SPEC], ew); alval = ALVAL(fake_fspec, ew); if(lval1) *alval = copy_list_array(lval1); else if(!edit_exceptions && ps->VAR_FOLDER_SPEC && ps->VAR_FOLDER_SPEC[0] && ps->VAR_FOLDER_SPEC[0][0]) *alval = copy_list_array(ps->VAR_FOLDER_SPEC); else fake_fspec = NULL; if(fake_fspec){ lval = LVAL(fake_fspec, ew); for(i = 0; lval && lval[i]; i++){ cp = NULL; if(i == 0 && !strcmp(lval[i], INHERIT)){ cp = (CONTEXT_S *)fs_get(sizeof(*cp)); memset((void *)cp, 0, sizeof(*cp)); cp->use = CNTXT_INHERIT; cp->label = cpystr("Default collections are inherited"); } else if((cp = new_context(lval[i], &prime)) != NULL){ cp->var.v = fake_fspec; cp->var.i = i; } if(cp){ *clist = cp; /* add it to list */ clist = &cp->next; /* prepare for next */ } } set_current_val(fake_fspec, FALSE, FALSE); } alval = ALVAL(fake_nspec, ew); if(lval2) *alval = copy_list_array(lval2); else if(!edit_exceptions && ps->VAR_NEWS_SPEC && ps->VAR_NEWS_SPEC[0] && ps->VAR_NEWS_SPEC[0][0]) *alval = copy_list_array(ps->VAR_NEWS_SPEC); else fake_nspec = NULL; if(fake_nspec){ lval = LVAL(fake_nspec, ew); for(i = 0; lval && lval[i]; i++){ cp = NULL; if(i == 0 && !strcmp(lval[i], INHERIT)){ cp = (CONTEXT_S *)fs_get(sizeof(*cp)); memset((void *)cp, 0, sizeof(*cp)); cp->use = CNTXT_INHERIT; cp->label = cpystr("Default collections are inherited"); } else if((cp = new_context(lval[i], &prime)) != NULL){ cp->var.v = fake_nspec; cp->var.i = i; } if(cp){ *clist = cp; /* add it to list */ clist = &cp->next; /* prepare for next */ } } set_current_val(fake_nspec, FALSE, FALSE); } for(cp = top; cp; cp = cp->next) if(!(cp->use & CNTXT_INHERIT)){ some_defined++; break; } if(edit_exceptions && !some_defined){ q_status_message(SM_ORDER, 3, 7, _("No exceptions to edit. First collection exception must be set by editing file")); free_contexts(&top); if(reinit_contexts){ free_contexts(&ps_global->context_list); init_folders(ps_global); } return; } /* fix up prev pointers */ for(cp = top; cp; cp = cp->next) if(cp->next) cp->next->prev = cp; new_confline(&ctmpa); /* blank line */ ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_config_tool; ctmpa->flags |= (CF_NOSELECT | CF_B_LINE); for(cp = top; cp; cp = cp->next){ new_confline(&ctmpa); heading = ctmpa; if(!(cp->use & CNTXT_INHERIT)) ctmpa->value = cpystr(cp->nickname ? cp->nickname : cp->context); ctmpa->var = cp->var.v; ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_config_tool; ctmpa->flags |= CF_STARTITEM; ctmpa->valoffset = 4; ctmpa->d.c.ct = cp; ctmpa->d.c.cs = cs; if(cp->use & CNTXT_INHERIT) ctmpa->flags |= CF_INHERIT | CF_NOSELECT; if((!first_line && !(cp->use & CNTXT_INHERIT)) || (!(cp->use & CNTXT_INHERIT) && cp->var.v && (cs->starting_var == cp->var.v) && (cs->starting_varmem == cp->var.i))) first_line = ctmpa; /* Add explanatory text */ new_confline(&ctmpa); ctmpa->value = cpystr(cp->label ? cp->label : "* * *"); ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_config_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 8; /* Always add blank line, make's shuffling a little easier */ new_confline(&ctmpa); heading->headingp = ctmpa; /* use headingp to mark end */ ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_config_tool; ctmpa->flags |= CF_NOSELECT | CF_B_LINE; ctmpa->valoffset = 0; } cs->starting_var = NULL; memset(&screen, 0, sizeof(screen)); screen.ro_warning = readonly_warning; ret = conf_scroll_screen(ps, &screen, first_line, cs->title, cs->print_string, 0); free_contexts(&top); if(ret) reinit_contexts++; /* * 15 means the tool wants us to reset and go again. The config var * has been changed. The contexts will be built again from the * config variable and the real contexts will be rebuilt below. * This is easier and safer than having the tools rebuild the context * list and the display correct. It's difficult to do because of all * the inheriting and defaulting going on. */ if(ret == 15){ if(edit_exceptions && !LVAL(fake_fspec, ew) && !LVAL(fake_nspec, ew)){ if(want_to(_("Really delete last exceptional collection"), 'n', 'n', h_config_context_del_except, WT_FLUSH_IN) != 'y'){ free_variable_values(fake_fspec); free_variable_values(fake_nspec); goto go_again; } } /* resolve variable changes */ if((lval1 && !equal_list_arrays(lval1, LVAL(fake_fspec, ew))) || (fake_fspec && !equal_list_arrays(ps->VAR_FOLDER_SPEC, LVAL(fake_fspec, ew)))){ i = set_variable_list(V_FOLDER_SPEC, LVAL(fake_fspec, ew), TRUE, ew); set_current_val(&ps->vars[V_FOLDER_SPEC], TRUE, FALSE); if(i) q_status_message(SM_ORDER, 3, 3, _("Trouble saving change, cancelled")); else if(!edit_exceptions && lval1 && !LVAL(fake_fspec, ew)){ cs->starting_var = fake_fspec; cs->starting_varmem = 0; q_status_message(SM_ORDER, 3, 3, _("Deleted last Folder-Collection, reverting to default")); } else if(!edit_exceptions && !lval1 && !LVAL(fake_fspec, ew)){ cs->starting_var = fake_fspec; cs->starting_varmem = 0; q_status_message(SM_ORDER, 3, 3, _("Deleted default Folder-Collection, reverting back to default")); } } if((lval2 && !equal_list_arrays(lval2, LVAL(fake_nspec, ew))) || (fake_nspec && !equal_list_arrays(ps->VAR_NEWS_SPEC, LVAL(fake_nspec, ew)))){ i = set_variable_list(V_NEWS_SPEC, LVAL(fake_nspec, ew), TRUE, ew); set_news_spec_current_val(TRUE, FALSE); if(i) q_status_message(SM_ORDER, 3, 3, _("Trouble saving change, cancelled")); else if(!edit_exceptions && lval2 && !LVAL(fake_nspec, ew) && ps->VAR_NEWS_SPEC && ps->VAR_NEWS_SPEC[0] && ps->VAR_NEWS_SPEC[0][0]){ cs->starting_var = fake_nspec; cs->starting_varmem = 0; q_status_message(SM_ORDER, 3, 3, _("Deleted last News-Collection, reverting to default")); } else if(!edit_exceptions && !lval2 && !LVAL(fake_nspec, ew) && ps->VAR_NEWS_SPEC && ps->VAR_NEWS_SPEC[0] && ps->VAR_NEWS_SPEC[0][0]){ cs->starting_var = fake_nspec; cs->starting_varmem = 0; q_status_message(SM_ORDER, 3, 3, _("Deleted default News-Collection, reverting back to default")); } } free_variable_values(fake_fspec); free_variable_values(fake_nspec); goto go_again; } ps->mangled_screen = 1; /* make the real context list match the changed config variables */ if(reinit_contexts){ free_contexts(&ps_global->context_list); init_folders(ps_global); } }
/*---------------------------------------------------------------------- Function to display/manage collections ----*/ CONTEXT_S * context_select_screen(struct pine *ps, CONT_SCR_S *cs, int ro_warn) { CONTEXT_S *cp; CONF_S *ctmpa = NULL, *first_line = NULL, *heading; OPT_SCREEN_S screen, *saved_screen; int readonly_warning = 0; /* restrict to normal config */ ew = Main; if(!cs->edit) readonly_warning = 0; else if(ps->restricted) readonly_warning = 1; else{ PINERC_S *prc = NULL; switch(ew){ case Main: prc = ps->prc; break; case Post: prc = ps->post_prc; break; default: break; } readonly_warning = prc ? prc->readonly : 1; if(ro_warn && prc && prc->quit_to_edit){ quit_to_edit_msg(prc); return(NULL); } } readonly_warning *= ro_warn; /* * Loop thru available contexts, setting up for display * (note: if no "cp" we're hosed. should never happen ;) */ for(cp = *cs->contexts; cp->prev; cp = cp->prev) ; /* delimiter for Mail Collections */ new_confline(&ctmpa); /* blank line */ ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_select_tool; ctmpa->flags |= CF_NOSELECT | CF_B_LINE; do{ new_confline(&ctmpa); heading = ctmpa; ctmpa->value = cpystr(cp->nickname ? cp->nickname : cp->context); ctmpa->var = cp->var.v; ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_select_tool; ctmpa->flags |= CF_STARTITEM; ctmpa->valoffset = 4; ctmpa->d.c.ct = cp; ctmpa->d.c.cs = cs; if(!first_line || cp == cs->start) first_line = ctmpa; /* Add explanatory text */ new_confline(&ctmpa); ctmpa->value = cpystr(cp->label ? cp->label : "* * *"); ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_select_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 8; /* Always add blank line, make's shuffling a little easier */ new_confline(&ctmpa); heading->headingp = ctmpa; ctmpa->keymenu = cs->keymenu; ctmpa->help = cs->help.text; ctmpa->help_title = cs->help.title; ctmpa->tool = context_select_tool; ctmpa->flags |= CF_NOSELECT | CF_B_LINE; ctmpa->valoffset = 0; } while((cp = cp->next) != NULL); saved_screen = opt_screen; memset(&screen, 0, sizeof(screen)); screen.ro_warning = readonly_warning; (void) conf_scroll_screen(ps, &screen, first_line, cs->title, cs->print_string, 0); opt_screen = saved_screen; ps->mangled_screen = 1; return(cs->selected); }
/*---------------------------------------------------------------------- Function to control flag set/clearing Basically, turn the flags into a fake list of features... Returns 0 unless user has added a keyword, then 1. ----*/ int flag_maintenance_screen(struct pine *ps, struct flag_screen *flags) { int i, lv, lc, maxwidth, offset, need, rv = 0; char tmp[1200], **p, *spacer; CONF_S *ctmpa, *first_line; struct flag_table *fp; OPT_SCREEN_S screen; try_again: maxwidth = MAX(MIN((ps->ttyo ? ps->ttyo->screen_cols : 80), 150), 30); first_line = NULL; ctmpa = NULL; for(p = flags->explanation; p && *p; p++) { new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; ctmpa->value = cpystr(_(*p)); } /* Now wire flags checkboxes together */ for(lv = 0, lc = 0, fp = (flags->flag_table ? *flags->flag_table : NULL); fp && fp->name; fp++) { /* longest name */ if(fp->flag != F_COMMENT) { if(lv < (i = utf8_width(_(fp->name)))) lv = i; if(fp->comment && lc < (i = utf8_width(fp->comment))) lc = i; } } lv = MIN(lv,100); lc = MIN(lc,100); if(lc > 0) spacer = " "; else spacer = ""; offset = 6; if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth) { offset -= (need - maxwidth); offset = MAX(0,offset); if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth) { spacer = " "; if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth) { lc -= (need - maxwidth); lc = MAX(0,lc); if(lc == 0) spacer = ""; } } } new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; ctmpa->value = cpystr(""); new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; utf8_snprintf(tmp, sizeof(tmp), "%*.*w %s", offset+3, offset+3, _("Set"), _("Flag/Keyword Name")); tmp[sizeof(tmp)-1] = '\0'; ctmpa->value = cpystr(tmp); new_confline(&ctmpa); ctmpa->keymenu = &flag_keymenu; ctmpa->help = NO_HELP; ctmpa->tool = flag_checkbox_tool; ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = 0; snprintf(tmp, sizeof(tmp), "%*.*s--- %.*s", offset, offset, "", lv+lc+strlen(spacer), repeat_char(lv+lc+strlen(spacer), '-')); tmp[sizeof(tmp)-1] = '\0'; ctmpa->value = cpystr(tmp); for(fp = (flags->flag_table ? *flags->flag_table : NULL); fp && fp->name; fp++) { /* build the list */ new_confline(&ctmpa); if(!first_line && (fp->flag != F_COMMENT)) first_line = ctmpa; ctmpa->keymenu = &flag_keymenu; ctmpa->tool = flag_checkbox_tool; ctmpa->valoffset = offset; if(fp->flag == F_COMMENT) { ctmpa->help = NO_HELP; ctmpa->flags |= CF_NOSELECT; ctmpa->value = cpystr(fp->name); } else { ctmpa->help = fp->help; ctmpa->d.f.ftbl = flags->flag_table; ctmpa->d.f.fp = fp; utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w%s%-*.*w", (fp->set == 0) ? ' ' : (fp->set == 1) ? 'X' : '?', lv, lv, _(fp->name), spacer, lc, lc, fp->comment ? fp->comment : ""); ctmpa->value = cpystr(tmp); } } memset(&screen, 0, sizeof(screen)); /* * TRANSLATORS: FLAG MAINTENANCE is a screen title. * Print something1 using something2. configuration is something1 */ if(conf_scroll_screen(ps, &screen, first_line, _("FLAG MAINTENANCE"), _("configuration"), 0) == FLAG_ADD_RETURN) { int flags, r; char keyword[500]; char nickname[500]; char prompt[500]; char *error = NULL; KEYWORD_S *kw; HelpType help; /* * User is asking to add a new keyword. We will add it to the * mailbox if necessary and add it to the keywords list from * Setup/Config. Then we will modify the flag_table and present * the flag modification screen again. */ ps->mangled_screen = 1; keyword[0] = '\0'; flags = OE_APPEND_CURRENT; help = NO_HELP; do { if(error) { q_status_message(SM_ORDER, 3, 4, error); fs_give((void **) &error); } strncpy(prompt, _("Keyword to be added : "), sizeof(prompt)-1); prompt[sizeof(prompt)-1] = '\0'; r = optionally_enter(keyword, -FOOTER_ROWS(ps_global), 0, sizeof(keyword), prompt, NULL, help, &flags); if(r == 3) help = help == NO_HELP ? h_type_keyword : NO_HELP; else if(r == 1) { cmd_cancelled("Add Keyword"); goto try_again; } removing_leading_and_trailing_white_space(keyword); } while(r == 3 || keyword_check(keyword, &error)); for(kw = ps->keywords; kw; kw = kw->next) { if(kw->kw && !strucmp(kw->kw, keyword)) { q_status_message(SM_ORDER, 3, 4, _("Keyword already configured, changing nickname")); break; } } snprintf(prompt, sizeof(prompt), _("Optional nickname for \"%s\" : "), keyword); nickname[0] = '\0'; help = NO_HELP; do { r = optionally_enter(nickname, -FOOTER_ROWS(ps_global), 0, sizeof(nickname), prompt, NULL, help, &flags); if(r == 3) help = help == NO_HELP ? h_type_keyword_nickname : NO_HELP; else if(r == 1) { cmd_cancelled("Add Keyword"); goto try_again; } removing_leading_and_trailing_white_space(nickname); } while(r == 3); if(keyword[0]) { char ***alval; int offset = -1; struct variable *var; var = &ps_global->vars[V_KEYWORDS]; alval = ALVAL(var, Main); for(kw = ps->keywords; kw; kw = kw->next) { offset++; if(kw->kw && !strucmp(kw->kw, keyword)) { /* looks like it should already exist at offset */ break; } } if(!kw) offset = -1; if(offset >= 0 && (*alval) && (*alval)[offset]) { fs_give((void **) &(*alval)[offset]); (*alval)[offset] = put_pair(nickname, keyword); } else if(!*alval) { offset = 0; *alval = (char **) fs_get(2*sizeof(char *)); (*alval)[offset] = put_pair(nickname, keyword); (*alval)[offset+1] = NULL; } else { for(offset=0; (*alval)[offset]; offset++); ; fs_resize((void **) alval, (offset + 2) * sizeof(char *)); (*alval)[offset] = put_pair(nickname, keyword); (*alval)[offset+1] = NULL; } set_current_val(var, TRUE, FALSE); if(ps_global->prc) ps_global->prc->outstanding_pinerc_changes = 1; if(ps_global->keywords) free_keyword_list(&ps_global->keywords); if(var->current_val.l && var->current_val.l[0]) ps_global->keywords = init_keyword_list(var->current_val.l); clear_index_cache(ps_global->mail_stream, 0); rv = 1; } } ps->mangled_screen = 1; return(rv); }
void smime_config_screen(struct pine *ps, int edit_exceptions) { CONF_S *ctmp = NULL, *first_line = NULL; SAVED_CONFIG_S *vsave; OPT_SCREEN_S screen; int ew, readonly_warning = 0; dprint((9, "smime_config_screen()")); ps->next_screen = SCREEN_FUN_NULL; 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; break; case Post: prc = ps->post_prc; break; default: break; } readonly_warning = prc ? prc->readonly : 1; if(prc && prc->quit_to_edit){ quit_to_edit_msg(prc); return; } } smime_config_init_display(ps, &ctmp, &first_line); vsave = save_smime_config_vars(ps); memset(&screen, 0, sizeof(screen)); screen.deferred_ro_warning = readonly_warning; switch(conf_scroll_screen(ps, &screen, first_line, edit_exceptions ? _("SETUP S/MIME EXCEPTIONS") : _("SETUP S/MIME"), /* TRANSLATORS: Print something1 using something2. configuration is something1 */ _("configuration"), 0)){ case 0: break; case 1: write_pinerc(ps, ew, WRP_NONE); break; case 10: revert_to_saved_smime_config(ps, vsave); break; default: q_status_message(SM_ORDER, 7, 10, _("conf_scroll_screen bad ret in smime_config")); break; } free_saved_smime_config(ps, &vsave); smime_deinit(); }