xref: /plan9-contrib/sys/src/cmd/aux/antiword/stylelist.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * stylelist.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  * Build, read and destroy a list of Word style information
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdlib.h>
10f5736e95SDavid du Colombier #include <stddef.h>
11f5736e95SDavid du Colombier #include <ctype.h>
12f5736e95SDavid du Colombier #include "antiword.h"
13f5736e95SDavid du Colombier 
14f5736e95SDavid du Colombier 
15f5736e95SDavid du Colombier /*
16f5736e95SDavid du Colombier  * Private structure to hide the way the information
17f5736e95SDavid du Colombier  * is stored from the rest of the program
18f5736e95SDavid du Colombier  */
19f5736e95SDavid du Colombier typedef struct style_mem_tag {
20f5736e95SDavid du Colombier 	style_block_type	tInfo;
21f5736e95SDavid du Colombier 	ULONG			ulSequenceNumber;
22f5736e95SDavid du Colombier 	struct style_mem_tag	*pNext;
23f5736e95SDavid du Colombier } style_mem_type;
24f5736e95SDavid du Colombier 
25f5736e95SDavid du Colombier /* Variables needed to write the Style Information List */
26f5736e95SDavid du Colombier static style_mem_type	*pAnchor = NULL;
27f5736e95SDavid du Colombier static style_mem_type	*pStyleLast = NULL;
28f5736e95SDavid du Colombier /* The type of conversion */
29f5736e95SDavid du Colombier static conversion_type	eConversionType = conversion_unknown;
30f5736e95SDavid du Colombier /* The character set encoding */
31f5736e95SDavid du Colombier static encoding_type	eEncoding = encoding_neutral;
32f5736e95SDavid du Colombier /* Values for efficiency reasons */
33f5736e95SDavid du Colombier static const style_mem_type	*pMidPtr = NULL;
34f5736e95SDavid du Colombier static BOOL		bMoveMidPtr = FALSE;
35f5736e95SDavid du Colombier static BOOL		bInSequence = TRUE;
36f5736e95SDavid du Colombier 
37f5736e95SDavid du Colombier 
38f5736e95SDavid du Colombier /*
39f5736e95SDavid du Colombier  * vDestroyStyleInfoList - destroy the Style Information List
40f5736e95SDavid du Colombier  */
41f5736e95SDavid du Colombier void
vDestroyStyleInfoList(void)42f5736e95SDavid du Colombier vDestroyStyleInfoList(void)
43f5736e95SDavid du Colombier {
44f5736e95SDavid du Colombier 	style_mem_type	*pCurr, *pNext;
45f5736e95SDavid du Colombier 
46f5736e95SDavid du Colombier 	DBG_MSG("vDestroyStyleInfoList");
47f5736e95SDavid du Colombier 
48f5736e95SDavid du Colombier 	/* Free the Style Information List */
49f5736e95SDavid du Colombier 	pCurr = pAnchor;
50f5736e95SDavid du Colombier 	while (pCurr != NULL) {
51f5736e95SDavid du Colombier 		pNext = pCurr->pNext;
52f5736e95SDavid du Colombier 		pCurr = xfree(pCurr);
53f5736e95SDavid du Colombier 		pCurr = pNext;
54f5736e95SDavid du Colombier 	}
55f5736e95SDavid du Colombier 	pAnchor = NULL;
56f5736e95SDavid du Colombier 	/* Reset all control variables */
57f5736e95SDavid du Colombier 	pStyleLast = NULL;
58f5736e95SDavid du Colombier 	pMidPtr = NULL;
59f5736e95SDavid du Colombier 	bMoveMidPtr = FALSE;
60f5736e95SDavid du Colombier 	bInSequence = TRUE;
61f5736e95SDavid du Colombier } /* end of vDestroyStyleInfoList */
62f5736e95SDavid du Colombier 
63f5736e95SDavid du Colombier /*
64f5736e95SDavid du Colombier  * vConvertListCharacter - convert the list character
65f5736e95SDavid du Colombier  */
66f5736e95SDavid du Colombier static void
vConvertListCharacter(UCHAR ucNFC,USHORT usListChar,char * szListChar)67f5736e95SDavid du Colombier vConvertListCharacter(UCHAR ucNFC, USHORT usListChar, char *szListChar)
68f5736e95SDavid du Colombier {
69f5736e95SDavid du Colombier 	options_type	tOptions;
70f5736e95SDavid du Colombier 	size_t	tLen;
71f5736e95SDavid du Colombier 
72f5736e95SDavid du Colombier 	fail(szListChar == NULL);
73f5736e95SDavid du Colombier 	fail(szListChar[0] != '\0');
74f5736e95SDavid du Colombier 
75f5736e95SDavid du Colombier 	if (usListChar < 0x80 && isprint((int)usListChar)) {
76f5736e95SDavid du Colombier 		DBG_CHR_C(isalnum((int)usListChar), usListChar);
77f5736e95SDavid du Colombier 		szListChar[0] = (char)usListChar;
78f5736e95SDavid du Colombier 		szListChar[1] = '\0';
79f5736e95SDavid du Colombier 		return;
80f5736e95SDavid du Colombier 	}
81f5736e95SDavid du Colombier 
82*25b329d5SDavid du Colombier 	if (ucNFC != LIST_SPECIAL &&
83*25b329d5SDavid du Colombier 	    ucNFC != LIST_SPECIAL2 &&
84*25b329d5SDavid du Colombier 	    ucNFC != LIST_BULLETS) {
85f5736e95SDavid du Colombier 		szListChar[0] = '.';
86f5736e95SDavid du Colombier 		szListChar[1] = '\0';
87f5736e95SDavid du Colombier 		return;
88f5736e95SDavid du Colombier 	}
89f5736e95SDavid du Colombier 
90f5736e95SDavid du Colombier 	if (eConversionType == conversion_unknown ||
91f5736e95SDavid du Colombier 	    eEncoding == encoding_neutral) {
92f5736e95SDavid du Colombier 		vGetOptions(&tOptions);
93f5736e95SDavid du Colombier 		eConversionType = tOptions.eConversionType;
94f5736e95SDavid du Colombier 		eEncoding = tOptions.eEncoding;
95f5736e95SDavid du Colombier 	}
96f5736e95SDavid du Colombier 
97f5736e95SDavid du Colombier 	switch (usListChar) {
98f5736e95SDavid du Colombier 	case 0x0000: case 0x00b7: case 0x00fe: case  0xf021: case 0xf043:
99*25b329d5SDavid du Colombier 	case 0xf06c: case 0xf093: case 0xf0b7:
100f5736e95SDavid du Colombier 		usListChar = 0x2022;	/* BULLET */
101f5736e95SDavid du Colombier 		break;
102f5736e95SDavid du Colombier 	case 0x0096: case 0xf02d:
103f5736e95SDavid du Colombier 		usListChar = 0x2013;	/* EN DASH */
104f5736e95SDavid du Colombier 		break;
105f5736e95SDavid du Colombier 	case 0x00a8:
106f5736e95SDavid du Colombier 		usListChar = 0x2666;	/* BLACK DIAMOND SUIT */
107f5736e95SDavid du Colombier 		break;
108f5736e95SDavid du Colombier 	case 0x00de:
109f5736e95SDavid du Colombier 		usListChar = 0x21d2;	/* RIGHTWARDS DOUBLE ARROW */
110f5736e95SDavid du Colombier 		break;
111f5736e95SDavid du Colombier 	case 0x00e0: case 0xf074:
112f5736e95SDavid du Colombier 		usListChar = 0x25ca;	/* LOZENGE */
113f5736e95SDavid du Colombier 		break;
114f5736e95SDavid du Colombier 	case 0x00e1:
115f5736e95SDavid du Colombier 		usListChar = 0x2329;	/* LEFT ANGLE BRACKET */
116f5736e95SDavid du Colombier 		break;
117f5736e95SDavid du Colombier 	case 0xf020:
118f5736e95SDavid du Colombier 		usListChar = 0x0020;	/* SPACE */
119f5736e95SDavid du Colombier 		break;
120f5736e95SDavid du Colombier 	case 0xf041:
121f5736e95SDavid du Colombier 		usListChar = 0x270c;	/* VICTORY HAND */
122f5736e95SDavid du Colombier 		break;
123f5736e95SDavid du Colombier 	case 0xf066:
124f5736e95SDavid du Colombier 		usListChar = 0x03d5;	/* GREEK PHI SYMBOL */
125f5736e95SDavid du Colombier 		break;
126f5736e95SDavid du Colombier 	case 0xf06e:
127f5736e95SDavid du Colombier 		usListChar = 0x25a0;	/* BLACK SQUARE */
128f5736e95SDavid du Colombier 		break;
129f5736e95SDavid du Colombier 	case 0xf06f: case 0xf070: case 0xf0a8:
130f5736e95SDavid du Colombier 		usListChar = 0x25a1;	/* WHITE SQUARE */
131f5736e95SDavid du Colombier 		break;
132f5736e95SDavid du Colombier 	case 0xf071:
133f5736e95SDavid du Colombier 		usListChar = 0x2751;	/* LOWER RIGHT SHADOWED WHITE SQUARE */
134f5736e95SDavid du Colombier 		break;
135*25b329d5SDavid du Colombier 	case 0xf075: case 0xf077:
136f5736e95SDavid du Colombier 		usListChar = 0x25c6;	/* BLACK DIAMOND */
137f5736e95SDavid du Colombier 		break;
138f5736e95SDavid du Colombier 	case 0xf076:
139f5736e95SDavid du Colombier 		usListChar = 0x2756;	/* BLACK DIAMOND MINUS WHITE X */
140f5736e95SDavid du Colombier 		break;
141f5736e95SDavid du Colombier 	case 0xf0a7:
142f5736e95SDavid du Colombier 		usListChar = 0x25aa;	/* BLACK SMALL SQUARE */
143f5736e95SDavid du Colombier 		break;
144f5736e95SDavid du Colombier 	case 0xf0d8:
145f5736e95SDavid du Colombier 		usListChar = 0x27a2;	/* RIGHTWARDS ARROWHEAD */
146f5736e95SDavid du Colombier 		break;
147f5736e95SDavid du Colombier 	case 0xf0e5:
148f5736e95SDavid du Colombier 		usListChar = 0x2199;	/* SOUTH WEST ARROW */
149f5736e95SDavid du Colombier 		break;
150f5736e95SDavid du Colombier 	case 0xf0f0:
151f5736e95SDavid du Colombier 		usListChar = 0x21e8;	/* RIGHTWARDS WHITE ARROW */
152f5736e95SDavid du Colombier 		break;
153f5736e95SDavid du Colombier 	case 0xf0fc:
154f5736e95SDavid du Colombier 		usListChar = 0x2713;	/* CHECK MARK */
155f5736e95SDavid du Colombier 		break;
156f5736e95SDavid du Colombier 	default:
157f5736e95SDavid du Colombier 		if ((usListChar >= 0xe000 && usListChar < 0xf900) ||
158f5736e95SDavid du Colombier 		    (usListChar < 0x80 && !isprint((int)usListChar))) {
159f5736e95SDavid du Colombier 			/*
160f5736e95SDavid du Colombier 			 * All remaining private area characters and all
161*25b329d5SDavid du Colombier 			 * remaining non-printable ASCII characters to their
162*25b329d5SDavid du Colombier 			 * default bullet character
163f5736e95SDavid du Colombier 			 */
164f5736e95SDavid du Colombier 			DBG_HEX(usListChar);
165f5736e95SDavid du Colombier 			DBG_FIXME();
166*25b329d5SDavid du Colombier 			if (ucNFC == LIST_SPECIAL || ucNFC == LIST_SPECIAL2) {
167*25b329d5SDavid du Colombier 				usListChar = 0x2190;	/* LEFTWARDS ARROW */
168*25b329d5SDavid du Colombier 			} else {
169f5736e95SDavid du Colombier 				usListChar = 0x2022;	/* BULLET */
170f5736e95SDavid du Colombier 			}
171*25b329d5SDavid du Colombier 		}
172f5736e95SDavid du Colombier 		break;
173f5736e95SDavid du Colombier 	}
174f5736e95SDavid du Colombier 
175*25b329d5SDavid du Colombier 	if (eEncoding == encoding_utf_8) {
176f5736e95SDavid du Colombier 		tLen = tUcs2Utf8(usListChar, szListChar, 4);
177f5736e95SDavid du Colombier 		szListChar[tLen] = '\0';
178f5736e95SDavid du Colombier 	} else {
179f5736e95SDavid du Colombier 		switch (usListChar) {
180f5736e95SDavid du Colombier 		case 0x03d5: case 0x25a1: case 0x25c6: case 0x25ca:
181f5736e95SDavid du Colombier 		case 0x2751:
182f5736e95SDavid du Colombier 			szListChar[0] = 'o';
183f5736e95SDavid du Colombier 			break;
184f5736e95SDavid du Colombier 		case 0x2013: case 0x2500:
185f5736e95SDavid du Colombier 			szListChar[0] = '-';
186f5736e95SDavid du Colombier 			break;
187*25b329d5SDavid du Colombier 		case 0x2190: case 0x2199: case 0x2329:
188f5736e95SDavid du Colombier 			szListChar[0] = '<';
189f5736e95SDavid du Colombier 			break;
190f5736e95SDavid du Colombier 		case 0x21d2:
191f5736e95SDavid du Colombier 			szListChar[0] = '=';
192f5736e95SDavid du Colombier 			break;
193f5736e95SDavid du Colombier 		case 0x21e8: case 0x27a2:
194f5736e95SDavid du Colombier 			szListChar[0] = '>';
195f5736e95SDavid du Colombier 			break;
196f5736e95SDavid du Colombier 		case 0x25a0: case 0x25aa:
197f5736e95SDavid du Colombier 			szListChar[0] = '.';
198f5736e95SDavid du Colombier 			break;
199f5736e95SDavid du Colombier 		case 0x2666:
200f5736e95SDavid du Colombier 			szListChar[0] = OUR_DIAMOND;
201f5736e95SDavid du Colombier 			break;
202f5736e95SDavid du Colombier 		case 0x270c:
203f5736e95SDavid du Colombier 			szListChar[0] = 'x';
204f5736e95SDavid du Colombier 			break;
205f5736e95SDavid du Colombier 		case 0x2713:
206f5736e95SDavid du Colombier 			szListChar[0] = 'V';
207f5736e95SDavid du Colombier 			break;
208f5736e95SDavid du Colombier 		case 0x2756:
209f5736e95SDavid du Colombier 			szListChar[0] = '*';
210f5736e95SDavid du Colombier 			break;
211f5736e95SDavid du Colombier 		case 0x2022:
212f5736e95SDavid du Colombier 		default:
213f5736e95SDavid du Colombier 			vGetBulletValue(eConversionType, eEncoding,
214f5736e95SDavid du Colombier 					szListChar, 2);
215f5736e95SDavid du Colombier 			break;
216f5736e95SDavid du Colombier 		}
217f5736e95SDavid du Colombier 		tLen = 1;
218f5736e95SDavid du Colombier 	}
219f5736e95SDavid du Colombier 	szListChar[tLen] = '\0';
220f5736e95SDavid du Colombier } /* end of vConvertListCharacter */
221f5736e95SDavid du Colombier 
222f5736e95SDavid du Colombier /*
223f5736e95SDavid du Colombier  * eGetNumType - get the level type from the given level number
224f5736e95SDavid du Colombier  *
225f5736e95SDavid du Colombier  * Returns the level type
226f5736e95SDavid du Colombier  */
227f5736e95SDavid du Colombier level_type_enum
eGetNumType(UCHAR ucNumLevel)228f5736e95SDavid du Colombier eGetNumType(UCHAR ucNumLevel)
229f5736e95SDavid du Colombier {
230f5736e95SDavid du Colombier 	switch (ucNumLevel) {
231f5736e95SDavid du Colombier 	case  1: case  2: case  3: case  4: case  5:
232f5736e95SDavid du Colombier 	case  6: case  7: case  8: case  9:
233f5736e95SDavid du Colombier 		return level_type_outline;
234f5736e95SDavid du Colombier 	case 10:
235f5736e95SDavid du Colombier 		return level_type_numbering;
236f5736e95SDavid du Colombier 	case 11:
237f5736e95SDavid du Colombier 		return level_type_sequence;
238f5736e95SDavid du Colombier 	case 12:
239f5736e95SDavid du Colombier 		return level_type_pause;
240f5736e95SDavid du Colombier 	default:
241f5736e95SDavid du Colombier 		return level_type_none;
242f5736e95SDavid du Colombier 	}
243f5736e95SDavid du Colombier } /* end of eGetNumType */
244f5736e95SDavid du Colombier 
245f5736e95SDavid du Colombier /*
246f5736e95SDavid du Colombier  * vCorrectStyleValues - correct style values that Antiword can't use
247f5736e95SDavid du Colombier  */
248f5736e95SDavid du Colombier void
vCorrectStyleValues(style_block_type * pStyleBlock)249f5736e95SDavid du Colombier vCorrectStyleValues(style_block_type *pStyleBlock)
250f5736e95SDavid du Colombier {
251f5736e95SDavid du Colombier 	if (pStyleBlock->usBeforeIndent > 0x7fff) {
252f5736e95SDavid du Colombier 		pStyleBlock->usBeforeIndent = 0;
253f5736e95SDavid du Colombier 	} else if (pStyleBlock->usBeforeIndent > 2160) {
254f5736e95SDavid du Colombier 		/* 2160 twips = 1.5 inches or 38.1 mm */
255f5736e95SDavid du Colombier 		DBG_DEC(pStyleBlock->usBeforeIndent);
256f5736e95SDavid du Colombier 		pStyleBlock->usBeforeIndent = 2160;
257f5736e95SDavid du Colombier 	}
258f5736e95SDavid du Colombier 	if (pStyleBlock->usIstd >= 1 &&
259f5736e95SDavid du Colombier 	    pStyleBlock->usIstd <= 9 &&
260f5736e95SDavid du Colombier 	    pStyleBlock->usBeforeIndent < HEADING_GAP) {
261f5736e95SDavid du Colombier 		NO_DBG_DEC(pStyleBlock->usBeforeIndent);
262f5736e95SDavid du Colombier 		pStyleBlock->usBeforeIndent = HEADING_GAP;
263f5736e95SDavid du Colombier 	}
264f5736e95SDavid du Colombier 
265f5736e95SDavid du Colombier 	if (pStyleBlock->usAfterIndent > 0x7fff) {
266f5736e95SDavid du Colombier 		pStyleBlock->usAfterIndent = 0;
267f5736e95SDavid du Colombier 	} else if (pStyleBlock->usAfterIndent > 2160) {
268f5736e95SDavid du Colombier 		/* 2160 twips = 1.5 inches or 38.1 mm */
269f5736e95SDavid du Colombier 		DBG_DEC(pStyleBlock->usAfterIndent);
270f5736e95SDavid du Colombier 		pStyleBlock->usAfterIndent = 2160;
271f5736e95SDavid du Colombier 	}
272f5736e95SDavid du Colombier 	if (pStyleBlock->usIstd >= 1 &&
273f5736e95SDavid du Colombier 	    pStyleBlock->usIstd <= 9 &&
274f5736e95SDavid du Colombier 	    pStyleBlock->usAfterIndent < HEADING_GAP) {
275f5736e95SDavid du Colombier 		NO_DBG_DEC(pStyleBlock->usAfterIndent);
276f5736e95SDavid du Colombier 		pStyleBlock->usAfterIndent = HEADING_GAP;
277f5736e95SDavid du Colombier 	}
278f5736e95SDavid du Colombier 
279f5736e95SDavid du Colombier 	if (pStyleBlock->sLeftIndent < 0) {
280f5736e95SDavid du Colombier 		pStyleBlock->sLeftIndent = 0;
281f5736e95SDavid du Colombier 	}
282f5736e95SDavid du Colombier 	if (pStyleBlock->sRightIndent > 0) {
283f5736e95SDavid du Colombier 		pStyleBlock->sRightIndent = 0;
284f5736e95SDavid du Colombier 	}
285f5736e95SDavid du Colombier 	vConvertListCharacter(pStyleBlock->ucNFC,
286f5736e95SDavid du Colombier 			pStyleBlock->usListChar,
287f5736e95SDavid du Colombier 			pStyleBlock->szListChar);
288f5736e95SDavid du Colombier } /* end of vCorrectStyleValues */
289f5736e95SDavid du Colombier 
290f5736e95SDavid du Colombier /*
291f5736e95SDavid du Colombier  * vAdd2StyleInfoList - Add an element to the Style Information List
292f5736e95SDavid du Colombier  */
293f5736e95SDavid du Colombier void
vAdd2StyleInfoList(const style_block_type * pStyleBlock)294f5736e95SDavid du Colombier vAdd2StyleInfoList(const style_block_type *pStyleBlock)
295f5736e95SDavid du Colombier {
296f5736e95SDavid du Colombier 	style_mem_type	*pListMember;
297f5736e95SDavid du Colombier 
298f5736e95SDavid du Colombier 	fail(pStyleBlock == NULL);
299f5736e95SDavid du Colombier 
300f5736e95SDavid du Colombier 	NO_DBG_MSG("bAdd2StyleInfoList");
301f5736e95SDavid du Colombier 
302f5736e95SDavid du Colombier 	if (pStyleBlock->ulFileOffset == FC_INVALID) {
303f5736e95SDavid du Colombier 		NO_DBG_DEC(pStyleBlock->usIstd);
304f5736e95SDavid du Colombier 		return;
305f5736e95SDavid du Colombier 	}
306f5736e95SDavid du Colombier 
307f5736e95SDavid du Colombier 	NO_DBG_HEX(pStyleBlock->ulFileOffset);
308f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->sLeftIndent != 0,
309f5736e95SDavid du Colombier 					pStyleBlock->sLeftIndent);
310f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->sRightIndent != 0,
311f5736e95SDavid du Colombier 					pStyleBlock->sRightIndent);
312f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->bNumPause, pStyleBlock->bNumPause);
313f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->usIstd != 0, pStyleBlock->usIstd);
314f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->usStartAt != 1, pStyleBlock->usStartAt);
315f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->usAfterIndent != 0,
316f5736e95SDavid du Colombier 					pStyleBlock->usAfterIndent);
317f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pStyleBlock->ucAlignment != 0, pStyleBlock->ucAlignment);
318f5736e95SDavid du Colombier 	NO_DBG_DEC(pStyleBlock->ucNFC);
319f5736e95SDavid du Colombier 	NO_DBG_HEX(pStyleBlock->usListChar);
320f5736e95SDavid du Colombier 
321f5736e95SDavid du Colombier 	if (pStyleLast != NULL &&
322f5736e95SDavid du Colombier 	    pStyleLast->tInfo.ulFileOffset == pStyleBlock->ulFileOffset) {
323f5736e95SDavid du Colombier 		/*
324f5736e95SDavid du Colombier 		 * If two consecutive styles share the same
325f5736e95SDavid du Colombier 		 * offset, remember only the last style
326f5736e95SDavid du Colombier 		 */
327f5736e95SDavid du Colombier 		fail(pStyleLast->pNext != NULL);
328f5736e95SDavid du Colombier 		pStyleLast->tInfo = *pStyleBlock;
329f5736e95SDavid du Colombier 		/* Correct the values where needed */
330f5736e95SDavid du Colombier 		vCorrectStyleValues(&pStyleLast->tInfo);
331f5736e95SDavid du Colombier 		return;
332f5736e95SDavid du Colombier 	}
333f5736e95SDavid du Colombier 
334f5736e95SDavid du Colombier 	/* Create list member */
335f5736e95SDavid du Colombier 	pListMember = xmalloc(sizeof(style_mem_type));
336f5736e95SDavid du Colombier 	/* Fill the list member */
337f5736e95SDavid du Colombier 	pListMember->tInfo = *pStyleBlock;
338f5736e95SDavid du Colombier 	pListMember->pNext = NULL;
339f5736e95SDavid du Colombier 	/* Add the sequence number */
340f5736e95SDavid du Colombier 	pListMember->ulSequenceNumber =
341f5736e95SDavid du Colombier 			ulGetSeqNumber(pListMember->tInfo.ulFileOffset);
342f5736e95SDavid du Colombier 	/* Correct the values where needed */
343f5736e95SDavid du Colombier 	vCorrectStyleValues(&pListMember->tInfo);
344f5736e95SDavid du Colombier 	/* Add the new member to the list */
345f5736e95SDavid du Colombier 	if (pAnchor == NULL) {
346f5736e95SDavid du Colombier 		pAnchor = pListMember;
347f5736e95SDavid du Colombier 		/* For efficiency */
348f5736e95SDavid du Colombier 		pMidPtr = pAnchor;
349f5736e95SDavid du Colombier 		bMoveMidPtr = FALSE;
350f5736e95SDavid du Colombier 		bInSequence = TRUE;
351f5736e95SDavid du Colombier 	} else {
352f5736e95SDavid du Colombier 		fail(pStyleLast == NULL);
353f5736e95SDavid du Colombier 		pStyleLast->pNext = pListMember;
354f5736e95SDavid du Colombier 		/* For efficiency */
355f5736e95SDavid du Colombier 		if (bMoveMidPtr) {
356f5736e95SDavid du Colombier 			pMidPtr = pMidPtr->pNext;
357f5736e95SDavid du Colombier 			bMoveMidPtr = FALSE;
358f5736e95SDavid du Colombier 		} else {
359f5736e95SDavid du Colombier 			bMoveMidPtr = TRUE;
360f5736e95SDavid du Colombier 		}
361f5736e95SDavid du Colombier 		if (bInSequence) {
362f5736e95SDavid du Colombier 			bInSequence = pListMember->ulSequenceNumber >
363f5736e95SDavid du Colombier 					pStyleLast->ulSequenceNumber;
364f5736e95SDavid du Colombier 		}
365f5736e95SDavid du Colombier 	}
366f5736e95SDavid du Colombier 	pStyleLast = pListMember;
367f5736e95SDavid du Colombier } /* end of vAdd2StyleInfoList */
368f5736e95SDavid du Colombier 
369f5736e95SDavid du Colombier /*
370f5736e95SDavid du Colombier  * Get the record that follows the given recored in the Style Information List
371f5736e95SDavid du Colombier  */
372f5736e95SDavid du Colombier const style_block_type *
pGetNextStyleInfoListItem(const style_block_type * pCurr)373f5736e95SDavid du Colombier pGetNextStyleInfoListItem(const style_block_type *pCurr)
374f5736e95SDavid du Colombier {
375f5736e95SDavid du Colombier 	const style_mem_type	*pRecord;
376f5736e95SDavid du Colombier 	size_t	tOffset;
377f5736e95SDavid du Colombier 
378f5736e95SDavid du Colombier 	if (pCurr == NULL) {
379f5736e95SDavid du Colombier 		if (pAnchor == NULL) {
380f5736e95SDavid du Colombier 			/* There are no records */
381f5736e95SDavid du Colombier 			return NULL;
382f5736e95SDavid du Colombier 		}
383f5736e95SDavid du Colombier 		/* The first record is the only one without a predecessor */
384f5736e95SDavid du Colombier 		return &pAnchor->tInfo;
385f5736e95SDavid du Colombier 	}
386f5736e95SDavid du Colombier 	tOffset = offsetof(style_mem_type, tInfo);
387f5736e95SDavid du Colombier 	/* Many casts to prevent alignment warnings */
388f5736e95SDavid du Colombier 	pRecord = (style_mem_type *)(void *)((char *)pCurr - tOffset);
389f5736e95SDavid du Colombier 	fail(pCurr != &pRecord->tInfo);
390f5736e95SDavid du Colombier 	if (pRecord->pNext == NULL) {
391f5736e95SDavid du Colombier 		/* The last record has no successor */
392f5736e95SDavid du Colombier 		return NULL;
393f5736e95SDavid du Colombier 	}
394f5736e95SDavid du Colombier 	return &pRecord->pNext->tInfo;
395f5736e95SDavid du Colombier } /* end of pGetNextStyleInfoListItem */
396f5736e95SDavid du Colombier 
397f5736e95SDavid du Colombier /*
398*25b329d5SDavid du Colombier  * Get the next text style
399*25b329d5SDavid du Colombier  */
400*25b329d5SDavid du Colombier const style_block_type *
pGetNextTextStyle(const style_block_type * pCurr)401*25b329d5SDavid du Colombier pGetNextTextStyle(const style_block_type *pCurr)
402*25b329d5SDavid du Colombier {
403*25b329d5SDavid du Colombier 	const style_block_type	*pRecord;
404*25b329d5SDavid du Colombier 
405*25b329d5SDavid du Colombier 	pRecord = pCurr;
406*25b329d5SDavid du Colombier 	do {
407*25b329d5SDavid du Colombier 		pRecord = pGetNextStyleInfoListItem(pRecord);
408*25b329d5SDavid du Colombier 	} while (pRecord != NULL &&
409*25b329d5SDavid du Colombier 		 (pRecord->eListID == hdrftr_list ||
410*25b329d5SDavid du Colombier 		  pRecord->eListID == macro_list ||
411*25b329d5SDavid du Colombier 		  pRecord->eListID == annotation_list));
412*25b329d5SDavid du Colombier 	return pRecord;
413*25b329d5SDavid du Colombier } /* end of pGetNextTextStyle */
414*25b329d5SDavid du Colombier 
415*25b329d5SDavid du Colombier /*
416f5736e95SDavid du Colombier  * usGetIstd - get the istd that belongs to the given file offset
417f5736e95SDavid du Colombier  */
418f5736e95SDavid du Colombier USHORT
usGetIstd(ULONG ulFileOffset)419f5736e95SDavid du Colombier usGetIstd(ULONG ulFileOffset)
420f5736e95SDavid du Colombier {
421f5736e95SDavid du Colombier 	const style_mem_type	*pCurr, *pBest, *pStart;
422f5736e95SDavid du Colombier 	ULONG	ulSeq, ulBest;
423f5736e95SDavid du Colombier 
424f5736e95SDavid du Colombier 	ulSeq = ulGetSeqNumber(ulFileOffset);
425f5736e95SDavid du Colombier 	if (ulSeq == FC_INVALID) {
426f5736e95SDavid du Colombier 		return ISTD_NORMAL;
427f5736e95SDavid du Colombier 	}
428f5736e95SDavid du Colombier 	NO_DBG_HEX(ulFileOffset);
429f5736e95SDavid du Colombier 	NO_DBG_DEC(ulSeq);
430f5736e95SDavid du Colombier 
431f5736e95SDavid du Colombier 	if (bInSequence &&
432f5736e95SDavid du Colombier 	    pMidPtr != NULL &&
433f5736e95SDavid du Colombier 	    ulSeq > pMidPtr->ulSequenceNumber) {
434f5736e95SDavid du Colombier 		/* The istd is in the second half of the chained list */
435f5736e95SDavid du Colombier 		pStart = pMidPtr;
436f5736e95SDavid du Colombier 	} else {
437f5736e95SDavid du Colombier 		pStart = pAnchor;
438f5736e95SDavid du Colombier 	}
439f5736e95SDavid du Colombier 
440f5736e95SDavid du Colombier 	pBest = NULL;
441f5736e95SDavid du Colombier 	ulBest = 0;
442f5736e95SDavid du Colombier 	for (pCurr = pStart; pCurr != NULL; pCurr = pCurr->pNext) {
443f5736e95SDavid du Colombier 		if (pCurr->ulSequenceNumber != FC_INVALID &&
444f5736e95SDavid du Colombier 		    (pBest == NULL || pCurr->ulSequenceNumber > ulBest) &&
445f5736e95SDavid du Colombier 		    pCurr->ulSequenceNumber <= ulSeq) {
446f5736e95SDavid du Colombier 			pBest = pCurr;
447f5736e95SDavid du Colombier 			ulBest = pCurr->ulSequenceNumber;
448f5736e95SDavid du Colombier 		}
449f5736e95SDavid du Colombier 		if (bInSequence && pCurr->ulSequenceNumber > ulSeq) {
450f5736e95SDavid du Colombier 			break;
451f5736e95SDavid du Colombier 		}
452f5736e95SDavid du Colombier 	}
453f5736e95SDavid du Colombier 	NO_DBG_DEC(ulBest);
454f5736e95SDavid du Colombier 
455f5736e95SDavid du Colombier 	if (pBest == NULL) {
456f5736e95SDavid du Colombier 		return ISTD_NORMAL;
457f5736e95SDavid du Colombier 	}
458f5736e95SDavid du Colombier 
459f5736e95SDavid du Colombier 	NO_DBG_DEC(pBest->tInfo.usIstd);
460f5736e95SDavid du Colombier 	return pBest->tInfo.usIstd;
461f5736e95SDavid du Colombier } /* end of usGetIstd */
462f5736e95SDavid du Colombier 
463f5736e95SDavid du Colombier /*
464f5736e95SDavid du Colombier  * bStyleImpliesList - does style info implies being part of a list
465f5736e95SDavid du Colombier  *
466f5736e95SDavid du Colombier  * Decide whether the style information implies that the given paragraph is
467f5736e95SDavid du Colombier  * part of a list
468f5736e95SDavid du Colombier  *
469f5736e95SDavid du Colombier  * Returns TRUE when the paragraph is part of a list, otherwise FALSE
470f5736e95SDavid du Colombier  */
471f5736e95SDavid du Colombier BOOL
bStyleImpliesList(const style_block_type * pStyle,int iWordVersion)472f5736e95SDavid du Colombier bStyleImpliesList(const style_block_type *pStyle, int iWordVersion)
473f5736e95SDavid du Colombier {
474f5736e95SDavid du Colombier 	fail(pStyle == NULL);
475f5736e95SDavid du Colombier 	fail(iWordVersion < 0);
476f5736e95SDavid du Colombier 
477f5736e95SDavid du Colombier 	if (pStyle->usIstd >= 1 && pStyle->usIstd <= 9) {
478f5736e95SDavid du Colombier 		/* These are heading levels */
479f5736e95SDavid du Colombier 		return FALSE;
480f5736e95SDavid du Colombier 	}
481f5736e95SDavid du Colombier 	if (iWordVersion < 8) {
482f5736e95SDavid du Colombier 		/* Check for old style lists */
483f5736e95SDavid du Colombier 		return pStyle->ucNumLevel != 0;
484f5736e95SDavid du Colombier 	}
485f5736e95SDavid du Colombier 	/* Check for new style lists */
486f5736e95SDavid du Colombier 	return pStyle->usListIndex != 0;
487f5736e95SDavid du Colombier } /* end of bStyleImpliesList */
488