1/* $NetBSD: hdb.cpp,v 1.2 2018/05/16 13:53:28 joerg Exp $ */ 2 3 /* Last non-groff version: hdb.c 1.8 (Berkeley) 84/10/20 4 * 5 * Copyright -C- 1982 Barry S. Roitblat 6 * 7 * This file contains database routines for the hard copy programs of the 8 * gremlin picture editor. 9 */ 10 11#include "gprint.h" 12#include <stdlib.h> 13#include <string.h> 14#include <ctype.h> 15 16#include "errarg.h" 17#include "error.h" 18 19#define MAXSTRING 128 20#define MAXSTRING_S "127" 21 22/* imports from main.cpp */ 23 24extern int linenum; /* current line number in input file */ 25extern char gremlinfile[]; /* name of file currently reading */ 26extern int SUNFILE; /* TRUE if SUN gremlin file */ 27extern int compatibility_flag; /* TRUE if in compatibility mode */ 28extern void savebounds(double x, double y); 29 30/* imports from hpoint.cpp */ 31 32extern POINT *PTInit(); 33extern POINT *PTMakePoint(double x, double y, POINT ** pplist); 34 35 36int DBGetType(char *s); 37 38 39/* 40 * This routine returns a pointer to an initialized database element which 41 * would be the only element in an empty list. 42 */ 43ELT * 44DBInit() 45{ 46 return ((ELT *) NULL); 47} /* end DBInit */ 48 49 50/* 51 * This routine creates a new element with the specified attributes and 52 * links it into database. 53 */ 54ELT * 55DBCreateElt(int type, 56 POINT * pointlist, 57 int brush, 58 int size, 59 char *text, 60 ELT **db) 61{ 62 ELT *temp; 63 64 temp = (ELT *) malloc(sizeof(ELT)); 65 temp->nextelt = *db; 66 temp->type = type; 67 temp->ptlist = pointlist; 68 temp->brushf = brush; 69 temp->size = size; 70 temp->textpt = text; 71 *db = temp; 72 return (temp); 73} /* end CreateElt */ 74 75 76/* 77 * This routine reads the specified file into a database and returns a 78 * pointer to that database. 79 */ 80ELT * 81DBRead(FILE *file) 82{ 83 int i; 84 int done; /* flag for input exhausted */ 85 double nx; /* x holder so x is not set before orienting */ 86 int type; /* element type */ 87 ELT *elist; /* pointer to the file's elements */ 88 POINT *plist; /* pointer for reading in points */ 89 char string[MAXSTRING], *txt; 90 double x, y; /* x and y are read in point coords */ 91 int len, brush, size; 92 int lastpoint; 93 94 SUNFILE = FALSE; 95 elist = DBInit(); 96 (void) fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string); 97 if (strcmp(string, "gremlinfile")) { 98 if (strcmp(string, "sungremlinfile")) { 99 error("`%1' is not a gremlin file", gremlinfile); 100 return (elist); 101 } 102 SUNFILE = TRUE; 103 } 104 105 (void) fscanf(file, "%d%lf%lf\n", &size, &x, &y); 106 /* ignore orientation and file positioning point */ 107 108 done = FALSE; 109 while (!done) { 110 /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */ 111 /* I changed the scanf format because the element */ 112 /* can have two words (e.g. CURVE SPLINE) */ 113 if (fscanf(file, "\n%" MAXSTRING_S "[^\n]%*[^\n]\n", string) == EOF) { 114 error("`%1', error in file format", gremlinfile); 115 return (elist); 116 } 117 118 type = DBGetType(string); /* interpret element type */ 119 if (type < 0) { /* no more data */ 120 done = TRUE; 121 } else { 122#ifdef UW_FASTSCAN 123 (void) xscanf(file, &x, &y); /* always one point */ 124#else 125 (void) fscanf(file, "%lf%lf\n", &x, &y); /* always one point */ 126#endif /* UW_FASTSCAN */ 127 plist = PTInit(); /* NULL point list */ 128 129 /* 130 * Files created on the SUN have point lists terminated by a line 131 * containing only an asterik ('*'). Files created on the AED have 132 * point lists terminated by the coordinate pair (-1.00 -1.00). 133 */ 134 if (TEXT(type)) { /* read only first point for TEXT elements */ 135 nx = xorn(x, y); 136 y = yorn(x, y); 137 (void) PTMakePoint(nx, y, &plist); 138 savebounds(nx, y); 139 140#ifdef UW_FASTSCAN 141 while (xscanf(file, &x, &y)); 142#else 143 lastpoint = FALSE; 144 do { 145 fgets(string, MAXSTRING, file); 146 if (string[0] == '*') { /* SUN gremlin file */ 147 lastpoint = TRUE; 148 } else { 149 (void) sscanf(string, "%lf%lf", &x, &y); 150 if ((x == -1.00 && y == -1.00) && (!SUNFILE)) 151 lastpoint = TRUE; 152 else { 153 if (compatibility_flag) 154 savebounds(xorn(x, y), yorn(x, y)); 155 } 156 } 157 } while (!lastpoint); 158#endif /* UW_FASTSCAN */ 159 } else { /* not TEXT element */ 160#ifdef UW_FASTSCAN 161 do { 162 nx = xorn(x, y); 163 y = yorn(x, y); 164 (void) PTMakePoint(nx, y, &plist); 165 savebounds(nx, y); 166 } while (xscanf(file, &x, &y)); 167#else 168 lastpoint = FALSE; 169 while (!lastpoint) { 170 nx = xorn(x, y); 171 y = yorn(x, y); 172 (void) PTMakePoint(nx, y, &plist); 173 savebounds(nx, y); 174 175 fgets(string, MAXSTRING, file); 176 if (string[0] == '*') { /* SUN gremlin file */ 177 lastpoint = TRUE; 178 } else { 179 (void) sscanf(string, "%lf%lf", &x, &y); 180 if ((x == -1.00 && y == -1.00) && (!SUNFILE)) 181 lastpoint = TRUE; 182 } 183 } 184#endif /* UW_FASTSCAN */ 185 } 186 (void) fscanf(file, "%d%d\n", &brush, &size); 187 (void) fscanf(file, "%d", &len); /* text length */ 188 (void) getc(file); /* eat blank */ 189 txt = (char *) malloc((unsigned) len + 1); 190 for (i = 0; i < len; ++i) { /* read text */ 191 int c = getc(file); 192 if (c == EOF) 193 break; 194 txt[i] = c; 195 } 196 txt[len] = '\0'; 197 (void) DBCreateElt(type, plist, brush, size, txt, &elist); 198 } /* end else */ 199 } /* end while not done */ ; 200 return (elist); 201} /* end DBRead */ 202 203 204/* 205 * Interpret element type in string s. 206 * Old file format consisted of integer element types. 207 * New file format has literal names for element types. 208 */ 209int 210DBGetType(char *s) 211{ 212 if (isdigit(s[0]) || (s[0] == '-')) /* old element format or EOF */ 213 return (atoi(s)); 214 215 switch (s[0]) { 216 case 'P': 217 return (POLYGON); 218 case 'V': 219 return (VECTOR); 220 case 'A': 221 return (ARC); 222 case 'C': 223 if (s[1] == 'U') { 224 if (s[5] == '\n') 225 return (CURVE); 226 switch (s[7]) { 227 case 'S': 228 return(BSPLINE); 229 case 'E': 230 fprintf(stderr, 231 "Warning: Bezier Curves will be printed as B-Splines\n"); 232 return(BSPLINE); 233 default: 234 return(CURVE); 235 } 236 } 237 switch (s[4]) { 238 case 'L': 239 return (CENTLEFT); 240 case 'C': 241 return (CENTCENT); 242 case 'R': 243 return (CENTRIGHT); 244 default: 245 fatal("unknown element type"); 246 } 247 case 'B': 248 switch (s[3]) { 249 case 'L': 250 return (BOTLEFT); 251 case 'C': 252 return (BOTCENT); 253 case 'R': 254 return (BOTRIGHT); 255 default: 256 fatal("unknown element type"); 257 } 258 case 'T': 259 switch (s[3]) { 260 case 'L': 261 return (TOPLEFT); 262 case 'C': 263 return (TOPCENT); 264 case 'R': 265 return (TOPRIGHT); 266 default: 267 fatal("unknown element type"); 268 } 269 default: 270 fatal("unknown element type"); 271 } 272 273 return 0; /* never reached */ 274} 275 276#ifdef UW_FASTSCAN 277/* 278 * Optimization hack added by solomon@crys.wisc.edu, 12/2/86. 279 * A huge fraction of the time was spent reading floating point numbers from 280 * the input file, but the numbers always have the format 'ddd.dd'. Thus 281 * the following special-purpose version of fscanf. 282 * 283 * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except: 284 * -the next piece of input must be of the form 285 * <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>* 286 * -xscanf eats the character following the second number 287 * -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where 288 * end-of-data is signalled by a '*' [in which case the rest of the 289 * line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE]. 290 */ 291int 292xscanf(FILE *f, 293 double *xp, 294 double *yp) 295{ 296 int c, i, j, m, frac; 297 int iscale = 1, jscale = 1; /* x = i/scale, y=j/jscale */ 298 299 while ((c = getc(f)) == ' '); 300 if (c == '*') { 301 while ((c = getc(f)) != '\n'); 302 return 0; 303 } 304 i = m = frac = 0; 305 while (isdigit(c) || c == '.' || c == '-') { 306 if (c == '-') { 307 m++; 308 c = getc(f); 309 continue; 310 } 311 if (c == '.') 312 frac = 1; 313 else { 314 if (frac) 315 iscale *= 10; 316 i = 10 * i + c - '0'; 317 } 318 c = getc(f); 319 } 320 if (m) 321 i = -i; 322 *xp = (double) i / (double) iscale; 323 324 while ((c = getc(f)) == ' '); 325 j = m = frac = 0; 326 while (isdigit(c) || c == '.' || c == '-') { 327 if (c == '-') { 328 m++; 329 c = getc(f); 330 continue; 331 } 332 if (c == '.') 333 frac = 1; 334 else { 335 if (frac) 336 jscale *= 10; 337 j = 10 * j + c - '0'; 338 } 339 c = getc(f); 340 } 341 if (m) 342 j = -j; 343 *yp = (double) j / (double) jscale; 344 return (SUNFILE || i != -iscale || j != -jscale); 345} 346#endif /* UW_FASTSCAN */ 347 348/* EOF */ 349