Commit | Line | Data |
---|---|---|
38babee7 | 1 | /* dip.c 1.9 (Berkeley) 84/04/30 |
ef0f9059 DS |
2 | * dip |
3 | * driver for impress/imagen canon laser printer | |
4 | */ | |
5 | ||
6 | /* | |
7 | output language from troff: | |
8 | all numbers are character strings | |
9 | ||
10 | sn size in points | |
11 | fn font as number from 1-n | |
9a0557cf | 12 | in stipple `font' as number from 1-n |
ef0f9059 DS |
13 | cx ascii character x |
14 | Cxyz funny char xyz. terminated by white space | |
15 | Hn go to absolute horizontal position n | |
16 | Vn go to absolute vertical position n (down is positive) | |
17 | hn go n units horizontally (relative) | |
18 | vn ditto vertically | |
19 | nnc move right nn, then print c (exactly 2 digits!) | |
20 | (this wart is an optimization that shrinks output file size | |
21 | about 35% and run-time about 15% while preserving ascii-ness) | |
22 | Dt ...\n draw operation 't': | |
9a0557cf DS |
23 | Dt d line thickness set to d |
24 | Ds d line style (coordinate bit map) set to d | |
ef0f9059 DS |
25 | Dl x y line from here by x,y |
26 | Dc d circle of diameter d with left side here | |
27 | De x y ellipse of axes x,y with left side here | |
28 | Da x y r arc counter-clockwise by x,y of radius r | |
29 | D~ x y x y ... wiggly line by x,y then x,y ... | |
9a0557cf DS |
30 | Dg x y x y ... gremlin spline by x,y then x,y ... |
31 | Dp s x y ... polygon filled with s by x,y then ... | |
ef0f9059 DS |
32 | nb a end of line (information only -- no action needed) |
33 | b = space before line, a = after | |
6dded2dd | 34 | pn new page begins -- set v to 0 |
ef0f9059 DS |
35 | #...\n comment |
36 | x ...\n device control functions: | |
37 | x i init | |
38 | x T s name of device is s | |
39 | x r n h v resolution is n/inch | |
40 | h = min horizontal motion, v = min vert | |
41 | x p pause (can restart) | |
42 | x s stop -- done for ever | |
43 | x t generate trailer | |
44 | x f n s font position n contains font s | |
45 | x H n set character height to n | |
46 | x S n set slant to N | |
47 | ||
48 | Subcommands like "i" are often spelled out like "init". | |
49 | */ | |
50 | ||
51 | #include <stdio.h> | |
52 | #include <signal.h> | |
53 | #include <math.h> | |
54 | #include <ctype.h> | |
ef0f9059 DS |
55 | #include "dev.h" |
56 | #include "canon.h" | |
6dded2dd | 57 | #include "rst.h" |
ef0f9059 | 58 | |
ef0f9059 | 59 | |
6dded2dd DS |
60 | /* #define DEBUGABLE /* whether or not it'll accept the -d option */ |
61 | #define abs(n) ((n) >= 0 ? (n) : -(n)) | |
62 | #define hmot(n) hpos += n | |
63 | #define hgoto(n) hpos = n | |
64 | #define vmot(n) vpos += n | |
65 | #define vgoto(n) vpos = n | |
ef0f9059 | 66 | |
6dded2dd DS |
67 | #define FATAL 1 |
68 | #define BMASK 0377 | |
9a0557cf | 69 | #define NFONT 35 /* maximum forever */ |
6dded2dd | 70 | |
313aa806 | 71 | #ifndef FONTDIR |
6dded2dd | 72 | #define FONTDIR "/usr/lib/font"; |
313aa806 | 73 | #endif |
6dded2dd DS |
74 | #define BITDIR "/usr/local/lib/ifontt"; |
75 | ||
76 | /* BOTTOMTHRESH and DELTATHRESH are used to */ | |
77 | /* search through the glyphs downloaded to */ | |
78 | /* determine which ones to keep and which to */ | |
79 | /* dump. They're tested against BOTTOMTHRESH */ | |
80 | /* first, then if THAT doesn't release enough */ | |
81 | /* space, DELTATHRESH is added until it is. */ | |
82 | #define BOTTOMTHRESH 16 | |
83 | #define DELTATHRESH 16 | |
84 | #define MEMSIZE 70000 /* amount of memory inside imagen */ | |
85 | #define BUFFER 20000 /* imagen memory set aside for page buffer */ | |
86 | #define CHARRAY 128 /* size of character use count array */ | |
87 | ||
88 | int MAXX = (RES*8+RES/3); /* size of the page... (not 8-1/2" x 11", */ | |
89 | int MAXY = (RES*10+RES/2+RES/4); /* but 8-1/3" x 10-3/4") */ | |
90 | ||
91 | int output = 0; /* do we do output at all? */ | |
92 | int pageno = -1; /* output page number */ | |
93 | int nolist = 0; /* output page list if > 0 */ | |
94 | int olist[20]; /* pairs of page numbers */ | |
ef0f9059 DS |
95 | |
96 | struct dev dev; | |
97 | struct font *fontbase[NFONT+1]; | |
6dded2dd DS |
98 | short * pstab; |
99 | int nsizes = 1; | |
ef0f9059 | 100 | int nfonts; |
9a0557cf | 101 | int nstips; |
ef0f9059 | 102 | int nchtab; |
6dded2dd DS |
103 | char * chname; |
104 | short * chtab; | |
105 | unsigned char * fitab[NFONT+1]; /* legal characters for each font */ | |
106 | unsigned char * widtab[NFONT+1]; /* width table for each font */ | |
107 | unsigned char * codetab[NFONT+1]; /* device code translation */ | |
108 | char * fontname[NFONT+1]; /* what font is on what position? */ | |
109 | ||
110 | #ifdef DEBUGABLE | |
ef0f9059 | 111 | int dbg = 0; |
6dded2dd DS |
112 | #endif |
113 | ||
114 | FILE * tf = stdout; /* output file pointer */ | |
115 | char * fontdir = FONTDIR; | |
116 | char * bitdir = BITDIR; | |
117 | FILE * fp = stdin; /* input file pointer */ | |
118 | ||
119 | int totglyph= 0; /* total space used by glyphs sent down */ | |
120 | int maxglyph= MEMSIZE - BUFFER; /* maximum space for glyphs */ | |
121 | ||
122 | int size = 1; | |
123 | int font = 1; | |
9a0557cf | 124 | int stip = 1; |
6dded2dd DS |
125 | int family; |
126 | int hpos; /* current horizontal position (left = 0) */ | |
127 | int vpos; /* current vertical position (down positive) */ | |
128 | int lastw = 0; /* width of last input character */ | |
129 | extern int linethickness; /* line drawing pars: Thickness (pixels) */ | |
130 | extern int style; /* and type (SOLID, DOTTED, . . . ) */ | |
131 | ||
132 | typedef struct { | |
133 | int font; | |
134 | int size; | |
9a0557cf DS |
135 | short first; |
136 | short last; | |
6dded2dd DS |
137 | unsigned char chused[CHARRAY]; /* test array - character downloaded? */ |
138 | glyph_dir *glyph; /* array of character descriptions */ | |
139 | unsigned char *cdp; /* char data pointer */ | |
140 | } fontset; | |
141 | ||
142 | fontset *fs; /* A global pointer to the current family */ | |
143 | fontset fontdata[NFONT+1]; /* table of family data descripters */ | |
144 | ||
145 | int lastsize = -1; | |
146 | int lastfont = -1; | |
147 | int lastx = -1; | |
148 | int lasty = -1; | |
149 | int lastfam = -1; | |
9a0557cf DS |
150 | int laststip = -1; |
151 | int laststipmem = -1; | |
6dded2dd DS |
152 | |
153 | ||
ef0f9059 DS |
154 | |
155 | main(argc, argv) | |
156 | char *argv[]; | |
157 | { | |
6dded2dd | 158 | int i; |
ef0f9059 | 159 | char *mktemp(); |
6dded2dd | 160 | char *operand(); |
ef0f9059 | 161 | |
6dded2dd DS |
162 | while (--argc > 0 && **++argv == '-') { |
163 | switch ((*argv)[1]) { | |
2cf235a3 DS |
164 | case 'X': |
165 | MAXX = atoi(operand(&argc, &argv)); | |
166 | break; | |
167 | case 'Y': | |
168 | MAXY = atoi(operand(&argc, &argv)); | |
169 | break; | |
6dded2dd DS |
170 | case 'F': |
171 | fontdir = operand(&argc, &argv); | |
ef0f9059 DS |
172 | break; |
173 | case 'f': | |
6dded2dd | 174 | bitdir = operand(&argc, &argv); |
ef0f9059 DS |
175 | break; |
176 | case 'o': | |
6dded2dd | 177 | outlist(operand(&argc, &argv)); |
ef0f9059 DS |
178 | break; |
179 | case 'b': | |
6dded2dd DS |
180 | if ((i = atoi(operand(&argc, &argv))) < 1000) i = 1000; |
181 | else if (i > MEMSIZE - 1000) i = MEMSIZE - 1000; | |
182 | maxglyph = MEMSIZE - i; | |
ef0f9059 | 183 | break; |
6dded2dd | 184 | #ifdef DEBUGABLE |
ef0f9059 | 185 | case 'd': |
6dded2dd DS |
186 | dbg = atoi(operand(&argc, &argv)); |
187 | if (dbg == 0) error (FATAL, "no debug value"); | |
ef0f9059 | 188 | break; |
6dded2dd | 189 | #endif |
ef0f9059 | 190 | } |
ef0f9059 DS |
191 | } |
192 | ||
6dded2dd | 193 | if (argc < 1) |
ef0f9059 DS |
194 | conv(stdin); |
195 | else | |
6dded2dd DS |
196 | while (argc-- > 0) { |
197 | if (strcmp(*argv, "-") == 0) | |
ef0f9059 DS |
198 | fp = stdin; |
199 | else if ((fp = fopen(*argv, "r")) == NULL) | |
200 | error(FATAL, "can't open %s", *argv); | |
201 | conv(fp); | |
202 | fclose(fp); | |
6dded2dd | 203 | argv++; |
ef0f9059 | 204 | } |
6dded2dd | 205 | |
ef0f9059 | 206 | t_wrapup(); |
6dded2dd DS |
207 | exit(0); |
208 | } | |
209 | ||
210 | ||
211 | /*----------------------------------------------------------------------------* | |
212 | | Routine: char * operand (& argc, & argv) | |
213 | | | |
214 | | Results: returns address of the operand given with a command-line | |
215 | | option. It uses either "-Xoperand" or "-X operand", whichever | |
216 | | is present. The program is terminated if no option is present. | |
217 | | | |
218 | | Side Efct: argc and argv are updated as necessary. | |
219 | *----------------------------------------------------------------------------*/ | |
220 | ||
221 | char *operand(argcp, argvp) | |
222 | int * argcp; | |
223 | char ***argvp; | |
224 | { | |
225 | if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */ | |
226 | if ((--*argcp) <= 0) { /* no operand */ | |
2cf235a3 | 227 | error (FATAL, "command-line option operand missing."); |
ef0f9059 | 228 | } |
6dded2dd | 229 | return(*(++(*argvp))); /* operand next word */ |
ef0f9059 DS |
230 | } |
231 | ||
6dded2dd | 232 | |
ef0f9059 | 233 | outlist(s) /* process list of page numbers to be printed */ |
0b2b2a0e | 234 | register char *s; |
ef0f9059 | 235 | { |
0b2b2a0e | 236 | register int n1, n2; |
ef0f9059 DS |
237 | |
238 | nolist = 0; | |
239 | while (*s) { | |
240 | n1 = 0; | |
241 | if (isdigit(*s)) | |
242 | do | |
243 | n1 = 10 * n1 + *s++ - '0'; | |
244 | while (isdigit(*s)); | |
245 | else | |
246 | n1 = -9999; | |
247 | n2 = n1; | |
248 | if (*s == '-') { | |
249 | s++; | |
250 | n2 = 0; | |
251 | if (isdigit(*s)) | |
252 | do | |
253 | n2 = 10 * n2 + *s++ - '0'; | |
254 | while (isdigit(*s)); | |
255 | else | |
256 | n2 = 9999; | |
257 | } | |
258 | olist[nolist++] = n1; | |
259 | olist[nolist++] = n2; | |
260 | if (*s != '\0') | |
261 | s++; | |
262 | } | |
263 | olist[nolist] = 0; | |
6dded2dd | 264 | #ifdef DEBUGABLE |
ef0f9059 DS |
265 | if (dbg) |
266 | for (i=0; i<nolist; i += 2) | |
267 | printf("%3d %3d\n", olist[i], olist[i+1]); | |
6dded2dd | 268 | #endif |
ef0f9059 DS |
269 | } |
270 | ||
6dded2dd | 271 | |
ef0f9059 DS |
272 | in_olist(n) /* is n in olist? */ |
273 | int n; | |
274 | { | |
275 | int i; | |
276 | ||
277 | if (nolist == 0) | |
278 | return(1); /* everything is included */ | |
279 | for (i = 0; i < nolist; i += 2) | |
280 | if (n >= olist[i] && n <= olist[i+1]) | |
281 | return(1); | |
282 | return(0); | |
283 | } | |
284 | ||
6dded2dd | 285 | |
ef0f9059 DS |
286 | conv(fp) |
287 | register FILE *fp; | |
288 | { | |
6dded2dd DS |
289 | register int c; |
290 | register int k; | |
291 | int m, n, n1, m1; | |
ef0f9059 DS |
292 | char str[100], buf[300]; |
293 | ||
294 | while ((c = getc(fp)) != EOF) { | |
295 | switch (c) { | |
296 | case '\n': /* when input is text */ | |
297 | case ' ': | |
298 | case 0: /* occasional noise creeps in */ | |
299 | break; | |
300 | case '0': case '1': case '2': case '3': case '4': | |
301 | case '5': case '6': case '7': case '8': case '9': | |
302 | /* two motion digits plus a character */ | |
303 | hmot((c-'0')*10 + getc(fp)-'0'); | |
304 | put1(getc(fp)); | |
305 | break; | |
306 | case 'c': /* single ascii character */ | |
307 | put1(getc(fp)); | |
308 | break; | |
309 | case 'C': | |
310 | fscanf(fp, "%s", str); | |
311 | put1s(str); | |
312 | break; | |
313 | case 'D': /* draw function */ | |
0a9d8bca DS |
314 | if (fgets(buf, sizeof(buf), fp) == NULL) |
315 | error(FATAL, "unexpected end of input"); | |
ef0f9059 DS |
316 | switch (buf[0]) { |
317 | case 'l': /* draw a line */ | |
318 | sscanf(buf+1, "%d %d", &n, &m); | |
6dded2dd | 319 | drawline(n, m, "."); |
ef0f9059 DS |
320 | break; |
321 | case 'c': /* circle */ | |
322 | sscanf(buf+1, "%d", &n); | |
323 | drawcirc(n); | |
324 | break; | |
325 | case 'e': /* ellipse */ | |
326 | sscanf(buf+1, "%d %d", &m, &n); | |
327 | drawellip(m, n); | |
328 | break; | |
329 | case 'a': /* arc */ | |
330 | sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); | |
331 | drawarc(n, m, n1, m1); | |
332 | break; | |
9a0557cf DS |
333 | case 'p': /* polygon */ |
334 | sscanf(buf+1, "%d", &m);/* get stipple */ | |
335 | n = 1; /* number first */ | |
336 | while (buf[++n] == ' '); | |
337 | while (isdigit(buf[n])) n++; | |
338 | setfill(m); /* set up stipple */ | |
339 | drawwig(buf+n, fp, -1); /* draw polygon */ | |
340 | break; | |
ef0f9059 | 341 | case 'g': /* gremlin curve */ |
0b2b2a0e DS |
342 | drawwig(buf+1, fp, 0); |
343 | break; | |
ef0f9059 | 344 | case '~': /* wiggly line */ |
0b2b2a0e | 345 | drawwig(buf+1, fp, 1); |
6dded2dd | 346 | break; |
0b2b2a0e | 347 | case 't': /* line-thickness */ |
6dded2dd DS |
348 | sscanf(buf+1, "%d", &n); |
349 | drawthick(n); | |
350 | break; | |
0b2b2a0e | 351 | case 's': /* line-style */ |
6dded2dd DS |
352 | sscanf(buf+1, "%d", &n); |
353 | drawstyle(n); | |
ef0f9059 DS |
354 | break; |
355 | default: | |
6dded2dd | 356 | error(FATAL, "unknown drawing function %s",buf); |
ef0f9059 DS |
357 | break; |
358 | } | |
359 | break; | |
360 | case 's': | |
361 | fscanf(fp, "%d", &n); /* ignore fractional sizes */ | |
362 | setsize(t_size(n)); | |
363 | break; | |
364 | case 'f': | |
365 | fscanf(fp, "%s", str); | |
366 | setfont(t_font(str)); | |
367 | break; | |
9a0557cf DS |
368 | case 'i': |
369 | fscanf(fp, "%d", &n); | |
370 | setstip(n); | |
371 | break; | |
ef0f9059 DS |
372 | case 'H': /* absolute horizontal motion */ |
373 | /* fscanf(fp, "%d", &n); */ | |
374 | while ((c = getc(fp)) == ' ') | |
375 | ; | |
376 | k = 0; | |
377 | do { | |
378 | k = 10 * k + c - '0'; | |
379 | } while (isdigit(c = getc(fp))); | |
380 | ungetc(c, fp); | |
381 | hgoto(k); | |
382 | break; | |
383 | case 'h': /* relative horizontal motion */ | |
384 | /* fscanf(fp, "%d", &n); */ | |
385 | while ((c = getc(fp)) == ' ') | |
386 | ; | |
387 | k = 0; | |
388 | do { | |
389 | k = 10 * k + c - '0'; | |
390 | } while (isdigit(c = getc(fp))); | |
391 | ungetc(c, fp); | |
392 | hmot(k); | |
393 | break; | |
394 | case 'w': /* word space */ | |
395 | break; | |
396 | case 'V': | |
397 | fscanf(fp, "%d", &n); | |
398 | vgoto(n); | |
399 | break; | |
400 | case 'v': | |
401 | fscanf(fp, "%d", &n); | |
402 | vmot(n); | |
403 | break; | |
404 | case 'p': /* new page */ | |
405 | fscanf(fp, "%d", &n); | |
406 | t_page(n); | |
407 | break; | |
408 | case 'n': /* end of line */ | |
6dded2dd | 409 | hpos = 0; |
0a9d8bca | 410 | |
ef0f9059 | 411 | case '#': /* comment */ |
0a9d8bca DS |
412 | do |
413 | c = getc(fp); | |
414 | while (c != '\n' && c != EOF); | |
ef0f9059 DS |
415 | break; |
416 | case 'x': /* device control */ | |
0b2b2a0e | 417 | if (devcntrl(fp)) return; |
ef0f9059 DS |
418 | break; |
419 | default: | |
2cf235a3 | 420 | error(FATAL, "unknown input character %o %c", c, c); |
ef0f9059 DS |
421 | } |
422 | } | |
423 | } | |
424 | ||
6dded2dd | 425 | |
0b2b2a0e DS |
426 | int devcntrl(fp) /* interpret device control functions */ |
427 | FILE *fp; /* returns -1 upon "stop" command */ | |
ef0f9059 DS |
428 | { |
429 | char str[20], str1[50], buf[50]; | |
430 | int c, n; | |
431 | ||
432 | fscanf(fp, "%s", str); | |
433 | switch (str[0]) { /* crude for now */ | |
434 | case 'i': /* initialize */ | |
435 | fileinit(); | |
9a0557cf | 436 | t_init(); |
ef0f9059 DS |
437 | break; |
438 | case 'T': /* device name */ | |
ef0f9059 | 439 | case 't': /* trailer */ |
ef0f9059 | 440 | case 'p': /* pause -- can restart */ |
ef0f9059 | 441 | break; |
0b2b2a0e DS |
442 | case 's': /* stop */ |
443 | return -1; | |
ef0f9059 | 444 | case 'r': /* resolution assumed when prepared */ |
6dded2dd DS |
445 | fscanf(fp, "%d", &n); |
446 | if (n!=RES) error(FATAL,"Input computed with wrong resolution"); | |
ef0f9059 DS |
447 | break; |
448 | case 'f': /* font used */ | |
449 | fscanf(fp, "%d %s", &n, str); | |
450 | fgets(buf, sizeof buf, fp); /* in case there's a filename */ | |
451 | ungetc('\n', fp); /* fgets goes too far */ | |
452 | str1[0] = 0; /* in case there's nothing to come in */ | |
453 | sscanf(buf, "%s", str1); | |
454 | loadfont(n, str, str1); | |
455 | break; | |
456 | case 'H': /* char height */ | |
457 | fscanf(fp, "%d", &n); | |
458 | t_charht(n); | |
459 | break; | |
460 | case 'S': /* slant */ | |
461 | fscanf(fp, "%d", &n); | |
462 | t_slant(n); | |
463 | break; | |
464 | } | |
465 | while ((c = getc(fp)) != '\n') /* skip rest of input line */ | |
466 | if (c == EOF) | |
0b2b2a0e DS |
467 | return -1; |
468 | return 0; | |
ef0f9059 DS |
469 | } |
470 | ||
6dded2dd | 471 | |
ef0f9059 DS |
472 | fileinit() /* read in font and code files, etc. */ |
473 | { | |
6dded2dd DS |
474 | register int i; |
475 | register int fin; | |
476 | register int nw; | |
477 | register unsigned char *filebase; | |
478 | register unsigned char *p; | |
479 | unsigned char *malloc(); | |
480 | char temp[100]; | |
ef0f9059 | 481 | |
6dded2dd DS |
482 | /* open table for device, |
483 | * read in resolution, size info, font info, etc. | |
484 | * and set params | |
485 | */ | |
ef0f9059 | 486 | |
6dded2dd | 487 | sprintf(temp, "%s/devip/DESC.out", fontdir); |
ef0f9059 DS |
488 | if ((fin = open(temp, 0)) < 0) |
489 | error(FATAL, "can't open tables for %s", temp); | |
490 | read(fin, &dev, sizeof(struct dev)); | |
491 | nfonts = dev.nfonts; | |
9a0557cf | 492 | nstips = dev.nstips; |
ef0f9059 DS |
493 | nsizes = dev.nsizes; |
494 | nchtab = dev.nchtab; | |
495 | filebase = malloc(dev.filesize); /* enough room for whole file */ | |
496 | read(fin, filebase, dev.filesize); /* all at once */ | |
497 | pstab = (short *) filebase; | |
498 | chtab = pstab + nsizes + 1; | |
499 | chname = (char *) (chtab + dev.nchtab); | |
6dded2dd DS |
500 | p = (unsigned char *) chname + dev.lchname; |
501 | for (i = 1; i <= nfonts; i++) { | |
502 | fontbase[i] = (struct font *) p; | |
503 | nw = *p & BMASK; /* 1st thing is width count */ | |
504 | p += sizeof(struct font); | |
505 | widtab[i] = p; /* then width table */ | |
506 | codetab[i] = p + 2 * nw; /* then code conversion table */ | |
507 | fitab[i] = p + 3 * nw; /* then font inclusion table */ | |
508 | p += 3 * nw + dev.nchtab + 128 - 32; | |
509 | t_fp(i, fontbase[i]->namefont, fontbase[i]->intname); | |
510 | #ifdef DEBUGABLE | |
511 | if (dbg > 1) fontprint(i); | |
512 | #endif | |
ef0f9059 | 513 | } |
9a0557cf DS |
514 | for (i = 1; i <= nstips; i++) { /* add in Stipple "filenames" */ |
515 | if (nfonts + i <= NFONT) | |
516 | t_fp(nfonts + i, p, (char *)0); | |
517 | p += strlen(p) + 1; | |
518 | } | |
6dded2dd DS |
519 | fontbase[0] = NULL; |
520 | close(fin); /* no fonts loaded yet */ | |
521 | for (i = 0; i <= NFONT; i++) fontdata[i].font = fontdata[i].size = -1; | |
ef0f9059 DS |
522 | } |
523 | ||
6dded2dd DS |
524 | |
525 | #ifdef DEBUGABLE | |
ef0f9059 DS |
526 | fontprint(i) /* debugging print of font i (0,...) */ |
527 | { | |
6dded2dd | 528 | int j, n; |
ef0f9059 DS |
529 | char *p; |
530 | ||
531 | printf("font %d:\n", i); | |
532 | p = (char *) fontbase[i]; | |
533 | n = fontbase[i]->nwfont & BMASK; | |
534 | printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", | |
6dded2dd | 535 | p, n, fontbase[i]->specfont, fontbase[i]->namefont, widtab[i], fitab[i]); |
ef0f9059 DS |
536 | printf("widths:\n"); |
537 | for (j=0; j <= n; j++) { | |
6dded2dd | 538 | printf(" %2d", widtab[i][j] & BMASK); |
ef0f9059 DS |
539 | if (j % 20 == 19) printf("\n"); |
540 | } | |
541 | printf("\ncodetab:\n"); | |
542 | for (j=0; j <= n; j++) { | |
543 | printf(" %2d", codetab[i][j] & BMASK); | |
544 | if (j % 20 == 19) printf("\n"); | |
545 | } | |
546 | printf("\nfitab:\n"); | |
547 | for (j=0; j <= dev.nchtab + 128-32; j++) { | |
548 | printf(" %2d", fitab[i][j] & BMASK); | |
549 | if (j % 20 == 19) printf("\n"); | |
550 | } | |
551 | printf("\n"); | |
552 | } | |
6dded2dd DS |
553 | #endif |
554 | ||
ef0f9059 DS |
555 | |
556 | loadfont(n, s, s1) /* load font info for font s on position n (0...) */ | |
557 | int n; | |
558 | char *s, *s1; | |
559 | { | |
560 | char temp[60]; | |
6dded2dd | 561 | int fin, nw; |
ef0f9059 DS |
562 | |
563 | if (n < 0 || n > NFONT) | |
564 | error(FATAL, "illegal fp command %d %s", n, s); | |
565 | if (fontbase[n] != NULL && strcmp(s, fontbase[n]->namefont) == 0) | |
566 | return; | |
38babee7 DS |
567 | |
568 | for (fin = 1; fin <= NFONT; fin++) /* first check to see if the */ | |
569 | if (strcmp(s, fontbase[fin]->namefont) == 0) { /* font is loaded */ | |
570 | register unsigned char *c; /* somewhere else */ | |
571 | ||
572 | #define ptrswap(x, y) { c = (unsigned char*) (x); x = y; y = c; } | |
573 | #define ptrfswap(x, y) { c=(unsigned char*)(x); x = y; y = (struct font *) c; } | |
574 | ||
575 | ptrfswap(fontbase[n], fontbase[fin]); | |
576 | ptrswap(codetab[n], codetab[fin]); | |
577 | ptrswap(widtab[n], widtab[fin]); | |
578 | ptrswap(fitab[n], fitab[fin]); | |
579 | t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); | |
580 | t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname); | |
581 | return; | |
582 | } | |
583 | ||
ef0f9059 | 584 | if (s1 == NULL || s1[0] == '\0') |
6dded2dd | 585 | sprintf(temp, "%s/devip/%s.out", fontdir, s); |
ef0f9059 DS |
586 | else |
587 | sprintf(temp, "%s/%s.out", s1, s); | |
588 | if ((fin = open(temp, 0)) < 0) { | |
589 | error(!FATAL, "can't open font table %s", temp); | |
590 | return; | |
591 | } | |
592 | if (fontbase[n] != NULL) | |
593 | free(fontbase[n]); | |
594 | fontbase[n] = (struct font *) malloc(3*255 + dev.nchtab + | |
595 | (128-32) + sizeof(struct font)); | |
596 | if (fontbase[n] == NULL) | |
597 | error(FATAL, "Out of space in loadfont %s", s); | |
598 | read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct font)); | |
599 | close(fin); | |
ef0f9059 | 600 | nw = fontbase[n]->nwfont & BMASK; |
6dded2dd DS |
601 | widtab[n] = (unsigned char *) fontbase[n] + sizeof(struct font); |
602 | codetab[n] = (unsigned char *) widtab[n] + 2 * nw; | |
603 | fitab[n] = (unsigned char *) widtab[n] + 3 * nw; | |
ef0f9059 | 604 | t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); |
6dded2dd | 605 | #ifdef DEBUGABLE |
ef0f9059 | 606 | if (dbg > 1) fontprint(n); |
6dded2dd | 607 | #endif |
ef0f9059 DS |
608 | } |
609 | ||
ef0f9059 | 610 | |
6dded2dd DS |
611 | /*VARARGS2*/ |
612 | error(f, s, a1, a2, a3, a4, a5, a6, a7) | |
613 | int f; | |
614 | char *s; | |
615 | { | |
ef0f9059 DS |
616 | fprintf(stderr, "dip: "); |
617 | fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); | |
618 | fprintf(stderr, "\n"); | |
619 | if (f) | |
2cf235a3 | 620 | exit(2); |
ef0f9059 DS |
621 | } |
622 | ||
623 | ||
9a0557cf | 624 | t_init() /* initialize device */ |
ef0f9059 | 625 | { |
9a0557cf | 626 | drawthick(3); /* set the line thickness parameter */ |
ef0f9059 DS |
627 | hpos = vpos = 0; |
628 | setsize(t_size(10)); /* start somewhere */ | |
629 | } | |
630 | ||
6dded2dd DS |
631 | |
632 | /*----------------------------------------------------------------------------* | |
633 | | Routine: t_page ( page_number ) | |
634 | | | |
635 | | Results: mark this page done for printing. If we think we've filled | |
636 | | the imagen too much, delete some of the info in the glyph cache. | |
637 | | This is a good time to do this since it's at the end of a page | |
638 | | and will get done every so often. | |
639 | *----------------------------------------------------------------------------*/ | |
ef0f9059 DS |
640 | |
641 | t_page(pg) /* do whatever new page functions */ | |
642 | { | |
6dded2dd DS |
643 | register int i; |
644 | register int threshold; | |
ef0f9059 DS |
645 | |
646 | pageno = pg; | |
6dded2dd | 647 | #ifdef DEBUGABLE |
ef0f9059 | 648 | if(dbg)fprintf(stderr, "t_page %d, output=%d\n", pg, output); |
6dded2dd DS |
649 | #endif |
650 | if (output != 0) | |
ef0f9059 | 651 | putc(AEND, tf); |
ef0f9059 | 652 | output = in_olist(pg); |
6dded2dd | 653 | |
ef0f9059 | 654 | if (output) { |
6dded2dd DS |
655 | threshold = BOTTOMTHRESH; |
656 | while (totglyph >= maxglyph) { | |
657 | for (i = 0; i < NFONT; i++) { | |
658 | if (fontdata[i].font != -1) | |
659 | clearglyphs(i, threshold); | |
ef0f9059 | 660 | } |
6dded2dd DS |
661 | threshold += DELTATHRESH; |
662 | } | |
ef0f9059 DS |
663 | } |
664 | lastx = lasty = -1; | |
9a0557cf | 665 | hpos = vpos = 0; |
ef0f9059 DS |
666 | } |
667 | ||
ef0f9059 DS |
668 | |
669 | t_size(n) /* convert integer to internal size number*/ | |
670 | int n; | |
671 | { | |
672 | int i; | |
673 | ||
674 | if (n <= pstab[0]) | |
9a0557cf | 675 | return(0); |
ef0f9059 | 676 | else if (n >= pstab[nsizes-1]) |
6dded2dd | 677 | return(nsizes-1); |
ef0f9059 DS |
678 | for (i = 0; n > pstab[i]; i++) |
679 | ; | |
6dded2dd | 680 | return(i); |
ef0f9059 DS |
681 | } |
682 | ||
6dded2dd | 683 | |
ef0f9059 DS |
684 | t_charht(n) /* set character height to n */ |
685 | int n; | |
686 | { | |
687 | /* punt for now */ | |
688 | } | |
689 | ||
6dded2dd | 690 | |
ef0f9059 DS |
691 | t_slant(n) /* set slant to n */ |
692 | int n; | |
693 | { | |
694 | /* punt for now */ | |
695 | } | |
696 | ||
6dded2dd | 697 | |
ef0f9059 DS |
698 | t_font(s) /* convert string to internal font number */ |
699 | char *s; | |
700 | { | |
701 | int n; | |
702 | ||
703 | n = atoi(s); | |
704 | if (n < 0 || n > nfonts) | |
705 | n = 1; | |
706 | return(n); | |
707 | } | |
708 | ||
ef0f9059 DS |
709 | |
710 | t_wrapup() | |
711 | { | |
712 | putc(AEND, tf); | |
713 | putc(AEOF, tf); | |
714 | } | |
715 | ||
ef0f9059 | 716 | |
ef0f9059 | 717 | put1s(s) /* s is a funny char name */ |
6dded2dd | 718 | register char *s; |
ef0f9059 DS |
719 | { |
720 | static int i = 0; | |
721 | ||
722 | if (!output) | |
723 | return; | |
6dded2dd | 724 | #ifdef DEBUGABLE |
ef0f9059 | 725 | if (dbg) printf("%s ", s); |
6dded2dd | 726 | #endif |
ef0f9059 DS |
727 | if (strcmp(s, &chname[chtab[i]]) != 0) |
728 | for (i = 0; i < nchtab; i++) | |
729 | if (strcmp(&chname[chtab[i]], s) == 0) | |
730 | break; | |
731 | if (i < nchtab) | |
732 | put1(i + 128); | |
733 | else | |
734 | i = 0; | |
735 | } | |
736 | ||
6dded2dd | 737 | |
ef0f9059 | 738 | put1(c) /* output char c */ |
6dded2dd | 739 | register int c; |
ef0f9059 | 740 | { |
6dded2dd DS |
741 | register unsigned char *pw; |
742 | register unsigned char *p; | |
743 | register int i; | |
744 | register int j; | |
745 | register int k; | |
746 | int ofont, code; | |
ef0f9059 DS |
747 | |
748 | if (!output) | |
749 | return; | |
750 | c -= 32; | |
751 | if (c <= 0) { | |
6dded2dd | 752 | #ifdef DEBUGABLE |
ef0f9059 | 753 | if (dbg) printf("non-exist 0%o\n", c+32); |
6dded2dd | 754 | #endif |
ef0f9059 DS |
755 | return; |
756 | } | |
6dded2dd DS |
757 | ofont = font; |
758 | i = fitab[font][c]; | |
ef0f9059 DS |
759 | if (i != 0) { /* it's on this font */ |
760 | p = codetab[font]; | |
6dded2dd DS |
761 | pw = widtab[font]; |
762 | } else { /* on another font */ | |
2cf235a3 | 763 | k = font; /* start with current, then run down the list */ |
6dded2dd DS |
764 | for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1)) |
765 | if (fontbase[k] != NULL && (i = fitab[k][c]) != 0) { | |
ef0f9059 | 766 | p = codetab[k]; |
6dded2dd | 767 | pw = widtab[k]; |
ef0f9059 DS |
768 | setfont(k); |
769 | break; | |
770 | } | |
771 | } | |
6dded2dd DS |
772 | code = p[i] & BMASK; |
773 | if (i == 0) { | |
774 | #ifdef DEBUGABLE | |
ef0f9059 | 775 | if (dbg) printf("not found 0%o\n", c+32); |
6dded2dd | 776 | #endif |
ef0f9059 DS |
777 | return; |
778 | } | |
6dded2dd DS |
779 | lastw = (pw[i] * pstab[size] + dev.unitwidth/2) / dev.unitwidth; |
780 | #ifdef DEBUGABLE | |
ef0f9059 DS |
781 | if (dbg) { |
782 | if (isprint(c+32)) | |
783 | printf("%c %d\n", c+32, code); | |
784 | else | |
785 | printf("%03o %d\n", c+32, code); | |
786 | } else | |
6dded2dd DS |
787 | #endif |
788 | if (output) xychar(code); | |
ef0f9059 DS |
789 | if (font != ofont) |
790 | setfont(ofont); | |
791 | } | |
792 | ||
6dded2dd | 793 | |
ef0f9059 DS |
794 | setsize(n) /* set point size to n (internal) */ |
795 | int n; | |
796 | { | |
797 | size = n; | |
798 | } | |
799 | ||
ef0f9059 | 800 | |
6dded2dd DS |
801 | /*----------------------------------------------------------------------------* |
802 | | Routine: t_fp ( number, string, string_internal ) | |
803 | | | |
804 | | Results: font position number now contains font 'string', internal | |
805 | | font name (number) is ignored. | |
806 | | | |
807 | | Side Efct: any fonts loaded into fontdata with this font number are | |
808 | | removed. And, to make sure they're not accessed, if lastfont | |
809 | | equals number, it is "disabled" by setting lastfont to -1. | |
810 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 811 | |
6dded2dd | 812 | t_fp(n, s, si) |
ef0f9059 DS |
813 | int n; |
814 | char *s, *si; | |
815 | { | |
6dded2dd DS |
816 | register int i; |
817 | ||
818 | fontname[n] = s; | |
819 | for (i = 0; i <= NFONT; i++) /* release any font files */ | |
820 | if (fontdata[i].font == n) { /* for this font */ | |
821 | clearglyphs (i, 1000); | |
822 | putc(AFORCE, tf); | |
823 | free (fontdata[i].cdp); | |
824 | free (fontdata[i].glyph); | |
825 | fontdata[i].font = -1; | |
826 | } | |
827 | if (n == lastfont) lastfont = -1; | |
ef0f9059 DS |
828 | } |
829 | ||
6dded2dd | 830 | |
ef0f9059 DS |
831 | setfont(n) /* set font to n */ |
832 | int n; | |
833 | { | |
834 | if (!output) | |
835 | return; | |
9a0557cf | 836 | if (n < 0 || n > nfonts) |
ef0f9059 DS |
837 | error(FATAL, "illegal font %d", n); |
838 | font = n; | |
839 | } | |
840 | ||
ef0f9059 | 841 | |
9a0557cf DS |
842 | setstip(n) /* set stipple "font" to n */ |
843 | int n; | |
844 | { | |
845 | if (!output) | |
846 | return; | |
847 | if (n < 1 || n > nstips) | |
848 | error(FATAL, "illegal stipple %d", n); | |
849 | stip = n; | |
850 | } | |
851 | ||
852 | ||
6dded2dd DS |
853 | /*----------------------------------------------------------------------------* |
854 | | Routine: rd1, rd2, rd3, rd4 ( file_pointer ) | |
855 | | | |
856 | | Results: gets one, two three or four bytes from a file and interprets | |
857 | | them as integers. Most significant bytes come first. | |
858 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 859 | |
6dded2dd DS |
860 | int rd1(fp) |
861 | FILE *fp; | |
862 | { | |
863 | register int i; | |
ef0f9059 | 864 | |
6dded2dd DS |
865 | if((i = getc(fp)) == EOF) error(FATAL, "font file read error"); |
866 | return i; | |
867 | } | |
ef0f9059 | 868 | |
6dded2dd DS |
869 | int rd2(fp) |
870 | FILE *fp; | |
871 | { | |
872 | register short i = rd1(fp) << 8; | |
ef0f9059 | 873 | |
6dded2dd DS |
874 | return i | rd1(fp); |
875 | } | |
ef0f9059 | 876 | |
6dded2dd DS |
877 | int rd3(fp) |
878 | FILE *fp; | |
ef0f9059 | 879 | { |
6dded2dd | 880 | register int i = rd2(fp) << 8; |
ef0f9059 | 881 | |
6dded2dd | 882 | return i | rd1(fp); |
ef0f9059 DS |
883 | } |
884 | ||
6dded2dd DS |
885 | int rd4(fp) |
886 | FILE *fp; | |
ef0f9059 | 887 | { |
6dded2dd | 888 | register int i = rd2(fp) << 16; |
ef0f9059 | 889 | |
6dded2dd DS |
890 | return i | rd2(fp); |
891 | } | |
ef0f9059 | 892 | |
ef0f9059 | 893 | |
6dded2dd DS |
894 | /*----------------------------------------------------------------------------* |
895 | | Routine: getfontdata ( font, size ) | |
896 | | | |
897 | | Results: returns the family number of the font/size found. The font | |
898 | | information pointer, fs, is set to point to data for "font" | |
899 | | at point size "size". If no information for that font is | |
900 | | available, the info is read in from the appropriate font file. | |
901 | | The table "fontdata" holds all the fonts, and it is cleared | |
902 | | of a random font/size if necessary. | |
903 | *----------------------------------------------------------------------------*/ | |
904 | ||
905 | int getfontdata(f, s) | |
906 | int f; | |
907 | int s; | |
908 | { | |
909 | char name[100]; | |
910 | register FILE *fd; | |
911 | register int i; | |
912 | register int fam; | |
913 | register int bitbase; | |
914 | register glyph_dir *maxgp; | |
6dded2dd DS |
915 | register glyph_dir *gp; |
916 | preamble p; | |
917 | ||
918 | /* first check if it's here already */ | |
919 | for (fam = 0; fam <= NFONT; fam++) | |
920 | if (fontdata[fam].font == f && fontdata[fam].size == s) { | |
921 | fs = &fontdata[fam]; | |
922 | return (fam); | |
923 | } | |
924 | /* find an empty slot */ | |
925 | for (fam = 0; fam < NFONT && fontdata[fam].font != -1; fam++); | |
926 | fs = &fontdata[fam]; | |
927 | if (fs->font != -1) { /* clear a slot if not empty */ | |
928 | clearglyphs(fam, 1000); /* dumb version - always take */ | |
929 | putc(AFORCE, tf); /* the last one to replace */ | |
930 | free(fs->glyph); | |
931 | free(fs->cdp); | |
932 | } | |
933 | /* open font file */ | |
934 | sprintf(name, "%s/%s.%d", bitdir, fontname[f], pstab[s]); | |
935 | if ((fd = fopen(name, "r")) == NULL) | |
936 | error(FATAL, "can't open %s", name); | |
937 | /* check for proper file mark */ | |
2cf235a3 DS |
938 | for(i = 0; i < FMARK; filemark[i++] = getc(fd)); |
939 | if (strncmp(filemark, "Rast", 4)) | |
6dded2dd DS |
940 | error(FATAL, "bad File Mark in %s.", name); |
941 | /* get preamble */ | |
942 | p.p_size = rd2(fd); | |
943 | p.p_version = rd1(fd); | |
944 | if (p.p_version) | |
945 | error(FATAL, "wrong version of Font file: %s.", name); | |
946 | p.p_glyph = rd3(fd); | |
9a0557cf DS |
947 | fs->first = p.p_first = rd2(fd); |
948 | fs->last = p.p_last = rd2(fd); | |
6dded2dd DS |
949 | /* skip rest of preamble */ |
950 | i = p.p_glyph - 18; | |
951 | while (i--) getc(fd); | |
952 | fs->glyph = (glyph_dir *) /* allocate first */ | |
953 | ((char *) malloc((p.p_last - p.p_first + 1) * sizeof(glyph_dir)) | |
954 | - (char *) (p.p_first * sizeof(glyph_dir))); | |
9a0557cf DS |
955 | maxgp = gp = &(fs->glyph[p.p_first]); |
956 | bitbase = maxgp->g_bitp; | |
6dded2dd DS |
957 | for (i = p.p_first; i++ <= p.p_last; gp++) { |
958 | gp->g_height = rd2(fd); | |
959 | gp->g_width = rd2(fd); | |
960 | gp->g_up = rd2(fd); | |
961 | gp->g_left = rd2(fd); | |
962 | gp->g_pwidth = rd4(fd); | |
963 | if ((gp->g_bitp = rd3(fd)) > maxgp->g_bitp) /* find the glyphs */ | |
9a0557cf DS |
964 | maxgp = gp; /* farthest from and */ |
965 | else if(gp->g_bitp < bitbase) /* nearest to the */ | |
966 | bitbase = gp->g_bitp; /* start of the file */ | |
ef0f9059 | 967 | } |
9a0557cf | 968 | /* remove file offset in bit pointers */ |
6dded2dd DS |
969 | for (gp = fs->glyph, i = p.p_first; i++ <= p.p_last; gp++) |
970 | gp->g_bitp -= bitbase; | |
971 | ||
972 | i = maxgp->g_bitp + maxgp->g_height * ((maxgp->g_width + 7) / 8); | |
973 | fs->cdp = (unsigned char *) malloc(i); | |
974 | lseek(fileno(fd), (long) bitbase, 0); | |
975 | if (read(fileno (fd), fs->cdp, i) != i) | |
976 | error(FATAL, "can't read in %s", name); | |
977 | fclose(fd); | |
978 | ||
979 | fs->size = s; | |
980 | fs->font = f; | |
981 | for (i = 0; i < CHARRAY; fs->chused[i++] = 0); | |
982 | return (fam); | |
ef0f9059 DS |
983 | } |
984 | ||
6dded2dd | 985 | |
9a0557cf DS |
986 | /*----------------------------------------------------------------------------* |
987 | | Routine: setfill(stipple_number) | |
988 | | | |
989 | | Results: sends the appropriate command to set the fill-pattern | |
990 | | for a particular stipple. Sends the glyph if necessary, | |
991 | | and does nothing if the pattern is the same. Takes stipple | |
992 | | font from current "stip" number. | |
993 | *----------------------------------------------------------------------------*/ | |
994 | ||
995 | setfill(number) | |
996 | register int number; | |
997 | { | |
998 | register int fam; | |
999 | register int gsize; | |
1000 | register glyph_dir *par; | |
1001 | register unsigned char *p; | |
1002 | register fontset *savefs; | |
1003 | ||
1004 | if (stip == laststip && number == laststipmem) | |
1005 | return; | |
1006 | ||
1007 | savefs = fs; /* getfontdata sets fs, so we have to */ | |
1008 | /* save it before calling getfontdata */ | |
1009 | fam = getfontdata(nfonts + stip, nsizes); | |
1010 | laststip = stip; | |
1011 | laststipmem = number; /* must be set before call to polygon */ | |
1012 | ||
1013 | if (!number || number < fs->first || number > fs->last) { | |
1014 | fs = savefs; /* forget it if it's out of range */ | |
1015 | laststipmem = 0; /* force NO stipple */ | |
1016 | return; | |
1017 | } | |
1018 | if (fs->chused[number] == 0) { /* stipple not down-loaded */ | |
1019 | totglyph += glspace(par = &(fs->glyph[number])); | |
1020 | putc(ABGLY, tf); | |
1021 | putint((fam << 7) | number, tf); | |
1022 | putint(par->g_pwidth, tf); | |
1023 | putint(par->g_width, tf); | |
1024 | putint(par->g_left, tf); | |
1025 | putint(par->g_height, tf); | |
1026 | putint(par->g_up, tf); | |
1027 | gsize = ((par->g_width + 7)/8) * par->g_height; | |
1028 | p = fs->cdp + par->g_bitp; | |
1029 | while (gsize--) | |
1030 | putc(*p++, tf); | |
1031 | } | |
1032 | /* mark that it's been used */ | |
1033 | if (fs->chused[number] != BMASK) | |
1034 | fs->chused[number]++; | |
1035 | putc(ASTEXTURE, tf); /* set the texture */ | |
1036 | putint((fam << 7) | number, tf); | |
1037 | fs = savefs; /* return fs to proper spot */ | |
1038 | } | |
1039 | ||
1040 | ||
ef0f9059 | 1041 | xychar(c) |
6dded2dd | 1042 | register int c; |
ef0f9059 DS |
1043 | { |
1044 | register unsigned char *p; | |
6dded2dd DS |
1045 | register glyph_dir *par; |
1046 | register int gsize; | |
ef0f9059 | 1047 | |
ef0f9059 | 1048 | |
6dded2dd DS |
1049 | if (c >= CHARRAY) { |
1050 | #ifdef DEBUGABLE | |
1051 | if (dbg) error(!FATAL, "character out of range: %d 0%o", c, c); | |
1052 | #endif | |
1053 | return; | |
1054 | } | |
ef0f9059 | 1055 | if (font != lastfont || size != lastsize) { |
6dded2dd | 1056 | family = getfontdata(font, size); |
ef0f9059 DS |
1057 | lastsize = size; |
1058 | lastfont = font; | |
1059 | } | |
6dded2dd DS |
1060 | par = &(fs->glyph[c]); |
1061 | p = fs->cdp + par->g_bitp; | |
1062 | if (family != lastfam) { | |
ef0f9059 | 1063 | putc(AF, tf); |
6dded2dd | 1064 | putc(lastfam = family ,tf); |
ef0f9059 DS |
1065 | } |
1066 | ||
6dded2dd | 1067 | if (fs->chused[c] == 0) { /* 1st use of this character */ |
ef0f9059 | 1068 | totglyph += glspace(par); |
6dded2dd DS |
1069 | putc(ABGLY, tf); |
1070 | putint((family << 7) | c, tf); | |
1071 | putint(lastw, tf); /* use troff's width, not */ | |
1072 | putint(par->g_width, tf); /* the RST character width */ | |
1073 | putint(par->g_left, tf); | |
1074 | putint(par->g_height, tf); | |
1075 | putint(par->g_up, tf); | |
1076 | gsize = ((par->g_width + 7)/8) * par->g_height; | |
1077 | while (gsize--) | |
ef0f9059 DS |
1078 | putc(*p++, tf); |
1079 | } | |
9a0557cf DS |
1080 | /* note that character's been used */ |
1081 | if (fs->chused[c] != BMASK) | |
1082 | fs->chused[c]++; | |
6dded2dd DS |
1083 | hvflush(); |
1084 | putc(c, tf); /* guaranteed to be in range */ | |
1085 | lastx += lastw; /* take account of the automatic advance */ | |
ef0f9059 DS |
1086 | } |
1087 | ||
ef0f9059 | 1088 | |
6dded2dd DS |
1089 | /*----------------------------------------------------------------------------* |
1090 | | Routine: hvflush ( ) | |
1091 | | | |
1092 | | Results: force current position (hpos, vpos) on the imagen | |
1093 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 1094 | |
6dded2dd DS |
1095 | hvflush() |
1096 | { | |
1097 | if (vpos != lasty) { | |
1098 | putc(ASETV, tf); | |
1099 | putint(lasty = vpos, tf); | |
ef0f9059 | 1100 | } |
6dded2dd DS |
1101 | if (hpos != lastx) { |
1102 | putc(ASETH, tf); | |
1103 | putint(lastx = hpos, tf); | |
ef0f9059 DS |
1104 | } |
1105 | } | |
1106 | ||
6dded2dd DS |
1107 | |
1108 | /*----------------------------------------------------------------------------* | |
1109 | | Routine: glspace ( glyph ) | |
1110 | | | |
1111 | | Results: returns how much space the glyph (defined by the glyph_dir | |
1112 | | entry) will take in the imagen's memory. | |
1113 | *----------------------------------------------------------------------------*/ | |
1114 | ||
ef0f9059 | 1115 | glspace(par) |
6dded2dd | 1116 | glyph_dir *par; |
ef0f9059 | 1117 | { |
6dded2dd DS |
1118 | return 19 + ((par->g_width + 15) / 16 ) * (par->g_height); |
1119 | } | |
ef0f9059 | 1120 | |
ef0f9059 | 1121 | |
6dded2dd DS |
1122 | /*----------------------------------------------------------------------------* |
1123 | | Routine: clearglyphs ( index, limit ) | |
1124 | | | |
1125 | | Results: any glyphs downloaded into the imagen with a "chused" entry | |
1126 | | less than "limit" (and > 0) are marked for deletion and their | |
1127 | | space is "unrecorded" in totglyph. | |
1128 | | | |
1129 | | Bugs: clearglyphs does NOT check index to make sure the family exists | |
1130 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 1131 | |
6dded2dd DS |
1132 | clearglyphs(index, limit) |
1133 | int index; | |
1134 | int limit; | |
ef0f9059 | 1135 | { |
6dded2dd DS |
1136 | register fontset *f = &fontdata[index]; |
1137 | register int j; | |
1138 | ||
1139 | #ifdef DEBUGABLE | |
1140 | if (dbg) fprintf(stderr, "clear %d family of %d (%d/%d) on page %d\n", | |
1141 | index, limit, totglyph, maxglyph, pageno); | |
1142 | #endif | |
1143 | for (j = 0; j < CHARRAY; j++) { | |
1144 | if (f->chused[j] && f->chused[j] < limit) { | |
1145 | putc(ADELG, tf); | |
1146 | putint(index<<7 | j, tf); | |
1147 | totglyph -= glspace (&(f->glyph[j])); | |
1148 | f->chused[j] = 0; | |
ef0f9059 | 1149 | } |
6dded2dd | 1150 | } |
ef0f9059 DS |
1151 | } |
1152 | ||
ef0f9059 DS |
1153 | |
1154 | putint(n, f) | |
1155 | int n; | |
1156 | FILE *f; | |
1157 | { | |
1158 | putc(n >> 8, f); | |
1159 | putc(n & 0377, f); | |
1160 | } |