1 /* $Id: dvi2xx.c,v 2.5 1997/12/08 20:52:20 neumann Exp $ */
2 #define VERSION "dviljk (version 2.6p5)"
3 /*
4 #define DEBUGGS 1
5 */
6 /**********************************************************************
7 **************************** Intro *********************************
8 **********************************************************************
9 * This program translates TeX's DVI-Code into device dependent
10 * code of either the
11 *
12 * - HP-LASERJET+ and compatibles (PCL), or the
13 * - IBM 3812 pageprinter
14 *
15 * depending on the preprocessor switches specified before compilation.
16 * The program is written to run on a PC XT/AT/PS2 under MS-DOS. It can
17 * be compiled nicely with MSC Rel. 3.0-5.1 with option -AL (large memory
18 * model). Take care that in the CONFIG.SYS file the FILES parameter
19 * is set to 20; otherwise reduce MAXOPEN. 640K are recommended.
20 * I use link option /stack:9000 to increase runtime stack.
21 * It also works without modifications under Unix System V.
22 **********************************************************************
23 * Adapted for the PC: Gustaf Neumann
24 * +1002 stuff University of Economics
25 * +3812 support Augasse 2-6
26 * +Output buffering A-1090 Vienna, AUSTRIA
27 * +lpt binary support Tel. *43-222-340525/533
28 * +pk-89 stuff 773
29 * +pixelpaths
30 * +alternative directory structure
31 * +code compiles also under Unix V (HP/UX)
32 * (thx Michael Haberler)
33 * +huge characters (a character bigger than 32K)
34 * formats PXL1001 and PXL 1002
35 * (use: raster graphics)
36 * +reduction of the produced code
37 * +new options -X -Y -c -g
38 * +changed options -r (LJ now default from first to last)
39 * -x,-y (accept floats)
40 * +new option -z for LJ: print testpage containing
41 * pagecounter after printjob
42 * +try to overcome font limit on LJ (max 16 fonts/page) and
43 * (max 32 fonts/document):
44 * additional fonts are drawn as bitmap-
45 * graphics.
46 * +allows to set character close to the paperedge on LJ
47 * +gf-supprt (by Joe Kelsey joe@Pacer.com)
48 * gf.c and gf.h from mitdevices/dvi2ps
49 * +clipping of rules
50 * +OS/2 defines from Rutger Berns, apprmb@hheouh50.bitnet
51 *
52 * BITNET/EARN: NEUMANN at AWIWUW11
53 **********************************************************************
54 * fixes in LJ-mode: rule-drawing,
55 * characters with 127<=height<=200
56 * reset printer at beginning and end of each job
57 * better positioning of rules
58 * 30.1.89 (0.48) bug fixed for files containing >32 fonts (thanks A. Brosig),
59 * different font assignment heuristic
60 * fixes in 3812-mode: 14.juli 87 positioning of rastered characters
61 * better positioning of rules
62 * general fixes
63 * 1.1.88 page origin set to 1in/1in (hopefully everywhere)
64 * 22.7.88 reset y-position for each page-eject
65 * 15.1.89 fixing bug is space allocation for EmitFileName
66 * (thanks to Bernhard Simon)
67 * 15.3.91 (0.49) landscape support for lj ii p, lj iii and lj 2000
68 * fixing rule drawing problems for IBM3812 in landcape mode,
69 * 256 character clean (lj family and IBM3812)
70 * 5.5.91 (0.50) -DSEVENBIT added for older LJ-emulations
71 * -D1, -D2, -D-, -D1-, -D2- options added due to suggestions
72 * from Tomasz Wolniewicz
73 **********************************************************************
74 * Preprocessor switches:
75 * #define DEBUG for massive printing of trace information
76 * when -d cmdline option specified
77 * #define IBM3812 produce output for the IBM3812 pageprinter
78 * #define LJ produce output for the HP Laserjet+ or LJ II
79 * #define LJ2P produce output for the HP Laserjet LJ IIP, LJ III
80 * or LaserJet 2000
81 * #define LJ_LARGE_FONT_MEMORY large FONT Memory for LJ printer family
82 * #define DRAWGLYPH draws PK-Glyphs on stderr
83 * #define USEPXL use PXL and PK fonts rather than gf fonts
84 **********************************************************************
85 * Adapted for Acorn RISC OS computers: Andreas Dehmel
86 * Address: Andreas Dehmel
87 * Am Schorn 18
88 * 82327 Tutzing
89 * Germany
90 * dehmel@informatik.tu-muenchen.de
91 *
92 * Changes:
93 * - Split the whole thing up into smaller files
94 * - Rearranged certain parts of the output
95 * - If fonts are missing a taskobey file is created that
96 * contains MF commands to build the fonts.
97 * - SUPPORT FOR DIAGRAMS AS USED IN DVIVIEW!!!
98 * - Fixed problem of raster chars being scrambled when diagram
99 * printouts were on the same page.
100 * - Raster chars and fonts can now also be downloaded in
101 * compressed format; many thanks to Karl Berry!
102 */
103
104 #include "dvi2xx.h"
105 #include "tfm.h"
106
107 #ifdef SEVENBIT
108 #define VIS 33
109 #define VIS2 (VIS+32)
110 static unsigned char
VisChar(unsigned char c)111 VisChar(unsigned char c)
112 {
113 c &= 0xff;
114 if (c < VIS)
115 return ((unsigned char)(160 + c));
116 if (c < 128)
117 return (c);
118 if (c < (255 - VIS2))
119 return ((unsigned char)(VIS2 + c));
120 return (255);
121 }
122 #endif
123
124
125 /**********************************************************************/
126 /******************************* main *******************************/
127 /**********************************************************************/
128 int
main(int argc,char * argv[])129 main(int argc, char *argv[])
130 {
131 struct stack_entry { /* stack entry */
132 long4 h, v, w, x, y, z; /* what's on stack */
133 };
134 short command; /* current command */
135 long4 count[10]; /* the 10 counters at begining of each page*/
136 long4 cpagep = 0; /* current page pointer */
137 bool Emitting = _FALSE; /* outputting typsetting instructions? */
138 int i; /* command parameter; loop index */
139 int k; /* temporary parameter */
140 char n[STRSIZE]; /* command parameter */
141 int PassNo = 0; /* which pass over the DVI page are we on? */
142 bool SkipMode = _FALSE; /* in skip mode flag */
143 int sp = 0; /* stack pointer */
144 struct stack_entry stack[STACK_SIZE]; /* stack */
145 char SpecialStr[STRSIZE]; /* "\special" strings */
146 long4 val, val2; /* temporarys to hold command information */
147 long4 w = 0; /* current horizontal spacing */
148 long4 x = 0; /* current horizontal spacing */
149 long4 y = 0; /* current vertical spacing */
150 long4 z = 0; /* current vertical spacing */
151
152 #ifdef vms
153 extern noshare int errno;
154 extern noshare char *sys_errlist[];
155 #else
156 # if !defined (__riscos) && !defined (KPATHSEA)
157 extern char *sys_errlist[];
158 extern int errno;
159 # endif
160 #endif
161
162 /* Initialize pixel_files */
163 for (i = 0; i <= MAXOPEN; i++)
164 pixel_files[i].pixel_file_id = FPNULL;
165
166 x_origin = XDEFAULTOFF; /* x-origin in dots */
167 y_origin = YDEFAULTOFF; /* y-origin in dots */
168
169 setbuf(ERR_STREAM, NULL);
170 #ifdef KPATHSEA
171 kpse_set_program_name(argv[0], "dvilj");
172 kpse_set_program_enabled (kpse_pk_format, MAKE_TEX_PK_BY_DEFAULT, kpse_src_compile);
173 G_progname = kpse_program_name;
174 #else
175 G_progname = argv[0];
176 #endif
177 DecodeArgs(argc, argv);
178
179 #ifdef LJ4
180 if (CompressCharWidth < 0) {
181 switch(UseCompression) {
182 case 0: CompressCharWidth = COMPRESS_WIDTH0; break;
183 case 2: CompressCharWidth = COMPRESS_WIDTH2; break;
184 case 3: CompressCharWidth = COMPRESS_WIDTH3; break;
185 }
186 }
187 #endif
188
189 #ifdef KPATHSEA
190 kpse_init_prog("DVILJ", RESOLUTION, MFMODE, "cmr10");
191 #endif
192
193 power[0] = 1;
194 for (i = 1; i <= 31; i ++)
195 power[i] = power[i - 1] << 1;
196 gpower[0] = 0l;
197 for ( i = 1; i <= 32; i ++)
198 gpower[i] = gpower[i - 1] + power[i - 1];
199
200 if ((i = (int)NoSignExtend(dvifp, 1)) != PRE) {
201 Fatal("%s: PRE doesn't occur first--are you sure this is a DVI file?\n\n",
202 G_progname);
203 }
204 i = (int)SignExtend(dvifp, 1);
205 if (i != DVIFORMAT) {
206 Fatal( "%s: DVI format = %d, can only process DVI format %d files\n\n",
207 G_progname, i, DVIFORMAT);
208 }
209
210 if (*EmitFileName == '-') {
211 #ifdef RISC_USE_OSL
212 EMTO = BOUTOPEN("Vdu:");
213 #else
214 EMTO = stdout;
215 #endif
216 }
217 else
218 if ((EMTO = BOUTOPEN(EmitFileName)) == FPNULL)
219 #ifndef KPATHSEA
220 Fatal("opening output file: fopen(%s) : %s", EmitFileName,
221 #ifdef __riscos
222 "Cannot open"
223 #else
224 sys_errlist[errno]
225 #endif
226 )
227 #endif /* not KPATHSEA */
228 ;
229 #ifdef __riscos
230 xosfile_set_type(EmitFileName,0xff4);
231 #endif
232
233 /* If EmitFileName is "-", we use stdout. But it is by default open
234 in TEXT mode, and we need to switch it to binary, unless they are
235 writing to the screen (in which case they get what they deserve). */
236 if (O_BINARY && !isatty(fileno(outfp)))
237 (void)AssureBinary(fileno(outfp));
238
239 #ifdef TIMING
240 #ifdef BSD_TIME_CALLS
241 ftime(&timebuffer);
242 start_time = timebuffer.time + (float)(timebuffer.millitm) / 1000.0;
243 #else
244 gettimeofday(&Tp, NULL);
245 start_time = Tp.tv_sec + ((float)(Tp.tv_usec))/ 1000000.0;
246 #endif
247 #endif
248
249 /* it is important that these be the very first things output !!! */
250 if ( G_header )
251 my_CopyFile( HeaderFileName );
252
253 /*****************************/
254 /*for( i0=0; i0<nif; i0++ ) */ /* copy all included files */
255 /* my_CopyFile( Ifile[i0] ); */
256 /*****************************/
257
258 #ifdef IBM3812
259 PMPout(3, "\307\310\366"); /* unload all fonts and macros */
260 EMITWORD(MAX_PAGE_WIDTH);
261 EMITWORD(MAX_PAGE_HEIGHT);
262 if (Landscape)
263 PMPout(2, "\322\1");
264 #endif
265
266 #ifdef LJ
267 # ifdef LJ4
268 /* According to the PCL (p. 4-2) and PJL (p. 4-3) reference manuals, it is
269 critical that the UEL escape sequence (\e%-12345X) comes before the
270 reset sequence (\eE). According to PJL Reference Manual (p. 4-3) the
271 correct order is (1) UEL, (2) PJL commands, (3) Reset and PCL job, (4)
272 Reset, (5) UEL. */
273 if (my_ResetPrinter) {
274 EMIT1("\033%%-12345X"); /* UEL: Universal Exit Language */
275 EMIT2("@PJL SET RESOLUTION=%d\012",RESOLUTION);
276 EMIT1("@PJL SET PAGEPROTECT=OFF\012");
277 if (econoMode && LJ6)
278 EMIT1("@PJL SET ECONOMODE=ON\012");
279 /* The PJL ENTER LANGUAGE command must be the last PJL command before
280 PCL output starts. */
281 EMIT1("@PJL ENTER LANGUAGE=PCL\012");
282 EMIT1("\033E");
283 }
284 EMIT3("\033&u%dD\033*t%dR",RESOLUTION,RESOLUTION);
285 if (econoMode && !LJ6)
286 EMIT1("\033*v1T");
287 # else
288 if (my_ResetPrinter)
289 EMIT1("\033E");
290 # endif
291 # ifdef LJ2P
292 if (DuplexMode)
293 EMIT2("\033&l%dS", DuplexMode);
294 # endif
295 if (Landscape)
296 EMIT1("\033&l1O\033*rF");
297 if (pagesize>0) {
298 # ifndef vms
299 EMIT2("\033&l%hdaE\033&aL", pagesize);
300 # else
301 EMIT2("\033&l%daE\033&aL", pagesize);
302 # endif
303 } else
304 EMIT1("\033&lE\033&aL");
305
306 if (ncopies>1) {
307 # ifndef vms
308 EMIT2("\033&l%hdX", ncopies);
309 # else
310 EMIT2("\033&l%dX", ncopies);
311 # endif
312 }
313 #endif /* LJ */
314
315 if (DoublePage) {
316 StartPrintPages = PrintPages;
317 #ifdef IBM3812
318 Reverse = (bool)!Reverse; /* perverse and strange */
319 #endif
320 }
321
322 if (ManualFeed)
323 EMIT(outfp, "\033&l2H"); /* Manual Feed */
324
325 if (Reverse) {
326 #ifdef DEBUG
327 if (Debug)
328 fprintf(ERR_STREAM, "reverse\n");
329 #endif
330 ReadPostAmble(_TRUE);
331 FSEEK(dvifp, ppagep, SEEK_SET);
332 } else {
333 ReadPostAmble(_TRUE);
334 FSEEK(dvifp, 14l, SEEK_SET);
335 k = (int)NoSignExtend(dvifp, 1);
336 GetBytes(dvifp, n, k);
337 }
338 PassNo = 0;
339
340 while (_TRUE) {
341 command = (short) NoSignExtend(dvifp, 1);
342 #ifdef DEBUG
343 if (Debug)
344 fprintf(ERR_STREAM,"CMD@%ld:\t%d\n", (long) ftell(dvifp) - 1, command);
345 #endif
346 switch (command) {
347 case SET1:
348 case SET2:
349 case SET3:
350 case SET4:
351 val = NoSignExtend(dvifp, (int)command - SET1 + 1);
352 if (!SkipMode)
353 SetChar(val, command, PassNo, _TRUE,_FALSE);
354 break;
355 case SET_RULE:
356 val = NoSignExtend(dvifp, 4);
357 val2 = NoSignExtend(dvifp, 4);
358 if (Emitting)
359 SetRule(val, val2, 1);
360 break;
361 case PUT1:
362 case PUT2:
363 case PUT3:
364 case PUT4:
365 val = NoSignExtend(dvifp, (int)command - PUT1 + 1);
366 if (!SkipMode)
367 SetChar(val, command, PassNo, _TRUE,_FALSE);
368 break;
369 case PUT_RULE:
370 val = NoSignExtend(dvifp, 4);
371 val2 = NoSignExtend(dvifp, 4);
372 if (Emitting)
373 SetRule(val, val2, 0);
374 break;
375 case NOP:
376 break;
377 case BOP:
378 cpagep = FTELL(dvifp) - 1;
379 DEBUG_PRINT ("BOP for [");
380 for (i = 0; i <= 9; i++) {
381 count[i] = NoSignExtend(dvifp, 4);
382 DEBUG_PRINT1 ("%ld.", (long) count[i]);
383 }
384 DEBUG_PRINT1 ("] at %ld.\n", (long)cpagep);
385 ppagep = (long)NoSignExtend(dvifp, 4);
386 h = v = w = x = y = z = 0;
387 hh = vv = 0;
388 last_rx = last_ry = UNKNOWN;
389 sp = 0;
390 fontptr = NULL;
391 prevfont = NULL;
392 DoBop();
393 /*
394 fprintf(ERR_STREAM,"skimode %d, count %d, F %d, L %d\n",
395 (int)SkipMode,(int)count[0],(int)FirstPageSpecified,(int)LastPageSpecified);
396 */
397 SkipMode = (bool)((FirstPageSpecified && count[0] < FirstPage) ||
398 (LastPageSpecified && count[0] > LastPage ));
399 /*
400 fprintf(ERR_STREAM,"skimode %d, count %d, F %d, L %d\n",
401 (int)SkipMode,(int)count[0],(int)FirstPageSpecified,(int)LastPageSpecified);
402 */
403
404 if (DoublePage && !SkipMode) {
405 if (PassNo == 0) {
406 LastPtobePrinted = count[0];
407 if (!Reverse && (WouldPrint == 0)) {
408 if (count[0] == 0l) {
409 ZeroPage = _TRUE;
410 EvenPage = _FALSE;
411 }
412 else {
413 EvenPage = (bool)( (count[0]<0? labs(count[0])+1: count[0]) %2 == 0);
414
415 if (PrintEmptyPages && EvenPage && PageParity==1) {
416 WouldPrint ++;
417 if (PrintFirstPart) {
418 qfprintf(ERR_STREAM,"[EvenPage] ");
419 FormFeed();
420 }
421 }
422 }
423 }
424 WouldPrint ++;
425 /*
426 fprintf(ERR_STREAM, "doublepage %d, page parity = %d, 1=%d 2=%d, Reverse %d, WouldPrint %d, fpZ %d\n",
427 (int)DoublePage, (int)PageParity,(int)PrintFirstPart,(int)PrintSecondPart,
428 (int)Reverse, (int)WouldPrint, (int)ZeroPage);
429 */
430 }
431 if (!PrintFirstPart && PageParity==1) {
432 if (count[0] == 0) {
433 ZeroPage = _TRUE;
434 EvenPage = _FALSE;
435 }
436 SkipMode = _TRUE;
437 }
438 else {
439 /*
440 fprintf(ERR_STREAM,"FirstPart\n count %d, mod %d, pp %d\n",(int)count[0],(int)count[0]%2,PageParity);
441 */
442 SkipMode =
443 (bool)(PageParity != (short)((count[0]<0 ?
444 labs(count[0])+1 : count[0])%2));
445 if (count[0] == 0) SkipMode = (bool)!SkipMode;
446 }
447
448 }
449 Emitting = (bool)((PassNo != 0) && !SkipMode);
450 /*
451 fprintf(ERR_STREAM,"Emitting= %d, PassNo=%d, SkipMode = %d\n",(int)Emitting,(int)PassNo,(int)SkipMode);
452 */
453 if ( !SkipMode ) {
454 if (PassNo == 0)
455 qfprintf(ERR_STREAM,"[%ld", (long)count[0]);
456 }
457 break;
458 case EOP:
459 if ( !SkipMode ) {
460 if (PassNo == 0) {
461 /* start second pass on current page */
462 FSEEK(dvifp, cpagep, SEEK_SET);
463 PassNo = 1;
464 #ifdef DEBUG
465 if (Debug)
466 fprintf(ERR_STREAM,"\nStarting second pass\n");
467 #endif
468
469 } else {
470 /* end of second pass, and of page processing */
471
472 last_rx = last_ry = UNKNOWN;
473 FormFeed();
474 ++ndone;
475
476 qfprintf(ERR_STREAM,"] ");
477 if ( (ndone % 10) == 0 )
478 qfprintf(ERR_STREAM,"\n");
479
480 if (DoublePage) --PrintPages;
481 if (--PrintPages < 1) AllDone(_TRUE);
482 PassNo = 0;
483 }
484 } else
485 PassNo = 0;
486
487 if ( PassNo == 0 && Reverse ) {
488 if ( ppagep > 0 )
489 FSEEK(dvifp, ppagep, SEEK_SET);
490 else {
491 if (DoublePage && !SkipMode)
492 ZeroPage = (bool)(count[0] == 0);
493
494 if (ZeroPage)
495 EvenPage = _FALSE;
496 else
497 EvenPage = (bool)((int)LastPtobePrinted%2 == 0);
498
499 AllDone(_FALSE);
500 }
501 }
502 break;
503 case PUSH:
504 if (sp >= STACK_SIZE)
505 Fatal("stack overflow");
506 stack[sp].h = h;
507 stack[sp].v = v;
508 stack[sp].w = w;
509 stack[sp].x = x;
510 stack[sp].y = y;
511 stack[sp].z = z;
512 sp++;
513 break;
514 case POP:
515 --sp;
516 if (sp < 0)
517 Fatal("stack underflow");
518 h = stack[sp].h;
519 v = stack[sp].v;
520 w = stack[sp].w;
521 x = stack[sp].x;
522 y = stack[sp].y;
523 z = stack[sp].z;
524 last_rx = last_ry = UNKNOWN;
525 break;
526 case RIGHT1:
527 case RIGHT2:
528 case RIGHT3:
529 case RIGHT4:
530 val = SignExtend(dvifp, (int)command - RIGHT1 + 1);
531 if (Emitting)
532 MoveOver(val);
533 break;
534 case W0:
535 if (Emitting)
536 MoveOver(w);
537 break;
538 case W1:
539 case W2:
540 case W3:
541 case W4:
542 w = SignExtend(dvifp, (int)command - W1 + 1);
543 if (Emitting)
544 MoveOver(w);
545 break;
546 case X0:
547 if (Emitting)
548 MoveOver(x);
549 break;
550 case X1:
551 case X2:
552 case X3:
553 case X4:
554 x = SignExtend(dvifp, (int)command - X1 + 1);
555 if (Emitting)
556 MoveOver(x);
557 break;
558 case DOWN1:
559 case DOWN2:
560 case DOWN3:
561 case DOWN4:
562 val = SignExtend(dvifp, (int)command - DOWN1 + 1);
563 if (Emitting)
564 MoveDown(val);
565 break;
566 case Y0:
567 if (Emitting)
568 MoveDown(y);
569 break;
570 case Y1:
571 case Y2:
572 case Y3:
573 case Y4:
574 y = SignExtend(dvifp, (int)command - Y1 + 1);
575 if (Emitting)
576 MoveDown(y);
577 break;
578 case Z0:
579 if (Emitting)
580 MoveDown(z);
581 break;
582 case Z1:
583 case Z2:
584 case Z3:
585 case Z4:
586 z = SignExtend(dvifp, (int)command - Z1 + 1);
587 if (Emitting)
588 MoveDown(z);
589 break;
590 case FNT1:
591 case FNT2:
592 case FNT3:
593 case FNT4:
594 k = NoSignExtend(dvifp, (int) command - FNT1 + 1);
595 if (!SkipMode) {
596 SetFntNum(k, Emitting);
597 }
598 break;
599 case XXX1:
600 case XXX2:
601 case XXX3:
602 case XXX4:
603 k = (int)NoSignExtend(dvifp, (int)command - XXX1 + 1);
604 GetBytes(dvifp, SpecialStr, k);
605 if (Emitting)
606 DoSpecial(SpecialStr, k);
607 break;
608 case FNT_DEF1:
609 case FNT_DEF2:
610 case FNT_DEF3:
611 case FNT_DEF4:
612 k = (int)NoSignExtend(dvifp, (int)command - FNT_DEF1 + 1);
613 SkipFontDef(); /* SkipFontDef(k); */
614 break;
615 case PRE:
616 Fatal("PRE occurs within file");
617 break;
618 case POST:
619 AllDone(_FALSE);
620 PassNo = 0;
621 break;
622 case POST_POST:
623 Fatal("POST_POST with no preceding POST");
624 break;
625 default:
626 if (command >= FONT_00 && command <= FONT_63) {
627 if (!SkipMode)
628 SetFntNum((long4)command - FONT_00, Emitting);
629 } else if (command >= SETC_000 && command <= SETC_127) {
630 if (!SkipMode) {
631 SetString(command, PassNo);
632 }
633 } else
634 Fatal("%d is an undefined command", command);
635 break;
636 }
637 } /* while _TRUE */
638 }
639
640
641
642
643
644
645 /*------------------------ begin dviIO.c ----------------------------------*/
646
647 /* The following functions buffer input/output during my_CopyFile / CopyHPFile
648 Write functions are only needed if RISC_BUFFER is defined; otherwise output
649 is not buffered. */
650
651 /* read a buffered byte */
652 char
b_read(FILEPTR spfp)653 b_read(FILEPTR spfp)
654 {
655 if (biact >= binumber) {
656 #ifdef RISC_USE_OSL
657 binumber = BUFFSIZE - read_multi(buffin,1,BUFFSIZE,spfp);
658 #else
659 binumber = read_multi(buffin,1,BUFFSIZE,spfp);
660 #endif
661 biact = 0;
662 }
663 return binumber == 0 ? 0 : buffin[biact++];
664 }
665
666 #ifdef RISC_BUFFER
667 void
b_write(FILEPTR spfp,char c)668 b_write(FILEPTR spfp, char c) /* write a buffered byte */
669 {
670 if (boact >= BUFFSIZE) {
671 write_multi(buffout,1,BUFFSIZE,spfp);
672 boact = 0;
673 }
674 buffout[boact++] = c;
675 }
676
677 void
b_wrtmult(FILEPTR spfp,char * buf,int len)678 b_wrtmult(FILEPTR spfp, char *buf, int len) /* write a sequence of bytes to the output buffer */
679 {
680 register int i;
681
682 if ((len > (BUFFSIZE - boact)) || (len >= (BUFFSIZE/4))) {
683 write_multi(buffout,1,boact,spfp);
684 /* Copy only small blocks; large ones are written directly */
685 if (len < (BUFFSIZE/4)) {
686 for (i = 0; i<len; i++)
687 buffout[i] = buf[i];
688 boact = len;
689 } else {
690 write_multi(buf,1,len,spfp);
691 boact = 0;
692 }
693 }
694 else {
695 for (i = 0; i<len; i++)
696 buffout[boact++] = buf[i];
697 }
698 }
699
700 /* flush the output buffer */
701 void
b_oflush(FILEPTR spfp)702 b_oflush(FILEPTR spfp)
703 {
704 write_multi(buffout,1,boact,spfp);
705 boact = 0;
706 }
707 #endif
708 /* end of buffer handling functions */
709
710
711 /*-->my_CopyFile*/ /* copy a file straight through to output */
712 /*********************************************************************/
713 /***************************** my_CopyFile ***************************/
714 /*********************************************************************/
715 void
my_CopyFile(const char * str)716 my_CopyFile(const char *str )
717 {
718 FILEPTR spfp;
719 int todo;
720
721 if ( (spfp = BINOPEN(str)) == FPNULL ) {
722 if ( errno != EACCES || ! kpse_tex_hush("readable") ) {
723 Warning("Unable to open file %s (errno=%d), skipping inclusion",
724 str, errno);
725 }
726 return;
727 }
728 qfprintf(ERR_STREAM," [%s", str);
729 #ifdef RISC_BUFFER
730 b_oflush(outfp);
731 #endif
732 do {
733 todo = read_multi(buffin,1,BUFFSIZE,spfp);
734 write_multi(buffin,1,todo,outfp);
735 }
736 while (todo == BUFFSIZE);
737
738 BCLOSE(spfp);
739 qfprintf(ERR_STREAM,"]");
740 }
741
742
743 /*-->CopyHPFile*/ /* copy a HP file to output removing unwanted control codes*/
744 /*********************************************************************/
745 /***************************** CopyHPFile ******************************/
746 /*********************************************************************/
747 static int
getnum(FILEPTR spfp,char * t,char * numstr)748 getnum(FILEPTR spfp, char *t, char *numstr)
749 {
750 int count=0;
751 for (*t = (char)b_read(spfp); *t<0x40; *t = (char)b_read(spfp))
752 numstr[count++] = *t;
753 numstr[count] = 0;
754 return atoi(numstr);
755 }
756
757 static void
setOffset(char dir,char sign,int pos)758 setOffset(char dir, char sign, int pos)
759 {
760 if ((sign == '+' || sign == '-') && pos > 0 ) {
761 EMIT4("\033*p%c%d%c",sign,pos,dir);
762 #ifdef DEBUGGS
763 fprintf(stderr, "relative: *p%c%d%c\n", sign, pos, dir);
764 #endif
765 } else if (pos>0) {
766 EMIT3("\033*p%d%c",pos,dir);
767 #ifdef DEBUGGS
768 fprintf(stderr, "absolute: *p%d%c\n", pos, dir);
769 #endif
770 if (dir == 'X')
771 last_rx = pos;
772 else
773 last_ry = pos;
774 } else {
775 /*EMIT3("\033*p%d%c",pos,dir);*/
776 #ifdef DEBUGGS
777 fprintf(stderr, "Relative: *p%d%c\n", pos, dir);
778 #endif
779 }
780 }
781
782
783 void
CopyHPFile(char * str)784 CopyHPFile(char *str )
785 {
786 FILEPTR spfp;
787 char t,numstr[20];
788 int count,miny,minx,num;
789
790 if ( (spfp = BINOPEN(str)) == FPNULL ) {
791 if ( errno != EACCES || ! kpse_tex_hush("readable") ) {
792 Warning("Unable to open file %s (errno=%d), skipping inclusion",
793 str, errno);
794 }
795 return;
796 }
797 minx = 32767; /* Set to a high value initially */
798 miny = 32767;
799
800 /* Pass through the input PCL file twice. The first time find the
801 smallest x- and y-offsets so that they can be subtracted out when
802 sending positioning commands later. The second pass strips the
803 unwanted commands from the input file and outputs the rest */
804
805 /* reset the input buffer */
806 binumber = 0;
807 biact = 0;
808
809 qfprintf(ERR_STREAM," [%s", str);
810 /* Test for !EOF now ((binumber == BUFFSIZE) || (biact < binumber)) */
811 do {
812 t = (char)b_read(spfp);
813 if (t==0x1B) { /* Find the escape character */
814 t = (char)b_read(spfp);
815 if (t==0x2A) { /* This indiactes the start of a graphics command */
816 t = (char)b_read(spfp);
817 switch(t) {
818 case('p'):
819 /* These are the graphics positioning commands */
820 /* Find the smallest x and y offsets */
821 num = getnum(spfp, &t, numstr);
822
823 /* Take into account the possible different ordering */
824 /* of the commands (x first, y first) */
825
826 if (t=='Y' || t=='y') {
827 if (numstr[0]!='+' && numstr[0]!='-' && num<miny)
828 miny = num;
829 if (t=='y') {
830 num = getnum(spfp, &t, numstr);
831 if (numstr[0]!='+' && numstr[0]!='-' && num<minx)
832 minx = num;
833 }
834 }
835 if (t=='X' || t=='x') {
836 if (numstr[0]!='+' && numstr[0]!='-' && num<minx)
837 minx = num;
838
839 if (t=='x') {
840 num = getnum(spfp, &t,numstr);
841 if (numstr[0]!='+' && numstr[0]!='-' && num<miny)
842 miny = num;
843 }
844 }
845 break;
846 /* Ignore all other commands for the moment - just read them */
847 case(0x74):
848 for (t = (char)b_read(spfp); t != 0x52; t = (char)b_read(spfp));
849 break;
850
851 case(0x72):
852 for (t = (char)b_read(spfp); ((t< 0x40)||(t>0x60)); t = (char)b_read(spfp));
853 break;
854
855 case(0x62):
856 num = 0;
857 count = 0;
858 /* Read in the correct number of bytes of raster graphics */
859 /* so that we don't get commands and raster graphics confused */
860
861 for (t = (char)b_read(spfp); ((t<0x40)||(t>=0x60)); t = (char)b_read(spfp))
862 numstr[count++]=t;
863 numstr[count]=0;
864 if (t==0x4D)
865 for(t = numstr[count = 0]; t!=0; t = numstr[++count]);
866 if (t==0x57) {
867 for(t = numstr[count = 0]; t!=0; t = numstr[++count]);
868 for(count = atoi(numstr); count>0; count--)
869 t = (char)b_read(spfp);
870 }
871 break;
872
873 case(0x63):
874 for (t = (char)b_read(spfp); t< 0x40 || t>0x60; t = (char)b_read(spfp));
875 break;
876
877 default:
878 break;
879 }
880 }
881 }
882 }
883 while ((binumber == BUFFSIZE) || (biact < binumber));
884
885 /* reset input buffer, to read it anew */
886 if ( FSEEK(spfp, 0L, SEEK_SET) == -1 ) {
887 Warning(" could not seek to start of file (errno=%d), abandon %s inclusion",
888 errno, str);
889 return;
890 }
891 binumber = 0;
892 biact = 0;
893
894
895 /* Pass through the input file again but this time output the */
896 /* retained PCL commands */
897 #ifdef DEBUGGS
898 fprintf(stderr,"\nminx=%d, miny=%d, xg=%d, yg=%d\n",
899 minx, miny, x_goffset, y_goffset);
900 #endif
901 do {
902 t = (char)b_read(spfp);
903 if (t==0x1B) {
904 t = (char)b_read(spfp);
905 if (t==0x2A) {
906 t = (char)b_read(spfp);
907 switch(t) {
908 case('p'):
909 num = getnum(spfp, &t,numstr);
910 if (t == 'Y' || t == 'y') {
911 if (numstr[0]!='+' && numstr[0]!='-') {
912 /* Subtract the minimum offset found in first pass */
913 /* and add in the current vertical offset */
914 setOffset('Y',numstr[0],
915 num-miny + (int)PIXROUND(v,vconv) + y_goffset);
916 } else {
917 setOffset('Y',numstr[0], num);
918 }
919
920 if (t == 'y') {
921 num = getnum(spfp, &t,numstr);
922 if (numstr[0]!='+' && numstr[0]!='-') {
923 /*Add in correct horizontal offset */
924 setOffset('X',numstr[0],
925 num - minx + (int)PIXROUND(h,hconv) + x_goffset);
926 } else if (num>=0) {
927 setOffset('X',numstr[0], num);
928 }
929 }
930 }
931
932 if (t=='X' || t=='x') {
933 if (numstr[0]!='+' && numstr[0]!='-') {
934 /*Add in the correct horizontal offset*/
935 setOffset('X',numstr[0],
936 num - minx + (int)PIXROUND(h,hconv) + x_goffset);
937 } else {
938 setOffset('X',numstr[0], num);
939 }
940
941 if (t=='x') {
942 num = getnum(spfp, &t,numstr);
943 if (numstr[0]!='+' && numstr[0]!='-') {
944 /* Subtract the minimum offset found in first pass */
945 /* and add in the current vertical offset */
946 setOffset('Y',numstr[0],
947 num-miny + (int)PIXROUND(v,vconv) + y_goffset);
948 } else {
949 setOffset('Y',numstr[0], num);
950 }
951 }
952 }
953 break;
954
955 case(0x74):
956 /* Set the Raster resolution */
957 EMIT1("\033*t");
958 for (t = (char)b_read(spfp); t != 0x52; t = (char)b_read(spfp))
959 EMITC(t);
960 EMITC(t);
961 break;
962
963 case(0x72):
964 /* Raster Graphics commands such as start */
965 EMIT1("\033*r");
966 for (t = (char)b_read(spfp); t< 0x40 || t>0x60; t = (char)b_read(spfp))
967 EMITC(t);
968 EMITC(t);
969 break;
970
971 case(0x62):
972 /* Transfer the correct number of bytes of raster graphics */
973 EMIT1("\033*b");
974 num = 0;
975 count = 0;
976 for (t = (char)b_read(spfp); t<0x40 || t>=0x60; t = (char)b_read(spfp))
977 numstr[count++] = t;
978 numstr[count] = 0;
979 if (t==0x4D) {
980 for (t = numstr[count = 0]; t!=0; t = numstr[++count])
981 EMITC(t);
982 EMIT1("M");
983 }
984 if (t==0x57) {
985 for(t = numstr[count = 0]; t!=0; t = numstr[++count])
986 EMITC(t);
987 EMIT1("W");
988 for (count = atoi(numstr); count>0; count--) {
989 t = (char)b_read(spfp);
990 EMITC(t);
991 }
992 }
993 break;
994
995 case(0x63):
996 /* Rectangular draw commands */
997 EMIT1("\033*c");
998 for (t = (char)b_read(spfp); t<0x40 || t>0x60;
999 t = (char)b_read(spfp))
1000 EMITC(t);
1001 EMITC(t);
1002 break;
1003
1004 default:
1005 break;
1006 }
1007 }
1008 }
1009 }
1010 while ((binumber == BUFFSIZE) || (biact < binumber));
1011
1012 BCLOSE(spfp);
1013 qfprintf(ERR_STREAM,"]");
1014 }
1015
1016 /* This function closes all open files */
1017 void
CloseFiles(void)1018 CloseFiles(void)
1019 {
1020 struct font_entry *fe;
1021 FILEPTR f;
1022
1023 /* First input/output files */
1024 if (outfp != FPNULL) {
1025 #ifdef RISC_BUFFER
1026 b_oflush(outfp);
1027 #endif
1028 BCLOSE(outfp);
1029 }
1030 if (dvifp != FPNULL) {
1031 BCLOSE(dvifp);
1032 }
1033 #ifdef __riscos
1034 if (metafile != FPNULL) {
1035 BCLOSE(metafile);
1036 }
1037 #endif
1038 /* Now all open font files */
1039 fe = hfontptr;
1040 while (fe != NULL) {
1041 f = fe->font_file_id;
1042 if ((f != FPNULL) && (f != NO_FILE)) {
1043 BCLOSE(f);
1044 }
1045 fe = fe->next;
1046 }
1047 }
1048
1049 /*-->NoSignExtend*/
1050 /**********************************************************************/
1051 /*************************** NoSignExtend ***************************/
1052 /**********************************************************************/
1053 long4
NoSignExtend(FILEPTR fp,register int n)1054 NoSignExtend(FILEPTR fp, register int n)
1055 {
1056 long4 x = 0; /* number being constructed */
1057 unsigned char h;
1058 while (n--) {
1059 x <<= 8;
1060 read_byte(fp,h);
1061 x |= h;
1062 }
1063 /* fprintf(stderr,"[%ld] ",(long)x);*/
1064 return(x);
1065 }
1066
1067
1068 #ifndef ARITHMETIC_RIGHT_SHIFT
1069 long4 signTab[5] = {0,0x00000080,0x00008000,0x00800000,0x00000000};
1070 long4 extendTab[5] = {0,~0^0xff,~0^0xffff,~0^0xffffff,~0^0xffffffff};
1071 #endif
1072
1073 /*-->SignExtend*/
1074 /**********************************************************************/
1075 /**************************** SignExtend ****************************/
1076 /**********************************************************************/
1077 long4
SignExtend(FILEPTR fp,register int n)1078 SignExtend(FILEPTR fp, register int n)
1079 {
1080 int n1; /* number of bytes */
1081 long4 x; /* number being constructed */
1082 unsigned char h;
1083 #ifdef SIGN_DEBUG
1084 long4 x0; /* copy of x */
1085 #endif
1086 read_byte(fp,h);
1087 x = h; /* get first (high-order) byte */
1088 n1 = n--;
1089 while (n--) {
1090 x <<= 8;
1091 read_byte(fp,h);
1092 x |= h;
1093 }
1094 /*
1095 * NOTE: This code assumes that the right-shift is an arithmetic, rather
1096 * than logical, shift which will propagate the sign bit right. According
1097 * to Kernighan and Ritchie, this is compiler dependent!
1098 */
1099
1100 #ifdef SIGN_DEBUG
1101 x0 = x;
1102 #endif
1103
1104 #ifdef ARITHMETIC_RIGHT_SHIFT
1105 x <<= 32 - 8 * n1;
1106 x >>= 32 - 8 * n1; /* sign extend */
1107 #else
1108 if (x & signTab[n1]) x |= extendTab[n1];
1109 #endif
1110
1111 #ifdef SIGN_DEBUG
1112 fprintf(ERR_STREAM,"\tSignExtend(fp,%d)=%lX, was=%lX,%d\n",
1113 n1,x,x0,x0&signTab[n1]);
1114 #endif
1115
1116 #ifdef DEBUG
1117 if (Debug > 1)
1118 fprintf(ERR_STREAM,"\tSignExtend(fp,%d)=%lX\n", n1, x);
1119 #endif
1120 return(x);
1121 }
1122
1123
1124 #ifdef IBM3812
1125 /*-->PMPout*/
1126 /*****************************************************************************/
1127 /* This routine produces the PMP-envelopes for the 3812. Its semantics are:
1128
1129 first arg == 0 ... flush buffer
1130 first arg == -1 ... number of bytes specified in the second argument
1131 have to be continuous, that is they must not
1132 be disrupted by ENTER PMP etc.
1133 first arg > 0 output first arg bytes
1134
1135 If arg2 > OUTBUFSIZE ... flush buffer,
1136 switch to unbuffered mode
1137 (dont't collect PMP commands)
1138 If arg2+bufferpointer > OUTBUFSIZE ... flush buffer,
1139 block will fit into buffer
1140 otherwise ..... block will fit into buffer
1141
1142 Buffering is done to reduce the ENTER PMP-commands. Initially
1143 the 3812 is in PC-ASCII mode. In order to issue a PMP-command it is
1144 necessary to enter PMP mode. The ENTER-PMP-command contains the
1145 number of bytes that will be interpreted as PMP-commands. In the
1146 most naive approach for each primitive command (eg. set cursor) you
1147 have to produce a seperate ENTER-PMP-envelope (5 bytes). It is
1148 favourable to collect as many PMP commands as possible in one envelope. */
1149 /*****************************************************************************/
1150 void
PMPout(int l,char * s)1151 PMPout(int l, char *s)
1152 {
1153 static char buffer[OUTBUFSIZE];
1154 static unsigned short bp = 0; /* range 0..OUTBUFSIZE */
1155 static long4 continuous = 0l;
1156 static bool buffered = _TRUE;
1157
1158 if (l == 0) {
1159 if (bp == 0)
1160 return;
1161 EMIT3("\033[C%c%c", (unsigned char)(bp & 0xFF), (unsigned char)(bp >> 8));
1162 EMITB((int)bp, buffer);
1163 bp = 0;
1164 return;
1165 }
1166 if (l == -1) {
1167 continuous = (long4)s;
1168 if (continuous + (long4)bp + 5l > (long4)OUTBUFSIZE)
1169 PMPflush;
1170 buffered = (bool)((continuous + 5l <= (long4)OUTBUFSIZE));
1171 if (!buffered) {
1172 EMIT3("\033[C%c%c", (unsigned char)(continuous & 0xFF),
1173 (unsigned char)((continuous >> 8) & 0xFF));
1174 }
1175 return;
1176 }
1177 if (buffered) {
1178 register int i;
1179 if ( ((long4)l + bp) > OUTBUFSIZE)
1180 PMPflush;
1181 for (i = 0; i < l; i++)
1182 buffer[bp+i] = s[i];
1183 bp += (unsigned short)l;
1184 } else {
1185 EMITB((int)l, s);
1186 buffered = (bool)((continuous -= (long4)l) <= 0);
1187 }
1188 }
1189
1190
1191 void
PMPoutC(char c)1192 PMPoutC(char c)
1193 {
1194 PMPout(1, &c);
1195 }
1196 #endif /* IBM3812 */
1197
1198
1199 #ifdef MSC5
1200 /*-->AssureBinary*/
1201 /**********************************************************************/
1202 /*************************** AssureBinary *****************************/
1203 /**********************************************************************/
1204 /* This procedure is both DOS AND MSC dependent. The MSC file open on */
1205 /* a device ignores the 'binary' of the "wb" parameter and opens the */
1206 /* file in ascii mode. This procedure sets the file f to binary mode */
1207 /* if it is connected to a device that is not console input or output */
1208 /* or the null device. For other operating systems this routine is */
1209 /* useless. (Background: MSDOS 3.2 Technical Reference upd 1 pg 6-137 */
1210 /**********************************************************************/
1211 void
AssureBinary(FILEPTR f)1212 AssureBinary(FILEPTR f)
1213 {
1214 union REGS regs; /* registers for bios call */
1215
1216 regs.h.ah = (unsigned char) 0x44; /* IOCTL */
1217 regs.h.al = (unsigned char) 0x00; /* get device information */
1218 regs.x.bx = (unsigned int) fileno(f); /* handle from MSC */
1219 intdos(®s, ®s); /* call DOS interrupt */
1220 /* ---> result in DX */
1221
1222 if ( (regs.h.dl & 0x80) /* file handle points to a device */
1223 && !(regs.h.dl & 0x07) ) { /* neither console i/o or null */
1224
1225 regs.h.dl |= 0x20; /* set BINARY bit in device info */
1226 regs.h.ah = (unsigned char) 0x44; /* IOCTL */
1227 regs.h.al = (unsigned char) 0x01; /* set device information */
1228 regs.x.bx = (unsigned int) fileno(f); /* handle from MSC */
1229 regs.h.dh = (unsigned char) 0x00; /* clear DH */
1230 intdos(®s, ®s); /* call DOS interrupt */
1231 }
1232 }
1233 #endif /* MSC5 */
1234
1235 /*------------------------ end dviIO.c ----------------------------------*/
1236
1237 /*------------------------ begin dvichars.c -----------------------------*/
1238 /*-->EmitChar*/
1239 /**********************************************************************/
1240 /**************************** EmitChar ******************************/
1241 /**********************************************************************/
1242 void /* output a character bitmap */
EmitChar(long4 c,struct char_entry * ce)1243 EmitChar(long4 c, struct char_entry *ce)
1244 {
1245 register int i;
1246 register unsigned char *sl;
1247 unsigned short nbpl, nwpl;
1248 long total;
1249 #ifdef LJ
1250 unsigned char cnv_buffer[10];
1251 #endif
1252
1253
1254 #ifdef LJ
1255 /*
1256 printf("Emit character %c(%d) id=%d, yoff=%d[%d], w=%d[%d], h=%d[%d]\n",
1257 (char)c,(int)c,
1258 fontptr->plusid,
1259 ce->yOffset, fontptr->max_yoff,
1260 ce->width, fontptr->max_width,
1261 ce->height, fontptr->max_height
1262 );
1263 */
1264 #endif
1265
1266
1267
1268 if ( fontptr->ncdl == 0 ) {
1269 #ifdef IBM3812
1270 used_fontstorage += 1028;
1271 #endif
1272 #ifdef LJ
1273 if (fontptr->max_width == 0) { /* we have no realistic values */
1274 fontptr->max_yoff = CHAR_HEIGTH_LARGE;
1275 fontptr->max_width = CHAR_WIDTH_LARGE;
1276 fontptr->max_height = CHAR_HEIGTH_LARGE*2;
1277 }
1278
1279 /* open font dict before first char, set active font */
1280 INT_ASCII(cnv_buffer,fontptr->plusid);
1281 # ifdef LJ4
1282 EMIT2("\033*c%sD\033)s68W", cnv_buffer);
1283 EMITB(6, "\0\104\024\2\0\0");
1284 # else
1285 EMIT2("\033*c%sD\033)s64W", cnv_buffer); /* changed 26 to 64 (khk) */
1286 EMITWORD( 64 ); /* Font descriptor size */
1287 EMITC((char) 0 ); /* res0 (byte) */
1288 # ifdef SEVENBIT
1289 EMITC((char) 1); /* Font Type */
1290 # else
1291 EMITC((char) 2); /* Font Type */
1292 # endif /* SEVENBIT */
1293 EMITWORD( 0 ); /* res1 */
1294 # endif /* LJ 4 */
1295 EMITWORD( fontptr->max_yoff); /* Baseline Distance */
1296 EMITWORD( fontptr->max_width); /* Cell Width */
1297 EMITWORD( fontptr->max_height); /* Cell Height */
1298 EMITC((char) 0); /* Orientation */
1299 EMITC((char) 1); /* Spacing */
1300 EMITWORD( 277 ); /* Symbol Set */
1301 EMITWORD( 1024 ); /* Pitch */
1302 EMITWORD( 1024 ); /* Height */
1303 EMITWORD( 0 ); /* xHeight */
1304 EMITC((char) 0); /* Width Type */
1305 EMITC((char) 0); /* Style */
1306 EMITC((char) 0); /* Stroke Weight */
1307 EMITC((char) 0); /* Typeface */
1308 EMITC((char) 0); /* res2 (byte) */
1309 EMITC((char) 0); /* Serif Style */
1310 EMITWORD( 0 ); /* res 3 */
1311 EMITC((char) 0); /* Underline Distance */
1312 EMITC((char) 0); /* Underline Height */
1313 EMITWORD( 0 ); /* Text Height */
1314 EMITWORD( 0 ); /* Text Width */
1315 EMITWORD( 0 ); /* res4 */
1316 EMITWORD( 0 ); /* res5 */
1317 EMITC((char) 0); /* Pitch Extended */
1318 EMITC((char) 0); /* Height Extended */
1319 EMITWORD( 0 ); /* res6 */
1320 EMITWORD( 0 ); /* res7 */
1321 EMITWORD( 0 ); /* res8 */
1322 EMITB(16," ");
1323 # ifdef LJ4
1324 EMITB(4 ,"\2\130\2\130");
1325 # endif
1326 EMIT1("\033*c4F");
1327 #endif /* LJ */
1328 }
1329 if ( fontptr != prevfont ) { /* because this isn't done on pass 0 */
1330 #ifdef LJ
1331 INT_ASCII(cnv_buffer,fontptr->plusid);
1332 EMIT2("\033(%sX", cnv_buffer);
1333 #endif
1334 prevfont = fontptr;
1335 }
1336
1337 #ifdef USEPXL
1338 if (fontptr->id == pk89) {
1339 nwpl = 0; /* initialize variable */
1340 nbpl = ((int)(ce->width) + 7) >> 3;
1341 total = (long)ce->height * nbpl;
1342 } else if (fontptr->id == id1002) {
1343 nwpl = 0; /* initialize variable */
1344 nbpl = ((int)(ce->width) + 7) >> 3;
1345 total = (long)ce->height * nbpl;
1346 } else if (fontptr->id == id1001) {
1347 nwpl = ((int)(ce->width) + 31) >> 5;
1348 nbpl = ((int)(ce->width) + 7) >> 3;
1349 total = (long)ce->height * nbpl;
1350 } else {
1351 /* should never be necessary */
1352 nwpl = 0;
1353 nbpl = 0;
1354 total = 0;
1355 }
1356 #else
1357 nbpl = (num_cols + 7) >> 3;
1358 total = num_rows * nbpl;
1359 #endif
1360 /***************************************************************
1361 if ( ((char) c == 'i') && (fontptr->plusid == 0)) {
1362 long j;
1363 fprintf(ERR_STREAM, "cols=%ld, ncols=%ld\n",(long)nwpl,(long)nbpl);
1364
1365 fprintf(ERR_STREAM, "%ld Bytes:->",(long)total);
1366 for (j=0; j<total; j++) {
1367 char *ch; char ic;
1368 ch = (char *)(ce->where.address.pixptr);
1369 ic = *(ch+j);
1370 fprintf(ERR_STREAM,"%X.",ic);
1371 }
1372 fprintf(ERR_STREAM,"<- Now Emitting\n");
1373 }
1374 ***************************************************************/
1375 #ifdef USEPXL
1376 #ifdef IBM3812
1377 if ((short)(ce->height) - ce->yOffset > 55) {
1378 ce->yyOffset = (short) ce->height - ce->yOffset;
1379 ce->yOffset = (short) ce->height;
1380 } else {
1381 ce->yyOffset = (short) 0;
1382 }
1383 #endif
1384 #ifdef LJ
1385 ce->yyOffset = (short) 0;
1386 #endif
1387 #endif
1388
1389 /* ce->cw = (long4)(((double)ce->tfmw / (double)hconv) +0.5); */
1390 /* set active font to nn, load font pattern xx ... */
1391 #ifdef IBM3812
1392 PMPcont(total + 9);
1393 # ifdef USEPXL
1394 sprintf(PMPformat, "\323%c\360%c%c%c",
1395 (unsigned char)fontptr->plusid,
1396 (unsigned char)VisChar((char)c),
1397 (unsigned char)ce->height,
1398 (unsigned char)ce->width);
1399 PMPout(6, PMPformat);
1400 PMPoutC((char)(-(ce->xOffset)));
1401 PMPoutC((char)(ce->cw - (-ce->xOffset + ce->width)));
1402 PMPoutC((char)(ce->yOffset));
1403 # else
1404 sprintf(PMPformat, "\323%c\360%c%c%c",
1405 (unsigned char)fontptr->plusid,
1406 (unsigned char)VisChar((char)c),
1407 (unsigned char)num_rows,
1408 (unsigned char)num_cols);
1409 PMPout(6, PMPformat);
1410 PMPoutC((char)(-x_offset));
1411 PMPoutC((char)(ce->cw - (-x_offset + num_cols)));
1412 PMPoutC((char)num_rows-y_offset);
1413 # endif
1414 #endif
1415
1416 #ifdef LJ
1417 # ifdef LJ4
1418 if (CompressFontMode) { /* Should we use compressed font downloading? */
1419 /* For COMPRESSED CHARS */
1420 if (PrevSize < nbpl) {
1421 PrevSize = nbpl;
1422 if (PrevLine != NULL)
1423 free(PrevLine);
1424 if ((PrevLine = (unsigned char*)malloc(PrevSize*sizeof(char)))
1425 == NULL) {
1426 PrevSize = 0;
1427 Fatal("EmitChar: Out of memory error!\n");
1428 }
1429 }
1430 /* Clear seed line */
1431 for (i = 0; i<nbpl; i++)
1432 PrevLine[i] = 0;
1433 CChar_Off = 0;
1434 CChar_Last = -1;
1435
1436 /* This bit copied from below... */
1437 # ifdef USEPXL
1438 if (fontptr->id == pk89)
1439 PkRaster(ce,2);
1440 else if (fontptr->id == id1002)
1441 for (i = 0; i < (int)ce->height; i++) {
1442 sl = ((unsigned char *)(ce->where.address.pixptr) + i * nbpl);
1443 CompressedCharLine(ce,nbpl,sl);
1444 }
1445 else if (fontptr->id == id1001)
1446 for (i = 0; i < (int)ce->height; i++) {
1447 sl = (unsigned char *)(ce->where.address.pixptr + i * nwpl);
1448 CompressedCharLine(ce,nbpl,sl);
1449 }
1450 # else
1451 for (i = num_rows; i > 0; i--)
1452 CompressedCharLine(ce,nbpl,(bits + (i-1)*nbpl));
1453 # endif /* USEPXL */
1454 }
1455 else
1456 CChar_Off = -1;
1457 # endif /* LJ4 */
1458
1459 INT_ASCII(cnv_buffer,fontptr->plusid);
1460 /* Depending on whether character could be packed or not the header looks
1461 different! */
1462 # ifdef LJ4
1463 /* printf("raw: %d (%d * %d), comp: %d\n",
1464 total,ce->width,ce->height,CChar_Off); */
1465 /* Characters that don't compress well are usually rather small so
1466 reading them again and writing them uncompressed won't take
1467 much time anyway. */
1468 if (CChar_Off > total)
1469 CChar_Off = -1;
1470 if (CChar_Off >= 0) {
1471 EMIT4("\033*c%sd%dE\033(s%ldW", cnv_buffer,
1472 (unsigned int)VisChar((char)c), (long)(CChar_Off + 16));
1473 EMITB(4, "\4\0\016\2");
1474 }
1475 else
1476 # endif
1477 {
1478 EMIT4("\033*c%sd%dE\033(s%ldW", cnv_buffer,
1479 (unsigned int)VisChar((char)c), total + 16);
1480 EMITB(4, "\4\0\016\1");
1481 }
1482 /* EMITC((char)(Landscape==_TRUE)); */
1483 EMITC((char)0);
1484 EMITC((char)0);
1485 #ifdef USEPXL
1486 EMITWORD(-ce->xOffset);
1487 EMITWORD(ce->yOffset);
1488 EMITWORD(ce->width);
1489 EMITWORD(ce->height);
1490 #else
1491 EMITWORD(-x_offset);
1492 EMITWORD(num_rows-y_offset);
1493 EMITWORD(num_cols);
1494 EMITWORD(num_rows);
1495 #endif
1496 EMITWORD((int)ce->cw * 4);
1497 #endif
1498
1499 #ifdef LJ4
1500 /* Now output compressed or uncompressed */
1501 if (CChar_Off >= 0) {
1502 EMITL(CChar_Off,buffin); /* Could compress character into buffer */
1503 }
1504 else /* Couldn't compress character - output literally */
1505 #endif
1506
1507 {
1508 #ifdef USEPXL
1509 if (fontptr->id == pk89)
1510 PkRaster(ce, 0);
1511 else if (fontptr->id == id1002)
1512 for (i = 0; i < (int)ce->height; i++) {
1513 sl = ((unsigned char *)(ce->where.address.pixptr) + i * nbpl);
1514 EMITL(nbpl, (char *)sl);
1515 }
1516 else if (fontptr->id == id1001)
1517 for (i = 0; i < (int)ce->height; i++) {
1518 sl = (unsigned char *)(ce->where.address.pixptr + i * nwpl);
1519 EMITL(nbpl, (char *)sl);
1520 }
1521 #else
1522 for (i = num_rows; i > 0; i--) {
1523 EMITL (nbpl, bits + (i-1) * nbpl);
1524 }
1525 #endif
1526 }
1527
1528 #ifdef IBM3812
1529 #ifdef USEPXL
1530 used_fontstorage += (long4)ce->height * ((ce->width + 15) >> 4) * 2 + 14;
1531 #else
1532 used_fontstorage += (long4)num_rows * ((num_cols + 15) >> 4) * 2 + 14;
1533 #endif
1534 #endif
1535 #ifdef LJ
1536 #ifdef USEPXL
1537 used_fontstorage += 64 * (((int)((ce->height * ce->width) - 1) / 64) + 1);
1538 #else
1539 used_fontstorage += 64 * ((((num_rows * num_cols) - 1) / 64) + 1);
1540 #endif
1541 #endif
1542 fontptr->ncdl += 1;
1543 G_ncdl += 1;
1544 }
1545
1546 /*-->PkRaster*/
1547 /*********************************************************************/
1548 /**************************** PkRaster *******************************/
1549 /*********************************************************************/
1550
1551 #ifdef USEPXL
1552 static long4 pk_packed_num(void);
1553
1554 #define PKBYTE *pkloc; pkloc ++
1555 #define OUTCHAR(c) raster_line_buf[bp]= (unsigned char)c; bp++
1556
1557 unsigned char bitweight, inputbyte;
1558 unsigned char dyn_f;
1559 unsigned char *pkloc;
1560 int repeatcount;
1561
1562 void /* <Read and translate raster description@>*/
PkRaster(struct char_entry * ce,int raster)1563 PkRaster(struct char_entry *ce, int raster)
1564 {
1565 int rp;
1566 int current_line;
1567 int wordwidth;
1568 bool turnon;
1569 unsigned short nbpl;
1570 long4 rowsleft, word, wordweight, hbit, count, i, j, tl;
1571 long4 row[101];
1572 unsigned char raster_line_buf[BYTES_PER_PIXEL_LINE];
1573 unsigned short bp;
1574
1575
1576 if (ce->charsize == HUGE_SIZE)
1577 Fatal( "cannot process currently PK font patterns of that size!\n");
1578
1579
1580 current_line = 0;
1581 pkloc = (unsigned char *)ce->where.address.pixptr;
1582 dyn_f = (unsigned char)(ce->flag_byte >> 4);
1583 turnon = (bool)((ce->flag_byte & 8) == 8);
1584 wordwidth = (int)(ce->width + 31) >> 5;
1585 nbpl = ((int)(ce->width) + 7) >> 3;
1586
1587 bitweight = 0;
1588 if (dyn_f == 14) {
1589 /*printf("<Get raster by bits@>\n");*/
1590 for (i = 1; i <= (long4)ce->height; i++) {
1591 word = 0;
1592 wordweight = 31;
1593 bp = 0; /* Sowa */
1594
1595 #ifdef DRAWGLYPH
1596 printf(" |");
1597 #endif
1598 for (j = 1; j <= (long4)ce->width; j++) {
1599 bool getbit;
1600 /* bp = 0; SOWA */
1601 /*******************************************begin Getbit *********/
1602 bitweight /= 2;
1603 if ( bitweight == 0 ) {
1604 inputbyte = PKBYTE;
1605 bitweight = 128;
1606 }
1607 getbit = (bool)
1608 ( inputbyte >= bitweight );
1609 if ( getbit )
1610 inputbyte -= bitweight;
1611 /*********************************************end Getbit *********/
1612
1613 if (getbit)
1614 word += power[wordweight];
1615
1616 wordweight --;
1617 if (wordweight == -1) {
1618
1619 #ifdef DRAWGLYPH
1620 { int k;
1621 for (k = 31; k>=0; k--) {
1622 if ((power[k] & word)!=0) printf("M");
1623 else printf(".");
1624 }
1625 }
1626 #endif
1627
1628 OUTCHAR((word >> 24 & 0xFF));
1629 OUTCHAR((word >> 16 & 0xFF));
1630 OUTCHAR((word >> 8 & 0xFF));
1631 OUTCHAR((word & 0xFF));
1632
1633 word = 0;
1634 wordweight = 31;
1635 }
1636 }
1637 if (wordweight < 31) {
1638 #ifdef COMMENT
1639 # ifdef DRAWGLYPH
1640 {
1641 int k;
1642 for (k = 15; k>=0; k--) {
1643 if ((power[k] & word)!=0) printf("Z");
1644 else printf(":");
1645 }
1646 }
1647 printf("|\n ----|");
1648 # endif
1649 #endif
1650
1651 for (j = 3; j >= (wordwidth * 4 - (long4)nbpl); j--) {
1652 OUTCHAR(((word >> (j << 3)) & 0xff));
1653 #ifdef DRAWGLYPH
1654 {
1655 int k;
1656 for (k = 7; k>=0; k--) {
1657 if ((power[k] & ((word >> (j << 3)) & 0xff))!=0) printf("M");
1658 else printf(".");
1659 }
1660 }
1661 #endif
1662 }
1663
1664 }
1665
1666 switch (raster) {
1667 case 1:
1668 RasterLine(ce, nbpl, current_line, raster_line_buf);
1669 current_line++;
1670 break;
1671 #ifdef LJ4
1672 case 2:
1673 CompressedCharLine(ce,(unsigned int)nbpl,raster_line_buf);
1674 break;
1675 #endif
1676 default:
1677 EMITL(bp, (char *)raster_line_buf);
1678 }
1679
1680 #ifdef DRAWGLYPH
1681 printf("|\n");
1682 #endif
1683 }
1684 } else {
1685 /* fprintf(ERR_STREAM, "@<Create normally packed raster@>\n"); */
1686 rowsleft = (long4)ce->height;
1687 hbit = (long4)ce->width;
1688 repeatcount = 0;
1689 wordweight = 32;
1690 word = 0;
1691 rp = 1;
1692 while ( rowsleft > 0 ) {
1693 count = pk_packed_num();
1694 bp = 0;
1695
1696 while (count > 0) {
1697 if ((count < wordweight) && (count < hbit)) {
1698 if (turnon)
1699 word +=
1700 gpower[wordweight] -
1701 gpower[wordweight - count];
1702
1703 hbit -= count;
1704 wordweight -= count;
1705 count = 0;
1706 } else if ((count >= hbit) && (hbit <=
1707 wordweight)) {
1708
1709 if (turnon)
1710 word +=
1711 gpower[wordweight] -
1712 gpower[wordweight - hbit];
1713
1714 row[rp] = word;
1715
1716 /*fprintf(ERR_STREAM, " @<Send row@> \n");*/
1717 for (i = 0; i <= (long4)repeatcount; i++) { int ii;
1718
1719 #ifdef DRAWGLYPH
1720 printf("*** |");
1721 #endif
1722 for (ii = 1; ii < wordwidth; ii++) {
1723 tl = row[ii];
1724
1725 OUTCHAR((tl >> 24 & 0xFF));
1726 OUTCHAR((tl >> 16 & 0xFF));
1727 OUTCHAR((tl >> 8 & 0xFF));
1728 OUTCHAR((tl & 0xFF));
1729
1730 #ifdef DRAWGLYPH
1731 {
1732 int k;
1733 for (k = 31; k>=0; k--) {
1734 if ((power[k] & row[ii])!=0) printf("M");
1735 else printf(".");
1736 }
1737 }
1738 #endif
1739 }
1740 tl = row[wordwidth];
1741 for (j = 3; j >= (wordwidth *4 - (long4)nbpl); j--) {
1742 OUTCHAR(((tl >> (j << 3)) & 0xff));
1743 #ifdef DRAWGLYPH
1744 {
1745 int k;
1746 for (k = 7; k>=0; k--) {
1747 if ((power[k] & ((tl >> (j << 3)) & 0xff))!=0) printf("M");
1748 else printf(".");
1749 }
1750 }
1751 #endif
1752 }
1753
1754 switch (raster) {
1755 case 1:
1756 RasterLine(ce, (unsigned int)nbpl, current_line, raster_line_buf);
1757 current_line++;
1758 break;
1759 #ifdef LJ4
1760 case 2:
1761 CompressedCharLine(ce,(unsigned int)nbpl,raster_line_buf);
1762 break;
1763 #endif
1764 default:
1765 EMITL(bp, (char *)raster_line_buf);
1766 }
1767
1768 bp = 0;
1769
1770 #ifdef DRAWGLYPH
1771 printf("| ");
1772 for (j = 1; j <= (long4)wordwidth; j++) printf("%02lX/",row[j]);
1773 printf(" raster=%d\n",raster);
1774 #endif
1775 }
1776
1777 rowsleft -= (long4)repeatcount + 1;
1778 repeatcount = 0;
1779 rp = 1;
1780 word = 0;
1781 wordweight = 32;
1782 count -= hbit;
1783 hbit = (long4)ce->width;
1784 } else {
1785 if (turnon) word += gpower[wordweight];
1786 row[rp] = word;
1787 rp = rp + 1;
1788 word = 0;
1789 count -= wordweight;
1790 hbit -= wordweight;
1791 wordweight = 32;
1792 }
1793 } /* .....while count > 0 */
1794 if (turnon)
1795 turnon = _FALSE;
1796 else
1797 turnon = _TRUE;
1798 } /* ...... rowsleft > 0 */
1799 if ((rowsleft != 0) || (hbit != (long4)ce->width))
1800 Fatal("Bad pk file----more bits than required!\n");
1801 } /* .... create normally packed raster */
1802 }
1803
1804 static unsigned char
getnyb(void)1805 getnyb(void)
1806 {
1807 register unsigned char temp;
1808 if ( bitweight == 0 ) {
1809 inputbyte = PKBYTE;
1810 bitweight = 16;
1811 }
1812 temp = inputbyte / bitweight;
1813 inputbyte -= temp * bitweight;
1814 bitweight /= 16;
1815 return ( temp );
1816 }
1817
1818
1819 static long4
pk_packed_num(void)1820 pk_packed_num(void)
1821 { /*@<Packed number procedure@>= */
1822 register int i;
1823 long4 j;
1824
1825 i = (int)getnyb();
1826 if (i == 0) {
1827 do {
1828 j = (long4)getnyb();
1829 i++;
1830 } while (j == 0);
1831 while (i > 0) {
1832 j = j * 16 + (long4)getnyb();
1833 i--;
1834 };
1835 return (j - 15 + (13 - dyn_f) * 16 + dyn_f);
1836 } else if (i <= (int)dyn_f) {
1837 return ((long4)i);
1838 } else if (i < 14) {
1839 return ((i-(long4)dyn_f - 1) * 16 + (long4)getnyb() + dyn_f + 1);
1840 } else {
1841 if (i == 14) {
1842 repeatcount = (int)pk_packed_num();
1843 } else {
1844 repeatcount = 1;
1845 }
1846 /* fprintf(ERR_STREAM,"repeatcount = [%d]\n",repeatcount); */
1847 return (pk_packed_num()); /* tail end recursion !! */
1848 }
1849 }
1850 #endif
1851
1852 #ifndef USEPXL
1853 void
bad_gf(int n)1854 bad_gf(int n)
1855 {
1856 Fatal("Bad gf file, case %d\n",n); /* See gf.c */
1857 }
1858 #endif
1859
1860
1861 #ifdef LJ4
1862 /* Compress a raster line in compression mode 2 */
1863 int
CompressLine2(unsigned char * buffer,unsigned char * buffout,int emitbytes)1864 CompressLine2(unsigned char *buffer, unsigned char *buffout, int emitbytes)
1865 {
1866 unsigned char *pos,*ppos,*litpos,*upper;
1867 int lit,i,pack;
1868 char last,c;
1869
1870 /* trap empty lines (otherwise problems with Packbits) */
1871 if (emitbytes == 0)
1872 return(0);
1873 /* Use Packbits compression (mode 2) on raster line */
1874 pos = buffer;
1875 litpos = buffer;
1876 pack = 1;
1877 ppos = buffout;
1878 last = *pos++;
1879 upper = buffer + emitbytes;
1880 while (pos < upper) {
1881 c = *pos++;
1882 if (c == last) {
1883 pack++;
1884 /* At least three equal bytes ==> write out preceding literal sequence */
1885 if ((pack == 3) && ((lit = (int)(pos - litpos - 3)) != 0)) {
1886 while (lit >= 128) {
1887 *ppos++ = 127;
1888 for (i = 1; i<=128; i++)
1889 *ppos++ = *litpos++;
1890 lit -= 128;
1891 }
1892 if (lit != 0) {
1893 *ppos++ = lit-1;
1894 while ((lit--) > 0)
1895 *ppos++ = *litpos++;
1896 /* litpos is now pos-3 (i.e. first of the sequence) */
1897 }
1898 }
1899 }
1900 else {
1901 while (pack >= 128) {
1902 *ppos++ = 129;
1903 *ppos++ = last;
1904 litpos += 128;
1905 pack -= 128;
1906 }
1907 /* At least 3 equal bytes or 2 that don't break a literal sequence
1908 ==> write out packed sequence */
1909 if ((pack >= 3) || ((pack == 2) && (litpos == pos-3))) {
1910 *ppos++ = 257 - pack;
1911 *ppos++ = last;
1912 litpos += pack;
1913 }
1914 pack = 1;
1915 last = c;
1916 }
1917 if (ppos > (buffout + BUFFSIZE/2 - 129)) {
1918 fprintf(ERR_STREAM,
1919 "Can't compact raster character; rerun without compression!\n");
1920 return(0);
1921 }
1922 }
1923
1924 while (pack >= 128) {
1925 *ppos++ = 129;
1926 *ppos++ = last;
1927 litpos += 128;
1928 pack -= 128;
1929 }
1930 if ((pack >= 3) || ((pack == 2) && (litpos == pos-3))) {
1931 *ppos++ = 257 - pack;
1932 *ppos++ = last;
1933 litpos += pack;
1934 }
1935 else if ((lit = (int)(pos - litpos)) != 0) {
1936 while (lit >= 128) {
1937 *ppos++ = 127;
1938 for (i = 1; i<=128; i++)
1939 *ppos++ = *litpos++;
1940 lit -= 128;
1941 }
1942 if (lit != 0) {
1943 *ppos++ = lit-1;
1944 while ((lit--) > 0)
1945 *ppos++ = *litpos++;
1946 }
1947 }
1948 return((int)(ppos - buffout));
1949 }
1950
1951
1952 /* Compress a raster line in compression mode 3 */
CompressLine3(unsigned char * buffer,unsigned char * buffout,int emitbytes)1953 int CompressLine3(unsigned char *buffer, unsigned char *buffout, int emitbytes)
1954 {
1955 unsigned char *pos,*ppos,*litpos,*upper,*prev;
1956 int lit,i,pack;
1957
1958 /* Use compression mode 3 */
1959 pos = buffer;
1960 ppos = buffout;
1961 upper = buffer + emitbytes;
1962 prev = PrevLine;
1963 while(pos < upper) {
1964 litpos = pos;
1965 while ((*prev == *pos) && (pos < upper)) {
1966 prev++;
1967 pos++;
1968 }
1969 if (pos < upper) {
1970 pack = (int)(pos - litpos);
1971 litpos = pos;
1972 i = upper - pos;
1973 if (i > 8)
1974 i = 8;
1975 while ((*pos != *prev) && (i > 0)) {
1976 *prev++ = *pos++;
1977 i--;
1978 }
1979 i = (int)(pos - litpos - 1);
1980 lit = i<<5;
1981 if (pack < 31) {
1982 *ppos++ = lit + pack;
1983 }
1984 else {
1985 *ppos++ = lit + 31;
1986 pack -= 31;
1987 while (pack >= 255) {
1988 *ppos++ = 255;
1989 pack -= 255;
1990 }
1991 *ppos++ = pack;
1992 }
1993 while (i >= 0) {
1994 *ppos++ = *litpos++;
1995 i--;
1996 }
1997 }
1998 if (ppos > (buffout + BUFFSIZE/2 - 16)) {
1999 fprintf(ERR_STREAM,
2000 "Can't compact raster character; rerun without compression!\n");
2001 return(0);
2002 }
2003 }
2004 return((int)(ppos - buffout));
2005 }
2006 #endif
2007
2008 /*-->RasterLine*/
2009 /**********************************************************************/
2010 /**************************** RasterLine ****************************/
2011 /**********************************************************************/
2012 void
RasterLine(struct char_entry * ce,unsigned int nbpl,unsigned int current_line,unsigned char * buffer)2013 RasterLine(struct char_entry *ce, unsigned int nbpl,
2014 unsigned int current_line, unsigned char *buffer)
2015 {
2016 #ifdef IBM3812
2017 long total;
2018 static unsigned short maxlines;
2019
2020 if (current_line == 0) {
2021 # ifdef USEPXL
2022 maxlines = ce->height;
2023
2024 MoveVert(-ce->yOffset); /* move cursor up */
2025 MoveHor(-ce->xOffset); /* move cursor right */
2026 # else
2027 maxlines = num_rows;
2028
2029 MoveVert(- (num_rows-y_offset) ); /* move cursor up */
2030 MoveHor(-x_offset); /* move cursor right */
2031 # endif
2032 last_rx = last_ry = UNKNOWN; /* next time full positioning */
2033 }
2034
2035 if (current_line % maxlines == 0) {
2036 if (current_line > 0) { /* maxlines lines have been printed*/
2037 MoveVert(maxlines); /* move cursor down */
2038 last_rx = last_ry = UNKNOWN; /* next time full positioning */
2039 }
2040 # ifdef USEPXL
2041 total = (long)(ce->height - current_line) * (long4)nbpl;
2042 # else
2043 total = (long)(num_rows - current_line) * (long4)nbpl;
2044 # endif
2045 if ((total + 9) > 65535) {
2046 maxlines = (unsigned short)((65535 - 9) / nbpl);
2047 total = (long)maxlines * (long)nbpl;
2048 }
2049
2050 PMPcont(total + 9);
2051 PMPout(2, "\365\0");
2052 EMITWORD(maxlines);
2053 # ifdef USEPXL
2054 EMITWORD(ce->width);
2055 # else
2056 EMITWORD(num_cols);
2057 # endif
2058 PMPoutC((unsigned char) (total >> 16) & 0xFF);
2059 PMPoutC((unsigned char) (total >> 8 ) & 0xFF);
2060 PMPoutC((unsigned char) total & 0xFF);
2061 }
2062 EMITL((int)nbpl, (char *)buffer);
2063 #endif /* IBM3812 */
2064
2065
2066 #ifdef LJ
2067 register int emitbytes;
2068 #ifdef LJ4
2069 int i;
2070 #endif
2071
2072 for (emitbytes = (int)nbpl;
2073 (*(buffer + emitbytes - 1) == '\0') && (emitbytes > 0);
2074 emitbytes--);
2075 # ifdef LJ4
2076 switch (CompressCharMode) {
2077 case 0:
2078 EMIT2("\033*b%dW", emitbytes);
2079 EMITL(emitbytes, buffer);
2080 break;
2081
2082 case 2:
2083 i = CompressLine2(buffer,buffin,emitbytes);
2084 EMIT2("\033*b%dW", i);
2085 EMITL(i,buffin);
2086 break;
2087
2088 case 3:
2089 i = CompressLine3(buffer,buffin + BUFFSIZE/2,(int)nbpl);
2090 EMIT2("\033*b%dW", i);
2091 EMITL(i,buffin + BUFFSIZE/2);
2092 break;
2093
2094 default:
2095 fprintf(ERR_STREAM,"Unsupported compression mode!\n");
2096 }
2097 # else
2098 EMIT2("\033*b%dW", emitbytes);
2099 EMITL(emitbytes, buffer);
2100 # endif /* LJ4 */
2101 #endif /* LJ */
2102 }
2103
2104
2105 /*-->RasterChar*/
2106 /**********************************************************************/
2107 /**************************** RasterChar ****************************/
2108 /**********************************************************************/
2109 void /* raster a character bitmap */
RasterChar(struct char_entry * ce)2110 RasterChar(struct char_entry *ce)
2111 {
2112 int i;
2113 register unsigned char *sl;
2114 unsigned short nbpl, nwpl;
2115 unsigned char raster_line_buf[BYTES_PER_PIXEL_LINE];
2116
2117 #ifdef DEBUG
2118 if (Debug)
2119 fprintf(ERR_STREAM,"Raster character ...size=%d \n", (int)ce->charsize);
2120 #endif
2121
2122 #ifdef USEPXL
2123 if (fontptr->id == pk89) {
2124 nwpl = 0; /* initialize variable */
2125 nbpl = ((int)(ce->width) + 7) >> 3;
2126 } else if (fontptr->id == id1002) {
2127 nwpl = 0; /* initialize variable */
2128 nbpl = ((int)ce->width + 7) >> 3;
2129 } else if (fontptr->id == id1001) {
2130 nwpl = ((int)ce->width + 31) >> 5;
2131 nbpl = ((int)ce->width + 7) >> 3;
2132 } else {
2133 /* should never be necessary */
2134 nwpl = 0;
2135 nbpl = 0;
2136 }
2137 #else
2138 nbpl = (num_cols + 7) >> 3;
2139 #endif
2140
2141 #ifdef LJ
2142 # ifdef LJ4
2143 CompressCharMode = (ce->width < CompressCharWidth) ? 0 : UseCompression;
2144 EMIT3("\033*t%dR\033*r1A\033*b%dM",RESOLUTION,CompressCharMode);
2145 if (CompressCharMode == 3) {
2146 /* Check if PrevLine big enough; claim more space if not */
2147 if (((int)nbpl) > PrevSize) {
2148 if (PrevLine != NULL)
2149 free(PrevLine);
2150 if ((PrevLine = (unsigned char *)malloc(nbpl*sizeof(char))) == NULL) {
2151 PrevSize = 0;
2152 Fatal("RasterChar: out of memory!\n");
2153 }
2154 PrevSize = (int)nbpl;
2155 }
2156 /* Clear previous line */
2157 sl = PrevLine;
2158 for (i = 0; i<nbpl; i++)
2159 *sl++ = 0;
2160 }
2161 # else
2162 EMIT2("\033*t%dR\033*r1A\033*b0M",RESOLUTION);
2163 # endif /* LJ4 */
2164 #endif
2165 { /* read pixel from file */
2166 if ((ce->charsize == HUGE_SIZE) && (fontptr->id != pk89))
2167 OpenFontFile();
2168 #ifdef USEPXL
2169 FSEEK(pxlfp, ce->where.address.fileOffset, SEEK_SET);
2170 #else
2171 FSEEK(gfin, ce->where.address.fileOffset, SEEK_SET);
2172 gettochar();
2173 readbits();
2174 #endif /* USEPXL */
2175 }
2176
2177 #ifdef USEPXL
2178 if (fontptr->id == pk89)
2179 PkRaster(ce, 1);
2180 else if (fontptr->id == id1002) {
2181 for (i = 0; i < (int)ce->height; i++) {
2182 if (ce->charsize == HUGE_SIZE) {
2183 fread(raster_line_buf, 1, (int)nbpl, pxlfp);
2184 sl = raster_line_buf;
2185 } else
2186 sl = ((unsigned char *)(ce->where.address.pixptr)
2187 + i * nbpl);
2188 RasterLine(ce, (unsigned int)nbpl, i, sl);
2189 }
2190 } else if (fontptr->id == id1001) {
2191 long filediff;
2192 filediff = (long)nwpl * 4 - nbpl;
2193 for (i = 0; i < (int)ce->height; i++) {
2194 if (ce->charsize == HUGE_SIZE) {
2195 read_multi(raster_line_buf, 1, (int)nbpl, pxlfp);
2196 /* skip fill bytes */
2197 FSEEK(pxlfp, filediff, SEEK_CUR);
2198 sl = raster_line_buf;
2199 } else
2200 sl = (unsigned char *)(ce->where.address.pixptr + i * nwpl);
2201 RasterLine(ce, (unsigned int)nbpl, i, sl);
2202 }
2203 }
2204 #else
2205 for (i = num_rows; i > 0; i--)
2206 RasterLine(ce, (unsigned int)nbpl, i, bits + (i-1) * nbpl);
2207 #endif
2208 #ifdef LJ
2209 EMIT1("\033*rB");
2210 #endif
2211 last_rx = last_ry = UNKNOWN;
2212 }
2213
2214 /*-->LoadAChar*/
2215 /**********************************************************************/
2216 /***************************** LoadAChar ******************************/
2217 /**********************************************************************/
2218 void
LoadAChar(long4 c,register struct char_entry * ptr)2219 LoadAChar(long4 c, register struct char_entry *ptr)
2220 {
2221 long4 *pr;
2222 long bytes;
2223
2224 if (ptr->where.address.fileOffset == NONEXISTANT
2225 #ifdef LJ_RESIDENT_FONTS
2226 || fontptr->resident_p
2227 #endif
2228 ) {
2229 ptr->where.isloaded = _FALSE;
2230 return;
2231 }
2232
2233 OpenFontFile();
2234
2235 #ifdef DEBUG
2236 if (Debug)
2237 fprintf(ERR_STREAM, "LoadAChar: <%c>(%ld) from file at pos %ld\n",
2238 (char)c,(long)c,(long)ptr->where.address.fileOffset);
2239 #endif
2240
2241 #ifdef USEPXL
2242
2243 FSEEK(pxlfp, ptr->where.address.fileOffset, SEEK_SET);
2244
2245 if (fontptr->id == pk89) {
2246 #ifdef PARANOIA
2247 unsigned char temp;
2248 temp = (unsigned char) NoSignExtend(pxlfp, 1);
2249
2250 if ((int)(ptr->flag_byte) != (int)temp) {
2251 fprintf(ERR_STREAM,"font=%lx, ptr=%lx\n",fontptr,ptr);
2252 Fatal("%d: oh boy! old flag %d, new flag %d, ptr=%lx\n",
2253 (int)c,(int)(ptr->flag_byte),(int)temp,ptr);
2254 }
2255 #endif
2256
2257 if ((ptr->flag_byte & 7) == 7) {
2258 bytes = NoSignExtend(pxlfp, 4) - 28;
2259 FSEEK(pxlfp, ptr->where.address.fileOffset + 36, SEEK_SET);
2260 /*
2261 fprintf(ERR_STREAM,"bytes=%d, seeking at %ld\n",
2262 bytes, ptr->where.address.fileOffset + 36);
2263 */
2264 } else if ((ptr->flag_byte & 4) == 4) {
2265 bytes = ((long4)ptr->flag_byte & 3) * 65536l + NoSignExtend(pxlfp, 2) - 13;
2266 FSEEK(pxlfp, ptr->where.address.fileOffset + 16, SEEK_SET);
2267 } else {
2268 bytes = ((long4)ptr->flag_byte & 3) * 256 + NoSignExtend(pxlfp, 1) - 8;
2269 FSEEK(pxlfp, ptr->where.address.fileOffset + 10, SEEK_SET);
2270 }
2271 } else if (fontptr->id == id1002)
2272 bytes = ((( (long4)ptr->width + 7) >> 3) * (long4)ptr->height);
2273 else if (fontptr->id == id1001)
2274 bytes = 4 * (((long4)ptr->width + 31) >> 5) * (long4)ptr->height;
2275 else
2276 bytes = 0;
2277
2278 if (bytes > 0) {
2279 /* do NOT load Huge characters */
2280 if ((bytes > HUGE_CHAR_PATTERN) && (fontptr->id != pk89)) {
2281 qfprintf(ERR_STREAM,"Huge Character <%c> (%ld Bytes)\n",
2282 (char)c, bytes);
2283 ptr->charsize = HUGE_SIZE;
2284 ptr->where.isloaded = _FALSE;
2285 } else {
2286 if ( (pr = (long4 *)malloc( bytes )) == NULL )
2287 Fatal("Unable to allocate %ld bytes for char <%c>\n", bytes, (char)c);
2288 /*
2289 * else fprintf(ERR_STREAM,"allocating %ld bytes char <%c>(%d)\t at 0x%lx\n",
2290 * bytes, (char)c,(int)c,pr);
2291 */
2292 #ifdef DEBUG
2293 if (Debug)
2294 fprintf(ERR_STREAM,
2295 "Allocating Char <%c>, FileOffset=%lX, Bytes=%ld (%d) <%d>\n",
2296 (char)c, ptr->where.address.fileOffset, bytes,
2297 (int)bytes, (unsigned int)bytes);
2298 #endif
2299 allocated_storage += bytes;
2300 read_multi(pr, 1, (int)bytes , pxlfp);
2301 ptr->where.address.pixptr = pr;
2302 }
2303 }
2304 #else
2305 FSEEK(gfin, ptr->where.address.fileOffset, SEEK_SET);
2306 gettochar();
2307 readbits();
2308 if (num_bytes > HUGE_CHAR_PATTERN)
2309 ptr->charsize = HUGE_SIZE;
2310 #endif
2311 ptr->where.isloaded = _TRUE;
2312 if (ptr->charsize != SMALL_SIZE
2313 #ifdef LJ
2314 /* we might have problems at the edge of the paper with diff. sized characters
2315 * the correct treatment would be to check whether the bounding box of
2316 * tfontptr is within the paper relative to the current position
2317 */
2318 || fontptr->max_height > CHAR_HEIGTH_LARGE
2319 || (rasterfont[fontptr->plusid])
2320 #endif
2321 )
2322 return;
2323
2324 EmitChar(c, ptr);
2325 #ifdef USEPXL
2326 /* we should really free the space used by the PXL data after this
2327 point, but it is not large, and besides, we may want to be
2328 more clever in the future, about sending bitmaps. So keep
2329 the data around */
2330 #endif
2331 }
2332
2333 /*-->SetChar*/
2334 /**********************************************************************/
2335 /***************************** SetChar ******************************/
2336 /**********************************************************************/
2337 void
SetChar(long4 c,short command,int PassNo,bool do_posn,bool in_string)2338 SetChar(long4 c, short command, int PassNo, bool do_posn, bool in_string)
2339 {
2340 register struct char_entry *ptr; /* temporary char_entry pointer */
2341 bool pos_after = _FALSE;
2342
2343 ptr = &(fontptr->ch[c]);
2344 if (!((ptr->where.isloaded) || (ptr->charsize == HUGE_SIZE)))
2345 LoadAChar(c, ptr);
2346 if (PassNo == 0)
2347 return;
2348
2349 if (do_posn) {
2350 #ifdef IBM3812
2351 if (CharStringPos>0) {
2352 fprintf(ERR_STREAM,"!!!! That should never happen!!!\n");
2353 CharStringOut;
2354 }
2355 #endif
2356 SetPosn(h, v);
2357 }
2358
2359 /*
2360 fprintf(ERR_STREAM,
2361 "(%d) hh=%ld (+%ld/+%ld), h=%ld, xh=%ld,xhh=%ld, [%ld|%ld] ->%d\n",
2362 (int)do_posn,hh,(long4)ptr->cw,(long4)ptr->cw*(long4)hconv,h,
2363 (long)PIXROUND(h, hconv),
2364 (long)PIXROUND(hh, hconv),
2365 (long)labs((hh-h)),(long)hconv,
2366 (labs((hh-h))>hconv)
2367 );
2368 */
2369
2370 if (in_string && (labs((hh-h))>hconv)) {
2371 #ifdef IBM3812
2372 CharStringOut;
2373 #endif
2374 SetPosn(h, v);
2375 }
2376
2377 /*
2378 fprintf(ERR_STREAM,"raster?=%d - last_ry=%d, last_rx=%d,mmax-height=%d\n",
2379 (int)last_ry < fontptr->max_height, (int)last_ry,(int)last_rx,
2380 (int)fontptr->max_height);
2381 */
2382
2383 if (fontptr->font_file_id != NO_FILE) { /* ignore missing fonts */
2384 if (
2385 #ifdef LJ_RESIDENT_FONTS
2386 !fontptr->resident_p &&
2387 #endif
2388 (ptr->charsize != SMALL_SIZE
2389 #ifdef LJ
2390 /* the LaserJet cannot print characters
2391 * where the bounding box lies outside the
2392 * paper edge. Missing: right paper edge
2393 */
2394 || last_ry < (int)fontptr->max_height
2395 || fontptr->max_height > CHAR_HEIGTH_LARGE
2396 || (rasterfont[fontptr->plusid])
2397 || (brother_mode && c == 0)
2398 #ifdef SEVENBIT
2399 || (kyocera_mode && c == 32)
2400 #endif
2401 #endif
2402 )) {
2403 #ifdef LJ
2404 int tmp;
2405 char sign;
2406
2407 if (!do_posn)
2408 SetPosn(h, v);
2409
2410 #ifdef USEPXL
2411 tmp = (int)-ptr->yOffset;
2412 #else
2413 tmp = (int)num_rows-y_offset;
2414 #endif
2415 if (tmp != 0) {
2416 if (tmp < 0) {
2417 sign = '-';
2418 tmp = -tmp;
2419 } else
2420 sign = '+';
2421 EMIT3("\033*p%c%dY", sign, tmp);
2422 }
2423 #ifdef USEPXL
2424 tmp = (int)-ptr->xOffset;
2425 #else
2426 tmp = (int)-x_offset;
2427 #endif
2428 if (tmp != 0) {
2429 if (tmp < 0) {
2430 sign = '-';
2431 tmp = -tmp;
2432 } else
2433 sign = '+';
2434 EMIT3("\033*p%c%dX", sign, tmp);
2435 }
2436 #endif
2437 #ifdef IBM3812
2438 CharStringOut;
2439 #endif
2440 #ifdef DEBUG
2441 if (Debug)
2442 #ifndef vms
2443 fprintf(ERR_STREAM,"Raster character <%c> %hd\n", (char) c,(short)c);
2444 #else
2445 fprintf(ERR_STREAM,"Raster character <%c> %d\n", (char) c,(short)c);
2446 #endif
2447 #endif
2448 RasterChar(ptr);
2449 pos_after = _TRUE;
2450 } else {
2451 unsigned char cc;
2452 cc = VisChar((char)c);
2453 #ifdef IBM3812
2454 #ifdef USEPXL
2455 if ( ptr->yyOffset || (!in_string) ) {
2456 CharStringOut;
2457 MoveVert(ptr->yyOffset);
2458 sprintf(PMPformat, "\01%c", cc);
2459 PMPout(2, PMPformat);
2460 MoveVert((int)-(ptr->yyOffset));
2461 } else {
2462 #endif
2463 if (CharStringPos==CHARSTRINGMAX)
2464 CharStringOut;
2465
2466 CharString[CharStringPos] = cc;
2467 CharStringPos++;
2468 #ifdef USEPXL
2469 }
2470 #endif
2471 #endif
2472 #ifdef LJ
2473 #define TRANSPARENTCHAR(ch) \
2474 if ((ch == 0l) || (ch >= 7l && ch <= 15l) || (ch == 27l)) \
2475 EMIT2("\033&p1X%c", (unsigned char)ch); \
2476 else { EMITC((unsigned char)ch); }
2477 #ifdef USEPXL
2478 if (ptr->yyOffset) {
2479 #ifndef vms
2480 EMIT2("\033*p+%hdY", ptr->yyOffset);
2481 TRANSPARENTCHAR(cc);
2482 EMIT2("\033*p-%hdY", ptr->yyOffset); /* GUGUGU 255 */
2483 #else
2484 EMIT2("\033*p+%dY", ptr->yyOffset);
2485 TRANSPARENTCHAR(cc);
2486 EMIT2("\033*p-%dY", ptr->yyOffset); /* GUGUGU 255 */
2487 #endif
2488 } else
2489 #endif
2490 /* EMITC( (unsigned char)c);*/
2491 { TRANSPARENTCHAR(cc);}
2492 #endif
2493 }
2494 /*
2495 fprintf(stderr,"--> hh(%ld) += cw(%ld) * hconv(%ld)",
2496 (long)hh, (long)ptr->cw, (long) hconv);
2497 */
2498 #ifdef LJ
2499 /* the guessed position must be a multiple of pixels */
2500 if (RESOLUTION == 300)
2501 hh += (long4) ((ptr->cw)/4)*4*hconv;
2502 else /* RESOLUTION == 600 */
2503 hh += (long4) ((ptr->cw)/2)*2*hconv;
2504 #else
2505 hh += (long4)(ptr->cw * hconv);
2506 #endif
2507 /*
2508 fprintf(stderr," = hh(%ld)\n",(long)hh);
2509 */
2510 }
2511
2512 if (command <= SET4)
2513 h += ptr->tfmw;
2514
2515 if (pos_after)
2516 SetPosn(h, v);
2517 else
2518 last_rx = (int)PIXROUND(h, hconv) + x_goffset;
2519 }
2520
DoBop(void)2521 void DoBop(void)
2522 {
2523 struct font_entry *p;
2524 #ifdef LJ
2525 register short i;
2526 if (fonts_used_on_this_page > MAX_FONTS_PER_PAGE) {
2527 for (i = 0; i < HANDLE_MAX_FONTS; i++)
2528 rasterfont[i] = _FALSE;
2529 }
2530 fonts_used_on_this_page = 0;
2531 #endif
2532 for (p = hfontptr; p; p = p->next)
2533 p->used_on_this_page = _FALSE;
2534 }
2535
2536 /*-->SetString*/
2537 /**********************************************************************/
2538 /***************************** SetString ****************************/
2539 /**********************************************************************/
2540 void
SetString(short firstch,int PassNo)2541 SetString(short firstch, int PassNo)
2542 {
2543 short c;
2544 register unsigned short i;
2545
2546 #ifdef DEBUG
2547 if (Debug)
2548 fprintf(ERR_STREAM, "SetString ");
2549 #endif
2550 for (i = 0, c = firstch; c >= SETC_000 && c <= SETC_127; i++) {
2551 #ifdef DEBUG
2552 if (Debug)
2553 fprintf(ERR_STREAM, "%d(%c) ", c, c);
2554 #endif
2555 SetChar((long4)c, c, PassNo, (bool)(i==0), _TRUE);
2556 c = (short)NoSignExtend(dvifp, 1);
2557 }
2558 FSEEK(dvifp, -1l, SEEK_CUR); /* backup one character */
2559 #ifdef IBM3812
2560 CharStringOut;
2561 #endif
2562 #ifdef DEBUG
2563 if (Debug)
2564 fprintf(ERR_STREAM, "...SetString\n");
2565 #endif
2566 }
2567
2568 /*-->SetPosn*/
2569 /**********************************************************************/
2570 /***************************** SetPosn ******************************/
2571 /**********************************************************************/
2572 void /* output a positioning command */
SetPosn(long4 x,long4 y)2573 SetPosn(long4 x, long4 y)
2574 {
2575 int rx, ry;
2576 rx = (int)PIXROUND(x, hconv) + x_goffset;
2577 ry = (int)PIXROUND(y, vconv) + y_goffset;
2578
2579 /*
2580 fprintf(ERR_STREAM,
2581 "setposn to %ld/%ld, %d/%d, last: %d/%d\n",
2582 (long)x,(long)y,
2583 rx,ry,
2584 last_rx,last_ry
2585 );
2586 */
2587
2588 #ifdef IBM3812
2589 PMPcont(3);
2590 PMPoutC('\340');
2591 EMITWORD(LARGER(rx,0));
2592
2593 if (last_ry != ry) { /* necessary to set new y-position */
2594 PMPcont(3);
2595 PMPoutC('\341');
2596 EMITWORD(LARGER(ry,0));
2597 }
2598 #endif
2599 #ifdef LJ
2600 #if 0
2601 /* this optimization doesn't work, as last_XX is set to the
2602 starting(!) position of the last string not to the end position! */
2603
2604 if (last_rx != rx || last_ry != ry) {
2605 if (last_ry == ry) /* not necessary to set new y-position */
2606 EMIT2("\033*p%dX", LARGER(rx,0));
2607 else if (last_rx == rx)
2608 EMIT2("\033*p%dY", LARGER(ry,0));
2609 else
2610 EMIT3("\033*p%dx%dY", LARGER(rx,0), LARGER(ry,0));
2611 }
2612 #endif
2613 if (last_ry == ry) /* not necessary to set new y-position */
2614 EMIT2("\033*p%dX", LARGER(rx,0));
2615 else
2616 EMIT3("\033*p%dx%dY", LARGER(rx,0), LARGER(ry,0));
2617 #endif
2618
2619 last_ry = ry; /* last y-position on output device */
2620 last_rx = rx; /* last x-position on output device */
2621 /*
2622 * must know where device "really" is horizontally, for rel. posning.
2623 * (maybe in the future), but we always use direct positioning for
2624 * vertical movement.
2625 */
2626 /* hh = rx * hconv; */
2627 hh = x;
2628 vv = y;
2629 /*
2630 * fprintf(ERR_STREAM,"DoPosn: x=%ld, y=%ld, rx=%d, ry=%d, hh=%ld, vv=%ld\n",
2631 * (long)x,(long)y,rx,ry,(long)hh,(long)vv);
2632 */
2633 }
2634
2635
2636
2637 #ifdef LJ4
2638 /* Compresses a rasterline of font data and appends it to buffin (used
2639 for storage of the compressed character). CChar_Off is the current
2640 offset in the buffer, CChar_Last is the first byte of the last
2641 compacted row (line repeat count). Updates the previous line
2642 (PrevLine) if necessary. */
2643 void
CompressedCharLine(struct char_entry * ce,int nbpl,unsigned char * buffer)2644 CompressedCharLine(struct char_entry *ce, int nbpl, unsigned char *buffer)
2645 {
2646 if (CChar_Off >= 0) {
2647 register unsigned char *obuf,*buff;
2648 unsigned char *prev,*end;
2649 #undef max /* cc thinks any max macro overrides a variable */
2650 int t,mode,max;
2651 register int x,y,i;
2652
2653 prev = PrevLine;
2654 obuf = buffer;
2655 end = buffer + nbpl;
2656 x = 0;
2657 while (obuf < end) {
2658 if (*obuf != *prev) {
2659 *prev = *obuf;
2660 x = 1;
2661 }
2662 obuf++;
2663 prev++;
2664 }
2665 if (x == 0 && CChar_Last >= 0) {
2666 (buffin[CChar_Last])++;
2667 return; /* line repeat count +1 */
2668 }
2669
2670 end = buffin + BUFFSIZE - 16;
2671 obuf = buffin + CChar_Off;
2672 buff = buffer;
2673 *obuf++ = 0; /* Line repeat count = 0 */
2674 t = 0;
2675 CChar_Last = CChar_Off; /* Next line */
2676 mode = 0;
2677 y = *buff++;
2678 i = 7; /* i = current bit */
2679 while ((t < ce->width) && (obuf < end)) {
2680 max = ce->width - t; /* maximum pixels left to do */
2681 x = 0;
2682 if (mode == 0) {
2683 /* white run */
2684 while ((y & (1<<i)) == 0 && x < max) {
2685 x++;
2686 i--;
2687 if (i < 0) {
2688 i = 7;
2689 y = *buff++;
2690 while (y == 0 && x < max) {
2691 x += 8;
2692 y = *buff++;
2693 }
2694 }
2695 }
2696 mode = 1;
2697 }
2698 else {
2699 /* black run */
2700 while ((y & (1<<i)) != 0 && x < max) {
2701 x++;
2702 i--;
2703 if (i < 0) {
2704 i = 7;
2705 y = *buff++;
2706 while (y == 0xff && x < max) {
2707 x += 8;
2708 y = *buff++;
2709 }
2710 }
2711 }
2712 mode = 0;
2713 }
2714 if (x > max)
2715 x = max;
2716 t += x;
2717 /* make precautions for very long runs */
2718 while (x > 0xff) {
2719 *obuf++ = 0xff;
2720 *obuf++ = 0;
2721 x -= 0xff;
2722 }
2723 *obuf++ = x;
2724 }
2725 CChar_Off = obuf >= end ? -1 : obuf - buffin;
2726 }
2727 }
2728 #endif
2729
2730 /*------------------------ end dvichars.c ------------------------------*/
2731
2732
2733 /* Report a warning if both checksums are nonzero, they don't match, and
2734 the user hasn't turned it off. */
2735
2736 static void
check_checksum(unsigned c1,unsigned c2,const char * name)2737 check_checksum (unsigned c1, unsigned c2, const char *name)
2738 {
2739 if (c1 && c2 && c1 != c2
2740 #ifdef KPATHSEA
2741 && !kpse_tex_hush ("checksum")
2742 #endif
2743 ) {
2744 Warning ("Checksum mismatch in %s", name) ;
2745 }
2746 }
2747
2748
2749 /*------------------------ begin dviconv.c -----------------------------*/
2750 /*-->ActualFactor*/
2751 /**********************************************************************/
2752 /************************** ActualFactor ****************************/
2753 /**********************************************************************/
2754 double /* compute the actual size factor given the approximation */
ActualFactor(long4 unmodsize)2755 ActualFactor(long4 unmodsize)
2756 {
2757 double realsize; /* the actual magnification factor */
2758 realsize = (double)unmodsize / 1000.0;
2759 if (abs((int)(unmodsize - 1095l))<2)
2760 realsize = 1.095445115; /*stephalf*/
2761 else if (abs((int)(unmodsize - 1315l))<2)
2762 realsize = 1.31453414; /*stepihalf*/
2763 else if (abs((int)(unmodsize - 1577l))<2)
2764 realsize = 1.57744097; /*stepiihalf*/
2765 else if (abs((int)(unmodsize - 1893l))<2)
2766 realsize = 1.89292916; /*stepiiihalf*/
2767 else if (abs((int)(unmodsize - 2074l))<2)
2768 realsize = 2.0736; /*stepiv*/
2769 else if (abs((int)(unmodsize - 2488l))<2)
2770 realsize = 2.48832; /*stepv*/
2771 else if (abs((int)(unmodsize - 2986l))<2)
2772 realsize = 2.985984; /*stepvi*/
2773 /* the remaining magnification steps are represented with sufficient
2774 accuracy already */
2775 return(realsize);
2776 }
2777
2778
2779 /*-->DecodeArgs*/
2780 /*********************************************************************/
2781 /***************************** DecodeArgs ****************************/
2782 /*********************************************************************/
2783 void
DecodeArgs(int argc,char * argv[])2784 DecodeArgs(int argc, char *argv[])
2785 {
2786 int argind; /* argument index for flags */
2787 char *curarea; /* current file area */
2788 char *curname; /* current file name */
2789 char *tcp, *tcp1; /* temporary character pointers */
2790 const char *ctcp; /* temporary const char pointer */
2791 char *this_arg;
2792 double x_offset = 0.0, y_offset = 0.0;
2793 #ifdef __riscos
2794 int ddi;
2795 #endif
2796
2797
2798 #ifndef KPATHSEA
2799 if ((tcp = getenv("TEXPXL")) != NULL) PXLpath = tcp;
2800 #ifdef LJ_RESIDENT_FONTS
2801 if ((tcp = getenv("TFMFONTS")) != NULL)
2802 TFMpath = tcp;
2803 else if ((tcp = getenv("TEXFONTS")) != NULL)
2804 TFMpath = tcp;
2805 #endif
2806 #endif
2807
2808 if (argc == 2 && EQ(argv[1], "--version")) {
2809 puts (VERSION);
2810 puts (kpathsea_version_string);
2811 puts ("Copyright (C) 1997 Gustaf Neumann.\n\
2812 There is NO warranty. You may redistribute this software\n\
2813 under the terms of the GNU General Public License.\n\
2814 For more information about these matters, see the files\n\
2815 named COPYING and dvi2xx.c.\n\
2816 Primary author of Dvi2xx: Gustaf Neumann; -k maintainer: K. Berry.");
2817 exit (0);
2818 }
2819
2820 #ifdef LJ4
2821 /* check if last character is a 6 */
2822 LJ6 = ('6' == argv[0][strlen(argv[0])-1]);
2823 #endif
2824
2825 argind = 1;
2826 while (argind < argc) {
2827 tcp = argv[argind];
2828 if (tcp[0] == '-' && tcp[1] != '\0') {
2829 ++tcp;
2830 switch (*tcp) {
2831 #ifndef KPATHSEA
2832 case 'a': /* a selects different pxl font area */
2833 PXLpath = ++tcp;
2834 break;
2835 #endif
2836 case 'A':
2837 ManualFeed = _TRUE;
2838 break;
2839 #ifdef IBM3812
2840 case 'b': /* first page from alternate casette */
2841 FirstAlternate = _TRUE;
2842 break;
2843 #endif
2844 case 'c': /* number of copies to print */
2845 if ( sscanf(tcp + 1, "%hd", &ncopies) != 1 )
2846 Fatal("Argument of -c is not a valid integer\n");
2847 if (ncopies<1) {
2848 Warning("argument of -c < 1; set to 1!");
2849 ncopies = 1;
2850 }
2851 break;
2852 #ifdef DEBUG
2853 case '-': /* --D selects Debug output */
2854 tcp++;
2855 if (*tcp == 'D') {
2856 Debug = _TRUE;
2857 #ifdef KPATHSEA
2858 sscanf(tcp + 1, "%u", &kpathsea_debug);
2859 #endif
2860 qfprintf(ERR_STREAM,"Debug output enabled\n");
2861 }
2862 break;
2863 #endif
2864 #ifdef LJ2P
2865 case 'd': /* d selects DUPLEX mode */
2866 tcp++;
2867 if (*tcp == '1' )
2868 DuplexMode = 1;
2869 else if (*tcp == '2')
2870 DuplexMode = 2;
2871 else {
2872 Warning("Invalid DUPLEX mode, assuming DUPLEX=1, Long-Edge Binding");
2873 DuplexMode = 1;
2874 }
2875 break;
2876 #endif
2877 case 'D': /* D selects DoublePage */
2878 DoublePage = _TRUE;
2879 tcp++;
2880 if (*tcp == '1' || *tcp == '2') {
2881 if (*tcp == '2')
2882 PrintFirstPart = _FALSE;
2883 else
2884 PrintSecondPart = _FALSE;
2885 tcp++;
2886 }
2887 if (*tcp == '-')
2888 PrintEmptyPages = _FALSE;
2889 break;
2890 #ifdef LJ4
2891 case 'E': /* do not reset printer (go) */
2892 econoMode = _TRUE;
2893 break;
2894 #endif
2895 case 'e': /* emit file is specified */
2896 tcp++;
2897 #ifdef MSDOS
2898 /* delete trailing ':' (causing hangup) */
2899 if (tcp[strlen(tcp)-1] == ':')
2900 tcp[strlen(tcp)-1] = '\0';
2901 #endif
2902 #ifdef OS2 /* repeated to avoid problems with stupid c preprocessors */
2903 /* delete trailing ':' (causing hangup) */
2904 if (tcp[strlen(tcp)-1] == ':')
2905 tcp[strlen(tcp)-1] = '\0';
2906 #endif
2907 EmitFileName = tcp;
2908 break;
2909 case 'f': /* next arg is starting pagenumber */
2910 if ( sscanf(tcp + 1, FMT_long4, &FirstPage) != 1 )
2911 Fatal("Argument is not a valid integer\n");
2912 FirstPageSpecified = _TRUE;
2913 break;
2914 #ifdef LJ
2915 case 'g': /* do not reset printer (go) */
2916 my_ResetPrinter = _FALSE;
2917 break;
2918 #endif
2919 case 'h': /* copy header file through to output */
2920 HeaderFileName = ++tcp;
2921 G_header = _TRUE;
2922 break;
2923 #if defined(LJ2P) || defined(IBM3812)
2924 case 'l': /* landscape */
2925 Landscape = _TRUE;
2926 break;
2927 #endif
2928 #ifdef MAKETEXPK
2929 case 'M':
2930 /* -M, -M1 => don't make font; -M0 => do. */
2931 makeTexPK = *(tcp + 1) == '0';
2932 #ifdef KPATHSEA
2933 kpse_set_program_enabled (kpse_pk_format, MAKE_TEX_PK_BY_DEFAULT, kpse_src_cmdline);
2934 #endif /* KPATHSEA */
2935 break;
2936 #endif /* MAKETEXPK */
2937 case 'x': /* specify x-offset */
2938 this_arg = 0;
2939 if (!(*++tcp)) {
2940 this_arg = (++argind >= argc ? 0 : argv[argind]);
2941 } else {
2942 this_arg = tcp;
2943 }
2944 if (!this_arg
2945 || sscanf(this_arg,"%lf", &x_offset) != 1)
2946 Fatal("Argument of -x is not a valid floating point number\n");
2947 break;
2948 case 'y': /* specify y-offset */
2949 this_arg = 0;
2950 if (!(*++tcp)) {
2951 this_arg = (++argind >= argc ? 0 : argv[argind]);
2952 } else {
2953 this_arg = tcp;
2954 }
2955 if (!this_arg || sscanf(this_arg, "%lf", &y_offset) != 1)
2956 Fatal("Argument of -y is not a valid floating point number\n");
2957 break;
2958 case 'X': /* specify X-origin in dots */
2959 this_arg = 0;
2960 if (!(*++tcp)) {
2961 this_arg = (++argind >= argc ? 0 : argv[argind]);
2962 } else {
2963 this_arg = tcp;
2964 }
2965 if (!this_arg || sscanf(this_arg,"%hd", &x_origin) != 1)
2966 Fatal("Argument of -X is not a valid integer\n");
2967 break;
2968 case 'Y': /* specify Y-origin in dots */
2969 this_arg = 0;
2970 if (!(*++tcp)) {
2971 this_arg = (++argind >= argc ? 0 : argv[argind]);
2972 } else {
2973 this_arg = tcp;
2974 }
2975 if (!this_arg ||
2976 sscanf(this_arg, "%hd", &y_origin) != 1)
2977 Fatal("Argument of -Y is not a valid integer\n");
2978 break;
2979 case 'm': /* specify magnification to use */
2980 switch ( (*++tcp) ) {
2981 case '#':
2982 /* next arg is a magnification to use */
2983 if ( sscanf(tcp + 1, "%ld", &usermag) != 1 )
2984 Fatal("Argument of mag is not a valid integer\n");
2985 break;
2986 case '0':
2987 usermag = 1000;
2988 break;
2989 case 'h':
2990 case 'H':
2991 usermag = 1095;
2992 break;
2993 case '1':
2994 usermag = 1200;
2995 break;
2996 case 'q':
2997 usermag = 1250;
2998 break;
2999 case '2':
3000 usermag = 1440;
3001 break;
3002 case '3':
3003 usermag = 1728;
3004 break;
3005 case '4':
3006 usermag = 2074;
3007 break;
3008 case '5':
3009 usermag = 2488;
3010 break;
3011 default:
3012 Fatal("%c is a bad mag step\n", *tcp);
3013 }
3014 break;
3015 #ifdef SUPERCOMMENT
3016 case 'o': /* PostScript command to send */
3017 if ( ++argind >= argc )
3018 Fatal("No argument following -o\n", 0);
3019 PScmd[nps++] = argv[argind];
3020 break;
3021 #endif
3022 case 'p': /* print n pages */
3023 if ( sscanf(tcp + 1, FMT_long4, &PrintPages) != 1 )
3024 Fatal("Argument is not a valid integer\n");
3025 if (PrintPages < 1)
3026 Fatal("Argument of -p must be greater than 0\n");
3027 break;
3028 case 'q': /* quiet operation */
3029 G_quiet = _TRUE;
3030 break;
3031 case 'r': /* switch order to process pages */
3032 Reverse = (bool)(!Reverse);
3033 break;
3034 #ifdef LJ
3035 case 's': /* specify X-origin in dots */
3036 this_arg = 0;
3037 if (!(*++tcp)) this_arg = (++argind >= argc ? 0 : argv[argind]);
3038 else this_arg = tcp;
3039 if (!this_arg || sscanf(this_arg,"%hd", &pagesize) != 1)
3040 Fatal("Argument of -s is not a valid integer\n");
3041 /*
3042 * The pgsiz_dots value assumes a resolution of 300dpi. This loses
3043 * at 600dpi so we will scale them below for the LJ4.
3044 */
3045 switch (pagesize) {
3046 case 1: pgsiz_dots = 10.5 * 300; break; /* executive */
3047 case 2: pgsiz_dots = 11 * 300; break; /* letter */
3048 case 3: pgsiz_dots = 14 * 300; break; /* legal */
3049 case 6: pgsiz_dots = 17 * 300; break; /* ledger */
3050 case 25: pgsiz_dots = 210 * 300 / 25.4; break; /* a5 */
3051 case 26: pgsiz_dots = 297 * 300 / 25.4; break; /* a4 */
3052 case 27: pgsiz_dots = 420 * 300 / 25.4; break; /* a3 */
3053 case 45: pgsiz_dots = 257 * 300 / 25.4; break; /* jis b5 */
3054 case 46: pgsiz_dots = 354 * 300 / 25.4; break; /* jis b4 */
3055 case 71: pgsiz_dots = 148 * 300 / 25.4; break; /* hagaki postcard */
3056 case 72: pgsiz_dots = 148 * 300 / 25.4; break; /* oufuku-hagaki */
3057 case 80: pgsiz_dots = 7.5 * 300; break; /* monarch envelope */
3058 case 81: pgsiz_dots = 9.5 * 300; break; /* com10 envelope */
3059 case 90: pgsiz_dots = 220 * 300 / 25.4; break; /* int dl */
3060 case 91: pgsiz_dots = 229 * 300 / 25.4; break; /* int c5 */
3061 case 100: pgsiz_dots = 250 * 300 / 25.4; break; /* int b5 */
3062 default: Fatal(
3063 #ifndef vms
3064 "%hd is a bad value for pagesize (1,2,3,26,80,81,90,91)",
3065 #else
3066 "%d is a bad value for pagesize (1,2,3,26,80,81,90,91)",
3067 #endif
3068 pagesize);
3069 }
3070 break;
3071 #endif
3072 case 't': /* ending pagenumber */
3073 if ( sscanf(tcp + 1, FMT_long4, &LastPage) != 1 )
3074 Fatal("Argument is not a valid integer\n");
3075 LastPageSpecified = _TRUE;
3076 break;
3077 case 'v': /* verbatim mode (print pxl-file names) */
3078 G_verbose = _TRUE;
3079 break;
3080
3081 #ifdef LJ
3082 case 'V': /* bugfixes for various vendor's PCL emulations */
3083 tcp++;
3084 if (*tcp == 'K' || *tcp == 'k')
3085 kyocera_mode = _TRUE;
3086 else
3087 if (*tcp == 'B' || *tcp == 'b')
3088 brother_mode = _TRUE;
3089 # ifdef LJ4
3090 else
3091 if (*tcp == '6' || *tcp == '6')
3092 LJ6 = _TRUE;
3093 # endif
3094 break;
3095 #endif
3096
3097 case 'w': /* don't print out warnings */
3098 G_nowarn = _TRUE;
3099 break;
3100 #ifdef LJ
3101 case 'z':
3102 PrintTestPage = (bool)(!PrintTestPage);
3103 break;
3104 #endif
3105 #ifdef LJ4
3106 case 'R': /* number of copies to print */
3107 if ( sscanf(tcp + 1, "%d", &RESOLUTION) != 1 )
3108 Fatal("Argument of -R is not a valid integer\n");
3109 if (RESOLUTION != 300 && RESOLUTION != 600 ) {
3110 Warning("Resolution must be 300 or 600! Assuming 300.dpi.");
3111 RESOLUTION = 300;
3112 } else {
3113 if (RESOLUTION == 600) {
3114 MFMODE = MFMODE600;
3115 x_origin = 600;
3116 y_origin = 600;
3117 }
3118 }
3119 break;
3120 case 'W': /* Set minimum width of compressed raster characters */
3121 CompressCharWidth = atoi(tcp+1);
3122 break;
3123 case 'C': /* Set compression mode to use for raster characters */
3124 UseCompression = atoi(tcp+1);
3125 if ((UseCompression != 0) && (UseCompression != 2) && (UseCompression != 3))
3126 Fatal("Unsupported compression mode %d\n",UseCompression);
3127 break;
3128 case 'n': /* Download fonts raw */
3129 CompressFontMode = _FALSE;
3130 break;
3131 #endif
3132 #ifdef __riscos
3133 case 'i': /* name of directory to store diagrams in */
3134 tcp++;
3135 ddi = 0;
3136 while (*tcp != ' ' && *tcp != '\0' && ddi < DIAGDIRSIZE-1) {
3137 diagdir[ddi++] = *tcp++;
3138 }
3139 diagdir[ddi] = '\0';
3140 break;
3141 case 'j': /* don't print digrams */
3142 printdiag = _FALSE;
3143 break;
3144 case 'k': /* cache diagram bitmap in document folder */
3145 cachediag = _TRUE;
3146 break;
3147 case 'P':
3148 RasterMultipass = 1;
3149 break;
3150 #endif
3151 default:
3152 fprintf(ERR_STREAM, "%c is not a valid flag\n", *tcp);
3153 }
3154 } else {
3155
3156 filename = tcp;
3157 if (EQ(filename, "-")) {
3158 EmitFileName = "-";
3159 #ifdef RISC_USE_OSL
3160 dvifp = BINOPEN("Kbd:");
3161 #else
3162 dvifp = stdin;
3163 if (O_BINARY && !isatty(fileno(dvifp)))
3164 (void)AssureBinary(fileno(dvifp));
3165 #endif
3166 } else {
3167 /* Since this code is used only once during startup, we don't care
3168 about free()ing the allocated strings that represent filenames.
3169 It will be more work to realize proper deallocation handling than
3170 it's worth in terms of saving a few bytes. We consider these
3171 bytes actually static memory where we don't know the size in
3172 advance and don't add them to the allocated_storage count.
3173 [27 Jun 07 -js] */
3174 #ifdef KPATHSEA
3175 /* split into directory + file name */
3176 int tcplen, argvlen;
3177 ctcp = xbasename(argv[argind]);/* this knows about any kind of slashes */
3178 tcplen = strlen(ctcp);
3179 if ( tcplen == 0 ) {
3180 /* This happens when the DVI file name has a trailing slash; this
3181 is not a valid name. Then we terminate the argument parsing
3182 loop, a usage message will be output below. */
3183 break;
3184 }
3185 argvlen = strlen(argv[argind]);
3186 if (tcplen == argvlen)
3187 curarea = xstrdup("");
3188 else {
3189 curarea = xstrdup(argv[argind]);
3190 curarea[argvlen-tcplen] = '\0';
3191 }
3192 #else
3193 ctcp = strrchr(argv[argind], '/');
3194 /* split into directory + file name */
3195 if (ctcp == NULL) {
3196 curarea = xstrdup("");
3197 ctcp = argv[argind];
3198 } else {
3199 curarea = xstrdup(argv[argind]);
3200 curarea[ctcp-argv[argind]+1] = '\0';
3201 ctcp += 1;
3202 }
3203 #endif
3204
3205 curname = (char *) xmalloc(strlen(ctcp)+5); /* + space for ".dvi" */
3206 (void) strcpy(curname, ctcp);
3207 /* split into file name + extension */
3208 tcp1 = strrchr(curname, '.');
3209 if (tcp1 == NULL) {
3210 rootname = xstrdup(curname);
3211 strcat(curname, ".dvi");
3212 } else {
3213 *tcp1 = '\0';
3214 rootname = xstrdup(curname);
3215 *tcp1 = '.';
3216 }
3217
3218 filename = (char *) xmalloc(strlen(curarea)+strlen(curname)+1);
3219 (void) strcpy(filename, curarea);
3220 (void) strcat(filename, curname);
3221
3222 if ((dvifp = BINOPEN(filename)) == FPNULL) {
3223 /* do not insist on .dvi */
3224 if (tcp1 == NULL) {
3225 filename[strlen(filename) - 4] = '\0';
3226 dvifp = BINOPEN(filename);
3227 }
3228 if (dvifp == FPNULL) {
3229 #ifdef MSC5
3230 Fatal("%s: can't find DVI file \"%s\"\n\n",
3231 G_progname, filename);
3232 #else
3233 perror(filename);
3234 exit (EXIT_FAILURE);
3235 #endif
3236 }
3237 }
3238 } /* dvi filename != '-" */
3239 }
3240 argind++;
3241 }
3242
3243 #ifdef LJ4
3244 pgsiz_dots *= (int)(RESOLUTION/300); /* rescale dots to page */
3245 #endif
3246 x_goffset = (short) MM_TO_PXL(x_offset) + x_origin;
3247 y_goffset = (short) MM_TO_PXL(y_offset) + y_origin;
3248
3249 if (dvifp == FPNULL) {
3250 fprintf(ERR_STREAM,"\nThis is the DVI to %s converter %s",
3251 PRINTER, VERSION);
3252 #ifdef SEVENBIT
3253 fprintf(ERR_STREAM,", 7bit");
3254 #endif
3255 fprintf(ERR_STREAM," (%s)\n", OS);
3256 fprintf(ERR_STREAM,"usage: %s [OPTION]... DVIFILE\n", G_progname);
3257
3258 fprintf(ERR_STREAM,"OPTIONS are:\n");
3259 #ifdef DEBUG
3260 fprintf(ERR_STREAM,"\t--D ..... turns debug output on\n");
3261 #endif
3262 #ifndef KPATHSEA
3263 fprintf(ERR_STREAM,
3264 "\t-aX ..... X= searchpath leading to pixel-files (.pk or .pxl)\n");
3265 #endif
3266 #ifdef IBM3812
3267 fprintf(ERR_STREAM,
3268 "\t-b ..... take paper for first page from alternate casette\n");
3269 #endif
3270 fprintf(ERR_STREAM,"\t-cX ..... X= number of copies\n");
3271 #ifdef LJ4
3272 fprintf(ERR_STREAM,"\t-CX ..... X= compression mode for raster chars; can be 0,2,3 (default=%d)\n", DEFAULT_COMPRESS_MODE);
3273 #endif
3274 #ifdef LJ2P
3275 fprintf(ERR_STREAM,"\t-dX ..... duplex, X=1: long-edge, 2: short-edge binding\n");
3276 #endif
3277 fprintf(ERR_STREAM,"\t-D ..... turns doublepage output on; ");
3278 fprintf(ERR_STREAM,"-D1 odd pages only, -D2 even\n");
3279 #ifdef LJ4
3280 fprintf(ERR_STREAM,"\t-E ..... print in econo-mode\n");
3281 #endif
3282 fprintf(ERR_STREAM,"\t-eX ..... X= output file\n");
3283 fprintf(ERR_STREAM,"\t-fX ..... print from begin of page number X\n");
3284 #ifdef LJ
3285 fprintf(ERR_STREAM,
3286 "\t-g ..... do not reset printer at begin of job (go)\n");
3287 #endif
3288 #ifdef __riscos
3289 fprintf(ERR_STREAM,"\t-iX ..... X= name of dir to cache diagrams in\n");
3290 fprintf(ERR_STREAM,"\t-j ..... don't print diagrams\n");
3291 fprintf(ERR_STREAM,"\t-k ..... cache diagram bitmaps\n");
3292 #endif
3293 fprintf(ERR_STREAM,"\t-hX ..... X= name of headerfile\n");
3294 #ifdef LJ2P
3295 fprintf(ERR_STREAM,"\t-l ..... landscape mode\n");
3296 #endif
3297 #ifdef MAKETEXPK
3298 fprintf(ERR_STREAM,"\t-MX ..... Don't generate missing PK files\n");
3299 #endif
3300 fprintf(ERR_STREAM,"\t-mX ..... magnification X=0;h;1;2;3;4;5;#xxxx\n");
3301 #ifdef LJ4
3302 fprintf(ERR_STREAM,"\t-n ..... download fonts raw (default: compressed)\n");
3303 #endif
3304 fprintf(ERR_STREAM,"\t-pX ..... print X pages\n");
3305 #ifdef __riscos
3306 fprintf(ERR_STREAM,"\t-P ..... Process printouts in 2 passes\n");
3307 #endif
3308 fprintf(ERR_STREAM,"\t-q ..... quiet operation\n");
3309 fprintf(ERR_STREAM,"\t-r ..... process pages in reverse order\n");
3310 #ifdef LJ4
3311 fprintf(ERR_STREAM,"\t-RX ..... set resolution to 300 or 600 dpi\n");
3312 #endif
3313 #ifdef LJ
3314 fprintf(ERR_STREAM,"\t-sX ..... set paper size to X (see documentation)\n");
3315 #endif
3316 fprintf(ERR_STREAM,"\t-tX ..... print to end of page number X\n");
3317 fprintf(ERR_STREAM,"\t-w ..... don't print out warnings\n");
3318 #ifdef LJ4
3319 fprintf(ERR_STREAM,"\t-WX ..... X= minimum width of compressed chars (default=%d)\n",
3320 DEFAULT_COMPRESS_WIDTH);
3321 #endif
3322 fprintf(ERR_STREAM,"\t-v ..... tell user which pixel-files are used\n");
3323 #ifdef LJ
3324 fprintf(ERR_STREAM,"\t-VX .... Vendor options (kyocara or brother)\n");
3325 #endif
3326 fprintf(ERR_STREAM,"\t-xX ..... X= x-offset on printout in mm\n");
3327 fprintf(ERR_STREAM,"\t-yX ..... X= y-offset on printout in mm\n");
3328 fprintf(ERR_STREAM,"\t-XO ..... O= x page origin in dots (default=%d)\n",
3329 XDEFAULTOFF );
3330 fprintf(ERR_STREAM,"\t-YO ..... O= y page origin in dots (default=%d)\n",
3331 YDEFAULTOFF );
3332 #ifdef LJ
3333 fprintf(ERR_STREAM,"\t-z ..... print test page with pagecounter after job\n");
3334 #endif
3335 fprintf(ERR_STREAM,"\t- ..... dvifile is stdin (must be seekable); implies -e-\n");
3336 #ifdef KPATHSEA
3337 {
3338 putc ('\n', ERR_STREAM);
3339 fputs (kpse_bug_address, ERR_STREAM);
3340 }
3341 #endif
3342 exit(1);
3343 }
3344 if (EQ(EmitFileName, "")) {
3345 tcp = (char *) xmalloc(strlen(rootname)+sizeof(EMITFILE_EXTENSION));
3346 (void) strcpy(tcp, rootname);
3347 strcat(tcp, EMITFILE_EXTENSION);
3348 EmitFileName = tcp;
3349 }
3350 if (G_quiet)
3351 G_verbose = _FALSE;
3352 }
3353
3354 /*-->DoConv*/
3355 /*********************************************************************/
3356 /******************************** DoConv ***************************/
3357 /*********************************************************************/
3358 long4
DoConv(long4 num,long4 den,int convResolution)3359 DoConv(long4 num, long4 den, int convResolution)
3360 {
3361 /*register*/ double conv;
3362 conv = ((double)num / (double)den) *
3363 ((double)mag / 1000.0) *
3364 ((double)convResolution/254000.0);
3365
3366 return((long4)((1.0/conv)+0.5));
3367 }
3368 /*------------------------ end dviconv.c -------------------------------*/
3369
3370
3371 /*------------------------ begin dvimisc.c -----------------------------*/
3372 /*-->AllDone*/
3373 /**********************************************************************/
3374 /****************************** AllDone ******************************/
3375 /**********************************************************************/
AllDone(bool PFlag)3376 void AllDone(bool PFlag)
3377 {
3378 #ifdef TIMING
3379 double time;
3380 #endif
3381
3382 if (DoublePage && (PageParity==1)) { /* Shall we go around again?*/
3383 int k;
3384 char n[STRSIZE];
3385
3386 if (PrintEmptyPages && EvenPage && Reverse && PrintFirstPart) {
3387 WouldPrint ++;
3388 qfprintf(ERR_STREAM,"[EvenPage] ");
3389 FormFeed();
3390 }
3391 #ifdef LJ
3392 Reverse = (bool)!Reverse;
3393 #endif
3394 if (Reverse) {
3395 if (!PFlag) {
3396 FSEEK(dvifp, postambleptr, SEEK_SET);
3397 (void) NoSignExtend(dvifp, 1);
3398 ppagep = (long) NoSignExtend(dvifp, 4);
3399 }
3400 FSEEK(dvifp, ppagep, SEEK_SET);
3401 } else {
3402 FSEEK(dvifp, 14l, SEEK_SET);
3403 k = (int)NoSignExtend(dvifp, 1);
3404 GetBytes(dvifp, n, k);
3405 }
3406
3407 if (PrintSecondPart) {
3408 if (PrintFirstPart) {
3409 qfprintf(ERR_STREAM,"\n----------------------starting second pass\n");
3410 #ifdef LJ
3411 EMIT1("\033&l2H"); /* Manual Feed */
3412 #endif
3413 #ifdef IBM3812
3414 PMPout(6,"\326\001\305\300\326\252");
3415 /* set display; ring bell; stop; clear display */
3416 PMPflush;
3417 #endif
3418 }
3419
3420 if (PrintEmptyPages && Reverse) {
3421 if (ZeroPage) WouldPrint++;
3422 if ((WouldPrint%2) == 1) {
3423 qfprintf(ERR_STREAM,"[Padding] ");
3424 FormFeed();
3425 }
3426 }
3427 WouldPrint = 0;
3428 if (PrintEmptyPages && !Reverse && ZeroPage) {
3429 WouldPrint++;
3430 qfprintf(ERR_STREAM,"[ZeroPage] ");
3431 FormFeed();
3432 }
3433 PageParity = 0;
3434 PrintPages = StartPrintPages;
3435 return;
3436 }
3437 }
3438
3439 if (EvenPage && DoublePage && !Reverse) WouldPrint++;
3440
3441 if (PrintEmptyPages && DoublePage && PrintSecondPart) {
3442 if (Reverse) {
3443 if (ZeroPage) {
3444 WouldPrint ++;
3445 qfprintf(ERR_STREAM,"[ZeroPage] ");
3446 FormFeed();
3447 }
3448 }
3449 else if ((WouldPrint%2) != 0) {
3450 qfprintf(ERR_STREAM,"[Padding] ");
3451 FormFeed();
3452 }
3453 }
3454
3455 #ifdef IBM3812
3456 PMPout(10, "\373\010PMP.init"); /* re-init printer */
3457 PMPflush;
3458
3459 if (used_fontstorage > MAXFONTSTORAGE) {
3460 Warning("\n\7used font_storage of %s: %ld Bytes (of %ld)\7",
3461 PRINTER, (long)used_fontstorage, MAXFONTSTORAGE);
3462 Warning("Try to format file in separate runs!");
3463 } else
3464 qfprintf(ERR_STREAM,"\nAll done, used font_storage of %s: %ld Bytes (of %ld)",
3465 PRINTER, (long)used_fontstorage, MAXFONTSTORAGE);
3466 #endif
3467 #ifdef LJ
3468 # ifdef SHARP_JX_9500
3469 if (used_fontstorage > MAXFONTSTORAGE) {
3470 Warning("\n\7used font_storage of %s: %ld Bytes (of %ld)\7",
3471 PRINTER, (long)used_fontstorage, MAXFONTSTORAGE);
3472 Warning("Try to format file in separate runs!");
3473 } else
3474 qfprintf(ERR_STREAM,"\nAll done, used font_storage of %s: %ld Bytes (of %ld)",
3475 PRINTER, (long)used_fontstorage, MAXFONTSTORAGE);
3476 # else
3477 qfprintf(ERR_STREAM,"\nAll done, used font_storage of %s: %ld Bytes",
3478 PRINTER, (long)used_fontstorage);
3479 # endif
3480 #ifdef LJ_RESIDENT_FONTS
3481 qfprintf(ERR_STREAM," + %d resident font%s", resident_count,
3482 resident_count == 1 ? "" : "s");
3483 #endif
3484 EMIT1("\033E");
3485 #ifdef LJ4
3486 EMIT1("\033%%-12345X"); /* what does it? */
3487 #endif
3488 if (PrintTestPage) EMIT1("\033z");
3489 #ifdef vms
3490 /* last record is not flushed to file, unless it is completely filled */
3491 for (kk = (int)((*outfp)->_cnt); kk > 0; --kk)
3492 putc('\0',outfp);
3493 fflush(outfp);
3494 #endif
3495 #endif
3496
3497 if (!G_quiet) {
3498 fprintf(ERR_STREAM,"\nDynamically allocated storage: %ld Bytes \n",
3499 (long)allocated_storage);
3500 fprintf(ERR_STREAM,"%d characters downloaded as soft fonts\n", G_ncdl);
3501
3502 #ifdef TIMING
3503 #ifdef BSD_TIME_CALLS
3504 ftime(&timebuffer);
3505 time = (timebuffer.time + (float)(timebuffer.millitm)/1000.0) - start_time;
3506 #else
3507 gettimeofday(&Tp, NULL);
3508 time = (Tp.tv_sec + (float)(Tp.tv_usec)/1000000.0) - start_time;
3509 #endif
3510
3511 if (ndone > 0) {
3512 fprintf(ERR_STREAM,
3513 "Time of complete run: %.2f seconds, %d page(s), %.2f seconds/page",
3514 time, ndone, time / ndone);
3515 fprintf(ERR_STREAM," (%.2f ppm)\n",(ndone * 60) / time);
3516 }
3517 fprintf(ERR_STREAM,"\n");
3518 #endif
3519 }
3520 CloseFiles();
3521 if ( tmp_dir[0] != '\0' )
3522 rmdir (tmp_dir); /* ignore errors */
3523 exit(G_errenc);
3524 }
3525
3526 /*-->DoSpecial*/
3527 /*********************************************************************/
3528 /***************************** DoSpecial ***************************/
3529 /*********************************************************************/
3530
3531 typedef enum {
3532 ORIENTATION,
3533 RESETPOINTS,
3534 DEFPOINT,
3535 FILL,
3536 GRAY,
3537 my_PATTERN,
3538 COMMENT,
3539 HPFILE,
3540 HPFILE_VERBATIM,
3541 PSFILE_SYNTAX,
3542 PSFILE,
3543 LLX,
3544 LLY,
3545 URX,
3546 URY,
3547 RWI,
3548 RHI
3549 } SpecialKeywords;
3550
3551 KeyDesc KeyTab[] = {
3552 { ORIENTATION, "orientation", Integer},
3553 { RESETPOINTS, "resetpoints", String},
3554 { DEFPOINT, "defpoint", String},
3555 { FILL, "fill", String},
3556 { GRAY, "gray", Integer},
3557 { GRAY, "grey", Integer},
3558 { my_PATTERN, "pattern", Integer},
3559 { COMMENT, "comment", String},
3560 { HPFILE, "hpfile", String},
3561 { HPFILE_VERBATIM, "hpfile-verbatim", String},
3562 { PSFILE_SYNTAX, "dvilj-psfile-syntax", String },
3563 { PSFILE, "psfile", String },
3564 { LLX, "llx", Integer},
3565 { LLY, "lly", Integer},
3566 { URX, "urx", Integer},
3567 { URY, "ury", Integer},
3568 { RWI, "rwi", Integer},
3569 { RHI, "rhi", Integer}
3570 /*,
3571 {"hsize", Dimension},
3572 {"vsize", Dimension},
3573 {"hoffset", Dimension},
3574 {"voffset", Dimension},
3575 {"hscale", Number},
3576 {"vscale", Number}*/
3577 };
3578
3579 #define NKEYS (sizeof(KeyTab)/sizeof(KeyTab[0]))
3580
3581 #ifdef __riscos
3582 # ifdef LJ
3583
3584 /* Compare two strings, ignoring case;
3585 s1 pointer to null-terminated keyword, s2 pointer to parseline;
3586 returns (if successful) pointer to character following keyword in s2 */
StrCompare(char * s1,char * s2,char ** end)3587 bool StrCompare(char *s1, char *s2, char **end)
3588 {
3589 char *a,*b;
3590
3591 a = s1;
3592 b = s2;
3593 while (*a != '\0') {
3594 if (tolower(*a) != tolower(*b)) return(_FALSE);
3595 a++;
3596 b++;
3597 }
3598 *end = b;
3599 return(_TRUE);
3600 }
3601
3602 /* Read <number> integer values from string and store results in
3603 <result>. Returns number + of arguments actually read, end =
3604 pointer to char following last number */
3605 int
ParseNumbers(char * str,int * result,int number,char ** end)3606 ParseNumbers(char *str, int *result, int number, char **end)
3607 {
3608 char *s;
3609 int count = 0;
3610
3611 s = str;
3612 while ((*s != '\0') && (count < number)) {
3613 while ((*s == ' ') || (*s == ',') || (*s == '='))
3614 s++;
3615 if (*s != '\0') {
3616 result[count++] = strtod(s,&s);
3617 }
3618 }
3619 while ((*s == ' ') || (*s == ',') || (*s == '='))
3620 s++;
3621 *end = s;
3622 return(count);
3623 }
3624
3625
3626 /* Diagram commands are parsed separately since the format varies from the one
3627 used by the other special commands. */
ParseDiagram(char * str)3628 bool ParseDiagram(char *str)
3629 {
3630 diagtrafo dt;
3631 char *s,*sh;
3632 char diagname[STRSIZE];
3633 int results[4],no;
3634
3635 s = str;
3636 while (*s == ' ')
3637 s++;
3638 if ((StrCompare("drawfile",s,&s)) || (StrCompare("DVIview_diagram",s,&s))) {
3639
3640 if (printdiag == _FALSE)
3641 return(_TRUE); /* it's a diagram, but don't print */
3642
3643 while ((*s == ' ') || (*s == '='))
3644 s++; /* space or '=' separates keyword/keyval */
3645
3646 if (*s == '\0') {
3647 fprintf(ERR_STREAM,"No filename given for \\special-diagram!\n");
3648 return(_TRUE);
3649 }
3650 sh = diagname;
3651 while ((*s != ' ') && (*s != ',') && (*s != '\0'))
3652 *sh++ = *s++;
3653 *sh = '\0';
3654
3655 /* Set up default values */
3656 dt.scalex = dt.scaley = 100;
3657 dt.cropl = dt.cropb = dt.cropr = dt.cropt = 0;
3658 while (*s != '\0') {
3659 while ((*s == ' ') || (*s == ','))
3660 s++;
3661 if (*s != '\0') {
3662 if (StrCompare("scale",s,&s)) {
3663 if ((no = ParseNumbers(s,results,2,&s)) != 2) {
3664 fprintf(ERR_STREAM,
3665 "Too few arguments (%d) given for <scale> - ignored.\n",no);
3666 }
3667 dt.scalex = results[0];
3668 dt.scaley = results[1];
3669 }
3670 else if (StrCompare("crop",s,&s)) {
3671 if ((no = ParseNumbers(s,results,4,&s)) != 4) {
3672 fprintf(ERR_STREAM,
3673 "Too few arguments (%d) given for <crop> - ignored.\n",no);
3674 }
3675 dt.cropl = results[0];
3676 dt.cropr = results[1];
3677 dt.cropt = results[2];
3678 dt.cropb = results[3];
3679 }
3680 else {
3681 fprintf(ERR_STREAM,"Bad \\special keyword - <%s> ignored\n",s);
3682 /* skip over this word */
3683 while ((*s != ' ') && (*s != ',') && (*s != '=') && (*s != '\0'))
3684 s++;
3685 }
3686 }
3687 }
3688 /* fprintf(ERR_STREAM,"Diagram: %s, scale %d %d, crop %d %d %d %d\n",
3689 diagname,dt.scalex,dt.scaley,dt.cropl,dt.cropb,dt.cropr,dt.cropt);*/
3690 diagram(diagname,&dt);
3691 return(_TRUE);
3692 }
3693 else
3694 return(_FALSE);
3695 }
3696 # endif /* LJ */
3697 #endif /* __riscos */
3698
3699
3700 #ifndef HAVE_MKDTEMP
3701 /* If mkdtemp() is not available, supply an (unsecure) version of it. We try
3702 to use mktemp() to get the temporary directory name, since that maps best
3703 to mkdtemp() behavior. But if mktemp() is also not available, we resort
3704 to tmpnam() which is supposed to be there from the C standard. */
3705 #ifndef HAVE_MKTEMP
3706 #define mktemp tmpnam
3707 #endif
mkdtemp(char * template)3708 static char * mkdtemp ( char * template )
3709 {
3710 if ( mktemp(template) == NULL || template[0] == '\0' ) {
3711 if ( errno == 0 ) errno = EINVAL; /* if it's tmpnam() */
3712 return NULL;
3713 }
3714 #ifdef WIN32
3715 #undef mkdir
3716 #define mkdir(path, mode) mkdir(path)
3717 #endif
3718 if ( mkdir(template, 0700) == -1 ) {
3719 return NULL;
3720 }
3721 return template;
3722 }
3723 #endif
3724
3725
3726 /* interpret a \special command, made up of keyword=value pairs */
DoSpecial(char * str,int n)3727 void DoSpecial(char *str, int n)
3728 {
3729 bool first_keyword = _TRUE;
3730 char xs[STRSIZE], ys[STRSIZE];
3731 char *include_file = NULL;
3732 enum { None, VerbFile, HPFile, PSFile } file_type = None;
3733 float x,y;
3734 long4 x_pos, y_pos;
3735 KeyWord k;
3736 int i, j, j1;
3737 static int GrayScale = 10, Pattern = 1;
3738 static bool GrayFill = _TRUE;
3739 static long4 p_x[MAX_SPECIAL_DEFPOINTS], p_y[MAX_SPECIAL_DEFPOINTS];
3740 static bool need_init_pxy = _TRUE;
3741 int llx=0, lly=0, urx=0, ury=0, rwi=0;
3742
3743 str[n] = '\0';
3744 if ( need_init_pxy ) {
3745 for ( i=0 ; i<MAX_SPECIAL_DEFPOINTS ; i++ )
3746 p_x[i] = p_y[i] = -1;
3747 need_init_pxy = _FALSE;
3748 }
3749
3750 SetPosn(h, v);
3751 #ifdef __riscos
3752 #ifdef LJ
3753 if (ParseDiagram(str))
3754 return;
3755 #endif
3756 #endif
3757
3758 /* When the first keyword is already unknown, we skip the whole special.
3759 This is probably one for another driver and the user got notified
3760 already about the problem. */
3761 while ( (str = GetKeyStr(str, &k)) != NULL ) {
3762 /* get all keyword-value pairs */
3763 if ( k.vt == (ValTyp) None ) { /* no value */
3764 /* Single word might also be "comment", then ignore the rest */
3765 if ( EQ(k.Key, "comment") )
3766 return;
3767 /* For compatibility, single words are taken as file names. But then
3768 the include file must be accessible without being searched with
3769 kpathsea. */
3770 if ( access(k.Key, 0) == 0 ) {
3771 if ( include_file && !kpse_tex_hush ("special") ) {
3772 Warning("More than one \\special file name given, %s ignored", include_file);
3773 free (include_file);
3774 }
3775 include_file = xstrdup(k.Key);
3776 file_type = VerbFile;
3777 } else {
3778 if ( !kpse_tex_hush ("special") )
3779 Warning("Invalid keyword or value in \\special - <%s> ignored", k.Key);
3780 if ( first_keyword )
3781 return;
3782 }
3783 } else if ( GetKeyVal( &k, KeyTab, NKEYS, &i ) && i != -1 ) {
3784 switch (i) {
3785
3786 case ORIENTATION:
3787 #ifdef IBM3812
3788 if ((k.v.i >= 0) && (k.v.i < 4)) {
3789 last_ry = UNKNOWN;
3790 sprintf(PMPformat, "\322%c", (unsigned char)k.v.i);
3791 PMPout(2, PMPformat);
3792 if (k.v.i == 1) Landscape = _TRUE;
3793 else if (k.v.i == 0) Landscape = _FALSE;
3794 }
3795 #endif
3796 #ifdef LJ
3797 if ( k.v.i >= 0 && k.v.i <= 3 ) {
3798 last_rx = last_ry = UNKNOWN;
3799 EMIT2("\033&l%dO\033*rF", (unsigned char)k.v.i);
3800 }
3801 #endif
3802 else {
3803 Warning( "Invalid orientation (%d) given; ignored.", k.v.i);
3804 }
3805 break;
3806
3807 case RESETPOINTS:
3808 for ( i=0 ; i<MAX_SPECIAL_DEFPOINTS ; i++ )
3809 p_x[i] = p_y[i] = -1;
3810 break;
3811
3812 case DEFPOINT:
3813 /* 254 is STRSIZE-1. cpp should be used to construct that number. */
3814 i = sscanf(k.Val,"%d(%254[^,],%254s)",&j,xs,ys);
3815 if (i>0) {
3816 if ( j < 0 || j >= MAX_SPECIAL_DEFPOINTS ) {
3817 Warning ("defpoint %d ignored, must be between 0 and %d",
3818 j, MAX_SPECIAL_DEFPOINTS-1);
3819 break;
3820 }
3821 x_pos = h;
3822 y_pos = v;
3823 if ( i > 1 && sscanf(xs,"%fpt",&x) > 0 )
3824 x_pos = PT_TO_DVI(x);
3825 if ( i > 2 && sscanf(ys,"%fpt",&y) > 0 )
3826 y_pos = PT_TO_DVI(y);
3827 p_x[j]=x_pos;
3828 p_y[j]=y_pos;
3829 } else {
3830 Warning("invalid point definition");
3831 }
3832 break;
3833
3834 case FILL:
3835 /* 254 is STRSIZE-1. cpp should be used to construct that number. */
3836 i = sscanf(k.Val,"%d/%d",&j,&j1);
3837 if (i>1) {
3838 #ifdef LJ
3839 if ( j < 0 || j >= MAX_SPECIAL_DEFPOINTS ) {
3840 Warning ("fill ignored, point %d must be between 0 and %d",
3841 j, MAX_SPECIAL_DEFPOINTS);
3842 break;
3843 }
3844 if ( p_x[j] == -1 ) {
3845 Warning ("fill ignored, point %d is undefined\n", j);
3846 break;
3847 }
3848 if ( j1 < 0 || j1 >= MAX_SPECIAL_DEFPOINTS ) {
3849 Warning ("fill ignored, point %d must be between 0 and %d",
3850 j1, MAX_SPECIAL_DEFPOINTS);
3851 break;
3852 }
3853 if ( p_x[j1] == -1 ) {
3854 Warning ("fill ignored, point %d is undefined\n", j1);
3855 break;
3856 }
3857 SetPosn(p_x[j], p_y[j]);
3858 x_pos = (long4)PIXROUND(p_x[j1]-p_x[j], hconv);
3859 y_pos = (long4)PIXROUND(p_y[j1]-p_y[j], vconv);
3860 if (labs(x_pos)<labs(y_pos)) x_pos = x_pos+3;
3861 else y_pos = y_pos+3;
3862 if (GrayFill) {
3863 EMIT4("\033*c%lda%ldb%dg2P", (long)x_pos, (long)y_pos, GrayScale);
3864 } else {
3865 EMIT4("\033*c%lda%ldb%dg3P", (long)x_pos, (long)y_pos, Pattern);
3866 }
3867 last_rx = last_ry = UNKNOWN;
3868 #endif
3869 }
3870 break;
3871
3872 case GRAY:
3873 if ((k.v.i >= 0) && (k.v.i < 101)) {
3874 GrayScale = k.v.i;
3875 GrayFill = _TRUE;
3876 } else {
3877 Warning( "Invalid gray scale (%d) given; ignored.", k.v.i);
3878 }
3879 break;
3880
3881 case my_PATTERN:
3882 if ((k.v.i >= 0) && (k.v.i < 7)) {
3883 Pattern = k.v.i;
3884 GrayFill = _FALSE;
3885 } else {
3886 Warning( "Invalid pattern (%d) given; ignored.", k.v.i);
3887 }
3888 break;
3889
3890 case COMMENT:
3891 return;
3892 /*NOTREACHED*/
3893 break;
3894
3895 case HPFILE:
3896 if ( include_file && !kpse_tex_hush ("special") ) {
3897 Warning("More than one \\special file name given. %s ignored", include_file);
3898 free(include_file);
3899 }
3900 include_file = xstrdup(k.Val);
3901 file_type = HPFile;
3902 break;
3903
3904 case HPFILE_VERBATIM:
3905 if ( include_file && !kpse_tex_hush ("special") ) {
3906 Warning("More than one \\special file name given. %s ignored", include_file);
3907 free(include_file);
3908 }
3909 include_file = xstrdup(k.Val);
3910 file_type = VerbFile;
3911 break;
3912
3913 case PSFILE_SYNTAX:
3914 if ( EQ(k.Val, "ignore") )
3915 PSFileSyntaxTyp = Ignore;
3916 else if ( EQ(k.Val, "dvilj") )
3917 PSFileSyntaxTyp = PSFile_dvilj;
3918 else
3919 Warning("Ignored invalid value '%s' for dvilj-psfile-syntax", k.Val);
3920 break;
3921
3922 case PSFILE:
3923 if ( include_file ) {
3924 Warning("More than one \\special file name given. %s ignored", include_file);
3925 free(include_file);
3926 }
3927 if ( PSFileSyntaxTyp != Ignore ) {
3928 include_file = xstrdup(k.Val);
3929 file_type = PSFile;
3930 } else {
3931 include_file = NULL;
3932 }
3933 break;
3934
3935 case LLX: llx = k.v.i; break;
3936 case LLY: lly = k.v.i; break;
3937 case URX: urx = k.v.i; break;
3938 case URY: ury = k.v.i; break;
3939 case RWI: rwi = k.v.i; break;
3940 case RHI:
3941 if (!kpse_tex_hush ("special"))
3942 Warning("Whatever rhi was good for once, it is ignored now.");
3943 break;
3944
3945 default:
3946 if ( !kpse_tex_hush ("special") )
3947 Warning("Can't handle %s=%s command; ignored.", k.Key, k.Val);
3948 if ( first_keyword )
3949 return;
3950 break;
3951 }
3952
3953 } else {
3954 if ( !kpse_tex_hush ("special") )
3955 Warning("Invalid keyword or value in \\special - <%s> ignored", k.Key);
3956 if ( first_keyword )
3957 return;
3958 }
3959
3960 free (k.Key);
3961 if ( k.Val != NULL ) free(k.Val);
3962 first_keyword = _FALSE;
3963 }
3964
3965 if ( include_file ) {
3966 char * include_path;
3967 last_rx = last_ry = UNKNOWN;
3968 #ifdef IBM3812
3969 PMPflush;
3970 #endif
3971
3972 /* Search the include file with kpathsea, but don't open it immediately.
3973 If it's a psfile special, it will get passed to Ghostscript. An
3974 include file is often placed at the same place as documents: We use
3975 both a program specific search path and the tex search path. We can
3976 not use kpse_find_tex() as it would call mktex, which we don't want
3977 to do for included PCL files. */
3978 if ( (include_path = kpse_find_file(include_file, kpse_program_binary_format, false)) == NULL &&
3979 (include_path = kpse_find_file(include_file, kpse_tex_format, false)) == NULL ) {
3980 Warning ("Could not locate %s, ignoring inclusion special", include_file);
3981 file_type = None;
3982 } else {
3983 free (include_file);
3984 include_file = include_path;
3985 }
3986
3987 #ifdef LJ
3988 if ( file_type == PSFile) {
3989 /* int height = rwi * (urx - llx) / (ury - lly);*/
3990 int width = urx - llx;
3991 int height = ury - lly;
3992 char cmd[255];
3993 const char *cmd_format = "%s -q -dSIMPLE -dSAFER -dNOPAUSE -sDEVICE=%s -sOutputFile=%s %s %s showpage.ps -c quit";
3994 const char *gs_cmd;
3995 int scale_factor, adjusted_height, adjusted_llx;
3996 const char *printer = "ljetplus"; /* use the most stupid one */
3997
3998 char pcl_file[STRSIZE];
3999 char scale_file[STRSIZE];
4000 FILEPTR scalef;
4001
4002 if ( urx == 0 || ury == 0 || rwi == 0 ) {
4003 /* Since dvips' psfile special has a different syntax, this might
4004 well be one of those specials, i.e., a non-dviljk special. Then
4005 the Warning should be suppressable. */
4006 if ( !kpse_tex_hush ("special") )
4007 Warning ("Ignoring psfile special without urx, ury and rwi attributes");
4008 free (include_file);
4009 return;
4010 }
4011 scale_factor = 3000 * width / rwi;
4012 adjusted_height = height * 300/scale_factor;
4013 adjusted_llx = llx * 300/scale_factor;
4014
4015 /* We cannot use mkstemp, as we cannot pass two open file descriptors
4016 portably to Ghostscript. We don't want to use tmpnam() or tempnam()
4017 either, as they have tempfile creation race conditions. Instead we
4018 create a temporary directory with mkdtemp().
4019 We need to create the temporary directory only once per
4020 run; it will be deleted in AllDone(). */
4021 if ( tmp_dir[0] == '\0' ) {
4022 const char * base_dir, * base_base;
4023 #ifdef WIN32
4024 char *def_tmp;
4025 if ( (base_dir = getenv("WINDIR")) == NULL )
4026 base_dir = "";
4027 def_tmp = concat (base_dir, "/Temp");
4028 if ( (base_dir = getenv("TMPDIR")) == NULL &&
4029 (base_dir = getenv("TMP")) == NULL &&
4030 (base_dir = getenv("TEMP")) == NULL )
4031 #else
4032 # define def_tmp "/tmp"
4033 if ( (base_dir = getenv("TMPDIR")) == NULL )
4034 #endif
4035 base_dir = def_tmp;
4036 else if ( strlen(base_dir) > STRSIZE - sizeof("/dviljkXXXXXX/include.pcl") ) {
4037 Warning ("TMPDIR %s is too long, using %s instead", base_dir, def_tmp);
4038 base_dir = def_tmp;
4039 }
4040 /* FIXME: Actually, we would need a function to sanitize base_dir here.
4041 There may still be constructs like /.. or similar. [03 Jul 07 -js] */
4042 base_base = base_dir;
4043 #ifdef WIN32
4044 if ( isalnum(base_dir[0]) && base_dir[1] == ':' )
4045 base_base += 2;
4046 #endif
4047 if ( IS_DIR_SEP_CH(base_base[0]) && base_base[1] == '\0' ) {
4048 Warning ("Feeling naughty, do we? %s is no temporary directory, dude", base_dir);
4049 base_dir = def_tmp;
4050 }
4051 strcpy (tmp_dir, base_dir);
4052 #ifdef WIN32
4053 free (def_tmp);
4054 #endif
4055 strcat (tmp_dir, "/dviljkXXXXXX");
4056 if ( mkdtemp(tmp_dir) == NULL ) {
4057 Warning ("Could not create temporary directory %s, errno = %d; ignoring include file special",
4058 tmp_dir, errno);
4059 return;
4060 }
4061 }
4062 strcpy(pcl_file, tmp_dir);
4063 strcat(pcl_file, "/include.pcl");
4064 strcpy(scale_file, tmp_dir);
4065 strcat(scale_file, "/scale.ps");
4066
4067 if ( (scalef = BOUTOPEN(scale_file)) == FPNULL ) {
4068 Warning("Unable to open file %s for writing", scale_file );
4069 free (include_file);
4070 unlink(scale_file); /* ignore error */
4071 return;
4072 }
4073 fprintf(scalef, "%.2f %.2f scale\n%d %d translate\n",
4074 300.0/scale_factor, 300.0/scale_factor,
4075 0, adjusted_height == height ? 0 : ury);
4076 BCLOSE( scalef );
4077
4078 #ifdef WIN32
4079 if ( (gs_cmd = getenv("GS_PATH")) == NULL )
4080 gs_cmd = "rungs.exe";
4081 #else
4082 gs_cmd = "gs";
4083 #endif
4084 if ( strlen(cmd_format)-10 + strlen(gs_cmd) + strlen(printer) +
4085 strlen(pcl_file) + strlen(scale_file) + strlen(include_file) +1 >
4086 sizeof(cmd) ) {
4087 Warning ("Ghostscript command for %s would be too long, skipping special", include_file);
4088 free (include_file);
4089 unlink(scale_file); /* ignore errors */
4090 unlink(pcl_file);
4091 return;
4092 }
4093 sprintf(cmd, cmd_format,
4094 gs_cmd, printer, pcl_file, scale_file, include_file);
4095 #ifdef DEBUGGS
4096 fprintf(stderr,
4097 "PS-file '%s' w=%d, h=%d, urx=%d, ury=%d, llx=%d, lly=%d, rwi=%d\n",
4098 include_file, urx - llx, height, urx,ury,llx,lly, rwi);
4099 fprintf(stderr,"%s\n",cmd);
4100 #endif
4101 if (system(cmd)) {
4102 Warning("execution of '%s' returned an error", cmd);
4103 } else {
4104 #ifdef DEBUGGS
4105 fprintf(stderr, "o=%d, h=%d, so=%d, sh=%d\n",
4106 llx, height, adjusted_llx, adjusted_height);
4107
4108 fprintf(stderr, "OLD x=%d, y=%d\n",
4109 (int)PIXROUND(h, hconv) + x_goffset,
4110 (int)PIXROUND(v, vconv) + y_goffset);
4111 #endif
4112 v -= 65536l*adjusted_height; /**300/scale_factor;*/
4113 h -= 65536l*adjusted_llx; /* *300/scale_factor;*/
4114 SetPosn(h, v);
4115 #ifdef DEBUGGS
4116 fprintf(stderr, "NEW x=%d, y=%d\n",
4117 (int)PIXROUND(h, hconv) + x_goffset,
4118 (int)PIXROUND(v, vconv) + y_goffset);
4119 #endif
4120
4121 CopyHPFile( pcl_file );
4122 }
4123 unlink(scale_file); /* ignore errors */
4124 unlink(pcl_file);
4125 }
4126 else
4127 #endif /* LJ */
4128
4129 if ( file_type == HPFile )
4130 CopyHPFile( include_file );
4131 else if ( file_type == VerbFile )
4132 my_CopyFile( include_file );
4133 else if ( file_type == None )
4134 /* do nothing */ ;
4135 else
4136 Warning ("This can't happen: unknown file_type value %d", file_type);
4137
4138 if ( include_file != NULL ) free(include_file);
4139 }
4140 }
4141
4142
4143
4144
4145 /*-->GetKeyStr*/
4146 /**********************************************************************/
4147 /***************************** GetKeyStr ****************************/
4148 /**********************************************************************/
4149 /* Extract first keyword-value pair from string (value part may be null),
4150 * keyword and value are allocated and must be free by caller.
4151 * Return pointer to remainder of string,
4152 * return NULL if none found.
4153 */
GetKeyStr(char * str,KeyWord * kw)4154 char *GetKeyStr(char *str, KeyWord *kw )
4155 {
4156 char *s, *start;
4157 char save_char, quote_char;
4158 if ( !str )
4159 return( NULL );
4160 for (s = str; *s == ' '; s++)
4161 ; /* skip over blanks */
4162 if (*s == '\0')
4163 return( NULL );
4164 start = s++; /* start of keyword */
4165 while ( *s != ' ' && *s != '\0' && *s != '=' ) /* locate end */
4166 s++;
4167 save_char = *s;
4168 *s = '\0';
4169 kw->Key = xstrdup(start);
4170 kw->Val = NULL;
4171 kw->vt = None;
4172 if ( save_char == '\0' ) /* shortcut when we're at the end */
4173 return (s);
4174 *s = save_char; /* restore keyword end char */
4175 while ( *s == ' ' ) s++ ; /* skip over blanks */
4176 if ( *s != '=' ) /* no "=" means no value */
4177 return( s );
4178 for (s++; *s == ' '; s++)
4179 ; /* skip over blanks */
4180 if ( *s == '\'' || *s == '\"' ) /* get string delimiter */
4181 quote_char = *s++;
4182 else
4183 quote_char = ' ';
4184 start = s; /* no increment, might be "" as value */
4185 while ( *s != quote_char && *s != '\0' )
4186 s++; /* locate end of value portion */
4187 save_char = *s;
4188 *s = '\0';
4189 kw->Val = xstrdup(start);
4190 kw->vt = String;
4191 if ( save_char != '\0' ) { /* save_char is now quote_char */
4192 *s = save_char;
4193 if ( quote_char != ' ' ) /* we had real quote chars */
4194 s++;
4195 }
4196 return( s );
4197 }
4198
4199
4200 /*-->GetKeyVal*/
4201 /**********************************************************************/
4202 /***************************** GetKeyVal ****************************/
4203 /**********************************************************************/
4204 /* get next keyword-value pair decode value according to table entry */
GetKeyVal(KeyWord * kw,KeyDesc tab[],int nt,int * tno)4205 bool GetKeyVal(KeyWord *kw, KeyDesc tab[], int nt, int *tno)
4206 {
4207 int i;
4208 char c = '\0';
4209 *tno = -1;
4210 for (i = 0; i < nt; i++)
4211 if ( IsSame(kw->Key, tab[i].Entry) ) {
4212 *tno = tab[i].KeyId;
4213 switch ( tab[i].Typ ) {
4214 case None:
4215 if ( kw->vt != None )
4216 return( _FALSE );
4217 break;
4218 case String:
4219 if ( kw->vt != String )
4220 return( _FALSE );
4221 break;
4222 case Integer:
4223 if ( kw->vt != String )
4224 return( _FALSE );
4225 if ( sscanf(kw->Val, "%d%c", &(kw->v.i), &c) != 1 || c != '\0' )
4226 return( _FALSE );
4227 break;
4228 }
4229 kw->vt = tab[i].Typ;
4230 return( _TRUE );
4231 }
4232 return( _TRUE );
4233 }
4234
4235
4236 /*-->IsSame*/
4237 /**********************************************************************/
4238 /******************************* IsSame *****************************/
4239 /**********************************************************************/
4240 /* compare strings, ignore case */
IsSame(const char * a,const char * b)4241 bool IsSame(const char *a, const char *b)
4242 {
4243 for (; *a; a++, b++)
4244 if ( tolower((unsigned char)*a) != tolower((unsigned char)*b) )
4245 return( _FALSE );
4246
4247 return( *a == *b ? _TRUE : _FALSE );
4248 }
4249
4250
4251 /*-->FindPostAmblePtr*/
4252 /**********************************************************************/
4253 /************************ FindPostAmblePtr **************************/
4254 /**********************************************************************/
4255 /* this routine will move to the end of the file and find the start
4256 of the postamble */
FindPostAmblePtr(long * postambleptr)4257 void FindPostAmblePtr(long *postambleptr)
4258 {
4259 long4 i;
4260 FSEEK(dvifp, 0l, SEEK_END); /* goto end of file */
4261 *postambleptr = FTELL(dvifp) - 4;
4262 FSEEK(dvifp, *postambleptr, SEEK_SET);
4263 while (_TRUE) {
4264 FSEEK(dvifp, --(*postambleptr), SEEK_SET);
4265 if (((i = NoSignExtend(dvifp, 1)) != 223) &&
4266 (i != DVIFORMAT))
4267 Fatal("Bad end of DVI file");
4268 if (i == DVIFORMAT)
4269 break;
4270 }
4271 FSEEK(dvifp, (*postambleptr) - 4, SEEK_SET);
4272 (*postambleptr) = NoSignExtend(dvifp, 4);
4273 FSEEK(dvifp, *postambleptr, SEEK_SET);
4274 }
4275
4276
4277 /*-->ReadPostAmble*/
4278 /**********************************************************************/
4279 /************************** ReadPostAmble ***************************/
4280 /**********************************************************************/
4281 /***********************************************************************
4282 This routine is used to read in the postamble values. It
4283 initializes the magnification and checks the stack height prior to
4284 starting printing the document.
4285 ***********************************************************************/
ReadPostAmble(bool load)4286 void ReadPostAmble(bool load)
4287 {
4288 long4 den, num; /* denominator and numerator */
4289 FindPostAmblePtr(&postambleptr);
4290 if (NoSignExtend(dvifp, 1) != POST)
4291 Fatal("POST missing at head of postamble");
4292 #ifdef DEBUG
4293 if (Debug)
4294 fprintf(ERR_STREAM,"got POST command\n");
4295 #endif
4296 ppagep = (long)NoSignExtend(dvifp, 4);
4297 num = NoSignExtend(dvifp, 4);
4298 den = NoSignExtend(dvifp, 4);
4299 mag = NoSignExtend(dvifp, 4);
4300 if ( usermag > 0 && usermag != mag )
4301 Warning("DVI magnification of %ld over-ridden by user (%ld)",
4302 (long)mag, usermag );
4303 if ( usermag > 0 )
4304 mag = usermag;
4305 hconv = DoConv(num, den, hconvRESOLUTION);
4306 vconv = DoConv(num, den, vconvRESOLUTION);
4307 (void) NoSignExtend(dvifp, 4); /* height-plus-depth of tallest page */
4308 (void) NoSignExtend(dvifp, 4); /* width of widest page */
4309 if (NoSignExtend(dvifp, 2) >= STACK_SIZE)
4310 Fatal("Stack size is too small");
4311 (void) NoSignExtend(dvifp, 2); /* this reads the number of pages in */
4312 /* the DVI file */
4313 #ifdef DEBUG
4314 if (Debug)
4315 fprintf(ERR_STREAM,"now reading font defs");
4316 #endif
4317 if (load)
4318 GetFontDef();
4319 }
4320
4321 #ifdef IBM3812
4322 /*-->PMPLine*/
4323 /**********************************************************************/
4324 /***************************** PMPLine ******************************/
4325 /**********************************************************************/
4326 /* drawing lines on the 3812 using PMP vector commands */
PMPLine(int w,int y,int x)4327 void PMPLine(int w, int y, int x)
4328 {
4329
4330 if ((w == 0) || (x == 0 && y == 0))
4331 return;
4332
4333 /*
4334 fprintf(ERR_STREAM,"w=%d / %d - %d, y=%d / %d - %d, x=%d / %d - %d\n",
4335 w,(char)(w & 0xff),(int)((signed_char)(w & 0xff)),
4336 y,(char)(y & 0xff),(int)((signed_char)(y & 0xff)),
4337 x,(char)(x & 0xff),(int)((signed_char)(x & 0xff)));
4338 */
4339
4340 if ( (((signed_char)(x & 0xff)) == x ) &&
4341 ( ((signed_char)(y & 0xff)) == y ) ) {
4342 PMPcont(6);
4343 PMPout(1, "\370");
4344 EMITWORD(3); /* length of vector */
4345 PMPoutC((unsigned char)(0x80 | 0x00 | (unsigned char) w));
4346 PMPoutC((signed_char)(y & 0xff));
4347 PMPoutC((signed_char)(x & 0xff));
4348 /*
4349 fprintf(ERR_STREAM,"F8 00 03: w=%d, x=%d(%d-%.2X), y=%d(%d-%.2X),\n",
4350 w,x,(char)(x & 0xff),(signed_char)(x & 0xff),
4351 y,(char)(y & 0xff),(signed_char)(y & 0xff));
4352 */
4353
4354 } else {
4355 PMPcont(8);
4356 PMPout(1, "\370");
4357 EMITWORD(4 + 1); /* length of vector */
4358 PMPoutC((unsigned char)(0xC0 | 0x00 | (unsigned char) w));
4359 EMITWORD(y);
4360 EMITWORD(x);
4361 /*
4362 fprintf(ERR_STREAM,"F8 00 05: w=%d, x=%d, y=%d,\n", w,x,y);
4363 */
4364 }
4365 }
4366
4367
4368 #endif
4369 /*-->SetRule*/
4370 /**********************************************************************/
4371 /***************************** SetRule ******************************/
4372 /**********************************************************************/
4373 /* this routine will draw a rule */
SetRule(long4 a,long4 b,int Set)4374 void SetRule(long4 a, long4 b, int Set)
4375 {
4376 long4 xx, yy;
4377 #ifdef IBM3812
4378 short hor_offset, vert_offset, ll;
4379 #endif
4380 if ( a > 0 && b > 0 ) {
4381 SetPosn(h, v); /* lower left corner */
4382 xx = (long4)PIXROUND(b, hconv); /* width */
4383 yy = (long4)PIXROUND(a, vconv); /* height */
4384
4385 #ifdef DEBUG
4386 if (Debug)
4387 fprintf(ERR_STREAM,"Rule xx=%ld, yy=%ld\n", (long)xx, (long)yy);
4388 #endif
4389
4390 #ifdef IBM3812
4391 hor_offset = (short)(last_ry - yy);
4392 if (hor_offset < 0) yy += hor_offset;
4393 if (last_rx < 0) xx += last_rx;
4394
4395 if (Landscape) {
4396 if (last_ry > MAX_PAGE_WIDTH) yy += MAX_PAGE_WIDTH-last_ry;
4397 hor_offset = (short)(MAX_PAGE_HEIGHT - (last_rx + xx));
4398 } else {
4399 if (last_ry > MAX_PAGE_HEIGHT) yy += MAX_PAGE_HEIGHT-last_ry;
4400 hor_offset = (short)(MAX_PAGE_WIDTH - (last_rx + xx));
4401 }
4402 if (hor_offset < 0) xx += hor_offset;
4403
4404 if ((xx > 31) && (yy > 31)) {
4405 /*
4406 * fill area by multiple lines (kind of a mess)
4407 * process for simplicity always horizontally
4408 */
4409
4410 /*
4411 fprintf(ERR_STREAM,"large box: w=%d,x=%d,y=%d\n",(int)yy,(int)xx,0);
4412 */
4413
4414 hor_offset = HOR_HALF(30);
4415 MoveHor(hor_offset);
4416 vert_offset = VERT_HALF(30);
4417 MoveVert(-vert_offset);
4418 ll = (short)xx - 30;
4419
4420 for (; yy > 30; yy -= 30) {
4421 PMPLine(30, 0, ll);
4422 MoveHor(-ll);
4423 MoveVert(-30);
4424 }
4425
4426 hor_offset = -hor_offset + HOR_HALF(yy);
4427 MoveHor(hor_offset);
4428 vert_offset = (vert_offset - 30) + VERT_HALF(yy);
4429 MoveVert(-vert_offset);
4430
4431 PMPLine((int)yy, 0, (int)(xx - yy));
4432
4433 } else if ( (yy < xx) && (xx > 0) ) {
4434
4435 /* fprintf(ERR_STREAM, "hori rule: w=%d, x=%d, y=%d\n",(int)yy,(int)(xx-yy),0);*/
4436
4437 hor_offset = HOR_HALF(yy);
4438 vert_offset = VERT_HALF(yy);
4439
4440 MoveHor(hor_offset);
4441 MoveVert(-vert_offset);
4442
4443 PMPLine((int)yy, 0, (int)(xx - yy));
4444 } else if ( (xx < yy) && (yy > 0)) {
4445
4446 hor_offset = HOR_HALF(xx);
4447 vert_offset = VERT_HALF(xx);
4448 /*
4449 fprintf(ERR_STREAM, "move: x=%d, y=%d\n",hor_offset,-vert_offset);
4450 fprintf(ERR_STREAM, "vert rule: w=%d, x=%d, y=%d\n",(int)xx,0,(int)-(yy-xx));
4451 */
4452 MoveHor(hor_offset);
4453 MoveVert(-vert_offset);
4454
4455 PMPLine((int)xx, (int)-(yy - xx), 0);
4456 } else if (xx == yy) {
4457 short y0; /* small square box!! */
4458
4459 y0 = (short)yy / 2;
4460 hor_offset = HOR_HALF(y0);
4461 MoveHor(hor_offset);
4462 vert_offset = VERT_HALF(y0);
4463 MoveVert(-vert_offset);
4464 ll = (short)xx - y0;
4465
4466 PMPLine((int)y0, 0, ll);
4467
4468 hor_offset = - (ll + hor_offset);
4469 vert_offset = (y0 - vert_offset);
4470
4471 yy -= (long4)y0;
4472 hor_offset += HOR_HALF(yy);
4473 MoveHor(hor_offset);
4474 vert_offset += VERT_HALF(yy);
4475 MoveVert(-vert_offset);
4476
4477 PMPLine((int)yy, 0, (int)xx - yy);
4478 }
4479 #endif
4480 #ifdef LJ
4481 if (last_ry + 1 < yy) yy = last_ry + 1;
4482 if (last_rx < 0) xx += last_rx;
4483
4484 if ((int)pgsiz_dots > 0 && (int)last_ry > (int)pgsiz_dots)
4485 yy += (long4)pgsiz_dots - (long4)last_ry;
4486
4487 if ((yy>0) && (xx>0))
4488 EMIT4("\033*p-%ldY\033*c%lda%ldbP",
4489 (long)yy - 1, (long)xx, (long)yy);
4490 #endif
4491 last_rx = last_ry = UNKNOWN; /* next time full positioning */
4492 }
4493 if (Set)
4494 h += b;
4495 }
4496
4497
4498
4499 /*-->FormFeed*/
4500 /**********************************************************************/
4501 /***************************** FormFeed ******************************/
4502 /**********************************************************************/
FormFeed(void)4503 void FormFeed(void)
4504 {
4505
4506 #ifdef IBM3812
4507 unsigned short pages;
4508 if ( ndone == 0 && FirstAlternate ){
4509 for (pages = 1; pages < ncopies; pages++) {
4510 PMPout(2, "\321\300"); /* PMP-command xD1C0 */
4511 }
4512 PMPout(2, "\321\100"); /* PMP-command xD140 */
4513 } else {
4514 for (pages = 1; pages < ncopies; pages++){
4515 PMPout(2, "\321\200"); /* PMP-command xD180 */
4516 }
4517 PMPout(2, "\321\0"); /* PMP-command xD100 */
4518 }
4519 #endif
4520 #ifdef LJ
4521 EMITC('\f');
4522 #endif
4523 }
4524 /*------------------------ end dvimisc.c -------------------------------*/
4525
4526
4527
4528
4529 /*------------------------ begin dvifont.c -----------------------------*/
4530 /*-->GetFontDef*/
4531 /**********************************************************************/
4532 /**************************** GetFontDef *****************************/
4533 /**********************************************************************/
GetFontDef(void)4534 void GetFontDef(void)
4535 /***********************************************************************
4536 Read the font definitions as they are in the postamble of the DVI
4537 file.
4538 ***********************************************************************/
4539 {
4540 unsigned char byte;
4541 while (((byte = (unsigned char) NoSignExtend(dvifp, 1)) >= FNT_DEF1) &&
4542 (byte <= FNT_DEF4)) {
4543 switch (byte) {
4544 case FNT_DEF1:
4545 ReadFontDef( NoSignExtend(dvifp, 1));
4546 break;
4547 case FNT_DEF2:
4548 ReadFontDef( NoSignExtend(dvifp, 2));
4549 break;
4550 case FNT_DEF3:
4551 ReadFontDef( NoSignExtend(dvifp, 3));
4552 break;
4553 case FNT_DEF4:
4554 ReadFontDef( NoSignExtend(dvifp, 4));
4555 break;
4556 default:
4557 Fatal("Bad byte value in font defs");
4558 break;
4559 }
4560 }
4561 if (byte != POST_POST)
4562 Fatal("POST_POST missing after fontdefs");
4563 }
4564
4565
4566
4567
4568 /*-->OpenFontFile*/
4569 /**********************************************************************/
4570 /************************** OpenFontFile *****************************/
4571 /**********************************************************************/
OpenFontFile(void)4572 void OpenFontFile(void)
4573 /***********************************************************************
4574 The original version of this dvi driver reopened the font file each
4575 time the font changed, resulting in an enormous number of relatively
4576 expensive file openings. This version keeps a cache of up to
4577 MAXOPEN open files, so that when a font change is made, the file
4578 pointer, pxlfp, can usually be updated from the cache. When the
4579 file is not found in the cache, it must be opened. In this case,
4580 the next empty slot in the cache is assigned, or if the cache is
4581 full, the least used font file is closed and its slot reassigned for
4582 the new file. Identification of the least used file is based on the
4583 counts of the number of times each file has been "opened" by this
4584 routine. On return, the file pointer is always repositioned to the
4585 beginning of the file.
4586 ***********************************************************************/
4587
4588 #if MAXOPEN > 1
4589
4590 {
4591 int i, least_used, current;
4592 struct pixel_list tmp;
4593 FILEPTR fid;
4594 struct font_entry *fp;
4595
4596 #ifdef DEBUG
4597 if (Debug)
4598 fprintf(ERR_STREAM,"open font file %s\n", fontptr->name);
4599 #endif
4600 /*
4601 fprintf(ERR_STREAM,"? %lx == %lx\n", pfontptr,fontptr);
4602 */
4603 if ((pfontptr == fontptr) && (pxlfp != NO_FILE))
4604 return; /* we need not have been called */
4605
4606 if (fontptr->font_file_id == NO_FILE)
4607 return; /* we need not have been called */
4608
4609 tmp = pixel_files[1];
4610 current = 1;
4611 while (current <= nopen && tmp.pixel_file_id != fontptr->font_file_id) {
4612 ++current;
4613 tmp = pixel_files[current];
4614 }
4615 /* try to find file in open list */
4616
4617 if (current <= nopen) /* file already open */ {
4618 if ( pixel_files[current].pixel_file_id != NO_FILE ) {
4619 pxlfp = pixel_files[current].pixel_file_id;
4620 /* reposition to start of file */
4621 FSEEK(pxlfp, 0l, SEEK_SET);
4622 }
4623 } else {
4624 /* file not in open list */
4625 if (nopen < MAXOPEN) /* just add it to list */
4626 current = ++nopen;
4627 else {
4628 /* list full -- find least used file, */
4629 /* close it, and reuse slot for new file */
4630 least_used = 1;
4631 for (i = 2; i <= MAXOPEN; ++i)
4632 if (pixel_files[least_used].use_count > pixel_files[i].use_count)
4633 least_used = i;
4634 if ((fid = pixel_files[least_used].pixel_file_id) != NO_FILE) {
4635 /* mark file as being closed in the entry */
4636 fp = hfontptr;
4637 while (fp != NULL && fp->font_file_id != fid)
4638 fp = fp->next;
4639 if (fp == NULL)
4640 Fatal("Open file %x not found in font entry list.\n", fid);
4641 else {
4642 fp->font_file_id = FPNULL;
4643 }
4644 BCLOSE( fid );
4645 }
4646 #ifdef DEBUG
4647 if (Debug)
4648 fprintf(ERR_STREAM,"\n__reuse slot %d\n", least_used);
4649 #endif
4650 current = least_used;
4651 }
4652 if ((pxlfp = BINOPEN(fontptr->name)) == FPNULL) {
4653 Warning("PXL-file %s could not be opened", fontptr->name);
4654 pxlfp = NO_FILE;
4655 } else {
4656 #ifdef DEBUG
4657 if (Debug)
4658 fprintf(ERR_STREAM,"Opening File <%s> /%p/, Size(font_entry)=%d\n",
4659 fontptr->name, pxlfp, sizeof(struct font_entry ));
4660 #endif
4661
4662 }
4663 pixel_files[current].pixel_file_id = pxlfp;
4664 pixel_files[current].use_count = 0;
4665 }
4666 pfontptr = fontptr; /* make previous = current font */
4667 fontptr->font_file_id = pxlfp; /* set file identifier */
4668 pixel_files[current].use_count++; /* update reference count */
4669 #ifndef USEPXL
4670 gfin = pxlfp;
4671 #endif
4672 }
4673
4674 #else /* ! MAXOPEN > 1 */
4675
4676 {
4677 FILEPTR f;
4678 struct font_entry *fp;
4679
4680 if (pfontptr == fontptr && pxlfp != NO_FILE)
4681 return; /* we need not have been called */
4682 if (fontptr->font_file_id == NO_FILE)
4683 return; /* we need not have been called */
4684
4685 f = pfontptr->font_file_id;
4686 if (f != FPNULL) {
4687 if (pxlfp != FPNULL) {
4688 fp = hfontptr;
4689 while ((fp != NULL) && (fp->font_file_id != f))
4690 fp = fp->next;
4691
4692 if (fp == NULL)
4693 Fatal("Open file %x not found in font entry list.\n",f);
4694 else
4695 fp->font_file_id = FPNULL;
4696 }
4697 BCLOSE(f);
4698 }
4699 if ((pxlfp = BINOPEN(fontptr->name)) == FPNULL) {
4700 Warning("PXL-file %s could not be opened", fontptr->name);
4701 pxlfp = NO_FILE;
4702 }
4703 pfontptr = fontptr;
4704 fontptr->font_file_id = pxlfp;
4705 }
4706
4707 #endif
4708
4709
4710 /*-->PixRound*/
4711 /**********************************************************************/
4712 /***************************** PixRound *****************************/
4713 /**********************************************************************/
PixRound(long4 x,long4 conv)4714 long4 PixRound(long4 x, long4 conv)
4715 {
4716 return((x + conv) / conv);
4717 }
4718
4719
4720 #ifdef LJ_RESIDENT_FONTS
4721 /*-->TryResident*/
4722 /**********************************************************************/
4723 /**************************** TryResident ***************************/
4724 /**********************************************************************/
4725 static bool
TryResident(struct font_entry * fontptr)4726 TryResident(struct font_entry *fontptr)
4727 {
4728 tfm_info_type tfm_info;
4729
4730 /* To determine if a font is resident, check for a special family
4731 value (header bytes 12..16 in the TFM file). This seems cleaner,
4732 and certainly more convenient, than somehow reading an external
4733 ljfonts.map file in which we'd have to specify information for all
4734 the resident fonts. */
4735 if (tfm_read_info(fontptr->n, &tfm_info)
4736 && tfm_info.family[0]
4737 && EQ((char *)tfm_info.family, "HPAUTOTFM")) {
4738 unsigned i;
4739 double factor = fontptr->s / (double)0x100000;
4740
4741 resident_count++;
4742 fontptr->resident_p = _TRUE;
4743 strncpy(fontptr->symbol_set, (char *)tfm_info.coding_scheme, 39);
4744 fontptr->symbol_set[39] = '\0';
4745 fontptr->resid = tfm_info.typeface_id;
4746 fontptr->spacing = tfm_info.spacing;
4747 fontptr->style = tfm_info.style;
4748 fontptr->weight = tfm_info.weight;
4749
4750 if (fontptr->spacing == SPACING_FIXED) {
4751 /* Have to select the point in pitch (characters per inch) instead
4752 of point size, and thus have to figure out the pitch that
4753 corresponds to the point size at which the font is used.
4754
4755 To do this, take the width of the interword space, and see how
4756 many of those characters will fit in the at size. Then convert
4757 to how many characters will fit in one inch. That's our pitch.
4758
4759 All the builtin LJ4 fonts that are monospaced are Intellifont,
4760 which have 72.307 points per inch. Not that it really makes any
4761 difference. We don't worry about this elsewhere, since all
4762 point sizes are rounded to .25pt anyway, which is more than the
4763 difference between the various definitions of `point'. */
4764 double ds_in_points = fontptr->s / 65536.0;
4765 double w_in_points = tfm_info.interword / (double)0x100000;
4766 if (ds_in_points == 0 || w_in_points == 0) {
4767 /* Avoid division by zero if no interword space. */
4768 Warning("%s: Can't determine pitch for this monospaced font.\n",
4769 fontptr->n);
4770 fontptr->pitch = 10; /* Result will look awful, which is good. */
4771 } else {
4772 fontptr->pitch = 72.307 / (ds_in_points * w_in_points);
4773 }
4774 }
4775
4776 #ifdef DEBUG
4777 if (Debug)
4778 fprintf(ERR_STREAM,"%6s: typeface=%u\tspacing=%u\tstyle=%u\tweight=%d\n",
4779 fontptr->n, fontptr->resid, fontptr->spacing,
4780 fontptr->style, fontptr->weight);
4781 #endif
4782 for (i = 0; i < NFNTCHARS; i++) {
4783 struct char_entry *cptr = &(fontptr->ch[i]);
4784 cptr->tfmw = (long4)(tfm_info.widths[i] * factor);
4785 cptr->cw = ((fontptr->ch[i].tfmw) / (double)hconv) + .5;
4786 cptr->width =
4787 cptr->height =
4788 cptr->xOffset =
4789 cptr->yOffset =
4790 cptr->yyOffset = 0;
4791 }
4792 return _TRUE;
4793 } else {
4794 fontptr->resident_p = _FALSE;
4795 return _FALSE;
4796 }
4797 }
4798 #endif
4799
4800
4801
4802 /*-->ReadFontDef*/
4803 /**********************************************************************/
4804 /**************************** ReadFontDef ***************************/
4805 /**********************************************************************/
4806
skip_specials(long4 * pkloc)4807 unsigned char skip_specials(long4 *pkloc)
4808 {
4809 long4 i, j;
4810 register unsigned char flag_byte;
4811 do {
4812 flag_byte = (unsigned char) NoSignExtend(pxlfp, 1);
4813 /*
4814 fprintf(ERR_STREAM,"flagbyte = %d, pkloc=%ld\n",(int)flag_byte,(long)*pkloc);
4815 */
4816
4817 (*pkloc) ++;
4818 if (flag_byte >= 240)
4819 switch (flag_byte) {
4820 case 240:
4821 case 241:
4822 case 242:
4823 case 243 : {
4824 i = 0;
4825 for (j = 240; j <= (long4)flag_byte; j++) {
4826 i = 256 * i + NoSignExtend(pxlfp, 1);
4827 (*pkloc) ++;
4828 }
4829 for (j = 1; j <= i; j++) {
4830 (void) NoSignExtend(pxlfp, 1);
4831 (*pkloc) ++;
4832 }
4833 break;
4834 }
4835 case 244 : {
4836 i = NoSignExtend(pxlfp, 4);
4837 (*pkloc) += 4;
4838 break;
4839 }
4840 case 245 :
4841 break;
4842 case 246 :
4843 break;
4844 case 247:
4845 case 248:
4846 case 249:
4847 case 250:
4848 case 251:
4849 case 252:
4850 case 253:
4851 case 254:
4852 case 255: {
4853 Fatal("Unexpected flagbyte %d!\n", (int)flag_byte);
4854 }
4855 }
4856 } while (!((flag_byte < 240) || (flag_byte == PK_POST)));
4857 return(flag_byte);
4858 }
4859
4860
ReadFontDef(long4 k)4861 void ReadFontDef(long4 k)
4862 {
4863 long4 t;
4864 unsigned short i;
4865 struct font_entry *tfontptr; /* temporary font_entry pointer */
4866 struct char_entry *tcharptr; /* temporary char_entry pointer */
4867 static int plusid = 0;
4868 bool font_found = _FALSE;
4869 #ifdef LJ_RESIDENT_FONTS
4870 bool resident_font_located = _FALSE;
4871 #endif
4872 #ifdef LJ
4873 int depth, max_depth;
4874 #endif
4875
4876 #ifdef DEBUG
4877 if (Debug)
4878 fprintf(ERR_STREAM,"Mallocating %d Bytes)...\n", sizeof(struct font_entry ));
4879 #endif
4880
4881 if ((tfontptr = NEW(struct font_entry )) == NULL)
4882 Fatal("can't malloc space for font_entry");
4883
4884 allocated_storage += sizeof(struct font_entry );
4885
4886 tfontptr->next = hfontptr;
4887 tfontptr->font_file_id = FPNULL;
4888 fontptr = hfontptr = tfontptr;
4889 tfontptr->ncdl = 0;
4890 tfontptr->k = k;
4891 tfontptr->c = NoSignExtend(dvifp, 4); /* checksum */
4892 tfontptr->s = NoSignExtend(dvifp, 4); /* space size */
4893 tfontptr->d = NoSignExtend(dvifp, 4); /* design size */
4894 tfontptr->a = (int)NoSignExtend(dvifp, 1); /* length for font name */
4895 tfontptr->l = (int)NoSignExtend(dvifp, 1); /* device length */
4896
4897 #ifdef LJ
4898 tfontptr->max_width = tfontptr->max_height = tfontptr->max_yoff =
4899 max_depth = 0;
4900 #endif
4901
4902 GetBytes(dvifp, tfontptr->n, tfontptr->a + tfontptr->l);
4903 tfontptr->n[tfontptr->a+tfontptr->l] = '\0';
4904
4905 tfontptr->font_mag =
4906 (long4)((ActualFactor((long4)(1000.0*tfontptr->s/(double)tfontptr->d+0.5))
4907 * ActualFactor(mag)
4908 #ifdef USEPXL
4909 * RESOLUTION * 5.0
4910 #else
4911 * RESOLUTION
4912 #endif
4913 ) + 0.5);
4914 /*
4915 printf("[%ld]=%lf * %lf * %lf + 0.5 = %ld\n",
4916 ((long)(1000.0*tfontptr->s/(double)tfontptr->d+0.5)),
4917 ActualFactor((long4)(1000.0*tfontptr->s/(double)tfontptr->d+0.5)),
4918 ActualFactor(mag),
4919 (double)RESOLUTION * 5,
4920 (long)tfontptr->font_mag );
4921 */
4922
4923 #ifdef LJ_RESIDENT_FONTS
4924 /* Pass in the name; fills in resident_p and resid (if resident). */
4925
4926 resident_font_located = (bool)TryResident(tfontptr);
4927
4928 if (tfontptr->resident_p)
4929 return;
4930
4931 if (!(resident_font_located))
4932 #endif
4933
4934 {
4935 kpse_glyph_file_type font_ret;
4936 char *name;
4937 unsigned dpi
4938 = kpse_magstep_fix ((unsigned) (tfontptr->font_mag / 5.0 + .5),
4939 RESOLUTION, NULL);
4940 tfontptr->font_mag = dpi * 5; /* save correct dpi */
4941
4942 name = kpse_find_pk (tfontptr->n, dpi, &font_ret);
4943 if (name)
4944 {
4945 font_found = _TRUE;
4946 tfontptr->name = name;
4947 allocated_storage += strlen(name)+1;
4948
4949 if (!FILESTRCASEEQ (tfontptr->n, font_ret.name)) {
4950 fprintf (stderr,
4951 "dvilj: Font %s not found, using %s at %d instead.\n",
4952 tfontptr->n, font_ret.name, font_ret.dpi);
4953 tfontptr->c = 0; /* no checksum warning */
4954 }
4955 else if (!kpse_bitmap_tolerance ((double)font_ret.dpi, (double) dpi))
4956 fprintf (stderr,
4957 "dvilj: Font %s at %d not found, using %d instead.\n",
4958 tfontptr->name, dpi, font_ret.dpi);
4959 if (G_verbose)
4960 fprintf(stderr,"%d: using font <%s>\n", plusid,tfontptr->name);
4961 }
4962 else
4963 {
4964 tfontptr->font_file_id = NO_FILE;
4965 fprintf (stderr,
4966 "dvilj: Font %s at %u not found, characters will be left blank.\n",
4967 tfontptr->n, dpi);
4968 }
4969 }
4970
4971 tfontptr->plusid = plusid;
4972 plusid++;
4973
4974 /* sprintf(tfontptr->psname,"%s.%ld.%d",
4975 tfontptr->n, (long)tfontptr->font_mag, (long)tfontptr->plusid);*/
4976
4977 #ifdef LJ
4978 if (plusid >= HANDLE_MAX_FONTS)
4979 Fatal("can handle only %d fonts! ask a wizzard...\n",
4980 HANDLE_MAX_FONTS);
4981 #endif
4982 if (tfontptr != pfontptr) {
4983 if (font_found)
4984 OpenFontFile();
4985 else
4986 pxlfp = NO_FILE;
4987 }
4988 #ifdef USEPXL
4989 if ( pxlfp == NO_FILE ) { /* allow missing pxl files */
4990 tfontptr->magnification = 0;
4991 tfontptr->designsize = 0;
4992 #endif
4993 for (i = FIRSTFNTCHAR; i <= LASTFNTCHAR; i++) {
4994 tcharptr = &(tfontptr->ch[i]);
4995 #ifdef USEPXL
4996 tcharptr->width = 0;
4997 tcharptr->height = 0;
4998 tcharptr->xOffset = 0;
4999 tcharptr->yOffset = 0;
5000 #endif
5001 tcharptr->where.isloaded = _FALSE;
5002 tcharptr->where.address.fileOffset = NONEXISTANT;
5003 tcharptr->tfmw = 0;
5004 }
5005 #ifdef USEPXL
5006 return;
5007 }
5008 t = NoSignExtend(pxlfp, 1);
5009 if (t == 0) {
5010 t = NoSignExtend(pxlfp, 1);
5011 t = NoSignExtend(pxlfp, 2);
5012 if (t == 1002)
5013 tfontptr->id = id1002;
5014 else if (t == 1001)
5015 tfontptr->id = id1001;
5016 else
5017 Fatal("Unknown Version of PXL-format\n");
5018 } else {
5019 if (t == PK_PRE) {
5020 unsigned char temp_byte;
5021 temp_byte = (unsigned char) NoSignExtend(pxlfp, 1);
5022 if (temp_byte != PK_ID)
5023 Fatal( "Wrong Version of pk file! (%d should be 89)\n",
5024 (int)temp_byte);
5025 else
5026 tfontptr->id = pk89;
5027 } else
5028 Fatal("unknown font format in file <%s> !\n",fontptr->name);
5029 }
5030
5031 if ((tfontptr->id == id1002) || (tfontptr->id == id1001)) {
5032 FSEEK(pxlfp, -20l, SEEK_END);
5033
5034 t = NoSignExtend(pxlfp, 4);
5035 check_checksum (tfontptr->c, t, tfontptr->name);
5036
5037 tfontptr->magnification = NoSignExtend(pxlfp, 4);
5038 tfontptr->designsize = NoSignExtend(pxlfp, 4);
5039
5040 if (tfontptr->id == id1001)
5041 FSEEK(pxlfp, (long)(NoSignExtend(pxlfp, 4) * 4), SEEK_SET);
5042 else
5043 FSEEK(pxlfp, (long)NoSignExtend(pxlfp, 4), SEEK_SET);
5044
5045 for (i = FIRSTFNTCHAR; i <= 127; i++) { /* only defined for 7bit*/
5046 tcharptr = &(tfontptr->ch[i]);
5047 tcharptr->width = (unsigned short) NoSignExtend(pxlfp, 2);
5048 tcharptr->height = (unsigned short) NoSignExtend(pxlfp, 2);
5049 tcharptr->xOffset = (short) SignExtend(pxlfp, 2);
5050 tcharptr->yOffset = (short) SignExtend(pxlfp, 2);
5051 tcharptr->where.isloaded = _FALSE;
5052 if (tfontptr->id == id1001)
5053 tcharptr->where.address.fileOffset = NoSignExtend(pxlfp,4) * 4;
5054 else
5055 tcharptr->where.address.fileOffset = NoSignExtend(pxlfp,4);
5056 tcharptr->tfmw = (long4)
5057 ( (double)(NoSignExtend(pxlfp, 4))
5058 * (double)tfontptr->s / (double)0x100000 );
5059 tcharptr->cw = (long4)(((double)tcharptr->tfmw/(double)hconv) + 0.5);
5060
5061 if (tcharptr->width > CHAR_WIDTH_LARGE ||
5062 tcharptr->height > CHAR_HEIGTH_LARGE )
5063 tcharptr->charsize = LARGE_SIZE;
5064 else
5065 tcharptr->charsize = SMALL_SIZE;
5066 #ifdef LJ
5067 # define set_max(x,y) if ((y)>(x)) x = y
5068
5069 set_max(tfontptr->max_width,tcharptr->width);
5070 set_max(tfontptr->max_height,tcharptr->height);
5071 if (tcharptr->yOffset > 0 && (int)tfontptr->max_yoff < (int)tcharptr->yOffset)
5072 tfontptr->max_yoff = tcharptr->yOffset;
5073 if ((depth = tcharptr->height - tcharptr->yOffset)>max_depth)
5074 max_depth = depth;
5075 #endif
5076
5077 }
5078 #ifdef LJ
5079 tfontptr->max_height = max_depth ? tfontptr->max_yoff+max_depth :
5080 tfontptr->max_yoff+1;
5081 #endif
5082 } else { /* PK 89 format */
5083 unsigned char temp_byte;
5084 register unsigned char flag_byte;
5085 long4 hppp, vppp, pkloc, packet_length;
5086 int car, ii;
5087
5088 /* read comment */
5089 for ( ii = temp_byte = (unsigned char)NoSignExtend(pxlfp, 1); ii>0; ii--) {
5090 flag_byte = (unsigned char) NoSignExtend(pxlfp, 1);
5091 #ifdef DEBUG
5092 if (Debug) fprintf(ERR_STREAM, "%c", flag_byte );
5093 #endif
5094 }
5095 #ifdef DEBUG
5096 if (Debug) fprintf(ERR_STREAM, "\n");
5097 #endif
5098 pkloc = 3 + (int)temp_byte;
5099 tfontptr->designsize = NoSignExtend(pxlfp, 4);
5100
5101 t = NoSignExtend(pxlfp, 4);
5102 check_checksum (tfontptr->c, t, tfontptr->name);
5103
5104 hppp = NoSignExtend(pxlfp, 4);
5105 vppp = NoSignExtend(pxlfp, 4);
5106 if (hppp != vppp)
5107 Warning("aspect ratio is %ld:%ld (should be 1:1)!",
5108 (long)hppp, (long)vppp);
5109 tfontptr->magnification = (long4)(hppp * 72.27 * 5 / 65536l + 0.5);
5110
5111 pkloc += 16;
5112 flag_byte = skip_specials(&pkloc);
5113
5114 while (flag_byte != PK_POST) {
5115 if ((flag_byte & 7) == 7) {
5116 /* fprintf(ERR_STREAM,"\nRead long character preamble\n"); */
5117
5118 packet_length = (unsigned long4)NoSignExtend(pxlfp,4);
5119 if ((car = (int)NoSignExtend(pxlfp, 4)) > (LASTFNTCHAR))
5120 Fatal("Bad character (%d) in PK-File\n",(int)car);
5121
5122 tcharptr = &(tfontptr->ch[car]);
5123 tcharptr->where.address.fileOffset = pkloc;
5124 /* set pkloc to end_of_packet */
5125 pkloc += packet_length + 8;
5126
5127 tcharptr->tfmw = NoSignExtend(pxlfp, 4);
5128 (void) NoSignExtend(pxlfp, 4); /* horesc not used */
5129 (void) NoSignExtend(pxlfp, 4); /* not used */
5130
5131 tcharptr->width = (unsigned short) NoSignExtend(pxlfp, 4);
5132 tcharptr->height = (unsigned short) NoSignExtend(pxlfp, 4);
5133 tcharptr->xOffset = (short) SignExtend(pxlfp, 4);
5134 tcharptr->yOffset = (short) SignExtend(pxlfp, 4);
5135 tcharptr->where.isloaded = _FALSE;
5136 } else if (flag_byte & 4) {
5137 /* fprintf(ERR_STREAM,"Read extended short character preamble\n"); */
5138
5139 packet_length = ((long4)flag_byte & 3) * 65536l +
5140 (unsigned short) NoSignExtend(pxlfp, 2);
5141 if ((car = (int)NoSignExtend(pxlfp, 1)) > (LASTFNTCHAR))
5142 Fatal("Bad character (%d) in PK-File\n",(int)car);
5143
5144 tcharptr = &(tfontptr->ch[car]);
5145 tcharptr->where.address.fileOffset = pkloc;
5146 /* set pkloc to end_of_packet */
5147 pkloc += packet_length + 3;
5148
5149 tcharptr->tfmw = NoSignExtend(pxlfp, 3);
5150 /*
5151 { register unsigned short t;
5152 t = (unsigned short) NoSignExtend(pxlfp, 1);
5153 tcharptr->tfmw = t * 65536l +
5154 (unsigned short) NoSignExtend(pxlfp, 2);
5155 }
5156 */
5157 /* horesc not used */
5158 (void) NoSignExtend(pxlfp, 2);
5159 tcharptr->width = (unsigned short) NoSignExtend(pxlfp,2);
5160 tcharptr->height = (unsigned short) NoSignExtend(pxlfp,2);
5161 tcharptr->xOffset = (short) SignExtend(pxlfp, 2);
5162 tcharptr->yOffset = (short) SignExtend(pxlfp, 2);
5163 tcharptr->where.isloaded = _FALSE;
5164 } else {
5165 /* fprintf(ERR_STREAM,"<Read short character preamble@>\n"); */
5166
5167 packet_length = ((long4)flag_byte & 3) * 256 +
5168 NoSignExtend(pxlfp, 1);
5169 if ((car = (int)NoSignExtend(pxlfp, 1)) > (LASTFNTCHAR))
5170 Fatal("Bad character (%d) in PK-File\n",(int)car);
5171
5172 tcharptr = &(tfontptr->ch[car]);
5173 tcharptr->where.address.fileOffset = pkloc;
5174 /* set pkloc to end_of_packet */
5175 pkloc += packet_length + 2;
5176
5177 tcharptr->tfmw = NoSignExtend(pxlfp, 3);
5178 /*
5179 { register unsigned short t;
5180 t = (unsigned short) NoSignExtend(pxlfp, 1);
5181 tcharptr->tfmw = t * 65536l +
5182 (unsigned short) NoSignExtend(pxlfp, 2);
5183 }
5184 */
5185 /* horesc not used */
5186 (void) NoSignExtend(pxlfp, 1);
5187 tcharptr->width = (unsigned short) NoSignExtend(pxlfp,1);
5188 tcharptr->height = (unsigned short) NoSignExtend(pxlfp,1);
5189 tcharptr->xOffset = (short) SignExtend(pxlfp, 1);
5190 tcharptr->yOffset = (short) SignExtend(pxlfp, 1);
5191 tcharptr->where.isloaded = _FALSE;
5192 }
5193
5194 tcharptr->tfmw = (long4)
5195 ( tcharptr->tfmw * (double)tfontptr->s / (double)0x100000 );
5196
5197 tcharptr->cw = (long4)(((double)tcharptr->tfmw / (double)hconv) + 0.5);
5198
5199 if (tcharptr->width > CHAR_WIDTH_LARGE ||
5200 tcharptr->height > CHAR_HEIGTH_LARGE )
5201 tcharptr->charsize = LARGE_SIZE;
5202 else
5203 tcharptr->charsize = SMALL_SIZE;
5204
5205 #ifdef LJ
5206 /*
5207 printf("char=%d: this=%d, max_width=%d, this=%d,max_height=%d, this=%d,max_yoff=%d\n",
5208 car, tcharptr->width, tfontptr->max_width,
5209 tcharptr->height,tfontptr->max_height,
5210 tcharptr->yOffset,tfontptr->max_yoff);
5211 */
5212 set_max(tfontptr->max_width, tcharptr->width);
5213 set_max(tfontptr->max_height,tcharptr->height);
5214 if (tcharptr->yOffset > 0 && (int)tfontptr->max_yoff < (int)tcharptr->yOffset)
5215 tfontptr->max_yoff = tcharptr->yOffset;
5216
5217 if ((depth = tcharptr->height - tcharptr->yOffset) > max_depth)
5218 max_depth = depth;
5219 #endif
5220 /*
5221 fprintf(ERR_STREAM,"char=%d, yotcharptr=%lx, flag_byte=%d, font=%lx\n",car, tcharptr,flag_byte,tfontptr);
5222 */
5223 tcharptr->flag_byte = flag_byte;
5224 FSEEK(pxlfp, (long)pkloc, SEEK_SET);
5225 flag_byte = skip_specials(&pkloc);
5226
5227 } /* end of while */
5228 #ifdef LJ
5229 tfontptr->max_height = max_depth ? tfontptr->max_yoff+max_depth :
5230 tfontptr->max_yoff+1;
5231 #endif
5232
5233 /*
5234 printf("fontid=%d: max_width=%u, max_height=%d, max_yoff=%u\n",
5235 tfontptr->plusid, tfontptr->max_width,
5236 tfontptr->max_height, tfontptr->max_yoff);
5237 */
5238
5239 #else /* USEPXL */
5240 if ( pxlfp == NO_FILE ) /* allow missing pxl files */
5241 return;
5242
5243 gfin = pxlfp;
5244 seekpost();
5245 readpost();
5246 check_checksum (tfontptr->c, checksum, tfontptr->name);
5247
5248 for(i = FIRSTFNTCHAR; i<=LASTFNTCHAR; i++) {
5249 if (char_exists[i]) {
5250 tcharptr = &(tfontptr->ch[i]);
5251 tcharptr->tfmw = (long4)(((float)tfm_wd[i]*(float)tfontptr->s) /
5252 (float)((long4)1l<<20));
5253 tcharptr->where.address.fileOffset = char_pointer[i];
5254 }
5255 # ifdef LJ
5256 /* GF USER PLEASE CHECK IF THIS CODE WORKS
5257 tfontptr->max_width = gf_font_max_m;
5258 tfontptr->max_height = gf_font_max_n;
5259 tfontptr->max_yoff = gf_font_min_n;
5260 */
5261 # endif /* LJ */
5262 #endif /* USEPXL */
5263
5264 /*****************************************************************************/
5265 /*if (tcharptr->charsize==LARGE_SIZE)
5266 fprintf(ERR_STREAM,"%d:\t <%c> w=%d h=%d xO=%d yO=%d tfmw=%ld cw=%ld %d\n",
5267 i,(char) i,
5268 tcharptr->width,tcharptr->height,tcharptr->xOffset,tcharptr->yOffset,
5269 (long)tcharptr->tfmw, (long)tcharptr->cw, (int)(tcharptr->charsize));
5270 */
5271 /*****************************************************************************/
5272 }
5273 }
5274
5275
5276
5277
5278
5279 /*-->SetFntNum*/
5280 /**********************************************************************/
5281 /**************************** SetFntNum *****************************/
5282 /**********************************************************************/
5283 void SetFntNum(long4 k, bool Emitting)
5284 /* this routine is used to specify the font to be used in printing future
5285 characters */
5286 {
5287 #ifdef LJ
5288 static unsigned short plusid = 0;
5289 #endif
5290 fontptr = hfontptr;
5291 while ((fontptr != NULL) && (fontptr->k != k))
5292 fontptr = fontptr->next;
5293 if (fontptr == NULL)
5294 Fatal("font %ld undefined", (long)k);
5295 if (Emitting && fontptr->font_file_id != NO_FILE) {
5296 if (!fontptr->used_on_this_page
5297 #ifdef LJ_RESIDENT_FONTS
5298 && !fontptr->resident_p
5299 #endif
5300 ) {
5301 fontptr->used_on_this_page = _TRUE;
5302 #ifdef LJ
5303 if (++fonts_used_on_this_page > MAX_FONTS_PER_PAGE) {
5304 qfprintf(ERR_STREAM,"%s is font #%d font on this page!",
5305 fontptr->n, fonts_used_on_this_page);
5306 qfprintf(ERR_STREAM," (max = %d) rastering characters!\n",
5307 MAX_FONTS_PER_PAGE);
5308 rasterfont[fontptr->plusid] = _TRUE;
5309 }
5310 #endif
5311 }
5312 #ifdef DEBUG
5313 if (Debug)
5314 fprintf(ERR_STREAM, "Switching to font #%ld (%s).\n", k, fontptr->n);
5315 #endif
5316 /* activate font */
5317 #ifdef IBM3812
5318 sprintf(PMPformat, "\323%c", (unsigned char)fontptr->plusid);
5319 PMPout(2, PMPformat);
5320 #endif
5321 #ifdef LJ
5322 if (!rasterfont[fontptr->plusid]) {
5323 #ifdef LJ_RESIDENT_FONTS
5324 if (fontptr->resident_p) {
5325 #ifdef DEBUG
5326 if (Debug)
5327 fprintf(ERR_STREAM, "Resident font #%d.\n", fontptr->resid);
5328 #endif
5329 EMIT2("\033(%s", fontptr->symbol_set);
5330 EMIT4("\033(s%up%.2f%c",
5331 fontptr->spacing,
5332 /* height in points, or pitch */
5333 fontptr->spacing ? fontptr->s / 65536.0 : fontptr->pitch,
5334 fontptr->spacing ? 'v' : 'h' /* height or pitch? */
5335 );
5336 EMIT4("%us%db%uT",
5337 fontptr->style, /* upright, italic, ... */
5338 fontptr->weight, /* regular, bold, ... */
5339 fontptr->resid
5340 );
5341 } else
5342 #endif /* LJ_RESIDENT_FONTS */
5343 if (fontptr->plusid>0) EMIT2("\033(%dX", fontptr->plusid);
5344 else EMIT1("\033(X");
5345 }
5346 /* else fprintf(ERR_STREAM,"I am doing rasterfont for plusid=%d instead\n",
5347 fontptr->plusid);
5348 */
5349 #endif
5350 }
5351 #ifdef LJ /* reassignment of printer font id 0.48 */
5352 else if (fontptr->font_file_id != NO_FILE
5353 #ifdef LJ_RESIDENT_FONTS
5354 && !fontptr->resident_p
5355 #endif
5356 ) {
5357 if (fontptr->ncdl == 0) {
5358 #ifdef DEBUG
5359 if (Debug)
5360 fprintf(ERR_STREAM, "Changing plusid from %d to %d\n",
5361 fontptr->plusid, (int)plusid);
5362 #endif
5363 fontptr->plusid = plusid;
5364 plusid ++;
5365 }
5366 }
5367 #endif
5368 }
5369
5370
5371
5372 /*-->SkipFontDef*/
5373 /**********************************************************************/
5374 /**************************** SkipFontDef ***************************/
5375 /**********************************************************************/
5376 void SkipFontDef(void)
5377 {
5378 int a, l;
5379 char n[STRSIZE];
5380
5381 (void) NoSignExtend(dvifp, 4);
5382 (void) NoSignExtend(dvifp, 4);
5383 (void) NoSignExtend(dvifp, 4);
5384 a = (int)NoSignExtend(dvifp, 1);
5385 l = (int)NoSignExtend(dvifp, 1);
5386 GetBytes(dvifp, n, a + l);
5387 }
5388
5389
5390
5391 /*------------------------ end dvifont.c -------------------------------*/
5392
5393 /*-->Fatal*/
5394 /**********************************************************************/
5395 /****************************** Fatal *******************************/
5396 /**********************************************************************/
5397 void
5398 Fatal (const char *fmt, ...)
5399 {
5400 va_list args;
5401
5402 va_start(args, fmt);
5403 fprintf(ERR_STREAM, "\n");
5404 fprintf(ERR_STREAM, "%s: FATAL--", G_progname);
5405 vfprintf(ERR_STREAM, fmt, args);
5406
5407 fprintf(ERR_STREAM, "\n\n");
5408 va_end(args);
5409 CloseFiles();
5410 #ifndef vms
5411 exit(2);
5412 #else
5413 exit(SS$_ABORT);
5414 #endif
5415 }
5416
5417
5418
5419 /*-->Warning*/
5420 /**********************************************************************/
5421 /***************************** Warning ******************************/
5422 /**********************************************************************/
5423 void /* issue a warning */
5424 Warning(const char *fmt, ...)
5425 {
5426 va_list args;
5427
5428 va_start(args, fmt);
5429
5430 #ifndef vms
5431 G_errenc = 1;
5432 #else
5433 G_errenc = (SS$_ABORT | STS$M_INHIB_MSG); /* no message on screen */
5434 #endif
5435 if ( G_nowarn || G_quiet )
5436 return;
5437
5438 fprintf(ERR_STREAM, "%s: warning: ", G_progname);
5439 vfprintf(ERR_STREAM, fmt, args);
5440 fprintf(ERR_STREAM, "\n");
5441 va_end(args);
5442 }
5443
5444
5445 /* ------------------------------------------------------------
5446 * Local Variables:
5447 * c-file-style: "gnu"
5448 * fill-column: 76
5449 * End:
5450 */
5451