home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / anwor032.zip / antiword.0.32 / misc.c < prev    next >
C/C++ Source or Header  |  2001-09-12  |  13KB  |  585 lines

  1. /*
  2.  * misc.c
  3.  * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
  4.  *
  5.  * Description:
  6.  * misc. functions
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <time.h>
  14. #if defined(__riscos)
  15. #include "kernel.h"
  16. #include "swis.h"
  17. #else
  18. #include <errno.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #if defined(__dos)
  22. #define S_ISDIR(x)    (((x) & S_IFMT) == S_IFDIR)
  23. #define S_ISREG(x)    (((x) & S_IFMT) == S_IFREG)
  24. #endif /* __dos */
  25. #endif /* __riscos */
  26. #include "antiword.h"
  27.  
  28. static BOOL    bWord6MacFile = FALSE;
  29.  
  30.  
  31. #if !defined(__riscos)
  32. /*
  33.  * szGetHomeDirectory - get the name of the home directory
  34.  */
  35. const char *
  36. szGetHomeDirectory(void)
  37. {
  38.     const char    *szHome;
  39.  
  40.     szHome = getenv("HOME");
  41.     if (szHome == NULL || szHome[0] == '\0') {
  42. #if defined(__dos)
  43.         szHome = "C:";
  44. #else
  45.         werr(0, "I can't find the name of your HOME directory");
  46.         szHome = "";
  47. #endif /* __dos */
  48.     }
  49.     return szHome;
  50. } /* end of szGetHomeDirectory */
  51. #endif /* !__riscos */
  52.  
  53. /*
  54.  * Get the size of the given file.
  55.  * Returns -1 if the file does not exist or is not a proper file.
  56.  */
  57. long
  58. lGetFilesize(const char *szFilename)
  59. {
  60. #if defined(__riscos)
  61.     _kernel_swi_regs    regs;
  62.     _kernel_oserror        *e;
  63.  
  64.     (void)memset(®s, 0, sizeof(regs));
  65.     regs.r[0] = 17;
  66.     regs.r[1] = (int)szFilename;
  67.     e = _kernel_swi(OS_File, ®s, ®s);
  68.     if (e != NULL) {
  69.         werr(0, "Get Filesize error %d: %s",
  70.             e->errnum, e->errmess);
  71.         return -1;
  72.     }
  73.     if (regs.r[0] != 1) {
  74.         /* It's not a proper file or the file does not exist */
  75.         return -1;
  76.     }
  77.     return (long)regs.r[4];
  78. #else
  79.     struct stat    tBuffer;
  80.  
  81.     if (stat(szFilename, &tBuffer) != 0) {
  82.         werr(0, "Get Filesize error %d", errno);
  83.         return -1;
  84.     }
  85.     if (!S_ISREG(tBuffer.st_mode)) {
  86.         /* It's not a regular file */
  87.         return -1;
  88.     }
  89.     return (long)tBuffer.st_size;
  90. #endif /* __riscos */
  91. } /* end of lGetFilesize */
  92.  
  93. #if defined(DEBUG)
  94. void
  95. vPrintBlock(const char    *szFile, int iLine,
  96.         const unsigned char *aucBlock, size_t tLength)
  97. {
  98.     int i, j;
  99.  
  100.     fail(szFile == NULL || iLine < 0 || aucBlock == NULL);
  101.  
  102.     fprintf(stderr, "%s[%3d]:\n", szFile, iLine);
  103.     for (i = 0; i < 32; i++) {
  104.         if (16 * i >= (int)tLength) {
  105.             return;
  106.         }
  107.         fprintf(stderr, "%03x: ", 16 * i);
  108.         for (j = 0; j < 16; j++) {
  109.             if (16 * i + j < (int)tLength) {
  110.                 fprintf(stderr, "%02x ", aucBlock[16 * i + j]);
  111.             }
  112.         }
  113.         fprintf(stderr, "\n");
  114.     }
  115. } /* end of vPrintBlock */
  116.  
  117. void
  118. vPrintUnicode(const char  *szFile, int iLine, const char *s)
  119. {
  120.     size_t    tLen;
  121.     char    *szASCII;
  122.  
  123.     tLen = unilen(s) / 2;
  124.     szASCII = xmalloc(tLen + 1);
  125.     (void)unincpy(szASCII, s, tLen);
  126.     szASCII[tLen] = '\0';
  127.     (void)fprintf(stderr, "%s[%3d]: %.240s\n", szFile, iLine, szASCII);
  128.     szASCII = xfree(szASCII);
  129. } /* end of vPrintUnicode */
  130.  
  131. BOOL
  132. bCheckDoubleLinkedList(output_type *pAnchor)
  133. {
  134.     output_type    *pCurr, *pLast;
  135.     int        iInList;
  136.  
  137.     pLast = pAnchor;
  138.     iInList = 0;
  139.     for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
  140.         pLast = pCurr;
  141.         iInList++;
  142.     }
  143.     NO_DBG_DEC(iInList);
  144.     for (pCurr = pLast; pCurr != NULL; pCurr = pCurr->pPrev) {
  145.         pLast = pCurr;
  146.         iInList--;
  147.     }
  148.     DBG_DEC_C(iInList != 0, iInList);
  149.     return pAnchor == pLast && iInList == 0;
  150. } /* end of bCheckDoubleLinkedList */
  151. #endif /* DEBUG */
  152.  
  153. /*
  154.  * bReadBytes
  155.  * This function reads the given number of bytes from the given file,
  156.  * starting from the given offset.
  157.  * Returns TRUE when successfull, otherwise FALSE
  158.  */
  159. BOOL
  160. bReadBytes(unsigned char *aucBytes, size_t tMemb, long lOffset, FILE *pFile)
  161. {
  162.     fail(aucBytes == NULL || pFile == NULL || lOffset < 0);
  163.  
  164.     if (fseek(pFile, lOffset, SEEK_SET) != 0) {
  165.         return FALSE;
  166.     }
  167.     if (fread(aucBytes, sizeof(unsigned char), tMemb, pFile) != tMemb) {
  168.         return FALSE;
  169.     }
  170.     return TRUE;
  171. } /* end of bReadBytes */
  172.  
  173. /*
  174.  * bReadBuffer
  175.  * This function fills the given buffer with the given number of bytes,
  176.  * starting at the given offset within the Big/Small Block Depot.
  177.  *
  178.  * Returns TRUE when successful, otherwise FALSE
  179.  */
  180. BOOL
  181. bReadBuffer(FILE *pFile, long lStartBlock,
  182.     const long *alBlockDepot, size_t tBlockDepotLen, size_t tBlockSize,
  183.     unsigned char *aucBuffer, long lOffset, size_t tToRead)
  184. {
  185.     long    lBegin, lIndex;
  186.     size_t    tLen;
  187.  
  188.     fail(pFile == NULL);
  189.     fail(lStartBlock < 0);
  190.     fail(alBlockDepot == NULL);
  191.     fail(tBlockSize != BIG_BLOCK_SIZE && tBlockSize != SMALL_BLOCK_SIZE);
  192.     fail(aucBuffer == NULL);
  193.     fail(tToRead == 0);
  194.  
  195.     for (lIndex = lStartBlock;
  196.          lIndex != END_OF_CHAIN && tToRead != 0;
  197.          lIndex = alBlockDepot[lIndex]) {
  198.         if (lIndex < 0 || lIndex >= (long)tBlockDepotLen) {
  199.             if (tBlockSize >= BIG_BLOCK_SIZE) {
  200.                 werr(1, "The Big Block Depot is corrupt");
  201.             } else {
  202.                 werr(1, "The Small Block Depot is corrupt");
  203.             }
  204.         }
  205.         if (lOffset >= (long)tBlockSize) {
  206.             lOffset -= (long)tBlockSize;
  207.             continue;
  208.         }
  209.         lBegin = lDepotOffset(lIndex, tBlockSize) + lOffset;
  210.         tLen = min(tBlockSize - (size_t)lOffset, tToRead);
  211.         lOffset = 0;
  212.         if (!bReadBytes(aucBuffer, tLen, lBegin, pFile)) {
  213.             werr(0, "Read big block %ld not possible", lBegin);
  214.             return FALSE;
  215.         }
  216.         aucBuffer += tLen;
  217.         tToRead -= tLen;
  218.     }
  219.     DBG_DEC_C(tToRead != 0, tToRead);
  220.     return tToRead == 0;
  221. } /* end of bReadBuffer */
  222.  
  223. /*
  224.  * Translate a Word colornumber into a true color for use in a drawfile
  225.  *
  226.  * Returns the true color
  227.  */
  228. unsigned int
  229. uiColor2Color(int iWordColor)
  230. {
  231.     static const unsigned int    auiColorTable[] = {
  232.         /*  0 */    0x00000000U,    /* Automatic */
  233.         /*  1 */    0x00000000U,    /* Black */
  234.         /*  2 */    0xff000000U,    /* Blue */
  235.         /*  3 */    0xffff0000U,    /* Turquoise */
  236.         /*  4 */    0x00ff0000U,    /* Bright Green */
  237.         /*  5 */    0xff00ff00U,    /* Pink */
  238.         /*  6 */    0x0000ff00U,    /* Red */
  239.         /*  7 */    0x00ffff00U,    /* Yellow */
  240.         /*  8 */    0xffffff00U,    /* White */
  241.         /*  9 */    0x80000000U,    /* Dark Blue */
  242.         /* 10 */    0x80800000U,    /* Teal */
  243.         /* 11 */    0x00800000U,    /* Green */
  244.         /* 12 */    0x80008000U,    /* Violet */
  245.         /* 13 */    0x00008000U,    /* Dark Red */
  246.         /* 14 */    0x00808000U,    /* Dark Yellow */
  247.         /* 15 */    0x80808000U,    /* Gray 50% */
  248.         /* 16 */    0xc0c0c000U,    /* Gray 25% */
  249.     };
  250.     if (iWordColor < 0 ||
  251.         iWordColor >= (int)elementsof(auiColorTable)) {
  252.         return auiColorTable[0];
  253.     }
  254.     return auiColorTable[iWordColor];
  255. } /* end of uiColor2Color */
  256.  
  257. /*
  258.  * iFindSplit - find a place to split the string
  259.  *
  260.  * returns the index of the split character or -1 if no split found.
  261.  */
  262. static int
  263. iFindSplit(const char *szString, int iStringLen)
  264. {
  265.     int    iSplit;
  266.  
  267.     iSplit = iStringLen - 1;
  268.     while (iSplit >= 1) {
  269.         if (szString[iSplit] == ' ' ||
  270.             (szString[iSplit] == '-' && szString[iSplit - 1] != ' ')) {
  271.             return iSplit;
  272.         }
  273.         iSplit--;
  274.     }
  275.     return -1;
  276. } /* end of iFindSplit */
  277.  
  278. /*
  279.  * pSplitList - split the given list in a printable part and a leftover part
  280.  *
  281.  * returns the pointer to the leftover part
  282.  */
  283. output_type *
  284. pSplitList(output_type *pAnchor)
  285. {
  286.     output_type    *pCurr, *pLeftOver;
  287.     int        iIndex;
  288.  
  289.      fail(pAnchor == NULL);
  290.  
  291.     for (pCurr = pAnchor; pCurr->pNext != NULL; pCurr = pCurr->pNext)
  292.         ;    /* EMPTY */
  293.     iIndex = -1;
  294.     for (; pCurr != NULL; pCurr = pCurr->pPrev) {
  295.         iIndex = iFindSplit(pCurr->szStorage, pCurr->iNextFree);
  296.         if (iIndex >= 0) {
  297.             break;
  298.         }
  299.     }
  300.  
  301.     if (pCurr == NULL || iIndex < 0) {
  302.         /* No split, no leftover */
  303.         return NULL;
  304.     }
  305.     /* Split over the iIndex-th character */
  306.     NO_DBG_MSG("pLeftOver");
  307.     pLeftOver = xmalloc(sizeof(*pLeftOver));
  308.     pLeftOver->tStorageSize = (size_t)(pCurr->iNextFree - iIndex);
  309.     pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize);
  310.     pLeftOver->iNextFree = pCurr->iNextFree - iIndex - 1;
  311.     (void)strncpy(pLeftOver->szStorage,
  312.         pCurr->szStorage + iIndex + 1, (size_t)pLeftOver->iNextFree);
  313.     pLeftOver->szStorage[pLeftOver->iNextFree] = '\0';
  314.     NO_DBG_MSG(pLeftOver->szStorage);
  315.     pLeftOver->iColor = pCurr->iColor;
  316.     pLeftOver->ucFontstyle = pCurr->ucFontstyle;
  317.     pLeftOver->tFontRef = pCurr->tFontRef;
  318.     pLeftOver->sFontsize = pCurr->sFontsize;
  319.     pLeftOver->lStringWidth = lComputeStringWidth(
  320.                     pLeftOver->szStorage,
  321.                     pLeftOver->iNextFree,
  322.                     pLeftOver->tFontRef,
  323.                     pLeftOver->sFontsize);
  324.     pLeftOver->pPrev = NULL;
  325.     pLeftOver->pNext = pCurr->pNext;
  326.     if (pLeftOver->pNext != NULL) {
  327.         pLeftOver->pNext->pPrev = pLeftOver;
  328.     }
  329.     fail(!bCheckDoubleLinkedList(pLeftOver));
  330.  
  331.     NO_DBG_MSG("pAnchor");
  332.     NO_DBG_HEX(pCurr->szStorage[iIndex]);
  333.     while (iIndex >= 0 && isspace(pCurr->szStorage[iIndex])) {
  334.         iIndex--;
  335.     }
  336.     pCurr->iNextFree = iIndex + 1;
  337.     pCurr->szStorage[pCurr->iNextFree] = '\0';
  338.     NO_DBG_MSG(pCurr->szStorage);
  339.     pCurr->lStringWidth = lComputeStringWidth(
  340.                     pCurr->szStorage,
  341.                     pCurr->iNextFree,
  342.                     pCurr->tFontRef,
  343.                     pCurr->sFontsize);
  344.     pCurr->pNext = NULL;
  345.     fail(!bCheckDoubleLinkedList(pAnchor));
  346.  
  347.     return pLeftOver;
  348. } /* end of pSplitList */
  349.  
  350. /*
  351.  * iInteger2Roman - convert an integer to Roman Numerals
  352.  *
  353.  * returns the number of characters written
  354.  */
  355. int
  356. iInteger2Roman(int iNumber, BOOL bUpperCase, char *szOutput)
  357. {
  358.     char *outp, *p, *q;
  359.     int iNextVal, iValue;
  360.  
  361.     fail(szOutput == NULL);
  362.  
  363.     if (iNumber <= 0 || iNumber >= 4000) {
  364.         szOutput[0] = '\0';
  365.         return 0;
  366.     }
  367.  
  368.     outp = szOutput;
  369.     p = bUpperCase ? "M\2D\5C\2L\5X\2V\5I" : "m\2d\5c\2l\5x\2v\5i";
  370.     iValue = 1000;
  371.     for (;;) {
  372.         while (iNumber >= iValue) {
  373.             *outp++ = *p;
  374.             iNumber -= iValue;
  375.         }
  376.         if (iNumber <= 0) {
  377.             *outp = '\0';
  378.             return outp - szOutput;
  379.         }
  380.         q = p + 1;
  381.         iNextVal = iValue / (int)*q;
  382.         if ((int)*q == 2) {        /* magic */
  383.             iNextVal /= (int)*(q += 2);
  384.         }
  385.         if (iNumber + iNextVal >= iValue) {
  386.             *outp++ = *++q;
  387.             iNumber += iNextVal;
  388.         } else {
  389.             p++;
  390.             iValue /= (int)(*p++);
  391.         }
  392.     }
  393. } /* end of iInteger2Roman */
  394.  
  395. /*
  396.  * iInteger2Alpha - convert an integer to Alphabetic "numbers"
  397.  *
  398.  * returns the number of characters written
  399.  */
  400. int
  401. iInteger2Alpha(int iNumber, BOOL bUpperCase, char *szOutput)
  402. {
  403.     char    *outp;
  404.     int    iTmp;
  405.  
  406.     fail(szOutput == NULL);
  407.  
  408.     outp = szOutput;
  409.     iTmp = bUpperCase ? 'A': 'a';
  410.     if (iNumber <= 26) {
  411.         iNumber -= 1;
  412.         *outp++ = (char)(iTmp + iNumber);
  413.     } else if (iNumber <= 26 + 26*26) {
  414.         iNumber -= 26 + 1;
  415.         *outp++ = (char)(iTmp + iNumber / 26);
  416.         *outp++ = (char)(iTmp + iNumber % 26);
  417.     } else if (iNumber <= 26 + 26*26 + 26*26*26) {
  418.         iNumber -= 26 + 26*26 + 1;
  419.         *outp++ = (char)(iTmp + iNumber / (26*26));
  420.         *outp++ = (char)(iTmp + iNumber / 26 % 26);
  421.         *outp++ = (char)(iTmp + iNumber % 26);
  422.     }
  423.     *outp = '\0';
  424.     return outp - szOutput;
  425. } /* end of iInteger2Alpha */
  426.  
  427. /*
  428.  * unincpy - copy a counted Unicode string to an single-byte string
  429.  */
  430. char *
  431. unincpy(char *s1, const char *s2, size_t n)
  432. {
  433.     char        *dest;
  434.     unsigned long    ulChar;
  435.     size_t        len;
  436.     unsigned short    usUni;
  437.  
  438.     for (dest = s1, len = 0; len < n; dest++, len++) {
  439.         usUni = usGetWord(len * 2, s2);
  440.         if (usUni == 0) {
  441.             break;
  442.         }
  443.         ulChar = ulTranslateCharacters(usUni, 0, FALSE, FALSE);
  444.         if (ulChar == IGNORE_CHARACTER) {
  445.             ulChar = (unsigned long)'?';
  446.         }
  447.         *dest = (char)ulChar;
  448.     }
  449.     for (; len < n; len++) {
  450.         *dest++ = '\0';
  451.     }
  452.     return s1;
  453. } /* end of unincpy */
  454.  
  455. /*
  456.  * unilen - calculate the length of a Unicode string
  457.  */
  458. size_t
  459. unilen(const char *s)
  460. {
  461.     size_t        tLen;
  462.     unsigned short    usUni;
  463.  
  464.     tLen = 0;
  465.     for (;;) {
  466.         usUni = usGetWord(tLen * 2, s);
  467.         if (usUni == 0) {
  468.             return tLen;
  469.         }
  470.         tLen += 2;
  471.     }
  472. } /* end of unilen */
  473.  
  474. /*
  475.  * szBaseName - get the basename of the given filename
  476.  */
  477. const char *
  478. szBasename(const char *szFilename)
  479. {
  480.     const char    *szTmp;
  481.  
  482.     fail(szFilename == NULL);
  483.  
  484.     if (szFilename == NULL || szFilename[0] == '\0') {
  485.         return "null";
  486.     }
  487.  
  488.     szTmp = strrchr(szFilename, FILE_SEPARATOR[0]);
  489.     if (szTmp == NULL) {
  490.         return szFilename;
  491.     }
  492.     return ++szTmp;
  493. } /* end of szBasename */
  494.  
  495. /*
  496.  * iGetVersionNumber - get the Word version number from the header
  497.  *
  498.  * Returns the version number or -1 when unknown
  499.  */
  500. int
  501. iGetVersionNumber(const unsigned char *aucHeader)
  502. {
  503.     unsigned short  usFib, usChse;
  504.  
  505.     usFib = usGetWord(0x02, aucHeader);
  506.     DBG_DEC(usFib);
  507.     if (usFib < 101) {
  508.         /* This file is from a version of Word older than Word 6 */
  509.         return -1;
  510.     }
  511.     usChse = usGetWord(0x14, aucHeader);
  512.     DBG_DEC(usChse);
  513.     bWord6MacFile = FALSE;
  514.     switch (usFib) {
  515.     case 101:
  516.     case 102:
  517.         DBG_MSG("Word 6 for Windows");
  518.         return 6;
  519.     case 103:
  520.     case 104:
  521.         switch (usChse) {
  522.         case 0:
  523.             DBG_MSG("Word 7 for Win95");
  524.             return 7;
  525.         case 256:
  526.             DBG_MSG("Word 6 for Macintosh");
  527.             bWord6MacFile = TRUE;
  528.             return 6;
  529.         default:
  530.             DBG_FIXME();
  531.             if (ucGetByte(0x05, aucHeader) == 0xe0) {
  532.                 DBG_MSG("Word 7 for Win95");
  533.                 return 7;
  534.             }
  535.             DBG_MSG("Word 6 for Macintosh");
  536.             bWord6MacFile = TRUE;
  537.             return 6;
  538.         }
  539.     default: 
  540.         DBG_MSG_C(usChse != 256, "Word97 for Win95/98/NT");
  541.         DBG_MSG_C(usChse == 256, "Word98 for Macintosh");
  542.         return 8;
  543.     }
  544. } /* end of iGetVersionNumber */
  545.  
  546. /*
  547.  * TRUE if the current file was made by Word 6 on an Apple Macintosh,
  548.  * otherwise FALSE.
  549.  * This function hides the methode of how to find out from the rest of the
  550.  * program.
  551.  */
  552. BOOL
  553. bIsWord6MacFile(void)
  554. {
  555.     return bWord6MacFile;
  556. } /* end of bIsWord6MacFile */
  557.  
  558. /*
  559.  * lComputeLeading - compute the leading
  560.  *
  561.  * NOTE: the fontsize is given in half points
  562.  *
  563.  * Returns the leading in drawunits
  564.  */
  565. long
  566. lComputeLeading(int iFontsize)
  567. {
  568.     long    lLeading;
  569.  
  570.     lLeading = iFontsize * 500L;
  571.     if (iFontsize < 18) {        /* Small text: 112% */
  572.         lLeading *= 112;
  573.     } else if (iFontsize < 28) {    /* Normal text: 124% */
  574.         lLeading *= 124;
  575.     } else if (iFontsize < 48) {    /* Small headlines: 104% */
  576.         lLeading *= 104;
  577.     } else {            /* Large headlines: 100% */
  578.         lLeading *= 100;
  579.     }
  580.     lLeading = lMilliPoints2DrawUnits(lLeading);
  581.     lLeading += 50;
  582.     lLeading /= 100;
  583.     return lLeading;
  584. } /* end of lComputeLeading */
  585.