Commit | Line | Data |
---|---|---|
21bfce49 KB |
1 | |
2 | /* SC A Spreadsheet Calculator | |
3 | * Range Manipulations | |
4 | * | |
5 | * Robert Bond, 4/87 | |
6 | * | |
7 | * $Revision: 6.8 $ | |
8 | */ | |
9 | ||
10 | #include <stdio.h> | |
11 | #include <curses.h> | |
12 | #include <ctype.h> | |
13 | #include "sc.h" | |
14 | ||
15 | #ifdef BSD42 | |
16 | #include <strings.h> | |
17 | #else | |
18 | #ifndef SYSIII | |
19 | #include <string.h> | |
20 | #endif | |
21 | #endif | |
22 | ||
23 | static struct range *rng_base; | |
24 | ||
25 | add_range(name, left, right, is_range) | |
26 | char *name; | |
27 | struct ent_ptr left, right; | |
28 | int is_range; | |
29 | { | |
30 | struct range *r; | |
31 | register char *p; | |
32 | int len; | |
33 | int minr,minc,maxr,maxc; | |
34 | int minrf, mincf, maxrf, maxcf; | |
35 | ||
36 | if (left.vp->row < right.vp->row) { | |
37 | minr = left.vp->row; minrf = left.vf & FIX_ROW; | |
38 | maxr = right.vp->row; maxrf = right.vf & FIX_ROW; | |
39 | } else { | |
40 | minr = right.vp->row; minrf = right.vf & FIX_ROW; | |
41 | maxr = left.vp->row; maxrf = right.vf & FIX_ROW; | |
42 | } | |
43 | ||
44 | if (left.vp->col < right.vp->col) { | |
45 | minc = left.vp->col; mincf = left.vf & FIX_COL; | |
46 | maxc = right.vp->col; maxcf = right.vf & FIX_COL; | |
47 | } else { | |
48 | minc = right.vp->col; mincf = right.vf & FIX_COL; | |
49 | maxc = left.vp->col; maxcf = left.vf & FIX_COL; | |
50 | } | |
51 | ||
52 | left.vp = lookat(minr, minc); | |
53 | left.vf = minrf | mincf; | |
54 | right.vp = lookat(maxr, maxc); | |
55 | right.vf = maxrf | maxcf; | |
56 | ||
57 | if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) { | |
58 | error("Error: range name already defined"); | |
59 | xfree(name); | |
60 | return; | |
61 | } | |
62 | ||
63 | if (strlen(name) <= 2) { | |
64 | error("Invalid range name - too short"); | |
65 | xfree(name); | |
66 | return; | |
67 | } | |
68 | ||
69 | for(p=name, len=0; *p; p++, len++) | |
70 | if (!((isalpha(*p) && (len<=2)) || | |
71 | ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) { | |
72 | error("Invalid range name - illegal combination"); | |
73 | xfree(name); | |
74 | return; | |
75 | } | |
76 | ||
77 | r = (struct range *)xmalloc((unsigned)sizeof(struct range)); | |
78 | r->r_name = name; | |
79 | r->r_left = left; | |
80 | r->r_right = right; | |
81 | r->r_next = rng_base; | |
82 | r->r_prev = (struct range *)0; | |
83 | r->r_is_range = is_range; | |
84 | if (rng_base) | |
85 | rng_base->r_prev = r; | |
86 | rng_base = r; | |
87 | } | |
88 | ||
89 | del_range(left, right) | |
90 | struct ent *left, *right; | |
91 | { | |
92 | register struct range *r; | |
93 | int minr,minc,maxr,maxc; | |
94 | ||
95 | minr = left->row < right->row ? left->row : right->row; | |
96 | minc = left->col < right->col ? left->col : right->col; | |
97 | maxr = left->row > right->row ? left->row : right->row; | |
98 | maxc = left->col > right->col ? left->col : right->col; | |
99 | ||
100 | left = lookat(minr, minc); | |
101 | right = lookat(maxr, maxc); | |
102 | ||
103 | if (!(r = find_range((char *)0, 0, left, right))) | |
104 | return; | |
105 | ||
106 | if (r->r_next) | |
107 | r->r_next->r_prev = r->r_prev; | |
108 | if (r->r_prev) | |
109 | r->r_prev->r_next = r->r_next; | |
110 | else | |
111 | rng_base = r->r_next; | |
112 | xfree((char *)(r->r_name)); | |
113 | xfree((char *)r); | |
114 | } | |
115 | ||
116 | clean_range() | |
117 | { | |
118 | register struct range *r; | |
119 | register struct range *nextr; | |
120 | ||
121 | r = rng_base; | |
122 | rng_base = (struct range *)0; | |
123 | ||
124 | while (r) { | |
125 | nextr = r->r_next; | |
126 | xfree((char *)(r->r_name)); | |
127 | xfree((char *)r); | |
128 | r = nextr; | |
129 | } | |
130 | } | |
131 | ||
132 | /* Match on name or lmatch, rmatch */ | |
133 | ||
134 | struct range * | |
135 | find_range(name, len, lmatch, rmatch) | |
136 | char *name; | |
137 | int len; | |
138 | struct ent *lmatch; | |
139 | struct ent *rmatch; | |
140 | { | |
141 | struct range *r; | |
142 | register char *rp, *np; | |
143 | register int c; | |
144 | ||
145 | if (name) { | |
146 | for (r = rng_base; r; r = r->r_next) { | |
147 | for (np = name, rp = r->r_name, c = len; | |
148 | c && *rp && (*rp == *np); | |
149 | rp++, np++, c--) /* */; | |
150 | if (!c && !*rp) | |
151 | return(r); | |
152 | } | |
153 | return((struct range *)0); | |
154 | } | |
155 | ||
156 | for (r = rng_base; r; r= r->r_next) { | |
157 | if ((lmatch == r->r_left.vp) && (rmatch == r->r_right.vp)) | |
158 | return(r); | |
159 | } | |
160 | return((struct range *)0); | |
161 | } | |
162 | ||
163 | sync_ranges() | |
164 | { | |
165 | register struct range *r; | |
166 | ||
167 | r = rng_base; | |
168 | while(r) { | |
169 | r->r_left.vp = lookat(r->r_left.vp->row, r->r_left.vp->col); | |
170 | r->r_right.vp = lookat(r->r_right.vp->row, r->r_right.vp->col); | |
171 | r = r->r_next; | |
172 | } | |
173 | } | |
174 | ||
175 | write_range(f) | |
176 | FILE *f; | |
177 | { | |
178 | register struct range *r; | |
179 | ||
180 | for (r = rng_base; r; r = r->r_next) { | |
181 | (void) fprintf(f, "define \"%s\" %s%s%s%d", | |
182 | r->r_name, | |
183 | r->r_left.vf & FIX_COL ? "$":"", | |
184 | coltoa(r->r_left.vp->col), | |
185 | r->r_left.vf & FIX_ROW ? "$":"", | |
186 | r->r_left.vp->row); | |
187 | if (r->r_is_range) | |
188 | (void) fprintf(f, ":%s%s%s%d\n", | |
189 | r->r_right.vf & FIX_COL ? "$":"", | |
190 | coltoa(r->r_right.vp->col), | |
191 | r->r_right.vf & FIX_ROW ? "$":"", | |
192 | r->r_right.vp->row); | |
193 | else | |
194 | (void) fprintf(f, "\n"); | |
195 | } | |
196 | } | |
197 | ||
198 | void | |
199 | list_range(f) | |
200 | FILE *f; | |
201 | { | |
202 | register struct range *r; | |
203 | ||
204 | (void) fprintf(f, "%-30s %s\n\n","Name","Definition"); | |
205 | ||
206 | for (r = rng_base; r; r = r->r_next) { | |
207 | (void) fprintf(f, "%-30s %s%s%s%d", | |
208 | r->r_name, | |
209 | r->r_left.vf & FIX_COL ? "$":"", | |
210 | coltoa(r->r_left.vp->col), | |
211 | r->r_left.vf & FIX_ROW ? "$":"", | |
212 | r->r_left.vp->row); | |
213 | if (r->r_is_range) | |
214 | (void) fprintf(f, ":%s%s%s%d\n", | |
215 | r->r_right.vf & FIX_COL ? "$":"", | |
216 | coltoa(r->r_right.vp->col), | |
217 | r->r_right.vf & FIX_ROW ? "$":"", | |
218 | r->r_right.vp->row); | |
219 | else | |
220 | (void) fprintf(f, "\n"); | |
221 | } | |
222 | } | |
223 | ||
224 | char * | |
225 | v_name(row, col) | |
226 | int row, col; | |
227 | { | |
228 | struct ent *v; | |
229 | struct range *r; | |
230 | static char buf[20]; | |
231 | ||
232 | v = lookat(row, col); | |
233 | if (r = find_range((char *)0, 0, v, v)) { | |
234 | return(r->r_name); | |
235 | } else { | |
236 | (void) sprintf(buf, "%s%d", coltoa(col), row); | |
237 | return(buf); | |
238 | } | |
239 | } | |
240 | ||
241 | char * | |
242 | r_name(r1, c1, r2, c2) | |
243 | int r1, c1, r2, c2; | |
244 | { | |
245 | struct ent *v1, *v2; | |
246 | struct range *r; | |
247 | static char buf[100]; | |
248 | ||
249 | v1 = lookat(r1, c1); | |
250 | v2 = lookat(r2, c2); | |
251 | if (r = find_range((char *)0, 0, v1, v2)) { | |
252 | return(r->r_name); | |
253 | } else { | |
254 | (void) sprintf(buf, "%s", v_name(r1, c1)); | |
255 | (void) sprintf(buf+strlen(buf), ":%s", v_name(r2, c2)); | |
256 | return(buf); | |
257 | } | |
258 | } | |
259 | ||
260 | are_ranges() | |
261 | { | |
262 | return (rng_base != 0); | |
263 | } |