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