/* * Crd2txt -- convert Windows card files to text files * * 1997,2000,2002 Hannu.Aronsson@iki.fi * * File format looks basically like this (see code for details). This * Interpretation has been tested on card files of up to about 1100 * cards and 97k of data total. * * Header: Contains magic number (3 bytes) and number of cards. * * Title records: number of card times from offset 11 are 52-byte * records with rest-of-text offset in 2 shorts (within-page * address and page number) and the title text (terminated by NULL). * * Rest of text records: At indicated offset, there is a text length * short and then the text, with CRLF as line separator. * * Character set in all strings is Windows, i.e. about Latin1 8859-1 * * Updates: * 02/2002: Some cardfile files are packed tighter, relaxed check. * 02/2002: Some cardfile files do not hame magic number "MGC"? */ #include #include #include #ifdef TURBO_C #include #else #include #endif #include void seeknread(int f, unsigned long where, unsigned char *buf, unsigned long len) { unsigned long r; r = lseek(f, where, SEEK_SET); if (!(r==where)) printf("seek r=%lu where=%lu\n", r, where); assert(r == where); r = read(f, buf, len); if (!(r==len)) printf("read r=%lu len=%lu\n", r, len); assert(r == len); } unsigned short readshort(int f, unsigned long where) { unsigned char buf[2]; seeknread(f, where, buf, 2); return buf[0] + buf[1]*256; /* Windoze is big endian */ } #define MAXTEXT 2048 main(int ac, char **av) { unsigned char buf[MAXTEXT]; int f; int ncards, i, textlen, last; unsigned long rec, textloc, filelen, loc; if (ac < 2) { printf("Usage: crd2html file.crd > output.htm\n"); printf("(c) 1997,2000,2002 http://www.ihaa.com/english/crd2html.html\n"); exit(0); } f = open(av[1], O_RDONLY #ifdef TURBO_C | O_BINARY #endif ); assert(f >= 0); filelen = lseek(f, 0, SEEK_END); assert(filelen > 8); seeknread(f, 0, buf, 3); /* Too strict? assert(!strncmp(buf, "MGC", 3)); */ if (strncmp(buf, "MGC", 3)) { printf("\n"); } ncards = readshort(f, 3); assert(ncards >= 0 && ncards <= 4096); printf("\n", av[1], ncards); printf("
    \n"); for (rec = 0; rec < ncards; rec++) { loc = 11 + rec*52; textloc = readshort(f, loc); /* This is address within 64K */ textloc += readshort(f, loc+2) * 65536; /* This is "page" number */ assert(textloc >= 57 && textloc < filelen); seeknread(f, loc+5, buf, 52-5); /* printf("\n", rec+1, ncards); */ printf("
  • %s
    \n", buf); textlen = readshort(f, textloc + 2); assert(textlen >= 0 && textlen < filelen - textloc && textlen < MAXTEXT); seeknread(f, textloc + 4, buf, textlen); buf[textlen] = '\0'; last = '\n'; /* Text har CRLF line endings */ for (i=0; i< textlen; i++) switch(buf[i]) { case '\n': if (last != '\n') /* Print only one of consecutive LFs */ printf("
    \n"); last = '\n'; break; case '\r': /* Ignore, no change to last */ break; default: putchar(buf[i]); last = buf[i]; } printf("\n", buf); } printf("
\n"); printf("\n\n"); close(f); return 0; } /* EOF */