xref: /plan9/sys/src/cmd/aux/antiword/misc.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * misc.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Miscellaneous functions
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdio.h>
10f5736e95SDavid du Colombier #include <stdlib.h>
11f5736e95SDavid du Colombier #include <string.h>
12f5736e95SDavid du Colombier #include <ctype.h>
13f5736e95SDavid du Colombier #include <time.h>
14f5736e95SDavid du Colombier #if defined(__riscos)
15*25b329d5SDavid du Colombier #include "DeskLib:SWI.h"
16f5736e95SDavid du Colombier #else
17f5736e95SDavid du Colombier #include <errno.h>
18f5736e95SDavid du Colombier #include <sys/types.h>
19f5736e95SDavid du Colombier #include <sys/stat.h>
20f5736e95SDavid du Colombier #endif /* __riscos */
21*25b329d5SDavid du Colombier #if !defined(S_ISREG)
22f5736e95SDavid du Colombier #define S_ISREG(x)	(((x) & S_IFMT) == S_IFREG)
23*25b329d5SDavid du Colombier #endif /* !S_ISREG */
24f5736e95SDavid du Colombier #include "antiword.h"
25*25b329d5SDavid du Colombier #if defined(__vms)
26*25b329d5SDavid du Colombier #include <unixlib.h>
27*25b329d5SDavid du Colombier #endif
28f5736e95SDavid du Colombier 
29f5736e95SDavid du Colombier #if !defined(__riscos)
30f5736e95SDavid du Colombier /*
31f5736e95SDavid du Colombier  * szGetHomeDirectory - get the name of the home directory
32f5736e95SDavid du Colombier  */
33f5736e95SDavid du Colombier const char *
szGetHomeDirectory(void)34f5736e95SDavid du Colombier szGetHomeDirectory(void)
35f5736e95SDavid du Colombier {
36f5736e95SDavid du Colombier 	const char	*szHome;
37f5736e95SDavid du Colombier 
38f5736e95SDavid du Colombier #if defined(__vms)
39f5736e95SDavid du Colombier 	szHome = decc$translate_vms(getenv("HOME"));
40f5736e95SDavid du Colombier #elif defined(__Plan9__)
41f5736e95SDavid du Colombier 	szHome = getenv("home");
42f5736e95SDavid du Colombier #else
43f5736e95SDavid du Colombier 	szHome = getenv("HOME");
44*25b329d5SDavid du Colombier #endif /* __vms */
45f5736e95SDavid du Colombier 
46f5736e95SDavid du Colombier 	if (szHome == NULL || szHome[0] == '\0') {
47*25b329d5SDavid du Colombier #if defined(N_PLAT_NLM)
48*25b329d5SDavid du Colombier 		szHome = "SYS:";
49*25b329d5SDavid du Colombier #elif defined(__dos)
50f5736e95SDavid du Colombier 		szHome = "C:";
51f5736e95SDavid du Colombier #else
52f5736e95SDavid du Colombier 		werr(0, "I can't find the name of your HOME directory");
53f5736e95SDavid du Colombier 		szHome = "";
54f5736e95SDavid du Colombier #endif /* __dos */
55f5736e95SDavid du Colombier 	}
56f5736e95SDavid du Colombier 	return szHome;
57f5736e95SDavid du Colombier } /* end of szGetHomeDirectory */
58f5736e95SDavid du Colombier 
59f5736e95SDavid du Colombier /*
60f5736e95SDavid du Colombier  * szGetAntiwordDirectory - get the name of the Antiword directory
61f5736e95SDavid du Colombier  */
62f5736e95SDavid du Colombier const char *
szGetAntiwordDirectory(void)63f5736e95SDavid du Colombier szGetAntiwordDirectory(void)
64f5736e95SDavid du Colombier {
65f5736e95SDavid du Colombier #if defined(__vms)
66f5736e95SDavid du Colombier 	return decc$translate_vms(getenv("ANTIWORDHOME"));
67f5736e95SDavid du Colombier #else
68f5736e95SDavid du Colombier 	return getenv("ANTIWORDHOME");
69f5736e95SDavid du Colombier #endif /* __vms */
70*25b329d5SDavid du Colombier } /* end of szGetAntiwordDirectory */
71f5736e95SDavid du Colombier #endif /* !__riscos */
72f5736e95SDavid du Colombier 
73f5736e95SDavid du Colombier /*
74f5736e95SDavid du Colombier  * Get the size of the specified file.
75f5736e95SDavid du Colombier  * Returns -1 if the file does not exist or is not a proper file.
76f5736e95SDavid du Colombier  */
77f5736e95SDavid du Colombier long
lGetFilesize(const char * szFilename)78f5736e95SDavid du Colombier lGetFilesize(const char *szFilename)
79f5736e95SDavid du Colombier {
80f5736e95SDavid du Colombier #if defined(__riscos)
81*25b329d5SDavid du Colombier 	os_error	*e;
82*25b329d5SDavid du Colombier 	int	iType, iSize;
83f5736e95SDavid du Colombier 
84*25b329d5SDavid du Colombier 	e = SWI(2, 5, SWI_OS_File | XOS_Bit,
85*25b329d5SDavid du Colombier 		17, szFilename,
86*25b329d5SDavid du Colombier 		&iType, NULL, NULL, NULL, &iSize);
87f5736e95SDavid du Colombier 	if (e != NULL) {
88f5736e95SDavid du Colombier 		werr(0, "Get Filesize error %d: %s",
89f5736e95SDavid du Colombier 			e->errnum, e->errmess);
90f5736e95SDavid du Colombier 		return -1;
91f5736e95SDavid du Colombier 	}
92*25b329d5SDavid du Colombier 	if (iType != 1) {
93f5736e95SDavid du Colombier 		/* It's not a proper file or the file does not exist */
94f5736e95SDavid du Colombier 		return -1;
95f5736e95SDavid du Colombier 	}
96*25b329d5SDavid du Colombier 	return (long)iSize;
97f5736e95SDavid du Colombier #else
98f5736e95SDavid du Colombier 	struct stat	tBuffer;
99f5736e95SDavid du Colombier 
100*25b329d5SDavid du Colombier 	errno = 0;
101f5736e95SDavid du Colombier 	if (stat(szFilename, &tBuffer) != 0) {
102f5736e95SDavid du Colombier 		werr(0, "Get Filesize error %d", errno);
103f5736e95SDavid du Colombier 		return -1;
104f5736e95SDavid du Colombier 	}
105f5736e95SDavid du Colombier 	if (!S_ISREG(tBuffer.st_mode)) {
106f5736e95SDavid du Colombier 		/* It's not a regular file */
107f5736e95SDavid du Colombier 		return -1;
108f5736e95SDavid du Colombier 	}
109f5736e95SDavid du Colombier 	return (long)tBuffer.st_size;
110f5736e95SDavid du Colombier #endif /* __riscos */
111f5736e95SDavid du Colombier } /* end of lGetFilesize */
112f5736e95SDavid du Colombier 
113f5736e95SDavid du Colombier #if defined(DEBUG)
114f5736e95SDavid du Colombier void
vPrintBlock(const char * szFile,int iLine,const UCHAR * aucBlock,size_t tLength)115f5736e95SDavid du Colombier vPrintBlock(const char	*szFile, int iLine,
116f5736e95SDavid du Colombier 		const UCHAR *aucBlock, size_t tLength)
117f5736e95SDavid du Colombier {
118f5736e95SDavid du Colombier 	int i, j;
119f5736e95SDavid du Colombier 
120f5736e95SDavid du Colombier 	fail(szFile == NULL || iLine < 0 || aucBlock == NULL);
121f5736e95SDavid du Colombier 
122f5736e95SDavid du Colombier 	fprintf(stderr, "%s[%3d]:\n", szFile, iLine);
123f5736e95SDavid du Colombier 	for (i = 0; i < 32; i++) {
124f5736e95SDavid du Colombier 		if (16 * i >= (int)tLength) {
125f5736e95SDavid du Colombier 			return;
126f5736e95SDavid du Colombier 		}
127f5736e95SDavid du Colombier 		fprintf(stderr, "%03x: ", (unsigned int)(16 * i));
128f5736e95SDavid du Colombier 		for (j = 0; j < 16; j++) {
129f5736e95SDavid du Colombier 			if (16 * i + j < (int)tLength) {
130f5736e95SDavid du Colombier 				fprintf(stderr, "%02x ",
131f5736e95SDavid du Colombier 					(unsigned int)aucBlock[16 * i + j]);
132f5736e95SDavid du Colombier 			}
133f5736e95SDavid du Colombier 		}
134f5736e95SDavid du Colombier 		fprintf(stderr, "\n");
135f5736e95SDavid du Colombier 	}
136f5736e95SDavid du Colombier } /* end of vPrintBlock */
137f5736e95SDavid du Colombier 
138f5736e95SDavid du Colombier void
vPrintUnicode(const char * szFile,int iLine,const UCHAR * aucUni,size_t tLen)139f5736e95SDavid du Colombier vPrintUnicode(const char *szFile, int iLine, const UCHAR *aucUni, size_t tLen)
140f5736e95SDavid du Colombier {
141f5736e95SDavid du Colombier 	char	*szASCII;
142f5736e95SDavid du Colombier 
143f5736e95SDavid du Colombier 	fail(tLen % 2 != 0);
144f5736e95SDavid du Colombier 
145f5736e95SDavid du Colombier 	tLen /= 2;	/* Length in bytes to length in characters */
146f5736e95SDavid du Colombier 	szASCII = xmalloc(tLen + 1);
147f5736e95SDavid du Colombier 	(void)unincpy(szASCII, aucUni, tLen);
148f5736e95SDavid du Colombier 	szASCII[tLen] = '\0';
149f5736e95SDavid du Colombier 	(void)fprintf(stderr, "%s[%3d]: %.*s\n",
150f5736e95SDavid du Colombier 				szFile, iLine, (int)tLen, szASCII);
151f5736e95SDavid du Colombier 	szASCII = xfree(szASCII);
152f5736e95SDavid du Colombier } /* end of vPrintUnicode */
153f5736e95SDavid du Colombier 
154f5736e95SDavid du Colombier BOOL
bCheckDoubleLinkedList(output_type * pAnchor)155f5736e95SDavid du Colombier bCheckDoubleLinkedList(output_type *pAnchor)
156f5736e95SDavid du Colombier {
157f5736e95SDavid du Colombier 	output_type	*pCurr, *pLast;
158f5736e95SDavid du Colombier 	int		iInList;
159f5736e95SDavid du Colombier 
160f5736e95SDavid du Colombier 	pLast = pAnchor;
161f5736e95SDavid du Colombier 	iInList = 0;
162f5736e95SDavid du Colombier 	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
163f5736e95SDavid du Colombier 		pLast = pCurr;
164f5736e95SDavid du Colombier 		iInList++;
165f5736e95SDavid du Colombier 	}
166f5736e95SDavid du Colombier 	NO_DBG_DEC(iInList);
167f5736e95SDavid du Colombier 	for (pCurr = pLast; pCurr != NULL; pCurr = pCurr->pPrev) {
168f5736e95SDavid du Colombier 		pLast = pCurr;
169f5736e95SDavid du Colombier 		iInList--;
170f5736e95SDavid du Colombier 	}
171f5736e95SDavid du Colombier 	DBG_DEC_C(iInList != 0, iInList);
172f5736e95SDavid du Colombier 	return pAnchor == pLast && iInList == 0;
173f5736e95SDavid du Colombier } /* end of bCheckDoubleLinkedList */
174f5736e95SDavid du Colombier #endif /* DEBUG */
175f5736e95SDavid du Colombier 
176f5736e95SDavid du Colombier /*
177f5736e95SDavid du Colombier  * bReadBytes
178f5736e95SDavid du Colombier  * This function reads the specified number of bytes from the specified file,
179f5736e95SDavid du Colombier  * starting from the specified offset.
180f5736e95SDavid du Colombier  * Returns TRUE when successfull, otherwise FALSE
181f5736e95SDavid du Colombier  */
182f5736e95SDavid du Colombier BOOL
bReadBytes(UCHAR * aucBytes,size_t tMemb,ULONG ulOffset,FILE * pFile)183f5736e95SDavid du Colombier bReadBytes(UCHAR *aucBytes, size_t tMemb, ULONG ulOffset, FILE *pFile)
184f5736e95SDavid du Colombier {
185f5736e95SDavid du Colombier 	fail(aucBytes == NULL || pFile == NULL || ulOffset > (ULONG)LONG_MAX);
186f5736e95SDavid du Colombier 
187f5736e95SDavid du Colombier 	if (ulOffset > (ULONG)LONG_MAX) {
188f5736e95SDavid du Colombier 		return FALSE;
189f5736e95SDavid du Colombier 	}
190f5736e95SDavid du Colombier 	if (fseek(pFile, (long)ulOffset, SEEK_SET) != 0) {
191f5736e95SDavid du Colombier 		return FALSE;
192f5736e95SDavid du Colombier 	}
193f5736e95SDavid du Colombier 	if (fread(aucBytes, sizeof(UCHAR), tMemb, pFile) != tMemb) {
194f5736e95SDavid du Colombier 		return FALSE;
195f5736e95SDavid du Colombier 	}
196f5736e95SDavid du Colombier 	return TRUE;
197f5736e95SDavid du Colombier } /* end of bReadBytes */
198f5736e95SDavid du Colombier 
199f5736e95SDavid du Colombier /*
200f5736e95SDavid du Colombier  * bReadBuffer
201f5736e95SDavid du Colombier  * This function fills the specified buffer with the specified number of bytes,
202f5736e95SDavid du Colombier  * starting at the specified offset within the Big/Small Block Depot.
203f5736e95SDavid du Colombier  *
204f5736e95SDavid du Colombier  * Returns TRUE when successful, otherwise FALSE
205f5736e95SDavid du Colombier  */
206f5736e95SDavid du Colombier BOOL
bReadBuffer(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBlockDepot,size_t tBlockDepotLen,size_t tBlockSize,UCHAR * aucBuffer,ULONG ulOffset,size_t tToRead)207f5736e95SDavid du Colombier bReadBuffer(FILE *pFile, ULONG ulStartBlock,
208f5736e95SDavid du Colombier 	const ULONG *aulBlockDepot, size_t tBlockDepotLen, size_t tBlockSize,
209f5736e95SDavid du Colombier 	UCHAR *aucBuffer, ULONG ulOffset, size_t tToRead)
210f5736e95SDavid du Colombier {
211f5736e95SDavid du Colombier 	ULONG	ulBegin, ulIndex;
212f5736e95SDavid du Colombier 	size_t	tLen;
213f5736e95SDavid du Colombier 
214f5736e95SDavid du Colombier 	fail(pFile == NULL);
215f5736e95SDavid du Colombier 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
216f5736e95SDavid du Colombier 	fail(aulBlockDepot == NULL);
217f5736e95SDavid du Colombier 	fail(tBlockSize != BIG_BLOCK_SIZE && tBlockSize != SMALL_BLOCK_SIZE);
218f5736e95SDavid du Colombier 	fail(aucBuffer == NULL);
219f5736e95SDavid du Colombier 	fail(tToRead == 0);
220f5736e95SDavid du Colombier 
221f5736e95SDavid du Colombier 	for (ulIndex = ulStartBlock;
222f5736e95SDavid du Colombier 	     ulIndex != END_OF_CHAIN && tToRead != 0;
223f5736e95SDavid du Colombier 	     ulIndex = aulBlockDepot[ulIndex]) {
224f5736e95SDavid du Colombier 		if (ulIndex >= (ULONG)tBlockDepotLen) {
225f5736e95SDavid du Colombier 			DBG_DEC(ulIndex);
226f5736e95SDavid du Colombier 			DBG_DEC(tBlockDepotLen);
227f5736e95SDavid du Colombier 			if (tBlockSize >= BIG_BLOCK_SIZE) {
228f5736e95SDavid du Colombier 				werr(1, "The Big Block Depot is damaged");
229f5736e95SDavid du Colombier 			} else {
230f5736e95SDavid du Colombier 				werr(1, "The Small Block Depot is damaged");
231f5736e95SDavid du Colombier 			}
232f5736e95SDavid du Colombier 		}
233f5736e95SDavid du Colombier 		if (ulOffset >= (ULONG)tBlockSize) {
234f5736e95SDavid du Colombier 			ulOffset -= tBlockSize;
235f5736e95SDavid du Colombier 			continue;
236f5736e95SDavid du Colombier 		}
237f5736e95SDavid du Colombier 		ulBegin = ulDepotOffset(ulIndex, tBlockSize) + ulOffset;
238f5736e95SDavid du Colombier 		tLen = min(tBlockSize - (size_t)ulOffset, tToRead);
239f5736e95SDavid du Colombier 		ulOffset = 0;
240f5736e95SDavid du Colombier 		if (!bReadBytes(aucBuffer, tLen, ulBegin, pFile)) {
241f5736e95SDavid du Colombier 			werr(0, "Read big block 0x%lx not possible", ulBegin);
242f5736e95SDavid du Colombier 			return FALSE;
243f5736e95SDavid du Colombier 		}
244f5736e95SDavid du Colombier 		aucBuffer += tLen;
245f5736e95SDavid du Colombier 		tToRead -= tLen;
246f5736e95SDavid du Colombier 	}
247f5736e95SDavid du Colombier 	DBG_DEC_C(tToRead != 0, tToRead);
248f5736e95SDavid du Colombier 	return tToRead == 0;
249f5736e95SDavid du Colombier } /* end of bReadBuffer */
250f5736e95SDavid du Colombier 
251f5736e95SDavid du Colombier /*
252*25b329d5SDavid du Colombier  * Convert a Word colornumber into a true color for use in a drawfile
253f5736e95SDavid du Colombier  *
254f5736e95SDavid du Colombier  * Returns the true color
255f5736e95SDavid du Colombier  */
256f5736e95SDavid du Colombier ULONG
ulColor2Color(UCHAR ucFontColor)257f5736e95SDavid du Colombier ulColor2Color(UCHAR ucFontColor)
258f5736e95SDavid du Colombier {
259f5736e95SDavid du Colombier 	static const ULONG	aulColorTable[] = {
260f5736e95SDavid du Colombier 		/*  0 */	0x00000000UL,	/* Automatic */
261f5736e95SDavid du Colombier 		/*  1 */	0x00000000UL,	/* Black */
262f5736e95SDavid du Colombier 		/*  2 */	0xff000000UL,	/* Blue */
263f5736e95SDavid du Colombier 		/*  3 */	0xffff0000UL,	/* Turquoise */
264f5736e95SDavid du Colombier 		/*  4 */	0x00ff0000UL,	/* Bright Green */
265f5736e95SDavid du Colombier 		/*  5 */	0xff00ff00UL,	/* Pink */
266f5736e95SDavid du Colombier 		/*  6 */	0x0000ff00UL,	/* Red */
267f5736e95SDavid du Colombier 		/*  7 */	0x00ffff00UL,	/* Yellow */
268f5736e95SDavid du Colombier 		/*  8 */	0xffffff00UL,	/* White */
269f5736e95SDavid du Colombier 		/*  9 */	0x80000000UL,	/* Dark Blue */
270f5736e95SDavid du Colombier 		/* 10 */	0x80800000UL,	/* Teal */
271f5736e95SDavid du Colombier 		/* 11 */	0x00800000UL,	/* Green */
272f5736e95SDavid du Colombier 		/* 12 */	0x80008000UL,	/* Violet */
273f5736e95SDavid du Colombier 		/* 13 */	0x00008000UL,	/* Dark Red */
274f5736e95SDavid du Colombier 		/* 14 */	0x00808000UL,	/* Dark Yellow */
275f5736e95SDavid du Colombier 		/* 15 */	0x80808000UL,	/* Gray 50% */
276f5736e95SDavid du Colombier 		/* 16 */	0xc0c0c000UL,	/* Gray 25% */
277f5736e95SDavid du Colombier 	};
278f5736e95SDavid du Colombier 	if ((size_t)ucFontColor >= elementsof(aulColorTable)) {
279f5736e95SDavid du Colombier 		return aulColorTable[0];
280f5736e95SDavid du Colombier 	}
281f5736e95SDavid du Colombier 	return aulColorTable[(int)ucFontColor];
282f5736e95SDavid du Colombier } /* end of ulColor2Color */
283f5736e95SDavid du Colombier 
284f5736e95SDavid du Colombier /*
285f5736e95SDavid du Colombier  * iFindSplit - find a place to split the string
286f5736e95SDavid du Colombier  *
287f5736e95SDavid du Colombier  * returns the index of the split character or -1 if no split found.
288f5736e95SDavid du Colombier  */
289f5736e95SDavid du Colombier static int
iFindSplit(const char * szString,size_t tStringLen)290f5736e95SDavid du Colombier iFindSplit(const char *szString, size_t tStringLen)
291f5736e95SDavid du Colombier {
292f5736e95SDavid du Colombier 	size_t	tSplit;
293f5736e95SDavid du Colombier 
294f5736e95SDavid du Colombier 	if (tStringLen == 0) {
295f5736e95SDavid du Colombier 		return -1;
296f5736e95SDavid du Colombier 	}
297f5736e95SDavid du Colombier 	tSplit = tStringLen - 1;
298f5736e95SDavid du Colombier 	while (tSplit >= 1) {
299f5736e95SDavid du Colombier 		if (szString[tSplit] == ' ' ||
300f5736e95SDavid du Colombier 		    (szString[tSplit] == '-' && szString[tSplit - 1] != ' ')) {
301f5736e95SDavid du Colombier 			return (int)tSplit;
302f5736e95SDavid du Colombier 		}
303f5736e95SDavid du Colombier 		tSplit--;
304f5736e95SDavid du Colombier 	}
305f5736e95SDavid du Colombier 	return -1;
306f5736e95SDavid du Colombier } /* end of iFindSplit */
307f5736e95SDavid du Colombier 
308f5736e95SDavid du Colombier /*
309f5736e95SDavid du Colombier  * pSplitList - split the specified list in a printable part and a leftover part
310f5736e95SDavid du Colombier  *
311f5736e95SDavid du Colombier  * returns the pointer to the leftover part
312f5736e95SDavid du Colombier  */
313f5736e95SDavid du Colombier output_type *
pSplitList(output_type * pAnchor)314f5736e95SDavid du Colombier pSplitList(output_type *pAnchor)
315f5736e95SDavid du Colombier {
316f5736e95SDavid du Colombier 	output_type	*pCurr, *pLeftOver;
317f5736e95SDavid du Colombier 	int		iIndex;
318f5736e95SDavid du Colombier 
319f5736e95SDavid du Colombier  	fail(pAnchor == NULL);
320f5736e95SDavid du Colombier 
321f5736e95SDavid du Colombier 	for (pCurr = pAnchor; pCurr->pNext != NULL; pCurr = pCurr->pNext)
322f5736e95SDavid du Colombier 		;	/* EMPTY */
323f5736e95SDavid du Colombier 	iIndex = -1;
324f5736e95SDavid du Colombier 	for (; pCurr != NULL; pCurr = pCurr->pPrev) {
325f5736e95SDavid du Colombier 		iIndex = iFindSplit(pCurr->szStorage, pCurr->tNextFree);
326f5736e95SDavid du Colombier 		if (iIndex >= 0) {
327f5736e95SDavid du Colombier 			break;
328f5736e95SDavid du Colombier 		}
329f5736e95SDavid du Colombier 	}
330f5736e95SDavid du Colombier 
331f5736e95SDavid du Colombier 	if (pCurr == NULL || iIndex < 0) {
332f5736e95SDavid du Colombier 		/* No split, no leftover */
333f5736e95SDavid du Colombier 		return NULL;
334f5736e95SDavid du Colombier 	}
335f5736e95SDavid du Colombier 	/* Split over the iIndex-th character */
336f5736e95SDavid du Colombier 	NO_DBG_MSG("pLeftOver");
337f5736e95SDavid du Colombier 	pLeftOver = xmalloc(sizeof(*pLeftOver));
338f5736e95SDavid du Colombier 	fail(pCurr->tNextFree < (size_t)iIndex);
339f5736e95SDavid du Colombier 	pLeftOver->tStorageSize = pCurr->tNextFree - (size_t)iIndex;
340f5736e95SDavid du Colombier 	pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize);
341f5736e95SDavid du Colombier 	pLeftOver->tNextFree = pCurr->tNextFree - (size_t)iIndex - 1;
342f5736e95SDavid du Colombier 	(void)strncpy(pLeftOver->szStorage,
343f5736e95SDavid du Colombier 		pCurr->szStorage + iIndex + 1, pLeftOver->tNextFree);
344f5736e95SDavid du Colombier 	pLeftOver->szStorage[pLeftOver->tNextFree] = '\0';
345f5736e95SDavid du Colombier 	NO_DBG_MSG(pLeftOver->szStorage);
346f5736e95SDavid du Colombier 	pLeftOver->ucFontColor = pCurr->ucFontColor;
347f5736e95SDavid du Colombier 	pLeftOver->usFontStyle = pCurr->usFontStyle;
348f5736e95SDavid du Colombier 	pLeftOver->tFontRef = pCurr->tFontRef;
349f5736e95SDavid du Colombier 	pLeftOver->usFontSize = pCurr->usFontSize;
350f5736e95SDavid du Colombier 	pLeftOver->lStringWidth = lComputeStringWidth(
351f5736e95SDavid du Colombier 					pLeftOver->szStorage,
352f5736e95SDavid du Colombier 					pLeftOver->tNextFree,
353f5736e95SDavid du Colombier 					pLeftOver->tFontRef,
354f5736e95SDavid du Colombier 					pLeftOver->usFontSize);
355f5736e95SDavid du Colombier 	pLeftOver->pPrev = NULL;
356f5736e95SDavid du Colombier 	pLeftOver->pNext = pCurr->pNext;
357f5736e95SDavid du Colombier 	if (pLeftOver->pNext != NULL) {
358f5736e95SDavid du Colombier 		pLeftOver->pNext->pPrev = pLeftOver;
359f5736e95SDavid du Colombier 	}
360f5736e95SDavid du Colombier 	fail(!bCheckDoubleLinkedList(pLeftOver));
361f5736e95SDavid du Colombier 
362f5736e95SDavid du Colombier 	NO_DBG_MSG("pAnchor");
363f5736e95SDavid du Colombier 	NO_DBG_HEX(pCurr->szStorage[iIndex]);
364f5736e95SDavid du Colombier 	while (iIndex >= 0 && isspace((int)(UCHAR)pCurr->szStorage[iIndex])) {
365f5736e95SDavid du Colombier 		iIndex--;
366f5736e95SDavid du Colombier 	}
367f5736e95SDavid du Colombier 	pCurr->tNextFree = (size_t)iIndex + 1;
368f5736e95SDavid du Colombier 	pCurr->szStorage[pCurr->tNextFree] = '\0';
369f5736e95SDavid du Colombier 	NO_DBG_MSG(pCurr->szStorage);
370f5736e95SDavid du Colombier 	pCurr->lStringWidth = lComputeStringWidth(
371f5736e95SDavid du Colombier 					pCurr->szStorage,
372f5736e95SDavid du Colombier 					pCurr->tNextFree,
373f5736e95SDavid du Colombier 					pCurr->tFontRef,
374f5736e95SDavid du Colombier 					pCurr->usFontSize);
375f5736e95SDavid du Colombier 	pCurr->pNext = NULL;
376f5736e95SDavid du Colombier 	fail(!bCheckDoubleLinkedList(pAnchor));
377f5736e95SDavid du Colombier 
378f5736e95SDavid du Colombier 	return pLeftOver;
379f5736e95SDavid du Colombier } /* end of pSplitList */
380f5736e95SDavid du Colombier 
381f5736e95SDavid du Colombier /*
382f5736e95SDavid du Colombier  * tNumber2Roman - convert a number to Roman Numerals
383f5736e95SDavid du Colombier  *
384f5736e95SDavid du Colombier  * returns the number of characters written
385f5736e95SDavid du Colombier  */
386f5736e95SDavid du Colombier size_t
tNumber2Roman(UINT uiNumber,BOOL bUpperCase,char * szOutput)387f5736e95SDavid du Colombier tNumber2Roman(UINT uiNumber, BOOL bUpperCase, char *szOutput)
388f5736e95SDavid du Colombier {
389f5736e95SDavid du Colombier 	char	*outp, *p, *q;
390f5736e95SDavid du Colombier 	UINT	uiNextVal, uiValue;
391f5736e95SDavid du Colombier 
392f5736e95SDavid du Colombier 	fail(szOutput == NULL);
393f5736e95SDavid du Colombier 
394f5736e95SDavid du Colombier 	uiNumber %= 4000;	/* Very high numbers can't be represented */
395f5736e95SDavid du Colombier 	if (uiNumber == 0) {
396f5736e95SDavid du Colombier 		szOutput[0] = '\0';
397f5736e95SDavid du Colombier 		return 0;
398f5736e95SDavid du Colombier 	}
399f5736e95SDavid du Colombier 
400f5736e95SDavid du Colombier 	outp = szOutput;
401f5736e95SDavid du Colombier 	p = bUpperCase ? "M\2D\5C\2L\5X\2V\5I" : "m\2d\5c\2l\5x\2v\5i";
402f5736e95SDavid du Colombier 	uiValue = 1000;
403f5736e95SDavid du Colombier 	for (;;) {
404f5736e95SDavid du Colombier 		while (uiNumber >= uiValue) {
405f5736e95SDavid du Colombier 			*outp++ = *p;
406f5736e95SDavid du Colombier 			uiNumber -= uiValue;
407f5736e95SDavid du Colombier 		}
408f5736e95SDavid du Colombier 		if (uiNumber == 0) {
409f5736e95SDavid du Colombier 			*outp = '\0';
410f5736e95SDavid du Colombier 			fail(outp < szOutput);
411f5736e95SDavid du Colombier 			return (size_t)(outp - szOutput);
412f5736e95SDavid du Colombier 		}
413f5736e95SDavid du Colombier 		q = p + 1;
414f5736e95SDavid du Colombier 		uiNextVal = uiValue / (UINT)(UCHAR)*q;
415f5736e95SDavid du Colombier 		if ((int)*q == 2) {		/* magic */
416f5736e95SDavid du Colombier 			uiNextVal /= (UINT)(UCHAR)*(q += 2);
417f5736e95SDavid du Colombier 		}
418f5736e95SDavid du Colombier 		if (uiNumber + uiNextVal >= uiValue) {
419f5736e95SDavid du Colombier 			*outp++ = *++q;
420f5736e95SDavid du Colombier 			uiNumber += uiNextVal;
421f5736e95SDavid du Colombier 		} else {
422f5736e95SDavid du Colombier 			p++;
423f5736e95SDavid du Colombier 			uiValue /= (UINT)(UCHAR)(*p++);
424f5736e95SDavid du Colombier 		}
425f5736e95SDavid du Colombier 	}
426f5736e95SDavid du Colombier } /* end of tNumber2Roman */
427f5736e95SDavid du Colombier 
428f5736e95SDavid du Colombier /*
429f5736e95SDavid du Colombier  * iNumber2Alpha - convert a number to alphabetic "numbers"
430f5736e95SDavid du Colombier  *
431f5736e95SDavid du Colombier  * returns the number of characters written
432f5736e95SDavid du Colombier  */
433f5736e95SDavid du Colombier size_t
tNumber2Alpha(UINT uiNumber,BOOL bUpperCase,char * szOutput)434f5736e95SDavid du Colombier tNumber2Alpha(UINT uiNumber, BOOL bUpperCase, char *szOutput)
435f5736e95SDavid du Colombier {
436f5736e95SDavid du Colombier 	char	*outp;
437f5736e95SDavid du Colombier 	UINT	uiTmp;
438f5736e95SDavid du Colombier 
439f5736e95SDavid du Colombier 	fail(szOutput == NULL);
440f5736e95SDavid du Colombier 
441f5736e95SDavid du Colombier 	if (uiNumber == 0) {
442f5736e95SDavid du Colombier 		szOutput[0] = '\0';
443f5736e95SDavid du Colombier 		return 0;
444f5736e95SDavid du Colombier 	}
445f5736e95SDavid du Colombier 
446f5736e95SDavid du Colombier 	outp = szOutput;
447f5736e95SDavid du Colombier 	uiTmp = (UINT)(bUpperCase ? 'A': 'a');
448f5736e95SDavid du Colombier 	if (uiNumber <= 26) {
449f5736e95SDavid du Colombier 		uiNumber -= 1;
450f5736e95SDavid du Colombier 		*outp++ = (char)(uiTmp + uiNumber);
451f5736e95SDavid du Colombier 	} else if (uiNumber <= 26U + 26U*26U) {
452f5736e95SDavid du Colombier 		uiNumber -= 26 + 1;
453f5736e95SDavid du Colombier 		*outp++ = (char)(uiTmp + uiNumber / 26);
454f5736e95SDavid du Colombier 		*outp++ = (char)(uiTmp + uiNumber % 26);
455f5736e95SDavid du Colombier 	} else if (uiNumber <= 26U + 26U*26U + 26U*26U*26U) {
456f5736e95SDavid du Colombier 		uiNumber -= 26 + 26*26 + 1;
457f5736e95SDavid du Colombier 		*outp++ = (char)(uiTmp + uiNumber / (26*26));
458f5736e95SDavid du Colombier 		*outp++ = (char)(uiTmp + uiNumber / 26 % 26);
459f5736e95SDavid du Colombier 		*outp++ = (char)(uiTmp + uiNumber % 26);
460f5736e95SDavid du Colombier 	}
461f5736e95SDavid du Colombier 	*outp = '\0';
462f5736e95SDavid du Colombier 	fail(outp < szOutput);
463f5736e95SDavid du Colombier 	return (size_t)(outp - szOutput);
464f5736e95SDavid du Colombier } /* end of tNumber2Alpha */
465f5736e95SDavid du Colombier 
466f5736e95SDavid du Colombier /*
467f5736e95SDavid du Colombier  * unincpy - copy a counted Unicode string to an single-byte string
468f5736e95SDavid du Colombier  */
469f5736e95SDavid du Colombier char *
unincpy(char * s1,const UCHAR * s2,size_t n)470f5736e95SDavid du Colombier unincpy(char *s1, const UCHAR *s2, size_t n)
471f5736e95SDavid du Colombier {
472*25b329d5SDavid du Colombier 	char	*pcDest;
473f5736e95SDavid du Colombier 	ULONG	ulChar;
474f5736e95SDavid du Colombier 	size_t	tLen;
475f5736e95SDavid du Colombier 	USHORT	usUni;
476f5736e95SDavid du Colombier 
477*25b329d5SDavid du Colombier 	for (pcDest = s1, tLen = 0; tLen < n; pcDest++, tLen++) {
478f5736e95SDavid du Colombier 		usUni = usGetWord(tLen * 2, s2);
479f5736e95SDavid du Colombier 		if (usUni == 0) {
480f5736e95SDavid du Colombier 			break;
481f5736e95SDavid du Colombier 		}
482f5736e95SDavid du Colombier 		ulChar = ulTranslateCharacters(usUni, 0, 8,
483f5736e95SDavid du Colombier 				conversion_unknown, encoding_neutral, FALSE);
484f5736e95SDavid du Colombier 		if (ulChar == IGNORE_CHARACTER) {
485f5736e95SDavid du Colombier 			ulChar = (ULONG)'?';
486f5736e95SDavid du Colombier 		}
487*25b329d5SDavid du Colombier 		*pcDest = (char)ulChar;
488f5736e95SDavid du Colombier 	}
489f5736e95SDavid du Colombier 	for (; tLen < n; tLen++) {
490*25b329d5SDavid du Colombier 		*pcDest++ = '\0';
491f5736e95SDavid du Colombier 	}
492f5736e95SDavid du Colombier 	return s1;
493f5736e95SDavid du Colombier } /* end of unincpy */
494f5736e95SDavid du Colombier 
495f5736e95SDavid du Colombier /*
496f5736e95SDavid du Colombier  * unilen - calculate the length of a Unicode string
497f5736e95SDavid du Colombier  *
498f5736e95SDavid du Colombier  * returns the length in bytes
499f5736e95SDavid du Colombier  */
500f5736e95SDavid du Colombier size_t
unilen(const UCHAR * s)501f5736e95SDavid du Colombier unilen(const UCHAR *s)
502f5736e95SDavid du Colombier {
503f5736e95SDavid du Colombier 	size_t	tLen;
504f5736e95SDavid du Colombier 	USHORT	usUni;
505f5736e95SDavid du Colombier 
506f5736e95SDavid du Colombier 	tLen = 0;
507f5736e95SDavid du Colombier 	for (;;) {
508f5736e95SDavid du Colombier 		usUni = usGetWord(tLen, s);
509f5736e95SDavid du Colombier 		if (usUni == 0) {
510f5736e95SDavid du Colombier 			return tLen;
511f5736e95SDavid du Colombier 		}
512f5736e95SDavid du Colombier 		tLen += 2;
513f5736e95SDavid du Colombier 	}
514f5736e95SDavid du Colombier } /* end of unilen */
515f5736e95SDavid du Colombier 
516f5736e95SDavid du Colombier /*
517f5736e95SDavid du Colombier  * szBaseName - get the basename of the specified filename
518f5736e95SDavid du Colombier  */
519f5736e95SDavid du Colombier const char *
szBasename(const char * szFilename)520f5736e95SDavid du Colombier szBasename(const char *szFilename)
521f5736e95SDavid du Colombier {
522f5736e95SDavid du Colombier 	const char	*szTmp;
523f5736e95SDavid du Colombier 
524f5736e95SDavid du Colombier 	fail(szFilename == NULL);
525f5736e95SDavid du Colombier 
526f5736e95SDavid du Colombier 	if (szFilename == NULL || szFilename[0] == '\0') {
527f5736e95SDavid du Colombier 		return "null";
528f5736e95SDavid du Colombier 	}
529f5736e95SDavid du Colombier 
530f5736e95SDavid du Colombier 	szTmp = strrchr(szFilename, FILE_SEPARATOR[0]);
531f5736e95SDavid du Colombier 	if (szTmp == NULL) {
532f5736e95SDavid du Colombier 		return szFilename;
533f5736e95SDavid du Colombier 	}
534f5736e95SDavid du Colombier 	return ++szTmp;
535f5736e95SDavid du Colombier } /* end of szBasename */
536f5736e95SDavid du Colombier 
537f5736e95SDavid du Colombier /*
538f5736e95SDavid du Colombier  * lComputeLeading - compute the leading
539f5736e95SDavid du Colombier  *
540f5736e95SDavid du Colombier  * NOTE: the fontsize is specified in half points
541f5736e95SDavid du Colombier  *
542f5736e95SDavid du Colombier  * Returns the leading in drawunits
543f5736e95SDavid du Colombier  */
544f5736e95SDavid du Colombier long
lComputeLeading(USHORT usFontSize)545f5736e95SDavid du Colombier lComputeLeading(USHORT usFontSize)
546f5736e95SDavid du Colombier {
547f5736e95SDavid du Colombier 	long	lLeading;
548f5736e95SDavid du Colombier 
549f5736e95SDavid du Colombier 	lLeading = (long)usFontSize * 500L;
550f5736e95SDavid du Colombier 	if (usFontSize < 18) {		/* Small text: 112% */
551f5736e95SDavid du Colombier 		lLeading *= 112;
552f5736e95SDavid du Colombier 	} else if (usFontSize < 28) {	/* Normal text: 124% */
553f5736e95SDavid du Colombier 		lLeading *= 124;
554f5736e95SDavid du Colombier 	} else if (usFontSize < 48) {	/* Small headlines: 104% */
555f5736e95SDavid du Colombier 		lLeading *= 104;
556f5736e95SDavid du Colombier 	} else {			/* Large headlines: 100% */
557f5736e95SDavid du Colombier 		lLeading *= 100;
558f5736e95SDavid du Colombier 	}
559f5736e95SDavid du Colombier 	lLeading = lMilliPoints2DrawUnits(lLeading);
560f5736e95SDavid du Colombier 	lLeading += 50;
561f5736e95SDavid du Colombier 	lLeading /= 100;
562f5736e95SDavid du Colombier 	return lLeading;
563f5736e95SDavid du Colombier } /* end of lComputeLeading */
564f5736e95SDavid du Colombier 
565f5736e95SDavid du Colombier /*
566f5736e95SDavid du Colombier  * Convert a UCS character to an UTF-8 string
567f5736e95SDavid du Colombier  *
568f5736e95SDavid du Colombier  * Returns the string length of the result
569f5736e95SDavid du Colombier  */
570f5736e95SDavid du Colombier size_t
tUcs2Utf8(ULONG ulChar,char * szResult,size_t tMaxResultLen)571f5736e95SDavid du Colombier tUcs2Utf8(ULONG ulChar, char *szResult, size_t tMaxResultLen)
572f5736e95SDavid du Colombier {
573f5736e95SDavid du Colombier 	if (szResult == NULL || tMaxResultLen == 0) {
574f5736e95SDavid du Colombier 		return 0;
575f5736e95SDavid du Colombier 	}
576f5736e95SDavid du Colombier 
577f5736e95SDavid du Colombier 	if (ulChar < 0x80 && tMaxResultLen >= 2) {
578f5736e95SDavid du Colombier 		szResult[0] = (char)ulChar;
579f5736e95SDavid du Colombier 		szResult[1] = '\0';
580f5736e95SDavid du Colombier 		return 1;
581f5736e95SDavid du Colombier 	}
582f5736e95SDavid du Colombier 	if (ulChar < 0x800 && tMaxResultLen >= 3) {
583f5736e95SDavid du Colombier 		szResult[0] = (char)(0xc0 | ulChar >> 6);
584f5736e95SDavid du Colombier 		szResult[1] = (char)(0x80 | (ulChar & 0x3f));
585f5736e95SDavid du Colombier 		szResult[2] = '\0';
586f5736e95SDavid du Colombier 		return 2;
587f5736e95SDavid du Colombier 	}
588f5736e95SDavid du Colombier 	if (ulChar < 0x10000 && tMaxResultLen >= 4) {
589f5736e95SDavid du Colombier 		szResult[0] = (char)(0xe0 | ulChar >> 12);
590f5736e95SDavid du Colombier 		szResult[1] = (char)(0x80 | (ulChar >> 6 & 0x3f));
591f5736e95SDavid du Colombier 		szResult[2] = (char)(0x80 | (ulChar & 0x3f));
592f5736e95SDavid du Colombier 		szResult[3] = '\0';
593f5736e95SDavid du Colombier 		return 3;
594f5736e95SDavid du Colombier 	}
595f5736e95SDavid du Colombier 	if (ulChar < 0x200000 && tMaxResultLen >= 5) {
596f5736e95SDavid du Colombier 		szResult[0] = (char)(0xf0 | ulChar >> 18);
597f5736e95SDavid du Colombier 		szResult[1] = (char)(0x80 | (ulChar >> 12 & 0x3f));
598f5736e95SDavid du Colombier 		szResult[2] = (char)(0x80 | (ulChar >> 6 & 0x3f));
599f5736e95SDavid du Colombier 		szResult[3] = (char)(0x80 | (ulChar & 0x3f));
600f5736e95SDavid du Colombier 		szResult[4] = '\0';
601f5736e95SDavid du Colombier 		return 4;
602f5736e95SDavid du Colombier 	}
603f5736e95SDavid du Colombier 	szResult[0] = '\0';
604f5736e95SDavid du Colombier 	return 0;
605f5736e95SDavid du Colombier } /* end of tUcs2Utf8 */
606f5736e95SDavid du Colombier 
607f5736e95SDavid du Colombier /*
608f5736e95SDavid du Colombier  * vGetBulletValue - get the bullet value for the conversing type and encoding
609f5736e95SDavid du Colombier  */
610f5736e95SDavid du Colombier void
vGetBulletValue(conversion_type eConversionType,encoding_type eEncoding,char * szResult,size_t tMaxResultLen)611f5736e95SDavid du Colombier vGetBulletValue(conversion_type eConversionType, encoding_type eEncoding,
612f5736e95SDavid du Colombier 	char *szResult, size_t tMaxResultLen)
613f5736e95SDavid du Colombier {
614f5736e95SDavid du Colombier 	fail(szResult == NULL);
615f5736e95SDavid du Colombier 	fail(tMaxResultLen < 2);
616f5736e95SDavid du Colombier 
617*25b329d5SDavid du Colombier 	if (eEncoding == encoding_utf_8) {
618f5736e95SDavid du Colombier 		(void)tUcs2Utf8(UNICODE_BULLET, szResult, tMaxResultLen);
619f5736e95SDavid du Colombier 	} else {
620*25b329d5SDavid du Colombier 		szResult[0] = (char)ucGetBulletCharacter(eConversionType,
621*25b329d5SDavid du Colombier 							eEncoding);
622f5736e95SDavid du Colombier 		szResult[1] = '\0';
623f5736e95SDavid du Colombier 	}
624f5736e95SDavid du Colombier } /* end of vGetBulletValue */
625f5736e95SDavid du Colombier 
626f5736e95SDavid du Colombier /*
627f5736e95SDavid du Colombier  * bAllZero - are all bytes zero?
628f5736e95SDavid du Colombier  */
629f5736e95SDavid du Colombier BOOL
bAllZero(const UCHAR * aucBytes,size_t tLength)630f5736e95SDavid du Colombier bAllZero(const UCHAR *aucBytes, size_t tLength)
631f5736e95SDavid du Colombier {
632f5736e95SDavid du Colombier 	size_t	tIndex;
633f5736e95SDavid du Colombier 
634f5736e95SDavid du Colombier 	if (aucBytes == NULL || tLength == 0) {
635f5736e95SDavid du Colombier 		return TRUE;
636f5736e95SDavid du Colombier 	}
637f5736e95SDavid du Colombier 
638f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < tLength; tIndex++) {
639f5736e95SDavid du Colombier 		if (aucBytes[tIndex] != 0) {
640f5736e95SDavid du Colombier 			return FALSE;
641f5736e95SDavid du Colombier 		}
642f5736e95SDavid du Colombier 	}
643f5736e95SDavid du Colombier 	return TRUE;
644f5736e95SDavid du Colombier } /* end of bAllZero */
645*25b329d5SDavid du Colombier 
646*25b329d5SDavid du Colombier #if !defined(__riscos)
647*25b329d5SDavid du Colombier /*
648*25b329d5SDavid du Colombier  * GetCodesetFromLocale - get the codeset from the current locale
649*25b329d5SDavid du Colombier  *
650*25b329d5SDavid du Colombier  * Original version: Copyright (C) 1999  Bruno Haible
651*25b329d5SDavid du Colombier  * Syntax:
652*25b329d5SDavid du Colombier  * language[_territory][.codeset][@modifier][+special][,[sponsor][_revision]]
653*25b329d5SDavid du Colombier  *
654*25b329d5SDavid du Colombier  * Returns TRUE when sucessful, otherwise FALSE
655*25b329d5SDavid du Colombier  */
656*25b329d5SDavid du Colombier static BOOL
bGetCodesetFromLocale(char * szCodeset,size_t tMaxCodesetLength,BOOL * pbEuro)657*25b329d5SDavid du Colombier bGetCodesetFromLocale(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
658*25b329d5SDavid du Colombier {
659*25b329d5SDavid du Colombier #if !defined(__dos)
660*25b329d5SDavid du Colombier 	const char	*szLocale;
661*25b329d5SDavid du Colombier 	const char	*pcTmp;
662*25b329d5SDavid du Colombier 	size_t		tIndex;
663*25b329d5SDavid du Colombier 	char		szModifier[6];
664*25b329d5SDavid du Colombier #endif /* __dos */
665*25b329d5SDavid du Colombier 
666*25b329d5SDavid du Colombier 	if (pbEuro != NULL) {
667*25b329d5SDavid du Colombier 		*pbEuro = FALSE;	/* Until proven otherwise */
668*25b329d5SDavid du Colombier 	}
669*25b329d5SDavid du Colombier 	if (szCodeset == NULL || tMaxCodesetLength == 0) {
670*25b329d5SDavid du Colombier 		return FALSE;
671*25b329d5SDavid du Colombier 	}
672*25b329d5SDavid du Colombier 
673*25b329d5SDavid du Colombier #if defined(__dos)
674*25b329d5SDavid du Colombier 	if (tMaxCodesetLength < 2 + sizeof(int) * 3 + 1) {
675*25b329d5SDavid du Colombier 		DBG_DEC(tMaxCodesetLength);
676*25b329d5SDavid du Colombier 		DBG_DEC(2 + sizeof(int) * 3 + 1);
677*25b329d5SDavid du Colombier 		return FALSE;
678*25b329d5SDavid du Colombier 	}
679*25b329d5SDavid du Colombier 	/* Get the active codepage from DOS */
680*25b329d5SDavid du Colombier 	sprintf(szCodeset, "cp%d", iGetCodepage());
681*25b329d5SDavid du Colombier 	DBG_MSG(szCodeset);
682*25b329d5SDavid du Colombier #else
683*25b329d5SDavid du Colombier 	/* Get the locale from the environment */
684*25b329d5SDavid du Colombier 	szLocale = getenv("LC_ALL");
685*25b329d5SDavid du Colombier 	if (szLocale == NULL || szLocale[0] == '\0') {
686*25b329d5SDavid du Colombier 		szLocale = getenv("LC_CTYPE");
687*25b329d5SDavid du Colombier 		if (szLocale == NULL || szLocale[0] == '\0') {
688*25b329d5SDavid du Colombier 			szLocale = getenv("LANG");
689*25b329d5SDavid du Colombier 		}
690*25b329d5SDavid du Colombier 	}
691*25b329d5SDavid du Colombier 	if (szLocale == NULL || szLocale[0] == '\0') {
692*25b329d5SDavid du Colombier 		/* No locale, so no codeset name and no modifier */
693*25b329d5SDavid du Colombier 		return FALSE;
694*25b329d5SDavid du Colombier 	}
695*25b329d5SDavid du Colombier 	DBG_MSG(szLocale);
696*25b329d5SDavid du Colombier 	pcTmp = strchr(szLocale, '.');
697*25b329d5SDavid du Colombier 	if (pcTmp == NULL) {
698*25b329d5SDavid du Colombier 		/* No codeset name */
699*25b329d5SDavid du Colombier 		szCodeset[0] = '\0';
700*25b329d5SDavid du Colombier 	} else {
701*25b329d5SDavid du Colombier 		/* Copy the codeset name */
702*25b329d5SDavid du Colombier 		pcTmp++;
703*25b329d5SDavid du Colombier 		for (tIndex = 0; tIndex < tMaxCodesetLength; tIndex++) {
704*25b329d5SDavid du Colombier 			if (*pcTmp == '@' || *pcTmp == '+' ||
705*25b329d5SDavid du Colombier 			    *pcTmp == ',' || *pcTmp == '_' ||
706*25b329d5SDavid du Colombier 			    *pcTmp == '\0') {
707*25b329d5SDavid du Colombier 				szCodeset[tIndex] = '\0';
708*25b329d5SDavid du Colombier 				break;
709*25b329d5SDavid du Colombier 			}
710*25b329d5SDavid du Colombier 			szCodeset[tIndex] = *pcTmp;
711*25b329d5SDavid du Colombier 			pcTmp++;
712*25b329d5SDavid du Colombier 		}
713*25b329d5SDavid du Colombier 		szCodeset[tMaxCodesetLength - 1] = '\0';
714*25b329d5SDavid du Colombier 	}
715*25b329d5SDavid du Colombier 	if (pbEuro == NULL) {
716*25b329d5SDavid du Colombier 		/* No need to get the modifier */
717*25b329d5SDavid du Colombier 		return TRUE;
718*25b329d5SDavid du Colombier 	}
719*25b329d5SDavid du Colombier 	pcTmp = strchr(szLocale, '@');
720*25b329d5SDavid du Colombier 	if (pcTmp != NULL) {
721*25b329d5SDavid du Colombier 		/* Copy the modifier */
722*25b329d5SDavid du Colombier 		pcTmp++;
723*25b329d5SDavid du Colombier 		for (tIndex = 0; tIndex < sizeof(szModifier); tIndex++) {
724*25b329d5SDavid du Colombier 			if (*pcTmp == '+' || *pcTmp == ',' ||
725*25b329d5SDavid du Colombier 			    *pcTmp == '_' || *pcTmp == '\0') {
726*25b329d5SDavid du Colombier 				szModifier[tIndex] = '\0';
727*25b329d5SDavid du Colombier 				break;
728*25b329d5SDavid du Colombier 			}
729*25b329d5SDavid du Colombier 			szModifier[tIndex] = *pcTmp;
730*25b329d5SDavid du Colombier 			pcTmp++;
731*25b329d5SDavid du Colombier 		}
732*25b329d5SDavid du Colombier 		szModifier[sizeof(szModifier) - 1] = '\0';
733*25b329d5SDavid du Colombier 		*pbEuro = STRCEQ(szModifier, "Euro");
734*25b329d5SDavid du Colombier 	}
735*25b329d5SDavid du Colombier #endif /* __dos */
736*25b329d5SDavid du Colombier 	return TRUE;
737*25b329d5SDavid du Colombier } /* end of bGetCodesetFromLocale */
738*25b329d5SDavid du Colombier 
739*25b329d5SDavid du Colombier /*
740*25b329d5SDavid du Colombier  * GetNormalizedCodeset - get the normalized codeset from the current locale
741*25b329d5SDavid du Colombier  *
742*25b329d5SDavid du Colombier  * Returns TRUE when sucessful, otherwise FALSE
743*25b329d5SDavid du Colombier  */
744*25b329d5SDavid du Colombier BOOL
bGetNormalizedCodeset(char * szCodeset,size_t tMaxCodesetLength,BOOL * pbEuro)745*25b329d5SDavid du Colombier bGetNormalizedCodeset(char *szCodeset, size_t tMaxCodesetLength, BOOL *pbEuro)
746*25b329d5SDavid du Colombier {
747*25b329d5SDavid du Colombier 	BOOL	bOnlyDigits;
748*25b329d5SDavid du Colombier 	const char	*pcSrc;
749*25b329d5SDavid du Colombier 	char	*pcDest;
750*25b329d5SDavid du Colombier 	char	*szTmp, *szCodesetNorm;
751*25b329d5SDavid du Colombier 
752*25b329d5SDavid du Colombier 	if (pbEuro != NULL) {
753*25b329d5SDavid du Colombier 		*pbEuro = FALSE;	/* Until proven otherwise */
754*25b329d5SDavid du Colombier 	}
755*25b329d5SDavid du Colombier 	if (szCodeset == NULL || tMaxCodesetLength < 4) {
756*25b329d5SDavid du Colombier 		return FALSE;
757*25b329d5SDavid du Colombier 	}
758*25b329d5SDavid du Colombier 
759*25b329d5SDavid du Colombier 	/* Get the codeset name */
760*25b329d5SDavid du Colombier 	szTmp = xmalloc(tMaxCodesetLength - 3);
761*25b329d5SDavid du Colombier 	if (!bGetCodesetFromLocale(szTmp, tMaxCodesetLength - 3, pbEuro)) {
762*25b329d5SDavid du Colombier 		szTmp = xfree(szTmp);
763*25b329d5SDavid du Colombier 		return FALSE;
764*25b329d5SDavid du Colombier 	}
765*25b329d5SDavid du Colombier 	/* Normalize the codeset name */
766*25b329d5SDavid du Colombier 	szCodesetNorm = xmalloc(tMaxCodesetLength - 3);
767*25b329d5SDavid du Colombier 	bOnlyDigits = TRUE;
768*25b329d5SDavid du Colombier 	pcDest = szCodesetNorm;
769*25b329d5SDavid du Colombier 	for (pcSrc = szTmp; *pcSrc != '\0'; pcSrc++) {
770*25b329d5SDavid du Colombier 		if (isalnum(*pcSrc)) {
771*25b329d5SDavid du Colombier 			*pcDest = tolower(*pcSrc);
772*25b329d5SDavid du Colombier 			if (!isdigit(*pcDest)) {
773*25b329d5SDavid du Colombier 				bOnlyDigits = FALSE;
774*25b329d5SDavid du Colombier 			}
775*25b329d5SDavid du Colombier 			pcDest++;
776*25b329d5SDavid du Colombier 		}
777*25b329d5SDavid du Colombier 	}
778*25b329d5SDavid du Colombier 	*pcDest = '\0';
779*25b329d5SDavid du Colombier 	DBG_MSG(szCodesetNorm);
780*25b329d5SDavid du Colombier 	/* Add "iso" when szCodesetNorm contains all digits */
781*25b329d5SDavid du Colombier 	if (bOnlyDigits && szCodesetNorm[0] != '\0') {
782*25b329d5SDavid du Colombier 		fail(strlen(szCodesetNorm) + 3 >= tMaxCodesetLength);
783*25b329d5SDavid du Colombier 		sprintf(szCodeset, "iso%s", szCodesetNorm);
784*25b329d5SDavid du Colombier 	} else {
785*25b329d5SDavid du Colombier 		fail(strlen(szCodesetNorm) >= tMaxCodesetLength);
786*25b329d5SDavid du Colombier 		strncpy(szCodeset, szCodesetNorm, pcDest - szCodesetNorm + 1);
787*25b329d5SDavid du Colombier 		szCodeset[tMaxCodesetLength - 1] = '\0';
788*25b329d5SDavid du Colombier 	}
789*25b329d5SDavid du Colombier 	DBG_MSG(szCodeset);
790*25b329d5SDavid du Colombier 	/* Clean up and leave */
791*25b329d5SDavid du Colombier 	szCodesetNorm = xfree(szCodesetNorm);
792*25b329d5SDavid du Colombier 	szTmp = xfree(szTmp);
793*25b329d5SDavid du Colombier 	return TRUE;
794*25b329d5SDavid du Colombier } /* end of bGetNormalizedCodeset */
795*25b329d5SDavid du Colombier 
796*25b329d5SDavid du Colombier /*
797*25b329d5SDavid du Colombier  * szGetDefaultMappingFile - get the default mapping file
798*25b329d5SDavid du Colombier  *
799*25b329d5SDavid du Colombier  * Returns the basename of the default mapping file
800*25b329d5SDavid du Colombier  */
801*25b329d5SDavid du Colombier const char *
szGetDefaultMappingFile(void)802*25b329d5SDavid du Colombier szGetDefaultMappingFile(void)
803*25b329d5SDavid du Colombier {
804*25b329d5SDavid du Colombier 	static const struct {
805*25b329d5SDavid du Colombier 		const char	*szCodeset;
806*25b329d5SDavid du Colombier 		const char	*szMappingFile;
807*25b329d5SDavid du Colombier 	} atMappingFile[] = {
808*25b329d5SDavid du Colombier 		{ "iso88591",	MAPPING_FILE_8859_1 },
809*25b329d5SDavid du Colombier 		{ "iso88592",	MAPPING_FILE_8859_2 },
810*25b329d5SDavid du Colombier 		{ "iso88593",	"8859-3.txt" },
811*25b329d5SDavid du Colombier 		{ "iso88594",	"8859-4.txt" },
812*25b329d5SDavid du Colombier 		{ "iso88595",	"8859-5.txt" },
813*25b329d5SDavid du Colombier 		{ "iso88596",	MAPPING_FILE_8859_5 },
814*25b329d5SDavid du Colombier 		{ "iso88597",	"8859-7.txt" },
815*25b329d5SDavid du Colombier 		{ "iso88598",	"8859-8.txt" },
816*25b329d5SDavid du Colombier 		{ "iso88599",	"8859-9.txt" },
817*25b329d5SDavid du Colombier 		{ "iso885910",	"8859-10.txt" },
818*25b329d5SDavid du Colombier 		{ "iso885913",	"8859-13.txt" },
819*25b329d5SDavid du Colombier 		{ "iso885914",	"8859-14.txt" },
820*25b329d5SDavid du Colombier 		{ "iso885915",	MAPPING_FILE_8859_15 },
821*25b329d5SDavid du Colombier 		{ "iso885916",	"8859-16.txt" },
822*25b329d5SDavid du Colombier 		{ "koi8r",	MAPPING_FILE_KOI8_R },
823*25b329d5SDavid du Colombier 		{ "koi8u",	MAPPING_FILE_KOI8_U },
824*25b329d5SDavid du Colombier 		{ "utf8",	MAPPING_FILE_UTF_8 },
825*25b329d5SDavid du Colombier 		{ "cp437",	MAPPING_FILE_CP437 },
826*25b329d5SDavid du Colombier 		{ "cp850",	"cp850.txt" },
827*25b329d5SDavid du Colombier 		{ "cp852",	MAPPING_FILE_CP852 },
828*25b329d5SDavid du Colombier 		{ "cp862",	"cp862.txt" },
829*25b329d5SDavid du Colombier 		{ "cp864",	"cp864.txt" },
830*25b329d5SDavid du Colombier 		{ "cp866",	MAPPING_FILE_CP866 },
831*25b329d5SDavid du Colombier 		{ "cp1250",	MAPPING_FILE_CP1250 },
832*25b329d5SDavid du Colombier 		{ "cp1251",	MAPPING_FILE_CP1251 },
833*25b329d5SDavid du Colombier 		{ "cp1252",	"cp1252.txt" },
834*25b329d5SDavid du Colombier 	};
835*25b329d5SDavid du Colombier 	size_t	tIndex;
836*25b329d5SDavid du Colombier 	BOOL	bEuro;
837*25b329d5SDavid du Colombier 	char	szCodeset[20];
838*25b329d5SDavid du Colombier 
839*25b329d5SDavid du Colombier 	szCodeset[0] = '\0';
840*25b329d5SDavid du Colombier 	bEuro = FALSE;
841*25b329d5SDavid du Colombier 	/* Get the normalized codeset name */
842*25b329d5SDavid du Colombier 	if (!bGetNormalizedCodeset(szCodeset, sizeof(szCodeset), &bEuro)) {
843*25b329d5SDavid du Colombier 		return MAPPING_FILE_8859_1;
844*25b329d5SDavid du Colombier 	}
845*25b329d5SDavid du Colombier 	if (szCodeset[0] == '\0') {
846*25b329d5SDavid du Colombier 		if (bEuro) {
847*25b329d5SDavid du Colombier 			/* Default mapping file (with Euro sign) */
848*25b329d5SDavid du Colombier 			return MAPPING_FILE_8859_15;
849*25b329d5SDavid du Colombier 		} else {
850*25b329d5SDavid du Colombier 			/* Default mapping file (without Euro sign) */
851*25b329d5SDavid du Colombier 			return MAPPING_FILE_8859_1;
852*25b329d5SDavid du Colombier 		}
853*25b329d5SDavid du Colombier 	}
854*25b329d5SDavid du Colombier 	/* Find the name in the table */
855*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < elementsof(atMappingFile); tIndex++) {
856*25b329d5SDavid du Colombier 		if (STREQ(atMappingFile[tIndex].szCodeset, szCodeset)) {
857*25b329d5SDavid du Colombier 			return atMappingFile[tIndex].szMappingFile;
858*25b329d5SDavid du Colombier 		}
859*25b329d5SDavid du Colombier 	}
860*25b329d5SDavid du Colombier 	/* Default default mapping file */
861*25b329d5SDavid du Colombier #if defined(__dos)
862*25b329d5SDavid du Colombier 	return MAPPING_FILE_CP437;
863*25b329d5SDavid du Colombier #else
864*25b329d5SDavid du Colombier 	return MAPPING_FILE_8859_1;
865*25b329d5SDavid du Colombier #endif /* __dos */
866*25b329d5SDavid du Colombier } /* end of szGetDefaultMappingFile */
867*25b329d5SDavid du Colombier #endif /* !__riscos */
868*25b329d5SDavid du Colombier 
869*25b329d5SDavid du Colombier /*
870*25b329d5SDavid du Colombier  * tConvertDTTM - convert Windows Date and Time format
871*25b329d5SDavid du Colombier  *
872*25b329d5SDavid du Colombier  * returns Unix time_t or -1
873*25b329d5SDavid du Colombier  */
874*25b329d5SDavid du Colombier time_t
tConvertDTTM(ULONG ulDTTM)875*25b329d5SDavid du Colombier tConvertDTTM(ULONG ulDTTM)
876*25b329d5SDavid du Colombier {
877*25b329d5SDavid du Colombier 	struct tm	tTime;
878*25b329d5SDavid du Colombier 	time_t		tResult;
879*25b329d5SDavid du Colombier 
880*25b329d5SDavid du Colombier 	if (ulDTTM == 0) {
881*25b329d5SDavid du Colombier 		return (time_t)-1;
882*25b329d5SDavid du Colombier 	}
883*25b329d5SDavid du Colombier 	memset(&tTime, 0, sizeof(tTime));
884*25b329d5SDavid du Colombier 	tTime.tm_min = (int)(ulDTTM & 0x0000003f);
885*25b329d5SDavid du Colombier 	tTime.tm_hour = (int)((ulDTTM & 0x000007c0) >> 6);
886*25b329d5SDavid du Colombier 	tTime.tm_mday = (int)((ulDTTM & 0x0000f800) >> 11);
887*25b329d5SDavid du Colombier 	tTime.tm_mon = (int)((ulDTTM & 0x000f0000) >> 16);
888*25b329d5SDavid du Colombier 	tTime.tm_year = (int)((ulDTTM & 0x1ff00000) >> 20);
889*25b329d5SDavid du Colombier 	tTime.tm_isdst = -1;
890*25b329d5SDavid du Colombier 	tTime.tm_mon--;         /* From 01-12 to 00-11 */
891*25b329d5SDavid du Colombier 	tResult = mktime(&tTime);
892*25b329d5SDavid du Colombier 	NO_DBG_MSG(ctime(&tResult));
893*25b329d5SDavid du Colombier 	return tResult;
894*25b329d5SDavid du Colombier } /* end of tConvertDTTM */
895