xref: /csrg-svn/old/vpr/vtools/fed/io.c (revision 14546)
1*14546Ssam #ifndef lint
2*14546Ssam static char sccsid[] = "@(#)io.c	4.2 (Berkeley) 08/11/83";
3*14546Ssam #endif
4*14546Ssam 
511509Sralph /*
611509Sralph  * io.c: font file I/O subroutines for fed.
711509Sralph  */
811509Sralph 
911509Sralph #include "fed.h"
1011509Sralph 
getglyph(c)1111509Sralph getglyph(c)
1211509Sralph char c;
1311509Sralph {
1411509Sralph 	register int i, j;
1511509Sralph 	int windno;
1611509Sralph 	int vertoff, horoff;
1711509Sralph 	char *tmp;
1811509Sralph 
1911509Sralph 	if (trace)
2011509Sralph 		fprintf(trace, "\n\ngetglyph(%s)\n", rdchar(c));
2111509Sralph 	if (disptable[c].nbytes == 0) {
2211509Sralph 		if (trace)
2311509Sralph 			fprintf(trace, "no such char: %s\n", rdchar(c));
2411509Sralph 		sprintf(msgbuf, "no such character: %s", rdchar(c));
2511509Sralph 		message(msgbuf);
2611509Sralph 		return;
2711509Sralph 	}
2811509Sralph 
2911509Sralph 	curchar = c;
3011509Sralph 	turnofcurs();
3111509Sralph 	if (cht[curchar].wherewind >= 0) {
3211509Sralph 		/* It's already in a window.  Don't have to do much. */
3311509Sralph 		if (trace)
3411509Sralph 			fprintf(trace, "already in %d\n", cht[curchar].wherewind);
3511509Sralph 		windno = cht[curchar].wherewind;
3611509Sralph 		/* Put a box around the current window */
3711509Sralph 		if (windno != curwind) {
3811509Sralph 			drawbox(base[curwind].r-1, base[curwind].c-1, 0, GLROW+2, GLCOL+2);
3911509Sralph 			drawbox(base[windno].r-1, base[windno].c-1, 1, GLROW+2, GLCOL+2);
4011509Sralph 		}
4111509Sralph 		curwind = windno;
4211509Sralph 		syncwind(windno);
4311509Sralph 		/* should center base */
4411509Sralph 	} else {
4511509Sralph 		/*
4611509Sralph 		 * Not on screen.  First find a suitable window,
4711509Sralph 		 * using round robin.
4811509Sralph 		 */
4911509Sralph 		windno = nextwind;
5011509Sralph 		if (trace)
5111509Sralph 			fprintf(trace, "chose window %d\n", windno);
5211509Sralph 		if (++nextwind >= NWIND)
5311509Sralph 			nextwind = 0;
5411509Sralph #ifdef TWOWIND
5511509Sralph 		/*
5611509Sralph 		 * This is for debugging what happens when we run out
5711509Sralph 		 * of windows.
5811509Sralph 		 */
5911509Sralph 		if (nextwind >= 2)
6011509Sralph 			nextwind = 0;
6111509Sralph #endif
6211509Sralph 
6311509Sralph 		/* Put a box around the current window */
6411509Sralph 		if (windno != curwind) {
6511509Sralph 			if (trace)
6611509Sralph 				fprintf(trace, "drawbox (%d %d)\n", base[windno].r-1, base[windno].c-1);
6711509Sralph 			drawbox(base[curwind].r-1, base[curwind].c-1, 0, GLROW+2, GLCOL+2);
6811509Sralph 			drawbox(base[windno].r-1, base[windno].c-1, 1, GLROW+2, GLCOL+2);
6911509Sralph 		}
7011509Sralph 
7111509Sralph 		/* Print the char at the lower left of the window */
7211509Sralph 		sprintf(msgbuf, "%s", rdchar(curchar));
7311509Sralph 		dispmsg(msgbuf, base[windno].c, base[windno].r-11, 2);
7411509Sralph 
7511509Sralph 		/* Now make room in the window */
7611509Sralph 		if (wind[windno].onscreen == NULL) {
7711509Sralph 			/* Brand new window, have to allocate space */
7811509Sralph 			wind[windno].onscreen = newmat(GLROW, GLCOL);
7911509Sralph 		} else {
8011509Sralph 			/* Save prev glyph for later */
8111509Sralph 			cht[wind[windno].used].whereat = wind[windno].val;
8211509Sralph 			cht[wind[windno].used].wherewind = -2;
8311509Sralph 			if (trace)
8411509Sralph 				fprintf(trace, "windno=%s, wind[windno].used=%d, cht[..].wherewind set to -2\n", rdchar(windno), wind[windno].used);
8511509Sralph 		}
8611509Sralph 		if (wind[windno].undval != NULL) {
8711509Sralph 			if (trace)
8811509Sralph 				fprintf(trace, "getglyph frees undo: %x\n", wind[windno].undval);
8911509Sralph 			free(wind[windno].undval);
9011509Sralph 		}
9111509Sralph 		wind[windno].undval = NULL;
9211509Sralph 		wind[windno].used = curchar;
9311509Sralph 
9411509Sralph 		/*
9511509Sralph 		 * Vertical & horizontal offsets.  Line up the baseline
9611509Sralph 		 * of the char at BASELINE from bottom, but center
9711509Sralph 		 * horizontally.
9811509Sralph 		 */
9911509Sralph 		vertoff = GLROW - BASELINE - disptable[curchar].up;
10011509Sralph 		/* Check to see if the glyph is being nosed off the edge. */
10111509Sralph 		if (vertoff < 0) {
10211509Sralph 			vertoff = 0;
10311509Sralph 		} else if (vertoff + disptable[curchar].up + disptable[curchar].down >= GLROW) {
10411509Sralph 			vertoff = GLROW - disptable[curchar].up - disptable[curchar].down;
10511509Sralph 		}
10611509Sralph 		horoff = (GLCOL-(disptable[curchar].left+disptable[curchar].right)) / 2;
10711509Sralph 		wind[windno].val = findbits(curchar, GLROW, GLCOL, horoff, vertoff, &curs_r, &curs_c);
10811509Sralph 		cht[curchar].rcent = curs_r;
10911509Sralph 		cht[curchar].ccent = curs_c;
11011509Sralph 		curwind = windno;
11111509Sralph 		cht[curchar].wherewind = windno;
11211509Sralph 		syncwind(windno);
11311509Sralph 	}
11411509Sralph }
11511509Sralph 
11611509Sralph /*
11711509Sralph  * writeback: write the font back to the file at the end of editing.
11811509Sralph  * Also have to write width table.
11911509Sralph  */
writeback()12011509Sralph writeback()
12111509Sralph {
12211509Sralph 	writefont(fontfile);
12311509Sralph }
12411509Sralph 
12511509Sralph /*
12611509Sralph  * writefont: write current font on file fname.
12711509Sralph  */
writefont(fname)12811509Sralph writefont(fname)
12911509Sralph char *fname;
13011509Sralph {
13111509Sralph 	register int i, j;
13211509Sralph 	register int c;
13311509Sralph 	FILE *fntout;
13411509Sralph 	int bytes;
13511509Sralph 	bitmat tmp;
13611509Sralph 	int nextoff = 0;
13711509Sralph 	int charcount, bytecount;
13811509Sralph 	extern char *sys_errlist[];
13911509Sralph 	extern int errno;
14011509Sralph 
14111509Sralph 	if (trace)
14211509Sralph 		fprintf(trace, "writefont(%s)\n", fname);
14311509Sralph 	/*
14411509Sralph 	 * The following unlink is important because we are about to
14511509Sralph 	 * do an fopen( , "w") on fname.  We still have fontdes open
14611509Sralph 	 * for reading.  If we don't do the unlink the fopen will truncate
14711509Sralph 	 * the file and subsequent reads will fail.  If we do the unlink
14811509Sralph 	 * the file won't go away until it is closed, so we can still
14911509Sralph 	 * read from the old version.
15011509Sralph 	 */
15111509Sralph 	if (strcmp(fname, fontfile)==0 && unlink(fname) < 0) {
15211509Sralph 		sprintf(msgbuf, "unlink %s: %s", fname, sys_errlist[errno]);
15311509Sralph 		error(msgbuf);
15411509Sralph 	}
15511509Sralph 
15611509Sralph 	fntout = fopen(fname, "w");
15711509Sralph 	if (fntout == NULL) {
15811509Sralph 		sprintf(msgbuf, "%s: %s", fname, sys_errlist[errno]);
15911509Sralph 		if (trace)
16011509Sralph 			fprintf(trace, "%s\n", msgbuf);
16111509Sralph 		error(msgbuf);
16211509Sralph 	}
16311509Sralph 	sprintf(msgbuf, "\"%s\"", fname);
16411509Sralph 	message(msgbuf);
16511509Sralph 	fflush(stdout);
16611509Sralph 
16711509Sralph 	fwrite(&FontHeader, sizeof FontHeader, 1, fntout);
16811509Sralph 	fwrite(&disptable[0], sizeof disptable, 1, fntout);
16911509Sralph 	charcount = 0; bytecount = fbase;
17011509Sralph 	for (c=0; c<256; c++)
17111509Sralph 		if (disptable[c].nbytes || cht[c].wherewind != -1) {
17211509Sralph 			if (trace)
17311509Sralph 				fprintf(trace, "char %s, nbytes %d, wherewind %d.. ", rdchar(c), disptable[c].nbytes, cht[c].wherewind);
17411509Sralph 			packmat(c, &tmp, &bytes);
17511509Sralph 			disptable[c].addr = nextoff;
17611509Sralph 			disptable[c].nbytes = bytes;
17711509Sralph 			if (trace)
17811509Sralph 				fprintf(trace, "offset %d size %d\n", nextoff, bytes);
17911509Sralph 			nextoff += bytes;
18011509Sralph 			fwrite(tmp, bytes, 1, fntout);
18111509Sralph 			charcount++;
18211509Sralph 			bytecount += bytes;
18311509Sralph 		}
18411509Sralph 	FontHeader.size = nextoff;
18511509Sralph 	fseek(fntout, 0L, 0);
18611509Sralph 	fwrite(&FontHeader, sizeof FontHeader, 1, fntout);
18711509Sralph 	fwrite(&disptable[0], sizeof disptable, 1, fntout);
18811509Sralph 
18911509Sralph 	/* Should fix the width tables here */
19011509Sralph 	fclose(fntout);
19111509Sralph 	sprintf(msgbuf, "%s %d glyphs, %d bytes", fname, charcount, bytecount);
19211509Sralph 	message(msgbuf);
19311509Sralph 	changes = 0;
19411509Sralph }
19511509Sralph 
19611509Sralph /*
19711509Sralph  * make a packed matrix of the bits for char c.
19811509Sralph  * return the matrix ptr in result and the size in bytes in nbytes.
19911509Sralph  */
packmat(c,result,nbytes)20011509Sralph packmat(c, result, nbytes)
20111509Sralph int c;
20211509Sralph bitmat *result;
20311509Sralph int *nbytes;
20411509Sralph {
20511509Sralph 	register int i, j;
20611509Sralph 	bitmat wp;
20711509Sralph 	int nb, nr, nc;
20811509Sralph 	int rmin, cmin, rmax, cmax;
20911509Sralph 	static char tmp[WINDSIZE];
21011509Sralph 
21111509Sralph 	if (cht[c].wherewind == -1) {
21211509Sralph 		/* It has never been read from file.  Just copy from file. */
21311509Sralph 		nb = disptable[c].nbytes;
21411509Sralph 		fseek(fontdes, (long) fbase+disptable[c].addr, 0);
21511509Sralph 		fread(tmp, nb, 1, fontdes);
21611509Sralph 	} else {
21711509Sralph 		if (cht[c].wherewind == -2)
21811509Sralph 			wp = cht[c].whereat;
21911509Sralph 		else
22011509Sralph 			wp = wind[cht[c].wherewind].val;
22111509Sralph 		minmax(wp, GLROW, GLCOL, &rmin, &cmin, &rmax, &cmax);
22211509Sralph 		nr = rmax-rmin+1; nc = cmax-cmin+1;
22311509Sralph 		zermat(tmp, nr, nc);
22411509Sralph 		for (i=rmin; i<=rmax; i++)
22511509Sralph 			for (j=cmin; j<=cmax; j++) {
22611509Sralph 				setmat(tmp, nr, nc, i-rmin, j-cmin,
22711509Sralph 					mat(wp, GLROW, GLCOL, i, j));
22811509Sralph 			}
22911509Sralph 		nb = ((nc + 7) >> 3) * nr;
23011509Sralph 		disptable[c].up = cht[c].rcent - rmin;
23111509Sralph 		disptable[c].down = rmax - cht[c].rcent + 1;
23211509Sralph 		disptable[c].left = cht[c].ccent - cmin;
23311509Sralph 		disptable[c].right = cmax - cht[c].ccent + 1;
23411509Sralph 		if (trace) {
23511509Sralph 			fprintf(trace, "rmax=%d, rcent=%d, rmin=%d, cmax=%d, ccent=%d, cmin=%d, ", rmax, cht[c].rcent, rmin, cmax, cht[c].ccent, cmin);
23611509Sralph 			fprintf(trace, "up=%d, down=%d, left=%d, right=%d\n", disptable[c].up, disptable[c].down, disptable[c].left, disptable[c].right);
23711509Sralph 		}
23811509Sralph 	}
23911509Sralph 	*result = tmp;
24011509Sralph 	*nbytes = nb;
24111509Sralph 	if (trace)
24211509Sralph 		fprintf(trace, "nbytes = %d, ", nb);
24311509Sralph 	return;
24411509Sralph }
24511509Sralph 
24611509Sralph /*
24711509Sralph  * editfont: make the file fname be the current focus of attention,
24811509Sralph  * including reading it into the buffer.
24911509Sralph  */
editfont(fname)25011509Sralph editfont(fname)
25111509Sralph char *fname;
25211509Sralph {
25311509Sralph 	register char *cp;
25411509Sralph 
25511509Sralph 	clearfont();
25611509Sralph 	editing = 1;
25711509Sralph 	truename(fname, fontfile);
25811509Sralph 	fontdes = fopen(fontfile, "r");
25911509Sralph 	readfont(fontfile, 0, 255);
26011509Sralph 
26111509Sralph 	/*
26211509Sralph 	 * Figure out the point size, and make a guess as to the
26311509Sralph 	 * appropriate width of the heavy pen.
26411509Sralph 	 */
26511509Sralph 	for (cp=fontfile; *cp && *cp!='.'; cp++)
26611509Sralph 		;
26711509Sralph 	if (*cp) {
26811509Sralph 		pointsize = atoi(++cp);
26911509Sralph 		setpen(pointsize>30?3 : pointsize>15?2 : pointsize>8?1 : 0);
27011509Sralph 	} else {
27111509Sralph 		pointsize = 0;
27211509Sralph 		setpen(2);
27311509Sralph 	}
27411509Sralph }
27511509Sralph 
27611509Sralph /*
27711509Sralph  * readfont: read in a font, overlaying the current font.
27811509Sralph  * also used to edit a font by clearing first.
27911509Sralph  *
28011509Sralph  * Conflicts are handled interactively.
28111509Sralph  */
readfont(fname,c1,c2)28211509Sralph readfont(fname, c1, c2)
28311509Sralph char *fname;
28411509Sralph int c1, c2;
28511509Sralph {
28611509Sralph 	register int i;
28711509Sralph 	register char *cp;
28811509Sralph 	struct dispatch d;
28911509Sralph 	char choice, mode = 0;
29011509Sralph 	FILE *hold_fontdes;
29111509Sralph 	int horoff, vertoff;
29211509Sralph 	long ftsave;
29311509Sralph 
29411509Sralph 	hold_fontdes = fontdes;
29511509Sralph 	fontdes = fopen(fname, "r");
29611509Sralph 	if (fontdes == NULL) {
29711509Sralph 		sprintf(msgbuf, "%s not found", fname);
29811509Sralph 		fontdes = hold_fontdes;
29911509Sralph 		error(msgbuf);
30011509Sralph 	}
30111509Sralph 	fread(&FontHeader, sizeof FontHeader, 1, fontdes);
30211509Sralph 	fseek(fontdes, c1*sizeof d, 1);	/* skip over unread chars */
30311509Sralph 	ftsave = ftell(fontdes);
30411509Sralph 	for (i=c1; i<=c2; i++) {
30511509Sralph 		fseek(fontdes, ftsave, 0);
30611509Sralph 		fread(&d, sizeof d, 1, fontdes);
30711509Sralph 		ftsave = ftell(fontdes);
30811509Sralph 		/* Decide which of the two to take */
30911509Sralph 		if (d.nbytes == 0)
31011509Sralph 			continue;	/* We take the one in the buffer */
31111509Sralph 		if (disptable[i].nbytes > 0) {
31211509Sralph 			/* Conflict */
31311509Sralph 			switch(mode) {
31411509Sralph 			case 'f':
31511509Sralph 				/* fall through */
31611509Sralph 				break;
31711509Sralph 			case 'b':
31811509Sralph 				continue;
31911509Sralph 			default:
32011509Sralph 				sprintf(msgbuf, "%s <file> or <buffer>", rdchar(i));
32111509Sralph 				message(msgbuf);
32211509Sralph 				choice = inchar();
32311509Sralph 				switch(choice) {
32411509Sralph 				case 'F':
32511509Sralph 					mode = 'f';
32611509Sralph 				default:
32711509Sralph 				case 'f':
32811509Sralph 					break;
32911509Sralph 				case 'B':
33011509Sralph 					mode = 'b';
33111509Sralph 				case 'b':
33211509Sralph 					continue;
33311509Sralph 				}
33411509Sralph 			}
33511509Sralph 		}
33611509Sralph 		disptable[i] = d;	/* We take the one in the file */
33711509Sralph 		cht[i].nrow = d.up + d.down;
33811509Sralph 		cht[i].ncol = d.left + d.right;
33911509Sralph 		if (!editing && disptable[i].nbytes) {
34011509Sralph 			horoff = (GLCOL-(disptable[i].left+disptable[i].right))/2;
34111509Sralph 			vertoff = GLROW - BASELINE - disptable[i].up;
34211509Sralph 			/* Check to see if the glyph is being nosed off the edge. */
34311509Sralph 			if (vertoff < 0) {
34411509Sralph 				vertoff = 0;
34511509Sralph 			} else if (vertoff + disptable[curchar].up + disptable[curchar].down >= GLROW) {
34611509Sralph 				vertoff = GLROW - disptable[curchar].up - disptable[curchar].down;
34711509Sralph 			}
34811509Sralph 			if (cht[i].wherewind >= 0) {
34911509Sralph 				/* The old glyph is in a window - destroy it */
35011509Sralph 				wind[cht[i].wherewind].used = -1;
35111509Sralph 			}
35211509Sralph 			cht[i].wherewind = -1;
35311509Sralph 			cht[i].whereat = findbits(i, GLROW, GLCOL, horoff, vertoff, &cht[i].rcent, &cht[i].ccent);
35411509Sralph 			cht[i].wherewind = -2;
35511509Sralph 			if (trace)
35611509Sralph 				fprintf(trace, "setting cht[%d].wherewind to -2 in readfont\n", i);
35711509Sralph 		} else
35811509Sralph 			cht[i].wherewind = -1;
35911509Sralph 	}
36011509Sralph 	fbase = sizeof FontHeader + sizeof disptable;	/* ftell(fontdes) */
36111509Sralph 
36211509Sralph 	sprintf(msgbuf, "\"%s\", raster data %d bytes, width %d, height %d, xtend %d", fname, FontHeader.size, FontHeader.maxx, FontHeader.maxy, FontHeader.xtend);
36311509Sralph 
36411509Sralph 	fontdes = hold_fontdes;
36511509Sralph 	message(msgbuf);
36611509Sralph }
36711509Sralph 
36811509Sralph /*
36911509Sralph  * Figure out the true name of the font file, given that
37011509Sralph  * the abbreviated name is fname.  The result is placed
37111509Sralph  * in the provided buffer result.
37211509Sralph  */
truename(fname,result)37311509Sralph truename(fname, result)
37411509Sralph char *fname;
37511509Sralph char *result;
37611509Sralph {
37711509Sralph 	FILE *t;
37811509Sralph 
37911509Sralph 	strcpy(result, fname);
38011509Sralph 	if ((t = fopen(result, "r")) == NULL) {
38111509Sralph 		sprintf(result,"/usr/lib/vfont/%s",fname);
38211509Sralph 		if ((t = fopen(result, "r")) == NULL) {
38311509Sralph 			strcpy(result, fname);
38411509Sralph 			sprintf(msgbuf, "Can't find %s\n",fname);
38511509Sralph 			error(msgbuf);
38611509Sralph 		}
38711509Sralph 	}
38811509Sralph 	fclose(t);
38911509Sralph }
39011509Sralph 
39111509Sralph 
39211509Sralph /*
39311509Sralph  * clearfont: delete all characters in the current font.
39411509Sralph  */
clearfont()39511509Sralph clearfont()
39611509Sralph {
39711509Sralph 	register int i;
39811509Sralph 
39911509Sralph 	if (fontdes)
40011509Sralph 		fclose(fontdes);
40111509Sralph 	for (i=0; i<256; i++) {
40211509Sralph 		cht[i].wherewind = -1;
40311509Sralph 		disptable[i].addr = 0;
40411509Sralph 		disptable[i].nbytes = 0;
40511509Sralph 		disptable[i].up = 0;
40611509Sralph 		disptable[i].down = 0;
40711509Sralph 		disptable[i].left = 0;
40811509Sralph 		disptable[i].right = 0;
40911509Sralph 		disptable[i].width = 0;
41011509Sralph 	}
41111509Sralph }
41211509Sralph 
41311509Sralph /*
41411509Sralph  * fileiocmd: do a file I/O command.  These all take optional file
41511509Sralph  * names, defaulting to the current file.
41611509Sralph  */
fileiocmd(cmd)41711509Sralph fileiocmd(cmd)
41811509Sralph char cmd;
41911509Sralph {
42011509Sralph 	char fname[100], truefname[100];
42111509Sralph 
42211509Sralph 	readline("file: ", fname, sizeof fname);
42311509Sralph 	if (fname[0] == 0 || fname[0] == ' ')
42411509Sralph 		strcpy(fname, fontfile);
42511509Sralph 	switch(cmd) {
42611509Sralph 	case 'E':
42711509Sralph 		confirm();
42811509Sralph 		editfont(fname);
42911509Sralph 		break;
43011509Sralph 
43111509Sralph 	case 'N':
43211509Sralph 		if (changes)
43311509Sralph 			writeback();
43411509Sralph 		editfont(fname);
43511509Sralph 		break;
43611509Sralph 
43711509Sralph 	case 'R':
43811509Sralph 		editing = 0;
43911509Sralph 		truename(fname, truefname);
44011509Sralph 		readfont(truefname, 0, 255);
44111509Sralph 		changes++;
44211509Sralph 		break;
44311509Sralph 
44411509Sralph 	case 'W':
44511509Sralph 		editing = 0;
44611509Sralph 		writefont(fname);
44711509Sralph 		break;
44811509Sralph 	}
44911509Sralph 	if (editing)
45011509Sralph 		changes = 0;
45111509Sralph }
45211509Sralph 
45311509Sralph /*
45411509Sralph  * readchars: read in a partial font (the P command).
45511509Sralph  */
readchars()45611509Sralph readchars()
45711509Sralph {
45811509Sralph 	int c1, c2;
45911509Sralph 	char fnamebuf[100];
46011509Sralph 	char truebuf[100];
46111509Sralph 	char buf[5];
46211509Sralph 
46311509Sralph 	message("Partial read <firstchar>");
46411509Sralph 	c1 = inchar();
46511509Sralph 	sprintf(msgbuf, "Partial read %s thru <lastchar>", rdchar(c1));
46611509Sralph 	message(msgbuf);
46711509Sralph 	c2 = inchar();
46811509Sralph 	strcpy(buf, rdchar(c1));
46911509Sralph 	sprintf(msgbuf, "Partial read %s thru %s from file: ", buf, rdchar(c2));
47011509Sralph 	readline(msgbuf, fnamebuf, sizeof fnamebuf);
47111509Sralph 	editing = 0;
47211509Sralph 	if (fnamebuf[0] == 0 || fnamebuf[0] == ' ')
47311509Sralph 		strcpy(fnamebuf, fontfile);
47411509Sralph 	truename(fnamebuf, truebuf);
47511509Sralph 	changes++;
47611509Sralph 	readfont(truebuf, c1, c2);
47711509Sralph }
478