#if !defined(lint) && !defined(DOS) static char rcsid[] = "$Id: flagmaint.c 807 2007-11-09 01:21:33Z hubert@u.washington.edu $"; #endif /* * ======================================================================== * Copyright 2006-2007 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 "flagmaint.h" #include "confscroll.h" #include "../pith/state.h" #include "../pith/flag.h" #include "../pith/status.h" #include "../pith/mailcmd.h" #include "../pith/icache.h" #define FLAG_ADD_RETURN 15 /* * Internal prototypes */ int flag_checkbox_tool(struct pine *, int, CONF_S **, unsigned); /*---------------------------------------------------------------------- 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, "", (int)(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, NULL) == 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); } /* * Message flag manipulation tool * * * returns: -1 on unrecognized cmd, 0 if no change, 1 if change */ int flag_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0, state; switch(cmd){ case MC_TOGGLE: /* mark/unmark feature */ state = (*cl)->d.f.fp->set; state = (state == 1) ? 0 : (!state && ((*cl)->d.f.fp->ukn)) ? 2 : 1; (*cl)->value[1] = (state == 0) ? ' ' : ((state == 1) ? 'X': '?'); (*cl)->d.f.fp->set = state; rv = 1; break; case MC_ADD: rv = FLAG_ADD_RETURN; break; case MC_EXIT: /* exit */ rv = simple_exit_cmd(flags); break; default : rv = -1; break; } return(rv); }