* Addition of a link to the Apache License 2.0. This is available from
[alpine.git] / pith / color.c
blob4dcf95b7f281bba5fa9bf72381e94da0bb423935
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: color.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2013-2020 Eduardo Chappa
8 * Copyright 2006-2007 University of Washington
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 * ========================================================================
19 #include "../pith/headers.h"
20 #include "../pith/color.h"
21 #include "../pith/state.h"
22 #include "../pith/conf.h"
23 #include "../pith/filter.h"
26 char *
27 color_embed(char *fg, char *bg)
29 static char buf[(2 * RGBLEN) + 5], *p;
31 p = buf;
32 if(fg){
33 if(sizeof(buf)-(p-buf) > 1){
34 *p++ = TAG_EMBED;
35 *p++ = TAG_FGCOLOR;
38 sstrncpy(&p, color_to_asciirgb(fg), sizeof(buf)-(p-buf));
41 if(bg){
42 if(sizeof(buf)-(p-buf) > 1){
43 *p++ = TAG_EMBED;
44 *p++ = TAG_BGCOLOR;
47 sstrncpy(&p, color_to_asciirgb(bg), sizeof(buf)-(p-buf));
50 buf[sizeof(buf)-1] = '\0';
52 return(buf);
56 int
57 colorcmp(char *color1, char *color2)
59 if(color1 && color2)
60 return(strcmp(color_to_asciirgb(color1), color_to_asciirgb(color2)));
62 /* if both NULL they're the same? */
63 return(!(color1 || color2));
68 struct quote_colors {
69 COLOR_PAIR *color;
70 struct quote_colors *next;
74 int
75 color_a_quote(long int linenum, char *line, LT_INS_S **ins, void *is_flowed_msg)
77 int countem = 0;
78 struct variable *vars = ps_global->vars;
79 char *p;
80 struct quote_colors *colors = NULL, *cp, *next;
81 COLOR_PAIR *col = NULL;
82 int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
84 p = line;
85 if(!is_flowed)
86 while(isspace((unsigned char)*p))
87 p++;
89 if(p[0] == '>'){
90 struct quote_colors *c;
93 * We have a fixed number of quote level colors (3). If there are
94 * more levels of quoting than are defined, they repeat.
96 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR &&
97 (col = new_color_pair(VAR_QUOTE1_FORE_COLOR,
98 VAR_QUOTE1_BACK_COLOR)) &&
99 pico_is_good_colorpair(col)){
100 c = (struct quote_colors *)fs_get(sizeof(*c));
101 memset(c, 0, sizeof(*c));
102 c->color = col;
103 col = NULL;
104 colors = c;
105 cp = c;
106 countem++;
107 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR &&
108 (col = new_color_pair(VAR_QUOTE2_FORE_COLOR,
109 VAR_QUOTE2_BACK_COLOR)) &&
110 pico_is_good_colorpair(col)){
111 c = (struct quote_colors *)fs_get(sizeof(*c));
112 memset(c, 0, sizeof(*c));
113 c->color = col;
114 col = NULL;
115 cp->next = c;
116 cp = c;
117 countem++;
118 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR &&
119 (col = new_color_pair(VAR_QUOTE3_FORE_COLOR,
120 VAR_QUOTE3_BACK_COLOR)) &&
121 pico_is_good_colorpair(col)){
122 c = (struct quote_colors *)fs_get(sizeof(*cp));
123 memset(c, 0, sizeof(*c));
124 c->color = col;
125 col = NULL;
126 cp->next = c;
127 cp = c;
128 countem++;
134 if(col)
135 free_color_pair(&col);
137 cp = NULL;
138 while(*p == '>'){
139 cp = (cp && cp->next) ? cp->next : colors;
141 if(countem > 0)
142 ins = gf_line_test_new_ins(ins, p,
143 color_embed(cp->color->fg, cp->color->bg),
144 (2 * RGBLEN) + 4);
146 countem = (countem == 1) ? 0 : countem;
148 p++;
149 if(!is_flowed)
150 for(; isspace((unsigned char)*p); p++)
154 if(colors){
155 char fg[RGBLEN + 1], bg[RGBLEN + 1], rgbbuf[RGBLEN + 1];
157 strncpy(fg, color_to_asciirgb(VAR_NORM_FORE_COLOR), sizeof(fg));
158 strncpy(bg, color_to_asciirgb(VAR_NORM_BACK_COLOR), sizeof(bg));
159 fg[sizeof(fg)-1] = '\0';
160 bg[sizeof(bg)-1] = '\0';
163 * Loop watching colors, and override with most recent
164 * quote color whenever the normal foreground and background
165 * colors are in force.
167 while(*p)
168 if(*p++ == TAG_EMBED){
170 switch(*p++){
171 case TAG_HANDLE :
172 p += *p + 1; /* skip handle key */
173 break;
175 case TAG_FGCOLOR :
176 snprintf(rgbbuf, sizeof(rgbbuf), "%s", p);
177 p += RGBLEN; /* advance past color value */
179 if(!colorcmp(rgbbuf, VAR_NORM_FORE_COLOR)
180 && !colorcmp(bg, VAR_NORM_BACK_COLOR))
181 ins = gf_line_test_new_ins(ins, p,
182 color_embed(cp->color->fg,NULL),
183 RGBLEN + 2);
184 break;
186 case TAG_BGCOLOR :
187 snprintf(rgbbuf, sizeof(rgbbuf), "%s", p);
188 p += RGBLEN; /* advance past color value */
190 if(!colorcmp(rgbbuf, VAR_NORM_BACK_COLOR)
191 && !colorcmp(fg, VAR_NORM_FORE_COLOR))
192 ins = gf_line_test_new_ins(ins, p,
193 color_embed(NULL,cp->color->bg),
194 RGBLEN + 2);
196 break;
198 default :
199 break;
203 ins = gf_line_test_new_ins(ins, line + strlen(line),
204 color_embed(VAR_NORM_FORE_COLOR,
205 VAR_NORM_BACK_COLOR),
206 (2 * RGBLEN) + 4);
207 for(cp = colors; cp && cp->color; cp = next){
208 free_color_pair(&cp->color);
209 next = cp->next;
210 fs_give((void **)&cp);
214 return(0);
218 void
219 free_spec_colors(SPEC_COLOR_S **colors)
221 if(colors && *colors){
222 free_spec_colors(&(*colors)->next);
223 if((*colors)->spec)
224 fs_give((void **)&(*colors)->spec);
225 if((*colors)->fg)
226 fs_give((void **)&(*colors)->fg);
227 if((*colors)->bg)
228 fs_give((void **)&(*colors)->bg);
229 if((*colors)->val)
230 free_pattern(&(*colors)->val);
232 fs_give((void **)colors);