hdb.cpp revision 151497
1215976Sjmallett /* Last non-groff version: hdb.c  1.8 (Berkeley) 84/10/20
2232812Sjmallett *
3215976Sjmallett * Copyright -C- 1982 Barry S. Roitblat
4215976Sjmallett *
5215976Sjmallett * This file contains database routines for the hard copy programs of the
6215976Sjmallett * gremlin picture editor.
7215976Sjmallett */
8215976Sjmallett
9215976Sjmallett#include "gprint.h"
10215976Sjmallett#include <stdlib.h>
11215976Sjmallett#include <string.h>
12215976Sjmallett#include <ctype.h>
13215976Sjmallett
14215976Sjmallett#include "errarg.h"
15215976Sjmallett#include "error.h"
16215976Sjmallett
17215976Sjmallett#define MAXSTRING 128
18232812Sjmallett#define MAXSTRING_S "127"
19215976Sjmallett
20215976Sjmallett/* imports from main.cpp */
21215976Sjmallett
22215976Sjmallettextern int linenum;		/* current line number in input file */
23215976Sjmallettextern char gremlinfile[];	/* name of file currently reading */
24215976Sjmallettextern int SUNFILE;		/* TRUE if SUN gremlin file */
25215976Sjmallettextern int compatibility_flag;	/* TRUE if in compatibility mode */
26215976Sjmallettextern void savebounds(double x, double y);
27215976Sjmallett
28215976Sjmallett/* imports from hpoint.cpp */
29232812Sjmallett
30215976Sjmallettextern POINT *PTInit();
31215976Sjmallettextern POINT *PTMakePoint(double x, double y, POINT ** pplist);
32215976Sjmallett
33215976Sjmallett
34215976Sjmallettint DBGetType(register char *s);
35215976Sjmallett
36215976Sjmallett
37215976Sjmallett/*
38215976Sjmallett * This routine returns a pointer to an initialized database element which
39215976Sjmallett * would be the only element in an empty list.
40215976Sjmallett */
41215976SjmallettELT *
42215976SjmallettDBInit()
43215976Sjmallett{
44215976Sjmallett  return ((ELT *) NULL);
45215976Sjmallett}				/* end DBInit */
46215976Sjmallett
47215976Sjmallett
48215976Sjmallett/*
49215976Sjmallett * This routine creates a new element with the specified attributes and
50215976Sjmallett * links it into database.
51215976Sjmallett */
52232812SjmallettELT *
53232812SjmallettDBCreateElt(int type,
54215976Sjmallett	    POINT * pointlist,
55215976Sjmallett	    int brush,
56215976Sjmallett	    int size,
57215976Sjmallett	    char *text,
58215976Sjmallett	    ELT **db)
59232812Sjmallett{
60232812Sjmallett  register ELT *temp;
61215976Sjmallett
62232812Sjmallett  temp = (ELT *) malloc(sizeof(ELT));
63215976Sjmallett  temp->nextelt = *db;
64215976Sjmallett  temp->type = type;
65232812Sjmallett  temp->ptlist = pointlist;
66215976Sjmallett  temp->brushf = brush;
67215976Sjmallett  temp->size = size;
68215976Sjmallett  temp->textpt = text;
69215976Sjmallett  *db = temp;
70215976Sjmallett  return (temp);
71232812Sjmallett}				/* end CreateElt */
72232812Sjmallett
73215976Sjmallett
74232812Sjmallett/*
75215976Sjmallett * This routine reads the specified file into a database and returns a
76215976Sjmallett * pointer to that database.
77232812Sjmallett */
78215976SjmallettELT *
79215976SjmallettDBRead(register FILE *file)
80215976Sjmallett{
81215976Sjmallett  register int i;
82215976Sjmallett  register int done;		/* flag for input exhausted */
83232812Sjmallett  register double nx;		/* x holder so x is not set before orienting */
84232812Sjmallett  int type;			/* element type */
85215976Sjmallett  ELT *elist;			/* pointer to the file's elements */
86232812Sjmallett  POINT *plist;			/* pointer for reading in points */
87215976Sjmallett  char string[MAXSTRING], *txt;
88215976Sjmallett  double x, y;			/* x and y are read in point coords */
89232812Sjmallett  int len, brush, size;
90215976Sjmallett  int lastpoint;
91215976Sjmallett
92215976Sjmallett  SUNFILE = FALSE;
93215976Sjmallett  elist = DBInit();
94215976Sjmallett  (void) fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string);
95232812Sjmallett  if (strcmp(string, "gremlinfile")) {
96232812Sjmallett    if (strcmp(string, "sungremlinfile")) {
97215976Sjmallett      error("`%1' is not a gremlin file", gremlinfile);
98232812Sjmallett      return (elist);
99215976Sjmallett    }
100215976Sjmallett    SUNFILE = TRUE;
101232812Sjmallett  }
102215976Sjmallett
103215976Sjmallett  (void) fscanf(file, "%d%lf%lf\n", &size, &x, &y);
104215976Sjmallett  /* ignore orientation and file positioning point */
105215976Sjmallett
106215976Sjmallett  done = FALSE;
107232812Sjmallett  while (!done) {
108232812Sjmallett    /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */
109215976Sjmallett    /* I changed the scanf format because the element */
110232812Sjmallett    /* can have two words (e.g. CURVE SPLINE)         */
111215976Sjmallett    if (fscanf(file, "\n%" MAXSTRING_S "[^\n]%*[^\n]\n", string) == EOF) {
112215976Sjmallett      error("`%1', error in file format", gremlinfile);
113232812Sjmallett      return (elist);
114215976Sjmallett    }
115215976Sjmallett
116215976Sjmallett    type = DBGetType(string);	/* interpret element type */
117215976Sjmallett    if (type < 0) {		/* no more data */
118215976Sjmallett      done = TRUE;
119232812Sjmallett    } else {
120232812Sjmallett#ifdef UW_FASTSCAN
121215976Sjmallett      (void) xscanf(file, &x, &y);		/* always one point */
122232812Sjmallett#else
123215976Sjmallett      (void) fscanf(file, "%lf%lf\n", &x, &y);	/* always one point */
124215976Sjmallett#endif	/* UW_FASTSCAN */
125232812Sjmallett      plist = PTInit();		/* NULL point list */
126215976Sjmallett
127215976Sjmallett      /*
128215976Sjmallett       * Files created on the SUN have point lists terminated by a line
129215976Sjmallett       * containing only an asterik ('*').  Files created on the AED have
130215976Sjmallett       * point lists terminated by the coordinate pair (-1.00 -1.00).
131232812Sjmallett       */
132232812Sjmallett      if (TEXT(type)) {		/* read only first point for TEXT elements */
133215976Sjmallett	nx = xorn(x, y);
134232812Sjmallett	y = yorn(x, y);
135215976Sjmallett	(void) PTMakePoint(nx, y, &plist);
136215976Sjmallett	savebounds(nx, y);
137232812Sjmallett
138215976Sjmallett#ifdef UW_FASTSCAN
139215976Sjmallett	while (xscanf(file, &x, &y));
140215976Sjmallett#else
141215976Sjmallett	lastpoint = FALSE;
142215976Sjmallett	do {
143232812Sjmallett	  fgets(string, MAXSTRING, file);
144232812Sjmallett	  if (string[0] == '*') {	/* SUN gremlin file */
145215976Sjmallett	    lastpoint = TRUE;
146232812Sjmallett	  } else {
147215976Sjmallett	    (void) sscanf(string, "%lf%lf", &x, &y);
148215976Sjmallett	    if ((x == -1.00 && y == -1.00) && (!SUNFILE))
149232812Sjmallett	      lastpoint = TRUE;
150215976Sjmallett	    else {
151215976Sjmallett	      if (compatibility_flag)
152215976Sjmallett		savebounds(xorn(x, y), yorn(x, y));
153215976Sjmallett	    }
154215976Sjmallett	  }
155232812Sjmallett	} while (!lastpoint);
156232812Sjmallett#endif	/* UW_FASTSCAN */
157215976Sjmallett      } else {			/* not TEXT element */
158232812Sjmallett#ifdef UW_FASTSCAN
159215976Sjmallett	do {
160215976Sjmallett	  nx = xorn(x, y);
161232812Sjmallett	  y = yorn(x, y);
162215976Sjmallett	  (void) PTMakePoint(nx, y, &plist);
163215976Sjmallett	  savebounds(nx, y);
164215976Sjmallett	} while (xscanf(file, &x, &y));
165215976Sjmallett#else
166215976Sjmallett	lastpoint = FALSE;
167232812Sjmallett	while (!lastpoint) {
168232812Sjmallett	  nx = xorn(x, y);
169215976Sjmallett	  y = yorn(x, y);
170232812Sjmallett	  (void) PTMakePoint(nx, y, &plist);
171215976Sjmallett	  savebounds(nx, y);
172215976Sjmallett
173232812Sjmallett	  fgets(string, MAXSTRING, file);
174215976Sjmallett	  if (string[0] == '*') {	/* SUN gremlin file */
175215976Sjmallett	    lastpoint = TRUE;
176232812Sjmallett	  } else {
177232812Sjmallett	    (void) sscanf(string, "%lf%lf", &x, &y);
178232812Sjmallett	    if ((x == -1.00 && y == -1.00) && (!SUNFILE))
179232812Sjmallett	      lastpoint = TRUE;
180232812Sjmallett	  }
181232812Sjmallett	}
182232812Sjmallett#endif	/* UW_FASTSCAN */
183232812Sjmallett      }
184232812Sjmallett      (void) fscanf(file, "%d%d\n", &brush, &size);
185232812Sjmallett      (void) fscanf(file, "%d", &len);	/* text length */
186232812Sjmallett      (void) getc(file);		/* eat blank */
187215976Sjmallett      txt = (char *) malloc((unsigned) len + 1);
188215976Sjmallett      for (i = 0; i < len; ++i) {	/* read text */
189215976Sjmallett        int c = getc(file);
190232812Sjmallett        if (c == EOF)
191232812Sjmallett          break;
192215976Sjmallett	txt[i] = c;
193232812Sjmallett      }
194215976Sjmallett      txt[len] = '\0';
195215976Sjmallett      (void) DBCreateElt(type, plist, brush, size, txt, &elist);
196232812Sjmallett    }				/* end else */
197215976Sjmallett  } /* end while not done */ ;
198215976Sjmallett  return (elist);
199215976Sjmallett}				/* end DBRead */
200215976Sjmallett
201215976Sjmallett
202232812Sjmallett/*
203232812Sjmallett * Interpret element type in string s.
204215976Sjmallett * Old file format consisted of integer element types.
205232812Sjmallett * New file format has literal names for element types.
206215976Sjmallett */
207215976Sjmallettint
208232812SjmallettDBGetType(register char *s)
209215976Sjmallett{
210215976Sjmallett  if (isdigit(s[0]) || (s[0] == '-'))	/* old element format or EOF */
211215976Sjmallett    return (atoi(s));
212215976Sjmallett
213215976Sjmallett  switch (s[0]) {
214232812Sjmallett  case 'P':
215232812Sjmallett    return (POLYGON);
216215976Sjmallett  case 'V':
217232812Sjmallett    return (VECTOR);
218215976Sjmallett  case 'A':
219215976Sjmallett    return (ARC);
220232812Sjmallett  case 'C':
221215976Sjmallett    if (s[1] == 'U') {
222215976Sjmallett      if (s[5] == '\n')
223215976Sjmallett	return (CURVE);
224215976Sjmallett      switch (s[7]) {
225215976Sjmallett      case 'S':
226232812Sjmallett	return(BSPLINE);
227232812Sjmallett      case 'E':
228215976Sjmallett	fprintf(stderr,
229232812Sjmallett		"Warning: Bezier Curves will be printed as B-Splines\n");
230215976Sjmallett	return(BSPLINE);
231215976Sjmallett      default:
232232812Sjmallett	return(CURVE);
233215976Sjmallett      }
234215976Sjmallett    }
235215976Sjmallett    switch (s[4]) {
236215976Sjmallett    case 'L':
237215976Sjmallett      return (CENTLEFT);
238232812Sjmallett    case 'C':
239232812Sjmallett      return (CENTCENT);
240215976Sjmallett    case 'R':
241232812Sjmallett      return (CENTRIGHT);
242215976Sjmallett    default:
243215976Sjmallett      fatal("unknown element type");
244232812Sjmallett    }
245215976Sjmallett  case 'B':
246215976Sjmallett    switch (s[3]) {
247215976Sjmallett    case 'L':
248215976Sjmallett      return (BOTLEFT);
249215976Sjmallett    case 'C':
250232812Sjmallett      return (BOTCENT);
251232812Sjmallett    case 'R':
252215976Sjmallett      return (BOTRIGHT);
253232812Sjmallett    default:
254215976Sjmallett      fatal("unknown element type");
255215976Sjmallett    }
256232812Sjmallett  case 'T':
257215976Sjmallett    switch (s[3]) {
258215976Sjmallett    case 'L':
259215976Sjmallett      return (TOPLEFT);
260215976Sjmallett    case 'C':
261215976Sjmallett      return (TOPCENT);
262232812Sjmallett    case 'R':
263232812Sjmallett      return (TOPRIGHT);
264215976Sjmallett    default:
265232812Sjmallett      fatal("unknown element type");
266215976Sjmallett    }
267215976Sjmallett  default:
268232812Sjmallett    fatal("unknown element type");
269215976Sjmallett  }
270215976Sjmallett
271215976Sjmallett  return 0;				/* never reached */
272215976Sjmallett}
273215976Sjmallett
274232812Sjmallett#ifdef UW_FASTSCAN
275232812Sjmallett/*
276215976Sjmallett * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
277232812Sjmallett * A huge fraction of the time was spent reading floating point numbers from
278215976Sjmallett * the input file, but the numbers always have the format 'ddd.dd'.  Thus
279215976Sjmallett * the following special-purpose version of fscanf.
280232812Sjmallett *
281215976Sjmallett * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
282215976Sjmallett *   -the next piece of input must be of the form
283215976Sjmallett *      <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
284215976Sjmallett *   -xscanf eats the character following the second number
285215976Sjmallett *   -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
286232812Sjmallett *    end-of-data is signalled by a '*' [in which case the rest of the
287232812Sjmallett *    line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
288215976Sjmallett */
289232812Sjmallettint
290215976Sjmallettxscanf(FILE *f,
291215976Sjmallett       double *xp,
292232812Sjmallett       double *yp)
293215976Sjmallett{
294215976Sjmallett  register int c, i, j, m, frac;
295215976Sjmallett  int iscale = 1, jscale = 1;	/* x = i/scale, y=j/jscale */
296215976Sjmallett
297215976Sjmallett  while ((c = getc(f)) == ' ');
298232812Sjmallett  if (c == '*') {
299232812Sjmallett    while ((c = getc(f)) != '\n');
300215976Sjmallett    return 0;
301232812Sjmallett  }
302215976Sjmallett  i = m = frac = 0;
303215976Sjmallett  while (isdigit(c) || c == '.' || c == '-') {
304232812Sjmallett    if (c == '-') {
305215976Sjmallett      m++;
306215976Sjmallett      c = getc(f);
307215976Sjmallett      continue;
308215976Sjmallett    }
309215976Sjmallett    if (c == '.')
310232812Sjmallett      frac = 1;
311232812Sjmallett    else {
312215976Sjmallett      if (frac)
313232812Sjmallett	iscale *= 10;
314215976Sjmallett      i = 10 * i + c - '0';
315215976Sjmallett    }
316232812Sjmallett    c = getc(f);
317215976Sjmallett  }
318215976Sjmallett  if (m)
319215976Sjmallett    i = -i;
320215976Sjmallett  *xp = (double) i / (double) iscale;
321215976Sjmallett
322232812Sjmallett  while ((c = getc(f)) == ' ');
323232812Sjmallett  j = m = frac = 0;
324215976Sjmallett  while (isdigit(c) || c == '.' || c == '-') {
325232812Sjmallett    if (c == '-') {
326215976Sjmallett      m++;
327215976Sjmallett      c = getc(f);
328232812Sjmallett      continue;
329215976Sjmallett    }
330215976Sjmallett    if (c == '.')
331215976Sjmallett      frac = 1;
332215976Sjmallett    else {
333215976Sjmallett      if (frac)
334232812Sjmallett	jscale *= 10;
335232812Sjmallett      j = 10 * j + c - '0';
336215976Sjmallett    }
337232812Sjmallett    c = getc(f);
338215976Sjmallett  }
339215976Sjmallett  if (m)
340232812Sjmallett    j = -j;
341215976Sjmallett  *yp = (double) j / (double) jscale;
342215976Sjmallett  return (SUNFILE || i != -iscale || j != -jscale);
343215976Sjmallett}
344215976Sjmallett#endif	/* UW_FASTSCAN */
345215976Sjmallett
346232812Sjmallett/* EOF */
347232812Sjmallett