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