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(&regs, &regs);                 /* 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(&regs, &regs);               /* 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