1 /* SC A Spreadsheet Calculator
2 * Framed range manipulation
3 *
4 * Chuck Martin <nrocinu@myrealbox.com>
5 * Originally created: December, 2000
6 *
7 * $Revision: 7.16 $
8 */
9
10 #include <sys/types.h>
11 #ifdef BSD42
12 #include <strings.h>
13 #else
14 #ifndef SYSIII
15 #include <string.h>
16 #endif
17 #endif
18
19 #include <stdio.h>
20 #include <ctype.h>
21 #include "sc.h"
22
23 static struct frange *frame_base;
24 extern struct frange *lastfr;
25
26 void
add_frange(struct ent * or_left,struct ent * or_right,struct ent * ir_left,struct ent * ir_right,int toprows,int bottomrows,int leftcols,int rightcols)27 add_frange(struct ent *or_left, struct ent *or_right, struct ent *ir_left,
28 struct ent *ir_right, int toprows, int bottomrows, int leftcols,
29 int rightcols)
30 {
31 struct frange *r;
32 int minr, minc, maxr, maxc;
33
34 minr = or_left->row < or_right->row ? or_left->row : or_right->row;
35 minc = or_left->col < or_right->col ? or_left->col : or_right->col;
36 maxr = or_left->row > or_right->row ? or_left->row : or_right->row;
37 maxc = or_left->col > or_right->col ? or_left->col : or_right->col;
38
39 or_left = lookat(minr, minc);
40 or_right = lookat(maxr, maxc);
41
42 if (ir_left) {
43 minr = ir_left->row < ir_right->row ? ir_left->row : ir_right->row;
44 minc = ir_left->col < ir_right->col ? ir_left->col : ir_right->col;
45 maxr = ir_left->row > ir_right->row ? ir_left->row : ir_right->row;
46 maxc = ir_left->col > ir_right->col ? ir_left->col : ir_right->col;
47
48 ir_left = lookat(minr, minc);
49 ir_right = lookat(maxr, maxc);
50
51 if (ir_left->row < or_left->row ||
52 ir_left->col < or_left->col ||
53 ir_right->row > or_right->row ||
54 ir_right->col > or_right->col) {
55 error("Invalid parameters");
56 return;
57 }
58 }
59
60 if (frame_base) {
61 /*
62 * Has this frange already been created? If so, any negative
63 * parameters mean "don't change this value."
64 */
65 for (r = frame_base; r; r = r->r_next) {
66 if ((r->or_left == or_left) && (r->or_right == or_right)) {
67 if (ir_left) {
68 r->ir_left = ir_left;
69 r->ir_right = ir_right;
70 } else {
71 if (toprows < 0)
72 toprows = r->ir_left->row - r->or_left->row;
73 if (bottomrows < 0)
74 bottomrows = r->or_right->row - r->ir_right->row;
75 if (leftcols < 0)
76 leftcols = r->ir_left->col - r->or_left->col;
77 if (rightcols < 0)
78 rightcols = r->or_right->col - r->ir_right->col;
79 r->ir_left = lookat(r->or_left->row + toprows,
80 r->or_left->col + leftcols);
81 r->ir_right = lookat(r->or_right->row - bottomrows,
82 r->or_right->col - rightcols);
83 }
84
85 /* If all frame sides are 0, delete the frange */
86 if (r->ir_left == r->or_left && r->ir_right == r->or_right) {
87 if (r->r_next)
88 r->r_next->r_prev = r->r_prev;
89 if (r->r_prev)
90 r->r_prev->r_next = r->r_next;
91 else
92 frame_base = r->r_next;
93 scxfree((char *)r);
94 if (lastfr == r) lastfr = NULL;
95 }
96 modflg++;
97 FullUpdate++;
98 return;
99 }
100 }
101 /*
102 * See if the specified range overlaps any previously created frange.
103 */
104 for (r = frame_base; r; r = r->r_next) {
105 if ( !(r->or_left->row > or_right->row ||
106 r->or_right->row < or_left->row ||
107 r->or_left->col > or_right->col ||
108 r->or_right->col < or_left->col)) {
109 error("Framed ranges may not be nested or overlapping");
110 return;
111 }
112 }
113 }
114
115 if (ir_left != or_left || ir_right != or_right) {
116 r = (struct frange *)scxmalloc((unsigned)sizeof(struct frange));
117 r->or_left = or_left;
118 r->or_right = or_right;
119
120 if (ir_left) {
121 r->ir_left = ir_left;
122 r->ir_right = ir_right;
123 } else {
124 if (toprows < 0) toprows = 0;
125 if (bottomrows < 0) bottomrows = 0;
126 if (leftcols < 0) leftcols = 0;
127 if (rightcols < 0) rightcols = 0;
128 r->ir_left = lookat(r->or_left->row + toprows,
129 r->or_left->col + leftcols);
130 r->ir_right = lookat(r->or_right->row - bottomrows,
131 r->or_right->col - rightcols);
132 }
133
134 r->r_next = frame_base;
135 r->r_prev = NULL;
136 if (frame_base)
137 frame_base->r_prev = r;
138 frame_base = r;
139 modflg++;
140 FullUpdate++;
141 }
142 }
143
144 void
clean_frange()145 clean_frange()
146 {
147 register struct frange *fr;
148 register struct frange *nextfr;
149
150 fr = frame_base;
151 frame_base = NULL;
152
153 while (fr) {
154 nextfr = fr->r_next;
155 scxfree((char *)fr);
156 fr = nextfr;
157 }
158 lastfr = NULL;
159 }
160
161 struct frange *
find_frange(int row,int col)162 find_frange(int row, int col)
163 {
164 struct frange *r;
165
166 if (frame_base)
167 for (r = frame_base; r; r = r->r_next) {
168 if ((r->or_left->row <= row) && (r->or_left->col <= col) &&
169 (r->or_right->row >= row) && (r->or_right->col >= col))
170 return r;
171 }
172 return 0;
173 }
174
175 void
sync_franges()176 sync_franges()
177 {
178 struct frange *fr;
179
180 fr = frame_base;
181 while (fr) {
182 fr->or_left = lookat(fr->or_left->row, fr->or_left->col);
183 fr->or_right = lookat(fr->or_right->row, fr->or_right->col);
184 fr->ir_left = lookat(fr->ir_left->row, fr->ir_left->col);
185 fr->ir_right = lookat(fr->ir_right->row, fr->ir_right->col);
186 fr = fr->r_next;
187 }
188 }
189
190 void
write_franges(FILE * f)191 write_franges(FILE *f)
192 {
193 register struct frange *r;
194 register struct frange *nextr;
195
196 for (r = nextr = frame_base; nextr; r = nextr, nextr = r->r_next) /**/ ;
197 while (r) {
198 fprintf(f, "frame %s", v_name(r->or_left->row, r->or_left->col));
199 fprintf(f, ":%s", v_name(r->or_right->row, r->or_right->col));
200 fprintf(f, " %s", v_name(r->ir_left->row, r->ir_left->col));
201 fprintf(f, ":%s\n", v_name(r->ir_right->row, r->ir_right->col));
202
203 r = r->r_prev;
204 }
205 }
206
207 void
list_frames(FILE * f)208 list_frames(FILE *f)
209 {
210 register struct frange *r;
211 register struct frange *nextr;
212
213 if (!are_frames()) {
214 fprintf(f, " No frames");
215 return;
216 }
217
218 (void) fprintf(f, " %-30s %s\n","Outer Range","Inner Range");
219 if (!brokenpipe)
220 (void) fprintf(f, " %-30s %s\n","-----------","-----------");
221
222 for (r = nextr = frame_base; nextr; r = nextr, nextr = r->r_next) /* */ ;
223 while (r) {
224 fprintf(f, " %-30s", r_name(r->or_left->row, r->or_left->col,
225 r->or_right->row, r->or_right->col));
226 fprintf(f, " %s\n", r_name(r->ir_left->row, r->ir_left->col,
227 r->ir_right->row, r->ir_right->col));
228 if (brokenpipe) return;
229 r = r->r_prev;
230 }
231 }
232
233 int
are_frames()234 are_frames()
235 {
236 return (frame_base != 0);
237 }
238
239 void
fix_frames(int row1,int col1,int row2,int col2,int delta1,int delta2)240 fix_frames(int row1, int col1, int row2, int col2, int delta1, int delta2)
241 {
242 int r1, r2, c1, c2;
243 struct frange *fr, *cfr;
244
245 cfr = find_frange(currow, curcol);
246 if (frame_base)
247 for (fr = frame_base; fr; fr = fr->r_next) {
248 r1 = fr->or_left->row;
249 c1 = fr->or_left->col;
250 r2 = fr->or_right->row;
251 c2 = fr->or_right->col;
252
253 if (!(cfr && (c1 < cfr->or_left->col || c1 > cfr->or_right->col))) {
254 if (r1 >= row1 && r1 <= row2) r1 = row2 - delta1;
255 if (c1 >= col1 && c1 <= col2) c1 = col2 - delta1;
256 }
257
258 if (!(cfr && (c2 < cfr->or_left->col || c2 > cfr->or_right->col))) {
259 if (r2 >= row1 && r2 <= row2) r2 = row1 + delta2;
260 if (c2 >= col1 && c2 <= col2) c2 = col1 + delta2;
261 }
262
263 fr->or_left = lookat(r1, c1);
264 fr->or_right = lookat(r2, c2);
265
266 r1 = fr->ir_left->row;
267 c1 = fr->ir_left->col;
268 r2 = fr->ir_right->row;
269 c2 = fr->ir_right->col;
270
271 if (!(cfr && (c1 < cfr->or_left->col || c1 > cfr->or_right->col))) {
272 if (r1 >= row1 && r1 <= row2) r1 = row2 - delta1;
273 if (c1 >= col1 && c1 <= col2) c1 = col2 - delta1;
274 }
275
276 if (!(cfr && (c2 < cfr->or_left->col || c2 > cfr->or_right->col))) {
277 if (r2 >= row1 && r2 <= row2) r2 = row1 + delta2;
278 if (c2 >= col1 && c2 <= col2) c2 = col1 + delta2;
279 }
280
281 fr->ir_left = lookat(r1, c1);
282 fr->ir_right = lookat(r2, c2);
283 }
284 }
285