xref: /original-bsd/contrib/sc/range.c (revision d44d58ed)
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 
add_range(name,left,right,is_range)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 
clean_range()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 *
find_range(name,len,lmatch,rmatch)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 
sync_ranges()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 
write_range(f)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
list_range(f)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 *
v_name(row,col)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 *
r_name(r1,c1,r2,c2)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 
are_ranges()260 are_ranges()
261 {
262 return (rng_base != 0);
263 }
264