1 #ifndef lint 2 static char sccsid[] = "@(#)io.c 4.2 (Berkeley) 08/11/83"; 3 #endif 4 5 /* 6 * io.c: font file I/O subroutines for fed. 7 */ 8 9 #include "fed.h" 10 11 getglyph(c) 12 char c; 13 { 14 register int i, j; 15 int windno; 16 int vertoff, horoff; 17 char *tmp; 18 19 if (trace) 20 fprintf(trace, "\n\ngetglyph(%s)\n", rdchar(c)); 21 if (disptable[c].nbytes == 0) { 22 if (trace) 23 fprintf(trace, "no such char: %s\n", rdchar(c)); 24 sprintf(msgbuf, "no such character: %s", rdchar(c)); 25 message(msgbuf); 26 return; 27 } 28 29 curchar = c; 30 turnofcurs(); 31 if (cht[curchar].wherewind >= 0) { 32 /* It's already in a window. Don't have to do much. */ 33 if (trace) 34 fprintf(trace, "already in %d\n", cht[curchar].wherewind); 35 windno = cht[curchar].wherewind; 36 /* Put a box around the current window */ 37 if (windno != curwind) { 38 drawbox(base[curwind].r-1, base[curwind].c-1, 0, GLROW+2, GLCOL+2); 39 drawbox(base[windno].r-1, base[windno].c-1, 1, GLROW+2, GLCOL+2); 40 } 41 curwind = windno; 42 syncwind(windno); 43 /* should center base */ 44 } else { 45 /* 46 * Not on screen. First find a suitable window, 47 * using round robin. 48 */ 49 windno = nextwind; 50 if (trace) 51 fprintf(trace, "chose window %d\n", windno); 52 if (++nextwind >= NWIND) 53 nextwind = 0; 54 #ifdef TWOWIND 55 /* 56 * This is for debugging what happens when we run out 57 * of windows. 58 */ 59 if (nextwind >= 2) 60 nextwind = 0; 61 #endif 62 63 /* Put a box around the current window */ 64 if (windno != curwind) { 65 if (trace) 66 fprintf(trace, "drawbox (%d %d)\n", base[windno].r-1, base[windno].c-1); 67 drawbox(base[curwind].r-1, base[curwind].c-1, 0, GLROW+2, GLCOL+2); 68 drawbox(base[windno].r-1, base[windno].c-1, 1, GLROW+2, GLCOL+2); 69 } 70 71 /* Print the char at the lower left of the window */ 72 sprintf(msgbuf, "%s", rdchar(curchar)); 73 dispmsg(msgbuf, base[windno].c, base[windno].r-11, 2); 74 75 /* Now make room in the window */ 76 if (wind[windno].onscreen == NULL) { 77 /* Brand new window, have to allocate space */ 78 wind[windno].onscreen = newmat(GLROW, GLCOL); 79 } else { 80 /* Save prev glyph for later */ 81 cht[wind[windno].used].whereat = wind[windno].val; 82 cht[wind[windno].used].wherewind = -2; 83 if (trace) 84 fprintf(trace, "windno=%s, wind[windno].used=%d, cht[..].wherewind set to -2\n", rdchar(windno), wind[windno].used); 85 } 86 if (wind[windno].undval != NULL) { 87 if (trace) 88 fprintf(trace, "getglyph frees undo: %x\n", wind[windno].undval); 89 free(wind[windno].undval); 90 } 91 wind[windno].undval = NULL; 92 wind[windno].used = curchar; 93 94 /* 95 * Vertical & horizontal offsets. Line up the baseline 96 * of the char at BASELINE from bottom, but center 97 * horizontally. 98 */ 99 vertoff = GLROW - BASELINE - disptable[curchar].up; 100 /* Check to see if the glyph is being nosed off the edge. */ 101 if (vertoff < 0) { 102 vertoff = 0; 103 } else if (vertoff + disptable[curchar].up + disptable[curchar].down >= GLROW) { 104 vertoff = GLROW - disptable[curchar].up - disptable[curchar].down; 105 } 106 horoff = (GLCOL-(disptable[curchar].left+disptable[curchar].right)) / 2; 107 wind[windno].val = findbits(curchar, GLROW, GLCOL, horoff, vertoff, &curs_r, &curs_c); 108 cht[curchar].rcent = curs_r; 109 cht[curchar].ccent = curs_c; 110 curwind = windno; 111 cht[curchar].wherewind = windno; 112 syncwind(windno); 113 } 114 } 115 116 /* 117 * writeback: write the font back to the file at the end of editing. 118 * Also have to write width table. 119 */ 120 writeback() 121 { 122 writefont(fontfile); 123 } 124 125 /* 126 * writefont: write current font on file fname. 127 */ 128 writefont(fname) 129 char *fname; 130 { 131 register int i, j; 132 register int c; 133 FILE *fntout; 134 int bytes; 135 bitmat tmp; 136 int nextoff = 0; 137 int charcount, bytecount; 138 extern char *sys_errlist[]; 139 extern int errno; 140 141 if (trace) 142 fprintf(trace, "writefont(%s)\n", fname); 143 /* 144 * The following unlink is important because we are about to 145 * do an fopen( , "w") on fname. We still have fontdes open 146 * for reading. If we don't do the unlink the fopen will truncate 147 * the file and subsequent reads will fail. If we do the unlink 148 * the file won't go away until it is closed, so we can still 149 * read from the old version. 150 */ 151 if (strcmp(fname, fontfile)==0 && unlink(fname) < 0) { 152 sprintf(msgbuf, "unlink %s: %s", fname, sys_errlist[errno]); 153 error(msgbuf); 154 } 155 156 fntout = fopen(fname, "w"); 157 if (fntout == NULL) { 158 sprintf(msgbuf, "%s: %s", fname, sys_errlist[errno]); 159 if (trace) 160 fprintf(trace, "%s\n", msgbuf); 161 error(msgbuf); 162 } 163 sprintf(msgbuf, "\"%s\"", fname); 164 message(msgbuf); 165 fflush(stdout); 166 167 fwrite(&FontHeader, sizeof FontHeader, 1, fntout); 168 fwrite(&disptable[0], sizeof disptable, 1, fntout); 169 charcount = 0; bytecount = fbase; 170 for (c=0; c<256; c++) 171 if (disptable[c].nbytes || cht[c].wherewind != -1) { 172 if (trace) 173 fprintf(trace, "char %s, nbytes %d, wherewind %d.. ", rdchar(c), disptable[c].nbytes, cht[c].wherewind); 174 packmat(c, &tmp, &bytes); 175 disptable[c].addr = nextoff; 176 disptable[c].nbytes = bytes; 177 if (trace) 178 fprintf(trace, "offset %d size %d\n", nextoff, bytes); 179 nextoff += bytes; 180 fwrite(tmp, bytes, 1, fntout); 181 charcount++; 182 bytecount += bytes; 183 } 184 FontHeader.size = nextoff; 185 fseek(fntout, 0L, 0); 186 fwrite(&FontHeader, sizeof FontHeader, 1, fntout); 187 fwrite(&disptable[0], sizeof disptable, 1, fntout); 188 189 /* Should fix the width tables here */ 190 fclose(fntout); 191 sprintf(msgbuf, "%s %d glyphs, %d bytes", fname, charcount, bytecount); 192 message(msgbuf); 193 changes = 0; 194 } 195 196 /* 197 * make a packed matrix of the bits for char c. 198 * return the matrix ptr in result and the size in bytes in nbytes. 199 */ 200 packmat(c, result, nbytes) 201 int c; 202 bitmat *result; 203 int *nbytes; 204 { 205 register int i, j; 206 bitmat wp; 207 int nb, nr, nc; 208 int rmin, cmin, rmax, cmax; 209 static char tmp[WINDSIZE]; 210 211 if (cht[c].wherewind == -1) { 212 /* It has never been read from file. Just copy from file. */ 213 nb = disptable[c].nbytes; 214 fseek(fontdes, (long) fbase+disptable[c].addr, 0); 215 fread(tmp, nb, 1, fontdes); 216 } else { 217 if (cht[c].wherewind == -2) 218 wp = cht[c].whereat; 219 else 220 wp = wind[cht[c].wherewind].val; 221 minmax(wp, GLROW, GLCOL, &rmin, &cmin, &rmax, &cmax); 222 nr = rmax-rmin+1; nc = cmax-cmin+1; 223 zermat(tmp, nr, nc); 224 for (i=rmin; i<=rmax; i++) 225 for (j=cmin; j<=cmax; j++) { 226 setmat(tmp, nr, nc, i-rmin, j-cmin, 227 mat(wp, GLROW, GLCOL, i, j)); 228 } 229 nb = ((nc + 7) >> 3) * nr; 230 disptable[c].up = cht[c].rcent - rmin; 231 disptable[c].down = rmax - cht[c].rcent + 1; 232 disptable[c].left = cht[c].ccent - cmin; 233 disptable[c].right = cmax - cht[c].ccent + 1; 234 if (trace) { 235 fprintf(trace, "rmax=%d, rcent=%d, rmin=%d, cmax=%d, ccent=%d, cmin=%d, ", rmax, cht[c].rcent, rmin, cmax, cht[c].ccent, cmin); 236 fprintf(trace, "up=%d, down=%d, left=%d, right=%d\n", disptable[c].up, disptable[c].down, disptable[c].left, disptable[c].right); 237 } 238 } 239 *result = tmp; 240 *nbytes = nb; 241 if (trace) 242 fprintf(trace, "nbytes = %d, ", nb); 243 return; 244 } 245 246 /* 247 * editfont: make the file fname be the current focus of attention, 248 * including reading it into the buffer. 249 */ 250 editfont(fname) 251 char *fname; 252 { 253 register char *cp; 254 255 clearfont(); 256 editing = 1; 257 truename(fname, fontfile); 258 fontdes = fopen(fontfile, "r"); 259 readfont(fontfile, 0, 255); 260 261 /* 262 * Figure out the point size, and make a guess as to the 263 * appropriate width of the heavy pen. 264 */ 265 for (cp=fontfile; *cp && *cp!='.'; cp++) 266 ; 267 if (*cp) { 268 pointsize = atoi(++cp); 269 setpen(pointsize>30?3 : pointsize>15?2 : pointsize>8?1 : 0); 270 } else { 271 pointsize = 0; 272 setpen(2); 273 } 274 } 275 276 /* 277 * readfont: read in a font, overlaying the current font. 278 * also used to edit a font by clearing first. 279 * 280 * Conflicts are handled interactively. 281 */ 282 readfont(fname, c1, c2) 283 char *fname; 284 int c1, c2; 285 { 286 register int i; 287 register char *cp; 288 struct dispatch d; 289 char choice, mode = 0; 290 FILE *hold_fontdes; 291 int horoff, vertoff; 292 long ftsave; 293 294 hold_fontdes = fontdes; 295 fontdes = fopen(fname, "r"); 296 if (fontdes == NULL) { 297 sprintf(msgbuf, "%s not found", fname); 298 fontdes = hold_fontdes; 299 error(msgbuf); 300 } 301 fread(&FontHeader, sizeof FontHeader, 1, fontdes); 302 fseek(fontdes, c1*sizeof d, 1); /* skip over unread chars */ 303 ftsave = ftell(fontdes); 304 for (i=c1; i<=c2; i++) { 305 fseek(fontdes, ftsave, 0); 306 fread(&d, sizeof d, 1, fontdes); 307 ftsave = ftell(fontdes); 308 /* Decide which of the two to take */ 309 if (d.nbytes == 0) 310 continue; /* We take the one in the buffer */ 311 if (disptable[i].nbytes > 0) { 312 /* Conflict */ 313 switch(mode) { 314 case 'f': 315 /* fall through */ 316 break; 317 case 'b': 318 continue; 319 default: 320 sprintf(msgbuf, "%s <file> or <buffer>", rdchar(i)); 321 message(msgbuf); 322 choice = inchar(); 323 switch(choice) { 324 case 'F': 325 mode = 'f'; 326 default: 327 case 'f': 328 break; 329 case 'B': 330 mode = 'b'; 331 case 'b': 332 continue; 333 } 334 } 335 } 336 disptable[i] = d; /* We take the one in the file */ 337 cht[i].nrow = d.up + d.down; 338 cht[i].ncol = d.left + d.right; 339 if (!editing && disptable[i].nbytes) { 340 horoff = (GLCOL-(disptable[i].left+disptable[i].right))/2; 341 vertoff = GLROW - BASELINE - disptable[i].up; 342 /* Check to see if the glyph is being nosed off the edge. */ 343 if (vertoff < 0) { 344 vertoff = 0; 345 } else if (vertoff + disptable[curchar].up + disptable[curchar].down >= GLROW) { 346 vertoff = GLROW - disptable[curchar].up - disptable[curchar].down; 347 } 348 if (cht[i].wherewind >= 0) { 349 /* The old glyph is in a window - destroy it */ 350 wind[cht[i].wherewind].used = -1; 351 } 352 cht[i].wherewind = -1; 353 cht[i].whereat = findbits(i, GLROW, GLCOL, horoff, vertoff, &cht[i].rcent, &cht[i].ccent); 354 cht[i].wherewind = -2; 355 if (trace) 356 fprintf(trace, "setting cht[%d].wherewind to -2 in readfont\n", i); 357 } else 358 cht[i].wherewind = -1; 359 } 360 fbase = sizeof FontHeader + sizeof disptable; /* ftell(fontdes) */ 361 362 sprintf(msgbuf, "\"%s\", raster data %d bytes, width %d, height %d, xtend %d", fname, FontHeader.size, FontHeader.maxx, FontHeader.maxy, FontHeader.xtend); 363 364 fontdes = hold_fontdes; 365 message(msgbuf); 366 } 367 368 /* 369 * Figure out the true name of the font file, given that 370 * the abbreviated name is fname. The result is placed 371 * in the provided buffer result. 372 */ 373 truename(fname, result) 374 char *fname; 375 char *result; 376 { 377 FILE *t; 378 379 strcpy(result, fname); 380 if ((t = fopen(result, "r")) == NULL) { 381 sprintf(result,"/usr/lib/vfont/%s",fname); 382 if ((t = fopen(result, "r")) == NULL) { 383 strcpy(result, fname); 384 sprintf(msgbuf, "Can't find %s\n",fname); 385 error(msgbuf); 386 } 387 } 388 fclose(t); 389 } 390 391 392 /* 393 * clearfont: delete all characters in the current font. 394 */ 395 clearfont() 396 { 397 register int i; 398 399 if (fontdes) 400 fclose(fontdes); 401 for (i=0; i<256; i++) { 402 cht[i].wherewind = -1; 403 disptable[i].addr = 0; 404 disptable[i].nbytes = 0; 405 disptable[i].up = 0; 406 disptable[i].down = 0; 407 disptable[i].left = 0; 408 disptable[i].right = 0; 409 disptable[i].width = 0; 410 } 411 } 412 413 /* 414 * fileiocmd: do a file I/O command. These all take optional file 415 * names, defaulting to the current file. 416 */ 417 fileiocmd(cmd) 418 char cmd; 419 { 420 char fname[100], truefname[100]; 421 422 readline("file: ", fname, sizeof fname); 423 if (fname[0] == 0 || fname[0] == ' ') 424 strcpy(fname, fontfile); 425 switch(cmd) { 426 case 'E': 427 confirm(); 428 editfont(fname); 429 break; 430 431 case 'N': 432 if (changes) 433 writeback(); 434 editfont(fname); 435 break; 436 437 case 'R': 438 editing = 0; 439 truename(fname, truefname); 440 readfont(truefname, 0, 255); 441 changes++; 442 break; 443 444 case 'W': 445 editing = 0; 446 writefont(fname); 447 break; 448 } 449 if (editing) 450 changes = 0; 451 } 452 453 /* 454 * readchars: read in a partial font (the P command). 455 */ 456 readchars() 457 { 458 int c1, c2; 459 char fnamebuf[100]; 460 char truebuf[100]; 461 char buf[5]; 462 463 message("Partial read <firstchar>"); 464 c1 = inchar(); 465 sprintf(msgbuf, "Partial read %s thru <lastchar>", rdchar(c1)); 466 message(msgbuf); 467 c2 = inchar(); 468 strcpy(buf, rdchar(c1)); 469 sprintf(msgbuf, "Partial read %s thru %s from file: ", buf, rdchar(c2)); 470 readline(msgbuf, fnamebuf, sizeof fnamebuf); 471 editing = 0; 472 if (fnamebuf[0] == 0 || fnamebuf[0] == ' ') 473 strcpy(fnamebuf, fontfile); 474 truename(fnamebuf, truebuf); 475 changes++; 476 readfont(truebuf, c1, c2); 477 } 478