home *** CD-ROM | disk | FTP | other *** search
- /* mcread: macwrite.c
- Copyright (C) 1991, Mike Gleason Jr & NCEMRSoft.
- All Rights Reserved. */
-
- #include <stdio.h>
- #include <string.h>
- #include "mcread.h"
-
- typedef struct {
- short type; /* 0-1 */
- short unused1[3]; /* 2-7 */
- long offset; /* 8-11 */
- short len; /* 12-13 */
- short unused2; /* 14-15 */
- } MacWrite_Paragraph_Info;
-
- #define MACWRITE_45 6
- #define MACWRITE_22 3
-
- #define DEFAULT_COMMON " etnroaisdlhcfp"
- /* Most commonly occurring characters, MacWrite uses a crude
- compression scheme with these. The default uses the American
- version. */
-
- #define COMPRESSED_MASK 0x08
-
- char CommonChars[20];
- int GNNeedToReadByte = 1; /* for Getn() */
-
- int thrash_macwrite(in, name, dataforklen)
- FILE *in;
- char *name;
- long dataforklen;
- {
- MacWrite_Paragraph_Info P;
- long dataOffset, infoOffset, saved;
- register long Seek, StartOffset;
- char paragraphStatus;
- register int a, b, c, nibble, parIsCompressed;
- short version, numparas, curpara;
- short bytesInParagraph, bytesOut;
- #define CheckReadErr if (ferror(in)) goto ReadErr
- #define CheckSeekErr if (Seek) goto SeekErr;
-
- bytesOut = curpara = 0;
- (void) strcpy(CommonChars, (char *)DEFAULT_COMMON);
-
- if (dataforklen >= 0)
- (void) FindCommon(in, dataforklen);
-
- StartOffset = ftell(in); /* for macbinary files, this will be 128,
- otherwise it should be zero. */
-
- version = (short) Getw (in);
- CheckReadErr;
-
- if (version != MACWRITE_45) {
- if (version == MACWRITE_22)
- (void) fprintf (stderr, "%s: macwrite format too old (2.2)\n", name);
- else if (dataforklen) {
- if (version > MACWRITE_45)
- (void) fprintf (stderr, "%s: macwrite format too new (%d)\n", name, version);
- else
- (void) fprintf (stderr, "%s: macwrite format too old (%d)\n", name, version);
- }
- return (3);
- }
-
- numparas = (short) Getw (in);
- CheckReadErr;
-
- Seek = fseek (in, (long) (StartOffset + 264), SEEK_SET);
- CheckSeekErr;
- /* should now point to the variables for the body text. */
-
- infoOffset = (long) Getl (in);
- CheckReadErr;
-
- Seek = fseek (in, (StartOffset + infoOffset), SEEK_SET);
- CheckSeekErr;
-
- /* loop through and read all the paragraphs */
-
- while (1) {
- P.type = (short) Getw (in); if (ferror(in)) break;
- P.unused1[0] = (short) Getw (in); if (ferror(in)) break;
- P.unused1[1] = (short) Getw (in); if (ferror(in)) break;
- P.unused1[2] = (short) Getw (in); if (ferror(in)) break;
- P.offset = (long) Getl (in); if (ferror(in)) break;
- P.len = (short) Getw (in); if (ferror(in)) break;
- P.unused2 = (short) Getw (in); if (ferror(in)) break;
-
- dataOffset = P.offset & 0x00ffffff; /* lo 3 bytes only */
- paragraphStatus = (char) (P.offset >> 24);
-
- if (P.type < 0) { /* a PICT paragraph */
- (void) puts ("### picture omitted!");
- if (CheckPage())
- return (0);
- }
- if (P.type > 0) { /* a text paragraph */
- saved = ftell (in);
- Seek = fseek (in, (StartOffset + dataOffset), SEEK_SET);
- CheckSeekErr;
-
- bytesInParagraph = (short) Getw (in);
- CheckReadErr;
-
- wwInit();
- GNNeedToReadByte = 1;
- parIsCompressed = paragraphStatus & COMPRESSED_MASK;
- for (bytesOut=0; bytesOut<bytesInParagraph; bytesOut++) {
- if (parIsCompressed) { /* a compressed paragraph */
- nibble = Getn (in);
- if (nibble == 0x0f) { /* means that next 2
- nibbles form the
- next char. */
- a = Getn (in);
- b = Getn (in);
- c = (a << 4) + b;
- }
- else c = CommonChars[nibble];
- } else /* a regular paragraph */
- c = getc (in);
-
- if (c == EOF) {
- (void) fprintf(stderr, "%s: unexpected end of file.\n", name);
- return (4);
- }
-
- if (wwPutchar (c & 0x00ff))
- return (0); /* user skipped file */
- } /* end reading the para */
- if (wwFlush())
- return (0); /* user skipped file */
-
- Seek = fseek (in, saved, SEEK_SET);
- CheckSeekErr;
- } /* end text paragraph */
- else {
- /* it's a ruler, but
- who cares? */
- }
-
- if (++curpara >= numparas) break;
- } /* paragraph loop */
-
- return (0); /* exit success, mon */
-
- SeekErr:
- (void) fprintf(stderr, "%s: seek error occurred.\n", name);
- return (5);
-
- ReadErr:
- (void) fprintf(stderr, "%s: error occurred while trying to read the file.\n", name);
- return (6);
- } /* thrash_macwrite */
-
-
-
-
- int Getn (f)
- FILE *f;
- {
- static int c;
- extern int GNNeedToReadByte;
-
- if (GNNeedToReadByte) {
- c = getc(f);
- if (c == EOF) return (EOF);
- c &= 0x00ff;
- GNNeedToReadByte = 0; /* still got the other nibble to use. */
- return (c >> 4);
- }
-
- GNNeedToReadByte = 1;
- return (c & 0x000f);
- } /* Getn */
-
-
-
- /* This huge mess only accomplishes one thing: read in STR ID 700 from
- the resource fork of this macwrite file. What a waste... */
-
- int FindCommon(in, dataForkLen)
- FILE *in;
- long dataForkLen;
- {
- #define COMMON_ID 700
- register long rezforkstart, typeliststart, Seek;
- short numtypes;
- register short foundSTR;
-
- struct Oy {
- long dataOffset, mapOffset, datalen, maplen;
- } rheader;
-
- struct Foo {
- long crap[6];
- short typelistOffset, namelistOffset;
- } rmapheader;
-
- struct Bar {
- char type[5];/* really only [4], but I'm not reading in
- the whole structure at a time. */
- short n; /* number of rsrcs - 1*/
- short offset; /* from start of typelist to ref list */
- } typeinfo;
-
- struct Grok {
- short id, nameoffset;
- long dataoffset; /* from start of res data; lo 3 bytes */
- long handle;
- } refinfo;
-
- rezforkstart = (((128L + dataForkLen) / 128) + 1) * 128;
- /* the resource fork starts after the header (128 bytes) and
- after the data fork, which is padded to a multiple of 128. */
-
- Seek = fseek (in, rezforkstart, SEEK_SET);
- if (Seek) goto done; /* should be at rsrc fork start now */
-
-
- /* read the resource file header. */
- rheader.dataOffset = (long) Getl (in);
- if (ferror (in)) goto done;
-
- rheader.mapOffset = (long) Getl (in);
- if (ferror (in)) goto done;
-
- rheader.datalen = (long) Getl (in);
- if (ferror (in)) goto done;
-
- rheader.maplen = (long) Getl (in);
- if (ferror (in)) goto done;
-
-
- /* read the resource MAP header. */
- Seek = fseek (in, (long) (rezforkstart + rheader.mapOffset + 24L), SEEK_SET);
- if (Seek) goto done;
-
- rmapheader.typelistOffset = (short) Getw (in); /* 6 craps * 4 bytes = 24L bytes. */
- if (ferror (in)) goto done;
-
-
- /* read the typelist. */
- Seek = fseek (in, (long) (rezforkstart + rheader.mapOffset +
- rmapheader.typelistOffset), SEEK_SET);
- if (Seek) goto done;
-
- typeliststart = ftell (in);
-
- numtypes = (short) Getw (in) + 1; /* rez manager stores (numtypes - 1) ! */
- if (ferror(in)) goto done;
-
- foundSTR = 0;
- while (!foundSTR && --numtypes >= 0) {
- /* read in some info about the next type in the list. */
- typeinfo.type[0] = (char) getc (in);
- typeinfo.type[1] = (char) getc (in);
- typeinfo.type[2] = (char) getc (in);
- typeinfo.type[3] = (char) getc (in);
- typeinfo.type[4] = '\0';
- if (ferror (in)) goto done;
- typeinfo.n = (short) Getw (in) + 1; /* rez manager stores (numrsrcs - 1) ! */
- if (ferror (in)) goto done;
- typeinfo.offset = (short) Getw (in);
- if (ferror (in)) goto done;
-
- foundSTR = (strcmp (STR_TYPE, typeinfo.type) == 0);
- }
- if (!foundSTR) goto done; /* no 'STR '! */
- Seek = fseek (in, (long) (typeliststart + typeinfo.offset), SEEK_SET);
- if (Seek) goto done;
-
- while (--typeinfo.n >= 0) {
- refinfo.id = (short) Getw (in);
- if (ferror (in)) goto done;
- refinfo.nameoffset = (short) Getw (in);
- if (ferror (in)) goto done;
- refinfo.dataoffset = (long) Getl (in);
- if (ferror (in)) goto done;
- refinfo.handle = (long) Getl (in);
- if (ferror (in)) goto done;
-
- if (refinfo.id == COMMON_ID) break;
- }
- if (refinfo.id != COMMON_ID) goto done; /* no CommonChars! */
-
- refinfo.dataoffset &= 0x00ffffff; /* lo 3 bytes for offset */
- Seek = fseek (
- in,
- (long) (rezforkstart + refinfo.dataoffset +
- rheader.dataOffset + 5L), /* 4L for the length of the rsrc,
- which we already know, and
- another 1L for the pascal
- string's length byte. */
- SEEK_SET);
- if (Seek) goto done;
-
- (void) fgets (CommonChars, 18, in);
- CommonChars[16] = '\0';
-
- done:
- Seek = fseek (in, (long) 128, SEEK_SET);
- }
-
- /* eof */
-