Commit | Line | Data |
---|---|---|
9a0557cf | 1 | /* dip.c 1.8 (Berkeley) 84/04/17 |
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; | |
567 | if (s1 == NULL || s1[0] == '\0') | |
6dded2dd | 568 | sprintf(temp, "%s/devip/%s.out", fontdir, s); |
ef0f9059 DS |
569 | else |
570 | sprintf(temp, "%s/%s.out", s1, s); | |
571 | if ((fin = open(temp, 0)) < 0) { | |
572 | error(!FATAL, "can't open font table %s", temp); | |
573 | return; | |
574 | } | |
575 | if (fontbase[n] != NULL) | |
576 | free(fontbase[n]); | |
577 | fontbase[n] = (struct font *) malloc(3*255 + dev.nchtab + | |
578 | (128-32) + sizeof(struct font)); | |
579 | if (fontbase[n] == NULL) | |
580 | error(FATAL, "Out of space in loadfont %s", s); | |
581 | read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct font)); | |
582 | close(fin); | |
ef0f9059 | 583 | nw = fontbase[n]->nwfont & BMASK; |
6dded2dd DS |
584 | widtab[n] = (unsigned char *) fontbase[n] + sizeof(struct font); |
585 | codetab[n] = (unsigned char *) widtab[n] + 2 * nw; | |
586 | fitab[n] = (unsigned char *) widtab[n] + 3 * nw; | |
ef0f9059 | 587 | t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); |
6dded2dd | 588 | #ifdef DEBUGABLE |
ef0f9059 | 589 | if (dbg > 1) fontprint(n); |
6dded2dd | 590 | #endif |
ef0f9059 DS |
591 | } |
592 | ||
ef0f9059 | 593 | |
6dded2dd DS |
594 | /*VARARGS2*/ |
595 | error(f, s, a1, a2, a3, a4, a5, a6, a7) | |
596 | int f; | |
597 | char *s; | |
598 | { | |
ef0f9059 DS |
599 | fprintf(stderr, "dip: "); |
600 | fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); | |
601 | fprintf(stderr, "\n"); | |
602 | if (f) | |
2cf235a3 | 603 | exit(2); |
ef0f9059 DS |
604 | } |
605 | ||
606 | ||
9a0557cf | 607 | t_init() /* initialize device */ |
ef0f9059 | 608 | { |
9a0557cf | 609 | drawthick(3); /* set the line thickness parameter */ |
ef0f9059 DS |
610 | hpos = vpos = 0; |
611 | setsize(t_size(10)); /* start somewhere */ | |
612 | } | |
613 | ||
6dded2dd DS |
614 | |
615 | /*----------------------------------------------------------------------------* | |
616 | | Routine: t_page ( page_number ) | |
617 | | | |
618 | | Results: mark this page done for printing. If we think we've filled | |
619 | | the imagen too much, delete some of the info in the glyph cache. | |
620 | | This is a good time to do this since it's at the end of a page | |
621 | | and will get done every so often. | |
622 | *----------------------------------------------------------------------------*/ | |
ef0f9059 DS |
623 | |
624 | t_page(pg) /* do whatever new page functions */ | |
625 | { | |
6dded2dd DS |
626 | register int i; |
627 | register int threshold; | |
ef0f9059 DS |
628 | |
629 | pageno = pg; | |
6dded2dd | 630 | #ifdef DEBUGABLE |
ef0f9059 | 631 | if(dbg)fprintf(stderr, "t_page %d, output=%d\n", pg, output); |
6dded2dd DS |
632 | #endif |
633 | if (output != 0) | |
ef0f9059 | 634 | putc(AEND, tf); |
ef0f9059 | 635 | output = in_olist(pg); |
6dded2dd | 636 | |
ef0f9059 | 637 | if (output) { |
6dded2dd DS |
638 | threshold = BOTTOMTHRESH; |
639 | while (totglyph >= maxglyph) { | |
640 | for (i = 0; i < NFONT; i++) { | |
641 | if (fontdata[i].font != -1) | |
642 | clearglyphs(i, threshold); | |
ef0f9059 | 643 | } |
6dded2dd DS |
644 | threshold += DELTATHRESH; |
645 | } | |
ef0f9059 DS |
646 | } |
647 | lastx = lasty = -1; | |
9a0557cf | 648 | hpos = vpos = 0; |
ef0f9059 DS |
649 | } |
650 | ||
ef0f9059 DS |
651 | |
652 | t_size(n) /* convert integer to internal size number*/ | |
653 | int n; | |
654 | { | |
655 | int i; | |
656 | ||
657 | if (n <= pstab[0]) | |
9a0557cf | 658 | return(0); |
ef0f9059 | 659 | else if (n >= pstab[nsizes-1]) |
6dded2dd | 660 | return(nsizes-1); |
ef0f9059 DS |
661 | for (i = 0; n > pstab[i]; i++) |
662 | ; | |
6dded2dd | 663 | return(i); |
ef0f9059 DS |
664 | } |
665 | ||
6dded2dd | 666 | |
ef0f9059 DS |
667 | t_charht(n) /* set character height to n */ |
668 | int n; | |
669 | { | |
670 | /* punt for now */ | |
671 | } | |
672 | ||
6dded2dd | 673 | |
ef0f9059 DS |
674 | t_slant(n) /* set slant to n */ |
675 | int n; | |
676 | { | |
677 | /* punt for now */ | |
678 | } | |
679 | ||
6dded2dd | 680 | |
ef0f9059 DS |
681 | t_font(s) /* convert string to internal font number */ |
682 | char *s; | |
683 | { | |
684 | int n; | |
685 | ||
686 | n = atoi(s); | |
687 | if (n < 0 || n > nfonts) | |
688 | n = 1; | |
689 | return(n); | |
690 | } | |
691 | ||
ef0f9059 DS |
692 | |
693 | t_wrapup() | |
694 | { | |
695 | putc(AEND, tf); | |
696 | putc(AEOF, tf); | |
697 | } | |
698 | ||
ef0f9059 | 699 | |
ef0f9059 | 700 | put1s(s) /* s is a funny char name */ |
6dded2dd | 701 | register char *s; |
ef0f9059 DS |
702 | { |
703 | static int i = 0; | |
704 | ||
705 | if (!output) | |
706 | return; | |
6dded2dd | 707 | #ifdef DEBUGABLE |
ef0f9059 | 708 | if (dbg) printf("%s ", s); |
6dded2dd | 709 | #endif |
ef0f9059 DS |
710 | if (strcmp(s, &chname[chtab[i]]) != 0) |
711 | for (i = 0; i < nchtab; i++) | |
712 | if (strcmp(&chname[chtab[i]], s) == 0) | |
713 | break; | |
714 | if (i < nchtab) | |
715 | put1(i + 128); | |
716 | else | |
717 | i = 0; | |
718 | } | |
719 | ||
6dded2dd | 720 | |
ef0f9059 | 721 | put1(c) /* output char c */ |
6dded2dd | 722 | register int c; |
ef0f9059 | 723 | { |
6dded2dd DS |
724 | register unsigned char *pw; |
725 | register unsigned char *p; | |
726 | register int i; | |
727 | register int j; | |
728 | register int k; | |
729 | int ofont, code; | |
ef0f9059 DS |
730 | |
731 | if (!output) | |
732 | return; | |
733 | c -= 32; | |
734 | if (c <= 0) { | |
6dded2dd | 735 | #ifdef DEBUGABLE |
ef0f9059 | 736 | if (dbg) printf("non-exist 0%o\n", c+32); |
6dded2dd | 737 | #endif |
ef0f9059 DS |
738 | return; |
739 | } | |
6dded2dd DS |
740 | ofont = font; |
741 | i = fitab[font][c]; | |
ef0f9059 DS |
742 | if (i != 0) { /* it's on this font */ |
743 | p = codetab[font]; | |
6dded2dd DS |
744 | pw = widtab[font]; |
745 | } else { /* on another font */ | |
2cf235a3 | 746 | k = font; /* start with current, then run down the list */ |
6dded2dd DS |
747 | for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1)) |
748 | if (fontbase[k] != NULL && (i = fitab[k][c]) != 0) { | |
ef0f9059 | 749 | p = codetab[k]; |
6dded2dd | 750 | pw = widtab[k]; |
ef0f9059 DS |
751 | setfont(k); |
752 | break; | |
753 | } | |
754 | } | |
6dded2dd DS |
755 | code = p[i] & BMASK; |
756 | if (i == 0) { | |
757 | #ifdef DEBUGABLE | |
ef0f9059 | 758 | if (dbg) printf("not found 0%o\n", c+32); |
6dded2dd | 759 | #endif |
ef0f9059 DS |
760 | return; |
761 | } | |
6dded2dd DS |
762 | lastw = (pw[i] * pstab[size] + dev.unitwidth/2) / dev.unitwidth; |
763 | #ifdef DEBUGABLE | |
ef0f9059 DS |
764 | if (dbg) { |
765 | if (isprint(c+32)) | |
766 | printf("%c %d\n", c+32, code); | |
767 | else | |
768 | printf("%03o %d\n", c+32, code); | |
769 | } else | |
6dded2dd DS |
770 | #endif |
771 | if (output) xychar(code); | |
ef0f9059 DS |
772 | if (font != ofont) |
773 | setfont(ofont); | |
774 | } | |
775 | ||
6dded2dd | 776 | |
ef0f9059 DS |
777 | setsize(n) /* set point size to n (internal) */ |
778 | int n; | |
779 | { | |
780 | size = n; | |
781 | } | |
782 | ||
ef0f9059 | 783 | |
6dded2dd DS |
784 | /*----------------------------------------------------------------------------* |
785 | | Routine: t_fp ( number, string, string_internal ) | |
786 | | | |
787 | | Results: font position number now contains font 'string', internal | |
788 | | font name (number) is ignored. | |
789 | | | |
790 | | Side Efct: any fonts loaded into fontdata with this font number are | |
791 | | removed. And, to make sure they're not accessed, if lastfont | |
792 | | equals number, it is "disabled" by setting lastfont to -1. | |
793 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 794 | |
6dded2dd | 795 | t_fp(n, s, si) |
ef0f9059 DS |
796 | int n; |
797 | char *s, *si; | |
798 | { | |
6dded2dd DS |
799 | register int i; |
800 | ||
801 | fontname[n] = s; | |
802 | for (i = 0; i <= NFONT; i++) /* release any font files */ | |
803 | if (fontdata[i].font == n) { /* for this font */ | |
804 | clearglyphs (i, 1000); | |
805 | putc(AFORCE, tf); | |
806 | free (fontdata[i].cdp); | |
807 | free (fontdata[i].glyph); | |
808 | fontdata[i].font = -1; | |
809 | } | |
810 | if (n == lastfont) lastfont = -1; | |
ef0f9059 DS |
811 | } |
812 | ||
6dded2dd | 813 | |
ef0f9059 DS |
814 | setfont(n) /* set font to n */ |
815 | int n; | |
816 | { | |
817 | if (!output) | |
818 | return; | |
9a0557cf | 819 | if (n < 0 || n > nfonts) |
ef0f9059 DS |
820 | error(FATAL, "illegal font %d", n); |
821 | font = n; | |
822 | } | |
823 | ||
ef0f9059 | 824 | |
9a0557cf DS |
825 | setstip(n) /* set stipple "font" to n */ |
826 | int n; | |
827 | { | |
828 | if (!output) | |
829 | return; | |
830 | if (n < 1 || n > nstips) | |
831 | error(FATAL, "illegal stipple %d", n); | |
832 | stip = n; | |
833 | } | |
834 | ||
835 | ||
6dded2dd DS |
836 | /*----------------------------------------------------------------------------* |
837 | | Routine: rd1, rd2, rd3, rd4 ( file_pointer ) | |
838 | | | |
839 | | Results: gets one, two three or four bytes from a file and interprets | |
840 | | them as integers. Most significant bytes come first. | |
841 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 842 | |
6dded2dd DS |
843 | int rd1(fp) |
844 | FILE *fp; | |
845 | { | |
846 | register int i; | |
ef0f9059 | 847 | |
6dded2dd DS |
848 | if((i = getc(fp)) == EOF) error(FATAL, "font file read error"); |
849 | return i; | |
850 | } | |
ef0f9059 | 851 | |
6dded2dd DS |
852 | int rd2(fp) |
853 | FILE *fp; | |
854 | { | |
855 | register short i = rd1(fp) << 8; | |
ef0f9059 | 856 | |
6dded2dd DS |
857 | return i | rd1(fp); |
858 | } | |
ef0f9059 | 859 | |
6dded2dd DS |
860 | int rd3(fp) |
861 | FILE *fp; | |
ef0f9059 | 862 | { |
6dded2dd | 863 | register int i = rd2(fp) << 8; |
ef0f9059 | 864 | |
6dded2dd | 865 | return i | rd1(fp); |
ef0f9059 DS |
866 | } |
867 | ||
6dded2dd DS |
868 | int rd4(fp) |
869 | FILE *fp; | |
ef0f9059 | 870 | { |
6dded2dd | 871 | register int i = rd2(fp) << 16; |
ef0f9059 | 872 | |
6dded2dd DS |
873 | return i | rd2(fp); |
874 | } | |
ef0f9059 | 875 | |
ef0f9059 | 876 | |
6dded2dd DS |
877 | /*----------------------------------------------------------------------------* |
878 | | Routine: getfontdata ( font, size ) | |
879 | | | |
880 | | Results: returns the family number of the font/size found. The font | |
881 | | information pointer, fs, is set to point to data for "font" | |
882 | | at point size "size". If no information for that font is | |
883 | | available, the info is read in from the appropriate font file. | |
884 | | The table "fontdata" holds all the fonts, and it is cleared | |
885 | | of a random font/size if necessary. | |
886 | *----------------------------------------------------------------------------*/ | |
887 | ||
888 | int getfontdata(f, s) | |
889 | int f; | |
890 | int s; | |
891 | { | |
892 | char name[100]; | |
893 | register FILE *fd; | |
894 | register int i; | |
895 | register int fam; | |
896 | register int bitbase; | |
897 | register glyph_dir *maxgp; | |
6dded2dd DS |
898 | register glyph_dir *gp; |
899 | preamble p; | |
900 | ||
901 | /* first check if it's here already */ | |
902 | for (fam = 0; fam <= NFONT; fam++) | |
903 | if (fontdata[fam].font == f && fontdata[fam].size == s) { | |
904 | fs = &fontdata[fam]; | |
905 | return (fam); | |
906 | } | |
907 | /* find an empty slot */ | |
908 | for (fam = 0; fam < NFONT && fontdata[fam].font != -1; fam++); | |
909 | fs = &fontdata[fam]; | |
910 | if (fs->font != -1) { /* clear a slot if not empty */ | |
911 | clearglyphs(fam, 1000); /* dumb version - always take */ | |
912 | putc(AFORCE, tf); /* the last one to replace */ | |
913 | free(fs->glyph); | |
914 | free(fs->cdp); | |
915 | } | |
916 | /* open font file */ | |
917 | sprintf(name, "%s/%s.%d", bitdir, fontname[f], pstab[s]); | |
918 | if ((fd = fopen(name, "r")) == NULL) | |
919 | error(FATAL, "can't open %s", name); | |
920 | /* check for proper file mark */ | |
2cf235a3 DS |
921 | for(i = 0; i < FMARK; filemark[i++] = getc(fd)); |
922 | if (strncmp(filemark, "Rast", 4)) | |
6dded2dd DS |
923 | error(FATAL, "bad File Mark in %s.", name); |
924 | /* get preamble */ | |
925 | p.p_size = rd2(fd); | |
926 | p.p_version = rd1(fd); | |
927 | if (p.p_version) | |
928 | error(FATAL, "wrong version of Font file: %s.", name); | |
929 | p.p_glyph = rd3(fd); | |
9a0557cf DS |
930 | fs->first = p.p_first = rd2(fd); |
931 | fs->last = p.p_last = rd2(fd); | |
6dded2dd DS |
932 | /* skip rest of preamble */ |
933 | i = p.p_glyph - 18; | |
934 | while (i--) getc(fd); | |
935 | fs->glyph = (glyph_dir *) /* allocate first */ | |
936 | ((char *) malloc((p.p_last - p.p_first + 1) * sizeof(glyph_dir)) | |
937 | - (char *) (p.p_first * sizeof(glyph_dir))); | |
9a0557cf DS |
938 | maxgp = gp = &(fs->glyph[p.p_first]); |
939 | bitbase = maxgp->g_bitp; | |
6dded2dd DS |
940 | for (i = p.p_first; i++ <= p.p_last; gp++) { |
941 | gp->g_height = rd2(fd); | |
942 | gp->g_width = rd2(fd); | |
943 | gp->g_up = rd2(fd); | |
944 | gp->g_left = rd2(fd); | |
945 | gp->g_pwidth = rd4(fd); | |
946 | if ((gp->g_bitp = rd3(fd)) > maxgp->g_bitp) /* find the glyphs */ | |
9a0557cf DS |
947 | maxgp = gp; /* farthest from and */ |
948 | else if(gp->g_bitp < bitbase) /* nearest to the */ | |
949 | bitbase = gp->g_bitp; /* start of the file */ | |
ef0f9059 | 950 | } |
9a0557cf | 951 | /* remove file offset in bit pointers */ |
6dded2dd DS |
952 | for (gp = fs->glyph, i = p.p_first; i++ <= p.p_last; gp++) |
953 | gp->g_bitp -= bitbase; | |
954 | ||
955 | i = maxgp->g_bitp + maxgp->g_height * ((maxgp->g_width + 7) / 8); | |
956 | fs->cdp = (unsigned char *) malloc(i); | |
957 | lseek(fileno(fd), (long) bitbase, 0); | |
958 | if (read(fileno (fd), fs->cdp, i) != i) | |
959 | error(FATAL, "can't read in %s", name); | |
960 | fclose(fd); | |
961 | ||
962 | fs->size = s; | |
963 | fs->font = f; | |
964 | for (i = 0; i < CHARRAY; fs->chused[i++] = 0); | |
965 | return (fam); | |
ef0f9059 DS |
966 | } |
967 | ||
6dded2dd | 968 | |
9a0557cf DS |
969 | /*----------------------------------------------------------------------------* |
970 | | Routine: setfill(stipple_number) | |
971 | | | |
972 | | Results: sends the appropriate command to set the fill-pattern | |
973 | | for a particular stipple. Sends the glyph if necessary, | |
974 | | and does nothing if the pattern is the same. Takes stipple | |
975 | | font from current "stip" number. | |
976 | *----------------------------------------------------------------------------*/ | |
977 | ||
978 | setfill(number) | |
979 | register int number; | |
980 | { | |
981 | register int fam; | |
982 | register int gsize; | |
983 | register glyph_dir *par; | |
984 | register unsigned char *p; | |
985 | register fontset *savefs; | |
986 | ||
987 | if (stip == laststip && number == laststipmem) | |
988 | return; | |
989 | ||
990 | savefs = fs; /* getfontdata sets fs, so we have to */ | |
991 | /* save it before calling getfontdata */ | |
992 | fam = getfontdata(nfonts + stip, nsizes); | |
993 | laststip = stip; | |
994 | laststipmem = number; /* must be set before call to polygon */ | |
995 | ||
996 | if (!number || number < fs->first || number > fs->last) { | |
997 | fs = savefs; /* forget it if it's out of range */ | |
998 | laststipmem = 0; /* force NO stipple */ | |
999 | return; | |
1000 | } | |
1001 | if (fs->chused[number] == 0) { /* stipple not down-loaded */ | |
1002 | totglyph += glspace(par = &(fs->glyph[number])); | |
1003 | putc(ABGLY, tf); | |
1004 | putint((fam << 7) | number, tf); | |
1005 | putint(par->g_pwidth, tf); | |
1006 | putint(par->g_width, tf); | |
1007 | putint(par->g_left, tf); | |
1008 | putint(par->g_height, tf); | |
1009 | putint(par->g_up, tf); | |
1010 | gsize = ((par->g_width + 7)/8) * par->g_height; | |
1011 | p = fs->cdp + par->g_bitp; | |
1012 | while (gsize--) | |
1013 | putc(*p++, tf); | |
1014 | } | |
1015 | /* mark that it's been used */ | |
1016 | if (fs->chused[number] != BMASK) | |
1017 | fs->chused[number]++; | |
1018 | putc(ASTEXTURE, tf); /* set the texture */ | |
1019 | putint((fam << 7) | number, tf); | |
1020 | fs = savefs; /* return fs to proper spot */ | |
1021 | } | |
1022 | ||
1023 | ||
ef0f9059 | 1024 | xychar(c) |
6dded2dd | 1025 | register int c; |
ef0f9059 DS |
1026 | { |
1027 | register unsigned char *p; | |
6dded2dd DS |
1028 | register glyph_dir *par; |
1029 | register int gsize; | |
ef0f9059 | 1030 | |
ef0f9059 | 1031 | |
6dded2dd DS |
1032 | if (c >= CHARRAY) { |
1033 | #ifdef DEBUGABLE | |
1034 | if (dbg) error(!FATAL, "character out of range: %d 0%o", c, c); | |
1035 | #endif | |
1036 | return; | |
1037 | } | |
ef0f9059 | 1038 | if (font != lastfont || size != lastsize) { |
6dded2dd | 1039 | family = getfontdata(font, size); |
ef0f9059 DS |
1040 | lastsize = size; |
1041 | lastfont = font; | |
1042 | } | |
6dded2dd DS |
1043 | par = &(fs->glyph[c]); |
1044 | p = fs->cdp + par->g_bitp; | |
1045 | if (family != lastfam) { | |
ef0f9059 | 1046 | putc(AF, tf); |
6dded2dd | 1047 | putc(lastfam = family ,tf); |
ef0f9059 DS |
1048 | } |
1049 | ||
6dded2dd | 1050 | if (fs->chused[c] == 0) { /* 1st use of this character */ |
ef0f9059 | 1051 | totglyph += glspace(par); |
6dded2dd DS |
1052 | putc(ABGLY, tf); |
1053 | putint((family << 7) | c, tf); | |
1054 | putint(lastw, tf); /* use troff's width, not */ | |
1055 | putint(par->g_width, tf); /* the RST character width */ | |
1056 | putint(par->g_left, tf); | |
1057 | putint(par->g_height, tf); | |
1058 | putint(par->g_up, tf); | |
1059 | gsize = ((par->g_width + 7)/8) * par->g_height; | |
1060 | while (gsize--) | |
ef0f9059 DS |
1061 | putc(*p++, tf); |
1062 | } | |
9a0557cf DS |
1063 | /* note that character's been used */ |
1064 | if (fs->chused[c] != BMASK) | |
1065 | fs->chused[c]++; | |
6dded2dd DS |
1066 | hvflush(); |
1067 | putc(c, tf); /* guaranteed to be in range */ | |
1068 | lastx += lastw; /* take account of the automatic advance */ | |
ef0f9059 DS |
1069 | } |
1070 | ||
ef0f9059 | 1071 | |
6dded2dd DS |
1072 | /*----------------------------------------------------------------------------* |
1073 | | Routine: hvflush ( ) | |
1074 | | | |
1075 | | Results: force current position (hpos, vpos) on the imagen | |
1076 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 1077 | |
6dded2dd DS |
1078 | hvflush() |
1079 | { | |
1080 | if (vpos != lasty) { | |
1081 | putc(ASETV, tf); | |
1082 | putint(lasty = vpos, tf); | |
ef0f9059 | 1083 | } |
6dded2dd DS |
1084 | if (hpos != lastx) { |
1085 | putc(ASETH, tf); | |
1086 | putint(lastx = hpos, tf); | |
ef0f9059 DS |
1087 | } |
1088 | } | |
1089 | ||
6dded2dd DS |
1090 | |
1091 | /*----------------------------------------------------------------------------* | |
1092 | | Routine: glspace ( glyph ) | |
1093 | | | |
1094 | | Results: returns how much space the glyph (defined by the glyph_dir | |
1095 | | entry) will take in the imagen's memory. | |
1096 | *----------------------------------------------------------------------------*/ | |
1097 | ||
ef0f9059 | 1098 | glspace(par) |
6dded2dd | 1099 | glyph_dir *par; |
ef0f9059 | 1100 | { |
6dded2dd DS |
1101 | return 19 + ((par->g_width + 15) / 16 ) * (par->g_height); |
1102 | } | |
ef0f9059 | 1103 | |
ef0f9059 | 1104 | |
6dded2dd DS |
1105 | /*----------------------------------------------------------------------------* |
1106 | | Routine: clearglyphs ( index, limit ) | |
1107 | | | |
1108 | | Results: any glyphs downloaded into the imagen with a "chused" entry | |
1109 | | less than "limit" (and > 0) are marked for deletion and their | |
1110 | | space is "unrecorded" in totglyph. | |
1111 | | | |
1112 | | Bugs: clearglyphs does NOT check index to make sure the family exists | |
1113 | *----------------------------------------------------------------------------*/ | |
ef0f9059 | 1114 | |
6dded2dd DS |
1115 | clearglyphs(index, limit) |
1116 | int index; | |
1117 | int limit; | |
ef0f9059 | 1118 | { |
6dded2dd DS |
1119 | register fontset *f = &fontdata[index]; |
1120 | register int j; | |
1121 | ||
1122 | #ifdef DEBUGABLE | |
1123 | if (dbg) fprintf(stderr, "clear %d family of %d (%d/%d) on page %d\n", | |
1124 | index, limit, totglyph, maxglyph, pageno); | |
1125 | #endif | |
1126 | for (j = 0; j < CHARRAY; j++) { | |
1127 | if (f->chused[j] && f->chused[j] < limit) { | |
1128 | putc(ADELG, tf); | |
1129 | putint(index<<7 | j, tf); | |
1130 | totglyph -= glspace (&(f->glyph[j])); | |
1131 | f->chused[j] = 0; | |
ef0f9059 | 1132 | } |
6dded2dd | 1133 | } |
ef0f9059 DS |
1134 | } |
1135 | ||
ef0f9059 DS |
1136 | |
1137 | putint(n, f) | |
1138 | int n; | |
1139 | FILE *f; | |
1140 | { | |
1141 | putc(n >> 8, f); | |
1142 | putc(n & 0377, f); | |
1143 | } |