* S/MIME: validation of signed messages in servers that modify
[alpine.git] / alpine / colorconf.c
blob3ff1dcb0ad646dc723cd6c0954d420b205e59fea
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: colorconf.c 934 2008-02-23 00:44:29Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2014 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
20 #include "headers.h"
21 #include "colorconf.h"
22 #include "keymenu.h"
23 #include "status.h"
24 #include "confscroll.h"
25 #include "radio.h"
26 #include "mailview.h"
27 #include "../pith/state.h"
28 #include "../pith/util.h"
29 #include "../pith/color.h"
30 #include "../pith/icache.h"
31 #include "../pith/mailcmd.h"
32 #include "../pith/mailindx.h"
33 #include "../pith/list.h"
37 * Internal prototypes
39 char *colorindexrule(char *);
40 char *color_setting_text_line(struct pine *, struct variable *);
41 void revert_to_saved_color_config(struct pine *, SAVED_CONFIG_S *);
42 SAVED_CONFIG_S *save_color_config_vars(struct pine *);
43 void free_saved_color_config(struct pine *, SAVED_CONFIG_S **);
44 void color_config_init_display(struct pine *, CONF_S **, CONF_S **);
45 void add_header_color_line(struct pine *, CONF_S **, char *, int, int);
46 int is_rgb_color(char *);
47 char *new_color_line(char *, int, int, int);
48 int color_text_tool(struct pine *, int, CONF_S **, unsigned);
49 int offer_normal_color_for_var(struct pine *, struct variable *);
50 int offer_none_color_for_var(struct pine *, struct variable *);
51 void color_update_selected(struct pine *, CONF_S *, char *, char *, int);
52 int color_edit_screen(struct pine *, CONF_S **);
55 int treat_color_vars_as_text;
58 void
59 color_config_screen(struct pine *ps, int edit_exceptions)
61 CONF_S *ctmp = NULL, *first_line = NULL;
62 SAVED_CONFIG_S *vsave;
63 OPT_SCREEN_S screen;
64 int readonly_warning = 0;
66 ps->next_screen = SCREEN_FUN_NULL;
68 mailcap_free(); /* free resources we won't be using for a while */
70 if(ps->fix_fixed_warning)
71 offer_to_fix_pinerc(ps);
73 ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
75 if(ps->restricted)
76 readonly_warning = 1;
77 else{
78 PINERC_S *prc = NULL;
80 switch(ew){
81 case Main:
82 prc = ps->prc;
83 break;
84 case Post:
85 prc = ps->post_prc;
86 break;
87 default:
88 break;
91 readonly_warning = prc ? prc->readonly : 1;
92 if(prc && prc->quit_to_edit){
93 quit_to_edit_msg(prc);
94 return;
98 color_config_init_display(ps, &ctmp, &first_line);
100 vsave = save_color_config_vars(ps);
102 memset(&screen, 0, sizeof(screen));
103 screen.deferred_ro_warning = readonly_warning;
104 switch(conf_scroll_screen(ps, &screen, first_line,
105 edit_exceptions ? _("SETUP COLOR EXCEPTIONS")
106 : _("SETUP COLOR"),
107 /* TRANSLATORS: Print something1 using something2.
108 configuration is something1 */
109 _("configuration"), 0)){
110 case 0:
111 break;
113 case 1:
114 write_pinerc(ps, ew, WRP_NONE);
115 break;
117 case 10:
118 revert_to_saved_color_config(ps, vsave);
119 break;
121 default:
122 q_status_message(SM_ORDER, 7, 10,
123 _("conf_scroll_screen bad ret in color_config"));
124 break;
127 free_saved_color_config(ps, &vsave);
129 #ifdef _WINDOWS
130 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
131 #endif
135 char *
136 sample_text(struct pine *ps, struct variable *v)
138 char *ret = SAMP2;
139 char *pvalfg, *pvalbg;
141 pvalfg = PVAL(v, ew);
142 pvalbg = PVAL(v+1, ew);
144 if((v && v->name &&
145 srchstr(v->name, "-foreground-color") &&
146 pvalfg && pvalfg[0] && pvalbg && pvalbg[0]) ||
147 (v == &ps->vars[V_INDEX_TOKEN_COLORS] ||
148 v == &ps->vars[V_VIEW_HDR_COLORS] || v == &ps->vars[V_KW_COLORS]))
149 ret = SAMP1;
151 return(ret);
155 char *
156 sampleexc_text(struct pine *ps, struct variable *v)
158 char *ret = "";
159 char *pvalfg, *pvalbg;
161 pvalfg = PVAL(v, Post);
162 pvalbg = PVAL(v+1, Post);
163 if(v && color_holding_var(ps, v) &&
164 srchstr(v->name, "-foreground-color")){
165 if(ew == Main && pvalfg && pvalfg[0] && pvalbg && pvalbg[0])
166 ret = SAMPEXC;
169 return(ret);
173 char *
174 color_setting_text_line(struct pine *ps, struct variable *v)
176 char *p;
177 char tmp[1200];
179 p = sampleexc_text(ps, v);
182 * Don't need to use utf8_snprintf if we're not trying to
183 * control the widths of fields.
185 snprintf(tmp, sizeof(tmp), "%s %s%*s%s%s", SAMPLE_LEADER,
186 sample_text(ps,v), *p ? SBS : 0, "", p,
187 color_parenthetical(v));
188 return(cpystr(tmp));
193 * Compare saved user_val with current user_val to see if it changed.
194 * If any have changed, change it back and take the appropriate action.
196 void
197 revert_to_saved_color_config(struct pine *ps, SAVED_CONFIG_S *vsave)
199 struct variable *vreal;
200 SAVED_CONFIG_S *v;
201 int i, n;
202 int changed = 0;
203 char *pval, **apval, **lval, ***alval;
205 v = vsave;
206 for(vreal = ps->vars; vreal->name; vreal++,v++){
207 if(!(color_related_var(ps, vreal) || vreal==&ps->vars[V_FEATURE_LIST]))
208 continue;
210 if(vreal->is_list){
211 lval = LVAL(vreal, ew);
212 alval = ALVAL(vreal, ew);
214 if((v->saved_user_val.l && !lval)
215 || (!v->saved_user_val.l && lval))
216 changed++;
217 else if(!v->saved_user_val.l && !lval)
218 ;/* no change, nothing to do */
219 else
220 for(i = 0; v->saved_user_val.l[i] || lval[i]; i++)
221 if((v->saved_user_val.l[i]
222 && (!lval[i]
223 || strcmp(v->saved_user_val.l[i], lval[i])))
225 (!v->saved_user_val.l[i] && lval[i])){
226 changed++;
227 break;
230 if(changed){
231 char **list;
233 if(alval){
234 if(*alval)
235 free_list_array(alval);
237 /* copy back the original one */
238 if(v->saved_user_val.l){
239 list = v->saved_user_val.l;
240 n = 0;
241 /* count how many */
242 while(list[n])
243 n++;
245 *alval = (char **)fs_get((n+1) * sizeof(char *));
247 for(i = 0; i < n; i++)
248 (*alval)[i] = cpystr(v->saved_user_val.l[i]);
250 (*alval)[n] = NULL;
255 else{
256 pval = PVAL(vreal, ew);
257 apval = APVAL(vreal, ew);
259 if((v->saved_user_val.p &&
260 (!pval || strcmp(v->saved_user_val.p, pval))) ||
261 (!v->saved_user_val.p && pval)){
262 /* It changed, fix it */
263 changed++;
264 if(apval){
265 /* free the changed value */
266 if(*apval)
267 fs_give((void **)apval);
269 if(v->saved_user_val.p)
270 *apval = cpystr(v->saved_user_val.p);
275 if(changed){
276 if(vreal == &ps->vars[V_FEATURE_LIST])
277 set_feature_list_current_val(vreal);
278 else
279 set_current_val(vreal, TRUE, FALSE);
281 fix_side_effects(ps, vreal, 1);
285 if(changed){
286 set_current_color_vals(ps);
287 ClearScreen();
288 ps->mangled_screen = 1;
293 SAVED_CONFIG_S *
294 save_color_config_vars(struct pine *ps)
296 struct variable *vreal;
297 SAVED_CONFIG_S *vsave, *v;
299 vsave = (SAVED_CONFIG_S *)fs_get((V_LAST_VAR+1)*sizeof(SAVED_CONFIG_S));
300 memset((void *)vsave, 0, (V_LAST_VAR+1)*sizeof(SAVED_CONFIG_S));
301 v = vsave;
302 for(vreal = ps->vars; vreal->name; vreal++,v++){
303 if(!(color_related_var(ps, vreal) || vreal==&ps->vars[V_FEATURE_LIST]))
304 continue;
306 if(vreal->is_list){
307 int n, i;
308 char **list;
310 if(LVAL(vreal, ew)){
311 /* count how many */
312 n = 0;
313 list = LVAL(vreal, ew);
314 while(list[n])
315 n++;
317 v->saved_user_val.l = (char **)fs_get((n+1) * sizeof(char *));
318 memset((void *)v->saved_user_val.l, 0, (n+1)*sizeof(char *));
319 for(i = 0; i < n; i++)
320 v->saved_user_val.l[i] = cpystr(list[i]);
322 v->saved_user_val.l[n] = NULL;
325 else{
326 if(PVAL(vreal, ew))
327 v->saved_user_val.p = cpystr(PVAL(vreal, ew));
331 return(vsave);
335 void
336 free_saved_color_config(struct pine *ps, SAVED_CONFIG_S **vsavep)
338 struct variable *vreal;
339 SAVED_CONFIG_S *v;
341 if(vsavep && *vsavep){
342 for(v = *vsavep, vreal = ps->vars; vreal->name; vreal++,v++){
343 if(!(color_related_var(ps, vreal) ||
344 (vreal == &ps->vars[V_FEATURE_LIST])))
345 continue;
347 if(vreal->is_list){ /* free saved_user_val.l */
348 if(v && v->saved_user_val.l)
349 free_list_array(&v->saved_user_val.l);
351 else if(v && v->saved_user_val.p)
352 fs_give((void **)&v->saved_user_val.p);
355 fs_give((void **)vsavep);
360 void
361 color_config_init_display(struct pine *ps, CONF_S **ctmp, CONF_S **first_line)
363 char **lval;
364 int i, saw_first_index = 0;
365 struct variable *vtmp;
366 char *dashes = "--------------";
368 #ifndef _WINDOWS
369 vtmp = &ps->vars[V_COLOR_STYLE];
371 new_confline(ctmp);
372 (*ctmp)->flags |= (CF_NOSELECT | CF_STARTITEM);
373 (*ctmp)->keymenu = &config_radiobutton_keymenu;
374 (*ctmp)->tool = NULL;
375 (*ctmp)->varname = cpystr("Color Style");
376 (*ctmp)->varnamep = *ctmp;
378 standard_radio_setup(ps, ctmp, vtmp, first_line);
380 new_confline(ctmp);
381 /* Blank line */
382 (*ctmp)->flags |= (CF_NOSELECT | CF_B_LINE);
384 if(!pico_usingcolor()){
385 /* add a line explaining that color is not turned on */
386 new_confline(ctmp);
387 (*ctmp)->help = NO_HELP;
388 (*ctmp)->flags |= CF_NOSELECT;
389 (*ctmp)->value = cpystr(COLORNOSET);
391 new_confline(ctmp);
392 /* Blank line */
393 (*ctmp)->flags |= (CF_NOSELECT | CF_B_LINE);
396 #endif
398 vtmp = &ps->vars[V_INDEX_COLOR_STYLE];
400 new_confline(ctmp);
401 (*ctmp)->flags |= (CF_NOSELECT | CF_STARTITEM);
402 (*ctmp)->keymenu = &config_radiobutton_keymenu;
403 (*ctmp)->tool = NULL;
404 (*ctmp)->varname = cpystr(_("Current Indexline Style"));
405 (*ctmp)->varnamep = *ctmp;
407 standard_radio_setup(ps, ctmp, vtmp, NULL);
409 new_confline(ctmp);
410 /* Blank line */
411 (*ctmp)->flags |= (CF_NOSELECT | CF_B_LINE);
413 vtmp = &ps->vars[V_TITLEBAR_COLOR_STYLE];
415 new_confline(ctmp);
416 (*ctmp)->flags |= (CF_NOSELECT | CF_STARTITEM);
417 (*ctmp)->keymenu = &config_radiobutton_keymenu;
418 (*ctmp)->tool = NULL;
419 (*ctmp)->varname = cpystr(_("Titlebar Color Style"));
420 (*ctmp)->varnamep = *ctmp;
422 standard_radio_setup(ps, ctmp, vtmp, NULL);
424 new_confline(ctmp);
425 /* Blank line */
426 (*ctmp)->flags |= (CF_NOSELECT | CF_B_LINE);
428 new_confline(ctmp);
429 /* title before general colors */
430 (*ctmp)->help = NO_HELP;
431 (*ctmp)->flags |= CF_NOSELECT;
432 (*ctmp)->value = cpystr(dashes);
433 new_confline(ctmp);
434 (*ctmp)->help = NO_HELP;
435 (*ctmp)->flags |= CF_NOSELECT;
436 (*ctmp)->value = cpystr(_("GENERAL COLORS"));
437 new_confline(ctmp);
438 (*ctmp)->help = NO_HELP;
439 (*ctmp)->flags |= CF_NOSELECT;
440 (*ctmp)->value = cpystr(dashes);
442 for(vtmp = ps->vars; vtmp->name; vtmp++){
443 if(!color_holding_var(ps, vtmp))
444 continue;
446 /* If not foreground, skip it */
447 if(!srchstr(vtmp->name, "-foreground-color"))
448 continue;
450 /* skip this for now and include it with HEADER COLORS */
451 if(vtmp == &ps->vars[V_HEADER_GENERAL_FORE_COLOR])
452 continue;
454 if(!saw_first_index && !struncmp(vtmp->name, "index-", 6)){
455 saw_first_index++;
456 new_confline(ctmp); /* Blank line */
457 (*ctmp)->flags |= (CF_NOSELECT | CF_B_LINE);
458 new_confline(ctmp);
459 (*ctmp)->help = NO_HELP;
460 (*ctmp)->flags |= CF_NOSELECT;
461 (*ctmp)->value = cpystr(dashes);
462 new_confline(ctmp);
463 (*ctmp)->help = NO_HELP;
464 (*ctmp)->flags |= CF_NOSELECT;
465 (*ctmp)->value = cpystr(_("INDEX COLORS"));
466 new_confline(ctmp);
467 (*ctmp)->help = NO_HELP;
468 (*ctmp)->flags |= CF_NOSELECT;
469 (*ctmp)->value = cpystr(dashes);
472 new_confline(ctmp);
473 /* Blank line */
474 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
476 new_confline(ctmp)->var = vtmp;
477 if(first_line && !*first_line)
478 *first_line = *ctmp;
480 (*ctmp)->varnamep = *ctmp;
481 (*ctmp)->keymenu = &color_setting_keymenu;
482 (*ctmp)->help = config_help(vtmp - ps->vars, 0);
483 (*ctmp)->tool = color_setting_tool;
484 (*ctmp)->flags |= (CF_STARTITEM | CF_COLORSAMPLE | CF_POT_SLCTBL);
485 if(!pico_usingcolor())
486 (*ctmp)->flags |= CF_NOSELECT;
488 (*ctmp)->value = pretty_value(ps, *ctmp);
489 (*ctmp)->valoffset = COLOR_INDENT;
493 * custom index tokens colors
495 vtmp = &ps->vars[V_INDEX_TOKEN_COLORS];
496 lval = LVAL(vtmp, ew);
498 if(lval && lval[0] && lval[0][0]){
499 for(i = 0; lval && lval[i]; i++)
500 add_header_color_line(ps, ctmp, lval[i], i, V_INDEX_TOKEN_COLORS);
502 else{
503 new_confline(ctmp); /* Blank line */
504 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
505 new_confline(ctmp);
506 (*ctmp)->help = NO_HELP;
507 (*ctmp)->flags |= CF_NOSELECT;
508 (*ctmp)->value = cpystr(_(ADDINDEXTOKEN_COMMENT));
509 (*ctmp)->valoffset = COLOR_INDENT;
513 * custom header colors
515 new_confline(ctmp); /* Blank line */
516 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
517 new_confline(ctmp);
518 (*ctmp)->help = NO_HELP;
519 (*ctmp)->flags |= CF_NOSELECT;
520 (*ctmp)->value = cpystr(dashes);
521 new_confline(ctmp);
522 (*ctmp)->help = NO_HELP;
523 (*ctmp)->flags |= CF_NOSELECT;
524 (*ctmp)->value = cpystr(_(HDR_COLORS));
525 new_confline(ctmp);
526 (*ctmp)->help = NO_HELP;
527 (*ctmp)->flags |= CF_NOSELECT;
528 (*ctmp)->value = cpystr(dashes);
530 vtmp = &ps->vars[V_HEADER_GENERAL_FORE_COLOR];
531 new_confline(ctmp);
532 /* Blank line */
533 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
535 new_confline(ctmp)->var = vtmp;
537 (*ctmp)->varnamep = *ctmp;
538 (*ctmp)->keymenu = &color_setting_keymenu;
539 (*ctmp)->help = config_help(vtmp - ps->vars, 0);
540 (*ctmp)->tool = color_setting_tool;
541 (*ctmp)->flags |= (CF_STARTITEM | CF_COLORSAMPLE | CF_POT_SLCTBL);
542 if(!pico_usingcolor())
543 (*ctmp)->flags |= CF_NOSELECT;
545 (*ctmp)->value = pretty_value(ps, *ctmp);
546 (*ctmp)->valoffset = COLOR_INDENT;
548 vtmp = &ps->vars[V_VIEW_HDR_COLORS];
549 lval = LVAL(vtmp, ew);
551 if(lval && lval[0] && lval[0][0]){
552 for(i = 0; lval && lval[i]; i++)
553 add_header_color_line(ps, ctmp, lval[i], i, V_VIEW_HDR_COLORS);
555 else{
556 new_confline(ctmp); /* Blank line */
557 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
558 new_confline(ctmp);
559 (*ctmp)->help = NO_HELP;
560 (*ctmp)->flags |= CF_NOSELECT;
561 (*ctmp)->value = cpystr(_(ADDHEADER_COMMENT));
562 (*ctmp)->valoffset = COLOR_INDENT;
567 * custom keyword colors
569 new_confline(ctmp); /* Blank line */
570 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
571 new_confline(ctmp);
572 (*ctmp)->help = NO_HELP;
573 (*ctmp)->flags |= CF_NOSELECT;
574 (*ctmp)->value = cpystr(dashes);
575 new_confline(ctmp);
576 (*ctmp)->help = NO_HELP;
577 (*ctmp)->flags |= CF_NOSELECT;
578 (*ctmp)->value = cpystr(KW_COLORS_HDR);
579 new_confline(ctmp);
580 (*ctmp)->help = NO_HELP;
581 (*ctmp)->flags |= CF_NOSELECT;
582 (*ctmp)->value = cpystr(dashes);
585 if(ps->keywords){
586 KEYWORD_S *kw;
587 char *name, *comment, *word;
588 int j, lv = 0, lc = 0, ltot = 0, eq_col = EQ_COL;
590 vtmp = &ps->vars[V_KW_COLORS];
592 /* first figure out widths for display */
593 for(kw = ps->keywords; kw; kw = kw->next){
594 word = kw->nick ? kw->nick : kw->kw ? kw->kw : "";
595 i = utf8_width(word);
596 if(lv < i)
597 lv = i;
599 j = 0;
600 if(kw->nick && kw->kw && kw->kw[0]){
601 word = kw->kw;
602 j = utf8_width(word) + 2;
603 if(lc < j)
604 lc = j;
607 if(ltot < (i + (j > 2 ? j : 0)))
608 ltot = (i + (j > 2 ? j : 0));
611 lv = MIN(lv, 100);
612 lc = MIN(lc, 100);
613 ltot = MIN(ltot, 100);
616 * SC is width of " Color"
617 * SS is space between nickname and keyword value
618 * SW is space between words and Sample
620 #define SC 6
621 #define SS 1
622 #define SW 3
623 if(COLOR_INDENT + SC + ltot + (lc>0?SS:0) > eq_col - SW){
624 eq_col = MIN(MAX(ps->ttyo->screen_cols - 10, 20),
625 COLOR_INDENT + SC + ltot + (lc>0?SS:0) + SW);
626 if(COLOR_INDENT + SC + ltot + (lc>0?SS:0) > eq_col - SW){
627 eq_col = MIN(MAX(ps->ttyo->screen_cols - 10, 20),
628 COLOR_INDENT + SC + lv + (lc>0?SS:0) + lc + SW);
629 if(COLOR_INDENT + SC + lv + (lc>0?SS:0) + lc > eq_col - SW){
630 lc = MIN(lc, MAX(eq_col - SW - COLOR_INDENT - SC - lv - SS, 7));
631 if(COLOR_INDENT + SC + lv + (lc>0?SS:0) + lc > eq_col - SW){
632 lc = 0;
633 if(COLOR_INDENT + SC + lv > eq_col - SW){
634 lv = MAX(eq_col - SW - COLOR_INDENT - SC, 7);
641 lval = LVAL(vtmp, ew);
642 if(lval && lval[0] && !strcmp(lval[0], INHERIT)){
643 new_confline(ctmp);
644 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
646 new_confline(ctmp)->var = vtmp;
647 (*ctmp)->varnamep = *ctmp;
648 (*ctmp)->keymenu = &kw_color_setting_keymenu;
649 (*ctmp)->help = config_help(vtmp - ps->vars, 0);
650 (*ctmp)->tool = color_setting_tool;
651 (*ctmp)->varmem = CFC_SET_COLOR(i, 0);
652 (*ctmp)->valoffset = COLOR_INDENT;
654 (*ctmp)->flags = (CF_NOSELECT | CF_INHERIT);
657 /* now create the config lines */
658 for(kw = ps->keywords, i = 0; kw; kw = kw->next, i++){
659 char tmp[2000];
661 /* Blank line */
662 new_confline(ctmp);
663 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
665 new_confline(ctmp)->var = vtmp;
666 (*ctmp)->varnamep = *ctmp;
667 (*ctmp)->keymenu = &kw_color_setting_keymenu;
668 (*ctmp)->help = config_help(vtmp - ps->vars, 0);
669 (*ctmp)->tool = color_setting_tool;
670 (*ctmp)->flags |= (CF_STARTITEM | CF_COLORSAMPLE | CF_POT_SLCTBL);
671 if(!pico_usingcolor())
672 (*ctmp)->flags |= CF_NOSELECT;
675 * Not actually a color in this case, it is an index into
676 * the keywords list.
678 (*ctmp)->varmem = CFC_SET_COLOR(i, 0);
680 name = short_str(kw->nick ? kw->nick : kw->kw ? kw->kw : "",
681 tmp_20k_buf+10000, 1000, lv, EndDots);
682 if(lc > 0 && kw->nick && kw->kw && kw->kw[0])
683 comment = short_str(kw->kw, tmp_20k_buf+11000, SIZEOF_20KBUF - 11000, lc, EndDots);
684 else
685 comment = NULL;
687 utf8_snprintf(tmp, sizeof(tmp), "%.*w%*s%s%.*w%s Color%*s %s%s",
688 lv, name,
689 (lc > 0 && comment) ? SS : 0, "",
690 (lc > 0 && comment) ? "(" : "",
691 (lc > 0 && comment) ? lc : 0, (lc > 0 && comment) ? comment : "",
692 (lc > 0 && comment) ? ")" : "",
693 MAX(MIN(eq_col - COLOR_INDENT - MIN(lv,utf8_width(name))
694 - SC - 1
695 - ((lc > 0 && comment)
696 ? (SS+2+MIN(lc,utf8_width(comment))) : 0), 100), 0), "",
697 sample_text(ps,vtmp),
698 color_parenthetical(vtmp));
700 (*ctmp)->value = cpystr(tmp);
701 (*ctmp)->valoffset = COLOR_INDENT;
704 else{
705 new_confline(ctmp); /* Blank line */
706 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
707 new_confline(ctmp);
708 (*ctmp)->help = NO_HELP;
709 (*ctmp)->flags |= CF_NOSELECT;
710 (*ctmp)->value = cpystr(_("[ Use Setup/Config command to add Keywords ]"));
711 (*ctmp)->valoffset = COLOR_INDENT;
716 char *
717 color_parenthetical(struct variable *var)
719 int norm, exc, exc_inh;
720 char **lval, *ret = "";
722 if(var == &ps_global->vars[V_VIEW_HDR_COLORS]
723 || var == &ps_global->vars[V_INDEX_TOKEN_COLORS]
724 || var == &ps_global->vars[V_KW_COLORS]){
725 norm = (LVAL(var, Main) != NULL);
726 exc = (LVAL(var, ps_global->ew_for_except_vars) != NULL);
727 exc_inh = ((lval=LVAL(var, ps_global->ew_for_except_vars)) &&
728 lval[0] && !strcmp(INHERIT, lval[0]));
730 /* editing normal but there is an exception config */
731 if((ps_global->ew_for_except_vars != Main) && (ew == Main)){
732 if((exc && !exc_inh))
733 ret = _(" (overridden by exceptions)");
734 else if(exc && exc_inh)
735 ret = _(" (more in exceptions)");
737 /* editing exception config */
738 else if((ps_global->ew_for_except_vars != Main) &&
739 (ew == ps_global->ew_for_except_vars)){
740 if(exc && exc_inh && norm)
741 ret = _(" (more in main config)");
745 return(ret);
749 void
750 add_header_color_line(struct pine *ps, CONF_S **ctmp, char *val, int which, int varnum)
752 struct variable *vtmp;
753 SPEC_COLOR_S *hc;
754 char tmp[100+1];
755 int l;
757 hc = spec_color_from_var(val, 0);
758 if(varnum == V_INDEX_TOKEN_COLORS){
759 if(hc == NULL || hc->spec == NULL
760 || itoktype(hc->spec, FOR_INDEX) == NULL)
761 return;
763 vtmp = &ps->vars[varnum];
764 l = strlen(varnum == V_VIEW_HDR_COLORS ? HEADER_WORD : TOKEN_WORD);
766 /* Blank line */
767 new_confline(ctmp);
768 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
770 new_confline(ctmp)->var = vtmp;
771 (*ctmp)->varnamep = *ctmp;
772 (*ctmp)->keymenu = &custom_color_setting_keymenu;
773 (*ctmp)->help = config_help(vtmp - ps->vars, 0);
774 (*ctmp)->tool = color_setting_tool;
775 (*ctmp)->flags |= (CF_STARTITEM | CF_COLORSAMPLE | CF_POT_SLCTBL);
776 if(!pico_usingcolor())
777 (*ctmp)->flags |= CF_NOSELECT;
779 /* which is an index into the variable list */
780 (*ctmp)->varmem = CFC_SET_COLOR(which, 0);
782 if(hc && hc->inherit)
783 (*ctmp)->flags = (CF_NOSELECT | CF_INHERIT);
784 else{
786 * This isn't quite right because of the assumption that the
787 * first character of spec fits in one octet. I haven't tried
788 * to figure out what we're really trying to accomplish
789 * with all this. It probably doesn't happen in real life.
791 utf8_snprintf(tmp, sizeof(tmp), "%s%c%.*w Color%*w %s%s",
792 (varnum == V_VIEW_HDR_COLORS ? HEADER_WORD : TOKEN_WORD),
793 (hc && hc->spec) ? (islower((unsigned char)hc->spec[0])
794 ? toupper((unsigned char)hc->spec[0])
795 : hc->spec[0]) : '?',
796 MIN(utf8_width((hc && hc->spec && hc->spec[0]) ? hc->spec+1 : ""),30-l),
797 (hc && hc->spec && hc->spec[0]) ? hc->spec+1 : "",
798 MAX(EQ_COL - COLOR_INDENT -1 -
799 MIN(utf8_width((hc && hc->spec && hc->spec[0]) ? hc->spec+1 : ""),30-l)
800 - l - 6 - 1, 0), "",
801 sample_text(ps,vtmp),
802 color_parenthetical(vtmp));
803 tmp[sizeof(tmp)-1] = '\0';
804 (*ctmp)->value = cpystr(tmp);
807 (*ctmp)->valoffset = COLOR_INDENT;
809 if(hc)
810 free_spec_colors(&hc);
815 * Set up the standard color setting display for one color.
817 * Args fg -- the current foreground color
818 * bg -- the current background color
819 * def -- default box should be checked
821 void
822 add_color_setting_disp(struct pine *ps, CONF_S **ctmp, struct variable *var,
823 CONF_S *varnamep, struct key_menu *km,
824 struct key_menu *cb_km, HelpType help, int indent,
825 int which, char *fg, char *bg, int def)
827 int i, lv, count, trans_is_on, transparent;
828 char tmp[100+1];
829 char *title = _("HELP FOR SETTING UP COLOR");
830 int fg_is_custom = 1, bg_is_custom = 1;
831 #ifdef _WINDOWS
832 CONF_S *cl_custom = NULL;
833 #else
834 char *pvalfg, *pvalbg;
835 #endif
838 /* find longest value's name */
839 count = pico_count_in_color_table();
840 lv = COLOR_BLOB_LEN;
842 trans_is_on = pico_trans_is_on();
844 /* put a title before list */
845 new_confline(ctmp);
846 (*ctmp)->varnamep = varnamep;
847 (*ctmp)->keymenu = km;
848 (*ctmp)->help = NO_HELP;
849 (*ctmp)->tool = color_setting_tool;
850 (*ctmp)->valoffset = indent;
851 (*ctmp)->flags |= CF_NOSELECT;
852 (*ctmp)->varmem = 0;
855 * The width of Foreground plus the spaces before Background should
856 * be about lv + 5 + SPACE_BETWEEN_DOUBLEVARS.
858 (*ctmp)->value = cpystr("Foreground Background");
860 new_confline(ctmp)->var = var;
861 (*ctmp)->varnamep = varnamep;
862 (*ctmp)->keymenu = km;
863 (*ctmp)->help = NO_HELP;
864 (*ctmp)->tool = color_setting_tool;
865 (*ctmp)->valoffset = indent;
866 (*ctmp)->flags |= (CF_COLORSAMPLE | CF_NOSELECT);
867 (*ctmp)->varmem = CFC_SET_COLOR(which, 0);
868 (*ctmp)->value = color_setting_text_line(ps, var);
870 for(i = 0; i < count; i++){
871 new_confline(ctmp)->var = var;
872 (*ctmp)->varnamep = varnamep;
873 (*ctmp)->keymenu = km;
874 (*ctmp)->help = help;
875 (*ctmp)->help_title = title;
876 (*ctmp)->tool = color_setting_tool;
877 (*ctmp)->valoffset = indent;
878 /* 5 is length of "( ) " */
879 (*ctmp)->val2offset = indent + lv + 5 + SPACE_BETWEEN_DOUBLEVARS;
880 (*ctmp)->flags |= CF_DOUBLEVAR;
881 (*ctmp)->varmem = CFC_SET_COLOR(which, i);
883 transparent = (trans_is_on && i == count-1);
884 if(transparent)
885 (*ctmp)->help = h_config_usetransparent_color;
887 if(fg_is_custom && fg && !strucmp(color_to_canonical_name(fg), colorx(i)))
888 fg_is_custom = 0;
890 if(bg_is_custom && bg && !strucmp(color_to_canonical_name(bg), colorx(i)))
891 bg_is_custom = 0;
893 (*ctmp)->value = new_color_line(transparent ? COLOR_BLOB_TRAN
894 : COLOR_BLOB,
895 fg &&
896 !strucmp(color_to_canonical_name(fg), colorx(i)),
897 bg &&
898 !strucmp(color_to_canonical_name(bg), colorx(i)),
899 lv);
902 #ifdef _WINDOWS
903 new_confline(ctmp)->var = var;
904 (*ctmp)->varnamep = varnamep;
905 (*ctmp)->keymenu = (km == &custom_color_changing_keymenu)
906 ? &custom_rgb_keymenu :
907 (km == &kw_color_changing_keymenu)
908 ? &kw_rgb_keymenu : &color_rgb_keymenu;
909 (*ctmp)->help = help;
910 (*ctmp)->help_title = title;
911 (*ctmp)->tool = color_setting_tool;
912 (*ctmp)->valoffset = indent;
913 /* 5 is length of "( ) " */
914 (*ctmp)->val2offset = indent + lv + 5 + SPACE_BETWEEN_DOUBLEVARS;
915 (*ctmp)->flags |= CF_DOUBLEVAR;
916 (*ctmp)->varmem = CFC_SET_COLOR(which, i);
917 cl_custom = (*ctmp);
918 #endif
920 if(offer_normal_color_for_var(ps, var)){
921 new_confline(ctmp)->var = var;
922 (*ctmp)->varnamep = varnamep;
923 (*ctmp)->keymenu = km;
924 (*ctmp)->help = h_config_usenormal_color;
925 (*ctmp)->help_title = title;
926 (*ctmp)->tool = color_setting_tool;
927 (*ctmp)->valoffset = indent;
928 /* 5 is length of "( ) " */
929 (*ctmp)->val2offset = indent + lv + 5 + SPACE_BETWEEN_DOUBLEVARS;
930 (*ctmp)->flags |= CF_DOUBLEVAR;
931 (*ctmp)->varmem = CFC_SET_COLOR(which, CFC_ICOLOR_NORM);
932 if(fg_is_custom && fg && !struncmp(fg, MATCH_NORM_COLOR, RGBLEN))
933 fg_is_custom = 0;
935 if(bg_is_custom && bg && !struncmp(bg, MATCH_NORM_COLOR, RGBLEN))
936 bg_is_custom = 0;
938 (*ctmp)->value = new_color_line(COLOR_BLOB_NORM,
939 fg && !struncmp(fg, MATCH_NORM_COLOR, RGBLEN),
940 bg && !struncmp(bg, MATCH_NORM_COLOR, RGBLEN),
941 lv);
944 if(offer_none_color_for_var(ps, var)){
945 new_confline(ctmp)->var = var;
946 (*ctmp)->varnamep = varnamep;
947 (*ctmp)->keymenu = km;
948 (*ctmp)->help = h_config_usenone_color;
949 (*ctmp)->help_title = title;
950 (*ctmp)->tool = color_setting_tool;
951 (*ctmp)->valoffset = indent;
952 /* 5 is length of "( ) " */
953 (*ctmp)->val2offset = indent + lv + 5 + SPACE_BETWEEN_DOUBLEVARS;
954 (*ctmp)->flags |= CF_DOUBLEVAR;
955 (*ctmp)->varmem = CFC_SET_COLOR(which, CFC_ICOLOR_NONE);
956 if(fg_is_custom && fg && !struncmp(fg, MATCH_NONE_COLOR, RGBLEN))
957 fg_is_custom = 0;
959 if(bg_is_custom && bg && !struncmp(bg, MATCH_NONE_COLOR, RGBLEN))
960 bg_is_custom = 0;
962 (*ctmp)->value = new_color_line(COLOR_BLOB_NONE,
963 fg && !struncmp(fg, MATCH_NONE_COLOR, RGBLEN),
964 bg && !struncmp(bg, MATCH_NONE_COLOR, RGBLEN),
965 lv);
968 #ifdef _WINDOWS
969 if(cl_custom)
970 cl_custom->value = new_color_line("Custom", fg_is_custom, bg_is_custom, lv);
971 #endif
973 new_confline(ctmp)->var = var;
974 (*ctmp)->varnamep = varnamep;
975 (*ctmp)->keymenu = cb_km;
976 (*ctmp)->help = h_config_dflt_color;
977 (*ctmp)->help_title = title;
978 (*ctmp)->tool = color_setting_tool;
979 (*ctmp)->valoffset = indent;
980 (*ctmp)->varmem = CFC_SET_COLOR(which, 0);
981 #ifdef _WINDOWS
982 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ', "Default");
983 tmp[sizeof(tmp)-1] = '\0';
984 #else
985 pvalfg = PVAL(var,Main);
986 pvalbg = PVAL(var+1,Main);
987 if(!var->is_list &&
988 ((var == &ps->vars[V_NORM_FORE_COLOR]) ||
989 (ew == Post && pvalfg && pvalfg[0] && pvalbg && pvalbg[0]) ||
990 (var->global_val.p && var->global_val.p[0] &&
991 (var+1)->global_val.p && (var+1)->global_val.p[0])))
992 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ', "Default");
993 else if(var == &ps->vars[V_REV_FORE_COLOR])
994 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ',
995 "Default (terminal's standout mode, usually reverse video)");
996 else if(var == &ps->vars[V_SLCTBL_FORE_COLOR])
997 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ',
998 "Default (Bold Normal Color)");
999 else if(var == &ps->vars[V_TITLECLOSED_FORE_COLOR])
1000 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ',
1001 "Default (same as Title Color)");
1002 else if(var_defaults_to_rev(var))
1003 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ',
1004 "Default (same as Reverse Color)");
1005 else if(km == &kw_color_changing_keymenu)
1006 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ',
1007 "Default (same as Indexline Color)");
1008 else
1009 snprintf(tmp, sizeof(tmp), "[%c] %s", def ? 'X' : ' ',
1010 "Default (same as Normal Color)");
1012 tmp[sizeof(tmp)-1] = '\0';
1013 #endif
1014 (*ctmp)->value = cpystr(tmp);
1017 * Add a checkbox to turn bold on or off for selectable-item color.
1019 if(var == &ps->vars[V_SLCTBL_FORE_COLOR]){
1020 char **lval;
1022 new_confline(ctmp)->var = var;
1023 (*ctmp)->varnamep = varnamep;
1024 (*ctmp)->keymenu = &selectable_bold_checkbox_keymenu;
1025 (*ctmp)->help = h_config_bold_slctbl;
1026 (*ctmp)->help_title = title;
1027 (*ctmp)->tool = color_setting_tool;
1028 (*ctmp)->valoffset = indent;
1029 (*ctmp)->varmem = feature_list_index(F_SLCTBL_ITEM_NOBOLD);
1031 lval = LVAL(&ps->vars[V_FEATURE_LIST], ew);
1033 * We don't use checkbox_pretty_value here because we just want
1034 * the word Bold instead of the name of the variable and because
1035 * we are actually using the negative of the feature. That is,
1036 * the feature is really NOBOLD and we are using Bold.
1038 snprintf(tmp, sizeof(tmp), "[%c] %s",
1039 test_feature(lval, feature_list_name(F_SLCTBL_ITEM_NOBOLD), 0)
1040 ? ' ' : 'X', "Bold");
1041 tmp[sizeof(tmp)-1] = '\0';
1043 (*ctmp)->value = cpystr(tmp);
1049 is_rgb_color(char *color)
1051 int i, j;
1053 for(i = 0; i < 3; i++){
1054 if(i && *color++ != ',')
1055 return(FALSE);
1057 for(j = 0; j < 3; j++, color++)
1058 if(!isdigit((unsigned char) *color))
1059 return(FALSE);
1062 return(TRUE);
1066 char *
1067 new_color_line(char *color, int fg, int bg, int len)
1069 char tmp[256];
1071 snprintf(tmp, sizeof(tmp), "(%c) %-*.*s%*s(%c) %-*.*s",
1072 fg ? R_SELD : ' ', len, len, color, SPACE_BETWEEN_DOUBLEVARS, "",
1073 bg ? R_SELD : ' ', len, len, color);
1074 tmp[sizeof(tmp)-1] = '\0';
1075 return(cpystr(tmp));
1080 color_text_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
1082 int rv = 0, i;
1083 struct variable v, *save_var;
1084 SPEC_COLOR_S *hc, *hcolors;
1085 char *starting_val, *val, tmp[100], ***alval, **apval;
1087 if(cmd == MC_EXIT)
1088 return(simple_exit_cmd(flags));
1090 alval = ALVAL((*cl)->var, ew);
1091 if(!alval || !*alval)
1092 return(rv);
1094 hcolors = spec_colors_from_varlist(*alval, 0);
1096 for(hc = hcolors, i=0; hc; hc = hc->next, i++)
1097 if(CFC_ICUST(*cl) == i)
1098 break;
1100 starting_val = (hc && hc->val) ? pattern_to_string(hc->val) : NULL;
1102 memset(&v, 0, sizeof(v));
1103 v.is_used = 1;
1104 v.is_user = 1;
1105 snprintf(tmp, sizeof(tmp), "\"%c%s Pattern\"",
1106 islower((unsigned char)hc->spec[0])
1107 ? toupper((unsigned char)hc->spec[0])
1108 : hc->spec[0],
1109 hc->spec[1] ? hc->spec + 1 : "");
1110 tmp[sizeof(tmp)-1] = '\0';
1111 v.name = tmp;
1112 /* have to use right part of v so text_tool will work right */
1113 apval = APVAL(&v, ew);
1114 *apval = starting_val ? cpystr(starting_val) : NULL;
1115 set_current_val(&v, FALSE, FALSE);
1117 save_var = (*cl)->var;
1118 (*cl)->var = &v;
1119 rv = text_tool(ps, cmd, cl, flags);
1121 if(rv == 1){
1122 val = *apval;
1123 *apval = NULL;
1124 if(val)
1125 removing_leading_and_trailing_white_space(val);
1127 if(hc->val)
1128 fs_give((void **)&hc->val);
1130 hc->val = string_to_pattern(val);
1132 (*cl)->var = save_var;
1134 if((*alval)[CFC_ICUST(*cl)])
1135 fs_give((void **)&(*alval)[CFC_ICUST(*cl)]);
1137 (*alval)[CFC_ICUST(*cl)] = var_from_spec_color(hc);
1138 set_current_color_vals(ps);
1139 ps->mangled_screen = 1;
1141 else
1142 (*cl)->var = save_var;
1144 if(hcolors)
1145 free_spec_colors(&hcolors);
1146 if(*apval)
1147 fs_give((void **)apval);
1148 if(v.current_val.p)
1149 fs_give((void **)&v.current_val.p);
1150 if(starting_val)
1151 fs_give((void **)&starting_val);
1153 return(rv);
1158 * Test whether or not a var is one of the vars which might have a
1159 * color value stored in it.
1161 * returns: 1 if it is a color var, 0 otherwise
1164 color_holding_var(struct pine *ps, struct variable *var)
1166 if(treat_color_vars_as_text)
1167 return(0);
1168 else
1169 return(var && var->name &&
1170 (srchstr(var->name, "-foreground-color") ||
1171 srchstr(var->name, "-background-color") ||
1172 var == &ps->vars[V_INDEX_TOKEN_COLORS] ||
1173 var == &ps->vars[V_VIEW_HDR_COLORS] ||
1174 var == &ps->vars[V_KW_COLORS]));
1179 * test whether or not a var is one of the vars having to do with color
1181 * returns: 1 if it is a color var, 0 otherwise
1184 color_related_var(struct pine *ps, struct variable *var)
1186 return(
1187 #ifndef _WINDOWS
1188 var == &ps->vars[V_COLOR_STYLE] ||
1189 #endif
1190 var == &ps->vars[V_INDEX_COLOR_STYLE] ||
1191 var == &ps->vars[V_TITLEBAR_COLOR_STYLE] ||
1192 color_holding_var(ps, var));
1197 offer_normal_color_for_var(struct pine *ps, struct variable *var)
1199 return(color_holding_var(ps, var)
1200 && var != &ps->vars[V_NORM_FORE_COLOR]
1201 && var != &ps->vars[V_NORM_BACK_COLOR]
1202 && var != &ps->vars[V_REV_FORE_COLOR]
1203 && var != &ps->vars[V_REV_BACK_COLOR]
1204 && var != &ps->vars[V_SLCTBL_FORE_COLOR]
1205 && var != &ps->vars[V_SLCTBL_BACK_COLOR]);
1210 offer_none_color_for_var(struct pine *ps, struct variable *var)
1212 return(color_holding_var(ps, var)
1213 && (!struncmp(var->name, "index-", 6)
1214 || var == &ps->vars[V_KW_COLORS]));
1217 char *colorindexrule(char *s)
1219 char *conftext;
1220 char ***alval, **t;
1222 if(!strcmp(s, "SUBJECT") || !strcmp(s, "SUBJECTTEXT")
1223 || !strcmp(s, "SUBJKEYTEXT") || !strcmp(s, "SUBJKEYINITTEXT")
1224 || !strcmp(s, "FROMORTO") || !strcmp(s, "FROM"))
1225 return s;
1227 t = NULL;
1228 if((conftext = add_viewerhdr_escapes(s)) != NULL){
1229 if((alval = ALVAL(&ps_global->vars[V_INDEX_TOKEN_COLORS], ew)) != NULL){
1230 if((t = *alval) && t[0] && !t[0][0] && !(t+1)[0])
1231 free_list_array(alval);
1233 for(t = *alval; t && t[0]; t++){
1234 if(strstr(*t, conftext) != NULL)
1235 break;
1238 fs_give((void **)&conftext);
1240 return t && *t ? *t : NULL;
1245 color_setting_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
1247 int rv = 0, i, cancel = 0, deefault;
1248 int curcolor, prevcolor, nextcolor, another;
1249 CONF_S *ctmp, *first_line, *beg = NULL, *end = NULL,
1250 *cur_beg, *cur_end, *prev_beg, *prev_end,
1251 *next_beg, *next_end;
1252 struct variable *v, *fgv, *bgv, *setv = NULL, *otherv;
1253 SPEC_COLOR_S *hc = NULL, *new_hcolor;
1254 SPEC_COLOR_S *hcolors = NULL;
1255 KEYWORD_S *kw;
1256 char *old_val, *confline = NULL;
1257 char prompt[100], sval[MAXPATH+1];
1258 char **lval, **apval, ***alval, **t;
1259 char **apval1, **apval2;
1260 HelpType help;
1261 ESCKEY_S opts[3];
1262 #ifdef _WINDOWS
1263 char *pval;
1264 #endif
1266 sval[0] = '\0';
1268 switch(cmd){
1269 case MC_CHOICE : /* set a color */
1271 if(((*cl)->flags & CF_VAR2 && fixed_var((*cl)->var+1, NULL, NULL)) ||
1272 (!((*cl)->flags & CF_VAR2) && fixed_var((*cl)->var, NULL, NULL))){
1273 if(((*cl)->var->post_user_val.p ||
1274 ((*cl)->var+1)->post_user_val.p ||
1275 (*cl)->var->main_user_val.p ||
1276 ((*cl)->var+1)->main_user_val.p)
1277 && want_to(_("Delete old unused personal option setting"),
1278 'y', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){
1279 delete_user_vals((*cl)->var);
1280 delete_user_vals((*cl)->var+1);
1281 q_status_message(SM_ORDER, 0, 3, _("Deleted"));
1282 rv = 1;
1285 return(rv);
1288 fgv = (*cl)->var; /* foreground color */
1289 bgv = (*cl)->var+1; /* background color */
1290 v = ((*cl)->flags & CF_VAR2) ? bgv : fgv; /* var being changed */
1292 apval = APVAL(v, ew);
1293 old_val = apval ? *apval : NULL;
1295 if(apval){
1296 if(CFC_ICOLOR(*cl) < pico_count_in_color_table())
1297 *apval = cpystr(colorx(CFC_ICOLOR(*cl)));
1298 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NORM)
1299 *apval = cpystr(MATCH_NORM_COLOR);
1300 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NONE)
1301 *apval = cpystr(MATCH_NONE_COLOR);
1302 else if(old_val)
1303 *apval = cpystr(is_rgb_color(old_val)
1304 ? old_val : color_to_asciirgb(old_val));
1305 else if(v->current_val.p)
1306 *apval = cpystr(is_rgb_color(v->current_val.p)
1307 ? v->current_val.p
1308 : color_to_asciirgb(v->current_val.p));
1309 else if(v == fgv)
1310 *apval = cpystr(color_to_asciirgb(colorx(COL_BLACK)));
1311 else
1312 *apval = cpystr(color_to_asciirgb(colorx(COL_WHITE)));
1315 if(old_val)
1316 fs_give((void **)&old_val);
1318 set_current_val(v, TRUE, FALSE);
1321 * If the user sets one of foreground/background and the
1322 * other is not yet set, set the other.
1324 if(PVAL(v, ew)){
1325 if(v == fgv && !PVAL(bgv, ew)){
1326 setv = bgv;
1327 otherv = fgv;
1329 else if(v == bgv && !PVAL(fgv, ew)){
1330 setv = fgv;
1331 otherv = bgv;
1335 if(setv){
1336 if((apval = APVAL(setv, ew)) != NULL){
1337 if(setv->current_val.p)
1338 *apval = cpystr(setv->current_val.p);
1339 else if (setv == fgv && ps_global->VAR_NORM_FORE_COLOR)
1340 *apval = cpystr(ps_global->VAR_NORM_FORE_COLOR);
1341 else if (setv == bgv && ps_global->VAR_NORM_BACK_COLOR)
1342 *apval = cpystr(ps_global->VAR_NORM_BACK_COLOR);
1343 else if(!strucmp(color_to_canonical_name(otherv->current_val.p),
1344 colorx(COL_WHITE)))
1345 *apval = cpystr(colorx(COL_BLACK));
1346 else
1347 *apval = cpystr(colorx(COL_WHITE));
1350 set_current_val(setv, TRUE, FALSE);
1353 fix_side_effects(ps, v, 0);
1354 set_current_color_vals(ps);
1357 * Turn on selected *'s for default selections, if any, and
1358 * for ones we forced on.
1360 color_update_selected(ps, *cl, PVAL(fgv, ew), PVAL(bgv, ew), TRUE);
1362 ClearScreen();
1363 rv = ps->mangled_screen = 1;
1364 break;
1366 case MC_CHOICEB : /* set a custom hdr color */
1368 * Find the SPEC_COLOR_S for header.
1370 lval = LVAL((*cl)->var, ew);
1371 hcolors = spec_colors_from_varlist(lval, 0);
1372 for(hc = hcolors, i=0; hc; hc = hc->next, i++)
1373 if(CFC_ICUST(*cl) == i)
1374 break;
1376 if(hc){
1377 if((*cl)->flags & CF_VAR2){
1378 old_val = hc->bg;
1379 if(CFC_ICOLOR(*cl) < pico_count_in_color_table())
1380 hc->bg = cpystr(colorx(CFC_ICOLOR(*cl)));
1381 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NORM)
1382 hc->bg = cpystr(MATCH_NORM_COLOR);
1383 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NONE)
1384 hc->bg = cpystr(MATCH_NONE_COLOR);
1385 else if(old_val)
1386 hc->bg = cpystr(is_rgb_color(old_val)
1387 ? old_val
1388 : color_to_asciirgb(old_val));
1389 else
1390 hc->bg = cpystr(color_to_asciirgb(colorx(COL_WHITE)));
1392 if(old_val)
1393 fs_give((void **) &old_val);
1396 * If the user sets one of foreground/background and the
1397 * other is not yet set, set it.
1399 if(!(hc->fg && hc->fg[0])){
1400 if(hc->fg)
1401 fs_give((void **)&hc->fg);
1403 hc->fg = cpystr(ps->VAR_NORM_FORE_COLOR);
1406 else{
1407 old_val = hc->fg;
1409 if(CFC_ICOLOR(*cl) < pico_count_in_color_table())
1410 hc->fg = cpystr(colorx(CFC_ICOLOR(*cl)));
1411 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NORM)
1412 hc->fg = cpystr(MATCH_NORM_COLOR);
1413 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NONE)
1414 hc->fg = cpystr(MATCH_NONE_COLOR);
1415 else if(old_val)
1416 hc->fg = cpystr(is_rgb_color(old_val)
1417 ? old_val
1418 : color_to_asciirgb(old_val));
1419 else
1420 hc->fg = cpystr(color_to_asciirgb(colorx(COL_BLACK)));
1422 if(old_val)
1423 fs_give((void **) &old_val);
1425 if(!(hc->bg && hc->bg[0])){
1426 if(hc->bg)
1427 fs_give((void **)&hc->bg);
1429 hc->bg = cpystr(ps->VAR_NORM_BACK_COLOR);
1435 * Turn on selected *'s for default selections, if any, and
1436 * for ones we forced on.
1438 color_update_selected(ps, *cl,
1439 (hc && hc->fg && hc->fg[0]
1440 && hc->bg && hc->bg[0])
1441 ? hc->fg : ps->VAR_NORM_FORE_COLOR,
1442 (hc && hc->fg && hc->fg[0]
1443 && hc->bg && hc->bg[0])
1444 ? hc->bg : ps->VAR_NORM_BACK_COLOR,
1445 TRUE);
1447 if(hc && lval && lval[i]){
1448 fs_give((void **)&lval[i]);
1449 lval[i] = var_from_spec_color(hc);
1452 if(hcolors)
1453 free_spec_colors(&hcolors);
1455 fix_side_effects(ps, (*cl)->var, 0);
1456 set_current_color_vals(ps);
1457 ClearScreen();
1458 rv = ps->mangled_screen = 1;
1459 break;
1462 case MC_CHOICEC : /* set a custom keyword color */
1463 /* find keyword associated with color we are editing */
1464 for(kw=ps->keywords, i=0; kw; kw=kw->next, i++)
1465 if(CFC_ICUST(*cl) == i)
1466 break;
1468 if(!kw){ /* can't happen */
1469 dprint((1,
1470 "This can't happen, kw not set when setting keyword color\n"));
1471 break;
1474 hcolors = spec_colors_from_varlist(LVAL((*cl)->var, ew), 0);
1477 * Look through hcolors, derived from lval, to find this keyword
1478 * and its current color.
1480 for(hc = hcolors; hc; hc = hc->next)
1481 if(hc->spec && ((kw->nick && !strucmp(kw->nick, hc->spec))
1482 || (kw->kw && !strucmp(kw->kw, hc->spec))))
1483 break;
1485 if(!hc){ /* this keyword didn't have a color set, add to list */
1486 SPEC_COLOR_S *new;
1488 new = (SPEC_COLOR_S *) fs_get(sizeof(*hc));
1489 memset((void *) new, 0, sizeof(*new));
1490 new->spec = cpystr(kw->kw);
1491 new->fg = cpystr(ps->VAR_NORM_FORE_COLOR);
1492 new->bg = cpystr(ps->VAR_NORM_BACK_COLOR);
1494 if(hcolors){
1495 for(hc = hcolors; hc->next; hc = hc->next)
1498 hc->next = new;
1500 else
1501 hcolors = new;
1503 hc = new;
1506 if(hc){
1507 if((*cl)->flags & CF_VAR2){
1508 old_val = hc->bg;
1509 if(CFC_ICOLOR(*cl) < pico_count_in_color_table())
1510 hc->bg = cpystr(colorx(CFC_ICOLOR(*cl)));
1511 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NORM)
1512 hc->bg = cpystr(MATCH_NORM_COLOR);
1513 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NONE)
1514 hc->bg = cpystr(MATCH_NONE_COLOR);
1515 else if(old_val)
1516 hc->bg = cpystr(is_rgb_color(old_val)
1517 ? old_val
1518 : color_to_asciirgb(old_val));
1519 else
1520 hc->bg = cpystr(color_to_asciirgb(colorx(COL_WHITE)));
1522 if(old_val)
1523 fs_give((void **) &old_val);
1526 * If the user sets one of foreground/background and the
1527 * other is not yet set, set it.
1529 if(!(hc->fg && hc->fg[0])){
1530 if(hc->fg)
1531 fs_give((void **)&hc->fg);
1533 hc->fg = cpystr(ps->VAR_NORM_FORE_COLOR);
1536 else{
1537 old_val = hc->fg;
1539 if(CFC_ICOLOR(*cl) < pico_count_in_color_table())
1540 hc->fg = cpystr(colorx(CFC_ICOLOR(*cl)));
1541 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NORM)
1542 hc->fg = cpystr(MATCH_NORM_COLOR);
1543 else if(CFC_ICOLOR(*cl) == CFC_ICOLOR_NONE)
1544 hc->fg = cpystr(MATCH_NONE_COLOR);
1545 else if(old_val)
1546 hc->fg = cpystr(is_rgb_color(old_val)
1547 ? old_val
1548 : color_to_asciirgb(old_val));
1549 else
1550 hc->fg = cpystr(color_to_asciirgb(colorx(COL_BLACK)));
1552 if(old_val)
1553 fs_give((void **) &old_val);
1555 if(!(hc->bg && hc->bg[0])){
1556 if(hc->bg)
1557 fs_give((void **)&hc->bg);
1559 hc->bg = cpystr(ps->VAR_NORM_BACK_COLOR);
1565 * Turn on selected *'s for default selections, if any, and
1566 * for ones we forced on.
1568 color_update_selected(ps, *cl,
1569 (hc && hc->fg && hc->fg[0]
1570 && hc->bg && hc->bg[0])
1571 ? hc->fg : ps->VAR_NORM_FORE_COLOR,
1572 (hc && hc->fg && hc->fg[0]
1573 && hc->bg && hc->bg[0])
1574 ? hc->bg : ps->VAR_NORM_BACK_COLOR,
1575 TRUE);
1577 alval = ALVAL((*cl)->var, ew);
1578 free_list_array(alval);
1579 *alval = varlist_from_spec_colors(hcolors);
1581 if(hcolors)
1582 free_spec_colors(&hcolors);
1584 fix_side_effects(ps, (*cl)->var, 0);
1585 set_current_color_vals(ps);
1586 ClearScreen();
1587 rv = ps->mangled_screen = 1;
1588 break;
1590 case MC_TOGGLE : /* toggle default on or off */
1591 fgv = (*cl)->var; /* foreground color */
1592 bgv = (*cl)->var+1; /* background color */
1594 if((*cl)->value[1] == 'X'){ /* turning default off */
1595 (*cl)->value[1] = ' ';
1597 * Take whatever color is the current_val and suck it
1598 * into the user_val. Same colors remain checked.
1600 apval1 = APVAL(fgv, ew);
1601 if(apval1){
1602 if(*apval1)
1603 fs_give((void **)apval1);
1606 apval2 = APVAL(bgv, ew);
1607 if(apval2){
1608 if(*apval2)
1609 fs_give((void **)apval2);
1612 /* editing normal but there is an exception config */
1613 if((ps->ew_for_except_vars != Main) && (ew == Main)){
1614 COLOR_PAIR *newc;
1616 /* use global_val if it is set */
1617 if(fgv && fgv->global_val.p && fgv->global_val.p[0] &&
1618 bgv && bgv->global_val.p && bgv->global_val.p[0]){
1619 *apval1 = cpystr(fgv->global_val.p);
1620 *apval2 = cpystr(bgv->global_val.p);
1622 else if(var_defaults_to_rev(fgv) &&
1623 (newc = pico_get_rev_color())){
1624 *apval1 = cpystr(newc->fg);
1625 *apval2 = cpystr(newc->bg);
1627 else{
1628 *apval1 = cpystr(ps->VAR_NORM_FORE_COLOR);
1629 *apval2 = cpystr(ps->VAR_NORM_BACK_COLOR);
1632 else{ /* editing outermost config */
1633 /* just use current_vals */
1634 if(fgv->current_val.p)
1635 *apval1 = cpystr(fgv->current_val.p);
1636 if(bgv->current_val.p)
1637 *apval2 = cpystr(bgv->current_val.p);
1640 else{ /* turning default on */
1641 char *starred_fg = NULL, *starred_bg = NULL;
1643 (*cl)->value[1] = 'X';
1644 apval = APVAL(fgv, ew);
1645 if(apval && *apval)
1646 fs_give((void **)apval);
1648 apval = APVAL(bgv, ew);
1649 if(apval && *apval)
1650 fs_give((void **)apval);
1652 if(fgv->cmdline_val.p)
1653 fs_give((void **)&fgv->cmdline_val.p);
1655 if(bgv->cmdline_val.p)
1656 fs_give((void **)&bgv->cmdline_val.p);
1658 set_current_color_vals(ps);
1660 if(fgv == &ps->vars[V_SLCTBL_FORE_COLOR]){
1661 F_TURN_OFF(F_SLCTBL_ITEM_NOBOLD, ps);
1662 (*cl)->next->value[1] = 'X';
1665 /* editing normal but there is an exception config */
1666 if((ps->ew_for_except_vars != Main) && (ew == Main)){
1667 COLOR_PAIR *newc;
1669 /* use global_val if it is set */
1670 if(fgv && fgv->global_val.p && fgv->global_val.p[0] &&
1671 bgv && bgv->global_val.p && bgv->global_val.p[0]){
1672 starred_fg = fgv->global_val.p;
1673 starred_bg = bgv->global_val.p;
1675 else if(var_defaults_to_rev(fgv) &&
1676 (newc = pico_get_rev_color())){
1677 starred_fg = newc->fg;
1678 starred_bg = newc->bg;
1680 else{
1681 starred_fg = ps->VAR_NORM_FORE_COLOR;
1682 starred_bg = ps->VAR_NORM_BACK_COLOR;
1685 else{ /* editing outermost config */
1686 starred_fg = fgv->current_val.p;
1687 starred_bg = bgv->current_val.p;
1691 * Turn on selected *'s for default selections.
1693 color_update_selected(ps, prev_confline(*cl),
1694 starred_fg, starred_bg, FALSE);
1696 ps->mangled_body = 1;
1699 fix_side_effects(ps, fgv, 0);
1700 rv = 1;
1701 break;
1703 case MC_TOGGLEB : /* toggle default on or off, hdr color */
1705 * Find the SPEC_COLOR_S for header.
1707 rv = 1;
1708 lval = LVAL((*cl)->var, ew);
1709 hcolors = spec_colors_from_varlist(lval, 0);
1710 for(hc = hcolors, i=0; hc; hc = hc->next, i++)
1711 if(CFC_ICUST(*cl) == i)
1712 break;
1714 if((*cl)->value[1] == 'X'){ /* turning default off */
1715 (*cl)->value[1] = ' ';
1717 * Take whatever color is the default value and suck it
1718 * into the hc structure.
1720 if(hc){
1721 if(hc->bg)
1722 fs_give((void **)&hc->bg);
1723 if(hc->fg)
1724 fs_give((void **)&hc->fg);
1726 if(ps->VAR_NORM_FORE_COLOR &&
1727 ps->VAR_NORM_FORE_COLOR[0] &&
1728 ps->VAR_NORM_BACK_COLOR &&
1729 ps->VAR_NORM_BACK_COLOR[0]){
1730 hc->fg = cpystr(ps->VAR_NORM_FORE_COLOR);
1731 hc->bg = cpystr(ps->VAR_NORM_BACK_COLOR);
1734 if(lval && lval[i]){
1735 fs_give((void **)&lval[i]);
1736 lval[i] = var_from_spec_color(hc);
1740 else{ /* turning default on */
1741 (*cl)->value[1] = 'X';
1742 /* Remove current colors, leaving val */
1743 if(hc){
1744 if(hc->bg)
1745 fs_give((void **)&hc->bg);
1746 if(hc->fg)
1747 fs_give((void **)&hc->fg);
1749 if(lval && lval[i]){
1750 fs_give((void **)&lval[i]);
1751 lval[i] = var_from_spec_color(hc);
1755 set_current_color_vals(ps);
1756 ClearScreen();
1757 ps->mangled_screen = 1;
1761 if(hcolors)
1762 free_spec_colors(&hcolors);
1765 * Turn on selected *'s for default selections.
1767 color_update_selected(ps, prev_confline(*cl),
1768 ps->VAR_NORM_FORE_COLOR,
1769 ps->VAR_NORM_BACK_COLOR,
1770 FALSE);
1772 break;
1774 case MC_TOGGLEC : /* toggle default on or off, keyword color */
1775 for(kw=ps->keywords, i=0; kw; kw=kw->next, i++)
1776 if(CFC_ICUST(*cl) == i)
1777 break;
1779 if(!kw){ /* can't happen */
1780 dprint((1,
1781 "This can't happen, kw not set when togglec keyword color\n"));
1782 break;
1785 hcolors = spec_colors_from_varlist(LVAL((*cl)->var, ew), 0);
1788 * Look through hcolors, derived from lval, to find this keyword
1789 * and its current color.
1791 for(hc = hcolors; hc; hc = hc->next)
1792 if(hc->spec && ((kw->nick && !strucmp(kw->nick, hc->spec))
1793 || (kw->kw && !strucmp(kw->kw, hc->spec))))
1794 break;
1796 /* Remove this color from list */
1797 if(hc){
1798 SPEC_COLOR_S *tmp;
1800 if(hc == hcolors){
1801 hcolors = hc->next;
1802 hc->next = NULL;
1803 free_spec_colors(&hc);
1805 else{
1806 for(tmp = hcolors; tmp->next; tmp = tmp->next)
1807 if(tmp->next == hc)
1808 break;
1810 if(tmp->next){
1811 tmp->next = hc->next;
1812 hc->next = NULL;
1813 free_spec_colors(&hc);
1818 if((*cl)->value[1] == 'X')
1819 (*cl)->value[1] = ' ';
1820 else
1821 (*cl)->value[1] = 'X';
1824 * Turn on selected *'s for default selections, if any, and
1825 * for ones we forced on.
1827 color_update_selected(ps, prev_confline(*cl),
1828 ps->VAR_NORM_FORE_COLOR,
1829 ps->VAR_NORM_BACK_COLOR,
1830 FALSE);
1832 alval = ALVAL((*cl)->var, ew);
1833 free_list_array(alval);
1834 *alval = varlist_from_spec_colors(hcolors);
1836 if(hcolors)
1837 free_spec_colors(&hcolors);
1839 fix_side_effects(ps, (*cl)->var, 0);
1840 set_current_color_vals(ps);
1841 ClearScreen();
1842 rv = ps->mangled_screen = 1;
1843 break;
1845 case MC_TOGGLED : /* toggle selectable item bold on or off */
1846 toggle_feature_bit(ps, feature_list_index(F_SLCTBL_ITEM_NOBOLD),
1847 &ps->vars[V_FEATURE_LIST], *cl, 1);
1848 ps->mangled_body = 1; /* to fix Sample Text */
1849 rv = 1;
1850 break;
1852 case MC_DEFAULT : /* restore default values */
1854 /* First, confirm that user wants to restore all default colors */
1855 if(want_to(_("Really restore all colors to default values"),
1856 'y', 'n', NO_HELP, WT_NORM) != 'y'){
1857 cmd_cancelled("RestoreDefs");
1858 return(rv);
1861 /* get rid of all user set colors */
1862 for(v = ps->vars; v->name; v++){
1863 if(!color_holding_var(ps, v)
1864 || v == &ps->vars[V_INDEX_TOKEN_COLORS]
1865 || v == &ps->vars[V_VIEW_HDR_COLORS]
1866 || v == &ps->vars[V_KW_COLORS])
1867 continue;
1869 apval = APVAL(v, ew);
1870 if(apval && *apval)
1871 fs_give((void **)apval);
1873 if(v->cmdline_val.p)
1874 fs_give((void **)&v->cmdline_val.p);
1878 * For custom header colors, we want to remove the color values
1879 * but leave the spec value so that it is easy to reset.
1881 alval = ALVAL(&ps->vars[V_VIEW_HDR_COLORS], ew);
1882 if(alval && *alval){
1883 SPEC_COLOR_S *global_hcolors = NULL, *hcg;
1885 v = &ps->vars[V_VIEW_HDR_COLORS];
1886 if(v->global_val.l && v->global_val.l[0])
1887 global_hcolors = spec_colors_from_varlist(v->global_val.l, 0);
1889 hcolors = spec_colors_from_varlist(*alval, 0);
1890 for(hc = hcolors; hc; hc = hc->next){
1891 if(hc->fg)
1892 fs_give((void **)&hc->fg);
1893 if(hc->bg)
1894 fs_give((void **)&hc->bg);
1896 for(hcg = global_hcolors; hcg; hcg = hcg->next){
1897 if(hc->spec && hcg->spec && !strucmp(hc->spec, hcg->spec)){
1898 hc->fg = hcg->fg;
1899 hcg->fg = NULL;
1900 hc->bg = hcg->bg;
1901 hcg->bg = NULL;
1902 if(hc->val && !hcg->val)
1903 fs_give((void **) &hc->val);
1907 if(global_hcolors)
1908 free_spec_colors(&global_hcolors);
1911 free_list_array(alval);
1912 *alval = varlist_from_spec_colors(hcolors);
1914 if(hcolors)
1915 free_spec_colors(&hcolors);
1918 /* same for index token colors */
1919 alval = ALVAL(&ps->vars[V_INDEX_TOKEN_COLORS], ew);
1920 if(alval && *alval){
1921 SPEC_COLOR_S *global_hcolors = NULL, *hcg;
1923 v = &ps->vars[V_INDEX_TOKEN_COLORS];
1924 if(v->global_val.l && v->global_val.l[0])
1925 global_hcolors = spec_colors_from_varlist(v->global_val.l, 0);
1927 hcolors = spec_colors_from_varlist(*alval, 0);
1928 for(hc = hcolors; hc; hc = hc->next){
1929 if(hc->fg)
1930 fs_give((void **)&hc->fg);
1931 if(hc->bg)
1932 fs_give((void **)&hc->bg);
1934 for(hcg = global_hcolors; hcg; hcg = hcg->next){
1935 if(hc->spec && hcg->spec && !strucmp(hc->spec, hcg->spec)){
1936 hc->fg = hcg->fg;
1937 hcg->fg = NULL;
1938 hc->bg = hcg->bg;
1939 hcg->bg = NULL;
1940 if(hc->val && !hcg->val)
1941 fs_give((void **) &hc->val);
1945 if(global_hcolors)
1946 free_spec_colors(&global_hcolors);
1949 free_list_array(alval);
1950 *alval = varlist_from_spec_colors(hcolors);
1952 if(hcolors)
1953 free_spec_colors(&hcolors);
1957 * Same for keyword colors.
1959 alval = ALVAL(&ps->vars[V_KW_COLORS], ew);
1960 if(alval && *alval){
1961 hcolors = spec_colors_from_varlist(*alval, 0);
1962 for(hc = hcolors; hc; hc = hc->next){
1963 if(hc->fg)
1964 fs_give((void **)&hc->fg);
1965 if(hc->bg)
1966 fs_give((void **)&hc->bg);
1969 free_list_array(alval);
1970 *alval = varlist_from_spec_colors(hcolors);
1972 if(hcolors)
1973 free_spec_colors(&hcolors);
1976 /* set bold for selectable items */
1977 F_TURN_OFF(F_SLCTBL_ITEM_NOBOLD, ps);
1978 lval = LVAL(&ps->vars[V_FEATURE_LIST], ew);
1979 if(test_feature(lval, feature_list_name(F_SLCTBL_ITEM_NOBOLD), 0))
1980 toggle_feature_bit(ps, feature_list_index(F_SLCTBL_ITEM_NOBOLD),
1981 &ps->vars[V_FEATURE_LIST], *cl, 1);
1983 set_current_color_vals(ps);
1984 clear_index_cache(ps->mail_stream, 0);
1986 /* redo config display */
1987 *cl = first_confline(*cl);
1988 free_conflines(cl);
1989 opt_screen->top_line = NULL;
1990 first_line = NULL;
1991 color_config_init_display(ps, cl, &first_line);
1992 *cl = first_line;
1993 ClearScreen();
1994 ps->mangled_screen = 1;
1995 rv = 1;
1996 break;
1998 case MC_ADDHEADER: /* add custom index token color */
1999 case MC_ADD : /* add custom header color */
2000 /* get header field name */
2001 help = NO_HELP;
2002 while(1){
2003 i = optionally_enter(sval, -FOOTER_ROWS(ps), 0, sizeof(sval),
2004 (cmd == MC_ADD ? _("Enter the name of the header field to be added: ")
2005 : _("Enter the name of the index token to be added: ")),
2006 NULL, help, NULL);
2007 if(i == 0){
2008 if(cmd == MC_ADDHEADER){
2009 if(itoktype(sval, FOR_INDEX) == NULL){
2010 q_status_message1(SM_ORDER, 1, 3,
2011 _("token \"%s\" not recognized"), sval);
2012 continue;
2013 } else if(colorindexrule(sval) != NULL){
2014 q_status_message1(SM_ORDER, 1, 3,
2015 _("Color rule for token \"%s\" already exists"), sval);
2016 continue;
2019 break;
2021 else if(i == 1){
2022 cmd_cancelled("Add");
2023 cancel = 1;
2024 break;
2026 else if(i == 3){
2027 help = help == NO_HELP ? h_config_add_custom_color : NO_HELP;
2028 continue;
2030 else
2031 break;
2034 ps->mangled_footer = 1;
2036 removing_leading_and_trailing_white_space(sval);
2037 if(sval[strlen(sval)-1] == ':') /* remove trailing colon */
2038 sval[strlen(sval)-1] = '\0';
2040 removing_trailing_white_space(sval);
2042 if(cancel || !sval[0])
2043 break;
2045 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
2046 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
2047 new_hcolor->spec = cpystr(sval);
2048 confline = var_from_spec_color(new_hcolor);
2050 /* add it to end of list */
2051 alval = ALVAL(&ps->vars[(cmd == MC_ADD ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS)], ew);
2052 if(alval){
2053 /* get rid of possible empty value first */
2054 if((t = *alval) && t[0] && !t[0][0] && !(t+1)[0])
2055 free_list_array(alval);
2057 for(t = *alval, i=0; t && t[0]; t++)
2058 i++;
2060 if(i)
2061 fs_resize((void **)alval, sizeof(char *) * (i+1+1));
2062 else
2063 *alval = (char **)fs_get(sizeof(char *) * (i+1+1));
2065 (*alval)[i] = confline;
2066 (*alval)[i+1] = NULL;
2069 set_current_color_vals(ps);
2071 /* go to end of display */
2072 for(ctmp = *cl; ctmp && ctmp->next; ctmp = next_confline(ctmp))
2075 /* back up to the KEYWORD COLORS title line */
2076 for(; ctmp && (!ctmp->value || strcmp(ctmp->value, (cmd == MC_ADD ? KW_COLORS_HDR : HDR_COLORS)))
2077 && ctmp->prev;
2078 ctmp = prev_confline(ctmp))
2082 * Back up to last header line, or comment line if no header lines.
2083 * One of many in a long line of dangerous moves in the config
2084 * screens.
2086 ctmp = prev_confline(ctmp); /* ------- line */
2087 ctmp = prev_confline(ctmp); /* blank line */
2088 ctmp = prev_confline(ctmp); /* the line */
2090 *cl = ctmp;
2092 /* delete the comment line if there were no headers before this */
2093 if(i == 0){
2094 beg = ctmp->prev;
2095 end = ctmp;
2097 *cl = beg ? beg->prev : NULL;
2099 if(beg && beg->prev) /* this will always be true */
2100 beg->prev->next = end ? end->next : NULL;
2102 if(end && end->next)
2103 end->next->prev = beg ? beg->prev : NULL;
2105 if(end)
2106 end->next = NULL;
2108 if(beg == opt_screen->top_line || end == opt_screen->top_line)
2109 opt_screen->top_line = NULL;
2111 free_conflines(&beg);
2114 add_header_color_line(ps, cl, confline, i, cmd == MC_ADD
2115 ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS);
2117 /* be sure current is on selectable line */
2118 for(; *cl && ((*cl)->flags & CF_NOSELECT); *cl = next_confline(*cl))
2120 for(; *cl && ((*cl)->flags & CF_NOSELECT); *cl = prev_confline(*cl))
2123 rv = ps->mangled_body = 1;
2124 break;
2126 case MC_DELETE : /* delete custom header color */
2127 if((*cl)->var != &ps->vars[V_VIEW_HDR_COLORS]
2128 && (*cl)->var != &ps->vars[V_INDEX_TOKEN_COLORS]){
2129 q_status_message(SM_ORDER, 0, 2,
2130 _("Can't delete this color setting"));
2131 break;
2134 if(want_to(((*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
2135 ? _("Really delete header color from config")
2136 : _("Really delete index token color from config")),
2137 'y', 'n', NO_HELP, WT_NORM) != 'y'){
2138 cmd_cancelled("Delete");
2139 return(rv);
2142 alval = ALVAL((*cl)->var, ew);
2143 if(alval){
2144 int n, j;
2146 for(t = *alval, n=0; t && t[0]; t++)
2147 n++;
2149 j = CFC_ICUST(*cl);
2151 if(n > j){ /* it better be */
2152 if((*alval)[j])
2153 fs_give((void **)&(*alval)[j]);
2155 for(i = j; i < n; i++)
2156 (*alval)[i] = (*alval)[i+1];
2160 set_current_color_vals(ps);
2163 * Note the conf lines that go with this header. That's the
2164 * blank line before and the current line.
2166 beg = (*cl)->prev;
2167 end = *cl;
2169 another = 0;
2170 /* reset current line */
2171 if(end && end->next && end->next->next &&
2172 end->next->next->var == &ps->vars[(*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
2173 ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS]){
2174 *cl = end->next->next; /* next Header Color */
2175 another++;
2177 else if(beg && beg->prev &&
2178 beg->prev->var == &ps->vars[(*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
2179 ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS]){
2180 *cl = beg->prev; /* prev Header Color */
2181 another++;
2184 /* adjust SPEC_COLOR_S index (varmem) values */
2185 for(ctmp = end; ctmp; ctmp = next_confline(ctmp))
2186 if(ctmp->var == &ps->vars[(*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
2187 ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS])
2188 ctmp->varmem = CFC_ICUST_DEC(ctmp);
2191 * If that was the last header color line, add in the comment
2192 * line placeholder. If there is another, just delete the
2193 * old conf lines.
2195 if(another){
2196 if(beg && beg->prev) /* this will always be true */
2197 beg->prev->next = end ? end->next : NULL;
2199 if(end && end->next)
2200 end->next->prev = beg ? beg->prev : NULL;
2202 if(end)
2203 end->next = NULL;
2205 if(beg == opt_screen->top_line || end == opt_screen->top_line)
2206 opt_screen->top_line = NULL;
2208 free_conflines(&beg);
2210 else if(end){
2211 if(end->varname)
2212 fs_give((void **) &end->varname);
2214 if(end->value)
2215 fs_give((void **) &end->value);
2217 end->flags = CF_NOSELECT;
2218 end->help = NO_HELP;
2219 end->value = cpystr((*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
2220 ? _(ADDHEADER_COMMENT) : _(ADDINDEXTOKEN_COMMENT));
2221 end->valoffset = COLOR_INDENT;
2222 end->varnamep = NULL;
2223 end->varmem = 0;
2224 end->keymenu = NULL;
2225 end->tool = NULL;
2228 /* if not selectable, find next selectable line */
2229 for(; *cl && ((*cl)->flags & CF_NOSELECT) && next_confline(*cl); *cl = next_confline(*cl))
2231 /* if no next selectable line, search backwards for one */
2232 for(; *cl && ((*cl)->flags & CF_NOSELECT) && prev_confline(*cl); *cl = prev_confline(*cl))
2235 rv = ps->mangled_body = 1;
2236 q_status_message(SM_ORDER, 0, 3, _("header color deleted"));
2237 break;
2239 case MC_SHUFFLE : /* shuffle order of custom headers */
2240 if((*cl)->var != &ps->vars[V_VIEW_HDR_COLORS]){
2241 q_status_message(SM_ORDER, 0, 2,
2242 _("Can't shuffle this color setting"));
2243 break;
2246 alval = ALVAL((*cl)->var, ew);
2247 if(!alval)
2248 return(rv);
2250 curcolor = CFC_ICUST(*cl);
2251 prevcolor = curcolor-1;
2252 nextcolor = curcolor+1;
2253 if(!*alval || !(*alval)[nextcolor])
2254 nextcolor = -1;
2256 if((prevcolor < 0 && nextcolor < 0) || !*alval){
2257 q_status_message(SM_ORDER, 0, 3,
2258 _("Shuffle only makes sense when there is more than one Header Color defined"));
2259 return(rv);
2262 /* Move it up or down? */
2263 i = 0;
2264 opts[i].ch = 'u';
2265 opts[i].rval = 'u';
2266 opts[i].name = "U";
2267 opts[i++].label = _("Up");
2269 opts[i].ch = 'd';
2270 opts[i].rval = 'd';
2271 opts[i].name = "D";
2272 opts[i++].label = _("Down");
2274 opts[i].ch = -1;
2275 deefault = 'u';
2277 if(prevcolor < 0){ /* no up */
2278 opts[0].ch = -2;
2279 deefault = 'd';
2281 else if(nextcolor < 0)
2282 opts[1].ch = -2; /* no down */
2284 snprintf(prompt, sizeof(prompt), _("Shuffle %s%s%s ? "),
2285 (opts[0].ch != -2) ? _("UP") : "",
2286 (opts[0].ch != -2 && opts[1].ch != -2) ? " or " : "",
2287 (opts[1].ch != -2) ? _("DOWN") : "");
2288 prompt[sizeof(prompt)-1] = '\0';
2289 help = (opts[0].ch == -2) ? h_hdrcolor_shuf_down
2290 : (opts[1].ch == -2) ? h_hdrcolor_shuf_up
2291 : h_hdrcolor_shuf;
2293 i = radio_buttons(prompt, -FOOTER_ROWS(ps), opts, deefault, 'x',
2294 help, RB_NORM);
2296 switch(i){
2297 case 'x':
2298 cmd_cancelled("Shuffle");
2299 return(rv);
2301 case 'u':
2302 case 'd':
2303 break;
2306 /* swap order */
2307 if(i == 'd'){
2308 old_val = (*alval)[curcolor];
2309 (*alval)[curcolor] = (*alval)[nextcolor];
2310 (*alval)[nextcolor] = old_val;
2312 else if(i == 'u'){
2313 old_val = (*alval)[curcolor];
2314 (*alval)[curcolor] = (*alval)[prevcolor];
2315 (*alval)[prevcolor] = old_val;
2317 else /* can't happen */
2318 return(rv);
2320 set_current_color_vals(ps);
2323 * Swap the conf lines.
2326 cur_beg = (*cl)->prev;
2327 cur_end = *cl;
2329 if(i == 'd'){
2330 next_beg = cur_end->next;
2331 next_end = next_beg ? next_beg->next : NULL;
2333 if(next_end->next)
2334 next_end->next->prev = cur_end;
2335 cur_end->next = next_end->next;
2336 next_end->next = cur_beg;
2337 if(cur_beg->prev)
2338 cur_beg->prev->next = next_beg;
2339 next_beg->prev = cur_beg->prev;
2340 cur_beg->prev = next_end;
2342 /* adjust SPEC_COLOR_S index values */
2343 cur_beg->varmem = CFC_ICUST_INC(cur_beg);
2344 cur_beg->next->varmem = CFC_ICUST_INC(cur_beg->next);
2346 next_beg->varmem = CFC_ICUST_DEC(next_beg);
2347 next_beg->next->varmem = CFC_ICUST_DEC(next_beg->next);
2349 if(opt_screen->top_line == cur_end)
2350 opt_screen->top_line = next_end;
2351 else if(opt_screen->top_line == cur_beg)
2352 opt_screen->top_line = next_beg;
2354 else{
2355 prev_end = cur_beg->prev;
2356 prev_beg = prev_end ? prev_end->prev : NULL;
2358 if(prev_beg && prev_beg->prev)
2359 prev_beg->prev->next = cur_beg;
2360 cur_beg->prev = prev_beg->prev;
2361 prev_beg->prev = cur_end;
2362 if(cur_end->next)
2363 cur_end->next->prev = prev_end;
2364 prev_end->next = cur_end->next;
2365 cur_end->next = prev_beg;
2367 /* adjust SPEC_COLOR_S index values */
2368 cur_beg->varmem = CFC_ICUST_DEC(cur_beg);
2369 cur_beg->next->varmem = CFC_ICUST_DEC(cur_beg->next);
2371 prev_beg->varmem = CFC_ICUST_INC(prev_beg);
2372 prev_beg->next->varmem = CFC_ICUST_INC(prev_beg->next);
2374 if(opt_screen->top_line == prev_end)
2375 opt_screen->top_line = cur_end;
2376 else if(opt_screen->top_line == prev_beg)
2377 opt_screen->top_line = cur_beg;
2380 rv = ps->mangled_body = 1;
2381 q_status_message(SM_ORDER, 0, 3, _("Header Colors shuffled"));
2382 break;
2384 case MC_EDIT:
2385 rv = color_edit_screen(ps, cl);
2386 if((*cl)->value && (*cl)->var &&
2387 srchstr((*cl)->var->name, "-foreground-color")){
2388 fs_give((void **)&(*cl)->value);
2389 (*cl)->value = pretty_value(ps, *cl);
2392 break;
2394 case MC_EXIT: /* exit */
2395 if((*cl)->keymenu == &color_changing_keymenu ||
2396 (*cl)->keymenu == &kw_color_changing_keymenu ||
2397 (*cl)->keymenu == &custom_color_changing_keymenu ||
2398 ((*cl)->prev &&
2399 ((*cl)->prev->keymenu == &color_changing_keymenu ||
2400 (*cl)->prev->keymenu == &kw_color_changing_keymenu ||
2401 (*cl)->prev->keymenu == &custom_color_changing_keymenu)) ||
2402 ((*cl)->prev->prev &&
2403 ((*cl)->prev->prev->keymenu == &color_changing_keymenu ||
2404 (*cl)->prev->prev->keymenu == &kw_color_changing_keymenu ||
2405 (*cl)->prev->prev->keymenu == &custom_color_changing_keymenu)))
2406 rv = simple_exit_cmd(flags);
2407 else
2408 rv = config_exit_cmd(flags);
2410 break;
2412 #ifdef _WINDOWS
2413 case MC_RGB1 :
2414 fgv = (*cl)->var;
2415 bgv = (*cl)->var+1;
2416 v = (*cl)->var;
2417 if((*cl)->flags & CF_VAR2)
2418 v += 1;
2420 pval = PVAL(v, ew);
2421 apval = APVAL(v, ew);
2422 if(old_val = mswin_rgbchoice(pval ? pval : v->current_val.p)){
2423 if(*apval)
2424 fs_give((void **)apval);
2426 *apval = old_val;
2427 set_current_val(v, TRUE, FALSE);
2428 fix_side_effects(ps, v, 0);
2429 set_current_color_vals(ps);
2430 color_update_selected(ps, *cl, PVAL(fgv, ew), PVAL(bgv, ew), TRUE);
2431 rv = ps->mangled_screen = 1;
2434 break;
2436 case MC_RGB2 :
2438 * Find the SPEC_COLOR_S for header.
2440 alval = ALVAL((*cl)->var, ew);
2441 hcolors = spec_colors_from_varlist(*alval, 0);
2443 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
2444 if(CFC_ICUST(*cl) == i){
2445 char **pc = ((*cl)->flags & CF_VAR2) ? &hc->bg : &hc->fg;
2447 if(old_val = mswin_rgbchoice(*pc)){
2448 fs_give((void **) pc);
2449 *pc = old_val;
2450 color_update_selected(ps, *cl,
2451 (hc->fg && hc->fg[0]
2452 && hc->bg && hc->bg[0])
2453 ? hc->fg : ps->VAR_NORM_FORE_COLOR,
2454 (hc->fg && hc->fg[0]
2455 && hc->bg && hc->bg[0])
2456 ? hc->bg : ps->VAR_NORM_BACK_COLOR,
2457 TRUE);
2459 if(hc && *alval && (*alval)[i]){
2460 fs_give((void **)&(*alval)[i]);
2461 (*alval)[i] = var_from_spec_color(hc);
2464 if(hcolors)
2465 free_spec_colors(&hcolors);
2467 set_current_color_vals(ps);
2468 ClearScreen();
2469 rv = ps->mangled_screen = 1;
2472 break;
2475 break;
2477 case MC_RGB3 :
2479 * Custom colored keywords.
2481 for(kw=ps->keywords, i=0; kw; kw=kw->next, i++)
2482 if(CFC_ICUST(*cl) == i)
2483 break;
2485 if(!kw){ /* can't happen */
2486 dprint((1,
2487 "This can't happen, kw not set in MC_RGB3\n"));
2488 break;
2491 hcolors = spec_colors_from_varlist(LVAL((*cl)->var, ew), 0);
2494 * Look through hcolors, derived from lval, to find this keyword
2495 * and its current color.
2497 for(hc = hcolors; hc; hc = hc->next)
2498 if(hc->spec && ((kw->nick && !strucmp(kw->nick, hc->spec))
2499 || (kw->kw && !strucmp(kw->kw, hc->spec))))
2500 break;
2502 if(!hc){ /* this keyword didn't have a color set, add to list */
2503 SPEC_COLOR_S *new;
2505 new = (SPEC_COLOR_S *) fs_get(sizeof(*hc));
2506 memset((void *) new, 0, sizeof(*new));
2507 new->spec = cpystr(kw->kw);
2508 new->fg = cpystr(ps->VAR_NORM_FORE_COLOR);
2509 new->bg = cpystr(ps->VAR_NORM_BACK_COLOR);
2511 if(hcolors){
2512 for(hc = hcolors; hc->next; hc = hc->next)
2515 hc->next = new;
2517 else
2518 hcolors = new;
2520 hc = new;
2523 if(hc){
2524 char **pc = ((*cl)->flags & CF_VAR2) ? &hc->bg : &hc->fg;
2526 if(old_val = mswin_rgbchoice(*pc)){
2527 fs_give((void **) pc);
2528 *pc = old_val;
2531 * Turn on selected *'s for default selections, if any, and
2532 * for ones we forced on.
2534 color_update_selected(ps, *cl,
2535 (hc && hc->fg && hc->fg[0]
2536 && hc->bg && hc->bg[0])
2537 ? hc->fg : ps->VAR_NORM_FORE_COLOR,
2538 (hc && hc->fg && hc->fg[0]
2539 && hc->bg && hc->bg[0])
2540 ? hc->bg : ps->VAR_NORM_BACK_COLOR,
2541 TRUE);
2543 alval = ALVAL((*cl)->var, ew);
2544 free_list_array(alval);
2545 *alval = varlist_from_spec_colors(hcolors);
2546 fix_side_effects(ps, (*cl)->var, 0);
2547 set_current_color_vals(ps);
2548 ClearScreen();
2549 rv = 1;
2553 if(hcolors)
2554 free_spec_colors(&hcolors);
2556 ps->mangled_screen = 1;
2557 break;
2558 #endif
2560 default :
2561 rv = -1;
2562 break;
2566 if(rv == 1)
2567 exception_override_warning((*cl)->var);
2569 return(rv);
2574 * Turn on selected *'s for default selections, if any, and
2575 * for ones we forced on.
2576 * Adjust the Sample line right above the color selection lines.
2578 void
2579 color_update_selected(struct pine *ps, CONF_S *cl, char *fg, char *bg, int cleardef)
2581 int i, fg_is_custom = 1, bg_is_custom = 1;
2582 #ifdef _WINDOWS
2583 CONF_S *cl_custom = NULL;
2584 #endif
2586 /* back up to header line */
2587 for(; cl && (cl->flags & CF_DOUBLEVAR); cl = prev_confline(cl))
2590 /* adjust sample line */
2591 if(cl && cl->var && cl->flags & CF_COLORSAMPLE){
2592 if(cl->value)
2593 fs_give((void **)&cl->value);
2595 cl->value = color_setting_text_line(ps, cl->var);
2598 for(i = 0, cl = next_confline(cl);
2599 i < pico_count_in_color_table() && cl;
2600 i++, cl = next_confline(cl)){
2601 if(fg && !strucmp(color_to_canonical_name(fg), colorx(i))){
2602 cl->value[1] = R_SELD;
2603 fg_is_custom = 0;
2605 else
2606 cl->value[1] = ' ';
2608 if(bg && !strucmp(color_to_canonical_name(bg), colorx(i))){
2609 cl->value[cl->val2offset - cl->valoffset + 1] = R_SELD;
2610 bg_is_custom = 0;
2612 else
2613 cl->value[cl->val2offset - cl->valoffset + 1] = ' ';
2616 #ifdef _WINDOWS
2617 cl_custom = cl;
2618 cl = next_confline(cl);
2619 #endif
2621 if(cl && cl->var && offer_normal_color_for_var(ps, cl->var)){
2622 if(fg && !struncmp(color_to_canonical_name(fg), MATCH_NORM_COLOR, RGBLEN)){
2623 cl->value[1] = R_SELD;
2624 fg_is_custom = 0;
2626 else
2627 cl->value[1] = ' ';
2629 if(bg && !struncmp(color_to_canonical_name(bg), MATCH_NORM_COLOR, RGBLEN)){
2630 cl->value[cl->val2offset - cl->valoffset + 1] = R_SELD;
2631 bg_is_custom = 0;
2633 else
2634 cl->value[cl->val2offset - cl->valoffset + 1] = ' ';
2636 cl = next_confline(cl);
2639 if(cl && cl->var && offer_none_color_for_var(ps, cl->var)){
2640 if(fg && !struncmp(color_to_canonical_name(fg), MATCH_NONE_COLOR, RGBLEN)){
2641 cl->value[1] = R_SELD;
2642 fg_is_custom = 0;
2644 else
2645 cl->value[1] = ' ';
2647 if(bg && !struncmp(color_to_canonical_name(bg), MATCH_NONE_COLOR, RGBLEN)){
2648 cl->value[cl->val2offset - cl->valoffset + 1] = R_SELD;
2649 bg_is_custom = 0;
2651 else
2652 cl->value[cl->val2offset - cl->valoffset + 1] = ' ';
2654 cl = next_confline(cl);
2657 /* Turn off Default X */
2658 if(cleardef)
2659 cl->value[1] = ' ';
2661 #ifdef _WINDOWS
2662 /* check for a custom setting */
2663 if(cl_custom){
2664 cl_custom->value[1] = fg_is_custom ? R_SELD : ' ';
2665 cl_custom->value[cl_custom->val2offset - cl_custom->valoffset + 1]
2666 = bg_is_custom ? R_SELD : ' ';
2668 #endif
2673 color_edit_screen(struct pine *ps, CONF_S **cl)
2675 OPT_SCREEN_S screen, *saved_screen;
2676 CONF_S *ctmp = NULL, *first_line = NULL, *ctmpb;
2677 int rv, is_index = 0, is_hdrcolor = 0, indent = 12;
2678 int is_general = 0, is_keywordcol = 0, is_idxtokcol = 0;
2679 char tmp[1200+1], name[1200], *p;
2680 struct variable *vtmp, v;
2681 int i, def;
2682 COLOR_PAIR *color = NULL;
2683 SPEC_COLOR_S *hc = NULL, *hcolors = NULL;
2684 KEYWORD_S *kw;
2686 vtmp = (*cl)->var;
2687 if(vtmp == &ps->vars[V_VIEW_HDR_COLORS])
2688 is_hdrcolor++;
2689 else if(vtmp == &ps->vars[V_INDEX_TOKEN_COLORS])
2690 is_idxtokcol++;
2691 else if(vtmp == &ps->vars[V_KW_COLORS])
2692 is_keywordcol++;
2693 else if(color_holding_var(ps, vtmp)){
2694 if(!struncmp(vtmp->name, "index-", 6))
2695 is_index++;
2696 else
2697 is_general++;
2700 new_confline(&ctmp);
2701 /* Blank line */
2702 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
2704 first_line = ctmp;
2706 new_confline(&ctmp)->var = vtmp;
2708 name[0] = '\0';
2709 if(is_general){
2710 p = srchstr(vtmp->name, "-foreground-color");
2711 snprintf(name, sizeof(name), "%.*s", p ? MIN(p - vtmp->name, 30) : 30, vtmp->name);
2712 name[sizeof(name)-1] = '\0';
2713 if(islower((unsigned char)name[0]))
2714 name[0] = toupper((unsigned char)name[0]);
2716 else if(is_index){
2717 p = srchstr(vtmp->name, "-foreground-color");
2718 snprintf(name, sizeof(name), "%.*s Symbol",
2719 p ? MIN(p - vtmp->name, 30) : 30, vtmp->name);
2720 name[sizeof(name)-1] = '\0';
2721 if(islower((unsigned char)name[0]))
2722 name[0] = toupper((unsigned char)name[0]);
2724 else if(is_hdrcolor){
2725 char **lval;
2727 lval = LVAL(vtmp, ew);
2728 hcolors = spec_colors_from_varlist(lval, 0);
2730 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
2731 if(CFC_ICUST(*cl) == i)
2732 break;
2734 if(hc){
2735 snprintf(name, sizeof(name), "%s%s", HEADER_WORD, hc->spec);
2736 name[sizeof(name)-1] = '\0';
2737 i = sizeof(HEADER_WORD) - 1;
2738 if(islower((unsigned char) name[i]))
2739 name[i] = toupper((unsigned char) name[i]);
2742 else if(is_idxtokcol){
2743 char **lval;
2745 lval = LVAL(vtmp, ew);
2746 hcolors = spec_colors_from_varlist(lval, 0);
2748 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
2749 if(CFC_ICUST(*cl) == i)
2750 break;
2752 if(hc){
2753 snprintf(name, sizeof(name), "%s%s", TOKEN_WORD, hc->spec);
2754 name[sizeof(name)-1] = '\0';
2755 i = sizeof(TOKEN_WORD) - 1;
2756 if(islower((unsigned char) name[i]))
2757 name[i] = toupper((unsigned char) name[i]);
2760 else if(is_keywordcol){
2761 char **lval;
2763 for(kw=ps->keywords, i=0; kw; kw=kw->next, i++)
2764 if(CFC_ICUST(*cl) == i)
2765 break;
2767 if(kw){
2768 char *nm, *comment = NULL;
2770 nm = kw->nick ? kw->nick : kw->kw ? kw->kw : "";
2771 if(utf8_width(nm) > 60)
2772 nm = short_str(nm, tmp_20k_buf, SIZEOF_20KBUF, 60, EndDots);
2774 if(kw->nick && kw->kw && kw->kw[0])
2775 comment = kw->kw;
2777 if(utf8_width(nm) + (comment ? utf8_width(comment) : 0) < 60)
2778 utf8_snprintf(name, sizeof(name), "%.50w%s%.50w%s",
2780 comment ? " (" : "",
2781 comment ? comment : "",
2782 comment ? ")" : "");
2783 else
2784 snprintf(name, sizeof(name), "%s", nm);
2786 name[sizeof(name)-1] = '\0';
2788 lval = LVAL(vtmp, ew);
2789 hcolors = spec_colors_from_varlist(lval, 0);
2790 if(kw && hcolors)
2791 if(!(kw->nick && kw->nick[0]
2792 && (color=hdr_color(kw->nick, NULL, hcolors))))
2793 if(kw->kw && kw->kw[0])
2794 color = hdr_color(kw->kw, NULL, hcolors);
2798 snprintf(tmp, sizeof(tmp), "%s Color =", name[0] ? name : "?");
2799 tmp[sizeof(tmp)-1] = '\0';
2800 ctmp->varname = cpystr(tmp);
2801 ctmp->varnamep = ctmpb = ctmp;
2802 ctmp->flags |= (CF_STARTITEM | CF_NOSELECT);
2803 ctmp->keymenu = &color_changing_keymenu;
2805 if(is_hdrcolor || is_idxtokcol){
2806 char **apval;
2808 def = !(hc && hc->fg && hc->fg[0] && hc->bg && hc->bg[0]);
2810 add_color_setting_disp(ps, &ctmp, vtmp, ctmpb,
2811 &custom_color_changing_keymenu,
2812 &hdr_color_checkbox_keymenu,
2813 config_help(vtmp - ps->vars, 0),
2814 indent, CFC_ICUST(*cl),
2815 def ? ps_global->VAR_NORM_FORE_COLOR
2816 : hc->fg,
2817 def ? ps_global->VAR_NORM_BACK_COLOR
2818 : hc->bg,
2819 def);
2821 /* optional string to match in header value */
2822 new_confline(&ctmp);
2823 ctmp->varnamep = ctmpb;
2824 ctmp->keymenu = &color_pattern_keymenu;
2825 ctmp->help = h_config_customhdr_pattern;
2826 ctmp->tool = color_text_tool;
2827 ctmp->varoffset = indent-5;
2828 ctmp->varname = cpystr(_("Pattern to match ="));
2829 ctmp->valoffset = indent-5 + strlen(ctmp->varname) + 1;
2830 ctmp->varmem = (*cl)->varmem;
2833 * This is really ugly. This is just to get the value correct.
2835 memset(&v, 0, sizeof(v));
2836 v.is_used = 1;
2837 v.is_user = 1;
2838 apval = APVAL(&v, ew);
2839 if(hc && hc->val && apval)
2840 *apval = pattern_to_string(hc->val);
2842 set_current_val(&v, FALSE, FALSE);
2843 ctmp->var = &v;
2844 ctmp->value = pretty_value(ps, ctmp);
2845 ctmp->var = vtmp;
2846 if(apval && *apval)
2847 fs_give((void **)apval);
2849 if(v.current_val.p)
2850 fs_give((void **)&v.current_val.p);
2852 if(hcolors)
2853 free_spec_colors(&hcolors);
2855 else if(is_keywordcol){
2857 def = !(color && color->fg && color->fg[0]
2858 && color->bg && color->bg[0]);
2860 add_color_setting_disp(ps, &ctmp, vtmp, ctmpb,
2861 &kw_color_changing_keymenu,
2862 &kw_color_checkbox_keymenu,
2863 config_help(vtmp - ps->vars, 0),
2864 indent, CFC_ICUST(*cl),
2865 def ? ps_global->VAR_NORM_FORE_COLOR
2866 : color->fg,
2867 def ? ps_global->VAR_NORM_BACK_COLOR
2868 : color->bg,
2869 def);
2871 if(hcolors)
2872 free_spec_colors(&hcolors);
2874 else{
2875 char *pvalfg, *pvalbg;
2876 int def;
2877 COLOR_PAIR *newc;
2879 pvalfg = PVAL(vtmp, ew);
2880 pvalbg = PVAL(vtmp+1, ew);
2881 def = !(pvalfg && pvalfg[0] && pvalbg && pvalbg[0]);
2882 if(def){
2883 /* display default val, if there is one */
2884 pvalfg = PVAL(vtmp, Main);
2885 pvalbg = PVAL(vtmp+1, Main);
2886 if(ew == Post && pvalfg && pvalfg[0] && pvalbg && pvalbg[0]){
2889 else if(vtmp && vtmp->global_val.p && vtmp->global_val.p[0] &&
2890 (vtmp+1)->global_val.p && (vtmp+1)->global_val.p[0]){
2891 pvalfg = vtmp->global_val.p;
2892 pvalbg = (vtmp+1)->global_val.p;
2894 else{
2895 if(var_defaults_to_rev(vtmp) && (newc = pico_get_rev_color())){
2896 pvalfg = newc->fg;
2897 pvalbg = newc->bg;
2899 else{
2900 pvalfg = NULL;
2901 pvalbg = NULL;
2906 add_color_setting_disp(ps, &ctmp, vtmp, ctmpb,
2907 &color_changing_keymenu,
2908 &config_checkbox_keymenu,
2909 config_help(vtmp - ps->vars, 0),
2910 indent, 0, pvalfg, pvalbg, def);
2913 first_line = first_sel_confline(first_line);
2915 saved_screen = opt_screen;
2916 memset(&screen, 0, sizeof(screen));
2917 screen.ro_warning = saved_screen ? saved_screen->deferred_ro_warning : 0;
2918 rv = conf_scroll_screen(ps, &screen, first_line,
2919 ew == Post ? _("SETUP COLOR EXCEPTIONS")
2920 : _("SETUP COLOR"),
2921 _("configuration"), 1);
2923 opt_screen = saved_screen;
2924 ps->mangled_screen = 1;
2925 return(rv);