xref: /plan9/sys/src/cmd/aux/antiword/tabstop.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * tabstops.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Read the tab stop information from a MS Word file
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdio.h>
10f5736e95SDavid du Colombier #include "antiword.h"
11f5736e95SDavid du Colombier 
12f5736e95SDavid du Colombier #define HALF_INCH	36000L	/* In millipoints */
13f5736e95SDavid du Colombier 
14f5736e95SDavid du Colombier static long	lDefaultTabWidth = HALF_INCH;
15f5736e95SDavid du Colombier 
16f5736e95SDavid du Colombier 
17f5736e95SDavid du Colombier /*
18f5736e95SDavid du Colombier  * vSet0DefaultTabWidth -
19f5736e95SDavid du Colombier  */
20f5736e95SDavid du Colombier static void
vSet0DefaultTabWidth(const UCHAR * aucHeader)21f5736e95SDavid du Colombier vSet0DefaultTabWidth(const UCHAR *aucHeader)
22f5736e95SDavid du Colombier {
23f5736e95SDavid du Colombier 	USHORT	usTmp;
24f5736e95SDavid du Colombier 
25f5736e95SDavid du Colombier 	fail(aucHeader == NULL);
26f5736e95SDavid du Colombier 
27f5736e95SDavid du Colombier 	usTmp = usGetWord(0x70, aucHeader); /* dxaTab */
28f5736e95SDavid du Colombier 	DBG_DEC(usTmp);
29f5736e95SDavid du Colombier 	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
30f5736e95SDavid du Colombier 	DBG_DEC(lDefaultTabWidth);
31f5736e95SDavid du Colombier } /* end of vSet0DefaultTabWidth */
32f5736e95SDavid du Colombier 
33f5736e95SDavid du Colombier /*
34f5736e95SDavid du Colombier  * vSet2DefaultTabWidth -
35f5736e95SDavid du Colombier  */
36f5736e95SDavid du Colombier static void
vSet2DefaultTabWidth(FILE * pFile,const UCHAR * aucHeader)37f5736e95SDavid du Colombier vSet2DefaultTabWidth(FILE *pFile, const UCHAR *aucHeader)
38f5736e95SDavid du Colombier {
39f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
40f5736e95SDavid du Colombier 	ULONG	ulBeginDocpInfo;
41f5736e95SDavid du Colombier 	size_t	tDocpInfoLen;
42f5736e95SDavid du Colombier 	USHORT	usTmp;
43f5736e95SDavid du Colombier 
44f5736e95SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
45f5736e95SDavid du Colombier 
46f5736e95SDavid du Colombier 	ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
47f5736e95SDavid du Colombier 	DBG_HEX(ulBeginDocpInfo);
48f5736e95SDavid du Colombier 	tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
49f5736e95SDavid du Colombier 	DBG_DEC(tDocpInfoLen);
50f5736e95SDavid du Colombier 	if (tDocpInfoLen < 12) {
51f5736e95SDavid du Colombier 		DBG_MSG("No TAB information");
52f5736e95SDavid du Colombier 		return;
53f5736e95SDavid du Colombier 	}
54f5736e95SDavid du Colombier 
55f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tDocpInfoLen);
56f5736e95SDavid du Colombier 	if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
57f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
58f5736e95SDavid du Colombier 		return;
59f5736e95SDavid du Colombier 	}
60f5736e95SDavid du Colombier 	usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
61f5736e95SDavid du Colombier 	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
62f5736e95SDavid du Colombier 	DBG_DEC(lDefaultTabWidth);
63f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
64f5736e95SDavid du Colombier } /* end of vSet2DefaultTabWidth */
65f5736e95SDavid du Colombier 
66f5736e95SDavid du Colombier /*
67f5736e95SDavid du Colombier  * vSet6DefaultTabWidth -
68f5736e95SDavid du Colombier  */
69f5736e95SDavid du Colombier static void
vSet6DefaultTabWidth(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)70f5736e95SDavid du Colombier vSet6DefaultTabWidth(FILE *pFile, ULONG ulStartBlock,
71f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
72f5736e95SDavid du Colombier {
73f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
74f5736e95SDavid du Colombier 	ULONG	ulBeginDocpInfo;
75f5736e95SDavid du Colombier 	size_t	tDocpInfoLen;
76f5736e95SDavid du Colombier 	USHORT	usTmp;
77f5736e95SDavid du Colombier 
78f5736e95SDavid du Colombier 	ulBeginDocpInfo = ulGetLong(0x150, aucHeader); /* fcDop */
79f5736e95SDavid du Colombier 	DBG_HEX(ulBeginDocpInfo);
80f5736e95SDavid du Colombier 	tDocpInfoLen = (size_t)ulGetLong(0x154, aucHeader); /* lcbDop */
81f5736e95SDavid du Colombier 	DBG_DEC(tDocpInfoLen);
82f5736e95SDavid du Colombier 	if (tDocpInfoLen < 12) {
83f5736e95SDavid du Colombier 		DBG_MSG("No TAB information");
84f5736e95SDavid du Colombier 		return;
85f5736e95SDavid du Colombier 	}
86f5736e95SDavid du Colombier 
87f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tDocpInfoLen);
88f5736e95SDavid du Colombier 	if (!bReadBuffer(pFile, ulStartBlock,
89f5736e95SDavid du Colombier 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
90f5736e95SDavid du Colombier 			aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
91f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
92f5736e95SDavid du Colombier 		return;
93f5736e95SDavid du Colombier 	}
94f5736e95SDavid du Colombier 	usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
95f5736e95SDavid du Colombier 	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
96f5736e95SDavid du Colombier 	DBG_DEC(lDefaultTabWidth);
97f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
98f5736e95SDavid du Colombier } /* end of vSet6DefaultTabWidth */
99f5736e95SDavid du Colombier 
100f5736e95SDavid du Colombier /*
101f5736e95SDavid du Colombier  * vSet8DefaultTabWidth -
102f5736e95SDavid du Colombier  */
103f5736e95SDavid du Colombier static void
vSet8DefaultTabWidth(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)104f5736e95SDavid du Colombier vSet8DefaultTabWidth(FILE *pFile, const pps_info_type *pPPS,
105f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
106f5736e95SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
107f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
108f5736e95SDavid du Colombier {
109f5736e95SDavid du Colombier         const ULONG	*aulBlockDepot;
110f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
111f5736e95SDavid du Colombier 	ULONG	ulBeginDocpInfo;
112f5736e95SDavid du Colombier 	size_t	tDocpInfoLen, tBlockDepotLen, tBlockSize;
113*25b329d5SDavid du Colombier 	USHORT	usTmp;
114f5736e95SDavid du Colombier 
115f5736e95SDavid du Colombier 	ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
116f5736e95SDavid du Colombier 	DBG_HEX(ulBeginDocpInfo);
117f5736e95SDavid du Colombier 	tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
118f5736e95SDavid du Colombier 	DBG_DEC(tDocpInfoLen);
119f5736e95SDavid du Colombier 	if (tDocpInfoLen < 12) {
120f5736e95SDavid du Colombier 		DBG_MSG("No TAB information");
121f5736e95SDavid du Colombier 		return;
122f5736e95SDavid du Colombier 	}
123f5736e95SDavid du Colombier 
124*25b329d5SDavid du Colombier 	DBG_DEC(pPPS->tTable.ulSB);
125*25b329d5SDavid du Colombier 	DBG_HEX(pPPS->tTable.ulSize);
126*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize == 0) {
127f5736e95SDavid du Colombier 		DBG_MSG("No TAB information");
128f5736e95SDavid du Colombier 		return;
129f5736e95SDavid du Colombier 	}
130*25b329d5SDavid du Colombier 
131*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
132f5736e95SDavid du Colombier 		/* Use the Small Block Depot */
133f5736e95SDavid du Colombier 		aulBlockDepot = aulSBD;
134f5736e95SDavid du Colombier 		tBlockDepotLen = tSBDLen;
135f5736e95SDavid du Colombier 		tBlockSize = SMALL_BLOCK_SIZE;
136f5736e95SDavid du Colombier 	} else {
137f5736e95SDavid du Colombier 		/* Use the Big Block Depot */
138f5736e95SDavid du Colombier 		aulBlockDepot = aulBBD;
139f5736e95SDavid du Colombier 		tBlockDepotLen = tBBDLen;
140f5736e95SDavid du Colombier 		tBlockSize = BIG_BLOCK_SIZE;
141f5736e95SDavid du Colombier 	}
142f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tDocpInfoLen);
143*25b329d5SDavid du Colombier 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
144f5736e95SDavid du Colombier 			aulBlockDepot, tBlockDepotLen, tBlockSize,
145f5736e95SDavid du Colombier 			aucBuffer, ulBeginDocpInfo, tDocpInfoLen)) {
146f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
147f5736e95SDavid du Colombier 		return;
148f5736e95SDavid du Colombier 	}
149f5736e95SDavid du Colombier 	usTmp = usGetWord(0x0a, aucBuffer); /* dxaTab */
150f5736e95SDavid du Colombier 	lDefaultTabWidth = usTmp == 0 ? HALF_INCH : lTwips2MilliPoints(usTmp);
151f5736e95SDavid du Colombier 	DBG_DEC(lDefaultTabWidth);
152f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
153f5736e95SDavid du Colombier } /* end of vSet8DefaultTabWidth */
154f5736e95SDavid du Colombier 
155f5736e95SDavid du Colombier /*
156f5736e95SDavid du Colombier  * vSetDefaultTabWidth -
157f5736e95SDavid du Colombier  */
158f5736e95SDavid du Colombier void
vSetDefaultTabWidth(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader,int iWordVersion)159f5736e95SDavid du Colombier vSetDefaultTabWidth(FILE *pFile, const pps_info_type *pPPS,
160f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
161f5736e95SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
162f5736e95SDavid du Colombier 	const UCHAR *aucHeader, int iWordVersion)
163f5736e95SDavid du Colombier {
164f5736e95SDavid du Colombier 	fail(pFile == NULL && iWordVersion >= 1);
165f5736e95SDavid du Colombier 	fail(pPPS == NULL && iWordVersion >= 6);
166f5736e95SDavid du Colombier 	fail(aulBBD == NULL && tBBDLen != 0);
167f5736e95SDavid du Colombier 	fail(aulSBD == NULL && tSBDLen != 0);
168f5736e95SDavid du Colombier 	fail(aucHeader == NULL);
169f5736e95SDavid du Colombier 
170f5736e95SDavid du Colombier 	/* Reset to the default default value */
171f5736e95SDavid du Colombier 	lDefaultTabWidth = HALF_INCH;
172f5736e95SDavid du Colombier 
173f5736e95SDavid du Colombier 	switch (iWordVersion) {
174f5736e95SDavid du Colombier 	case 0:
175f5736e95SDavid du Colombier 		vSet0DefaultTabWidth(aucHeader);
176f5736e95SDavid du Colombier 		break;
177f5736e95SDavid du Colombier 	case 1:
178f5736e95SDavid du Colombier 	case 2:
179f5736e95SDavid du Colombier 		vSet2DefaultTabWidth(pFile, aucHeader);
180f5736e95SDavid du Colombier 		break;
181f5736e95SDavid du Colombier 	case 4:
182f5736e95SDavid du Colombier 	case 5:
183f5736e95SDavid du Colombier 		break;
184f5736e95SDavid du Colombier 	case 6:
185f5736e95SDavid du Colombier 	case 7:
186f5736e95SDavid du Colombier 		vSet6DefaultTabWidth(pFile, pPPS->tWordDocument.ulSB,
187f5736e95SDavid du Colombier 				aulBBD, tBBDLen, aucHeader);
188f5736e95SDavid du Colombier 		break;
189f5736e95SDavid du Colombier 	case 8:
190f5736e95SDavid du Colombier 		vSet8DefaultTabWidth(pFile, pPPS,
191f5736e95SDavid du Colombier 				aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
192f5736e95SDavid du Colombier 		break;
193f5736e95SDavid du Colombier 	default:
194f5736e95SDavid du Colombier 		werr(0, "Sorry, no TAB information");
195f5736e95SDavid du Colombier 		break;
196f5736e95SDavid du Colombier 	}
197f5736e95SDavid du Colombier } /* end of vSetDefaultTabWidth */
198f5736e95SDavid du Colombier 
199*25b329d5SDavid du Colombier #if 0
200f5736e95SDavid du Colombier /*
201f5736e95SDavid du Colombier  * lGetDefaultTabWidth - Get the default tabwidth in millipoints
202f5736e95SDavid du Colombier  */
203f5736e95SDavid du Colombier long
204f5736e95SDavid du Colombier lGetDefaultTabWidth(void)
205f5736e95SDavid du Colombier {
206f5736e95SDavid du Colombier 	if (lDefaultTabWidth <= 0) {
207f5736e95SDavid du Colombier 		DBG_DEC(lDefaultTabWidth);
208f5736e95SDavid du Colombier 		return lTwips2MilliPoints(1);
209f5736e95SDavid du Colombier 	}
210f5736e95SDavid du Colombier 	return lDefaultTabWidth;
211f5736e95SDavid du Colombier } /* end of lGetDefaultTabWidth */
212*25b329d5SDavid du Colombier #endif
213