Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / groff / src / preproc / grn / hdb.cc
1 /* Last non-groff version: hdb.c  1.8 (Berkeley) 84/10/20
2  *
3  * Copyright -C- 1982 Barry S. Roitblat
4  *
5  * This file contains database routines for the hard copy programs of the
6  * gremlin picture editor.
7  */
8
9 #include "gprint.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13
14 #include "errarg.h"
15 #include "error.h"
16
17 #define MAXSTRING 128
18 #define MAXSTRING_S "127"
19
20 /* imports from main.cc */
21
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);
26
27 /* imports from hpoint.cc */
28
29 extern POINT *PTInit();
30 extern POINT *PTMakePoint(float x, float y, POINT ** pplist);
31
32
33 int DBGetType(register char *s);
34
35
36 /*
37  * This routine returns a pointer to an initialized database element which
38  * would be the only element in an empty list.
39  */
40 ELT *
41 DBInit()
42 {
43   return ((ELT *) NULL);
44 }                               /* end DBInit */
45
46
47 /*
48  * This routine creates a new element with the specified attributes and
49  * links it into database.
50  */
51 ELT *
52 DBCreateElt(int type,
53             POINT * pointlist,
54             int brush,
55             int size,
56             char *text,
57             ELT **db)
58 {
59   register ELT *temp;
60
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 */
71
72
73 /*
74  * This routine reads the specified file into a database and returns a
75  * pointer to that database.
76  */
77 ELT *
78 DBRead(register FILE *file)
79 {
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;
90
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);
98     }
99     SUNFILE = TRUE;
100   }
101
102   (void) fscanf(file, "%d%f%f\n", &size, &x, &y);
103   /* ignore orientation and file positioning point */
104
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);
113     }
114
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 */
126
127       /*
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).
131        */
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);
137
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;
150           }
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);
168
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;
176           }
177         }
178 #endif  /* UW_FASTSCAN */
179       }
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);
186       }
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 */
193
194
195 /*
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.
199  */
200 int
201 DBGetType(register char *s)
202 {
203   if (isdigit(s[0]) || (s[0] == '-'))   /* old element format or EOF */
204     return (atoi(s));
205
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       if (s[5] == '\n')
216         return (CURVE);
217       switch (s[7]) {
218       case 'S': 
219         return(BSPLINE);
220       case 'E':
221         fprintf(stderr,
222                 "Warning: Bezier Curves will be printed as B-Splines\n");
223         return(BSPLINE);
224       default:
225         return(CURVE);
226       }
227     }
228     switch (s[4]) {
229     case 'L':
230       return (CENTLEFT);
231     case 'C':
232       return (CENTCENT);
233     case 'R':
234       return (CENTRIGHT);
235     default:
236       fatal("unknown element type");
237     }
238   case 'B':
239     switch (s[3]) {
240     case 'L':
241       return (BOTLEFT);
242     case 'C':
243       return (BOTCENT);
244     case 'R':
245       return (BOTRIGHT);
246     default:
247       fatal("unknown element type");
248     }
249   case 'T':
250     switch (s[3]) {
251     case 'L':
252       return (TOPLEFT);
253     case 'C':
254       return (TOPCENT);
255     case 'R':
256       return (TOPRIGHT);
257     default:
258       fatal("unknown element type");
259     }
260   default:
261     fatal("unknown element type");
262   }
263
264   return 0;                             /* never reached */
265 }
266
267 #ifdef UW_FASTSCAN
268 /*
269  * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
270  * A huge fraction of the time was spent reading floating point numbers from
271  * the input file, but the numbers always have the format 'ddd.dd'.  Thus
272  * the following special-purpose version of fscanf.
273  *
274  * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
275  *   -the next piece of input must be of the form
276  *      <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
277  *   -xscanf eats the character following the second number
278  *   -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
279  *    end-of-data is signalled by a '*' [in which case the rest of the
280  *    line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
281  */
282 int
283 xscanf(FILE *f,
284        float *xp,
285        float *yp)
286 {
287   register int c, i, j, m, frac;
288   int iscale = 1, jscale = 1;   /* x = i/scale, y=j/jscale */
289
290   while ((c = getc(f)) == ' ');
291   if (c == '*') {
292     while ((c = getc(f)) != '\n');
293     return 0;
294   }
295   i = m = frac = 0;
296   while (isdigit(c) || c == '.' || c == '-') {
297     if (c == '-') {
298       m++;
299       c = getc(f);
300       continue;
301     }
302     if (c == '.')
303       frac = 1;
304     else {
305       if (frac)
306         iscale *= 10;
307       i = 10 * i + c - '0';
308     }
309     c = getc(f);
310   }
311   if (m)
312     i = -i;
313   *xp = (double) i / (double) iscale;
314
315   while ((c = getc(f)) == ' ');
316   j = m = frac = 0;
317   while (isdigit(c) || c == '.' || c == '-') {
318     if (c == '-') {
319       m++;
320       c = getc(f);
321       continue;
322     }
323     if (c == '.')
324       frac = 1;
325     else {
326       if (frac)
327         jscale *= 10;
328       j = 10 * j + c - '0';
329     }
330     c = getc(f);
331   }
332   if (m)
333     j = -j;
334   *yp = (double) j / (double) jscale;
335   return (SUNFILE || i != -iscale || j != -jscale);
336 }
337 #endif  /* UW_FASTSCAN */
338
339 /* EOF */