diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /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-x | sys/src/cmd/aux/antiword/misc.c | 894 |
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 */ |