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