eps@toaster.SFSU.EDU (Eric P. Scott) (10/21/90)
Hey Macintosh-lovers! (Yeah, both of you!) Last year I submitted my first "Mac-to-NeXT connectivity product"-- tifftoeps. I've just hacked it into a Webster dictionary lookup that displays the pictures too! (I wouldn't need all this code if NeXT's TIFF routines would read their own files instead of complaining about NX_COMPRESSION_NOT_YET_SUPPORTED.) Actually, this won't display ALL the pictures, since some of them are EPSF instead of TIFF, and I don't use the Window Server for imaging... but the Mac's screen resolution IS less than 150dpi, so I don't think anyone would object... :-) This is for Mac II-family machines with 256-color RGB displays and NCSA Telnet 2.3 or later (this includes derivatives such as BYU Telnet). (NCSA Telnet is in the Public Domain, and available for anonymous FTP from zaphod.ncsa.uiuc.edu. If you have an Ethernet (or AppleTalk-to-Ethernet via Shiva FastPath or Cayman GatorBox) connection and you don't have NCSA Telnet, what are you waiting for? It's even better with Apple's MacTCP...) Compile with: cc -s -o icrwebster -O -bsd icrwebster.c -ltext -lsys_s -=EPS=- ------- /* * icrwebster - display webster's images with NCSA Telnet 2.3 * Eric P. Scott, San Francisco State University, October 1990 * * Copyright 1990 by Eric P. Scott except as noted below. * * Credit where credit is due-ware: recognize what I've * contributed, take responsibility for what you do with/to it. * (i.e. don't pass my work off as your own, or vice-versa.) * You are granted a nonexclusive, royalty-free license to use * and adapt this software, and you may redistribute it in whole * or in part, in source and/or binary forms. * * * This is an exercise in code reusability; several existing * code fragments were blended together to produce this * monstrosity. It's not intended to be elegant, it's just a * little experiment I thought I'd share with the net.community. * * You need a Mac II with an 8-bit color display to try this-- * see Chapter 7 in the NCSA Telnet 2.3 documentation. */ #include <stdio.h> #include <text/webster.h> #ifndef lint static char sccsid[]="@(#)icrwebster 1.0 (SFSU) 10/20/90"; #endif ReferenceBook *book; int thesaurus=0; char *wname; main(argc, argv) int argc; char *argv[]; { char *malloc(), *rindex(); void lookup(); extern int optind; extern char *optarg; register int i; char line[1024]; dictionaryFoldSenses=60; while ((i=getopt(argc, argv, "tw:"))!=EOF) switch (i) { case 't': thesaurus++; break; case 'w': if (*optarg>='0'&&*optarg<='9') { dictionaryFoldSenses=atoi(optarg); break; } /*FALL THROUGH*/ default: (void)fprintf(stderr, "Usage: %s [options] [word [...]]\n", *argv); (void)fputs("\t-t use Thesaurus\n\t-w# set width\n", stderr); exit(0); break; } #ifdef __STRICT_BSD__ (void)setbuffer(stdout, malloc(4096), 4096); #else setvbuf(stdout, (char *)NULL, _IOFBF, 4096); #endif if (optind<argc) do { if (wname=rindex(argv[optind], '/')) { wname++; (void)image(argv[optind]); } else lookup(argv[optind]); } while (++optind<argc); else for (;;) { (void)fputs("Word: ", stderr); fflush(stderr); if (!fgets(line, sizeof line, stdin)||line[0]=='\n') break; line[strlen(line)-1]='\0'; lookup(line); } if (book) (void)referenceClose(book); exit(0); } void lookup(word) char *word; { register int i; int n; Definition *D[16]; /* how big is big enough? */ if (!book) { if (!(book=referenceOpen(thesaurus ? "Webster-Thesaurus" : "Webster-Dictionary"))) { fputs("referenceOpen failed!\n", stderr); exit(1); } } bzero((char *)D, sizeof D); n=getDefinitions(word, book, 1, D, sizeof D/sizeof D[0]-1); if (n==0) { (void)fputs("No definition for ", stdout); (void)fputs(word, stdout); (void)fputs(".\n", stdout); (void)fflush(stdout); return; } i=0; do { if (i>1) putchar('\n'); if (D[i]->section>0&&!thesaurus) (void) printf("%% %s\n\n", websterSectionName[D[i]->section]); /* * The webster routines in libtext.a (1.0/1.0a) are really braindamaged. * I can't make use of font information since there's no setting for * dictionaryOutputFormat that doesn't trash stuff I need (why isn't * there a W_RAW???) and I don't feel like picking though the database * by hand. If you want a decent webster program, check out Steve * Hayman's--his way is faster, too. (And it does spell checking!) */ (void)putDefinition(D[i], 0); putchar('\n'); if (D[i]->picture&& D[i]->picture[strlen(D[i]->picture)-1]=='f') { (void)fflush(stdout); wname=D[i]->dotted ? D[i]->dotted : D[i]->entry; (void)image(D[i]->picture); } } while (++i<n); (void)fflush(stdout); freeDefinitions(D); } int iwidth, ilen, bits, invert, compression; long stripoff; int image(tfile) char *tfile; { void NULLDecode(), NeXTDecode(); FILE *tf; register int i; register long value; long sig, ifdoff; short ifditems; struct ifdent { short ifd_tag; short ifd_type; long ifd_len; union { unsigned long ifd_long; unsigned short ifd_short; unsigned char ifd_byte; } ifd_off; } *ifdp; if (!(tf=fopen(tfile, "r"))) { perror(tfile); return(1); } if (fread((char *)&sig, sizeof sig, 1, tf)!=1) { perror("fread"); fatal: fclose(tf); return(1); } if (sig!=0x4d4d002a) { /* big-endian */ (void)fprintf(stderr, "%s: that's not a TIFF file!\n", tfile); goto fatal; } iwidth=0; ilen=0; bits=0; invert=255; compression=1; stripoff=0L; if (fread((char *)&ifdoff, sizeof ifdoff, 1, tf)!=1) { perror("fread"); goto fatal; } if (fseek(tf, ifdoff, 0)<0L) { perror("fseek"); goto fatal; } if (fread((char *)&ifditems, sizeof ifditems, 1, tf)!=1) { perror("fread"); goto fatal; } if (!(ifdp=(struct ifdent *)malloc(ifditems*sizeof (struct ifdent)))) { perror("malloc"); goto fatal; } if (fread((char *)ifdp, sizeof (struct ifdent), ifditems, tf)!= ifditems) { perror("fread"); goto fatal; } for (i=0;i<ifditems;i++) { switch (ifdp->ifd_type) { case 1: value=ifdp->ifd_off.ifd_byte; break; case 3: value=ifdp->ifd_off.ifd_short; break; case 4: value=ifdp->ifd_off.ifd_long; break; default: /* ifdp->ifd_off.ifd_long is offset */ value=0L; /* do The Wrong Thing(tm) */ break; } switch (ifdp->ifd_tag) { case 256: /* ImageWidth */ iwidth=value; break; case 257: /* ImageLength */ ilen=value; break; case 258: /* BitsPerSample */ bits=value; break; case 259: /* Compression */ if (value!=1L&&value!=32766L) { (void)fprintf(stderr, "%s: unsupported Compression=%ld\n", tfile, value); goto fatal; } compression=value; break; case 262: /* PhotometricInterpretation */ switch (value) { case 0L: invert=255; break; case 1L: invert=0; break; default: (void)fprintf(stderr, "%s: unsupported PhotometricInterpretation=%ld\n", tfile , value); switch ((int)value) { case 5: /* grayscale alpha */ case 6: /* RGB alpha */ case 7: /* CMY or CMYK alpha */ case 14: /* 8-bit Pcolor alpha */ (void)fputs("\tI don't grok alpha\n", stderr); break; case 2: /* RGB */ case 3: /* CMY or CMYK */ case 10: /* 8-bit Pcolor */ (void)fputs("\tNo color support!\n", stderr); break; } goto fatal; } break; case 273: /* StripOffsets */ stripoff=value; break; case 277: /* SamplesPerPixel */ if (value!=1L) { (void)fprintf(stderr, "%s: unsupported SamplesPerPixel=%ld\n", tfile, value); goto fatal; } break; #ifdef NOTDEF case 284: /* PlanarConfiguration */ /* don't care when SamplesPerPixel==1 */ break; #endif default: break; } ifdp++; } if (iwidth<=0) { (void)fprintf(stderr, "%s: missing ImageWidth\n", tfile); goto fatal; } if (ilen<=0) { (void)fprintf(stderr, "%s: missing ImageLength\n", tfile); goto fatal; } if (bits<=0) { (void)fprintf(stderr, "%s: missing BitsPerSample\n", tfile); goto fatal; } if (stripoff<=0L) { (void)fprintf(stderr, "%s: missing StripOffsets\n", tfile); goto fatal; } if (fseek(tf, stripoff, 0L)<0L) { perror("fseek"); goto fatal; } #ifdef DEBUG (void)fprintf(stderr, "imaging %dx%dx%d\n", iwidth, ilen, bits); #endif if (compression==1) NULLDecode(tf); else if (compression==32766) { if (bits==2) NeXTDecode(tf); else (void)fprintf(stderr, "%s: NeXT compressions only supported for 2-bit images\n", tfile); } (void)fclose(tf); return(0); } void NULLDecode(tf) FILE *tf; { void output(); char buf[284]; int scanline, row; scanline = ((long)iwidth*bits+7L)/8L; for (row=0; row<ilen; row++) { (void)fread(buf, 1, scanline, tf); output((unsigned char *)buf, row); } } /* This table derived from NCSA Public Domain material. */ static unsigned char rgb[768]={ 255, 255, 255, 255, 255, 204, 255, 255, 153, 255, 255, 102, 255, 255, 51, 255, 255, 0, 255, 204, 255, 255, 204, 204, 255, 204, 153, 255, 204, 102, 255, 204, 51, 255, 204, 0, 255, 153, 255, 255, 153, 204, 255, 153, 153, 255, 153, 102, 255, 153, 51, 255, 153, 0, 255, 102, 255, 255, 102, 204, 255, 102, 153, 255, 102, 102, 255, 102, 51, 255, 102, 0, 255, 51, 255, 255, 51, 204, 255, 51, 153, 255, 51, 102, 255, 51, 51, 255, 51, 0, 255, 0, 255, 255, 0, 204, 255, 0, 153, 255, 0, 102, 255, 0, 51, 255, 0, 0, 204, 255, 255, 204, 255, 204, 204, 255, 153, 204, 255, 102, 204, 255, 51, 204, 255, 0, 204, 204, 255, 204, 204, 204, 204, 204, 153, 204, 204, 102, 204, 204, 51, 204, 204, 0, 204, 153, 255, 204, 153, 204, 204, 153, 153, 204, 153, 102, 204, 153, 51, 204, 153, 0, 204, 102, 255, 204, 102, 204, 204, 102, 153, 204, 102, 102, 204, 102, 51, 204, 102, 0, 204, 51, 255, 204, 51, 204, 204, 51, 153, 204, 51, 102, 204, 51, 51, 204, 51, 0, 204, 0, 255, 204, 0, 204, 204, 0, 153, 204, 0, 102, 204, 0, 51, 204, 0, 0, 153, 255, 255, 153, 255, 204, 153, 255, 153, 153, 255, 102, 153, 255, 51, 153, 255, 0, 153, 204, 255, 153, 204, 204, 153, 204, 153, 153, 204, 102, 153, 204, 51, 153, 204, 0, 153, 153, 255, 153, 153, 204, 153, 153, 153, 153, 153, 102, 153, 153, 51, 153, 153, 0, 153, 102, 255, 153, 102, 204, 153, 102, 153, 153, 102, 102, 153, 102, 51, 153, 102, 0, 153, 51, 255, 153, 51, 204, 153, 51, 153, 153, 51, 102, 153, 51, 51, 153, 51, 0, 153, 0, 255, 153, 0, 204, 153, 0, 153, 153, 0, 102, 153, 0, 51, 153, 0, 0, 102, 255, 255, 102, 255, 204, 102, 255, 153, 102, 255, 102, 102, 255, 51, 102, 255, 0, 102, 204, 255, 102, 204, 204, 102, 204, 153, 102, 204, 102, 102, 204, 51, 102, 204, 0, 102, 153, 255, 102, 153, 204, 102, 153, 153, 102, 153, 102, 102, 153, 51, 102, 153, 0, 102, 102, 255, 102, 102, 204, 102, 102, 153, 102, 102, 102, 102, 102, 51, 102, 102, 0, 102, 51, 255, 102, 51, 204, 102, 51, 153, 102, 51, 102, 102, 51, 51, 102, 51, 0, 102, 0, 255, 102, 0, 204, 102, 0, 153, 102, 0, 102, 102, 0, 51, 102, 0, 0, 51, 255, 255, 51, 255, 204, 51, 255, 153, 51, 255, 102, 51, 255, 51, 51, 255, 0, 51, 204, 255, 51, 204, 204, 51, 204, 153, 51, 204, 102, 51, 204, 51, 51, 204, 0, 51, 153, 255, 51, 153, 204, 51, 153, 153, 51, 153, 102, 51, 153, 51, 51, 153, 0, 51, 102, 255, 51, 102, 204, 51, 102, 153, 51, 102, 102, 51, 102, 51, 51, 102, 0, 51, 51, 255, 51, 51, 204, 51, 51, 153, 51, 51, 102, 51, 51, 51, 51, 51, 0, 51, 0, 255, 51, 0, 204, 51, 0, 153, 51, 0, 102, 51, 0, 51, 51, 0, 0, 0, 255, 255, 0, 255, 204, 0, 255, 153, 0, 255, 102, 0, 255, 51, 0, 255, 0, 0, 204, 255, 0, 204, 204, 0, 204, 153, 0, 204, 102, 0, 204, 51, 0, 204, 0, 0, 153, 255, 0, 153, 204, 0, 153, 153, 0, 153, 102, 0, 153, 51, 0, 153, 0, 0, 102, 255, 0, 102, 204, 0, 102, 153, 0, 102, 102, 0, 102, 51, 0, 102, 0, 0, 51, 255, 0, 51, 204, 0, 51, 153, 0, 51, 102, 0, 51, 51, 0, 51, 0, 0, 0, 255, 0, 0, 204, 0, 0, 153, 0, 0, 102, 0, 0, 51, 238, 0, 0, 221, 0, 0, 187, 0, 0, 170, 0, 0, 136, 0, 0, 119, 0, 0, 85, 0, 0, 68, 0, 0, 34, 0, 0, 17, 0, 0, 0, 238, 0, 0, 221, 0, 0, 187, 0, 0, 170, 0, 0, 136, 0, 0, 119, 0, 0, 85, 0, 0, 68, 0, 0, 34, 0, 0, 17, 0, 0, 0, 238, 0, 0, 221, 0, 0, 187, 0, 0, 170, 0, 0, 136, 0, 0, 119, 0, 0, 85, 0, 0, 68, 0, 0, 34, 0, 0, 17, 238, 238, 238, 221, 221, 221, 187, 187, 187, 170, 170, 170, 136, 136, 136, 119, 119, 119, 85, 85, 85, 68, 68, 68, 34, 34, 34, 17, 17, 17, 0, 0, 0 }; static unsigned char idx1[2]={ 255, 0 }, idx2[4]={ 255, 251, 248, 0 }, idx4[16]={ 255, 254, 253, 172, 252, 251, 129, 250, 249, 86, 248, 247, 43, 246, 245, 0 }; int ox, oy; void output(buf, row) unsigned char *buf; int row; { register unsigned char *p, *q; register int i, c; unsigned char pbuf[1132]; #ifndef NO_RLE unsigned char rbuf[1144]; #endif if (row==0) { (void)printf("\033^W;%d;%d;%d;%d;0;%s^", ox, oy, iwidth, ilen, wname); ox+=5; oy+=3; if (bits<8) { (void)printf("\033^M;0;256;768;%s^", wname); p=rgb; q=p+sizeof rgb; do { if (*p>31&&*p<123) putchar(*p++); else { putchar((*p>>6)+123); putchar((*p++&63)+32); } } while (p<q); } (void)fflush(stdout); } p=buf; q=pbuf; switch (bits) { case 1: for (i=0;i<iwidth;i++) { c= *p++^invert; *q++ = idx1[(c>>7)&1]; if (++i>=iwidth) break; *q++ = idx1[(c>>6)&1]; if (++i>=iwidth) break; *q++ = idx1[(c>>5)&1]; if (++i>=iwidth) break; *q++ = idx1[(c>>4)&1]; if (++i>=iwidth) break; *q++ = idx1[(c>>3)&1]; if (++i>=iwidth) break; *q++ = idx1[(c>>2)&1]; if (++i>=iwidth) break; *q++ = idx1[(c>>1)&1]; if (++i>=iwidth) break; *q++ = idx1[c&1]; } break; case 2: for (i=0;i<iwidth;i++) { c= *p++^invert; *q++ = idx2[(c>>6)&3]; if (++i>=iwidth) break; *q++ = idx2[(c>>4)&3]; if (++i>=iwidth) break; *q++ = idx2[(c>>2)&3]; if (++i>=iwidth) break; *q++ = idx2[c&3]; } break; case 4: for (i=0;i<iwidth;i++) { c= *p++^invert; *q++ = idx4[(c>>4)&15]; if (++i>=iwidth) break; *q++ = idx4[c&15]; } break; default: for (i=0;i<iwidth;i++) *q++ = *p++^invert; } #ifndef NO_RLE i = rleit(pbuf, rbuf, iwidth); if (i>0) { (void)printf("\033^R;0;%d;1;%d;%s^", row, i, wname); p=rbuf; q=p+i; #else if (iwidth>0) { (void)printf("\033^P;0;%d;1;%d;%s^", row, iwidth, wname); p=pbuf; q=p+iwidth; #endif do { if (*p>31&&*p<123) putchar(*p++); else { putchar((*p>>6)+123); putchar((*p++&63)+32); } } while (p<q); } (void)fflush(stdout); } #ifndef NO_RLE /* rleit * by Tim Krauskopf * National Center for Supercomputing Applications * University of Illinois, Urbana-Champaign * * This program is in the public domain. * * * Compress the data to go out with a simple run-length encoded scheme. * */ rleit(buf,bufto,len) int len; unsigned char *buf,*bufto; { register unsigned char *p,*q,*cfoll,*clead; unsigned char *begp; int i; p = buf; cfoll = bufto; /* place to copy to */ clead = cfoll + 1; begp = p; while (len > 0) { /* encode stuff until gone */ q = p + 1; i = len-1; while (i && *p == *q && i+120 > len) { q++; i--; } if (q > p + 2) { /* three in a row */ if (p > begp) { *cfoll = p - begp; cfoll = clead; } *cfoll++ = 128 | (q-p); /* len of seq */ *cfoll++ = *p; /* char of seq */ len -= q-p; /* subtract len of seq */ p = q; clead = cfoll+1; begp = p; } else { *clead++ = *p++; /* copy one char */ len--; if (p > begp + 120) { *cfoll = p - begp; cfoll = clead++; begp = p; } } } /* * fill in last bytecount */ if (p > begp) *cfoll = p - begp; else clead--; /* don't need count position */ return((int)(clead - bufto)); /* how many stored as encoded */ } #endif /* * The following adapted from tif_next.c 1.8 5/22/90 * Copyright (c) 1988, 1990 by Sam Leffler. * All rights reserved. * * This file is provided for unrestricted use provided that this * legend is included on all tape media and as a part of the * software program in whole or part. Users may copy, modify or * distribute this file at will. */ /* * NeXT 2-bit Gray Scale Compression Algorithm Support */ #define LITERALROW 0x00 #define LITERALSPAN 0x40 void NeXTDecode(tf) FILE *tf; { register unsigned char *op; register int n; unsigned char buf[284]; int scanline, row; scanline = ((long)iwidth*2+7L)/8L; for (row=0; row<ilen; row++) { switch (n = getc(tf)) { case LITERALROW: /* * The entire scanline is given as literal values. */ (void)fread((char *)buf, 1, scanline, tf); break; case LITERALSPAN: { int off; /* * Each scanline is assumed to start off as all * white (we assume a PhotometricInterpretation * of ``min-is-black''). */ op=buf; n=sizeof buf; do *op++ = 0xff; while (--n>0); /* * The scanline has a literal span * that begins at some offset. */ off = getc(tf)*256; off += getc(tf); n = getc(tf)*256; n += getc(tf); (void)fread((char *)buf+off, 1, n, tf); break; } default: { register int npixels = 0, gray; /* * The scanline is composed of a sequence * of constant color ``runs''. We shift * into ``run mode'' and interpret bytes * as codes of the form <color><npixels> * until we've filled the scanline. */ op = buf; for (;;) { gray = (n>>6) & 0x3; n &= 0x3f; while (n-- > 0) switch (npixels++ & 3) { case 0: op[0] = gray << 6; break; case 1: op[0] |= gray << 4; break; case 2: op[0] |= gray << 2; break; case 3: *op++ |= gray; break; } if (npixels >= iwidth) break; n = getc(tf); } break; } } output(buf, row); } }