1 /********************************************************************
2  *
3  * Harris - Emulator specific font stuff: bitmap files.
4  *
5  * @(#)font2.c	1.2 (CWI) 87/07/10
6  *
7  *******************************************************************/
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/file.h>
11 #include <errno.h>
12 #include "the.h"
13 #include "defs.h"		/* harris font definitions */
14 
15 
16 #define	BYTE	8
17 
18 
19 struct chardata {
20 	short charno;		/* character number	*/
21 	int XO, YO;		/* origin of char rel. to troff positions */
22 	int width, height;	/* scaled size in bits  */
23 	char *cbitmap;		/* bitmap of character  */
24 	short nbytes;		/* length of bitmap     */
25 	struct chardata *nextchar;
26 };
27 
28 struct fontadmin {
29 	short physical;
30 	short size;
31 	struct chardata *ch[128+1];	/* we start at index 1 */
32 	struct fontadmin *f;
33 };
34 
35 
36 
37 private struct	fontadmin *currentfnt;
38 private struct	fontadmin firstf;
39 
40 extern short	*pstab;
41 extern int	size;
42 extern char	buffer[];
43 extern int	hpos, vpos, vorigin;
44 extern int	virtRES;
45 extern int	debug, dbg;
46 extern int	slant;
47 extern double	slantoffset;
48 
49 extern int	errno;
50 
51 
52 char   *getfile();
53 
54 struct fontadmin *findfont();
55 struct fontadmin *falloc();
56 
57 extern char 	*malloc();
58 
59 
60 
61 
initfonts()62 initfonts()
63 {
64 	currentfnt = (struct fontadmin *) 0;	/* zero it out to start! */
65 	firstf.physical = 0;
66 	firstf.size = 0;
67 }
68 
69 
70 
71 /*
72  * putcode: get the necessary character data and write it.
73  *
74  * This function should be in put.c, but it knows too much
75  * about the internal structure of the fonts, so it
76  * is here.
77  */
78 
79 int	M[] = {	0x00000000, 0x01010101, 0x03030303, 0x07070707,
80 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
81 int	N[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
82 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
83 int	strip[] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff  };
84 
85 
putcode(code,f)86 putcode(code,f)
87 int code; int f;			/* character to print 			*/
88 {
89 	struct chardata *foundc;	/* pointer to found character 		*/
90 	char *scanp;			/* position to place character in buffer */
91 	char *sc;			/* real position to place char in buffer */
92 	char *cm;
93 	int nvpos;			/* new vertical position 		*/
94 	int nhpos;			/* new horizontal position 		*/
95 	int nhbyte;			/* byte index of horizontal position	*/
96 	int offbit, off8;		/* bit offset from byte index of hor. pos.*/
97 	double sloffset;		/* amount of offset due to slant	*/
98 	int bwidth, cnt;		/* width of bitmap in bytes 		*/
99 	int h;				/* height count		 		*/
100 	register unsigned int fontdata;
101 	unsigned char *to, *from;
102 	unsigned int n;
103 	int scan_inc;
104 
105 	if(currentfnt->physical != f || currentfnt->size != size)   {
106 		currentfnt = findfont(f);
107 	}
108 	foundc = currentfnt->ch[code];
109 	if( foundc == (struct chardata *)0 )
110 		return;
111 
112 	nvpos  = PHYS(vpos) - vorigin - foundc->height + foundc->YO;
113 	nhpos  = PHYS(hpos) + foundc->XO;
114 	bwidth = (foundc->width + 7)/BYTE;
115 	cm     = foundc->cbitmap;
116 
117 	if((nvpos >= NLINES) || (nvpos + foundc->height <= 0))
118 		return;
119 	if( nhpos < 0 )			/* ignore chars left of left margin */
120 		return;
121 
122 	/* the following is an ugly optimization: since slant will usually
123 	 * be zero, and we can save a whole lot of time if that is so,
124 	 * have a duplicate (faster) loop for that case (DD)
125 	 */
126 
127 	if( slant == 0 ) {
128 
129 		nhbyte = nhpos / BYTE;
130 		offbit = nhpos % BYTE;
131 		off8 = 8 - offbit;
132 		scanp = buf0p + nvpos * BYTES_PER_LINE + nhbyte;
133 		scan_inc = BYTES_PER_LINE - bwidth;
134 
135 		for(h = 0; h < foundc->height; h++) {
136 
137 			if (scanp + bwidth >= BUFBOTTOM)
138 				break;
139 
140 			cnt = bwidth;
141 			if (scanp >= BUFTOP) {
142 				do {
143 					fontdata = *(unsigned *)cm;
144 					cm += 4;
145 					if( cnt < 4 )
146 						fontdata &= strip[cnt];
147 					*(unsigned int *)scanp |= (fontdata >> offbit) & M[off8];
148 					scanp++;	/* _char_ increment */
149 					*(unsigned int *)scanp |= (fontdata << off8) & N[off8];
150 					scanp += 3;	/* to next _word_ */
151 					cnt -= 4;
152 				} while( cnt > 0 );
153 			}
154 			scanp += scan_inc + cnt;
155 			cm += cnt;
156 		}
157 	} else {	/* we have to add in a slant offset for each row */
158 
159 		scanp = buf0p + nvpos * BYTES_PER_LINE;
160 		sloffset = slantoffset * (foundc->height - foundc->YO);
161 
162 		for( h = 0;
163 			h < foundc->height;
164 			h++, scanp += BYTES_PER_LINE, sloffset -= slantoffset ){
165 
166 			nhbyte = (nhpos + (int)sloffset) / BYTE;
167 			offbit = (nhpos + (int)sloffset) % BYTE;
168 			off8 = 8 - offbit;
169 			sc = scanp + nhbyte;
170 
171 			if( sc <= BUFTOP )
172 				continue;
173 
174 			if( sc + bwidth >= BUFBOTTOM )
175 				break;
176 
177 			to = (unsigned char *)sc;
178 			from = (unsigned char *)&cm[ h*bwidth ];
179 			cnt = bwidth;
180 			while (cnt--) {
181 				n = *from++;
182 				*to++ |= n >> offbit;
183 				*to |= n << off8;
184 			}
185 		}
186 	}
187 }
188 
189 
190 
191 
192 
193 /*
194  *  findfont(f): Try to find font f (in current size).
195  *  If the font in this size is not already loaded, try to load it.
196  */
197 
198 
199 struct fontadmin *
findfont(f)200 findfont(f)
201 int f;
202 {
203 	struct fontadmin *p = &firstf;
204 	char file[BUFSIZ], *fbuf;
205 
206 
207 	DBGPRINT(0, ("Searching for %d size %d\n", f, size ));
208 	/*
209 	 * search list for desired font and size
210 	 */
211 
212 	while( p->physical != 0 )  {
213 
214 		if( p->physical == f && p->size == size )
215 			return(p);
216 #ifdef DEBUGABLE
217 		else if(p->physical > 10000 || p->physical < 10)
218 			error(FATAL, "odd font: %d!\n",p->physical);
219 #endif
220 		else
221 			p = p->f;
222 	}
223 
224 
225 	/*
226 	 * not in list, so make it
227 	 */
228 
229 	p->physical = f;
230 	p->size = size;
231 	p->f = falloc();
232 	p->f->physical = 0;
233 
234 
235 	sprintf(file,"%s/%d/%d", BITS, f, pstab[ size ] );
236 	fbuf = getfile(file);	/* getfile exits if unsuccessful */
237 
238 	DBGPRINT(0, ("Loading bitmaps for font %d size %d\n", f, size));
239 	loadbits( fbuf, p->ch );
240 
241 	return( p );
242 }
243 
244 
245 
246 /*
247  *  loadbits: reconstruct the linked char list from buf,
248  *  and put it into the given array.
249  */
250 
251 
loadbits(buf,cha)252 loadbits( buf, cha )
253 char *buf;
254 struct chardata *cha[];
255 {
256 	struct chardata *firstc, *ch;
257 	unsigned  offset = 0;
258 	int i;
259 
260 	ch = firstc = (struct chardata *)buf;
261 
262 	/* note we employ a trick here: we know that all
263 	 * the addresses (->nextchar and ->cbitmap) are
264 	 * garbage, yet still the list must have been
265 	 * terminated with ch->nextchar == 0, so we can
266 	 * still tell where it was supposed to end.
267 	 */
268 
269 	while( ch->nextchar != (struct chardata *)0 )
270 	{
271 		offset += sizeof( struct chardata );
272 		ch->cbitmap  = (char *)(buf + offset);
273 		offset += ch->nbytes;
274 		ch->nextchar = (struct chardata *)(buf + offset);
275 
276 		ch = ch->nextchar;
277 	}
278 	/* clean up last one */
279 	offset += sizeof( struct chardata );
280 	ch->cbitmap = (char *)(buf + offset);
281 
282 	/*
283 	 *  now go through and fill up the array
284 	 */
285 	ch = firstc;
286 	for( i=1; i<=128; i++ )
287 	{
288 		if( i == ch->charno )
289 		{
290 			cha[i] = ch;
291 			ch = ch->nextchar;
292 		}
293 		else
294 			cha[i] = 0;
295 	}
296 }
297 
298 
299 
300 struct fontadmin *
falloc()301 falloc()
302 {
303 	register char *p;
304 
305 	if(( p = malloc(sizeof(struct fontadmin))) == (char *) 0)
306 		error(FATAL, "Falloc");
307 	return((struct fontadmin *) p);
308 }
309 
310 
311 
312 
313 /*
314  *  get the contents of the file, and return a pointer to them.
315  *  All errors result in death.
316  *
317  */
318 
319 
320 char *
getfile(file)321 getfile(file)
322 char *file;
323 {
324 	struct	stat statbuf;
325 	char	*filebuf, *malloc();
326 	int	fdi;
327 
328 	if( stat(file, &statbuf) == -1 )
329 		error(FATAL, "Can't get file status: %s (error %d)", file, errno);
330 
331 	if((statbuf.st_mode & S_IFMT) != S_IFREG)
332 		error(FATAL, "File %s not a regular file", file);
333 
334 	if((fdi = open(file, O_RDONLY)) < 0 )
335 		error(FATAL, "Can not open %s (error %d)", file, errno );
336 
337 	if((filebuf = malloc( (unsigned int)statbuf.st_size )) == (char *)0)
338 		error(FATAL, "Not enough room for file %s!", file);
339 
340 	if(read(fdi, filebuf, (int)statbuf.st_size) != statbuf.st_size)
341 		error(FATAL, "Read error on %s", file);
342 
343 	(void) close( fdi );
344 	return( filebuf );
345 }
346