* MORE.STUFF: Added gpresent.
[s-roff.git] / src / preproc / grn / hdb.cc
blob8bbc6b5a16274f2cf5e699c031b88be56cfd2df7
1 /* Last non-groff version: hdb.c 1.8 (Berkeley) 84/10/20
3 * Copyright -C- 1982 Barry S. Roitblat
5 * This file contains database routines for the hard copy programs of the
6 * gremlin picture editor.
7 */
9 #include "gprint.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
14 #include "errarg.h"
15 #include "error.h"
17 #define MAXSTRING 128
18 #define MAXSTRING_S "127"
20 /* imports from main.cc */
22 extern int linenum; /* current line number in input file */
23 extern char gremlinfile[]; /* name of file currently reading */
24 extern int SUNFILE; /* TRUE if SUN gremlin file */
25 extern void savebounds(float x, float y);
27 /* imports from hpoint.cc */
29 extern POINT *PTInit();
30 extern POINT *PTMakePoint(float x, float y, POINT ** pplist);
33 int DBGetType(register char *s);
37 * This routine returns a pointer to an initialized database element which
38 * would be the only element in an empty list.
40 ELT *
41 DBInit()
43 return ((ELT *) NULL);
44 } /* end DBInit */
48 * This routine creates a new element with the specified attributes and
49 * links it into database.
51 ELT *
52 DBCreateElt(int type,
53 POINT * pointlist,
54 int brush,
55 int size,
56 char *text,
57 ELT **db)
59 register ELT *temp;
61 temp = (ELT *) malloc(sizeof(ELT));
62 temp->nextelt = *db;
63 temp->type = type;
64 temp->ptlist = pointlist;
65 temp->brushf = brush;
66 temp->size = size;
67 temp->textpt = text;
68 *db = temp;
69 return (temp);
70 } /* end CreateElt */
74 * This routine reads the specified file into a database and returns a
75 * pointer to that database.
77 ELT *
78 DBRead(register FILE *file)
80 register int i;
81 register int done; /* flag for input exhausted */
82 register float nx; /* x holder so x is not set before orienting */
83 int type; /* element type */
84 ELT *elist; /* pointer to the file's elements */
85 POINT *plist; /* pointer for reading in points */
86 char string[MAXSTRING], *txt;
87 float x, y; /* x and y are read in point coords */
88 int len, brush, size;
89 int lastpoint;
91 SUNFILE = FALSE;
92 elist = DBInit();
93 (void) fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string);
94 if (strcmp(string, "gremlinfile")) {
95 if (strcmp(string, "sungremlinfile")) {
96 error("`%1' is not a gremlin file", gremlinfile);
97 return (elist);
99 SUNFILE = TRUE;
102 (void) fscanf(file, "%d%f%f\n", &size, &x, &y);
103 /* ignore orientation and file positioning point */
105 done = FALSE;
106 while (!done) {
107 /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */
108 /* I changed the scanf format because the element */
109 /* can have two words (e.g. CURVE SPLINE) */
110 if (fscanf(file, "\n%" MAXSTRING_S "[^\n]%*[^\n]\n", string) == EOF) {
111 error("`%1', error in file format", gremlinfile);
112 return (elist);
115 type = DBGetType(string); /* interpret element type */
116 if (type < 0) { /* no more data */
117 done = TRUE;
118 (void) fclose(file);
119 } else {
120 #ifdef UW_FASTSCAN
121 (void) xscanf(file, &x, &y); /* always one point */
122 #else
123 (void) fscanf(file, "%f%f\n", &x, &y); /* always one point */
124 #endif /* UW_FASTSCAN */
125 plist = PTInit(); /* NULL point list */
128 * Files created on the SUN have point lists terminated by a line
129 * containing only an asterik ('*'). Files created on the AED have
130 * point lists terminated by the coordinate pair (-1.00 -1.00).
132 if (TEXT(type)) { /* read only first point for TEXT elements */
133 nx = xorn(x, y);
134 y = yorn(x, y);
135 (void) PTMakePoint(nx, y, &plist);
136 savebounds(nx, y);
138 #ifdef UW_FASTSCAN
139 while (xscanf(file, &x, &y));
140 #else
141 lastpoint = FALSE;
142 do {
143 fgets(string, MAXSTRING, file);
144 if (string[0] == '*') { /* SUN gremlin file */
145 lastpoint = TRUE;
146 } else {
147 (void) sscanf(string, "%f%f", &x, &y);
148 if ((x == -1.00 && y == -1.00) && (!SUNFILE))
149 lastpoint = TRUE;
151 } while (!lastpoint);
152 #endif /* UW_FASTSCAN */
153 } else { /* not TEXT element */
154 #ifdef UW_FASTSCAN
155 do {
156 nx = xorn(x, y);
157 y = yorn(x, y);
158 (void) PTMakePoint(nx, y, &plist);
159 savebounds(nx, y);
160 } while (xscanf(file, &x, &y));
161 #else
162 lastpoint = FALSE;
163 while (!lastpoint) {
164 nx = xorn(x, y);
165 y = yorn(x, y);
166 (void) PTMakePoint(nx, y, &plist);
167 savebounds(nx, y);
169 fgets(string, MAXSTRING, file);
170 if (string[0] == '*') { /* SUN gremlin file */
171 lastpoint = TRUE;
172 } else {
173 (void) sscanf(string, "%f%f", &x, &y);
174 if ((x == -1.00 && y == -1.00) && (!SUNFILE))
175 lastpoint = TRUE;
178 #endif /* UW_FASTSCAN */
180 (void) fscanf(file, "%d%d\n", &brush, &size);
181 (void) fscanf(file, "%d", &len); /* text length */
182 (void) getc(file); /* eat blank */
183 txt = (char *) malloc((unsigned) len + 1);
184 for (i = 0; i < len; ++i) { /* read text */
185 txt[i] = getc(file);
187 txt[len] = '\0';
188 (void) DBCreateElt(type, plist, brush, size, txt, &elist);
189 } /* end else */
190 } /* end while not done */ ;
191 return (elist);
192 } /* end DBRead */
196 * Interpret element type in string s.
197 * Old file format consisted of integer element types.
198 * New file format has literal names for element types.
201 DBGetType(register char *s)
203 if (isdigit(s[0]) || (s[0] == '-')) /* old element format or EOF */
204 return (atoi(s));
206 switch (s[0]) {
207 case 'P':
208 return (POLYGON);
209 case 'V':
210 return (VECTOR);
211 case 'A':
212 return (ARC);
213 case 'C':
214 if (s[1] == 'U')
215 return (CURVE);
216 switch (s[4]) {
217 case 'L':
218 return (CENTLEFT);
219 case 'C':
220 return (CENTCENT);
221 case 'R':
222 return (CENTRIGHT);
223 default:
224 fatal("unknown element type");
226 case 'B':
227 switch (s[3]) {
228 case 'L':
229 return (BOTLEFT);
230 case 'C':
231 return (BOTCENT);
232 case 'R':
233 return (BOTRIGHT);
234 default:
235 fatal("unknown element type");
237 case 'T':
238 switch (s[3]) {
239 case 'L':
240 return (TOPLEFT);
241 case 'C':
242 return (TOPCENT);
243 case 'R':
244 return (TOPRIGHT);
245 default:
246 fatal("unknown element type");
248 default:
249 fatal("unknown element type");
252 return 0; /* never reached */
255 #ifdef UW_FASTSCAN
257 * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
258 * A huge fraction of the time was spent reading floating point numbers from
259 * the input file, but the numbers always have the format 'ddd.dd'. Thus
260 * the following special-purpose version of fscanf.
262 * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
263 * -the next piece of input must be of the form
264 * <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
265 * -xscanf eats the character following the second number
266 * -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
267 * end-of-data is signalled by a '*' [in which case the rest of the
268 * line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
271 xscanf(FILE *f,
272 float *xp,
273 float *yp)
275 register int c, i, j, m, frac;
276 int iscale = 1, jscale = 1; /* x = i/scale, y=j/jscale */
278 while ((c = getc(f)) == ' ');
279 if (c == '*') {
280 while ((c = getc(f)) != '\n');
281 return 0;
283 i = m = frac = 0;
284 while (isdigit(c) || c == '.' || c == '-') {
285 if (c == '-') {
286 m++;
287 c = getc(f);
288 continue;
290 if (c == '.')
291 frac = 1;
292 else {
293 if (frac)
294 iscale *= 10;
295 i = 10 * i + c - '0';
297 c = getc(f);
299 if (m)
300 i = -i;
301 *xp = (double) i / (double) iscale;
303 while ((c = getc(f)) == ' ');
304 j = m = frac = 0;
305 while (isdigit(c) || c == '.' || c == '-') {
306 if (c == '-') {
307 m++;
308 c = getc(f);
309 continue;
311 if (c == '.')
312 frac = 1;
313 else {
314 if (frac)
315 jscale *= 10;
316 j = 10 * j + c - '0';
318 c = getc(f);
320 if (m)
321 j = -j;
322 *yp = (double) j / (double) jscale;
323 return (SUNFILE || i != -iscale || j != -jscale);
325 #endif /* UW_FASTSCAN */
327 /* EOF */