home *** CD-ROM | disk | FTP | other *** search
- /*
- * crdprt.c - version 2.1 - November 1st, 1990
- *
- * crdprint - print a Microsoft Windows cardfile
- *
- * This program will print a cardfile in a simple fashion on any ASCII
- * printer. It does not bother drawing the cute (and timeconsuming) boxes
- * around the cards.
- *
- * Art Zemon July 12, 1986
- *
- * CompuServe: 72406,3275
- * UUCP: ucbvax!trwrb!felix!zemon
- **************************************************************************
- *
- * Updated: Munjal M. July 21, 1990
- * CompuServe: 76264,602
- **************************************************************************
- *
- * Updated : Version 2.0 - September 5, 1990
- * : Rod Hutson... CompuServe 72411,564
- * (403) 461-2431 (Edmonton, Alberta, Canada)
- * Changes : couldn't get large cardfiles (90 cards, 19000+ bytes) to print
- * so changed design of program to use only one file handle and
- * track file position with a long variable instead... original
- * version used two file handles open simulataneously to maintain
- * file position.
- * : altered variable names to follow Windows-style Hungarian
- * notation (with some variations due mainly to old habits)
- * : added copious commenting for those who like such things
- * : ensured worked with WINDOWS 3.0 Cardfile files
- **************************************************************************
- *
- * Updated : Version 2.1 - November 1st, 1990
- * : Rod Hutson... CompuServe 72411,564
- * (403) 461-2431 (Edmonton, Alberta, Canada)
- * Changes : modified program to properly handle cardfile cards
- * containing graphic images; any card containing a standard
- * cardfile 'picture' graphic as well as standard text is
- * processed as if the graphic weren't there; if the card
- * contains only a graphic image or is blank, only the index
- * line is processed; if the card contains text only, then
- * it is processed normally;
- * : while modifying previous ver 2.0 for the above functionality,
- * I discovered a mistake in the card data structures... these
- * are now corrected as described below.
- * : tested the resulting executable with cardfiles issued by
- * WUGNET, consisting of 100,000+ bytes, over 300 cards, and
- * many or most with some graphic image(s) on them
- * NOTE : rather than obsfucate the code to make it 'nice and tight',
- * I have left it loose and readable, and maybe even somewhat
- * unstructured (ie. no sub-function calls, etc).
- **************************************************************************
- */
-
- #include <stdio.h> /* provides NULL, SEEK_SET, etc */
- #include <stdlib.h>
-
- #define TEXT_BUF 512 /* size of text buffer for card text */
- #define INDEX_TEXT 40 /* max length of index line string */
- #define BYTE char /* a convenience, thats all */
-
- #ifndef NULL /* lint told me NULL not declared, */
- #define NULL 0 /* so I did this, just to be sure */
- #endif
-
- /**********************************************************/
- /* layout the data structures for a MicroSoft '.crd' file */
- /**********************************************************/
- /* file header structure */
- typedef struct {
- char acSigniture[3]; /* 3 bytes ... 'MGC' */
- int iNumCrds; /* 2 bytes ... number of cards in cardfile */
- } sFILEHDR; /* structure is 5 bytes long */
-
- /* index data structure for each card */
- typedef struct {
- int aiFuture[3]; /* 6 bytes ... reserved for future */
- long lOffset; /* 4 bytes ... card offset into file */
- BYTE bFlag; /* 1 byte ... some kind of flag */
- char acIndexText[INDEX_TEXT]; /* INDEX_TEXT bytes ... index line */
- BYTE bNull; /* 1 byte ... always '0' or NULL */
- } sINDEXHDR; /* structure is (12+INDEX_TEXT) bytes long */
-
- /* if card contains text only, this structure applies to card data */
- typedef struct {
- int iLenBMap; /* 2 bytes ... if no bitmap, always 0X0000 */
- int iLenText; /* 2 bytes ... number of bytes in text strings */
- } sTEXTONLY; /* structure is 4 bytes long */
-
- void main (int argc, char **argv)
- {
- /* we'll substitute this simple string for the graphics in Windows */
- static char acSep[] = "════════════════════════════════════════";
-
- FILE *hFile; /* handle to current cardfile */
-
- sFILEHDR sFileHdr; /* file header variable */
-
- sINDEXHDR sIndexHdr; /* card index line variable */
-
- sTEXTONLY sTextOnly; /* text-only card body variable */
-
- unsigned char acText[TEXT_BUF]; /* card body text buffer */
-
- unsigned int iCard, /* current card count */
- iCardFile, /* current cardfile count */
- iCheck, /* dummy error variable */
- iTextLength; /* dummy text length variable */
-
- long lCurrPos, /* current file position */
- lTmpPos; /* dummy file position variable */
-
- /* if command line did not include cardfile(s) to print out, msg & exit */
- if (argc < 2) {
- fputs ("CrdPrt V2.1, November 1st, 1990\n\n", stderr);
- fputs ("Usage: CrdPrt {card-file} [{card-file-2}...]\n", stderr);
- fputs ("\t{card-file} is any DOS file-spec including wild-cards.\n\n", stderr);
- fputs ("\tCrdPrt will display one or several cardfile(s) in a simple format\n", stderr);
- fputs ("\t without wasting valuable time doing fancy graphics.\n", stderr);
- exit (1);
- }
-
- /* do this until no more cardfile files to process */
- iCardFile = 0;
- while (++iCardFile < argc) {
-
- /* if cannot open cardfile, msg & exit */
- if ((hFile = fopen (argv[iCardFile], "r")) == NULL) {
- perror (argv[iCardFile]);
- exit (1);
- }
- fclose (hFile);
-
- /* reopen the file for 'read-binary' access */
- hFile = fopen (argv[iCardFile], "rb");
-
- /* read current cardfile file header into appropriate structure */
- iCheck = fread ((void *) &sFileHdr, sizeof (sFILEHDR), 1, hFile);
-
- /* if we read incorrect number of records, msg & exit */
- if (iCheck != 1) {
- perror ("Error reading file header");
- fclose (hFile);
- exit (1);
- }
-
- /* initialize current position in file to origin */
- lCurrPos = ftell (hFile);
-
- /* for current cardfile, go thru each card & display/print text */
- for (iCard = 1; iCard <= sFileHdr.iNumCrds; ++iCard) {
-
- /* go to file offset of previous card index info */
- fseek (hFile, lCurrPos, SEEK_SET);
-
- /* get current index line data */
- iCheck = fread (&sIndexHdr, sizeof (sINDEXHDR), 1, hFile);
-
- /* if we read incorrect number of records, msg & exit */
- if (iCheck != 1) {
- perror ("Error reading cardfile index text");
- fclose (hFile);
- exit (1);
- }
-
- /* note current file position for later */
- lCurrPos = ftell (hFile);
-
- /* go to file offset where this card is located */
- iCheck = fseek (hFile, sIndexHdr.lOffset, SEEK_SET);
-
- /* if fseek() did not return a 0, msg & exit */
- if (iCheck) {
- perror ("Error seeking card location in file");
- fclose (hFile);
- exit (1);
- }
-
- /* note start of this card for later */
- lTmpPos = ftell (hFile);
-
- /* assuming current card is text only, read first four bytes */
- iCheck = fread ((void *) &sTextOnly, sizeof (sTEXTONLY), 1, hFile);
-
- /********************** debugging stuff ************************/
- /* ******* uncomment if you want to see progress details *******/
- /*
- fprintf (stderr, "iCard=%x iCheck=%x iLenBMap=%x iLenText=%x\n",
- iCard, iCheck, sTextOnly.iLenBMap,
- sTextOnly.iLenText);
- getchar ();
- */
- /***************************************************************/
-
- /* if we read incorrect number of records, msg & exit */
- if (iCheck != 1) {
- perror ("Error reading first card body data bytes");
- fclose (hFile);
- exit (1);
- }
-
- /* if first two bytes are 0, then no bitmap */
- if (sTextOnly.iLenBMap == 0) {
-
- /* could still be a pure text-bearing card, so check */
- if (sTextOnly.iLenText != 0) {
-
- /* okay, there IS some card body text, so process it */
- if (sTextOnly.iLenText < TEXT_BUF) {
-
- /* read designated number of card body text chars */
- iCheck = fread (acText, 1, sTextOnly.iLenText, hFile);
-
- /* if read incorrect number of chars, msg & exit */
- if (iCheck != sTextOnly.iLenText) {
- perror ("Error reading card body text");
- fclose (hFile);
- exit (1);
- }
-
- /* write separate string to output */
- puts (acSep);
-
- /* write index line to output */
- puts (sIndexHdr.acIndexText);
-
- /* write card body text to output */
- fwrite (acText, 1, sTextOnly.iLenText, stdout);
- putchar ('\n');
- }
- else
- /* uh, oh... more than TEXT_BUF chars in card text */
- fputs ("**Error** Cardfile Text Too Long!\a\n", stderr);
- }
- }
- else {
- /* card contains bitmap of length sTextOnly.iLenBMap bytes */
-
- /* skip graphic by moving to end of bitmap data for this card */
- iCheck = fseek (hFile,
- (lTmpPos + (long) (10 + sTextOnly.iLenBMap)),
- SEEK_SET);
-
- /* if fseek() failed, msg & exit */
- if (iCheck) {
- perror ("Error moving to end of card bitmap data");
- fclose (hFile);
- exit (1);
- }
-
- /* back to card body text: read length of card text in bytes */
- iCheck = fread ((void *) &iTextLength, sizeof (int), 1, hFile);
-
- /************ debugging stuff ***************/
- /***** uncomment to see progress details ****/
- /*
- fprintf (stderr, "iCheck=%x iTextLength=%x\n",
- iCheck, iTextLength);
- getchar ();
- */
- /********************************************/
-
- /* if we had a problem reading text length, msg & exit */
- if (iCheck != 1) {
- perror ("Error reading in card body text length");
- fclose (hFile);
- exit (1);
- }
-
- /* check to see how many chars are in card body text */
- if (iTextLength != 0) {
-
- /* not a blank card, so do your stuff! */
- if (iTextLength < TEXT_BUF) {
-
- /* read designated number of card body text bytes */
- iCheck = fread (acText, 1, iTextLength, hFile);
-
- /* if read incorrect number of bytes, msg & exit */
- if (iCheck != iTextLength) {
- perror ("Error reading card body text");
- fclose (hFile);
- exit (1);
- }
-
- /* write separator string to output */
- puts (acSep);
-
- /* write index line to output */
- puts (sIndexHdr.acIndexText);
-
- /* write card body text to output */
- fwrite (acText, 1, iTextLength, stdout);
- putchar ('\n');
- }
- else
- /* card body text > TEXT_BUF chars in length */
- fputs ("**Error** Cardfile Text Too Long!\a\n", stderr);
- }
- }
- }
-
- /* write final separator string to output, & close current cardfile */
- puts (acSep);
- fclose (hFile);
- }
-
- /* we're outa here! */
- exit (0);
- }
-
-