1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)vsort.c 5.2 (Berkeley) 06/30/88"; 26 #endif /* not lint */ 27 28 # include <stdio.h> 29 /* 30 * vsort - Sort troff output for versatec to reduce amount of reverse leading 31 */ 32 33 #define NULL 0 34 35 double atof(); 36 char *calloc(); 37 38 FILE *in,*out; 39 40 int skipfirst = 1; /* skip the first leading so start at top of page */ 41 int cpsize = 02; /* Funny sizes */ 42 struct point_sizes 43 { 44 int stupid_code; 45 int real_code; 46 } point_sizes[] = 47 { 48 010, 6, 49 0, 7, 50 01, 8, 51 07, 9, 52 02, 10, 53 03, 11, 54 04, 12, 55 05, 14, 56 0211, 16, 57 06, 18, 58 0212, 20, 59 0213, 22, 60 0214, 24, 61 0215, 28, 62 0216, 36, 63 0, 0 64 }; 65 66 int pagelength = 144 * 11; /* in Leading units */ 67 int pagemod; /* horizontal page number (for versatec) */ 68 #define MODOFF 3672 /* 432 * 8.5 */ 69 70 int esc, lead, back, verd, mcase, railmag; 71 int col, row; 72 int pstart = 0; /* Means a startline is pending */ 73 74 int oback, omcase, orailmag, ocol, orow; 75 int opsize = 02; 76 77 struct lstate 78 { 79 int col; 80 int psize; 81 char railmag; 82 char verd; 83 char back; 84 char mcase; 85 }; 86 87 struct line 88 { 89 struct line *nextp; 90 struct line *lastp; 91 int len; 92 int row; 93 struct lstate start; 94 struct lstate end; 95 char *codep; 96 }; 97 98 struct line *head; 99 struct line *tail; 100 struct line cline; 101 102 #define TBUFLEN 1024 103 char *codep; 104 char tbuf[TBUFLEN]; 105 106 char wide = 0; 107 char nocutmarks = 0; /* Remove lines that seem to be cut marks. */ 108 109 #define iscutmark(ch) (ch == 023 || ch == 040 || ch == 061) 110 main(argc, argv) 111 int argc; 112 char *argv[]; 113 { 114 register i; 115 116 for(i = 3; i < 15; i++) 117 close(i); 118 while (argc > 1 && argv[1][0] == '-') { 119 switch (argv[1][1]) { 120 case 'l': { 121 float f = 144 * atof(argv[1] + 2); 122 if (f < 144) { 123 error("bad length"); 124 exit(1); 125 } 126 pagelength = f; 127 break; 128 } 129 130 case 'W': 131 wide++; 132 break; 133 134 case 'c': 135 nocutmarks++; 136 break; 137 } 138 argc--; argv++; 139 } 140 out = stdout; 141 if(argc > 1) 142 { 143 while(--argc) 144 { 145 argv++; 146 if((in=fopen(argv[0], "r")) == NULL) 147 perror("vsort"); 148 else { 149 ofile(); 150 fclose(in); 151 } 152 } 153 } 154 else 155 { 156 in = stdin; 157 ofile(); 158 } 159 exit(0); 160 } 161 162 ofile() 163 { 164 register int c; 165 static int initialized; 166 167 while((c = getch()) != -1) { 168 if(!c) 169 continue; 170 if(c & 0200) /* escape (left/right) */ 171 { 172 if(!pstart) 173 stuffc(c); 174 esc += (~c) & 0177; 175 continue; 176 } 177 if(esc) 178 { 179 if(back) 180 esc = -esc; 181 col += esc; 182 esc = 0; 183 } 184 if((c & 0377) < 0100) /* Purely for efficiency */ 185 goto normal_char; 186 switch(c) { 187 case 0100: 188 if(initialized++) { 189 termline(); 190 linesflush(); /* Omit trailing leading. */ 191 return; 192 } 193 row = 0; 194 col = 0; esc = 0; 195 lead = 0; 196 verd = 0; back = 0; mcase = 0; 197 railmag = 0; 198 ocol = 0; 199 orow = 0; 200 oback = 0; omcase = 0; 201 orailmag = 0; 202 if(loadfont(railmag, cpsize) < 0) 203 error("init"); 204 startline(); 205 putc(0100, out); /* Dont stuff it guys */ 206 break; 207 case 0101: /* lower rail */ 208 crail(railmag &= ~01); 209 if(!pstart) 210 stuffc(c); 211 break; 212 case 0102: /* upper rail */ 213 crail(railmag |= 01); 214 if(!pstart) 215 stuffc(c); 216 break; 217 case 0103: /* upper mag */ 218 crail(railmag |= 02); 219 if(!pstart) 220 stuffc(c); 221 break; 222 case 0104: /* lower mag */ 223 crail(railmag &= ~02); 224 if(!pstart) 225 stuffc(c); 226 break; 227 case 0105: /* lower case */ 228 mcase = 0; 229 if(!pstart) 230 stuffc(c); 231 break; 232 case 0106: /* upper case */ 233 mcase = 1; 234 if(!pstart) 235 stuffc(c); 236 break; 237 case 0107: /* escape forward */ 238 back = 0; 239 if(!pstart) 240 stuffc(c); 241 break; 242 case 0110: /* escape backwards */ 243 back = 1; 244 if(!pstart) 245 stuffc(c); 246 break; 247 case 0111: /* stop */ 248 stuffc(c); 249 break; 250 case 0112: /* lead forward */ 251 verd = 0; 252 break; 253 case 0113: /* undefined */ 254 break; 255 case 0114: /* lead backward */ 256 verd = 1; 257 break; 258 case 0115: /* undefined */ 259 case 0116: 260 case 0117: 261 break; 262 default: 263 if((c & 0340) == 0140) /* leading */ 264 { 265 termline(); 266 lead = (~c) & 037; 267 if(verd) 268 lead = -lead; 269 if (skipfirst > 0) { 270 skipfirst--; 271 continue; 272 } 273 row += lead; 274 if (row >= pagelength) { 275 if (wide) { 276 if (pagemod == 3) { 277 allflush(); 278 col %= MODOFF; 279 pagemod = 0; 280 } else { 281 pagemod++; 282 col += MODOFF; 283 row -= pagelength; 284 } 285 } else { 286 allflush(); 287 } 288 } 289 if (wide && row < 0 && pagemod) { 290 pagemod--; 291 col -= MODOFF; 292 row += pagelength; 293 } 294 pstart++; 295 continue; 296 } 297 if((c & 0360) == 0120) /* size change */ 298 { 299 if(!pstart) 300 stuffc(c); 301 col += stupidadj(c & 017, cpsize); 302 loadfont(railmag, c & 017); 303 continue; 304 } 305 if(c & 0300) 306 continue; 307 normal_char: 308 c = (c & 077); 309 stuffc(c); 310 } 311 } /* End of while loop reading chars. */ 312 termline(); 313 linesflush(); /* don't put out trailing leading. */ 314 } 315 316 317 int peekc; 318 getch() { 319 register c; 320 if(peekc) { 321 c = peekc; 322 peekc = 0; 323 return(c); 324 } 325 return(getc(in)); 326 } 327 328 ungetc(c) { 329 peekc = c; 330 } 331 332 333 error(s) 334 char *s; 335 { 336 337 fflush(out); 338 fprintf(stderr, stderr, "vsort: %s\n", s); 339 } 340 341 crail(nrail) 342 register int nrail; 343 { 344 register int psize; 345 346 psize = cpsize; 347 loadfont(nrail, psize); 348 } 349 350 loadfont(fnum, size) 351 register int fnum; 352 register int size; 353 { 354 355 cpsize = size; 356 return(0); 357 } 358 359 startline() 360 { 361 362 if(pstart != 0) { 363 cline.row = row; 364 return; 365 } 366 cline.len = 0; 367 cline.row = row; 368 cline.start.col = col; 369 cline.start.psize = cpsize; 370 cline.start.mcase = mcase; 371 cline.start.back = back; 372 cline.start.verd = verd; 373 cline.start.railmag = railmag; 374 codep = tbuf; 375 } 376 377 termline() 378 { 379 register struct line *linep; 380 register char *allp; 381 register char *cp; 382 int i; 383 384 if(pstart != 0) 385 return; 386 if((allp = calloc(sizeof *linep,1)) == ((char *)-1)) 387 error("alloc"); 388 linep = (struct line *)allp; 389 linep->end.col = col; 390 linep->end.psize = cpsize; 391 linep->end.mcase = mcase; 392 linep->end.back = back; 393 linep->end.verd = verd; 394 linep->end.railmag = railmag; 395 linep->start.col = cline.start.col; 396 linep->start.psize = cline.start.psize; 397 linep->start.mcase = cline.start.mcase; 398 linep->start.back = cline.start.back; 399 linep->start.verd = cline.start.verd; 400 linep->start.railmag = cline.start.railmag; 401 linep->len = cline.len; 402 linep->row = row; 403 if((allp = calloc(cline.len,1)) == ((char *)-1)) 404 error("alloc"); 405 linep->codep = allp; 406 cp = tbuf; 407 for(i = 0; i < cline.len; i++) 408 *allp++ = *cp++; 409 sortin(linep); 410 } 411 412 sortin(linep) 413 register struct line *linep; 414 { 415 register struct line *clp; 416 417 if((clp = tail) == NULL) { 418 head = tail = linep; 419 linep->lastp = linep->nextp = NULL; 420 return; 421 } 422 while(clp != NULL && clp->row > linep->row) 423 clp = clp->lastp; 424 if(clp == tail) { 425 linep->lastp = tail; 426 linep->nextp = NULL; 427 tail->nextp = linep; 428 tail = linep; 429 } else 430 if(clp == NULL) /* goes at head of list */ { 431 linep->lastp = NULL; 432 linep->nextp = head; 433 head->lastp = linep; 434 head = linep; 435 } else { 436 linep->lastp = clp; 437 linep->nextp = clp->nextp; 438 clp->nextp->lastp = linep; 439 clp->nextp = linep; 440 } 441 } 442 443 stuffc(code) 444 register int code; 445 { 446 447 if(pstart != 0) { 448 pstart = 0; 449 startline(); 450 } 451 if(cline.len > TBUFLEN) { 452 termline(); 453 startline(); 454 } 455 *codep++ = code; 456 cline.len++; 457 } 458 459 460 allflush() /* Flush all lines, then put out trailing leading. */ 461 { 462 463 linesflush(); 464 if (row > orow) { 465 ptlead(row - orow); 466 } 467 row -= pagelength; 468 orow = row; 469 } 470 471 linesflush() 472 { 473 while(head != NULL) 474 sendline(); 475 } 476 477 sendline() 478 { 479 register char *cp; 480 register struct line *linep; 481 register int i; 482 register int remcutmark; 483 484 if ((linep = head) == NULL) 485 return; 486 487 /* Heuristic: if cut marks are present, they are on lines whose 488 * row numbers are <= 24 or >= pagelength-4. 489 * Cut marks are formed from 023's, 040's, or 061's. 490 * There are 2 or 4 of them on a line, and no other characters 491 * are present. cutmark(...) checks this. 492 * Cutmark lines are removed if nocutmarks is true. 493 * Three leading units are removed, too, to compensate for 494 * varian output not being exactly 1584 leading units long. 495 */ 496 #ifdef DUMPLINE 497 dumpline(linep); 498 #endif 499 remcutmark = 0; 500 if (nocutmarks 501 && (linep->row <= 24 || linep->row >= pagelength-4) 502 && cutmark(linep)) { 503 remcutmark++; 504 orow = orow + 3; 505 } 506 if(linep->start.railmag != orailmag) 507 ptrail(linep->start.railmag); 508 if(linep->start.psize != opsize) 509 ptsize(linep->start.psize); 510 if(linep->start.mcase != omcase) 511 ptmcase(); 512 if(linep->row > orow) /* lead forward */ 513 ptlead(linep->row - orow); 514 if(linep->start.col != ocol) 515 ptesc(linep->start.col-ocol); 516 if(linep->start.back != oback) 517 ptback(); 518 cp = linep->codep; 519 if (remcutmark) { 520 for(i = 0; i < linep->len; i++) { 521 if (!iscutmark(*cp)) /* iscutmark is a macro. */ 522 putc(*cp++, out); 523 else 524 cp++; 525 } 526 } else { 527 for(i = 0; i < linep->len; i++) 528 putc(*cp++, out); 529 } 530 531 orow = linep->row; 532 orailmag = linep->end.railmag; 533 opsize = linep->end.psize; 534 omcase = linep->end.mcase; 535 ocol = linep->end.col; 536 oback = linep->end.back; 537 head = linep->nextp; 538 539 cfree(linep->codep); 540 cfree(linep); 541 if(head == NULL) 542 tail = NULL; 543 else 544 head->lastp = NULL; 545 } 546 547 int 548 cutmark(linep) 549 register struct line *linep; 550 { 551 register int i; 552 register int ch; 553 register int dashcount = 0; 554 register int firstdash = 0; 555 556 for (i = 0; i < linep->len; i++) { 557 ch = linep->codep[i] & 0377; 558 if (ch < 0100) { 559 if (iscutmark(ch)) { 560 if (firstdash == 0) 561 firstdash = ch; 562 if (ch != firstdash) 563 return (0); 564 dashcount++; 565 } else 566 return(0); 567 } 568 } 569 /* Must have 2 or 4 dashes on a line. */ 570 return (dashcount == 4 || dashcount == 2); 571 } 572 573 ptrail(rlmg) 574 register int rlmg; 575 { 576 577 if((rlmg & 01) != (orailmag & 01)) 578 putc((rlmg & 01) ? 0102:0101, out); /* rail */ 579 if((rlmg & 02) != (orailmag & 02)) 580 putc((rlmg & 02) ? 0103:0104, out); /* mag */ 581 } 582 583 ptback() 584 { 585 586 putc(oback ? 0107:0110, out); 587 oback = !oback; 588 } 589 590 ptsize(size) 591 register int size; 592 { 593 594 putc(0120 | (size & 017), out); 595 ptesc(-stupidadj(size, opsize)); 596 } 597 598 stupidadj(code, lcode) 599 register int code; 600 int lcode; 601 { 602 register struct point_sizes *psp; 603 register struct point_sizes *lpsp; 604 605 psp = point_sizes; 606 while(psp->real_code != 0) { 607 if((psp->stupid_code & 017) == code) 608 break; 609 psp++; 610 } 611 lpsp = point_sizes; 612 while(lpsp->real_code != 0) { 613 if((lpsp->stupid_code & 017) == lcode) 614 break; 615 lpsp++; 616 } 617 code = 0; 618 if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200)) 619 code = -55; 620 else 621 if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200)) 622 code = 55; 623 return(code); 624 } 625 626 ptmcase() 627 { 628 629 putc(omcase ? 0105:0106, out); 630 } 631 632 ptesc(escc) 633 register int escc; 634 { 635 636 if((escc < 0 && !oback ) || (escc >= 0 && oback)) 637 ptback(); 638 escc = abs(escc); 639 while(escc > 0177) { 640 putc(0200, out); 641 escc -= 0177; 642 } 643 if(escc) 644 putc(0200 | ((~escc) & 0177), out); 645 } 646 647 ptlead(leadd) 648 register int leadd; 649 { 650 651 while(leadd > 037) { 652 putc(0140, out); 653 leadd -= 037; 654 } 655 if(leadd) 656 putc(0140 | ((~leadd) & 037), out); 657 } 658 659 #ifdef DUMPLINE 660 dumpline(linep) 661 register struct line *linep; 662 { 663 int i; 664 665 fprintf(stderr, "row: %d\n", linep->row); 666 fprintf(stderr, "start.col: %o ", linep->start.col & 0377); 667 fprintf(stderr, ".psize: %o ", linep->start.psize); 668 fprintf(stderr, ".railmag: %o ", linep->start.railmag); 669 fprintf(stderr, ".verd: %o ", linep->start.verd); 670 fprintf(stderr, ".back: %o ", linep->start.back); 671 fprintf(stderr, ".mcase: %o\n", linep->start.mcase); 672 fprintf(stderr, " end.col: %o ", linep->end.col); 673 fprintf(stderr, ".psize: %o ", linep->end.psize); 674 fprintf(stderr, ".railmag: %o ", linep->end.railmag); 675 fprintf(stderr, ".verd: %o ", linep->end.verd); 676 fprintf(stderr, ".back: %o ", linep->end.back); 677 fprintf(stderr, ".mcase: %o\n", linep->end.mcase); 678 fprintf(stderr, "len: %d\t", linep->len); 679 fprintf(stderr, "codep: "); 680 for (i = 0; i < linep->len; i++) 681 fprintf(stderr, "%o ", linep->codep[i] & 0377); 682 fprintf(stderr, "\n\n"); 683 } 684 #endif 685