1 #ifndef lint 2 static char sccsid[] = "@(#)t6.c 2.2 (CWI) 87/07/10"; 3 #endif lint 4 /* 5 * t6.c 6 * 7 * width functions, sizes and fonts 8 */ 9 10 #include "tdef.h" 11 #include "dev.h" 12 #include <sgtty.h> 13 #include <ctype.h> 14 #include "ext.h" 15 16 /* fitab[f][c] is 0 if c is not on font f 17 /* if it's non-zero, c is in fontab[f] at position 18 /* fitab[f][c]. 19 */ 20 extern struct Font *fontbase[NFONT+1]; 21 extern char *codetab[NFONT+1]; 22 extern int nchtab; 23 24 int fontlab[MAXFONTS+1]; 25 short *pstab; 26 int cstab[MAXFONTS+1]; 27 int ccstab[MAXFONTS+1]; 28 int bdtab[MAXFONTS+1]; 29 int sbold = 0; 30 31 width(j) 32 register tchar j; 33 { 34 register i, k; 35 36 if (j & (ZBIT|MOT)) { 37 if (iszbit(j)) 38 return(0); 39 if (isvmot(j)) 40 return(0); 41 k = absmot(j); 42 if (isnmot(j)) 43 k = -k; 44 return(k); 45 } 46 i = cbits(j); 47 if (i < ' ') { 48 if (i == '\b') 49 return(-widthp); 50 if (i == PRESC) 51 i = eschar; 52 else if (iscontrol(i)) 53 return(0); 54 } 55 if (i==ohc) 56 return(0); 57 i = trtab[i]; 58 if (i < 32) 59 return(0); 60 if (sfbits(j) == oldbits) { 61 xfont = pfont; 62 xpts = ppts; 63 } else 64 xbits(j, 0); 65 if (widcache[i-32].fontpts == (xfont<<8) + xpts && !setwdf) 66 k = widcache[i-32].width; 67 else { 68 k = getcw(i-32); 69 if (bd) 70 k += (bd - 1) * HOR; 71 if (cs) 72 k = cs; 73 } 74 widthp = k; 75 return(k); 76 } 77 78 /* 79 * clear width cache-- s means just space 80 */ 81 zapwcache(s) 82 { 83 register i; 84 85 if (s) { 86 widcache[0].fontpts = 0; 87 return; 88 } 89 for (i=0; i<NWIDCACHE; i++) 90 widcache[i].fontpts = 0; 91 } 92 93 getcw(i) 94 register int i; 95 { 96 register int k; 97 register char *p; 98 register int x, j; 99 int nocache = 0; 100 int savxfont = 0, savsbold = 0, savulfont = 0; 101 102 /* 103 * Here comes first part of bug fix 104 */ 105 106 if( xfont > nfonts) { /* font is not mounted */ 107 savxfont = xfont; 108 if( xfont == sbold) { 109 savsbold = sbold; 110 sbold = 0; 111 } 112 if( xfont == ulfont) { 113 savulfont = ulfont; 114 ulfont = 0; 115 } 116 xfont = 0; 117 setfp(0, fontlab[savxfont], 0); 118 bdtab[0] = bdtab[savxfont]; /* Save */ 119 cstab[0] = cstab[savxfont]; /* as */ 120 ccstab[0] = ccstab[savxfont]; /* well */ 121 } 122 /* End */ 123 124 125 bd = 0; 126 if (i >= nchtab + 128-32) { 127 j = abscw(i + 32 - (nchtab+128)); 128 goto g0; 129 } 130 if (i == 0) { /* a blank */ 131 k = (fontab[xfont][0] * spacesz + 6) / 12; 132 /* this nonsense because .ss cmd uses 1/36 em as its units */ 133 /* and default is 12 */ 134 goto g1; 135 } 136 if ((j = fitab[xfont][i] & BYTEMASK) == 0) { /* it's not on current font */ 137 /* search through search list of xfont 138 /* to see what font it ought to be on. 139 /* searches S, then remaining fonts in wraparound order. 140 */ 141 nocache = 1; 142 if (smnt) { 143 int ii, jj; 144 for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) { 145 j = fitab[ii][i] & BYTEMASK; 146 if (j != 0) { 147 p = fontab[ii]; 148 k = *(p + j); 149 if (xfont == sbold) 150 bd = bdtab[ii]; 151 if (setwdf) 152 numtab[CT].val |= kerntab[ii][j]; 153 goto g1; 154 } 155 } 156 } 157 k = fontab[xfont][0]; /* leave a space-size space */ 158 goto g1; 159 } 160 g0: 161 p = fontab[xfont]; 162 if (setwdf) 163 numtab[CT].val |= kerntab[xfont][j]; 164 k = *(p + j); 165 g1: 166 if (!bd) 167 bd = bdtab[xfont]; 168 if (cs = cstab[xfont]) { 169 nocache = 1; 170 if (ccs = ccstab[xfont]) 171 x = ccs; 172 else 173 x = xpts; 174 cs = (cs * EMPTS(x)) / 36; 175 } 176 k = ((k&BYTEMASK) * xpts + (Unitwidth / 2)) / Unitwidth; 177 /* 178 * undo the fontswap 179 */ 180 if(savxfont) { 181 xfont = savxfont; 182 if(savsbold) 183 sbold = savsbold; 184 if(savulfont) 185 ulfont = savulfont; 186 /* 187 * H'm, I guess we should not put 188 * this width in the cache 189 */ 190 nocache = 1; 191 } 192 if (nocache|bd) 193 widcache[i].fontpts = 0; 194 else { 195 widcache[i].fontpts = (xfont<<8) + xpts; 196 widcache[i].width = k; 197 } 198 return(k); 199 /* Unitwidth is Units/Point, where 200 /* Units is the fundamental digitization 201 /* of the character set widths, and 202 /* Point is the number of goobies in a point 203 /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6 204 /* In effect, it's the size at which the widths 205 /* translate directly into units. 206 */ 207 } 208 209 abscw(n) /* return index of abs char n in fontab[], etc. */ 210 { register int i, ncf; 211 212 ncf = fontbase[xfont]->nwfont & BYTEMASK; 213 for (i = 0; i < ncf; i++) 214 if (codetab[xfont][i] == n) 215 return i; 216 return 0; 217 } 218 219 xbits(i, bitf) 220 register tchar i; 221 { 222 register k; 223 224 xfont = fbits(i); 225 k = sbits(i); 226 if (k) { 227 xpts = pstab[--k]; 228 oldbits = sfbits(i); 229 pfont = xfont; 230 ppts = xpts; 231 return; 232 } 233 switch (bitf) { 234 case 0: 235 xfont = font; 236 xpts = pts; 237 break; 238 case 1: 239 xfont = pfont; 240 xpts = ppts; 241 break; 242 case 2: 243 xfont = mfont; 244 xpts = mpts; 245 } 246 } 247 248 249 tchar setch() 250 { 251 register j; 252 char temp[10]; 253 register char *s; 254 extern char *chname; 255 extern short *chtab; 256 extern int nchtab; 257 258 s = temp; 259 if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0) 260 return(0); 261 *s = '\0'; 262 for (j = 0; j < nchtab; j++) 263 if (strcmp(&chname[chtab[j]], temp) == 0) 264 return(j + 128 | chbits); 265 return(0); 266 } 267 268 tchar setabs() /* set absolute char from \C'...' */ 269 { 270 int i, n, nf; 271 extern int nchtab; 272 273 getch(); 274 n = 0; 275 n = inumb(&n); 276 getch(); 277 if (nonumb) 278 return 0; 279 return n + nchtab + 128; 280 } 281 /* 282 * I (jaap) expand fontlab to the maximum of fonts troff can 283 * handle. The maximum number i, due to the two chars 284 * fontname limit, is 99. 285 * If we don't use the (named) font in one of the 286 * standard position, we install the name in the next 287 * free slot. Whenever we need info about the font, we 288 * read in the data at position zero, and secretly use 289 * the data (actually only necessary for the width 290 * and ligature info). The ptfont() (t10.c) routine will tell 291 * the device filter to put the font always at position 292 * zero if xfont > physfonts, so no need to change these filters. 293 * Yes, this is a bit kludgy. 294 * 295 * This gives the new specs of findft: 296 * 297 * find the font name i, where i also can be a number. 298 * 299 * Installs the font(name) i when not present 300 * 301 * returns -1 on error 302 */ 303 304 findft(i) 305 register int i; 306 { 307 register k; 308 register char *p; 309 extern char * unpair(); 310 311 p = unpair(i); 312 313 /* first look for numbers */ 314 if( isdigit(p[0]) && (p[1] == 0 || isdigit(p[1]))) { 315 k = p[0] - '0'; 316 if( p[1] > 0 && isdigit(p[1])) 317 k = 10 * k + ( p[1] - '0'); 318 319 /* 320 fprintf(ptid, "x xxx it's a number: %d\n", k); 321 */ 322 if( k > 0 && k <= nfonts && fontbase[k]->specfont == 0 ) { 323 /* 324 fprintf(ptid, "x xxx it's a mounted font\n"); 325 */ 326 return(k); /* mounted font */ 327 } 328 if( fontlab[k] && k <= MAXFONTS) { /* translate */ 329 /* 330 fprintf(ptid, "x xxx font exists\n"); 331 */ 332 return(k); /*number to a name */ 333 } 334 else { 335 fprintf(stderr, "troff: no font at position %d\n", k); 336 return(-1); /* wild number */ 337 } 338 } 339 340 /* 341 * Now we look for font names 342 */ 343 for (k = 1; fontlab[k] != i; k++) { 344 if (k > MAXFONTS +1) /* the +1 is for the ``font cache'' */ 345 return(-1); /* running out of fontlab space */ 346 if ( !fontlab[k] ) { /* passed all existing names */ 347 if (k <= NFONT) { 348 if(setfp(k, i, 0) < 0) 349 return(-1); 350 nfonts = k; 351 } else 352 if(setfp(0, i, 0) < 0) 353 return(-1); 354 /* 355 fprintf(ptid, "x xxx installed %s on %d\n", name ,k); 356 */ 357 /* now install the name */ 358 fontlab[k] = i; 359 /* 360 * and remember accociated with 361 * this font, ligature info etc. 362 */ 363 return(k); 364 } 365 } 366 return(k); /* was one of the existing names */ 367 } 368 369 370 caseps() 371 { 372 register i; 373 374 if (skip()) 375 i = apts1; 376 else { 377 noscale++; 378 i = inumb(&apts); /* this is a disaster for fractional point sizes */ 379 noscale = 0; 380 if (nonumb) 381 return; 382 } 383 casps1(i); 384 } 385 386 387 casps1(i) 388 register int i; 389 { 390 391 /* 392 * in olden times, it used to ignore changes to 0 or negative. 393 * this is meant to allow the requested size to be anything, 394 * in particular so eqn can generate lots of \s-3's and still 395 * get back by matching \s+3's. 396 397 if (i <= 0) 398 return; 399 */ 400 apts1 = apts; 401 apts = i; 402 pts1 = pts; 403 pts = findps(i); 404 mchbits(); 405 } 406 407 408 findps(i) 409 register int i; 410 { 411 register j, k; 412 413 for (j=k=0 ; pstab[j] != 0 ; j++) 414 if (abs(pstab[j]-i) < abs(pstab[k]-i)) 415 k = j; 416 417 return(pstab[k]); 418 } 419 420 421 mchbits() 422 { 423 register i, j, k; 424 425 i = pts; 426 for (j = 0; i > (k = pstab[j]); j++) 427 if (!k) { 428 k = pstab[--j]; 429 break; 430 } 431 chbits = 0; 432 setsbits(chbits, ++j); 433 setfbits(chbits, font); 434 sps = width(' ' | chbits); 435 zapwcache(1); 436 } 437 438 setps() 439 { 440 register int i, j; 441 442 i = cbits(getch()); 443 if (isdigit(i)) { /* \sd or \sdd */ 444 i -= '0'; 445 if (i == 0) /* \s0 */ 446 j = apts1; 447 else if (i <= 3 && isdigit(j = cbits(ch=getch()))) { /* \sdd */ 448 j = 10 * i + j - '0'; 449 ch = 0; 450 } else /* \sd */ 451 j = i; 452 } else if (i == '(') { /* \s(dd */ 453 j = cbits(getch()) - '0'; 454 j = 10 * j + cbits(getch()) - '0'; 455 if (j == 0) /* \s(00 */ 456 j = apts1; 457 } else if (i == '+' || i == '-') { /* \s+, \s- */ 458 j = cbits(getch()); 459 if (isdigit(j)) { /* \s+d, \s-d */ 460 j -= '0'; 461 } else if (j == '(') { /* \s+(dd, \s-(dd */ 462 j = cbits(getch()) - '0'; 463 j = 10 * j + cbits(getch()) - '0'; 464 } 465 if (i == '-') 466 j = -j; 467 j += apts; 468 } 469 casps1(j); 470 } 471 472 473 tchar setht() /* set character height from \H'...' */ 474 { 475 int n; 476 tchar c; 477 478 getch(); 479 n = inumb(&apts); 480 getch(); 481 if (n == 0 || nonumb) 482 n = apts; /* does this work? */ 483 c = CHARHT; 484 c |= ZBIT; 485 setsbits(c, n); 486 return(c); 487 } 488 489 tchar setslant() /* set slant from \S'...' */ 490 { 491 int n; 492 tchar c; 493 494 getch(); 495 n = 0; 496 n = inumb(&n); 497 getch(); 498 if (nonumb) 499 n = 0; 500 c = SLANT; 501 c |= ZBIT; 502 setsfbits(c, n+180); 503 return(c); 504 } 505 506 507 casest() 508 { 509 register i, j; 510 register char last; 511 512 skip(); 513 i = getrq(); 514 if (!i || i == 'P') { 515 stip = stip1; 516 return; 517 } 518 if (i == '0') 519 goto sterr; 520 521 last = cbits(i) >> BYTE; 522 if ((j = (i & BYTEMASK) - '0') >= 0 && j <= 9) {/* digit - see if two */ 523 if (last) 524 if ((last -= '0') < 0 || last > 9) 525 goto sterr; 526 if (j > nstips) 527 goto sterr; 528 } else { /* stipple name */ 529 for (j = 0; stiplab[j] != i; j++) 530 if (j > nstips) 531 goto sterr; 532 } 533 stip1 = stip; 534 stip = j; 535 return; 536 sterr: 537 fprintf(stderr, "troff: Can't find stipple %c%c\n", i & BYTEMASK, last); 538 } 539 540 541 caseft() 542 { 543 skip(); 544 setfont(1); 545 } 546 547 548 setfont(a) 549 int a; 550 { 551 register i, j; 552 553 if (a) 554 i = getrq(); 555 else 556 i = getsn(); 557 if (!i || i == 'P') { 558 j = font1; 559 goto s0; 560 } 561 if (i == 'S' || i == '0') 562 return; 563 if ((j = findft(i)) == -1) 564 #ifdef notdef 565 /* findft does the setfp if possible */ 566 if ((j = setfp(0, i, 0)) == -1) /* try to put it in position 0 */ 567 #endif 568 return; 569 s0: 570 font1 = font; 571 font = j; 572 mchbits(); 573 } 574 575 576 setwd() 577 { 578 register base, wid; 579 register tchar i; 580 int delim, emsz, k; 581 int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; 582 583 base = numtab[ST].val = numtab[ST].val = wid = numtab[CT].val = 0; 584 if (ismot(i = getch())) 585 return; 586 delim = cbits(i); 587 savhp = numtab[HP].val; 588 numtab[HP].val = 0; 589 savapts = apts; 590 savapts1 = apts1; 591 savfont = font; 592 savfont1 = font1; 593 savpts = pts; 594 savpts1 = pts1; 595 setwdf++; 596 while (cbits(i = getch()) != delim && !nlflg) { 597 k = width(i); 598 wid += k; 599 numtab[HP].val += k; 600 if (!ismot(i)) { 601 emsz = POINT * xpts; 602 } else if (isvmot(i)) { 603 k = absmot(i); 604 if (isnmot(i)) 605 k = -k; 606 base -= k; 607 emsz = 0; 608 } else 609 continue; 610 if (base < numtab[SB].val) 611 numtab[SB].val = base; 612 if ((k = base + emsz) > numtab[ST].val) 613 numtab[ST].val = k; 614 } 615 setn1(wid, 0, (tchar) 0); 616 numtab[HP].val = savhp; 617 apts = savapts; 618 apts1 = savapts1; 619 font = savfont; 620 font1 = savfont1; 621 pts = savpts; 622 pts1 = savpts1; 623 mchbits(); 624 setwdf = 0; 625 } 626 627 628 tchar vmot() 629 { 630 dfact = lss; 631 vflag++; 632 return(mot()); 633 } 634 635 636 tchar hmot() 637 { 638 dfact = EM; 639 return(mot()); 640 } 641 642 643 tchar mot() 644 { 645 register int j, n; 646 register tchar i; 647 648 j = HOR; 649 getch(); /*eat delim*/ 650 if (n = atoi()) { 651 if (vflag) 652 j = VERT; 653 i = makem(quant(n, j)); 654 } else 655 i = 0; 656 getch(); 657 vflag = 0; 658 dfact = 1; 659 return(i); 660 } 661 662 663 tchar sethl(k) 664 int k; 665 { 666 register j; 667 tchar i; 668 669 j = EM / 2; 670 if (k == 'u') 671 j = -j; 672 else if (k == 'r') 673 j = -2 * j; 674 vflag++; 675 i = makem(j); 676 vflag = 0; 677 return(i); 678 } 679 680 681 tchar makem(i) 682 register int i; 683 { 684 register tchar j; 685 686 if ((j = i) < 0) 687 j = -j; 688 j |= MOT; 689 if (i < 0) 690 j |= NMOT; 691 if (vflag) 692 j |= VMOT; 693 return(j); 694 } 695 696 697 tchar getlg(i) 698 tchar i; 699 { 700 tchar j, k; 701 register int lf; 702 703 /* remember to map the font */ 704 if ((lf = fontbase[fbits(i) > nfonts ? 0 : fbits(i)]->ligfont) == 0) { 705 /* font lacks ligatures */ 706 return(i); 707 } 708 j = getch0(); 709 if (cbits(j) == 'i' && (lf & LFI)) 710 j = LIG_FI; 711 else if (cbits(j) == 'l' && (lf & LFL)) 712 j = LIG_FL; 713 else if (cbits(j) == 'f' && (lf & LFF)) { 714 if ((lf & (LFFI|LFFL)) && lg != 2) { 715 k = getch0(); 716 if (cbits(k)=='i' && (lf&LFFI)) 717 j = LIG_FFI; 718 else if (cbits(k)=='l' && (lf&LFFL)) 719 j = LIG_FFL; 720 else { 721 *pbp++ = k; 722 j = LIG_FF; 723 } 724 } else 725 j = LIG_FF; 726 } else { 727 *pbp++ = j; 728 j = i; 729 } 730 return(i & SFMASK | j); 731 } 732 733 734 caselg() 735 { 736 737 lg = 1; 738 if (skip()) 739 return; 740 lg = atoi(); 741 } 742 743 744 casefp() 745 { 746 register int i, j; 747 register char *s; 748 749 skip(); 750 /* allow .fp for fonts >nfonts, <NFONTS? */ 751 if ((i = cbits(getch()) - '0') <= 0 || i > nfonts) 752 errprint("fp: bad font position %d", i); 753 else if (skip() || !(j = getrq())) 754 errprint("fp: no font name"); 755 else if (skip() || !getname()) 756 setfp(i, j, 0); 757 else /* 3rd argument = filename */ 758 setfp(i, j, nextf); 759 } 760 761 setfp(pos, f, truename) /* mount font f at position pos[0...NFONTS] */ 762 register pos; 763 int f; 764 char *truename; 765 { 766 register k; 767 register struct Font *ft; 768 int n; 769 char longname[NS], shortname[20]; 770 extern int nchtab; 771 extern struct dev dev; 772 773 if (fontlab[pos] == f) /* if f already mounted at pos, */ 774 return(pos); /* don't remount it */ 775 zapwcache(0); 776 if (truename) 777 strcpy(shortname, truename); 778 else { 779 shortname[0] = f & BYTEMASK; 780 shortname[1] = f >> BYTE; 781 shortname[2] = '\0'; 782 } 783 sprintf(longname, "%s/dev%s/%s.out", fontfile, devname, shortname); 784 if ((k = open(longname, 0)) < 0) { 785 errprint("Can't open %s", longname); 786 return(-1); 787 } 788 if ((ft = fontbase[pos]) == 0) { 789 ft = fontbase[pos] = (struct Font *) malloc(EXTRAFONT); 790 ft->nwfont = MAXCHARS; 791 fontab[pos] = (char *)(ft + 1); 792 } 793 n = ft->nwfont; 794 read(k, (char *) ft, 3*n + nchtab + 128 - 32 + sizeof(struct Font)); 795 close(k); 796 797 k = ft->nwfont; 798 kerntab[pos] = (char *) fontab[pos] + k; 799 codetab[pos] = (char *) fontab[pos] + 2 * k; 800 /* have to reset the fitab pointer because the width may be different */ 801 fitab[pos] = (char *) fontab[pos] + 3 * k; 802 ft->nwfont = n; /* so can load a larger one again later */ 803 if (k > n) { 804 errprint("Font %s too big for position %d", shortname, pos); 805 return(-1); 806 } 807 if (pos == smnt) { 808 smnt = 0; 809 sbold = 0; 810 } 811 if ((fontlab[pos] = f) == 'S') 812 smnt = pos; 813 bdtab[pos] = cstab[pos] = ccstab[pos] = 0; 814 /* if there is a directory, no place to store its name. */ 815 /* if position isn't zero, no place to store its value. */ 816 /* only time a FONTPOS is pushed back is if it's a */ 817 /* standard font on position 0 (i.e., mounted implicitly. */ 818 /* there's a bug here: if there are several input lines */ 819 /* that look like .ft XX in short successtion, the output */ 820 /* will all be in the last one because the "x font ..." */ 821 /* comes out too soon. pushing back FONTPOS doesn't work */ 822 /* with .ft commands because input is flushed after .xx cmds */ 823 824 /* 825 * Trying to fix this FONTPOS problem: See findft() 826 */ 827 if ( pos > 0 && pos <= physfonts) 828 ptfpcmd(pos, shortname); 829 return(pos); 830 } 831 832 833 casecs() 834 { 835 register i, j; 836 837 noscale++; 838 skip(); 839 if (!(i = getrq()) || (i = findft(i)) < 0) 840 goto rtn; 841 skip(); 842 cstab[i] = atoi(); 843 skip(); 844 j = atoi(); 845 if (nonumb) 846 ccstab[i] = 0; 847 else 848 ccstab[i] = findps(j); 849 rtn: 850 zapwcache(0); 851 noscale = 0; 852 } 853 854 855 casebd() 856 { 857 register i, j, k; 858 859 zapwcache(0); 860 k = 0; 861 bd0: 862 if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { 863 if (k) 864 goto bd1; 865 else 866 return; 867 } 868 if (j == smnt) { 869 k = smnt; 870 goto bd0; 871 } 872 if (k) { 873 sbold = j; 874 j = k; 875 } 876 bd1: 877 skip(); 878 noscale++; 879 bdtab[j] = atoi(); 880 noscale = 0; 881 } 882 883 884 casevs() 885 { 886 register i; 887 888 skip(); 889 vflag++; 890 dfact = INCH; /* default scaling is points! */ 891 dfactd = 72; 892 res = VERT; 893 i = inumb(&lss); 894 if (nonumb) 895 i = lss1; 896 /* if(i < VERT)i = VERT; */ 897 if (i < VERT) 898 i = 0; 899 lss1 = lss; 900 lss = i; 901 } 902 903 904 casess() 905 { 906 register i; 907 908 noscale++; 909 skip(); 910 if (i = atoi()) { 911 spacesz = i & 0177; 912 zapwcache(0); 913 sps = width(' ' | chbits); 914 } 915 noscale = 0; 916 } 917 918 919 tchar xlss() 920 { 921 /* stores \x'...' into 922 /* two successive tchars. 923 /* the first contains HX, the second the value, 924 /* encoded as a vertical motion. 925 /* decoding is done in n2.c by pchar(). 926 */ 927 int i; 928 929 getch(); 930 dfact = lss; 931 i = quant(atoi(), VERT); 932 dfact = 1; 933 getch(); 934 if (i >= 0) 935 *pbp++ = MOT | VMOT | i; 936 else 937 *pbp++ = MOT | VMOT | NMOT | -i; 938 return(HX); 939 } 940 941 char * 942 unpair(i) 943 register int i; 944 { static char name[3]; 945 946 name[0] = i & BYTEMASK; 947 name[1] = i >> BYTE; 948 name[2] = 0; 949 return (name); 950 } 951