te: prevent tbl from dropping the last character of a file
[troff.git] / grap / misc.c
blob7a68a69277f0bdf1473ea2912fdeac3ae663fe69
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "grap.h"
5 #include "y.tab.h"
7 int nnum = 0; /* number of saved numbers */
8 double num[MAXNUM];
10 int just; /* current justification mode (RJUST, etc.) */
11 int sizeop; /* current optional operator for size change */
12 double sizexpr; /* current size change expression */
14 void savenum(int n, double f) /* save f in num[n] */
16 num[n] = f;
17 nnum = n+1;
18 if (nnum >= MAXNUM)
19 ERROR "too many numbers" WARNING;
22 void setjust(int j)
24 just |= j;
27 void setsize(int op, double expr)
29 sizeop = op;
30 sizexpr = expr;
33 char *tostring(char *s)
35 register char *p;
37 p = malloc(strlen(s)+1);
38 if (p == NULL)
39 ERROR "out of space in tostring on %s", s FATAL;
40 strcpy(p, s);
41 return(p);
44 void range(Point pt) /* update the range for point pt */
46 Obj *p = pt.obj;
48 if (!(p->coord & XFLAG)) {
49 if (pt.x > p->pt1.x)
50 p->pt1.x = pt.x;
51 if (pt.x < p->pt.x)
52 p->pt.x = pt.x;
54 if (!(p->coord & YFLAG)) {
55 if (pt.y > p->pt1.y)
56 p->pt1.y = pt.y;
57 if (pt.y < p->pt.y)
58 p->pt.y = pt.y;
62 void halfrange(Obj *p, int side, double val) /* record max and min for one direction */
64 if (!(p->coord&XFLAG) && (side == LEFT || side == RIGHT)) {
65 if (val < p->pt.y)
66 p->pt.y = val;
67 if (val > p->pt1.y)
68 p->pt1.y = val;
69 } else if (!(p->coord&YFLAG) && (side == TOP || side == BOT)) {
70 if (val < p->pt.x)
71 p->pt.x = val;
72 if (val > p->pt1.x)
73 p->pt1.x = val;
78 Obj *lookup(char *s, int inst) /* find s in objlist, install if inst */
80 Obj *p;
81 int found = 0;
83 for (p = objlist; p; p = p->next){
84 if (strcmp(s, p->name) == 0) {
85 found = 1;
86 break;
89 if (p == NULL && inst != 0) {
90 p = (Obj *) calloc(1, sizeof(Obj));
91 if (p == NULL)
92 ERROR "out of space in lookup" FATAL;
93 p->name = tostring(s);
94 p->type = NAME;
95 p->pt = ptmax;
96 p->pt1 = ptmin;
97 p->fval = 0.0;
98 p->next = objlist;
99 objlist = p;
101 dprintf("lookup(%s,%d) = %d\n", s, inst, found);
102 return p;
105 double getvar(Obj *p) /* return value of variable */
107 return p->fval;
110 double setvar(Obj *p, double f) /* set value of variable to f */
112 if (strcmp(p->name, "pointsize") == 0) { /* kludge */
113 pointsize = f;
114 ps_set = 1;
116 p->type = VARNAME;
117 return p->fval = f;
120 Point makepoint(Obj *s, double x, double y) /* make a Point */
122 Point p;
124 dprintf("makepoint: %s, %g,%g\n", s->name, x, y);
125 p.obj = s;
126 p.x = x;
127 p.y = y;
128 return p;
131 Attr *makefattr(int type, double fval) /* set double in attribute */
133 return makeattr(type, fval, (char *) 0, 0, 0);
136 Attr *makesattr(char *s) /* make an Attr cell containing s */
138 Attr *ap = makeattr(STRING, sizexpr, s, just, sizeop);
139 just = sizeop = 0;
140 sizexpr = 0.0;
141 return ap;
144 Attr *makeattr(int type, double fval, char *sval, int just, int op)
146 Attr *a;
148 a = (Attr *) malloc(sizeof(Attr));
149 if (a == NULL)
150 ERROR "out of space in makeattr" FATAL;
151 a->type = type;
152 a->fval = fval;
153 a->sval = sval;
154 a->just = just;
155 a->op = op;
156 a->next = NULL;
157 return a;
160 Attr *addattr(Attr *a1, Attr *ap) /* add attr ap to end of list a1 */
162 Attr *p;
164 if (a1 == 0)
165 return ap;
166 if (ap == 0)
167 return a1;
168 for (p = a1; p->next; p = p->next)
170 p->next = ap;
171 return a1;
174 void freeattr(Attr *ap) /* free an attribute list */
176 Attr *p;
178 while (ap) {
179 p = ap->next; /* save next */
180 if (ap->sval)
181 free(ap->sval);
182 free((char *) ap);
183 ap = p;
187 char *slprint(Attr *stringlist) /* print strings from stringlist */
189 int ntext, n, last_op, last_just;
190 double last_fval;
191 static char buf[1000];
192 Attr *ap;
194 buf[0] = '\0';
195 last_op = last_just = 0;
196 last_fval = 0.0;
197 for (ntext = 0, ap = stringlist; ap != NULL; ap = ap->next)
198 ntext++;
199 sprintf(buf, "box invis wid 0 ht %d*textht", ntext);
200 n = strlen(buf);
201 for (ap = stringlist; ap != NULL; ap = ap->next) {
202 if (ap->op == 0) { /* propagate last value */
203 ap->op = last_op;
204 ap->fval = last_fval;
205 } else {
206 last_op = ap->op;
207 last_fval = ap->fval;
209 sprintf(buf+n, " \"%s\"", ps_set || ap->op ? sizeit(ap) : ap->sval);
210 if (ap->just)
211 last_just = ap->just;
212 if (last_just)
213 strcat(buf+n, juststr(last_just));
214 n = strlen(buf);
216 return buf; /* watch it: static */
219 char *juststr(int j) /* convert RJUST, etc., into string */
221 static char buf[50];
223 buf[0] = '\0';
224 if (j & RJUST)
225 strcat(buf, " rjust");
226 if (j & LJUST)
227 strcat(buf, " ljust");
228 if (j & ABOVE)
229 strcat(buf, " above");
230 if (j & BELOW)
231 strcat(buf, " below");
232 return buf; /* watch it: static */
235 char *sprntf(char *s, Attr *ap) /* sprintf(s, attrlist ap) */
237 char buf[500];
238 int n;
239 Attr *p;
241 for (n = 0, p = ap; p; p = p->next)
242 n++;
243 switch (n) {
244 case 0:
245 return s;
246 case 1:
247 sprintf(buf, s, ap->fval);
248 break;
249 case 2:
250 sprintf(buf, s, ap->fval, ap->next->fval);
251 break;
252 case 3:
253 sprintf(buf, s, ap->fval, ap->next->fval, ap->next->next->fval);
254 break;
255 case 5:
256 ERROR "too many expressions in sprintf" WARNING;
257 case 4:
258 sprintf(buf, s, ap->fval, ap->next->fval, ap->next->next->fval, ap->next->next->next->fval);
259 break;
261 free(s);
262 return tostring(buf);