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