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