void my_list_listener (PluginParam *param) { GtkEntry *editable; if (sdlGoom->config_win == 0) return; editable = GTK_ENTRY(param->user_data); if (editable) { if (strcmp(gtk_entry_get_text(editable),LVAL(*param))) { gtk_entry_set_text (editable, LVAL(*param)); } } }
/* 0 on success, nonzero on error */ int check_types(struct lp_block *b) { int c = 0; /* we'll do all of the type checking here so that * the per-mod loaders only have to sanitize values */ for(c = 0; c < b->params_len; c++) { if(b->params[c]) { if(lp_param_name(b->type, b->params[c]->name) == -1) { fprintf(stderr, "*** warning: parameter %s not valid in context %s\n", b->params[c]->name, lp_modules[b->type]->name); } else if(lp_modules[b->type]->modvars[lp_param_name(b->type, b->params[c]->name)].type != PTYPE(b->params[c])) { /* implicitly convert ints to doubles */ if((lp_modules[b->type]->modvars[lp_param_name(b->type, b->params[c]->name)].type == D) && (PTYPE(b->params[c]) == I)) { b->params[c]->v->t = D; DVAL(b->params[c]) = (double) IVAL(b->params[c]); } else { fprintf(stderr, "*** error: type error: %s::\"%s\" cannot take type ", lp_modules[b->type]->name, b->params[c]->name); /* unparse_type(PTYPE(b->params[c]), stderr); */ fprintf(stderr, "\n"); die("check_types() failed"); } } if(PTYPE(b->params[c]) >= BLOCK) { check_types(BVAL(b->params[c])); } else if(PTYPE(b->params[c]) == LIST) { int d; struct lp_list *l = LVAL(b->params[c]); for(d = 0; d < l->values_len; d++) { if(l->values[d]) { if(l->values[d]->t >= BLOCK) { check_types(l->values[d]->v.b); } } } } } } return 0; }
void on_list_changed (GtkEditable *editable, gpointer user_data) { PluginParam *param = (PluginParam*)gtk_object_get_data (GTK_OBJECT(editable),"param"); LVAL(*param) = gtk_editable_get_chars (editable,0,-1); param->changed(param); }
SAVED_CONFIG_S * save_smime_config_vars(struct pine *ps) { struct variable *vreal; SAVED_CONFIG_S *vsave, *v; vsave = (SAVED_CONFIG_S *)fs_get((V_LAST_VAR+1)*sizeof(SAVED_CONFIG_S)); memset((void *)vsave, 0, (V_LAST_VAR+1)*sizeof(SAVED_CONFIG_S)); v = vsave; for(vreal = ps->vars; vreal->name; vreal++,v++){ if(!(smime_related_var(ps, vreal) || vreal==&ps->vars[V_FEATURE_LIST])) continue; if(vreal->is_list){ int n, i; char **list; if(LVAL(vreal, ew)){ /* count how many */ n = 0; list = LVAL(vreal, ew); while(list[n]) n++; v->saved_user_val.l = (char **)fs_get((n+1) * sizeof(char *)); memset((void *)v->saved_user_val.l, 0, (n+1)*sizeof(char *)); for(i = 0; i < n; i++) v->saved_user_val.l[i] = cpystr(list[i]); v->saved_user_val.l[n] = NULL; } } else{ if(PVAL(vreal, ew)) v->saved_user_val.p = cpystr(PVAL(vreal, ew)); } } return(vsave); }
int context_config_add(struct pine *ps, CONF_S **cl) { char *raw_ctxt; struct variable *var; char **lval; int count; if((raw_ctxt = context_edit_screen(ps, "ADD", NULL, NULL, NULL, NULL)) != NULL){ /* * If var is non-NULL we add to the end of that var. * If it is NULL, that means we're adding to the current_val, so * we'll have to soak up the default values from there into our * own variable. */ if((*cl)->var){ var = (*cl)->var; lval = LVAL((*cl)->var, ew); } else{ q_status_message(SM_ORDER|SM_DING, 3, 3, "Programmer botch in context_config_add"); return(0); } for(count = 0; lval && lval[count]; count++) ; if(!ccs_var_insert(ps, raw_ctxt, var, lval, count)){ fs_give((void **)&raw_ctxt); q_status_message(SM_ORDER|SM_DING, 3, 3, _("Error adding new collection")); return(0); } fs_give((void **)&raw_ctxt); (*cl)->d.c.cs->starting_var = var; (*cl)->d.c.cs->starting_varmem = count; q_status_message(SM_ORDER, 0, 3, _("New collection added. Use \"$\" to adjust order.")); return(15); } ps->mangled_screen = 1; return(0); }
int ccs_var_delete(struct pine *ps, CONTEXT_S *ctxt) { int count, i; char **newl = NULL, **lval, **lp, ***alval; if(ctxt) lval = LVAL(ctxt->var.v, ew); else lval = NULL; for(count = 0; lval && lval[count]; count++) ; /* sum the list */ if(count > 1){ newl = (char **) fs_get(count * sizeof(char *)); for(i = 0, lp = newl; lval[i]; i++) if(i != ctxt->var.i) *lp++ = cpystr(lval[i]); *lp = NULL; } alval = ALVAL(ctxt->var.v, ew); if(alval){ free_list_array(alval); if(newl){ for(i = 0; newl[i] ; i++) /* count elements */ ; *alval = (char **) fs_get((i+1) * sizeof(char *)); for(i = 0; newl[i] ; i++) (*alval)[i] = cpystr(newl[i]); (*alval)[i] = NULL; } } free_list_array(&newl); return(1); }
void addParams (GtkNotebook *notebook, PluginParameters *params) { int n; GtkWidget *table = gtk_table_new (params->nbParams, 2, FALSE); gtk_container_set_border_width (GTK_CONTAINER (table), 11); gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 6); for (n=0;n<params->nbParams;++n) { if (params->params[n] == 0) { GtkWidget *hseparator = gtk_hseparator_new (); gtk_widget_show (hseparator); gtk_table_attach (GTK_TABLE (table), hseparator, 0, 2, n, n+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 5); } else { PluginParam *p = params->params[n]; if (p->type != PARAM_BOOLVAL) { GtkWidget *label4 = gtk_label_new (p->name); gtk_widget_show (label4); gtk_table_attach (GTK_TABLE (table), label4, 0, 1, n, n+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_label_set_justify (GTK_LABEL (label4), GTK_JUSTIFY_RIGHT); gtk_misc_set_alignment (GTK_MISC (label4), 0, 0.5); } switch (p->type) { case PARAM_INTVAL: { GtkWidget *spinbutton_adj,*spinbutton; spinbutton_adj = (GtkWidget*)gtk_adjustment_new ( p->param.ival.value, p->param.ival.min, p->param.ival.max, p->param.ival.step, p->param.ival.step*10, p->param.ival.step*10); spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0); gtk_widget_show (spinbutton); gtk_table_attach (GTK_TABLE (table), spinbutton, 1, 2, n, n+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 1); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinbutton), GTK_UPDATE_IF_VALID); p->user_data = spinbutton; gtk_object_set_data (GTK_OBJECT(spinbutton),"param",(void*)p); p->change_listener = my_int_listener; gtk_signal_connect (GTK_OBJECT (spinbutton), "changed", GTK_SIGNAL_FUNC (on_spinbutton_int_changed), NULL); break; } case PARAM_FLOATVAL: { GtkWidget *progress,*prog_adj; prog_adj = (GtkWidget*)gtk_adjustment_new ( p->param.fval.value, p->param.fval.min, p->param.fval.max, p->param.fval.step, p->param.fval.step*10, p->param.fval.step*10); progress = gtk_progress_bar_new_with_adjustment(GTK_ADJUSTMENT(prog_adj)); gtk_widget_show(progress); gtk_table_attach (GTK_TABLE (table), progress, 1, 2, n, n+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 1); p->user_data = progress; p->change_listener = my_float_listener; break; } case PARAM_LISTVAL: { int i; GList *combo_winsize_items = NULL; GtkWidget *combo_entry_winsize = NULL; GtkWidget *combo_winsize = gtk_combo_new (); gtk_widget_show (combo_winsize); gtk_table_attach (GTK_TABLE (table), combo_winsize, 1, 2, n, n+1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_combo_set_value_in_list (GTK_COMBO (combo_winsize), TRUE, TRUE); for (i=0;i<p->param.slist.nbChoices;++i) combo_winsize_items = g_list_append (combo_winsize_items, p->param.slist.choices[i]); gtk_combo_set_popdown_strings (GTK_COMBO (combo_winsize), combo_winsize_items); g_list_free (combo_winsize_items); combo_entry_winsize = GTK_COMBO (combo_winsize)->entry; gtk_widget_show (combo_entry_winsize); gtk_entry_set_editable (GTK_ENTRY (combo_entry_winsize), FALSE); gtk_entry_set_text (GTK_ENTRY (combo_entry_winsize), LVAL(*p)); p->change_listener = my_list_listener; p->user_data = combo_entry_winsize; gtk_object_set_data (GTK_OBJECT(combo_entry_winsize),"param",(void*)p); gtk_signal_connect (GTK_OBJECT (combo_entry_winsize), "changed", GTK_SIGNAL_FUNC (on_list_changed), NULL); break; } case PARAM_BOOLVAL: { GtkWidget *checkbutton_double = gtk_check_button_new_with_label (p->name); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton_double),BVAL(*p)); gtk_widget_show (checkbutton_double); gtk_table_attach (GTK_TABLE (table), checkbutton_double, 1, 2, n, n+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_signal_connect (GTK_OBJECT (checkbutton_double), "toggled", GTK_SIGNAL_FUNC (on_bool_toggled), NULL); gtk_object_set_data (GTK_OBJECT(checkbutton_double),"param",(void*)p); p->user_data = checkbutton_double; p->change_listener = my_bool_listener; break; } } } } gtk_widget_show_all(GTK_WIDGET(table)); gtk_container_add(GTK_CONTAINER(notebook),table); gtk_notebook_set_tab_label_text(notebook,GTK_WIDGET(table),params->name); }
int incoming_monitoring_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0; CONTEXT_S *cntxt; char **the_list; CONF_S *ctmp; char ***alval; OPT_SCREEN_S *saved_screen; if(cmd != MC_EXIT && fixed_var((*cl)->var, NULL, NULL)) return(rv); switch(cmd){ case MC_ADD: case MC_EDIT: cntxt = ps->context_list; if(!(cntxt && cntxt->use & CNTXT_INCMNG)){ q_status_message1(SM_ORDER, 3, 3, _("Turn on incoming folders with Config feature \"%s\""), pretty_feature_name(feature_list_name(F_ENABLE_INCOMING), -1)); return(rv); } saved_screen = opt_screen; the_list = adjust_list_of_monitored_incoming(cntxt, ew, V_INCCHECKLIST); /* adjust top if it might be necessary */ for(ctmp = (*cl)->varnamep; ctmp && ctmp->varnamep == (*cl)->varnamep; ctmp = next_confline(ctmp)) if(ctmp == opt_screen->top_line) opt_screen->top_line = (*cl)->varnamep; if(the_list){ alval = ALVAL((*cl)->var, ew); free_list_array(alval); if(!*the_list){ q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders")); if(alval){ /* * Remove config lines except for first one. */ *cl = (*cl)->varnamep; while((*cl)->next && (*cl)->next->varnamep == (*cl)->varnamep) snip_confline(&(*cl)->next); } } else config_add_list(ps, cl, the_list, NULL, 0); /* only have to free the top-level pointer */ fs_give((void **) &the_list); rv = 1; } else{ if(LVAL((*cl)->var, ew)) q_status_message(SM_ORDER, 0, 3, _("List is unchanged")); else q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders")); } opt_screen = saved_screen; ps->mangled_screen = 1; break; default: rv = text_tool(ps, cmd, cl, flags); /* if we deleted last one, reverts to default */ if(cmd == MC_DELETE && rv == 1 && (*cl)->varmem == 0 && (!(*cl)->next || (*cl)->next->varnamep != (*cl))) q_status_message(SM_ORDER, 0, 3, _("Using default, monitor all incoming folders")); break; } /* * This is just like the end of text_tool. */ if(rv == 1){ /* * Now go and set the current_val based on user_val changes * above. Turn off command line settings... */ set_current_val((*cl)->var, TRUE, FALSE); fix_side_effects(ps, (*cl)->var, 0); if((*cl)->value) fs_give((void **) &(*cl)->value); (*cl)->value = pretty_value(ps, *cl); exception_override_warning((*cl)->var); } return(rv); }
/*---------------------------------------------------------------------- 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 }
int lp_loadparams(void *it, struct lp_block *b, struct lp_mod *m) { int c; int needed = 0; int param_stack[LP_STACK_MAX]; int stack_ptr = 0; // index of first free slot // XXX not static size char *paramvec = calloc(m->modvars_len, sizeof(char)); // This is pretty gross; there should be a better solution. // dirname() munges its operand. Its result may also be a static // buffer somewhere, hence the 2 copies. char *tmp = strdup(b->source_file); lp_cwd = strdup(dirname(tmp)); // free(tmp); for(c = 0; c < b->params_len; c++) { int pnum, deps; if(!b->params[c]) continue; TOP: pnum = lp_param_name(lp_mod_name(m->name), b->params[c]->name); // Don't initialize things more than once. // Should warn here, probably. if(BIT_TEST(paramvec, pnum)) continue; if(stack_ptr > 0) { for(c = 0; c < b->params_len; c++) { if(lp_param_name(lp_mod_name(m->name), b->params[c]->name) == needed) goto FOUND; } break; } FOUND: deps = m->param_deps[pnum](paramvec); if(deps > -1) { ddbg_assert(stack_ptr < LP_STACK_MAX); param_stack[stack_ptr++] = c; needed = deps; continue; } else { switch(PTYPE(b->params[c])) { case I: ((lp_paramloader_int)m->param_loaders[pnum])(it, IVAL(b->params[c])); break; case D: ((lp_paramloader_double)m->param_loaders[pnum])(it, DVAL(b->params[c])); break; case S: ((lp_paramloader_string)m->param_loaders[pnum])(it, SVAL(b->params[c])); break; case LIST: ((lp_paramloader_list)m->param_loaders[pnum])(it, LVAL(b->params[c])); break; case BLOCK: default: ((lp_paramloader_block)m->param_loaders[pnum])(it, BVAL(b->params[c])); break; } } BIT_SET(paramvec, pnum); if(stack_ptr > 0) { c = param_stack[--stack_ptr]; goto TOP; } } for(c = 0; c < m->modvars_len; c++) { if(m->modvars[c].req && !BIT_TEST(paramvec,c)) { fprintf(stderr, "*** error: in %s spec -- missing required parameter %s\n", m->name, m->modvars[c].name); break; } } free(paramvec); return 0; // ??? }
int context_config_edit(struct pine *ps, CONF_S **cl) { char *raw_ctxt, tpath[MAILTMPLEN], *p, **lval; struct variable *var; int i; if(!(*cl)->d.c.ct) return(0); /* Undigest the context */ strncpy(tpath, ((*cl)->d.c.ct->context[0] == '{' && (p = strchr((*cl)->d.c.ct->context, '}'))) ? ++p : (*cl)->d.c.ct->context, sizeof(tpath)-1); tpath[sizeof(tpath)-1] = '\0'; if((p = strstr(tpath, "%s")) != NULL) *p = '\0'; if((raw_ctxt = context_edit_screen(ps, "EDIT", (*cl)->d.c.ct->nickname, (*cl)->d.c.ct->server, tpath, (*cl)->d.c.ct->dir ? (*cl)->d.c.ct->dir->view.user : NULL)) != NULL){ if((*cl)->var){ var = (*cl)->var; lval = LVAL(var, ew); i = (*cl)->d.c.ct->var.i; if(lval && lval[i] && !strcmp(lval[i], raw_ctxt)) q_status_message(SM_ORDER, 0, 3, _("No change")); else if(lval){ if(lval[i]) fs_give((void **) &lval[i]); lval[i] = raw_ctxt; raw_ctxt = NULL; q_status_message(SM_ORDER, 0, 3, _("Collection list entry updated")); } (*cl)->d.c.cs->starting_var = var; (*cl)->d.c.cs->starting_varmem = i; if(raw_ctxt) fs_give((void **) &raw_ctxt); } else{ q_status_message(SM_ORDER|SM_DING, 3, 3, "Programmer botch in context_config_edit"); return(0); } return(15); } ps->mangled_screen = 1; return(0); }
int context_config_shuffle(struct pine *ps, CONF_S **cl) { char prompt[256]; int n = 0, cmd, i1, i2, count = 0, insert_num, starting_varmem; int news_problem = 0, deefault = 0; ESCKEY_S ekey[3]; CONTEXT_S *cur_ctxt, *other_ctxt; char *tmp, **lval, **lval1, **lval2; struct variable *cur_var, *other_var; if(!((*cl)->d.c.ct && (*cl)->var)) return(0); /* enable UP? */ if((*cl)->d.c.ct->prev && !((*cl)->d.c.ct->prev->use & CNTXT_INHERIT)){ /* * Don't allow shuffling news collection up to become * the primary collection. That would happen if prev is primary * and this one is news. */ if((*cl)->d.c.ct->prev->use & CNTXT_SAVEDFLT && (*cl)->d.c.ct->use & CNTXT_NEWS) news_problem++; else{ ekey[n].ch = 'u'; ekey[n].rval = 'u'; ekey[n].name = "U"; ekey[n++].label = N_("Up"); deefault = 'u'; } } /* enable DOWN? */ if((*cl)->d.c.ct->next && !((*cl)->d.c.ct->next->use & CNTXT_INHERIT)){ /* * Don't allow shuffling down past news collection if this * is primary collection. */ if((*cl)->d.c.ct->use & CNTXT_SAVEDFLT && (*cl)->d.c.ct->next->use & CNTXT_NEWS) news_problem++; else{ ekey[n].ch = 'd'; ekey[n].rval = 'd'; ekey[n].name = "D"; ekey[n++].label = N_("Down"); if(!deefault) deefault = 'd'; } } if(n){ ekey[n].ch = -1; snprintf(prompt, sizeof(prompt), _("Shuffle selected context %s%s%s? "), (ekey[0].ch == 'u') ? _("UP") : "", (n > 1) ? " or " : "", (ekey[0].ch == 'd' || n > 1) ? _("DOWN") : ""); prompt[sizeof(prompt)-1] = '\0'; cmd = radio_buttons(prompt, -FOOTER_ROWS(ps), ekey, deefault, 'x', NO_HELP, RB_NORM); switch(cmd){ case 'x': default: cmd_cancelled("Shuffle"); return(0); case 'u': case 'd': break; } /* * This is complicated by the fact that there are two * vars involved, the folder-collections and the news-collections. * We may have to shuffle across collections. */ cur_ctxt = (*cl)->d.c.ct; if(cmd == 'd') other_ctxt = (*cl)->d.c.ct->next; else if(cmd == 'u') other_ctxt = (*cl)->d.c.ct->prev; cur_var = cur_ctxt->var.v; other_var = other_ctxt->var.v; /* swap elements of config var */ if(cur_var == other_var){ i1 = cur_ctxt->var.i; i2 = other_ctxt->var.i; lval = LVAL(cur_var, ew); if(lval){ tmp = lval[i1]; lval[i1] = lval[i2]; lval[i2] = tmp; } starting_varmem = i2; } else{ /* swap into the other_var */ i1 = cur_ctxt->var.i; i2 = other_ctxt->var.i; lval1 = LVAL(cur_var, ew); lval2 = LVAL(other_var, ew); /* count */ for(count = 0; lval2 && lval2[count]; count++) ; if(cmd == 'd') insert_num = count ? 1 : 0; else{ insert_num = count ? count - 1 : count; } starting_varmem = insert_num; if(ccs_var_insert(ps,lval1[i1],other_var,lval2,insert_num)){ if(!ccs_var_delete(ps, cur_ctxt)){ q_status_message(SM_ORDER|SM_DING, 3, 3, _("Error deleting shuffled context")); return(0); } } else{ q_status_message(SM_ORDER, 3, 3, _("Trouble shuffling, cancelled")); return(0); } } (*cl)->d.c.cs->starting_var = other_var; (*cl)->d.c.cs->starting_varmem = starting_varmem; q_status_message(SM_ORDER, 0, 3, _("Collections shuffled")); return(15); } if(news_problem) /* TRANSLATORS: Sorry, can't move news group collections above email collections */ q_status_message(SM_ORDER, 0, 3, _("Sorry, cannot Shuffle news to top")); else q_status_message(SM_ORDER, 0, 3, _("Sorry, nothing to Shuffle")); return(0); }
/* * 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); } }
/* * Compare saved user_val with current user_val to see if it changed. * If any have changed, change it back and take the appropriate action. */ void revert_to_saved_smime_config(struct pine *ps, SAVED_CONFIG_S *vsave) { struct variable *vreal; SAVED_CONFIG_S *v; int i, n; int changed = 0; char *pval, **apval, **lval, ***alval; v = vsave; for(vreal = ps->vars; vreal->name; vreal++,v++){ if(!(smime_related_var(ps, vreal) || vreal==&ps->vars[V_FEATURE_LIST])) continue; if(vreal->is_list){ lval = LVAL(vreal, ew); alval = ALVAL(vreal, ew); if((v->saved_user_val.l && !lval) || (!v->saved_user_val.l && lval)) changed++; else if(!v->saved_user_val.l && !lval) ;/* no change, nothing to do */ else for(i = 0; v->saved_user_val.l[i] || lval[i]; i++) if((v->saved_user_val.l[i] && (!lval[i] || strcmp(v->saved_user_val.l[i], lval[i]))) || (!v->saved_user_val.l[i] && lval[i])){ changed++; break; } if(changed){ char **list; if(alval){ if(*alval) free_list_array(alval); /* copy back the original one */ if(v->saved_user_val.l){ list = v->saved_user_val.l; n = 0; /* count how many */ while(list[n]) n++; *alval = (char **)fs_get((n+1) * sizeof(char *)); for(i = 0; i < n; i++) (*alval)[i] = cpystr(v->saved_user_val.l[i]); (*alval)[n] = NULL; } } } } else{ pval = PVAL(vreal, ew); apval = APVAL(vreal, ew); if((v->saved_user_val.p && (!pval || strcmp(v->saved_user_val.p, pval))) || (!v->saved_user_val.p && pval)){ /* It changed, fix it */ changed++; if(apval){ /* free the changed value */ if(*apval) fs_give((void **)apval); if(v->saved_user_val.p) *apval = cpystr(v->saved_user_val.p); } } } if(changed){ if(vreal == &ps->vars[V_FEATURE_LIST]) set_feature_list_current_val(vreal); else set_current_val(vreal, TRUE, FALSE); fix_side_effects(ps, vreal, 1); } } }