Make LCALL like LJMP and avoid segmentation faults parsing segments (!).
[unix-history] / usr / src / contrib / sc / range.c
CommitLineData
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
23static struct range *rng_base;
24
25add_range(name, left, right, is_range)
26char *name;
27struct ent_ptr left, right;
28int 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
89del_range(left, right)
90struct 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
116clean_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
134struct range *
135find_range(name, len, lmatch, rmatch)
136char *name;
137int len;
138struct ent *lmatch;
139struct 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
163sync_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
175write_range(f)
176FILE *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
198void
199list_range(f)
200FILE *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
224char *
225v_name(row, col)
226int 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
241char *
242r_name(r1, c1, r2, c2)
243int 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
260are_ranges()
261{
262return (rng_base != 0);
263}