w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

dvi2xx.c
Go to the documentation of this file.
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
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
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 
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);
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",
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
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)))
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 )
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) {
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
332  } else {
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) {
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 )
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);
605  if (Emitting)
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
654 {
655  if (biact >= binumber) {
656 #ifdef RISC_USE_OSL
658 #else
660 #endif
661  biact = 0;
662  }
663  return binumber == 0 ? 0 : buffin[biact++];
664 }
665 
666 #ifdef RISC_BUFFER
667 void
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
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
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
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
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
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
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
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
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
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
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
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
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 */
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);
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;
1561 
1562 void /* <Read and translate raster description@>*/
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
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
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) {
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
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
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)) {
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 */
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)) {
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
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 */
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
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)
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
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
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
2519 }
2520 
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
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 */
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
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
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 */
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
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')
2883  else
2885  tcp++;
2886  }
2887  if (*tcp == '-')
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");
2913  break;
2914 #ifdef LJ
2915  case 'g': /* do not reset printer (go) */
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");
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)))
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
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
3264  "\t-aX ..... X= searchpath leading to pixel-files (.pk or .pxl)\n");
3265 #endif
3266 #ifdef IBM3812
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
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);
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
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 /**********************************************************************/
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 
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) {
3397  (void) NoSignExtend(dvifp, 1);
3398  ppagep = (long) NoSignExtend(dvifp, 4);
3399  }
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;
3435  return;
3436  }
3437  }
3438 
3439  if (EvenPage && DoublePage && !Reverse) WouldPrint++;
3440 
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) {
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 {
3548  RHI
3550 
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 */
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
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. */
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) {
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) {
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
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 */
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;
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",
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",
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") )
3916  else if ( EQ(k.Val, "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  */
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 */
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 */
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 */
4258 {
4259  long4 i;
4260  FSEEK(dvifp, 0l, SEEK_END); /* goto end of file */
4261  *postambleptr = FTELL(dvifp) - 4;
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);
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 ***********************************************************************/
4287 {
4288  long4 den, num; /* denominator and numerator */
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 */
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 */
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 /**********************************************************************/
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 /**********************************************************************/
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:
4546  break;
4547  case FNT_DEF2:
4549  break;
4550  case FNT_DEF3:
4552  break;
4553  case FNT_DEF4:
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 /**********************************************************************/
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 ) {
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  }
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;
4705 }
4706 
4707 #endif
4708 
4709 
4710 /*-->PixRound*/
4711 /**********************************************************************/
4712 /***************************** PixRound *****************************/
4713 /**********************************************************************/
4715 {
4716  return((x + conv) / conv);
4717 }
4718 
4719 
4720 #ifdef LJ_RESIDENT_FONTS
4721 /*-->TryResident*/
4722 /**********************************************************************/
4723 /**************************** TryResident ***************************/
4724 /**********************************************************************/
4725 static bool
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 
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 
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 =