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