1151497Sru /* Last non-groff version: hdb.c  1.8 (Berkeley) 84/10/20
2114402Sru *
3114402Sru * Copyright -C- 1982 Barry S. Roitblat
4114402Sru *
5114402Sru * This file contains database routines for the hard copy programs of the
6114402Sru * gremlin picture editor.
7114402Sru */
8114402Sru
9114402Sru#include "gprint.h"
10114402Sru#include <stdlib.h>
11114402Sru#include <string.h>
12114402Sru#include <ctype.h>
13114402Sru
14114402Sru#include "errarg.h"
15114402Sru#include "error.h"
16114402Sru
17114402Sru#define MAXSTRING 128
18114402Sru#define MAXSTRING_S "127"
19114402Sru
20114402Sru/* imports from main.cpp */
21114402Sru
22114402Sruextern int linenum;		/* current line number in input file */
23114402Sruextern char gremlinfile[];	/* name of file currently reading */
24114402Sruextern int SUNFILE;		/* TRUE if SUN gremlin file */
25151497Sruextern int compatibility_flag;	/* TRUE if in compatibility mode */
26151497Sruextern void savebounds(double x, double y);
27114402Sru
28114402Sru/* imports from hpoint.cpp */
29114402Sru
30114402Sruextern POINT *PTInit();
31151497Sruextern POINT *PTMakePoint(double x, double y, POINT ** pplist);
32114402Sru
33114402Sru
34114402Sruint DBGetType(register char *s);
35114402Sru
36114402Sru
37114402Sru/*
38114402Sru * This routine returns a pointer to an initialized database element which
39114402Sru * would be the only element in an empty list.
40114402Sru */
41114402SruELT *
42114402SruDBInit()
43114402Sru{
44114402Sru  return ((ELT *) NULL);
45114402Sru}				/* end DBInit */
46114402Sru
47114402Sru
48114402Sru/*
49114402Sru * This routine creates a new element with the specified attributes and
50114402Sru * links it into database.
51114402Sru */
52114402SruELT *
53114402SruDBCreateElt(int type,
54114402Sru	    POINT * pointlist,
55114402Sru	    int brush,
56114402Sru	    int size,
57114402Sru	    char *text,
58114402Sru	    ELT **db)
59114402Sru{
60114402Sru  register ELT *temp;
61114402Sru
62114402Sru  temp = (ELT *) malloc(sizeof(ELT));
63114402Sru  temp->nextelt = *db;
64114402Sru  temp->type = type;
65114402Sru  temp->ptlist = pointlist;
66114402Sru  temp->brushf = brush;
67114402Sru  temp->size = size;
68114402Sru  temp->textpt = text;
69114402Sru  *db = temp;
70114402Sru  return (temp);
71114402Sru}				/* end CreateElt */
72114402Sru
73114402Sru
74114402Sru/*
75114402Sru * This routine reads the specified file into a database and returns a
76114402Sru * pointer to that database.
77114402Sru */
78114402SruELT *
79114402SruDBRead(register FILE *file)
80114402Sru{
81114402Sru  register int i;
82114402Sru  register int done;		/* flag for input exhausted */
83151497Sru  register double nx;		/* x holder so x is not set before orienting */
84114402Sru  int type;			/* element type */
85114402Sru  ELT *elist;			/* pointer to the file's elements */
86114402Sru  POINT *plist;			/* pointer for reading in points */
87114402Sru  char string[MAXSTRING], *txt;
88151497Sru  double x, y;			/* x and y are read in point coords */
89114402Sru  int len, brush, size;
90114402Sru  int lastpoint;
91114402Sru
92114402Sru  SUNFILE = FALSE;
93114402Sru  elist = DBInit();
94114402Sru  (void) fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string);
95114402Sru  if (strcmp(string, "gremlinfile")) {
96114402Sru    if (strcmp(string, "sungremlinfile")) {
97114402Sru      error("`%1' is not a gremlin file", gremlinfile);
98114402Sru      return (elist);
99114402Sru    }
100114402Sru    SUNFILE = TRUE;
101114402Sru  }
102114402Sru
103151497Sru  (void) fscanf(file, "%d%lf%lf\n", &size, &x, &y);
104114402Sru  /* ignore orientation and file positioning point */
105114402Sru
106114402Sru  done = FALSE;
107114402Sru  while (!done) {
108114402Sru    /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */
109114402Sru    /* I changed the scanf format because the element */
110114402Sru    /* can have two words (e.g. CURVE SPLINE)         */
111114402Sru    if (fscanf(file, "\n%" MAXSTRING_S "[^\n]%*[^\n]\n", string) == EOF) {
112114402Sru      error("`%1', error in file format", gremlinfile);
113114402Sru      return (elist);
114114402Sru    }
115114402Sru
116114402Sru    type = DBGetType(string);	/* interpret element type */
117114402Sru    if (type < 0) {		/* no more data */
118114402Sru      done = TRUE;
119114402Sru    } else {
120114402Sru#ifdef UW_FASTSCAN
121114402Sru      (void) xscanf(file, &x, &y);		/* always one point */
122114402Sru#else
123151497Sru      (void) fscanf(file, "%lf%lf\n", &x, &y);	/* always one point */
124114402Sru#endif	/* UW_FASTSCAN */
125114402Sru      plist = PTInit();		/* NULL point list */
126114402Sru
127114402Sru      /*
128114402Sru       * Files created on the SUN have point lists terminated by a line
129114402Sru       * containing only an asterik ('*').  Files created on the AED have
130114402Sru       * point lists terminated by the coordinate pair (-1.00 -1.00).
131114402Sru       */
132114402Sru      if (TEXT(type)) {		/* read only first point for TEXT elements */
133114402Sru	nx = xorn(x, y);
134114402Sru	y = yorn(x, y);
135114402Sru	(void) PTMakePoint(nx, y, &plist);
136114402Sru	savebounds(nx, y);
137114402Sru
138114402Sru#ifdef UW_FASTSCAN
139114402Sru	while (xscanf(file, &x, &y));
140114402Sru#else
141114402Sru	lastpoint = FALSE;
142114402Sru	do {
143114402Sru	  fgets(string, MAXSTRING, file);
144114402Sru	  if (string[0] == '*') {	/* SUN gremlin file */
145114402Sru	    lastpoint = TRUE;
146114402Sru	  } else {
147151497Sru	    (void) sscanf(string, "%lf%lf", &x, &y);
148114402Sru	    if ((x == -1.00 && y == -1.00) && (!SUNFILE))
149114402Sru	      lastpoint = TRUE;
150151497Sru	    else {
151151497Sru	      if (compatibility_flag)
152151497Sru		savebounds(xorn(x, y), yorn(x, y));
153151497Sru	    }
154114402Sru	  }
155114402Sru	} while (!lastpoint);
156114402Sru#endif	/* UW_FASTSCAN */
157114402Sru      } else {			/* not TEXT element */
158114402Sru#ifdef UW_FASTSCAN
159114402Sru	do {
160114402Sru	  nx = xorn(x, y);
161114402Sru	  y = yorn(x, y);
162114402Sru	  (void) PTMakePoint(nx, y, &plist);
163114402Sru	  savebounds(nx, y);
164114402Sru	} while (xscanf(file, &x, &y));
165114402Sru#else
166114402Sru	lastpoint = FALSE;
167114402Sru	while (!lastpoint) {
168114402Sru	  nx = xorn(x, y);
169114402Sru	  y = yorn(x, y);
170114402Sru	  (void) PTMakePoint(nx, y, &plist);
171114402Sru	  savebounds(nx, y);
172114402Sru
173114402Sru	  fgets(string, MAXSTRING, file);
174114402Sru	  if (string[0] == '*') {	/* SUN gremlin file */
175114402Sru	    lastpoint = TRUE;
176114402Sru	  } else {
177151497Sru	    (void) sscanf(string, "%lf%lf", &x, &y);
178114402Sru	    if ((x == -1.00 && y == -1.00) && (!SUNFILE))
179114402Sru	      lastpoint = TRUE;
180114402Sru	  }
181114402Sru	}
182114402Sru#endif	/* UW_FASTSCAN */
183114402Sru      }
184114402Sru      (void) fscanf(file, "%d%d\n", &brush, &size);
185114402Sru      (void) fscanf(file, "%d", &len);	/* text length */
186114402Sru      (void) getc(file);		/* eat blank */
187114402Sru      txt = (char *) malloc((unsigned) len + 1);
188114402Sru      for (i = 0; i < len; ++i) {	/* read text */
189151497Sru        int c = getc(file);
190151497Sru        if (c == EOF)
191151497Sru          break;
192151497Sru	txt[i] = c;
193114402Sru      }
194114402Sru      txt[len] = '\0';
195114402Sru      (void) DBCreateElt(type, plist, brush, size, txt, &elist);
196114402Sru    }				/* end else */
197114402Sru  } /* end while not done */ ;
198114402Sru  return (elist);
199114402Sru}				/* end DBRead */
200114402Sru
201114402Sru
202114402Sru/*
203114402Sru * Interpret element type in string s.
204114402Sru * Old file format consisted of integer element types.
205114402Sru * New file format has literal names for element types.
206114402Sru */
207114402Sruint
208114402SruDBGetType(register char *s)
209114402Sru{
210114402Sru  if (isdigit(s[0]) || (s[0] == '-'))	/* old element format or EOF */
211114402Sru    return (atoi(s));
212114402Sru
213114402Sru  switch (s[0]) {
214114402Sru  case 'P':
215114402Sru    return (POLYGON);
216114402Sru  case 'V':
217114402Sru    return (VECTOR);
218114402Sru  case 'A':
219114402Sru    return (ARC);
220114402Sru  case 'C':
221114402Sru    if (s[1] == 'U') {
222114402Sru      if (s[5] == '\n')
223114402Sru	return (CURVE);
224114402Sru      switch (s[7]) {
225114402Sru      case 'S':
226114402Sru	return(BSPLINE);
227114402Sru      case 'E':
228114402Sru	fprintf(stderr,
229114402Sru		"Warning: Bezier Curves will be printed as B-Splines\n");
230114402Sru	return(BSPLINE);
231114402Sru      default:
232114402Sru	return(CURVE);
233114402Sru      }
234114402Sru    }
235114402Sru    switch (s[4]) {
236114402Sru    case 'L':
237114402Sru      return (CENTLEFT);
238114402Sru    case 'C':
239114402Sru      return (CENTCENT);
240114402Sru    case 'R':
241114402Sru      return (CENTRIGHT);
242114402Sru    default:
243114402Sru      fatal("unknown element type");
244114402Sru    }
245114402Sru  case 'B':
246114402Sru    switch (s[3]) {
247114402Sru    case 'L':
248114402Sru      return (BOTLEFT);
249114402Sru    case 'C':
250114402Sru      return (BOTCENT);
251114402Sru    case 'R':
252114402Sru      return (BOTRIGHT);
253114402Sru    default:
254114402Sru      fatal("unknown element type");
255114402Sru    }
256114402Sru  case 'T':
257114402Sru    switch (s[3]) {
258114402Sru    case 'L':
259114402Sru      return (TOPLEFT);
260114402Sru    case 'C':
261114402Sru      return (TOPCENT);
262114402Sru    case 'R':
263114402Sru      return (TOPRIGHT);
264114402Sru    default:
265114402Sru      fatal("unknown element type");
266114402Sru    }
267114402Sru  default:
268114402Sru    fatal("unknown element type");
269114402Sru  }
270114402Sru
271114402Sru  return 0;				/* never reached */
272114402Sru}
273114402Sru
274114402Sru#ifdef UW_FASTSCAN
275114402Sru/*
276114402Sru * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
277114402Sru * A huge fraction of the time was spent reading floating point numbers from
278114402Sru * the input file, but the numbers always have the format 'ddd.dd'.  Thus
279114402Sru * the following special-purpose version of fscanf.
280114402Sru *
281114402Sru * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
282114402Sru *   -the next piece of input must be of the form
283114402Sru *      <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
284114402Sru *   -xscanf eats the character following the second number
285114402Sru *   -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
286114402Sru *    end-of-data is signalled by a '*' [in which case the rest of the
287114402Sru *    line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
288114402Sru */
289114402Sruint
290114402Sruxscanf(FILE *f,
291151497Sru       double *xp,
292151497Sru       double *yp)
293114402Sru{
294114402Sru  register int c, i, j, m, frac;
295114402Sru  int iscale = 1, jscale = 1;	/* x = i/scale, y=j/jscale */
296114402Sru
297114402Sru  while ((c = getc(f)) == ' ');
298114402Sru  if (c == '*') {
299114402Sru    while ((c = getc(f)) != '\n');
300114402Sru    return 0;
301114402Sru  }
302114402Sru  i = m = frac = 0;
303114402Sru  while (isdigit(c) || c == '.' || c == '-') {
304114402Sru    if (c == '-') {
305114402Sru      m++;
306114402Sru      c = getc(f);
307114402Sru      continue;
308114402Sru    }
309114402Sru    if (c == '.')
310114402Sru      frac = 1;
311114402Sru    else {
312114402Sru      if (frac)
313114402Sru	iscale *= 10;
314114402Sru      i = 10 * i + c - '0';
315114402Sru    }
316114402Sru    c = getc(f);
317114402Sru  }
318114402Sru  if (m)
319114402Sru    i = -i;
320114402Sru  *xp = (double) i / (double) iscale;
321114402Sru
322114402Sru  while ((c = getc(f)) == ' ');
323114402Sru  j = m = frac = 0;
324114402Sru  while (isdigit(c) || c == '.' || c == '-') {
325114402Sru    if (c == '-') {
326114402Sru      m++;
327114402Sru      c = getc(f);
328114402Sru      continue;
329114402Sru    }
330114402Sru    if (c == '.')
331114402Sru      frac = 1;
332114402Sru    else {
333114402Sru      if (frac)
334114402Sru	jscale *= 10;
335114402Sru      j = 10 * j + c - '0';
336114402Sru    }
337114402Sru    c = getc(f);
338114402Sru  }
339114402Sru  if (m)
340114402Sru    j = -j;
341114402Sru  *yp = (double) j / (double) jscale;
342114402Sru  return (SUNFILE || i != -iscale || j != -jscale);
343114402Sru}
344114402Sru#endif	/* UW_FASTSCAN */
345114402Sru
346114402Sru/* EOF */
347