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