diff options
Diffstat (limited to 'dviware/ln03/rose/dvi2ln3.lis')
-rw-r--r-- | dviware/ln03/rose/dvi2ln3.lis | 1602 |
1 files changed, 1602 insertions, 0 deletions
diff --git a/dviware/ln03/rose/dvi2ln3.lis b/dviware/ln03/rose/dvi2ln3.lis new file mode 100644 index 0000000000..b8c209889d --- /dev/null +++ b/dviware/ln03/rose/dvi2ln3.lis @@ -0,0 +1,1602 @@ + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 1 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + + + 1 /* Dvi2ln3 translates a TeX DVI file to an LN03 format file. + 2 + 3 Dvi2ln3 is still being developed. Copyright (c) 1985 by Digital Equipment + 4 Corporation, Maynard, Massachusetts, USA. Author: Flavio Rose, + 5 shasta!decwrl!dec-rhea!dec-dvinci!rose. + 6 + 7 Dvi2ln3 is based on the publicly-available program DVItype, written by + 8 David R. Fuchs of Stanford University; and also on earlier DEC programs for + 9 the LN01 and LN03 laser printers, Dvi2lng, Topp and LN03Topp. This program + 10 is not a DEC product and is not guaranteed to work. + 11 + 12 Dvi2ln3 is written in VAX C. Specific VAX and VMS dependencies have + 13 generally been avoided, however. The reader may find them by searching + 14 for the strings VAX and VMS in this file. + 15 + 16 During development, double square brackets [[ ]] in a comment indicate some + 17 places where the code needs to be improved. + 18 + 19 [[Among the useful things that still need to be done: differentiating + 20 between int and long variables so this can be ported more easily to 16-bit + 21 architectures; testing to see if malloc returns 0; a \special for ROM + 22 fonts; a \special for sixels.]] + 23 + 24 Development history: + 25 + 26 Feb. 85: Did some early work on Dvi2ln3, translating bits and pieces + 27 of Dvi2lng. Concluded, however, that it was better to translate + 28 LN03Topp and Dvi2lng into C first. The reason for this is that code + 29 which mimics an existing program is easier to write and to test. + 30 + 31 5/15/85: At this date, the old LN03Topp program has been successfully + 32 translated into C (except for the ability to read files over + 33 DECnet). At this point, did some further cleanup of the Dvi2ln3 + 34 source. + 35 + 36 6/4/85: Coding of Dvi2ln3 begins in earnest. Merging bits and + 37 pieces from various places. Chucking chunks and all that + 38 junk from LN03Topp; pass2 is just straightforward translation. + 39 + 40 6/22/85: Cleanup after initial debugging. Ready to distribute. + 41 + 42 10/14/85: Bug in parsing of \special's. Version 1. + 43 + 44 */ + 45 + 46 #include stdio + 104 + 105 /* To please the VMS linker, we declare all global variables to be + 106 globaldef. This is done with #define's, so it may easily be undone when + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 2 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 107 porting the program to other systems. */ + 108 + 109 #ifdef vms + 110 #define GLOBAL globaldef + 111 #define EXTERN globalref + 112 #else + 113 X #define GLOBAL + 114 X #define EXTERN extern + 115 #endif + 116 + 117 /* hoff is the horizontal offset in pixels to be added to all dimensions + 118 read in; voff is the corresponding vertical offset. */ + 119 + 120 GLOBAL int hoff, voff, startp; + 121 GLOBAL FILE *dvifile,*tfmfile,*outfile; + 122 + 123 /* Each page in a DVI file is identified by ten longwords, which appear + 124 immediately after each bop (beginning of page) command. Dvi2ln3, like + 125 DVItype, supports certain options that allow one to print only selected + 126 pages. The following variables are used for this purpose. + 127 + 128 Num_pages is a count of how many pages have been passed to the output. + 129 Max_pages is the user-specified maximum number of pages to pass. + 130 How_many_counts denotes the number of identifying longwords to take into + 131 account when searching for the user-specified starting page. The user + 132 specifies the starting page as the first one whose identifying longwords + 133 match certain specified values, stored in start_page. However, identifying + 134 longword i is only required to match the value in start_page[i] if + 135 use_count[i] is nonzero. */ + 136 + 137 GLOBAL long int num_pages,max_pages; + 138 GLOBAL int how_many_counts,use_count[10]; + 139 GLOBAL long int start_page[10]; + 140 + 141 /* FILESPECLEN is the maximum size of a file specification under VMS. + 142 [[Perhaps arrays of fixed size should not be used, but rather malloc should + 143 be employed...]] */ + 144 + 145 #define FILESPECLEN 252 + 146 + 147 /* The main routine deals with the command line arguments, opens the dvi + 148 file, and then calls various other routines to handle the "passes". There + 149 are two passes which involve reading the DVI file; in between, the font + 150 load is constructed. */ + 151 + 152 main(argc,argv) + 153 int argc; + 154 char *argv[]; + 155 { + 156 1 int status,i,jnam,jext; + 157 1 char infnam[FILESPECLEN]; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 3 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 158 1 + 159 1 if (argc < 2) { printf("\n Usage: Dvi2ln3 <filename> <options>"); + 160 2 goto exit_label; } + 161 1 + 162 1 printf("\n Dvi2ln3 1"); + 163 1 + 164 1 strcpy(infnam,argv[1]); + 165 1 + 166 1 /* The extension of the input file defaults to .dvi. Locate the filename + 167 1 field within the filespec parameter, set jname to point to beginning, jext + 168 1 to point to one place after end. [[This code is of course dependent on the + 169 1 VMS filespec syntax.]] */ + 170 1 + 171 1 find_VMS_filename(infnam,&jnam,&jext); + 172 1 if (infnam[jext] == '\0') strcat(infnam,".dvi"); + 173 1 dvifile = fopen(infnam,"r"); + 174 1 if (dvifile == NULL) { printf("\n Couldn't open dvi file"); + 175 2 goto exit_label; } + 176 1 + 177 1 /* Now decipher the options off the command line. */ + 178 1 + 179 1 max_pages = 1000000000; + 180 1 how_many_counts = 0; + 181 1 hoff = 300; + 182 1 voff = 300; + 183 1 for (i=2; i<argc; i++) command_line_options(argv[i]); + 184 1 + 185 1 status = pass1(); + 186 1 if (status != 0) goto exit_label; + 187 1 if (rewind(dvifile) == -1) { + 188 2 printf("\n Couldn't rewind dvi file."); + 189 2 goto exit_label; + 190 2 } + 191 1 + 192 1 status = open_output_file(infnam,jnam,jext,".ln3"); + 193 1 if (status != 0) { printf("\n Couldn't open output file"); + 194 2 goto exit_label; } + 195 1 + 196 1 status = make_font_load(); + 197 1 if (status != 0) goto exit_label; + 198 1 + 199 1 pass2(); + 200 1 + 201 1 fprintf(outfile,"\033c"); + 202 1 fclose(dvifile); + 203 1 fclose(outfile); + 204 1 + 205 1 exit_label: + 206 1 ; + 207 1 } + 208 + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 4 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 209 /* Find_VMS_filename finds the filename part of a VMS filespec passed in s, + 210 returning the index of the first character in *ns, and the index of the + 211 character after the last in *ne. + 212 + 213 [[When porting Dvi2ln3 to a non-VMS system, we need to find an alternative + 214 to this function. Under Unix, as a first approximation, we could look for + 215 the last "/" or "~" and then for the first succeeding "." in the filespec. + 216 Is this correct?]] */ + 217 + 218 int find_VMS_filename(s,ns,ne) + 219 char s[]; + 220 int *ns,*ne; + 221 { + 222 1 int jnam,jext,j,slen; + 223 1 + 224 1 slen = strlen(s); + 225 1 jnam = 0; + 226 1 for (j = slen-1; j >= 0; j--) { + 227 2 if (s[j] == ':' || s[j] == ']' || + 228 2 s[j] == '>') { + 229 3 jnam = j+1; + 230 3 break; + 231 3 } + 232 2 } + 233 1 + 234 1 jext = slen; + 235 1 for (j = jnam; j < slen; j++) { + 236 2 if (s[j] == '.' || s[j] == ';') { + 237 3 jext = j; + 238 3 break; + 239 3 } + 240 2 } + 241 1 + 242 1 *ns = jnam; + 243 1 *ne = jext; + 244 1 } + 245 + 246 /* ERROR HANDLING: Errors should be reported as close to the source as + 247 possible, so that the maximum amount of information is available to the + 248 user to identify the error. + 249 + 250 Errors in the format of DVI or TFM files are not reported specifically, + 251 since there exist programs, DVItype and TFtoPL, which diagnose errors in + 252 such files. This program accepts some incorrect DVI files, for example, + 253 those with a bad postamble or bad backpointers. [[However, someday we may + 254 rewrite the program to select pages by using these features of the DVI + 255 format, rather than by skipping unwanted pages.]] */ + 256 + 257 GLOBAL char *bad_DVI_message = "\nBad DVI file - check it with DVItype"; + 258 + 259 /* Command_line_options reads and processes options off the string s. At + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 5 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 260 this time, four options are supported. + 261 + 262 The N option sets the maximum number of pages to be printed. Its syntax is + 263 /N=<integer> . + 264 + 265 The H option modifies the default horizontal offset. + 266 + 267 The V option modifies the default vertical offset. + 268 + 269 The S option has syntax /S=<pagespec>{.<pagespec>}* where the {}* denotes + 270 repetition, and a <pagespec> is either an integer or * to indicate any + 271 value. An example would be "/S=*.8.3". + 272 + 273 The meaning of the S option is as follows: In a DVI file, pages are + 274 identified by ten longword values which follow each bop (beginning of page) + 275 command. The value of the S option indicates which page to start printing + 276 on. For example, "*.8.3" means start printing at the first page whose + 277 second identifying longword is 8 and third is 3. */ + 278 + 279 int command_line_options(t) + 280 char *t; + 281 { + 282 1 long int i,k; + 283 1 char *u; + 284 1 + 285 1 while ((t = strchr(t,'/')) != 0) { + 286 2 t++; + 287 2 if (toupper(t[0]) == 'N' && t[1] == '=' + 288 2 && (sscanf(&t[2],"%ld",&k) == 1)) + 289 2 max_pages = k; + 290 2 if (toupper(t[0]) == 'H' && t[1] == '=' + 291 2 && (sscanf(&t[2],"%ld",&k) == 1)) + 292 2 hoff = k; + 293 2 if (toupper(t[0]) == 'V' && t[1] == '=' + 294 2 && (sscanf(&t[2],"%ld",&k) == 1)) + 295 2 voff = k; + 296 2 else if (toupper(t[0]) == 'S' && t[1] == '=') { + 297 3 t += 2; + 298 3 how_many_counts = 0; + 299 3 for (;;) { + 300 4 if (t[0] == '*') { + 301 5 use_count[how_many_counts] = 0; + 302 5 how_many_counts++; + 303 5 } + 304 4 else if (sscanf(t,"%ld",&k) != 0) { + 305 5 use_count[how_many_counts] = 1; + 306 5 start_page[how_many_counts] = k; + 307 5 how_many_counts++; + 308 5 } else break; + 309 4 u = strchr(t,'.'); + 310 4 if (u == 0) break; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 6 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 311 4 t = &u[1]; + 312 4 } + 313 3 } + 314 2 } + 315 1 } + 316 + 317 /* Open_output_file opens one of the output files, using the file pointer + 318 outfile. The name of the output file is obtained by appending the string + 319 ext to the substring of infnam beginning at jnam and ending at jext. + 320 + 321 [[This code contains a VMS depndency. We use creat followed by fdopen to + 322 open the file as a normal VMS file ("rat=cr","rfm=var") rather than a + 323 STREAM_LF file. Beginning with VAX C V2.0, this can be done by just calling + 324 fopen.]] */ + 325 + 326 int open_output_file(infnam,jnam,jext,ext) + 327 char *infnam,*ext; + 328 int jnam,jext; + 329 { + 330 1 char outfnam[FILESPECLEN]; + 331 1 int jj; + 332 1 + 333 1 strcpy(outfnam,&infnam[jnam]); + 334 1 strcpy(&outfnam[jext-jnam],ext); + 335 1 + 336 1 jj = creat(outfnam,0,"rat=cr","rfm=var"); + 337 1 if (jj == -1) return(1); + 338 1 outfile = fdopen(jj,"w"); + 339 1 if (outfile == NULL) return(1); + 340 1 + 341 1 return(0); + 342 1 } + 343 + 344 /* Bytes are read one by one from the DVI file using getc. We use an + 345 overlay, as suggested in the DVItype documentation, to combine these bytes + 346 into larger integers. [[Note that this technique relies on the fact that + 347 numbers on the VAX are stored with the least significant byte first. The + 348 macros below would have to be changed if the program were to be ported to a + 349 machine architecture for which this is not so.]] + 350 + 351 [[The use of getc is expensive, since getc is a function in VAX C V2.0. + 352 Eventually, one would want to rewrite these macros to work like the old + 353 getc macro.]] */ + 354 + 355 GLOBAL union lc { long int l; unsigned long int ul; char c[4]; + 356 unsigned char uc[4]; } lcx; + 357 + 358 #define two_bytes_u lcx.uc[1] = getc(dvifile); \ + 359 lcx.uc[0] = getc(dvifile); lcx.uc[2] = 0; lcx.uc[3] = 0 + 360 + 361 #define two_bytes_s lcx.c[1] = getc(dvifile); \ + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 7 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 362 lcx.c[0] = getc(dvifile); \ + 363 if (lcx.c[1] >= 0) { lcx.uc[2] = 0; lcx.uc[3] = 0 ;} \ + 364 else { lcx.uc[2] = 255; lcx.uc[3] = 255; } + 365 + 366 #define three_bytes_u lcx.uc[3] = getc(dvifile); lcx.uc[1] = getc(dvifile); \ + 367 lcx.uc[0] = getc(dvifile); lcx.uc[2] = 0 + 368 + 369 #define three_bytes_s lcx.c[2] = getc(dvifile); lcx.c[1] = getc(dvifile); \ + 370 lcx.c[0] = getc(dvifile); \ + 371 lcx.uc[3] = (lcx.c[2] >= 0) ? 0 : 255; + 372 + 373 #define four_bytes lcx.c[3] = getc(dvifile); \ + 374 lcx.c[2] = getc(dvifile); lcx.c[1] = getc(dvifile); \ + 375 lcx.c[0] = getc(dvifile); + 376 + 377 /* Knuth's programs like to hardcode fixed maximum sizes for various + 378 things, for example, the maximum number of fonts allowed in a DVI file. In + 379 general, it is preferable to use the C function malloc to allocate storage + 380 as needed. That is what we generally do in this Dvi2ln3, but there are some + 381 residues of the Knuthian approach, like MAXTEXFONTS below. By the way, we + 382 never attempt to return any storage to the system. + 383 + 384 [[Eventually, it would be better to get rid of MAXTEXFONTS and use a linked + 385 list of records instead. There would be no cpu time penalty to using a + 386 linked list, because the function set_curf below does a linear search + 387 through the font array anyway.]] */ + 388 + 389 #define MAXTEXFONTS 100 + 390 + 391 struct txf { unsigned char chu[256]; int bc, ec; long int space, design_size, + 392 scaled_size; int nchs; }; + 393 + 394 GLOBAL struct txf *txfa[MAXTEXFONTS+1]; + 395 + 396 /* Font width information needs to be read from TFM files. TFM is a special + 397 format defined by TeX. Dvi2ln3 stores each width in a longword. DVItype + 398 tries to save space by a two-level width storage method. We just allocate + 399 an array of widths for each font with malloc. + 400 + 401 [[We don't check that font checksums match in Dvi2ln3, because there are a + 402 lot of slightly obsolete TFMs floating around which would result in a + 403 checksum error, but seem to give perfectly reasonable formatted output + 404 nonetheless.]] */ + 405 + 406 GLOBAL long int *font_width[MAXTEXFONTS+1]; + 407 + 408 /* TeX fonts are referred to by their internal numbers, which go from 0 to + 409 nf-1. The DVI file refers to them by external numbers, hence the array + 410 to_ext used to convert internal numbers to external numbers. Curf is the + 411 internal font number of the current font in the DVI file. */ + 412 + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 8 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 413 GLOBAL int to_ext[MAXTEXFONTS+1], + 414 nf, + 415 curf; + 416 + 417 /* In some switch statements, a lot of cases have to be enumerated. We + 418 employ this Knuthian macro for that purpose: */ + 419 + 420 #define four_cases(_x1) case _x1: case _x1+1: case _x1+2: case _x1+3: + 421 + 422 /* We define a lot of constants corresponding to the DVI operation codes. + 423 These are copied from DVItype. */ + 424 + 425 #define id_byte 2 /* current version of the dvi format */ + 426 #define set_char_0 0 /* typeset character 0 and move right */ + 427 #define set1 128 /* typeset a character and move right */ + 428 #define set_rule 132 /* typeset a rule and move right */ + 429 #define put1 133 /* typeset a character */ + 430 #define put_rule 137 /* typeset a rule */ + 431 #define nop 138 /* no operation */ + 432 #define bop 139 /* beginning of page */ + 433 #define eop 140 /* ending of page */ + 434 #define push 141 /* save the current positions */ + 435 #define pop 142 /* restore previous positions */ + 436 #define right1 143 /* move right */ + 437 #define w0 147 /* move right by |w| */ + 438 #define w1 148 /* move right and set |w| */ + 439 #define x0 152 /* move right by |x| */ + 440 #define x1 153 /* move right and set |x| */ + 441 #define down1 157 /* move down */ + 442 #define y0 161 /* move down by |y| */ + 443 #define y1 162 /* move down and set |y| */ + 444 #define z0 166 /* move down by |z| */ + 445 #define z1 167 /* move down and set |z| */ + 446 #define fnt_num_0 171 /* set current font to 0 */ + 447 #define fnt1 235 /* set current font */ + 448 #define xxx1 239 /* extension to dvi primitives (\special) */ + 449 #define xxx4 242 /* potentially long extension to dvi primitives */ + 450 #define fnt_def1 243 /* define the meaning of a font number */ + 451 #define pre 247 /* preamble */ + 452 #define post 248 /* postamble beginning */ + 453 #define post_post 249 /* postamble ending */ + 454 #define undefined_command 250 + 455 + 456 GLOBAL long int mag, num, den; + 457 GLOBAL float conv, unmag_conv; + 458 + 459 /* Read_preamble reads the preamble of the dvi file. The comment is thrown + 460 away. The format version number is checked. The magnification, numerator, + 461 and denominator are remembered in the globals mag, num, den. The float + 462 values conv and unmag_conv serve to convert measurements from DVI units to + 463 pixels. */ + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 9 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 464 + 465 int read_preamble() { + 466 1 unsigned int i; + 467 1 int j; + 468 1 + 469 1 i = getc(dvifile); + 470 1 if (i != pre) return(1); + 471 1 i = getc(dvifile); + 472 1 if (i != id_byte) return(1); + 473 1 four_bytes; num = lcx.l; + 474 1 if (num <= 0) return(1); + 475 1 four_bytes; den = lcx.l; + 476 1 if (den <= 0) return(1); + 477 1 four_bytes; mag = lcx.l; + 478 1 if (mag <= 0) return(1); + 479 1 + 480 1 unmag_conv = (num/254000.0) * (300.0/den); + 481 1 conv = unmag_conv * (mag/1000.0); + 482 1 + 483 1 /* Skip over the comment field. */ + 484 1 + 485 1 i = getc(dvifile); + 486 1 for (j=0; j<i; j++) getc(dvifile); + 487 1 return(0); + 488 1 } + 489 + 490 /* The dvi file format requires us to keep track of various quantities, + 491 among them the horizontal and vertical positions h and v, and four values + 492 referred to simply as x, y, z and w. We also keep pixel-rounded versions + 493 of h and v, called hh and vv. */ + 494 + 495 GLOBAL long h, v, x, y, z, w; + 496 GLOBAL int hh, vv; + 497 + 498 /* The following function, copied from DVItype, reads from the DVI file the + 499 first parameter of the current DVI command. In the case of functions whose + 500 first parameter is implicit, such as set_char_0 through set_char_127, the + 501 implicit parameter is returned. */ + 502 + 503 long first_par(o) + 504 int o; + 505 { + 506 1 unsigned int i; + 507 1 + 508 1 if ((o >= set_char_0) && (o < set_char_0+128)) + 509 1 return(o-set_char_0); + 510 1 if ((o >= fnt_num_0) && (o < fnt_num_0+64)) + 511 1 return(o-fnt_num_0); + 512 1 switch (o) { + 513 2 case set1: + 514 2 case put1: + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 10 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 515 2 case fnt1: + 516 2 case xxx1: + 517 2 case fnt_def1: + 518 2 i = getc(dvifile); + 519 2 return(i); + 520 2 case set1+1: + 521 2 case put1+1: + 522 2 case fnt1+1: + 523 2 case xxx1+1: + 524 2 case fnt_def1+1: + 525 2 two_bytes_u; + 526 2 return(lcx.ul); + 527 2 case set1+2: + 528 2 case put1+2: + 529 2 case fnt1+2: + 530 2 case xxx1+2: + 531 2 case fnt_def1+2: + 532 2 three_bytes_u; + 533 2 return(lcx.ul); + 534 2 case right1: + 535 2 case w1: + 536 2 case x1: + 537 2 case down1: + 538 2 case y1: + 539 2 case z1: + 540 2 return(getc(dvifile)); + 541 2 case right1+1: + 542 2 case w1+1: + 543 2 case x1+1: + 544 2 case down1+1: + 545 2 case y1+1: + 546 2 case z1+1: + 547 2 two_bytes_s; + 548 2 return(lcx.l); + 549 2 case right1+2: + 550 2 case w1+2: + 551 2 case x1+2: + 552 2 case down1+2: + 553 2 case y1+2: + 554 2 case z1+2: + 555 2 three_bytes_s; + 556 2 return(lcx.l); + 557 2 case set_rule: + 558 2 case put_rule: + 559 2 case right1+3: + 560 2 case w1+3: + 561 2 case x1+3: + 562 2 case down1+3: + 563 2 case y1+3: + 564 2 case z1+3: + 565 2 case set1+3: + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 11 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 566 2 case put1+3: + 567 2 case fnt1+3: + 568 2 case xxx1+3: + 569 2 case fnt_def1+3: + 570 2 four_bytes; + 571 2 return(lcx.l); + 572 2 case w0: + 573 2 return(w); + 574 2 case x0: + 575 2 return(x); + 576 2 case y0: + 577 2 return(y); + 578 2 case z0: + 579 2 return(z); + 580 2 default: + 581 2 return(0); + 582 2 } + 583 1 } + 584 + 585 /* Pass1 reads from the DVI file until the starting page condition is met. + 586 Return 1 if something goes wrong, or if the DVI file comes to an end. This + 587 resembles skip_pages below. */ + 588 + 589 int pass1() { + 590 1 + 591 1 unsigned int k; + 592 1 long int p; + 593 1 int i; + 594 1 char startp; + 595 1 + 596 1 if (read_preamble() != 0) { + 597 2 printf(bad_DVI_message); + 598 2 return(1); + 599 2 } + 600 1 + 601 1 for (;;) { + 602 2 if (feof(dvifile)) { + 603 3 printf(bad_DVI_message); + 604 3 return(1); + 605 3 } + 606 2 k = getc(dvifile); + 607 2 if (k == post) return(0); + 608 2 p = first_par(k); + 609 2 if (k >= set_char_0 && k < set_char_0+128) k = set1; + 610 2 if (k >= fnt_num_0 && k < fnt_num_0+64) k = fnt1; + 611 2 + 612 2 switch (k) { + 613 3 case bop: + 614 3 startp = 1; + 615 3 for (i=0; i<10; i++) { + 616 4 four_bytes; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 12 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 617 4 if (i < how_many_counts && use_count[i] && + 618 4 lcx.l != start_page[i]) startp = 0; + 619 4 } + 620 3 four_bytes; + 621 3 if (startp != 0) num_pages = 1; + 622 3 else if (num_pages > 0) { + 623 4 num_pages++; + 624 4 if (num_pages > max_pages) return(0); + 625 4 } + 626 3 break; + 627 3 case set_rule: + 628 3 case put_rule: + 629 3 four_bytes; + 630 3 break; + 631 3 four_cases(fnt_def1) + 632 3 i = define_font(p); + 633 3 if (i != 0) return(1); + 634 3 break; + 635 3 four_cases(fnt1) + 636 3 if (num_pages > 0) set_curf(p); + 637 3 break; + 638 3 four_cases(set1) + 639 3 four_cases(put1) + 640 3 if (num_pages > 0) + 641 3 txfa[curf] -> chu[p] = 1; + 642 3 break; + 643 3 four_cases(xxx1) + 644 3 for (; p>0; p--) getc(dvifile); + 645 3 break; + 646 3 default: + 647 3 break; + 648 3 } + 649 2 } + 650 1 return(0); + 651 1 } + 652 + 653 #define leftfirst 33 + 654 #define rightfirst 161 + 655 #define leftlast 126 + 656 #define rightlast 254 + 657 + 658 /* The define of maxnfonts below is based on a belief, perhaps + 659 superstitious, that there is a limit of 31 downline-loaded fonts in the + 660 LN03. For us an nfont is two LN03 fonts, hence the following definition. */ + 661 + 662 #define maxnfonts 16 + 663 + 664 /* Txf is a record structure describing a TeX font. Txfa is an array of txf + 665 records. Txf2lnf describes the mapping between TeX fonts and pairs of LN03 + 666 fonts. Because the constructed LN03 font load has just the glyphs that are + 667 needed, we can often cram more than one TeX font into a pair of LN03 fonts. + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 13 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 668 + 669 Why a pair of fonts? Because LN03 fonts are allowed to hold 94 glyphs only. + 670 They come in two flavors, "left" which answer to character codes 33 to 126, + 671 and "right" which answer to codes 161 to 254. LN03Topp assigns each TeX + 672 font to one "lnfno", where each lnfno denotes a pair of LN03 fonts, one + 673 left, one right. */ + 674 + 675 GLOBAL int txf2lnf[MAXTEXFONTS]; + 676 + 677 /* Maxfontnos reflects the fact that all LN03 fonts must be denoted by + 678 a number from 10 to 19. */ + 679 + 680 #define maxfontnos 9 + 681 + 682 GLOBAL int lastch[maxnfonts]; + 683 GLOBAL unsigned char chw[maxnfonts][256]; + 684 GLOBAL char fname[maxnfonts][32]; + 685 + 686 /* The LN03 font-denoting numbers 10-19 have to be allocated among the + 687 fonts. The useno array keeps track of which number a font is allowed to + 688 use, -1 if none is currently allocated. The whouses array says which font + 689 is using a number. */ + 690 + 691 GLOBAL int useno[maxnfonts],whouses[maxfontnos]; + 692 + 693 /* Font_name points to strings containing font names, which are created + 694 with malloc as needed. */ + 695 + 696 GLOBAL char *font_name[MAXTEXFONTS+1]; + 697 + 698 GLOBAL int maxrmar,maxbmar; + 699 + 700 #define max(x,y) (((x)>(y))?(x):(y)) + 701 #define min(x,y) (((x)<(y))?(x):(y)) + 702 + 703 /* Make_font_load calls on other procedures to generate the LN03 font load. + 704 */ + 705 + 706 int make_font_load() { + 707 1 + 708 1 int i,j,jj,k,l,fno,maxfno,chsize; + 709 1 long int totsize; + 710 1 int lnfcnt,txfcnt,the_txf,txf_size,lnfleft; + 711 1 int txford[MAXTEXFONTS]; + 712 1 char cnt[3]; + 713 1 + 714 1 totsize = 0; + 715 1 chsize = 0; + 716 1 curf = 0; + 717 1 for (i=0; i<maxnfonts; i++) + 718 1 for (j=0; j<256; j++) chw[i][j] = 0; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 14 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 719 1 + 720 1 for (jj=0; jj<MAXTEXFONTS; jj++) txf2lnf[jj] = -1; + 721 1 + 722 1 /* Fill the fname strings with different valid LN03 font names. */ + 723 1 + 724 1 for (i=0; i<maxnfonts; i++) + 725 1 strcpy(fname[i],"U000000002SK00GG0001UZZZZ02F000"); + 726 1 for (jj=1; jj<maxnfonts; jj++) { + 727 2 sprintf(cnt,"%02d",jj); + 728 2 strncpy(&(fname[jj][5]),cnt,2); + 729 2 } + 730 1 + 731 1 /* The margins are set to values appropriate for American 8 1/2 by 11 + 732 1 paper. It is not clear if this needs to be changed for European A4 paper. + 733 1 Not changing it might deprive Europeans of access to the bottom 1.5cm of + 734 1 their paper. */ + 735 1 + 736 1 maxrmar = 2550; + 737 1 maxbmar = 3300; + 738 1 + 739 1 /* In the following, esc[?27h means "advance the carriage by the character + 740 1 width when you set a character", esc[11h and esc[7 I together mean to + 741 1 interpret all dimensions in escape sequences as pixel units; esc[?52h means + 742 1 our origin of coordinates is the upper left edge of the paper; esc[%dt + 743 1 means the "maximum length" of the paper is maxbmar pixels. */ + 744 1 + 745 1 fprintf(outfile,"\033c\033[?27h\033[11h\033[7 I\033[?52h\033[%dt\n", + 746 1 maxbmar); + 747 1 + 748 1 for (i=0; i<maxnfonts; i++) useno[i] = -1; + 749 1 for (i=0; i<maxfontnos; i++) whouses[i] = -1; + 750 1 maxfno = -1; + 751 1 + 752 1 /* Write font loading escape sequence onto outf. [[It may be desirable to + 753 1 make this escape sequence clear all dowloaded fonts from RAM.]] */ + 754 1 + 755 1 fprintf(outfile,"\033P0;1;1y"); + 756 1 + 757 1 /* Count how many glyphs each font requires. */ + 758 1 + 759 1 for (fno=0; fno<nf; fno++) { + 760 2 + 761 2 txfa[fno] -> nchs = 0; + 762 2 for(i=0; i<256; i++) + 763 2 if (txfa[fno] -> chu[i] != 0) txfa[fno] -> nchs++; + 764 2 + 765 2 if (txfa[fno] -> nchs > 188) goto need_empty_slots; + 766 2 chsize += txfa[fno] -> nchs; + 767 2 } + 768 1 printf("\nFont load to contain %d glyphs.",chsize); + 769 1 + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 15 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 770 1 + 771 1 /* Now we have to allocate TeX fonts to LN03 fonts pairs and perform the + 772 1 actual load. The goal is to use as few slots as possible, where an LN03 + 773 1 font pair with <= 94 glyphs is one slot, and a font pair with > 94 but <= + 774 1 188 glyphs is two slots. + 775 1 + 776 1 As in the LN01 case, the allocation problem seems to be some sort of hard + 777 1 bin packing problem. (Proof of NP-hardness, anyone?) So we use a best fit + 778 1 heuristic: + 779 1 + 780 1 1. Find the unassigned largest TeX font. If none, exit, we're done. + 781 1 + 782 1 2. Allocate an LN03 font pair for that TeX font and put the TeX + 783 1 font into it. + 784 1 + 785 1 3. Find the largest remaining TeX font that fits in what is left of + 786 1 that LN03 font pair. + 787 1 + 788 1 3.1. if none exists, go to 1. + 789 1 3.2. if one exists, put it in the font pair and go back to 3. + 790 1 + 791 1 The txford array contains the TeX font numbers in the order that they are + 792 1 assigned. Txfcnt keeps track of how many TeX fonts have been assigned so + 793 1 far. */ + 794 1 + 795 1 lnfcnt = 0; + 796 1 txfcnt = 0; + 797 1 for (i=0; i<MAXTEXFONTS; i++) txford[i] = -1; + 798 1 + 799 1 while (1) { + 800 2 + 801 2 /* Find largest unassigned TeX font */ + 802 2 + 803 2 lnfleft = rightlast-rightfirst+1+leftlast-leftfirst+1; + 804 2 txf_size = -1; + 805 2 for (j = 0; j < MAXTEXFONTS; j++) { + 806 3 if (txfa[j] != 0 && txf2lnf[j] == -1 + 807 3 && txfa[j] -> nchs > txf_size) { + 808 4 txf_size = txfa[j] -> nchs; + 809 4 the_txf = j; + 810 4 } + 811 3 } + 812 2 if (txf_size <= 0) goto assignment_done; + 813 2 if (lnfcnt > maxnfonts) goto too_complex; + 814 2 if (txf_size > lnfleft) goto need_empty_slots; + 815 2 + 816 2 /* Now allocate new LN03 font pair and put the current TeX font into it */ + 817 2 + 818 2 txf2lnf[the_txf] = lnfcnt; + 819 2 txford[txfcnt] = the_txf; + 820 2 txfcnt++; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 16 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 821 2 k = leftfirst-1; + 822 2 for (j = 0; j <= 255; j++) { + 823 3 if (txfa[the_txf] -> chu[j] != 0) { + 824 4 k++; + 825 4 if (k == leftlast+1) k = rightfirst; + 826 4 lnfleft--; + 827 4 txfa[the_txf] -> chu[j] = k; + 828 4 } + 829 3 } + 830 2 lastch[lnfcnt] = k; + 831 2 + 832 2 /* Now try to fill the remaining part of the LN03 font pair using other TeX + 833 2 fonts */ + 834 2 + 835 2 while (1) { + 836 3 + 837 3 txf_size = -1; + 838 3 for (j = 0; j < MAXTEXFONTS; j++) { + 839 4 if (txfa[j] != 0 && txf2lnf[j] == -1 + 840 4 && txfa[j] -> nchs > txf_size + 841 4 && txfa[j] -> nchs <= lnfleft) { + 842 5 txf_size = txfa[j] -> nchs; + 843 5 the_txf = j; + 844 5 } + 845 4 } + 846 3 if (txf_size <= 0) break; + 847 3 + 848 3 txf2lnf[the_txf] = lnfcnt; + 849 3 txford[txfcnt] = the_txf; + 850 3 txfcnt++; + 851 3 k = lastch[lnfcnt]; + 852 3 for (j=0; j<=255; j++) { + 853 4 if (txfa[the_txf] -> chu[j] != 0) { + 854 5 k++; + 855 5 lnfleft--; + 856 5 if (k == leftlast+1) k = rightfirst; + 857 5 txfa[the_txf] -> chu[j] = k; + 858 5 } + 859 4 } + 860 3 lastch[lnfcnt] = k; + 861 3 } + 862 2 + 863 2 lnfcnt++; + 864 2 } + 865 1 + 866 1 assignment_done: + 867 1 + 868 1 /* At this point the array txf2lnf is properly initialized, as are lastch + 869 1 and txford. It remains to actually generate the desired font load. This has + 870 1 to be done carefully, since the function add_txf_to_lnf only supports + 871 1 adding glyphs to an LN03 font pair in ascending order of character code. */ + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 17 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 872 1 + 873 1 for (j=0; j<txfcnt; j++) { + 874 2 k = txford[j]; + 875 2 if (j != 0 && txf2lnf[k] != txf2lnf[txford[j-1]]) + 876 2 fprintf(outfile,",\n"); + 877 2 totsize += add_txf_to_lnf(txf2lnf[k],k); + 878 2 } + 879 1 + 880 1 /* [[At this point we ought to add code that writes a message saying how + 881 1 much font RAM the load will occupy. But there is no documentation for + 882 1 determining that! So, we make the following compromise:]] */ + 883 1 + 884 1 printf("\n Approximate size of font load: %ld bytes",totsize); + 885 1 + 886 1 /* [[We may want to insert a few \n's in the following to keep the line + 887 1 from getting too long.]] */ + 888 1 + 889 1 fprintf(outfile,"\n;Dvi2ln3 1 font load\033\\"); + 890 1 fprintf(outfile,"\033[1;%ds\033[%dt\033[1;%dr",maxrmar,maxbmar,maxbmar); + 891 1 for (j=0; j <= min(maxfontnos,lnfcnt-1); j++) { + 892 2 useno[j] = j; + 893 2 whouses[j] = j; + 894 2 k = fname[j][16]; + 895 2 fname[j][16] = '\0'; + 896 2 fprintf(outfile,"\033P1;1%d}%s\033\\",j,fname[j]); + 897 2 fname[j][16] = k; + 898 2 } + 899 1 fprintf(outfile,"\033[10m"); + 900 1 + 901 1 return(0); + 902 1 + 903 1 too_complex: + 904 1 printf("\n Can't construct a font load:"); + 905 1 printf("\n Dvi file uses too many glyphs from too many different fonts."); + 906 1 return(1); + 907 1 + 908 1 /* [[We need to determine what the real limit is on the number of LN03 + 909 1 fonts, and refine the test to detect if it is being exceeded. Fortunately, + 910 1 only a very complex DVI file could exceed the limit.]] */ + 911 1 + 912 1 need_empty_slots: + 913 1 printf("\nFont %s uses > 188 characters. Can't handle that.", + 914 1 font_name[fno]); + 915 1 return(1); + 916 1 + 917 1 /* [[The error message above should be fixed to specify the magnification + 918 1 of the font also.]] */ + 919 1 + 920 1 } + 921 + 922 /* The lines in the LN3 file are limited to lengths of about 100 bytes. We + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 18 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 923 keep track of how many bytes are written so far in the global lnhp. The + 924 accounting is conservative, so e.g. each pixel position counts as 4 bytes + 925 even though it might be shorter. [[One could easily increase 100 to 200. It + 926 is not clear what problems are provoked by going over, say, 256.]] + 927 + 928 Vpset keeps track of whether the vertical position needs to be output to + 929 the LN03 file before setting any more characters. Hh_old keeps track of the + 930 horizontal position which LN03 thinks it's at. */ + 931 + 932 GLOBAL int ln3p,vpset,hh_old; + 933 + 934 #define inc_ln3p(x) ln3p += x; if (ln3p > 100) \ + 935 { ln3p = 0; vpset = 0; hh_old = 30000; } + 936 + 937 /* [[In the above macro, hh_old is set to 30000 to mean "a very large + 938 number" (the maximum valid hh for an LN03 is 2550), so as to force the code + 939 below to re-output the true hh. What are the implications of this kludge? + 940 Would it not be more reasonable to have instead an hhset variable?]] */ + 941 + 942 /* A stack of hvxyzw values is kept; the stack pointer is called s. + 943 [[Again, it would be better to make this stack a linked list.]] */ + 944 + 945 #define STACKSIZE 100 + 946 + 947 GLOBAL long hstack[STACKSIZE], vstack[STACKSIZE], xstack[STACKSIZE], + 948 ystack[STACKSIZE], zstack[STACKSIZE], wstack[STACKSIZE]; + 949 GLOBAL int hhstack[STACKSIZE], vvstack[STACKSIZE]; + 950 GLOBAL int s; + 951 + 952 /* DVI files specify distances in units of 2^-16 points. When translating + 953 to a device-specific format, it is necessary to round the DVI distances to + 954 pixel units. This is done by means of the pixel_round macro. + 955 + 956 However, rather than using this macro in the straightforward way, rounding + 957 is often performed by more elaborate techniques, which we call "Stanford + 958 rules" (after John Le Carre's "Moscow rules"). These rules make use of a + 959 parameter MAX_DRIFT, which is roughly the maximum number of pixels that + 960 things are allowed to deviate from straightforward rounding. */ + 961 + 962 #define pixel_round(x) ((int) ((x<0) ? \ + 963 (conv*(x)-0.5) : (conv*(x)+0.5))) + 964 + 965 #define MAX_DRIFT 2 + 966 + 967 /* Pass2 reads the dvi file and interprets the commands in it, usually by + 968 calling other routines. The interpretation generally consists of writing + 969 something into the ln3 file, updating the current fonts and positions, and + 970 possibly updating the stack. */ + 971 + 972 int pass2() + 973 { + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 19 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 974 1 int i,j; + 975 1 long int p; + 976 1 unsigned int k; + 977 1 + 978 1 if (read_preamble() != 0) { + 979 2 printf(bad_DVI_message); + 980 2 return(1); + 981 2 } + 982 1 + 983 1 curf = 0; + 984 1 ln3p = 0; + 985 1 s = 0; + 986 1 vpset = 0; + 987 1 hh_old = 30000; + 988 1 + 989 1 /* Skip pages until the desired starting page is reached. A nonzero value + 990 1 is returned if the starting page is never encountered. */ + 991 1 + 992 1 if (skip_pages() != 0) return(0); + 993 1 + 994 1 for (;;) { + 995 2 if feof(dvifile) { + 996 3 printf(bad_DVI_message); + 997 3 return(1); } + 998 2 k = getc(dvifile); + 999 2 if (k == post) return(0); + 1000 2 if (k >= undefined_command) { + 1001 3 printf(bad_DVI_message); + 1002 3 return(1); } + 1003 2 + 1004 2 p = first_par(k); + 1005 2 + 1006 2 /* If the opcode is an "implicit parameter" opcode, either set_char_n and + 1007 2 fnt_num_n, we change it to an explicit parameter opcode to make the case + 1008 2 jumps more reasonable. */ + 1009 2 + 1010 2 if (k >= set_char_0 && k < set_char_0+128) k = set1; + 1011 2 if (k >= fnt_num_0 && k < fnt_num_0+64) k = fnt1; + 1012 2 + 1013 2 j = do_command(k,p); + 1014 2 if (j == 2) return(0); /* done with the required number of pages */ + 1015 2 else if (j == 1) return(1); /* error encountered, stop */ + 1016 2 + 1017 2 } + 1018 1 } + 1019 + 1020 /* Read from the DVI file until the starting page condition is met. Return + 1021 1 if something goes wrong, or if the DVI file comes to an end. This + 1022 function is copied quite closely from DVItype. */ + 1023 + 1024 int skip_pages() { + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 20 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1025 1 + 1026 1 unsigned int k; + 1027 1 int i; + 1028 1 long p,first_page; + 1029 1 char startp; + 1030 1 + 1031 1 for (;;) { + 1032 2 if (feof(dvifile)) return(1); + 1033 2 k = getc(dvifile); + 1034 2 if (k == post) return(1); + 1035 2 p = first_par(k); + 1036 2 if (k >= set_char_0 && k < set_char_0+128) k = set1; + 1037 2 if (k >= fnt_num_0 && k < fnt_num_0+64) k = fnt1; + 1038 2 + 1039 2 switch (k) { + 1040 3 case bop: + 1041 3 startp = 1; + 1042 3 for (i=0; i<10; i++) { + 1043 4 four_bytes; + 1044 4 if (i == 0) first_page = lcx.l; + 1045 4 if (i < how_many_counts && use_count[i] && + 1046 4 lcx.l != start_page[i]) startp = 0; + 1047 4 } + 1048 3 four_bytes; + 1049 3 if (startp != 0) { + 1050 4 v = 0; vv = 0; h = 0; hh = 0; + 1051 4 printf("\n [%ld]",first_page); + 1052 4 num_pages = 1; return(0); } + 1053 3 break; + 1054 3 case set_rule: + 1055 3 case put_rule: + 1056 3 four_bytes; + 1057 3 break; + 1058 3 four_cases(fnt_def1) + 1059 3 i = define_font(p); + 1060 3 if (i != 0) return(1); + 1061 3 break; + 1062 3 four_cases(xxx1) + 1063 3 for (; p>0; p--) getc(dvifile); + 1064 3 break; + 1065 3 default: + 1066 3 break; + 1067 3 } + 1068 2 } + 1069 1 return(0); + 1070 1 } + 1071 + 1072 /* Do_command performs the DVI command of code k, assuming the "first + 1073 parameter" is p. It is assumed that k is not one of set_char0 through + 1074 set_char127. */ + 1075 + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 21 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1076 int do_command(k,p) + 1077 int k; + 1078 long p; + 1079 { + 1080 1 int i,j,l,lnf; + 1081 1 + 1082 1 switch (k) { + 1083 2 four_cases(fnt_def1) + 1084 2 define_font_pass2(); + 1085 2 break; + 1086 2 + 1087 2 /* [[In processing the put and set DVI commands, no check is made that the + 1088 2 character being set actually exists in the font. This can lead to messy + 1089 2 errors, like access violations or garbage values when one tries to find + 1090 2 that character's width. Neither is any check made that the horizontal and + 1091 2 vertical positions fall within the page.]] */ + 1092 2 + 1093 2 four_cases(put1) + 1094 2 four_cases(set1) + 1095 2 if (!vpset) { + 1096 3 fprintf(outfile,"\n\033[%dd\033[%d`",vv+voff,hh+hoff); + 1097 3 ln3p = 16; + 1098 3 vpset = 1; + 1099 3 hh_old = hh; + 1100 3 } + 1101 2 if (hh_old != hh) { + 1102 3 if (hh > hh_old) fprintf(outfile,"\033[%da",hh-hh_old); + 1103 3 else fprintf(outfile,"\033[%d`",hh+hoff); + 1104 3 ln3p += 7; + 1105 3 } + 1106 2 putc(txfa[curf] -> chu[p],outfile); + 1107 2 inc_ln3p(1); + 1108 2 if (k >= put1) { + 1109 3 hh_old = hh; + 1110 3 break; + 1111 3 } + 1112 2 h += font_width[curf][p]; + 1113 2 + 1114 2 /* In rounding h to generate the pixel-position hh, Stanford rules (see + 1115 2 above) come into play. We set the new hh (horizontal position in pixels) to + 1116 2 the value obtained by adding the pixel width of the character being set to + 1117 2 the current position. We then correct this value so that it does not exceed + 1118 2 the rounded version of the true position by more than MAX_DRIFT pixels. + 1119 2 + 1120 2 Note that if we did not apply Stanford rules here, or equivalently if we + 1121 2 set MAX_DRIFT to zero, many more set-X-position commands would appear in + 1122 2 the output. */ + 1123 2 + 1124 2 hh += chw[txf2lnf[curf]][txfa[curf] -> chu[p]]; + 1125 2 hh_old = hh; + 1126 2 l = pixel_round(h); + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 22 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1127 2 if (hh-l > MAX_DRIFT) hh = l+MAX_DRIFT; + 1128 2 else if (l-hh > MAX_DRIFT) hh = l-MAX_DRIFT; + 1129 2 break; + 1130 2 + 1131 2 four_cases(fnt1) + 1132 2 set_curf(p); + 1133 2 lnf = txf2lnf[curf]; + 1134 2 if (useno[lnf] == -1) { + 1135 3 useno[whouses[maxfontnos]] = -1; + 1136 3 useno[lnf] = maxfontnos; + 1137 3 whouses[maxfontnos] = lnf; + 1138 3 fprintf(outfile,"\033P1;1%d}%16s\033\\",maxfontnos, + 1139 3 fname[lnf]); + 1140 3 inc_ln3p(26); + 1141 3 } + 1142 2 fprintf(outfile,"\033[1%dm",useno[lnf]); + 1143 2 inc_ln3p(5); + 1144 2 break; + 1145 2 + 1146 2 case set_rule: + 1147 2 case put_rule: + 1148 2 + 1149 2 /* When converting rule dimensions to pixel dimensions, we do not follow + 1150 2 Stanford rules. Rather, we just round the true positions to obtain the + 1151 2 pixel positions. This avoids unsightly gaps between rules. [[It should not + 1152 2 cause much of a problem with typical rule applications (ruled tables, + 1153 2 fraction bars)...but perhaps with large delimiters there might be some + 1154 2 difficulty. This needs more thought...]] */ + 1155 2 + 1156 2 four_bytes; + 1157 2 if (p >= 0 && lcx.l >= 0) + 1158 2 do_rule(pixel_round(h), + 1159 2 pixel_round(v-p),pixel_round(h+lcx.l), + 1160 2 pixel_round(v)); + 1161 2 if (k == set_rule) { + 1162 3 h += lcx.l; + 1163 3 hh = pixel_round(h); + 1164 3 } + 1165 2 break; + 1166 2 + 1167 2 case push: + 1168 2 s++; + 1169 2 if (s == STACKSIZE) { + 1170 3 printf("\n Stack too deep for Dvi2ln3"); + 1171 3 return(1); + 1172 3 } + 1173 2 xstack[s] = x; + 1174 2 ystack[s] = y; + 1175 2 vstack[s] = v; + 1176 2 hstack[s] = h; + 1177 2 vvstack[s] = vv; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 23 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1178 2 hhstack[s] = hh; + 1179 2 wstack[s] = w; + 1180 2 zstack[s] = z; + 1181 2 break; + 1182 2 + 1183 2 case pop: + 1184 2 if (s == 0) { + 1185 3 printf(bad_DVI_message); + 1186 3 return(1); + 1187 3 } + 1188 2 if (vv != vvstack[s]) vpset = 0; + 1189 2 x = xstack[s]; + 1190 2 y = ystack[s]; + 1191 2 v = vstack[s]; + 1192 2 h = hstack[s]; + 1193 2 vv = vvstack[s]; + 1194 2 hh = hhstack[s]; + 1195 2 w = wstack[s]; + 1196 2 z = zstack[s]; + 1197 2 s--; + 1198 2 break; + 1199 2 + 1200 2 /* Right now there are no \special's defined, so when we get a \special, we + 1201 2 just skip over it. */ + 1202 2 + 1203 2 four_cases(xxx1) + 1204 2 for (; p != 0; p--) getc(dvifile); + 1205 2 break; + 1206 2 + 1207 2 case bop: + 1208 2 + 1209 2 /* If we've done the required number of pages, we'll skip the rest of the + 1210 2 DVI file. If not, type the first parameter of bop on the user's terminal + 1211 2 the way TeX does, to give an indication of progress. */ + 1212 2 + 1213 2 if (num_pages == max_pages) return(2); + 1214 2 v = 0; vv = 0; h = 0; hh = 0; + 1215 2 vpset = 0; hh_old = 100000; + 1216 2 four_bytes; + 1217 2 if (num_pages%12 == 0) printf("\n"); + 1218 2 printf(" [%ld]",lcx.ul); + 1219 2 num_pages++; + 1220 2 for (i = 0; i<40; i++) getc(dvifile); + 1221 2 break; + 1222 2 + 1223 2 case eop: + 1224 2 fprintf(outfile,"\n\f"); + 1225 2 ln3p = 0; + 1226 2 break; + 1227 2 + 1228 2 /* Now we have to consider the cases for pure motion. */ + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 24 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1229 2 + 1230 2 four_cases(right1) + 1231 2 set_h(h+p); + 1232 2 break; + 1233 2 four_cases(x1) + 1234 2 x = p; + 1235 2 case x0: + 1236 2 set_h(h+x); + 1237 2 break; + 1238 2 four_cases(y1) + 1239 2 y = p; + 1240 2 case y0: + 1241 2 set_v(v+y); + 1242 2 break; + 1243 2 four_cases(w1) + 1244 2 w = p; + 1245 2 case w0: + 1246 2 set_h(h+w); + 1247 2 break; + 1248 2 four_cases(z1) + 1249 2 z = p; + 1250 2 case z0: + 1251 2 set_v(v+z); + 1252 2 break; + 1253 2 four_cases(down1) + 1254 2 set_v(v+p); + 1255 2 break; + 1256 2 + 1257 2 } + 1258 1 return(0); + 1259 1 } + 1260 + 1261 /* Set_curf sets the current font to external number p. Note that the + 1262 current font is maintained as an internal font number. */ + 1263 + 1264 int set_curf(p) + 1265 int p; + 1266 { + 1267 1 to_ext[nf] = p; + 1268 1 curf = 0; + 1269 1 while (to_ext[curf] != p) { curf++; } + 1270 1 } + 1271 + 1272 /* Define_font processes a font definition from the DVI file. The TFM file + 1273 for the font is read at this point from the directory TEX$FONTS. */ + 1274 + 1275 int define_font(e) + 1276 int e; + 1277 { + 1278 1 int i; + 1279 1 unsigned char p,n; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 25 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1280 1 if (e == MAXTEXFONTS) { printf("\n Too many fonts for Dvi2ln3"); + 1281 2 return(1); } + 1282 1 txfa[nf] = malloc(sizeof(struct txf)); + 1283 1 to_ext[nf] = e; + 1284 1 four_bytes; + 1285 1 four_bytes; + 1286 1 txfa[nf] -> scaled_size = lcx.l; + 1287 1 four_bytes; + 1288 1 txfa[nf] -> design_size = lcx.l; + 1289 1 for (i=0; i<256; i++) txfa[nf] -> chu[i] = '\0'; + 1290 1 p = getc(dvifile); n = getc(dvifile); + 1291 1 font_name[nf] = malloc(p+n+1); + 1292 1 for (i=0; i<p+n; i++) { font_name[nf][i] = getc(dvifile); } + 1293 1 font_name[nf][p+n] = '\0'; + 1294 1 + 1295 1 if (txfa[nf] -> scaled_size <= 0 || txfa[nf] -> scaled_size >= + 1296 1 8*8*8*8*8*8*8*8*8) { + 1297 2 printf("\n Font %s has a bad scaled size",font_name[nf]); + 1298 2 return(1); + 1299 2 } + 1300 1 if (txfa[nf] -> design_size <= 0 || txfa[nf] -> design_size >= + 1301 1 8*8*8*8*8*8*8*8*8) { + 1302 2 printf("\n Font %s has a bad design size",font_name[nf]); + 1303 2 return(1); + 1304 2 } + 1305 1 + 1306 1 /* We follow DVItype and compute for each font a "space" parameter which is + 1307 1 one-sixth of the scaled design size. This parameter is used in rounding the + 1308 1 horizontal position to pixels according to "Stanford rules." See the + 1309 1 function set_h below. */ + 1310 1 + 1311 1 txfa[nf] -> space = txfa[nf] -> scaled_size/6; + 1312 1 + 1313 1 i = read_tfm_file(); + 1314 1 if (i != 0) return(i); + 1315 1 nf++; + 1316 1 return(0); + 1317 1 + 1318 1 } + 1319 + 1320 /* TFM files, like the DVI file, are read with getc, foolish as that may + 1321 seem. We use the same overlays that are used for merging DVI bytes into + 1322 longwords. However, since the TFM file consists of longwords, only + 1323 tfm_longword is need. [[This is also VAX dependent. It would not be + 1324 possible to use stdio's longword reading function getw here, because the + 1325 bytes have to be reversed.]] */ + 1326 + 1327 #define tfm_longword { lcx.uc[3] = getc(tfmfile); \ + 1328 lcx.uc[2] = getc(tfmfile); lcx.uc[1] = getc(tfmfile); \ + 1329 lcx.uc[0] = getc(tfmfile); } + 1330 + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 26 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1331 /* Read_tfm_file obtains the character widths from the TFM file + 1332 corresponding to font nf. */ + 1333 + 1334 int read_tfm_file() { + 1335 1 + 1336 1 int i,lh,nw; + 1337 1 int info[256]; + 1338 1 long z,alpha,beta; + 1339 1 long width[256]; + 1340 1 + 1341 1 open_tfm_file(); + 1342 1 if (tfmfile == NULL) { + 1343 2 printf("\n Can't open TFM file for font %s",font_name[nf]); + 1344 2 return(1); } + 1345 1 + 1346 1 /* The TFM format is described in some issue of the TUGBoat (TeX users' + 1347 1 group newsletter), and in the comments to the program TFtoPL. Here we + 1348 1 summarize those aspects of TFM format that are relevant to the task of + 1349 1 extracting the widths of the characters. + 1350 1 + 1351 1 The first 24 bytes of a TFM file contain twelve 16-bit integers that give + 1352 1 the lengths of the various subsequent portions of the file. The ones + 1353 1 relevant to our purposes are LH, length of the header data, BC, the + 1354 1 smallest character code in the font, EC, the largest character code in the + 1355 1 font, and NW, number of words in the width table. So, we read those right + 1356 1 now, and then skip over the remainder, and then over a set of LH longwords + 1357 1 called the "header." */ + 1358 1 + 1359 1 tfm_longword; + 1360 1 lh = 256*lcx.uc[1] + lcx.uc[0]; + 1361 1 tfm_longword; + 1362 1 txfa[nf] -> bc = 256*lcx.uc[3] + lcx.uc[2]; + 1363 1 txfa[nf] -> ec = 256*lcx.uc[1] + lcx.uc[0]; + 1364 1 tfm_longword; + 1365 1 nw = 256*lcx.uc[3] + lcx.uc[2]; + 1366 1 if (txfa[nf] -> bc > 255 || txfa[nf] -> ec > 255 || + 1367 1 txfa[nf] -> bc > txfa[nf] -> ec || nw > 256) { + 1368 2 printf("\n Bad TFM file for font %s",font_name[nf]); + 1369 2 return(1); + 1370 2 } + 1371 1 + 1372 1 for(i=0; i<lh+3; i++) tfm_longword; + 1373 1 + 1374 1 /* After the header, there are two arrays in the TFM file that interest us. + 1375 1 The first, INFO, is EC-BC+1 longwords long and contains pointers to the + 1376 1 second, WIDTH, which is NW longwords long. For each character i, the width + 1377 1 of i is WIDTH[INFO[i-BC]]. We read these arrays into memory. */ + 1378 1 + 1379 1 for(i=0; i<txfa[nf] -> ec-txfa[nf] -> bc+1; i++) { + 1380 2 tfm_longword; + 1381 2 if (lcx.uc[3] >= nw) { + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 27 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1382 3 printf("\n Bad TFM file for font %s",font_name[nf]); + 1383 3 return(1); + 1384 3 } + 1385 2 info[i] = lcx.uc[3]; + 1386 2 } + 1387 1 + 1388 1 /* The widths are stored in a rather strange format known as a "fix-word." + 1389 1 A nonnegative width is expressed in "fix-word" format by expressing it in + 1390 1 units of 2^-20 times the design size. A negative width is expressed in + 1391 1 "fix-word" format by expressing its negative in those units, and then + 1392 1 changing the most significant byte to 255. + 1393 1 + 1394 1 One needs to convert these widths into DVI units, multiplying by the scaled + 1395 1 design size according to a certain arcane algorithm. The algorithm is + 1396 1 copied from DVItype, to which we refer the reader for an explanation. */ + 1397 1 + 1398 1 z = txfa[nf] -> scaled_size; + 1399 1 alpha = 16*z; beta = 16; + 1400 1 while (z >= 4*(8*8*8*8*8*8*8)) { z = z/2; beta = beta/2; } + 1401 1 for(i=0; i<nw; i++) { + 1402 2 tfm_longword; + 1403 2 width[i] = ( ( (lcx.uc[0]*z)/256 + lcx.uc[1]*z )/256 + + 1404 2 lcx.uc[2]*z)/beta; + 1405 2 if (lcx.uc[3] == 255) width[i] -= alpha; + 1406 2 } + 1407 1 + 1408 1 fclose(tfmfile); + 1409 1 + 1410 1 /* Using these two arrays, we now compute the widths of the characters in + 1411 1 the fonts and place them into two malloc'ed arrays, one for the widths in + 1412 1 DVI units, one for the width in pixel units. */ + 1413 1 + 1414 1 font_width[nf] = malloc(4*(txfa[nf] -> ec+1)); + 1415 1 + 1416 1 for (i=0; i<txfa[nf] -> bc; i++) font_width[nf][i] = 0; + 1417 1 for (i=txfa[nf] -> bc; i <= txfa[nf] -> ec; i++) + 1418 1 font_width[nf][i] = width[info[i-txfa[nf] -> bc]]; + 1419 1 return(0); + 1420 1 } + 1421 + 1422 /* Open_tfm_file finds and opens the tfm file corresponding to a font nf. + 1423 The global file variable tfmfile is used to hold the file pointer. [[This + 1424 function will not work if the TFM file lies over the net on a VMS V3.x + 1425 host, because C file opens do not work in such circumstances. The problem + 1426 can be ignored, because eventually there should be no VMS V3.x hosts + 1427 left.]] */ + 1428 + 1429 int open_tfm_file () { + 1430 1 + 1431 1 int jext,jnam; + 1432 1 char filespec[FILESPECLEN]; + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 28 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1433 1 + 1434 1 find_VMS_filename(font_name[nf],&jnam,&jext); + 1435 1 filespec[0] = '\0'; + 1436 1 + 1437 1 /* If there is no directory part, fill in using the logical tex$fonts */ + 1438 1 + 1439 1 if (jnam == 0) strcpy(filespec,"tex$fonts:"); + 1440 1 strcat(filespec,font_name[nf]); + 1441 1 + 1442 1 /* if there is no extension, add the extension ".tfm" */ + 1443 1 + 1444 1 if (font_name[nf][jext] == '\0') strcat(filespec,".tfm"); + 1445 1 tfmfile = fopen(filespec,"r"); + 1446 1 + 1447 1 } + 1448 + 1449 /* Define_font_pass2 skips a font definition from the DVI file. */ + 1450 + 1451 int define_font_pass2() + 1452 { + 1453 1 unsigned char p,n; + 1454 1 int i; + 1455 1 four_bytes; + 1456 1 four_bytes; + 1457 1 four_bytes; + 1458 1 p = getc(dvifile); n = getc(dvifile); + 1459 1 for (i=0; i<p+n; i++) getc(dvifile); + 1460 1 } + 1461 + 1462 /* Do_rule writes into the ln3 file the escape sequence corresponding + 1463 to a rule. */ + 1464 + 1465 int do_rule(xx0,yy0,xx1,yy1) + 1466 int xx0,yy0,xx1,yy1; + 1467 { + 1468 1 int j; + 1469 1 + 1470 1 xx0 = min(xx0+hoff,maxrmar); + 1471 1 xx1 = min(xx1+hoff,maxrmar); + 1472 1 xx0 = max(xx0,0); + 1473 1 xx1 = max(xx1,0); + 1474 1 yy0 = min(yy0+voff,maxbmar); + 1475 1 yy1 = min(yy1+voff,maxbmar); + 1476 1 yy0 = max(yy0,0); + 1477 1 yy1 = max(yy1,0); + 1478 1 if (xx0 > xx1) { j = xx0; xx0 = xx1; xx1 = j; } + 1479 1 if (yy0 > yy1) { j = yy0; yy0 = yy1; yy1 = j; } + 1480 1 + 1481 1 if ((yy1 != yy0 && xx1 != xx0)) { + 1482 2 fprintf(outfile,"\033[1;%d;%d;%d;%d!|", + 1483 2 xx0,yy0,yy1-yy0,xx1-xx0); + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 29 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + 1484 2 inc_ln3p(25); + 1485 2 } + 1486 1 } + 1487 + 1488 /* Set_v is called to execute vertical-position-altering commands, other + 1489 than pops. It modifies v and vv, and outputs the vertical position to the + 1490 LN3 file. We don't follow Stanford rules here. They sometimes set the + 1491 vertical position in pixels vv to something other than the rounded value of + 1492 v. Not following Stanford rules implies, for example, that the relative + 1493 vertical positions of an accent and its accentee may differ by one pixel + 1494 according to how the baseline of the accentee gets rounded. [[This should + 1495 perhaps be fixed.]] */ + 1496 + 1497 int set_v(v1) + 1498 int v1; + 1499 { + 1500 1 int l; + 1501 1 + 1502 1 l = pixel_round(v1); + 1503 1 v = v1; + 1504 1 vv = l; + 1505 1 vpset = 0; + 1506 1 } + 1507 + 1508 /* Set_h is called whenever a DVI command is encountered that alters the + 1509 horizonal position, other than a set_char, set_rule or pop. It sets h to + 1510 the new value, and alters hh according to Stanford rules, printing the new + 1511 hh in the LN3 file. */ + 1512 + 1513 int set_h(new_h) + 1514 int new_h; + 1515 { + 1516 1 int l,old_hh; + 1517 1 + 1518 1 old_hh = hh; + 1519 1 l = pixel_round(new_h); + 1520 1 if (txfa[curf] == 0 || new_h-h >= txfa[curf] -> space + 1521 1 || new_h-h <= -4*txfa[curf] -> space) hh = l; + 1522 1 else { + 1523 2 hh += pixel_round(new_h-h); + 1524 2 if (hh-l > MAX_DRIFT) hh = l+MAX_DRIFT; + 1525 2 else if (hh-l < -MAX_DRIFT) hh = l-MAX_DRIFT; + 1526 2 } + 1527 1 h = new_h; + 1528 1 return(0); + 1529 1 } + + + +Command Line +------------ + +DVI2LN3 14-OCT-1985 13:19:13 VAX C V2.0-003 Page 30 +V1.0 14-OCT-1985 13:19:01 USER$4:[TEX.LN03.SOURCES]DVI2LN3.C;40 (1) + + +CC/DEB/LIS DVI2LN3 + |