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