xref: /original-bsd/old/vpr/vtools/vfontinfo.c (revision 87ea4f99)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)vfontinfo.c	5.1 (Berkeley) 11/04/87";
9 #endif /* not lint */
10 
11 /* Font Information for VCat-style fonts
12  *      Andy Hertzfeld  4/79
13  *
14  *	Modified to print Ascii chars 1/80 by Mark Horton
15  *	Zoom option added 5/81 by Steve Stone with tables from Mark Horton.
16  *	Message option added 5/31 by Mark Horton
17  */
18 #include <stdio.h>
19 #include <ctype.h>
20 #include <vfont.h>
21 
22 struct header FontHeader;
23 struct dispatch disptable[256];
24 
25 char	IName[100];
26 char *	rdchar();
27 long	fbase;
28 
29 char	defascii[256];
30 char	*charswanted = defascii;
31 int	verbose;
32 char	charbits[4000];
33 int	H, W, WB, base;
34 int 	zoom = 1;
35 
36 char msgout[24][80];
37 int msgflag = 0;
38 int curline, curcol;	/* cursor, numbered from lower left corner */
39 int minline=24, maxline=0, maxcol=0;
40 
main(argc,argv)41 main(argc,argv)
42 int argc;
43 char **argv;
44 
45 {
46 	int FID,i,j;
47 
48 	while (argc > 1 && argv[1][0] == '-') {
49 		switch(argv[1][1]) {
50 		case 'v':
51 			verbose++;
52 			break;
53 		case 'z':
54 			zoom = argv[1][2] - '0';
55 			break;
56 		case 'm':
57 			msgflag = 1;
58 			zoom = 2;
59 			for (i=0; i<24; i++)
60 				for (j=0; j<80; j++)
61 					msgout[i][j] = ' ';
62 			curline = 5; curcol = 0;
63 			break;
64 		default:
65 			printf("Bad flag: %s\n", argv[1]);
66 		}
67 		argc--; argv++;
68 	}
69 	if (argc < 2) {
70 		fprintf(stderr,"Usage: %s filename", argv[0]);
71 		exit(2);
72 	}
73 
74 	for (i=0; i<128; i++)
75 		defascii[i] = i;
76 	if (argc >= 3)
77 		charswanted = argv[2];
78 
79 	sprintf(IName,"/usr/lib/vfont/%s",argv[1]);
80 	if ((FID = open(argv[1],0)) < 0)
81 		if ((FID = open(IName,0)) < 0) {
82 			printf("Can't find %s\n",argv[1]);
83 			exit(8);
84 		};
85 
86 	if (read(FID,&FontHeader,sizeof FontHeader) != sizeof FontHeader)
87 		error("Bad header in Font file.");
88 
89 	if (read(FID,&disptable[0],sizeof disptable) != sizeof disptable)
90 		error("Bad dispatch table in Font file");
91 
92 	fbase = sizeof FontHeader + sizeof disptable;
93 
94 	if (FontHeader.magic != 0436)
95 		printf("Magic number %o wrong\n", FontHeader.magic);
96 	if (!msgflag) {
97 		printf("Font %s, ",argv[1]);
98 		printf("raster size %d, ",FontHeader.size);
99 		printf("max width %d, max height %d, xtend %d\n",
100 			FontHeader.maxx, FontHeader.maxy,FontHeader.xtend);
101 		printf("\n");
102 		for (i = strlen(argv[1]) + 1; i > 0; --i)
103 			printf(" ");
104 		printf("ASCII     offset    size  left    right   up     down    width \n");
105 	}
106 
107 	for (i=0; i<256; i++) {
108 		j = charswanted[i];
109 		if (i>0 && j==0)
110 			break;
111 		if (disptable[j].nbytes != 0) {
112 			if (!msgflag)
113 				printf("%s  %3o %2s     %4d   %4d   %4d   %4d   %4d   %4d   %5d\n",
114 					argv[1],
115 					j, rdchar(j),
116 					disptable[j].addr,
117 					disptable[j].nbytes,
118 					disptable[j].left,
119 					disptable[j].right,
120 					disptable[j].up,
121 					disptable[j].down,
122 					disptable[j].width);
123 			if (verbose || msgflag) {
124 				int len = disptable[j].nbytes;
125 				int k, l, last;
126 
127 				lseek(FID, fbase+disptable[j].addr, 0);
128 				read(FID, charbits, len);
129 				H = (disptable[j].up) + (disptable[j].down);
130 				W = (disptable[j].left) + (disptable[j].right);
131 				base = disptable[j].up;
132 				WB = (W+7)/8;
133 				if (zoom < 0) {
134 					/*
135 					 * Old 1 for 1 code.  The aspect ratio
136 					 * is awful, so we don't use it.
137 					 */
138 					for (k=0; k<H; k++) {
139 						for (last=W-1; last >= 0; last--)
140 							if (fbit(k, last))
141 								break;
142 						for (l=0; l<=W-1; l++) {
143 							printf("%c", fbit(k,l)?'M':' ');
144 						}
145 						printf("\n");
146 					}
147 					printf("\n");
148 				} else {
149 					shozoom();
150 					if (msgflag) {
151 						k = disptable[j].width;
152 						if (zoom == 0) k *= 2;
153 						else if (zoom == 2) k /= 2;
154 						curcol += k;
155 					}
156 				}
157 			}
158 		}
159 	}
160 	if (msgflag) {
161 		for (i=maxline; i>=minline; i--) {
162 			for (j=0; j<maxcol; j++)
163 				putchar(msgout[i][j]);
164 			putchar('\n');
165 		}
166 	}
167 }
168 
error(string)169 error(string)
170 char *string;
171 
172 {
173 	printf("\nvfontinfo: %s\n",string);
174 	exit(8);
175 };
176 
rdchar(c)177 char *rdchar(c)
178 char c;
179 {
180 	static char ret[3];
181 	ret[0] = isprint(c) ? ' ' : '^';
182 	ret[1] = isprint(c) ?  c  : c^0100;
183 	ret[2] = 0;
184 	return (ret);
185 }
186 
187 int
fbit(row,col)188 fbit(row, col)
189 int row, col;
190 {
191 	int thisbyte, thisbit, ret;
192 
193 	if (row<0 || row>=H || col>=W) return(0);
194 	thisbyte = charbits[row*WB + (col>>3)] & 0xff;
195 	thisbit = 0x80 >> (col&7);
196 	ret = thisbyte & thisbit;
197 	return (ret != 0);
198 }
199 
200 
201 /*
202 The implementation would work like this:
203 	zoom level	method
204 	0		2 chars/pixel, 1 is "[]", 0 is "  ".
205 	1		2 pixels/char 2x1, using " " "," "'" "|"
206 	2		8 pixels/char 4x2, using 16x16 table
207 	3		32 pixels/char 8x4, mapped into (2)
208 	4 and up	similar, mapped into (2)
209 
210 The 16x16 table maps a 4x2 pattern into a printing ascii character which
211 most closely approximates that pattern, e.g. the pattern
212 	|'
213 	''
214 would be represented by the character "[".  I have such a table worked out.
215 
216 Grainer zoom levels would take the rule of reducing it into a smaller bitmap,
217 or-ing the bits together.  (e.g. level 3 would take a 2x2 chunk and map it
218 into a single pixel: 0 if all 4 are 0, 1 otherwise.)  These pixels would be
219 displayed as in 2.
220 */
221 
222 /*
223  * graphtab: a table for rudimentary graphics on ordinary terminals.
224  * For each 4x2 bit pattern of the form:
225  *	ae
226  *	bf
227  *	cg
228  *	dh
229  * form the 4 bit quantities abcd and efgh and get table entry
230  *	graphtab[abcd][efgh]
231  * to display in that character position.
232  *
233  * General philosophies: the dh bits are intended for descenders where
234  * possible.  Characters with radically different appearance on different
235  * terminals (e.g. _ and ^) are avoided.
236  *
237  * Version 1.0, March 1981, Mark Horton.
238  */
239 
240 char tab1[4] = {
241 	' ', ',', '\'', '|'
242 };
243 
244 char graphtab[16][16] = {
245 ' ', '.', '.', ',', '.', ';', ':', 'j', '\'', ':', ':', ';', '\'', ';', '!', '|',
246 '.', '.', ':', ',', ';', ';', ';', 'j', '/', ';', ';', ';', 'j', 'j', 'j', 'j',
247 '.', ',', '~', ',', 'r', '<', 'j', 'q', '/', ';', 'I', ';', '/', '|', 'I', '|',
248 ',', ',', 'r', 'x', '/', '/', '/', 'd', '/', '/', '/', 'd', '/', '/', '/', 'd',
249 '.', ':', '\\', ';', '-', '=', 'v', 'q', '\'', ':', '<', '|', '\'', ':', '+', '+',
250 ';', ';', '>', ';', '=', '=', 'g', 'g', '\'', ':', 'S', 'S', '/', '/', '/', '+',
251 ':', '\\', '\\', '\\', 'r', '<', 'w', 'q', '/', '<', '6', '4', '/', '/', 'd', '+',
252 'l', 'L', '+', 'b', 'y', '[', 'p', 'g', '/', '<', '/', '6', '/', '/', '/', '+',
253 '`', ':', ':', ';', '`', '\\', '\\', '\\', '"', ':', ':', ';', '`', '\\', 'Y', 'T',
254 ';', ';', ';', ';', '`', '2', '>', '\\', ':', '=', ';', ';', '?', '?', ']', ']',
255 ':', ';', ';', ';', '>', '2', '>', '\\', 'F', ';', 'O', ';', '7', '?', ']', '7',
256 ';', ';', ';', ';', '?', '2', '>', 'b', ';', ';', ';', ';', '?', '?', ']', '#',
257 '\'', '\\', '\\', '\\', '`', '\\', '\\', '\\', '\'', '\'', '<', '5', '"', '"', 'v', 'q',
258 ';', '\\', '\\', '\\', '`', '=', '\\', '\\', '\'', '\'', '5', '5', '"', '?', 'g', 'g',
259 'I', 'L', 'L', 'L', 'D', '\\', 'b', 'f', 'F', '[', '[', '[', 'P', '?', '#', 'M',
260 '|', '|', '|', '|', '|', '#', '+', '#', 'T', '[', 'F', 'F', 'P', '?', 'P', 'M'
261 };
262 
263 
shozoom()264 shozoom()
265 {
266 	register i;
267 
268 	if (zoom == 0)
269 		sho0();
270 	else if (zoom == 1)
271 		sho1();
272 	else if (zoom == 2)
273 		sho2();
274 }
275 
sho0()276 sho0()
277 {
278 	register k,l;
279 
280 	for (k=0; k<H; k++) {
281 		for (l=0; l<W; l++)
282 			printf("%s", fbit(k,l)?"[]": "  ");
283 		printf("\n");
284 	}
285 	printf("\n");
286 }
287 
sho1()288 sho1()
289 {
290 	register i,k,l;
291 
292 	k = 0;
293 	while (k < H) {
294 		for(l=0;l<W;l++) {
295 			i = fbit(k,l)*2 + fbit(k+1,l);
296 			printf("%c",tab1[i]);
297 			l++;
298 		}
299 		printf("\n");
300 		k += 2;
301 	}
302 	printf("\n");
303 }
304 
sho2()305 sho2()
306 {
307 	register i,j,k,l;
308 	int line = curline + (base+3)/4;
309 	int col;
310 
311 	k = base%4;
312 	if (k > 0) k -= 4;
313 	while (k < H) {
314 		l = 0;
315 		col = curcol;
316 		while (l<W) {
317 			i = fbit(k,l)*8 + fbit(k+1,l)*4 +
318 			    fbit(k+2,l)*2 + fbit(k+3,l);
319 			l++;
320 			j = fbit(k,l)*8 + fbit(k+1,l)*4 +
321 			    fbit(k+2,l)*2 + fbit(k+3,l);
322 
323 			if (msgflag) {
324 				if (graphtab[i][j] != ' ') {
325 					if (line > maxline) maxline = line;
326 					if (line < minline) minline = line;
327 					if (col > maxcol)   maxcol  = col;
328 				}
329 				msgout[line][col] = graphtab[i][j];
330 			} else
331 				printf("%c",graphtab[i][j]);
332 			l++;
333 			col++;
334 		}
335 		if (msgflag == 0)
336 			printf("\n");
337 		k += 4;
338 		line--;
339 	}
340 	if (msgflag == 0)
341 		printf("\n");
342 }
343