Add groff 1.19.1, stripped down appropriately.
[dragonfly.git] / contrib / groff-1.19 / 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 void savebounds(double x, double y);
26
27 /* imports from hpoint.cpp */
28
29 extern POINT *PTInit();
30 extern POINT *PTMakePoint(double x, double 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 double 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   double 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%lf%lf\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     } else {
119 #ifdef UW_FASTSCAN
120       (void) xscanf(file, &x, &y);              /* always one point */
121 #else
122       (void) fscanf(file, "%lf%lf\n", &x, &y);  /* always one point */
123 #endif  /* UW_FASTSCAN */
124       plist = PTInit();         /* NULL point list */
125
126       /*
127        * Files created on the SUN have point lists terminated by a line
128        * containing only an asterik ('*').  Files created on the AED have
129        * point lists terminated by the coordinate pair (-1.00 -1.00).
130        */
131       if (TEXT(type)) {         /* read only first point for TEXT elements */
132         nx = xorn(x, y);
133         y = yorn(x, y);
134         (void) PTMakePoint(nx, y, &plist);
135         savebounds(nx, y);
136
137 #ifdef UW_FASTSCAN
138         while (xscanf(file, &x, &y));
139 #else
140         lastpoint = FALSE;
141         do {
142           fgets(string, MAXSTRING, file);
143           if (string[0] == '*') {       /* SUN gremlin file */
144             lastpoint = TRUE;
145           } else {
146             (void) sscanf(string, "%lf%lf", &x, &y);
147             if ((x == -1.00 && y == -1.00) && (!SUNFILE))
148               lastpoint = TRUE;
149           }
150         } while (!lastpoint);
151 #endif  /* UW_FASTSCAN */
152       } else {                  /* not TEXT element */
153 #ifdef UW_FASTSCAN
154         do {
155           nx = xorn(x, y);
156           y = yorn(x, y);
157           (void) PTMakePoint(nx, y, &plist);
158           savebounds(nx, y);
159         } while (xscanf(file, &x, &y));
160 #else
161         lastpoint = FALSE;
162         while (!lastpoint) {
163           nx = xorn(x, y);
164           y = yorn(x, y);
165           (void) PTMakePoint(nx, y, &plist);
166           savebounds(nx, y);
167
168           fgets(string, MAXSTRING, file);
169           if (string[0] == '*') {       /* SUN gremlin file */
170             lastpoint = TRUE;
171           } else {
172             (void) sscanf(string, "%lf%lf", &x, &y);
173             if ((x == -1.00 && y == -1.00) && (!SUNFILE))
174               lastpoint = TRUE;
175           }
176         }
177 #endif  /* UW_FASTSCAN */
178       }
179       (void) fscanf(file, "%d%d\n", &brush, &size);
180       (void) fscanf(file, "%d", &len);  /* text length */
181       (void) getc(file);                /* eat blank */
182       txt = (char *) malloc((unsigned) len + 1);
183       for (i = 0; i < len; ++i) {       /* read text */
184         int c = getc(file);
185         if (c == EOF)
186           break;
187         txt[i] = c;
188       }
189       txt[len] = '\0';
190       (void) DBCreateElt(type, plist, brush, size, txt, &elist);
191     }                           /* end else */
192   } /* end while not done */ ;
193   return (elist);
194 }                               /* end DBRead */
195
196
197 /*
198  * Interpret element type in string s.
199  * Old file format consisted of integer element types.
200  * New file format has literal names for element types.
201  */
202 int
203 DBGetType(register char *s)
204 {
205   if (isdigit(s[0]) || (s[0] == '-'))   /* old element format or EOF */
206     return (atoi(s));
207
208   switch (s[0]) {
209   case 'P':
210     return (POLYGON);
211   case 'V':
212     return (VECTOR);
213   case 'A':
214     return (ARC);
215   case 'C':
216     if (s[1] == 'U') {
217       if (s[5] == '\n')
218         return (CURVE);
219       switch (s[7]) {
220       case 'S': 
221         return(BSPLINE);
222       case 'E':
223         fprintf(stderr,
224                 "Warning: Bezier Curves will be printed as B-Splines\n");
225         return(BSPLINE);
226       default:
227         return(CURVE);
228       }
229     }
230     switch (s[4]) {
231     case 'L':
232       return (CENTLEFT);
233     case 'C':
234       return (CENTCENT);
235     case 'R':
236       return (CENTRIGHT);
237     default:
238       fatal("unknown element type");
239     }
240   case 'B':
241     switch (s[3]) {
242     case 'L':
243       return (BOTLEFT);
244     case 'C':
245       return (BOTCENT);
246     case 'R':
247       return (BOTRIGHT);
248     default:
249       fatal("unknown element type");
250     }
251   case 'T':
252     switch (s[3]) {
253     case 'L':
254       return (TOPLEFT);
255     case 'C':
256       return (TOPCENT);
257     case 'R':
258       return (TOPRIGHT);
259     default:
260       fatal("unknown element type");
261     }
262   default:
263     fatal("unknown element type");
264   }
265
266   return 0;                             /* never reached */
267 }
268
269 #ifdef UW_FASTSCAN
270 /*
271  * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
272  * A huge fraction of the time was spent reading floating point numbers from
273  * the input file, but the numbers always have the format 'ddd.dd'.  Thus
274  * the following special-purpose version of fscanf.
275  *
276  * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
277  *   -the next piece of input must be of the form
278  *      <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
279  *   -xscanf eats the character following the second number
280  *   -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
281  *    end-of-data is signalled by a '*' [in which case the rest of the
282  *    line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
283  */
284 int
285 xscanf(FILE *f,
286        double *xp,
287        double *yp)
288 {
289   register int c, i, j, m, frac;
290   int iscale = 1, jscale = 1;   /* x = i/scale, y=j/jscale */
291
292   while ((c = getc(f)) == ' ');
293   if (c == '*') {
294     while ((c = getc(f)) != '\n');
295     return 0;
296   }
297   i = m = frac = 0;
298   while (isdigit(c) || c == '.' || c == '-') {
299     if (c == '-') {
300       m++;
301       c = getc(f);
302       continue;
303     }
304     if (c == '.')
305       frac = 1;
306     else {
307       if (frac)
308         iscale *= 10;
309       i = 10 * i + c - '0';
310     }
311     c = getc(f);
312   }
313   if (m)
314     i = -i;
315   *xp = (double) i / (double) iscale;
316
317   while ((c = getc(f)) == ' ');
318   j = m = frac = 0;
319   while (isdigit(c) || c == '.' || c == '-') {
320     if (c == '-') {
321       m++;
322       c = getc(f);
323       continue;
324     }
325     if (c == '.')
326       frac = 1;
327     else {
328       if (frac)
329         jscale *= 10;
330       j = 10 * j + c - '0';
331     }
332     c = getc(f);
333   }
334   if (m)
335     j = -j;
336   *yp = (double) j / (double) jscale;
337   return (SUNFILE || i != -iscale || j != -jscale);
338 }
339 #endif  /* UW_FASTSCAN */
340
341 /* EOF */