summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/antiword/misc.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/antiword/misc.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/antiword/misc.c')
-rwxr-xr-xsys/src/cmd/aux/antiword/misc.c894
1 files changed, 894 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/antiword/misc.c b/sys/src/cmd/aux/antiword/misc.c
new file mode 100755
index 000000000..609a2f02f
--- /dev/null
+++ b/sys/src/cmd/aux/antiword/misc.c
@@ -0,0 +1,894 @@
+/*
+ * misc.c
+ * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
+ *
+ * Description:
+ * Miscellaneous functions
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#if defined(__riscos)
+#include "DeskLib:SWI.h"
+#else
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif /* __riscos */
+#if !defined(S_ISREG)
+#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
+#endif /* !S_ISREG */
+#include "antiword.h"
+#if defined(__vms)
+#include <unixlib.h>
+#endif
+
+#if !defined(__riscos)
+/*
+ * szGetHomeDirectory - get the name of the home directory
+ */
+const char *
+szGetHomeDirectory(void)
+{
+ const char *szHome;
+
+#if defined(__vms)
+ szHome = decc$translate_vms(getenv("HOME"));
+#elif defined(__Plan9__)
+ szHome = getenv("home");
+#else
+ szHome = getenv("HOME");
+#endif /* __vms */
+
+ if (szHome == NULL || szHome[0] == '\0') {
+#if defined(N_PLAT_NLM)
+ szHome = "SYS:";
+#elif defined(__dos)
+ szHome = "C:";
+#else
+ werr(0, "I can't find the name of your HOME directory");
+ szHome = "";
+#endif /* __dos */
+ }
+ return szHome;
+} /* end of szGetHomeDirectory */
+
+/*
+ * szGetAntiwordDirectory - get the name of the Antiword directory
+ */
+const char *
+szGetAntiwordDirectory(void)
+{
+#if defined(__vms)
+ return decc$translate_vms(getenv("ANTIWORDHOME"));
+#else
+ return getenv("ANTIWORDHOME");
+#endif /* __vms */
+} /* end of szGetAntiwordDirectory */
+#endif /* !__riscos */
+
+/*
+ * Get the size of the specified file.
+ * Returns -1 if the file does not exist or is not a proper file.
+ */
+long
+lGetFilesize(const char *szFilename)
+{
+#if defined(__riscos)
+ os_error *e;
+ int iType, iSize;
+
+ e = SWI(2, 5, SWI_OS_File | XOS_Bit,
+ 17, szFilename,
+ &iType, NULL, NULL, NULL, &iSize);
+ if (e != NULL) {
+ werr(0, "Get Filesize error %d: %s",
+ e->errnum, e->errmess);
+ return -1;
+ }
+ if (iType != 1) {
+ /* It's not a proper file or the file does not exist */
+ return -1;
+ }
+ return (long)iSize;
+#else
+ struct stat tBuffer;
+
+ errno = 0;
+ if (stat(szFilename, &tBuffer) != 0) {
+ werr(0, "Get Filesize error %d", errno);
+ return -1;
+ }
+ if (!S_ISREG(tBuffer.st_mode)) {
+ /* It's not a regular file */
+ return -1;
+ }
+ return (long)tBuffer.st_size;
+#endif /* __riscos */
+} /* end of lGetFilesize */
+
+#if defined(DEBUG)
+void
+vPrintBlock(const char *szFile, int iLine,
+ const UCHAR *aucBlock, size_t tLength)
+{
+ int i, j;
+
+ fail(szFile == NULL || iLine < 0 || aucBlock == NULL);
+
+ fprintf(stderr, "%s[%3d]:\n", szFile, iLine);
+ for (i = 0; i < 32; i++) {
+ if (16 * i >= (int)tLength) {
+ return;
+ }
+ fprintf(stderr, "%03x: ", (unsigned int)(16 * i));
+ for (j = 0; j < 16; j++) {
+ if (16 * i + j < (int)tLength) {
+ fprintf(stderr, "%02x ",
+ (unsigned int)aucBlock[16 * i + j]);
+ }
+ }
+ fprintf(stderr, "\n");
+ }
+} /* end of vPrintBlock */
+
+void
+vPrintUnicode(const char *szFile, int iLine, const UCHAR *aucUni, size_t tLen)
+{
+ char *szASCII;
+
+ fail(tLen % 2 != 0);
+
+ tLen /= 2; /* Length in bytes to length in characters */
+ szASCII = xmalloc(tLen + 1);
+ (void)unincpy(szASCII, aucUni, tLen);
+ szASCII[tLen] = '\0';
+ (void)fprintf(stderr, "%s[%3d]: %.*s\n",
+ szFile, iLine, (int)tLen, szASCII);
+ szASCII = xfree(szASCII);
+} /* end of vPrintUnicode */
+
+BOOL
+bCheckDoubleLinkedList(output_type *pAnchor)
+{
+ output_type *pCurr, *pLast;
+ int iInList;
+
+ pLast = pAnchor;
+ iInList = 0;
+ for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
+ pLast = pCurr;
+ iInList++;
+ }
+ NO_DBG_DEC(iInList);
+ for (pCurr = pLast; pCurr != NULL; pCurr = pCurr->pPrev) {
+ pLast = pCurr;
+ iInList--;
+ }
+ DBG_DEC_C(iInList != 0, iInList);
+ return pAnchor == pLast && iInList == 0;
+} /* end of bCheckDoubleLinkedList */
+#endif /* DEBUG */
+
+/*
+ * bReadBytes
+ * This function reads the specified number of bytes from the specified file,
+ * starting from the specified offset.
+ * Returns TRUE when successfull, otherwise FALSE
+ */
+BOOL
+bReadBytes(UCHAR *aucBytes, size_t tMemb, ULONG ulOffset, FILE *pFile)
+{
+ fail(aucBytes == NULL || pFile == NULL || ulOffset > (ULONG)LONG_MAX);
+
+ if (ulOffset > (ULONG)LONG_MAX) {
+ return FALSE;
+ }
+ if (fseek(pFile, (long)ulOffset, SEEK_SET) != 0) {
+ return FALSE;
+ }
+ if (fread(aucBytes, sizeof(UCHAR), tMemb, pFile) != tMemb) {
+ return FALSE;
+ }
+ return TRUE;
+} /* end of bReadBytes */
+
+/*
+ * bReadBuffer
+ * This function fills the specified buffer with the specified number of bytes,
+ * starting at the specified offset within the Big/Small Block Depot.
+ *
+ * Returns TRUE when successful, otherwise FALSE
+ */
+BOOL
+bReadBuffer(FILE *pFile, ULONG ulStartBlock,
+ const ULONG *aulBlockDepot, size_t tBlockDepotLen, size_t tBlockSize,
+ UCHAR *aucBuffer, ULONG ulOffset, size_t tToRead)
+{
+ ULONG ulBegin, ulIndex;
+ size_t tLen;
+
+ fail(pFile == NULL);
+ fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
+ fail(aulBlockDepot == NULL);
+ fail(tBlockSize != BIG_BLOCK_SIZE && tBlockSize != SMALL_BLOCK_SIZE);
+ fail(aucBuffer == NULL);
+ fail(tToRead == 0);
+
+ for (ulIndex = ulStartBlock;
+ ulIndex != END_OF_CHAIN && tToRead != 0;
+ ulIndex = aulBlockDepot[ulIndex]) {
+ if (ulIndex >= (ULONG)tBlockDepotLen) {
+ DBG_DEC(ulIndex);
+ DBG_DEC(tBlockDepotLen);
+ if (tBlockSize >= BIG_BLOCK_SIZE) {
+ werr(1, "The Big Block Depot is damaged");
+ } else {
+ werr(1, "The Small Block Depot is damaged");
+ }
+ }
+ if (ulOffset >= (ULONG)tBlockSize) {
+ ulOffset -= tBlockSize;
+ continue;
+ }
+ ulBegin = ulDepotOffset(ulIndex, tBlockSize) + ulOffset;
+ tLen = min(tBlockSize - (size_t)ulOffset, tToRead);
+ ulOffset = 0;
+ if (!bReadBytes(aucBuffer, tLen, ulBegin, pFile)) {
+ werr(0, "Read big block 0x%lx not possible", ulBegin);
+ return FALSE;
+ }
+ aucBuffer += tLen;
+ tToRead -= tLen;
+ }
+ DBG_DEC_C(tToRead != 0, tToRead);
+ return tToRead == 0;
+} /* end of bReadBuffer */
+
+/*
+ * Convert a Word colornumber into a true color for use in a drawfile
+ *
+ * Returns the true color
+ */
+ULONG
+ulColor2Color(UCHAR ucFontColor)
+{
+ static const ULONG aulColorTable[] = {
+ /* 0 */ 0x00000000UL, /* Automatic */
+ /* 1 */ 0x00000000UL, /* Black */
+ /* 2 */ 0xff000000UL, /* Blue */
+ /* 3 */ 0xffff0000UL, /* Turquoise */
+ /* 4 */ 0x00ff0000UL, /* Bright Green */
+ /* 5 */ 0xff00ff00UL, /* Pink */
+ /* 6 */ 0x0000ff00UL, /* Red */
+ /* 7 */ 0x00ffff00UL, /* Yellow */
+ /* 8 */ 0xffffff00UL, /* White */
+ /* 9 */ 0x80000000UL, /* Dark Blue */
+ /* 10 */ 0x80800000UL, /* Teal */
+ /* 11 */ 0x00800000UL, /* Green */
+ /* 12 */ 0x80008000UL, /* Violet */
+ /* 13 */ 0x00008000UL, /* Dark Red */
+ /* 14 */ 0x00808000UL, /* Dark Yellow */
+ /* 15 */ 0x80808000UL, /* Gray 50% */
+ /* 16 */ 0xc0c0c000UL, /* Gray 25% */
+ };
+ if ((size_t)ucFontColor >= elementsof(aulColorTable)) {
+ return aulColorTable[0];
+ }
+ return aulColorTable[(int)ucFontColor];
+} /* end of ulColor2Color */
+
+/*
+ * iFindSplit - find a place to split the string
+ *
+ * returns the index of the split character or -1 if no split found.
+ */
+static int
+iFindSplit(const char *szString, size_t tStringLen)
+{
+ size_t tSplit;
+
+ if (tStringLen == 0) {
+ return -1;
+ }
+ tSplit = tStringLen - 1;
+ while (tSplit >= 1) {
+ if (szString[tSplit] == ' ' ||
+ (szString[tSplit] == '-' && szString[tSplit - 1] != ' ')) {
+ return (int)tSplit;
+ }
+ tSplit--;
+ }
+ return -1;
+} /* end of iFindSplit */
+
+/*
+ * pSplitList - split the specified list in a printable part and a leftover part
+ *
+ * returns the pointer to the leftover part
+ */
+output_type *
+pSplitList(output_type *pAnchor)
+{
+ output_type *pCurr, *pLeftOver;
+ int iIndex;
+
+ fail(pAnchor == NULL);
+
+ for (pCurr = pAnchor; pCurr->pNext != NULL; pCurr = pCurr->pNext)
+ ; /* EMPTY */
+ iIndex = -1;
+ for (; pCurr != NULL; pCurr = pCurr->pPrev) {
+ iIndex = iFindSplit(pCurr->szStorage, pCurr->tNextFree);
+ if (iIndex >= 0) {
+ break;
+ }
+ }
+
+ if (pCurr == NULL || iIndex < 0) {
+ /* No split, no leftover */
+ return NULL;
+ }
+ /* Split over the iIndex-th character */
+ NO_DBG_MSG("pLeftOver");
+ pLeftOver = xmalloc(sizeof(*pLeftOver));
+ fail(pCurr->tNextFree < (size_t)iIndex);
+ pLeftOver->tStorageSize = pCurr->tNextFree - (size_t)iIndex;
+ pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize);
+ pLeftOver->tNextFree = pCurr->tNextFree - (size_t)iIndex - 1;
+ (void)strncpy(pLeftOver->szStorage,
+ pCurr->szStorage + iIndex + 1, pLeftOver->tNextFree);
+ pLeftOver->szStorage[pLeftOver->tNextFree] = '\0';
+ NO_DBG_MSG(pLeftOver->szStorage);
+ pLeftOver->ucFontColor = pCurr->ucFontColor;
+ pLeftOver->usFontStyle = pCurr->usFontStyle;
+ pLeftOver->tFontRef = pCurr->tFontRef;
+ pLeftOver->usFontSize = pCurr->usFontSize;
+ pLeftOver->lStringWidth = lComputeStringWidth(
+ pLeftOver->szStorage,
+ pLeftOver->tNextFree,
+ pLeftOver->tFontRef,
+ pLeftOver->usFontSize);
+ pLeftOver->pPrev = NULL;
+ pLeftOver->pNext = pCurr->pNext;
+ if (pLeftOver->pNext != NULL) {
+ pLeftOver->pNext->pPrev = pLeftOver;
+ }
+ fail(!bCheckDoubleLinkedList(pLeftOver));
+
+ NO_DBG_MSG("pAnchor");
+ NO_DBG_HEX(pCurr->szStorage[iIndex]);
+ while (iIndex >= 0 && isspace((int)(UCHAR)pCurr->szStorage[iIndex])) {
+ iIndex--;
+ }
+ pCurr->tNextFree = (size_t)iIndex + 1;
+ pCurr->szStorage[pCurr->tNextFree] = '\0';
+ NO_DBG_MSG(pCurr->szStorage);
+ pCurr->lStringWidth = lComputeStringWidth(
+ pCurr->szStorage,
+ pCurr->tNextFree,
+ pCurr->tFontRef,
+ pCurr->usFontSize);
+ pCurr->pNext = NULL;
+ fail(!bCheckDoubleLinkedList(pAnchor));
+
+ return pLeftOver;
+} /* end of pSplitList */
+
+/*
+ * tNumber2Roman - convert a number to Roman Numerals
+ *
+ * returns the number of characters written
+ */
+size_t
+tNumber2Roman(UINT uiNumber, BOOL bUpperCase, char *szOutput)
+{
+ char *outp, *p, *q;
+ UINT uiNextVal, uiValue;
+
+ fail(szOutput == NULL);
+
+ uiNumber %= 4000; /* Very high numbers can't be represented */
+ if (uiNumber == 0) {
+ szOutput[0] = '\0';
+ return 0;
+ }
+
+ outp = szOutput;
+ p = bUpperCase ? "M\2D\5C\2L\5X\2V\5I" : "m\2d\5c\2l\5x\2v\5i";
+ uiValue = 1000;
+ for (;;) {
+ while (uiNumber >= uiValue) {
+ *outp++ = *p;
+ uiNumber -= uiValue;
+ }
+ if (uiNumber == 0) {
+ *outp = '\0';
+ fail(outp < szOutput);
+ return (size_t)(outp - szOutput);
+ }
+ q = p + 1;
+ uiNextVal = uiValue / (UINT)(UCHAR)*q;
+ if ((int)*q == 2) { /* magic */
+ uiNextVal /= (UINT)(UCHAR)*(q += 2);
+ }
+ if (uiNumber + uiNextVal >= uiValue) {
+ *outp++ = *++q;
+ uiNumber += uiNextVal;
+ } else {
+ p++;
+ uiValue /= (UINT)(UCHAR)(*p++);
+ }
+ }
+} /* end of tNumber2Roman */
+
+/*
+ * iNumber2Alpha - convert a number to alphabetic "numbers"
+ *
+ * returns the number of characters written
+ */
+size_t
+tNumber2Alpha(UINT uiNumber, BOOL bUpperCase, char *szOutput)
+{
+ char *outp;
+ UINT uiTmp;
+
+ fail(szOutput == NULL);
+
+ if (uiNumber == 0) {
+ szOutput[0] = '\0';
+ return 0;
+ }
+
+ outp = szOutput;
+ uiTmp = (UINT)(bUpperCase ? 'A': 'a');
+ if (uiNumber <= 26) {
+ uiNumber -= 1;
+ *outp++ = (char)(uiTmp + uiNumber);
+ } else if (uiNumber <= 26U + 26U*26U) {
+ uiNumber -= 26 + 1;
+ *outp++ = (char)(uiTmp + uiNumber / 26);
+ *outp++ = (char)(uiTmp + uiNumber % 26);
+ } else if (uiNumber <= 26U + 26U*26U + 26U*26U*26U) {
+ uiNumber -= 26 + 26*26 + 1;
+ *outp++ = (char)(uiTmp + uiNumber / (26*26));
+ *outp++ = (char)(uiTmp + uiNumber / 26 % 26);
+ *outp++ = (char)(uiTmp + uiNumber % 26);
+ }
+ *outp = '\0';
+ fail(outp < szOutput);
+ return (size_t)(outp - szOutput);
+} /* end of tNumber2Alpha */
+
+/*
+ * unincpy - copy a counted Unicode string to an single-byte string
+ */
+char *
+unincpy(char *s1, const UCHAR *s2, size_t n)
+{
+ char *pcDest;
+ ULONG ulChar;
+ size_t tLen;
+ USHORT usUni;
+
+ for (pcDest = s1, tLen = 0; tLen < n; pcDest++, tLen++) {
+ usUni = usGetWord(tLen * 2, s2);
+ if (usUni == 0) {
+ break;
+ }
+ ulChar = ulTranslateCharacters(usUni, 0, 8,
+ conversion_unknown, encoding_neutral, FALSE);
+ if (ulChar == IGNORE_CHARACTER) {
+ ulChar = (ULONG)'?';
+ }
+ *pcDest = (char)ulChar;
+ }
+ for (; tLen < n; tLen++) {
+ *pcDest++ = '\0';
+ }
+ return s1;
+} /* end of unincpy */
+
+/*
+ * unilen - calculate the length of a Unicode string
+ *
+ * returns the length in bytes
+ */
+size_t
+unilen(const UCHAR *s)
+{
+ size_t tLen;
+ USHORT usUni;
+
+ tLen = 0;
+ for (;;) {
+ usUni = usGetWord(tLen, s);
+ if (usUni == 0) {
+ return tLen;
+ }
+ tLen += 2;
+ }
+} /* end of unilen */
+
+/*
+ * szBaseName - get the basename of the specified filename
+ */
+const char *
+szBasename(const char *szFilename)
+{
+ const char *szTmp;
+
+ fail(szFilename == NULL);
+
+ if (szFilename == NULL || szFilename[0] == '\0') {
+ return "null";
+ }
+
+ szTmp = strrchr(szFilename, FILE_SEPARATOR[0]);
+ if (szTmp == NULL) {
+ return szFilename;
+ }
+ return ++szTmp;
+} /* end of szBasename */
+
+/*
+ * lComputeLeading - compute the leading
+ *
+ * NOTE: the fontsize is specified in half points
+ *
+ * Returns the leading in drawunits
+ */
+long
+lComputeLeading(USHORT usFontSize)
+{
+ long lLeading;
+
+ lLeading = (long)usFontSize * 500L;
+ if (usFontSize < 18) { /* Small text: 112% */
+ lLeading *= 112;
+ } else if (usFontSize < 28) { /* Normal text: 124% */
+ lLeading *= 124;
+ } else if (usFontSize < 48) { /* Small headlines: 104% */
+ lLeading *= 104;
+ } else { /* Large headlines: 100% */
+ lLeading *= 100;
+ }
+ lLeading = lMilliPoints2DrawUnits(lLeading);
+ lLeading += 50;
+ lLeading /= 100;
+ return lLeading;
+} /* end of lComputeLeading */
+
+/*
+ * Convert a UCS character to an UTF-8 string
+ *
+ * Returns the string length of the result
+ */
+size_t
+tUcs2Utf8(ULONG ulChar, char *szResult, size_t tMaxResultLen)
+{
+ if (szResult == NULL || tMaxResultLen == 0) {
+ return 0;
+ }
+
+ if (ulChar < 0x80 && tMaxResultLen >= 2) {
+ szResult[0] = (char)ulChar;
+ szResult[1] = '\0';
+ return 1;
+ }
+ if (ulChar < 0x800 && tMaxResultLen >= 3) {
+ szResult[0] = (char)(0xc0 | ulChar >> 6);
+ szResult[1] = (char)(0x80 | (ulChar & 0x3f));
+ szResult[2] = '\0';
+ return 2;
+ }
+ if (ulChar < 0x10000 && tMaxResultLen >= 4) {
+ szResult[0] = (char)(0xe0 | ulChar >> 12);
+ szResult[1] = (char)(0x80 | (ulChar >> 6 & 0x3f));
+ szResult[2] = (char)(0x80 | (ulChar & 0x3f));
+ szResult[3] = '\0';
+ return 3;
+ }
+ if (ulChar < 0x200000 && tMaxResultLen >= 5) {
+ szResult[0] = (char)(0xf0 | ulChar >> 18);
+ szResult[1] = (char)(0x80 | (ulChar >> 12 & 0x3f));
+ szResult[2] = (char)(0x80 | (ulChar >> 6 & 0x3f));
+ szResult[3] = (char)(0x80 | (ulChar & 0x3f));
+ szResult[4] = '\0';
+ return 4;
+ }
+ szResult[0] = '\0';
+ return 0;
+} /* end of tUcs2Utf8 */
+
+/*
+ * vGetBulletValue - get the bullet value for the conversing type and encoding
+ */
+void
+vGetBulletValue(conversion_type eConversionType, encoding_type eEncoding,
+ char *szResult, size_t tMaxResultLen)
+{
+ fail(szResult == NULL);
+ fail(tMaxResultLen < 2);
+
+ if (eEncoding == encoding_utf_8) {
+ (void)tUcs2Utf8(UNICODE_BULLET, szResult, tMaxResultLen);
+ } else {
+ szResult[0] = (char)ucGetBulletCharacter(eConversionType,
+ eEncoding);
+ szResult[1] = '\0';
+ }
+} /* end of vGetBulletValue */
+
+/*
+ * bAllZero - are all bytes zero?
+ */
+BOOL
+bAllZero(const UCHAR *aucBytes, size_t tLength)
+{
+ size_t tIndex;
+
+ if (aucBytes == NULL || tLength == 0) {
+ return TRUE;
+ }
+
+ for (tIndex = 0; tIndex < tLength; tIndex++) {
+ if (aucBytes[tIndex] != 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+} /* end of bAllZero */
+
+#if !defined(__riscos)
+/*
+ * GetCodesetFromLocale - get the codeset from the current locale
+ *
+ * Original version: Copyright (C) 1999 Bruno Haible
+ * Syntax:
+ * language[_territory][.codeset][@modifier][+special][,[sponsor][_revision]]
+ *
+ * Returns TRUE when sucessful, otherwise FALSE
+ */
+static BOOL
+bGetCodesetFromLocale(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
+{
+#if !defined(__dos)
+ const char *szLocale;
+ const char *pcTmp;
+ size_t tIndex;
+ char szModifier[6];
+#endif /* __dos */
+
+ if (pbEuro != NULL) {
+ *pbEuro = FALSE; /* Until proven otherwise */
+ }
+ if (szCodeset == NULL || tMaxCodesetLength == 0) {
+ return FALSE;
+ }
+
+#if defined(__dos)
+ if (tMaxCodesetLength < 2 + sizeof(int) * 3 + 1) {
+ DBG_DEC(tMaxCodesetLength);
+ DBG_DEC(2 + sizeof(int) * 3 + 1);
+ return FALSE;
+ }
+ /* Get the active codepage from DOS */
+ sprintf(szCodeset, "cp%d", iGetCodepage());
+ DBG_MSG(szCodeset);
+#else
+ /* Get the locale from the environment */
+ szLocale = getenv("LC_ALL");
+ if (szLocale == NULL || szLocale[0] == '\0') {
+ szLocale = getenv("LC_CTYPE");
+ if (szLocale == NULL || szLocale[0] == '\0') {
+ szLocale = getenv("LANG");
+ }
+ }
+ if (szLocale == NULL || szLocale[0] == '\0') {
+ /* No locale, so no codeset name and no modifier */
+ return FALSE;
+ }
+ DBG_MSG(szLocale);
+ pcTmp = strchr(szLocale, '.');
+ if (pcTmp == NULL) {
+ /* No codeset name */
+ szCodeset[0] = '\0';
+ } else {
+ /* Copy the codeset name */
+ pcTmp++;
+ for (tIndex = 0; tIndex < tMaxCodesetLength; tIndex++) {
+ if (*pcTmp == '@' || *pcTmp == '+' ||
+ *pcTmp == ',' || *pcTmp == '_' ||
+ *pcTmp == '\0') {
+ szCodeset[tIndex] = '\0';
+ break;
+ }
+ szCodeset[tIndex] = *pcTmp;
+ pcTmp++;
+ }
+ szCodeset[tMaxCodesetLength - 1] = '\0';
+ }
+ if (pbEuro == NULL) {
+ /* No need to get the modifier */
+ return TRUE;
+ }
+ pcTmp = strchr(szLocale, '@');
+ if (pcTmp != NULL) {
+ /* Copy the modifier */
+ pcTmp++;
+ for (tIndex = 0; tIndex < sizeof(szModifier); tIndex++) {
+ if (*pcTmp == '+' || *pcTmp == ',' ||
+ *pcTmp == '_' || *pcTmp == '\0') {
+ szModifier[tIndex] = '\0';
+ break;
+ }
+ szModifier[tIndex] = *pcTmp;
+ pcTmp++;
+ }
+ szModifier[sizeof(szModifier) - 1] = '\0';
+ *pbEuro = STRCEQ(szModifier, "Euro");
+ }
+#endif /* __dos */
+ return TRUE;
+} /* end of bGetCodesetFromLocale */
+
+/*
+ * GetNormalizedCodeset - get the normalized codeset from the current locale
+ *
+ * Returns TRUE when sucessful, otherwise FALSE
+ */
+BOOL
+bGetNormalizedCodeset(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
+{
+ BOOL bOnlyDigits;
+ const char *pcSrc;
+ char *pcDest;
+ char *szTmp, *szCodesetNorm;
+
+ if (pbEuro != NULL) {
+ *pbEuro = FALSE; /* Until proven otherwise */
+ }
+ if (szCodeset == NULL || tMaxCodesetLength < 4) {
+ return FALSE;
+ }
+
+ /* Get the codeset name */
+ szTmp = xmalloc(tMaxCodesetLength - 3);
+ if (!bGetCodesetFromLocale(szTmp, tMaxCodesetLength - 3, pbEuro)) {
+ szTmp = xfree(szTmp);
+ return FALSE;
+ }
+ /* Normalize the codeset name */
+ szCodesetNorm = xmalloc(tMaxCodesetLength - 3);
+ bOnlyDigits = TRUE;
+ pcDest = szCodesetNorm;
+ for (pcSrc = szTmp; *pcSrc != '\0'; pcSrc++) {
+ if (isalnum(*pcSrc)) {
+ *pcDest = tolower(*pcSrc);
+ if (!isdigit(*pcDest)) {
+ bOnlyDigits = FALSE;
+ }
+ pcDest++;
+ }
+ }
+ *pcDest = '\0';
+ DBG_MSG(szCodesetNorm);
+ /* Add "iso" when szCodesetNorm contains all digits */
+ if (bOnlyDigits && szCodesetNorm[0] != '\0') {
+ fail(strlen(szCodesetNorm) + 3 >= tMaxCodesetLength);
+ sprintf(szCodeset, "iso%s", szCodesetNorm);
+ } else {
+ fail(strlen(szCodesetNorm) >= tMaxCodesetLength);
+ strncpy(szCodeset, szCodesetNorm, pcDest - szCodesetNorm + 1);
+ szCodeset[tMaxCodesetLength - 1] = '\0';
+ }
+ DBG_MSG(szCodeset);
+ /* Clean up and leave */
+ szCodesetNorm = xfree(szCodesetNorm);
+ szTmp = xfree(szTmp);
+ return TRUE;
+} /* end of bGetNormalizedCodeset */
+
+/*
+ * szGetDefaultMappingFile - get the default mapping file
+ *
+ * Returns the basename of the default mapping file
+ */
+const char *
+szGetDefaultMappingFile(void)
+{
+ static const struct {
+ const char *szCodeset;
+ const char *szMappingFile;
+ } atMappingFile[] = {
+ { "iso88591", MAPPING_FILE_8859_1 },
+ { "iso88592", MAPPING_FILE_8859_2 },
+ { "iso88593", "8859-3.txt" },
+ { "iso88594", "8859-4.txt" },
+ { "iso88595", "8859-5.txt" },
+ { "iso88596", MAPPING_FILE_8859_5 },
+ { "iso88597", "8859-7.txt" },
+ { "iso88598", "8859-8.txt" },
+ { "iso88599", "8859-9.txt" },
+ { "iso885910", "8859-10.txt" },
+ { "iso885913", "8859-13.txt" },
+ { "iso885914", "8859-14.txt" },
+ { "iso885915", MAPPING_FILE_8859_15 },
+ { "iso885916", "8859-16.txt" },
+ { "koi8r", MAPPING_FILE_KOI8_R },
+ { "koi8u", MAPPING_FILE_KOI8_U },
+ { "utf8", MAPPING_FILE_UTF_8 },
+ { "cp437", MAPPING_FILE_CP437 },
+ { "cp850", "cp850.txt" },
+ { "cp852", MAPPING_FILE_CP852 },
+ { "cp862", "cp862.txt" },
+ { "cp864", "cp864.txt" },
+ { "cp866", MAPPING_FILE_CP866 },
+ { "cp1250", MAPPING_FILE_CP1250 },
+ { "cp1251", MAPPING_FILE_CP1251 },
+ { "cp1252", "cp1252.txt" },
+ };
+ size_t tIndex;
+ BOOL bEuro;
+ char szCodeset[20];
+
+ szCodeset[0] = '\0';
+ bEuro = FALSE;
+ /* Get the normalized codeset name */
+ if (!bGetNormalizedCodeset(szCodeset, sizeof(szCodeset), &bEuro)) {
+ return MAPPING_FILE_8859_1;
+ }
+ if (szCodeset[0] == '\0') {
+ if (bEuro) {
+ /* Default mapping file (with Euro sign) */
+ return MAPPING_FILE_8859_15;
+ } else {
+ /* Default mapping file (without Euro sign) */
+ return MAPPING_FILE_8859_1;
+ }
+ }
+ /* Find the name in the table */
+ for (tIndex = 0; tIndex < elementsof(atMappingFile); tIndex++) {
+ if (STREQ(atMappingFile[tIndex].szCodeset, szCodeset)) {
+ return atMappingFile[tIndex].szMappingFile;
+ }
+ }
+ /* Default default mapping file */
+#if defined(__dos)
+ return MAPPING_FILE_CP437;
+#else
+ return MAPPING_FILE_8859_1;
+#endif /* __dos */
+} /* end of szGetDefaultMappingFile */
+#endif /* !__riscos */
+
+/*
+ * tConvertDTTM - convert Windows Date and Time format
+ *
+ * returns Unix time_t or -1
+ */
+time_t
+tConvertDTTM(ULONG ulDTTM)
+{
+ struct tm tTime;
+ time_t tResult;
+
+ if (ulDTTM == 0) {
+ return (time_t)-1;
+ }
+ memset(&tTime, 0, sizeof(tTime));
+ tTime.tm_min = (int)(ulDTTM & 0x0000003f);
+ tTime.tm_hour = (int)((ulDTTM & 0x000007c0) >> 6);
+ tTime.tm_mday = (int)((ulDTTM & 0x0000f800) >> 11);
+ tTime.tm_mon = (int)((ulDTTM & 0x000f0000) >> 16);
+ tTime.tm_year = (int)((ulDTTM & 0x1ff00000) >> 20);
+ tTime.tm_isdst = -1;
+ tTime.tm_mon--; /* From 01-12 to 00-11 */
+ tResult = mktime(&tTime);
+ NO_DBG_MSG(ctime(&tResult));
+ return tResult;
+} /* end of tConvertDTTM */