|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)io.c 4.2 (Berkeley) 8/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.