groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / preproc / grn / hdb.cpp
CommitLineData
92d0a6a6
JR
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
92d0a6a6 9#include <stdlib.h>
4d3e9548 10#include "gprint.h"
92d0a6a6
JR
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
22extern int linenum; /* current line number in input file */
23extern char gremlinfile[]; /* name of file currently reading */
24extern int SUNFILE; /* TRUE if SUN gremlin file */
465b256c 25extern int compatibility_flag; /* TRUE if in compatibility mode */
92d0a6a6
JR
26extern void savebounds(double x, double y);
27
28/* imports from hpoint.cpp */
29
30extern POINT *PTInit();
31extern POINT *PTMakePoint(double x, double y, POINT ** pplist);
32
33
34int 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 */
41ELT *
42DBInit()
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 */
52ELT *
53DBCreateElt(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 */
78ELT *
79DBRead(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;
465b256c
JR
150 else {
151 if (compatibility_flag)
152 savebounds(xorn(x, y), yorn(x, y));
153 }
92d0a6a6
JR
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 */
207int
208DBGetType(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 */
289int
290xscanf(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 */