Add support for tab-completion when selecting by rule
[alpine.git] / alpine / flagmaint.c
bloba6fcc1ff68c698c55020e6a7f02f7d91d662197a
1 /*
2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2022 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include "headers.h"
16 #include "flagmaint.h"
17 #include "confscroll.h"
18 #include "../pith/state.h"
19 #include "../pith/flag.h"
20 #include "../pith/status.h"
21 #include "../pith/mailcmd.h"
22 #include "../pith/icache.h"
25 #define FLAG_ADD_RETURN 15
29 * Internal prototypes
31 int flag_checkbox_tool(struct pine *, int, CONF_S **, unsigned);
34 /*----------------------------------------------------------------------
35 Function to control flag set/clearing
37 Basically, turn the flags into a fake list of features...
39 Returns 0 unless user has added a keyword, then 1.
41 ----*/
42 int
43 flag_maintenance_screen(struct pine *ps, struct flag_screen *flags)
45 int i, lv, lc, maxwidth, offset, need, rv = 0;
46 char tmp[1200], **p, *spacer;
47 CONF_S *ctmpa, *first_line;
48 struct flag_table *fp;
49 OPT_SCREEN_S screen;
51 try_again:
52 maxwidth = MAX(MIN((ps->ttyo ? ps->ttyo->screen_cols : 80), 150), 30);
53 first_line = NULL;
54 ctmpa = NULL;
56 for(p = flags->explanation; p && *p; p++){
57 new_confline(&ctmpa);
58 ctmpa->keymenu = &flag_keymenu;
59 ctmpa->help = NO_HELP;
60 ctmpa->tool = flag_checkbox_tool;
61 ctmpa->flags |= CF_NOSELECT;
62 ctmpa->valoffset = 0;
63 ctmpa->value = cpystr(_(*p));
66 /* Now wire flags checkboxes together */
67 for(lv = 0, lc = 0, fp = (flags->flag_table ? *flags->flag_table : NULL);
68 fp && fp->name; fp++){ /* longest name */
69 if(fp->flag != F_COMMENT){
70 if(lv < (i = utf8_width(_(fp->name))))
71 lv = i;
72 if(fp->comment && lc < (i = utf8_width(fp->comment)))
73 lc = i;
77 lv = MIN(lv,100);
78 lc = MIN(lc,100);
79 if(lc > 0)
80 spacer = " ";
81 else
82 spacer = "";
84 offset = 6;
85 if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth){
86 offset -= (need - maxwidth);
87 offset = MAX(0,offset);
88 if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth){
89 spacer = " ";
90 if((need = offset + 5 + lv + strlen(spacer) + lc) > maxwidth){
91 lc -= (need - maxwidth);
92 lc = MAX(0,lc);
93 if(lc == 0)
94 spacer = "";
99 new_confline(&ctmpa);
100 ctmpa->keymenu = &flag_keymenu;
101 ctmpa->help = NO_HELP;
102 ctmpa->tool = flag_checkbox_tool;
103 ctmpa->flags |= CF_NOSELECT;
104 ctmpa->valoffset = 0;
105 ctmpa->value = cpystr("");
107 new_confline(&ctmpa);
108 ctmpa->keymenu = &flag_keymenu;
109 ctmpa->help = NO_HELP;
110 ctmpa->tool = flag_checkbox_tool;
111 ctmpa->flags |= CF_NOSELECT;
112 ctmpa->valoffset = 0;
113 utf8_snprintf(tmp, sizeof(tmp), "%*.*w %s", offset+3, offset+3, _("Set"), _("Flag/Keyword Name"));
114 tmp[sizeof(tmp)-1] = '\0';
115 ctmpa->value = cpystr(tmp);
117 new_confline(&ctmpa);
118 ctmpa->keymenu = &flag_keymenu;
119 ctmpa->help = NO_HELP;
120 ctmpa->tool = flag_checkbox_tool;
121 ctmpa->flags |= CF_NOSELECT;
122 ctmpa->valoffset = 0;
123 snprintf(tmp, sizeof(tmp), "%*.*s--- %.*s",
124 offset, offset, "",
125 (int)(lv+lc+strlen(spacer)), repeat_char(lv+lc+strlen(spacer), '-'));
126 tmp[sizeof(tmp)-1] = '\0';
127 ctmpa->value = cpystr(tmp);
129 for(fp = (flags->flag_table ? *flags->flag_table : NULL);
130 fp && fp->name; fp++){ /* build the list */
131 new_confline(&ctmpa);
132 if(!first_line && (fp->flag != F_COMMENT))
133 first_line = ctmpa;
135 ctmpa->keymenu = &flag_keymenu;
136 ctmpa->tool = flag_checkbox_tool;
137 ctmpa->valoffset = offset;
139 if(fp->flag == F_COMMENT){
140 ctmpa->help = NO_HELP;
141 ctmpa->flags |= CF_NOSELECT;
142 ctmpa->value = cpystr(fp->name);
144 else{
145 ctmpa->help = fp->help;
146 ctmpa->d.f.ftbl = flags->flag_table;
147 ctmpa->d.f.fp = fp;
149 utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w%s%-*.*w",
150 (fp->set == 0) ? ' ' : (fp->set == 1) ? 'X' : '?',
151 lv, lv, _(fp->name),
152 spacer, lc, lc, fp->comment ? fp->comment : "");
153 ctmpa->value = cpystr(tmp);
157 memset(&screen, 0, sizeof(screen));
159 * TRANSLATORS: FLAG MAINTENANCE is a screen title.
160 * Print something1 using something2. configuration is something1
162 if(conf_scroll_screen(ps, &screen, first_line,
163 _("FLAG MAINTENANCE"),
164 _("configuration"), 0, NULL) == FLAG_ADD_RETURN){
165 int flags, r;
166 char keyword[500];
167 char nickname[500];
168 char prompt[500];
169 char *error = NULL;
170 KEYWORD_S *kw;
171 HelpType help;
174 * User is asking to add a new keyword. We will add it to the
175 * mailbox if necessary and add it to the keywords list from
176 * Setup/Config. Then we will modify the flag_table and present
177 * the flag modification screen again.
180 ps->mangled_screen = 1;
181 keyword[0] = '\0';
182 flags = OE_APPEND_CURRENT;
183 help = NO_HELP;
186 if(error){
187 q_status_message(SM_ORDER, 3, 4, error);
188 fs_give((void **) &error);
191 strncpy(prompt, _("Keyword to be added : "), sizeof(prompt)-1);
192 prompt[sizeof(prompt)-1] = '\0';
193 r = optionally_enter(keyword, -FOOTER_ROWS(ps_global), 0,
194 sizeof(keyword), prompt, NULL, help, &flags);
196 if(r == 3)
197 help = help == NO_HELP ? h_type_keyword : NO_HELP;
198 else if(r == 1){
199 cmd_cancelled("Add Keyword");
200 goto try_again;
203 removing_leading_and_trailing_white_space(keyword);
205 }while(r == 3 || keyword_check(keyword, &error));
207 for(kw = ps->keywords; kw; kw = kw->next){
208 if(kw->kw && !strucmp(kw->kw, keyword)){
209 q_status_message(SM_ORDER, 3, 4, _("Keyword already configured, changing nickname"));
210 break;
214 snprintf(prompt, sizeof(prompt), _("Optional nickname for \"%s\" : "), keyword);
216 nickname[0] = '\0';
217 help = NO_HELP;
220 r = optionally_enter(nickname, -FOOTER_ROWS(ps_global), 0,
221 sizeof(nickname), prompt, NULL, help, &flags);
223 if(r == 3)
224 help = help == NO_HELP ? h_type_keyword_nickname : NO_HELP;
225 else if(r == 1){
226 cmd_cancelled("Add Keyword");
227 goto try_again;
230 removing_leading_and_trailing_white_space(nickname);
232 }while(r == 3);
234 if(keyword[0]){
235 char ***alval;
236 int offset = -1;
237 struct variable *var;
239 var = &ps_global->vars[V_KEYWORDS];
240 alval = ALVAL(var, Main);
242 for(kw = ps->keywords; kw; kw = kw->next){
243 offset++;
244 if(kw->kw && !strucmp(kw->kw, keyword)){
245 /* looks like it should already exist at offset */
246 break;
250 if(!kw)
251 offset = -1;
253 if(offset >= 0 && (*alval) && (*alval)[offset]){
254 fs_give((void **) &(*alval)[offset]);
255 (*alval)[offset] = put_pair(nickname, keyword);
257 else if(!*alval){
258 offset = 0;
259 *alval = (char **) fs_get(2*sizeof(char *));
260 (*alval)[offset] = put_pair(nickname, keyword);
261 (*alval)[offset+1] = NULL;
263 else{
264 for(offset=0; (*alval)[offset]; offset++)
267 fs_resize((void **) alval, (offset + 2) * sizeof(char *));
268 (*alval)[offset] = put_pair(nickname, keyword);
269 (*alval)[offset+1] = NULL;
272 set_current_val(var, TRUE, FALSE);
273 if(ps_global->prc)
274 ps_global->prc->outstanding_pinerc_changes = 1;
276 if(ps_global->keywords)
277 free_keyword_list(&ps_global->keywords);
279 if(var->current_val.l && var->current_val.l[0])
280 ps_global->keywords = init_keyword_list(var->current_val.l);
282 clear_index_cache(ps_global->mail_stream, 0);
284 rv = 1;
288 ps->mangled_screen = 1;
290 return(rv);
295 * Message flag manipulation tool
298 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
301 flag_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
303 int rv = 0, state;
305 switch(cmd){
306 case MC_TOGGLE: /* mark/unmark feature */
307 state = (*cl)->d.f.fp->set;
308 state = (state == 1) ? 0 : (!state && ((*cl)->d.f.fp->ukn)) ? 2 : 1;
309 (*cl)->value[1] = (state == 0) ? ' ' : ((state == 1) ? 'X': '?');
310 (*cl)->d.f.fp->set = state;
311 rv = 1;
312 break;
314 case MC_ADD:
315 rv = FLAG_ADD_RETURN;
316 break;
318 case MC_EXIT: /* exit */
319 rv = simple_exit_cmd(flags);
320 break;
322 default :
323 rv = -1;
324 break;
327 return(rv);