1 
2 /*	SC	A Spreadsheet Calculator
3  *		Color manipulation routines
4  *
5  *		Chuck Martin <nrocinu@myrealbox.com>
6  *		Original Version Created:  January, 2001
7  *
8  *		$Revision: 7.16 $
9  */
10 
11 #include <sys/types.h>
12 #ifdef BSD42
13 #include <strings.h>
14 #else
15 #ifndef SYSIII
16 #include <string.h>
17 #endif
18 #endif
19 
20 #include <curses.h>
21 #include <ctype.h>
22 #include "sc.h"
23 
24 /* a linked list of free [struct ent]'s, uses .next as the pointer */
25 extern	struct ent *freeents;
26 
27 struct colorpair	*cpairs[8];
28 static struct crange	*color_base;
29 
30 void
initcolor(int colornum)31 initcolor(int colornum)
32 {
33     if (!colornum) {
34 	int i;
35 
36 	for (i = 0; i < 8; i++)	cpairs[i] =
37 	    (struct colorpair *)scxmalloc((unsigned)sizeof(struct colorpair));
38     }
39 
40 /* default colors */
41     if (!colornum || colornum == 1) {
42 	cpairs[0]->fg = COLOR_WHITE;
43 	cpairs[0]->bg = COLOR_BLUE;
44 	cpairs[0]->expr = NULL;
45 	init_pair(1, cpairs[0]->fg, cpairs[0]->bg);
46     }
47 
48 /* default for negative numbers */
49     if (!colornum || colornum == 2) {
50 	cpairs[1]->fg = COLOR_RED;
51 	cpairs[1]->bg = COLOR_WHITE;
52 	cpairs[1]->expr = NULL;
53 	init_pair(2, cpairs[1]->fg, cpairs[1]->bg);
54     }
55 
56 /* default for cells with errors */
57     if (!colornum || colornum == 3) {
58 	cpairs[2]->fg = COLOR_WHITE;
59 	cpairs[2]->bg = COLOR_RED;
60 	cpairs[2]->expr = NULL;
61 	init_pair(3, cpairs[2]->fg, cpairs[2]->bg);
62     }
63 
64 /* default for '*' marking cells with attached notes */
65     if (!colornum || colornum == 4) {
66 	cpairs[3]->fg = COLOR_BLACK;
67 	cpairs[3]->bg = COLOR_YELLOW;
68 	cpairs[3]->expr = NULL;
69 	init_pair(4, cpairs[3]->fg, cpairs[3]->bg);
70     }
71 
72     if (!colornum || colornum == 5) {
73 	cpairs[4]->fg = COLOR_BLACK;
74 	cpairs[4]->bg = COLOR_CYAN;
75 	cpairs[4]->expr = NULL;
76 	init_pair(5, cpairs[4]->fg, cpairs[4]->bg);
77     }
78 
79     if (!colornum || colornum == 6) {
80 	cpairs[5]->fg = COLOR_RED;
81 	cpairs[5]->bg = COLOR_CYAN;
82 	cpairs[5]->expr = NULL;
83 	init_pair(6, cpairs[5]->fg, cpairs[5]->bg);
84     }
85 
86     if (!colornum || colornum == 7) {
87 	cpairs[6]->fg = COLOR_WHITE;
88 	cpairs[6]->bg = COLOR_BLACK;
89 	cpairs[6]->expr = NULL;
90 	init_pair(7, cpairs[6]->fg, cpairs[6]->bg);
91     }
92 
93     if (!colornum || colornum == 8) {
94 	cpairs[7]->fg = COLOR_RED;
95 	cpairs[7]->bg = COLOR_BLACK;
96 	cpairs[7]->expr = NULL;
97 	init_pair(8, cpairs[7]->fg, cpairs[7]->bg);
98     }
99 
100     if (color && has_colors())
101 	color_set(1, NULL);
102 }
103 
104 void
change_color(int pair,struct enode * e)105 change_color(int pair, struct enode *e)
106 {
107     int v;
108 
109     if ((--pair) < 0 || pair > 7) {
110 	error("Invalid color number");
111 	return;
112     }
113 
114     v = (int) eval(e);
115 
116     if (!cpairs[pair])
117 	cpairs[pair] =
118 	    (struct colorpair *)scxmalloc((unsigned)sizeof(struct colorpair));
119     cpairs[pair]->fg = v & 7;
120     cpairs[pair]->bg = (v >> 3) & 7;
121     cpairs[pair]->expr = e;
122     if (color && has_colors())
123 	init_pair(pair + 1, cpairs[pair]->fg, cpairs[pair]->bg);
124 
125     modflg++;
126     FullUpdate++;
127 }
128 
129 void
add_crange(struct ent * r_left,struct ent * r_right,int pair)130 add_crange(struct ent *r_left, struct ent *r_right, int pair)
131 {
132     struct crange *r;
133     int minr, minc, maxr, maxc;
134 
135     minr = r_left->row < r_right->row ? r_left->row : r_right->row;
136     minc = r_left->col < r_right->col ? r_left->col : r_right->col;
137     maxr = r_left->row > r_right->row ? r_left->row : r_right->row;
138     maxc = r_left->col > r_right->col ? r_left->col : r_right->col;
139 
140     if (!pair) {
141 	if (color_base)
142 	    for (r = color_base; r; r = r->r_next)
143 		if (    (r->r_left->row == r_left->row) &&
144 			(r->r_left->col == r_left->col) &&
145 			(r->r_right->row == r_right->row) &&
146 			(r->r_right->col == r_right->col)) {
147 		    if (r->r_next)
148 			r->r_next->r_prev = r->r_prev;
149 		    if (r->r_prev)
150 			r->r_prev->r_next = r->r_next;
151 		    else
152 			color_base = r->r_next;
153 		    scxfree((char *)r);
154 		    modflg++;
155 		    FullUpdate++;
156 		    return;
157 		}
158 	error("Color range not defined");
159 	return;
160     }
161 
162     r = (struct crange *)scxmalloc((unsigned)sizeof(struct crange));
163     r->r_left = lookat(minr, minc);
164     r->r_right = lookat(maxr, maxc);
165     r->r_color = pair;
166 
167     r->r_next = color_base;
168     r->r_prev = (struct crange *)0;
169     if (color_base)
170 	color_base->r_prev = r;
171     color_base = r;
172 
173     modflg++;
174     FullUpdate++;
175 }
176 
177 void
clean_crange()178 clean_crange()
179 {
180     register struct crange *cr;
181     register struct crange *nextcr;
182 
183     cr = color_base;
184     color_base = (struct crange *)0;
185 
186     while (cr) {
187 	nextcr = cr->r_next;
188 	scxfree((char *)cr);
189 	cr = nextcr;
190     }
191 }
192 
193 struct crange *
find_crange(int row,int col)194 find_crange(int row, int col)
195 {
196     struct crange *r;
197 
198     if (color_base)
199 	for (r = color_base; r; r = r->r_next) {
200 	    if ((r->r_left->row <= row) && (r->r_left->col <= col) &&
201 		    (r->r_right->row >= row) && (r->r_right->col >= col))
202 		return r;
203 	}
204     return 0;
205 }
206 
207 void
sync_cranges()208 sync_cranges()
209 {
210     struct crange *cr;
211 
212     cr = color_base;
213     while (cr) {
214 	cr->r_left = lookat(cr->r_left->row, cr->r_left->col);
215 	cr->r_right = lookat(cr->r_right->row, cr->r_right->col);
216 	cr = cr->r_next;
217     }
218 }
219 
220 void
write_cranges(FILE * f)221 write_cranges(FILE *f)
222 {
223     register struct crange *r;
224     register struct crange *nextr;
225 
226     for (r = nextr = color_base; nextr; r = nextr, nextr = r->r_next) /**/ ;
227     while (r) {
228 	fprintf(f, "color %s", v_name(r->r_left->row, r->r_left->col));
229 	fprintf(f, ":%s", v_name(r->r_right->row, r->r_right->col));
230 	fprintf(f, " %d\n", r->r_color);
231 
232 	r = r->r_prev;
233     }
234 }
235 
236 void
write_colors(FILE * f,int indent)237 write_colors(FILE *f, int indent)
238 {
239     int i, c = 0;
240 
241     for (i = 0; i < 8; i++) {
242 	if (cpairs[i] && cpairs[i]->expr) {
243 	    sprintf(line, "color %d = ", i + 1);
244 	    linelim = strlen(line);
245 	    decompile(cpairs[i]->expr, 0);
246 	    line[linelim] = '\0';
247 	    fprintf(f, "%*s%s\n", indent, "", line);
248 	    if (brokenpipe) return;
249 	    c++;
250 	}
251     }
252     if (indent && c) fprintf(f, "\n");
253 }
254 
255 void
list_colors(FILE * f)256 list_colors(FILE *f)
257 {
258     struct crange *r;
259     struct crange *nextr;
260 
261     write_colors(f, 2);
262     linelim = -1;
263     if (brokenpipe) return;
264 
265     if (!are_colors()) {
266 	fprintf(f, "  No color ranges");
267 	return;
268     }
269 
270     fprintf(f, "  %-30s %s\n","Range", "Color");
271     if (!brokenpipe) fprintf(f, "  %-30s %s\n","-----", "-----");
272 
273     for (r = nextr = color_base; nextr; r = nextr, nextr = r->r_next) /* */ ;
274     while (r) {
275 	fprintf(f, "  %-32s %d\n", r_name(r->r_left->row, r->r_left->col,
276 		r->r_right->row, r->r_right->col), r->r_color);
277 	if (brokenpipe) return;
278 	r = r->r_prev;
279     }
280 }
281 
282 int
are_colors()283 are_colors()
284 {
285     return (color_base != 0);
286 }
287 
288 void
fix_colors(int row1,int col1,int row2,int col2,int delta1,int delta2)289 fix_colors(int row1, int col1, int row2, int col2, int delta1, int delta2)
290 {
291     int r1, c1, r2, c2;
292     struct crange *cr;
293     struct frange *fr;
294 
295     fr = find_frange(currow, curcol);
296 
297     if (color_base)
298 	for (cr = color_base; cr; cr = cr->r_next) {
299 	    r1 = cr->r_left->row;
300 	    c1 = cr->r_left->col;
301 	    r2 = cr->r_right->row;
302 	    c2 = cr->r_right->col;
303 
304 	    if (!(fr && (c1 < fr->or_left->col || c1 > fr->or_right->col))) {
305 		if (r1 != r2 && r1 >= row1 && r1 <= row2) r1 = row2 - delta1;
306 		if (c1 != c2 && c1 >= col1 && c1 <= col2) c1 = col2 - delta1;
307 	    }
308 
309 	    if (!(fr && (c2 < fr->or_left->col || c2 > fr->or_right->col))) {
310 		if (r1 != r2 && r2 >= row1 && r2 <= row2) r2 = row1 + delta2;
311 		if (c1 != c2 && c2 >= col1 && c2 <= col2) c2 = col1 + delta2;
312 	    }
313 
314 	    if (r1 > r2 || c1 > c2)	/* the 0 means delete color range */
315 		add_crange(cr->r_left, cr->r_right, 0);
316 	    else {
317 		cr->r_left = lookat(r1, c1);
318 		cr->r_right = lookat(r2, c2);
319 	    }
320 	}
321 }
322