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 9#include "gprint.h" 10#include <stdlib.h> 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 */ 25extern int compatibility_flag; /* TRUE if in compatibility mode */ 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; 150 else { 151 if (compatibility_flag) 152 savebounds(xorn(x, y), yorn(x, y)); 153 } 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 */ 347