xref: /plan9/sys/src/cmd/aux/antiword/xml.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * xml.c
3*25b329d5SDavid du Colombier  * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Functions to deal with the XML/DocBook format
7f5736e95SDavid du Colombier  *
8f5736e95SDavid du Colombier  */
9f5736e95SDavid du Colombier 
10f5736e95SDavid du Colombier #include <string.h>
11f5736e95SDavid du Colombier #include "antiword.h"
12f5736e95SDavid du Colombier 
13f5736e95SDavid du Colombier 
14f5736e95SDavid du Colombier #define vAddEndTagsUntil1(p,t)	vAddEndTagsUntil2(p,t,TAG_NOTAG)
15f5736e95SDavid du Colombier 
16f5736e95SDavid du Colombier #if defined(DEBUG)
17f5736e95SDavid du Colombier #define vStackTrace()	__vStackTrace(__LINE__)
18f5736e95SDavid du Colombier #else
19f5736e95SDavid du Colombier #define vStackTrace()	/* EMPTY */
20f5736e95SDavid du Colombier #endif /* DEBUG */
21f5736e95SDavid du Colombier 
22*25b329d5SDavid du Colombier /* The character set */
23*25b329d5SDavid du Colombier static encoding_type	eEncoding = encoding_neutral;
24*25b329d5SDavid du Colombier /* Word version */
25*25b329d5SDavid du Colombier static int	iWordVersion = -1;
26*25b329d5SDavid du Colombier /* Special treatment for files from Word 4/5/6 on an Apple Macintosh */
27*25b329d5SDavid du Colombier static BOOL	bOldMacFile = FALSE;
28f5736e95SDavid du Colombier /* Text is emphasised */
29f5736e95SDavid du Colombier static BOOL	bEmphasisOpen = FALSE;
30f5736e95SDavid du Colombier /* Text is superscript */
31f5736e95SDavid du Colombier static BOOL	bSuperscriptOpen = FALSE;
32f5736e95SDavid du Colombier /* Text is subscript */
33f5736e95SDavid du Colombier static BOOL	bSubscriptOpen = FALSE;
34f5736e95SDavid du Colombier /* Title is open */
35f5736e95SDavid du Colombier static BOOL	bTitleOpen = FALSE;
36f5736e95SDavid du Colombier /* Table is open */
37f5736e95SDavid du Colombier static BOOL	bTableOpen = FALSE;
38*25b329d5SDavid du Colombier /* Footnote is open */
39*25b329d5SDavid du Colombier static BOOL	bFootnoteOpen = FALSE;
40f5736e95SDavid du Colombier /* Current paragraph level */
41f5736e95SDavid du Colombier static UINT	uiParagraphLevel = 0;
42f5736e95SDavid du Colombier /* Current list level */
43f5736e95SDavid du Colombier static UINT	uiListLevel = 0;
44f5736e95SDavid du Colombier /* Current list level is still empty */
45f5736e95SDavid du Colombier static BOOL	bEmptyListLevel = TRUE;
46f5736e95SDavid du Colombier /* Current header level */
47f5736e95SDavid du Colombier static USHORT	usHeaderLevelCurrent = 0;
48f5736e95SDavid du Colombier /* Current header level is still empty */
49f5736e95SDavid du Colombier static BOOL	bEmptyHeaderLevel = TRUE;
50f5736e95SDavid du Colombier /* Number of columns in the current table */
51f5736e95SDavid du Colombier static int	iTableColumnsCurrent = 0;
52*25b329d5SDavid du Colombier /* Footnote number */
53*25b329d5SDavid du Colombier static UINT	uiFootnoteNumber = 0;
54f5736e95SDavid du Colombier 
55f5736e95SDavid du Colombier /* Constants for the stack */
56f5736e95SDavid du Colombier #define INITIAL_STACK_SIZE	10
57f5736e95SDavid du Colombier #if defined(DEBUG)
58f5736e95SDavid du Colombier #define EXTENSION_STACK_SIZE	 2
59f5736e95SDavid du Colombier #else
60f5736e95SDavid du Colombier #define EXTENSION_STACK_SIZE	10
61f5736e95SDavid du Colombier #endif /* DEBUG */
62f5736e95SDavid du Colombier 
63f5736e95SDavid du Colombier /* Variables for the stack */
64f5736e95SDavid du Colombier static UCHAR	*aucStack = NULL;
65f5736e95SDavid du Colombier static size_t	tStacksize = 0;
66f5736e95SDavid du Colombier static size_t	tStackNextFree = 0;
67f5736e95SDavid du Colombier 
68f5736e95SDavid du Colombier /* Constants for the tags */
69f5736e95SDavid du Colombier #define TAG_NOTAG		(UCHAR)0
70f5736e95SDavid du Colombier #define TAG_AUTHOR		(UCHAR)1
71f5736e95SDavid du Colombier #define TAG_BEGINPAGE		(UCHAR)2
72f5736e95SDavid du Colombier #define TAG_BOOK		(UCHAR)3
73f5736e95SDavid du Colombier #define TAG_BOOKINFO		(UCHAR)4
74f5736e95SDavid du Colombier #define TAG_CHAPTER		(UCHAR)5
75f5736e95SDavid du Colombier #define TAG_COLSPEC		(UCHAR)6
76f5736e95SDavid du Colombier #define TAG_CORPNAME		(UCHAR)7
77f5736e95SDavid du Colombier #define TAG_DATE		(UCHAR)8
78f5736e95SDavid du Colombier #define TAG_EMPHASIS		(UCHAR)9
79f5736e95SDavid du Colombier #define TAG_ENTRY		(UCHAR)10
80f5736e95SDavid du Colombier #define TAG_FILENAME		(UCHAR)11
81*25b329d5SDavid du Colombier #define TAG_FOOTNOTE		(UCHAR)12
82*25b329d5SDavid du Colombier #define TAG_INFORMALTABLE	(UCHAR)13
83*25b329d5SDavid du Colombier #define TAG_ITEMIZEDLIST	(UCHAR)14
84*25b329d5SDavid du Colombier #define TAG_LISTITEM		(UCHAR)15
85*25b329d5SDavid du Colombier #define TAG_ORDEREDLIST		(UCHAR)16
86*25b329d5SDavid du Colombier #define TAG_PARA		(UCHAR)17
87*25b329d5SDavid du Colombier #define TAG_ROW			(UCHAR)18
88*25b329d5SDavid du Colombier #define TAG_SECT1		(UCHAR)19
89*25b329d5SDavid du Colombier #define TAG_SECT2		(UCHAR)20
90*25b329d5SDavid du Colombier #define TAG_SECT3		(UCHAR)21
91*25b329d5SDavid du Colombier #define TAG_SECT4		(UCHAR)22
92*25b329d5SDavid du Colombier #define TAG_SECT5		(UCHAR)23
93*25b329d5SDavid du Colombier #define TAG_SUBSCRIPT		(UCHAR)24
94*25b329d5SDavid du Colombier #define TAG_SUBTITLE		(UCHAR)25
95*25b329d5SDavid du Colombier #define TAG_SUPERSCRIPT		(UCHAR)26
96*25b329d5SDavid du Colombier #define TAG_SURNAME		(UCHAR)27
97*25b329d5SDavid du Colombier #define TAG_TBODY		(UCHAR)28
98*25b329d5SDavid du Colombier #define TAG_TGROUP		(UCHAR)29
99*25b329d5SDavid du Colombier #define TAG_TITLE		(UCHAR)30
100f5736e95SDavid du Colombier 
101f5736e95SDavid du Colombier typedef struct docbooktags_tag {
102f5736e95SDavid du Colombier 	UCHAR	ucTagnumber;
103f5736e95SDavid du Colombier 	char	szTagname[15];
104*25b329d5SDavid du Colombier 	BOOL	bAddNewlineStart;
105*25b329d5SDavid du Colombier 	BOOL	bAddNewlineEnd;
106f5736e95SDavid du Colombier } docbooktags_type;
107f5736e95SDavid du Colombier 
108f5736e95SDavid du Colombier static const docbooktags_type atDocBookTags[] = {
109*25b329d5SDavid du Colombier 	{	TAG_NOTAG, 		"!ERROR!",	TRUE,	TRUE	},
110*25b329d5SDavid du Colombier 	{	TAG_AUTHOR,		"author",	TRUE,	TRUE	},
111*25b329d5SDavid du Colombier 	{	TAG_BEGINPAGE,		"beginpage",	TRUE,	TRUE	},
112*25b329d5SDavid du Colombier 	{	TAG_BOOK, 		"book",		TRUE,	TRUE	},
113*25b329d5SDavid du Colombier 	{	TAG_BOOKINFO, 		"bookinfo",	TRUE,	TRUE	},
114*25b329d5SDavid du Colombier 	{	TAG_CHAPTER, 		"chapter",	TRUE,	TRUE	},
115*25b329d5SDavid du Colombier 	{	TAG_COLSPEC,		"colspec",	TRUE,	TRUE	},
116*25b329d5SDavid du Colombier 	{	TAG_CORPNAME,		"corpname",	FALSE,	FALSE	},
117*25b329d5SDavid du Colombier 	{	TAG_DATE,		"date",		FALSE,	FALSE	},
118*25b329d5SDavid du Colombier 	{	TAG_EMPHASIS,		"emphasis",	FALSE,	FALSE	},
119*25b329d5SDavid du Colombier 	{	TAG_ENTRY,		"entry",	TRUE,	TRUE	},
120*25b329d5SDavid du Colombier 	{	TAG_FILENAME,		"filename",	FALSE,	FALSE	},
121*25b329d5SDavid du Colombier 	{	TAG_FOOTNOTE,		"footnote",	FALSE,	FALSE	},
122*25b329d5SDavid du Colombier 	{	TAG_INFORMALTABLE,	"informaltable",TRUE,	TRUE	},
123*25b329d5SDavid du Colombier 	{	TAG_ITEMIZEDLIST,	"itemizedlist",	TRUE,	TRUE	},
124*25b329d5SDavid du Colombier 	{	TAG_LISTITEM,		"listitem",	TRUE,	TRUE	},
125*25b329d5SDavid du Colombier 	{	TAG_ORDEREDLIST,	"orderedlist",	TRUE,	TRUE	},
126*25b329d5SDavid du Colombier 	{	TAG_PARA, 		"para",		TRUE,	TRUE	},
127*25b329d5SDavid du Colombier 	{	TAG_ROW,		"row",		TRUE,	TRUE	},
128*25b329d5SDavid du Colombier 	{	TAG_SECT1, 		"sect1",	TRUE,	TRUE	},
129*25b329d5SDavid du Colombier 	{	TAG_SECT2, 		"sect2",	TRUE,	TRUE	},
130*25b329d5SDavid du Colombier 	{	TAG_SECT3, 		"sect3",	TRUE,	TRUE	},
131*25b329d5SDavid du Colombier 	{	TAG_SECT4, 		"sect4",	TRUE,	TRUE	},
132*25b329d5SDavid du Colombier 	{	TAG_SECT5, 		"sect5",	TRUE,	TRUE	},
133*25b329d5SDavid du Colombier 	{	TAG_SUBSCRIPT,		"subscript",	FALSE,	FALSE	},
134*25b329d5SDavid du Colombier 	{	TAG_SUBTITLE,		"subtitle",	FALSE,	FALSE	},
135*25b329d5SDavid du Colombier 	{	TAG_SUPERSCRIPT,	"superscript",	FALSE,	FALSE	},
136*25b329d5SDavid du Colombier 	{	TAG_SURNAME,		"surname",	FALSE,	FALSE	},
137*25b329d5SDavid du Colombier 	{	TAG_TBODY,		"tbody",	TRUE,	TRUE	},
138*25b329d5SDavid du Colombier 	{	TAG_TGROUP,		"tgroup",	TRUE,	TRUE	},
139*25b329d5SDavid du Colombier 	{	TAG_TITLE, 		"title",	FALSE,	FALSE	},
140f5736e95SDavid du Colombier };
141f5736e95SDavid du Colombier 
142*25b329d5SDavid du Colombier static void	vAddStartTag(diagram_type *, UCHAR, const char *);
143*25b329d5SDavid du Colombier static void	vAddEndTag(diagram_type *, UCHAR);
144*25b329d5SDavid du Colombier static void	vAddCombinedTag(diagram_type *, UCHAR, const char *);
145*25b329d5SDavid du Colombier static void	vPrintChar(diagram_type *, char);
146*25b329d5SDavid du Colombier 
147f5736e95SDavid du Colombier 
148f5736e95SDavid du Colombier #if defined(DEBUG)
149f5736e95SDavid du Colombier /*
150f5736e95SDavid du Colombier  * vCheckTagTable - check the tag table
151f5736e95SDavid du Colombier  */
152f5736e95SDavid du Colombier static void
vCheckTagTable(void)153f5736e95SDavid du Colombier vCheckTagTable(void)
154f5736e95SDavid du Colombier {
155f5736e95SDavid du Colombier 	size_t	tIndex;
156f5736e95SDavid du Colombier 
157f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < elementsof(atDocBookTags); tIndex++) {
158f5736e95SDavid du Colombier 		if (tIndex != (size_t)atDocBookTags[tIndex].ucTagnumber) {
159f5736e95SDavid du Colombier 			DBG_DEC(tIndex);
160f5736e95SDavid du Colombier 			werr(1, "Array atDocBookTags is broken");
161f5736e95SDavid du Colombier 		}
162f5736e95SDavid du Colombier 	}
163f5736e95SDavid du Colombier } /* end of vCheckTagTable */
164f5736e95SDavid du Colombier 
165f5736e95SDavid du Colombier /*
166f5736e95SDavid du Colombier  * __vStackTrace - show a stack trace
167f5736e95SDavid du Colombier  */
168f5736e95SDavid du Colombier static void
__vStackTrace(int iLine)169f5736e95SDavid du Colombier __vStackTrace(int iLine)
170f5736e95SDavid du Colombier {
171f5736e95SDavid du Colombier 	int	iIndex;
172f5736e95SDavid du Colombier 
173f5736e95SDavid du Colombier 	fprintf(stderr, "%s[%3d]:\n", __FILE__, iLine);
174f5736e95SDavid du Colombier 
175f5736e95SDavid du Colombier 	if (tStackNextFree == 0) {
176f5736e95SDavid du Colombier 		fprintf(stderr, "The stack is empty\n");
177f5736e95SDavid du Colombier 		return;
178f5736e95SDavid du Colombier 	}
179f5736e95SDavid du Colombier 	for (iIndex = (int)tStackNextFree - 1; iIndex >= 0; iIndex--) {
180f5736e95SDavid du Colombier 		fprintf(stderr, "%2d: %2d: '%s'\n",
181f5736e95SDavid du Colombier 			iIndex,
182f5736e95SDavid du Colombier 			(int)atDocBookTags[(UINT)aucStack[iIndex]].ucTagnumber,
183f5736e95SDavid du Colombier 			atDocBookTags[(UINT)aucStack[iIndex]].szTagname);
184f5736e95SDavid du Colombier 	}
185f5736e95SDavid du Colombier } /* end of __vStackTrace */
186f5736e95SDavid du Colombier #endif /* DEBUG */
187f5736e95SDavid du Colombier 
188f5736e95SDavid du Colombier /*
189f5736e95SDavid du Colombier  * vPushStack - push a tag onto the stack
190f5736e95SDavid du Colombier  */
191f5736e95SDavid du Colombier static void
vPushStack(UCHAR ucTag)192f5736e95SDavid du Colombier vPushStack(UCHAR ucTag)
193f5736e95SDavid du Colombier {
194f5736e95SDavid du Colombier 	fail(tStackNextFree > tStacksize);
195f5736e95SDavid du Colombier 
196f5736e95SDavid du Colombier 	if (tStackNextFree == tStacksize) {
197f5736e95SDavid du Colombier 		/* The stack is full; enlarge the stack */
198f5736e95SDavid du Colombier 		tStacksize += EXTENSION_STACK_SIZE;
199f5736e95SDavid du Colombier 		aucStack = xrealloc(aucStack, tStacksize * sizeof(UCHAR));
200f5736e95SDavid du Colombier 		DBG_DEC(tStacksize);
201f5736e95SDavid du Colombier 	}
202f5736e95SDavid du Colombier 
203f5736e95SDavid du Colombier 	fail(tStackNextFree >= tStacksize);
204f5736e95SDavid du Colombier 
205f5736e95SDavid du Colombier 	aucStack[tStackNextFree++] = ucTag;
206f5736e95SDavid du Colombier } /* end of vPushStack */
207f5736e95SDavid du Colombier 
208f5736e95SDavid du Colombier /*
209f5736e95SDavid du Colombier  * vPopStack - pop a tag from the stack
210f5736e95SDavid du Colombier  */
211f5736e95SDavid du Colombier static UCHAR
ucPopStack(void)212f5736e95SDavid du Colombier ucPopStack(void)
213f5736e95SDavid du Colombier {
214f5736e95SDavid du Colombier 	DBG_DEC_C(tStackNextFree > tStacksize, tStackNextFree);
215f5736e95SDavid du Colombier 	DBG_DEC_C(tStackNextFree > tStacksize, tStacksize);
216f5736e95SDavid du Colombier 	fail(tStackNextFree > tStacksize);
217f5736e95SDavid du Colombier 	fail(tStackNextFree == 0);
218f5736e95SDavid du Colombier 
219f5736e95SDavid du Colombier 	if (tStackNextFree == 0) {
220f5736e95SDavid du Colombier 		werr(1, "The stack is empty, unable to continue");
221f5736e95SDavid du Colombier 		return TAG_NOTAG;
222f5736e95SDavid du Colombier 	}
223f5736e95SDavid du Colombier 	return aucStack[--tStackNextFree];
224f5736e95SDavid du Colombier } /* end of ucPopStack */
225f5736e95SDavid du Colombier 
226f5736e95SDavid du Colombier /*
227f5736e95SDavid du Colombier  * vReadStack - read a tag from the top of the stack
228f5736e95SDavid du Colombier  */
229f5736e95SDavid du Colombier static UCHAR
ucReadStack(void)230f5736e95SDavid du Colombier ucReadStack(void)
231f5736e95SDavid du Colombier {
232f5736e95SDavid du Colombier 	DBG_DEC_C(tStackNextFree > tStacksize, tStackNextFree);
233f5736e95SDavid du Colombier 	DBG_DEC_C(tStackNextFree > tStacksize, tStacksize);
234f5736e95SDavid du Colombier 	fail(tStackNextFree > tStacksize);
235f5736e95SDavid du Colombier 
236f5736e95SDavid du Colombier 	if (tStackNextFree == 0) {
237f5736e95SDavid du Colombier 		/* The stack is empty */
238f5736e95SDavid du Colombier 		return TAG_NOTAG;
239f5736e95SDavid du Colombier 	}
240f5736e95SDavid du Colombier 	return aucStack[tStackNextFree - 1];
241f5736e95SDavid du Colombier } /* end of ucReadStack */
242f5736e95SDavid du Colombier 
243f5736e95SDavid du Colombier /*
244f5736e95SDavid du Colombier  * vPrintLevel - print the tag level
245f5736e95SDavid du Colombier  */
246f5736e95SDavid du Colombier static void
vPrintLevel(FILE * pOutFile)247f5736e95SDavid du Colombier vPrintLevel(FILE *pOutFile)
248f5736e95SDavid du Colombier {
249f5736e95SDavid du Colombier 	size_t	tIndex;
250f5736e95SDavid du Colombier 
251f5736e95SDavid du Colombier 	fail(pOutFile == NULL);
252f5736e95SDavid du Colombier 
253f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < tStackNextFree; tIndex++) {
254f5736e95SDavid du Colombier 		(void)putc(' ', pOutFile);
255f5736e95SDavid du Colombier 	}
256f5736e95SDavid du Colombier } /* end of vPrintLevel */
257f5736e95SDavid du Colombier 
258f5736e95SDavid du Colombier /*
259*25b329d5SDavid du Colombier  * vPrintFootnote - print a footnote
260*25b329d5SDavid du Colombier  */
261*25b329d5SDavid du Colombier static void
vPrintFootnote(diagram_type * pDiag,UINT uiFootnoteIndex)262*25b329d5SDavid du Colombier vPrintFootnote(diagram_type *pDiag, UINT uiFootnoteIndex)
263*25b329d5SDavid du Colombier {
264*25b329d5SDavid du Colombier 	const char	*szText, *pcTmp;
265*25b329d5SDavid du Colombier 	BOOL	bSuScript;
266*25b329d5SDavid du Colombier 	UCHAR	ucTopTag;
267*25b329d5SDavid du Colombier 
268*25b329d5SDavid du Colombier 	TRACE_MSG("vPrintFootnote");
269*25b329d5SDavid du Colombier 
270*25b329d5SDavid du Colombier 	szText = szGetFootnootText(uiFootnoteIndex);
271*25b329d5SDavid du Colombier 
272*25b329d5SDavid du Colombier 	if (szText == NULL) {
273*25b329d5SDavid du Colombier 		szText = "";
274*25b329d5SDavid du Colombier 	}
275*25b329d5SDavid du Colombier 
276*25b329d5SDavid du Colombier 	/* Remove the subscript/superscript (if any) */
277*25b329d5SDavid du Colombier 	ucTopTag = ucReadStack();
278*25b329d5SDavid du Colombier 	bSuScript = ucTopTag == TAG_SUBSCRIPT || ucTopTag == TAG_SUPERSCRIPT;
279*25b329d5SDavid du Colombier 	if (bSuScript) {
280*25b329d5SDavid du Colombier 		vAddEndTag(pDiag, ucTopTag);
281*25b329d5SDavid du Colombier 	}
282*25b329d5SDavid du Colombier 
283*25b329d5SDavid du Colombier 	/* Start a footnote */
284*25b329d5SDavid du Colombier 	vAddStartTag(pDiag, TAG_FOOTNOTE, NULL);
285*25b329d5SDavid du Colombier 	vAddStartTag(pDiag, TAG_PARA, NULL);
286*25b329d5SDavid du Colombier 
287*25b329d5SDavid du Colombier 	/* Print a footnote */
288*25b329d5SDavid du Colombier 	for (pcTmp = szText; *pcTmp != '\0'; pcTmp++) {
289*25b329d5SDavid du Colombier 		if (*pcTmp == PAR_END) {
290*25b329d5SDavid du Colombier 			if (*(pcTmp + 1) != PAR_END && *(pcTmp + 1) != '\0') {
291*25b329d5SDavid du Colombier 				/* PAR_END is not empty and not last */
292*25b329d5SDavid du Colombier 				vAddEndTag(pDiag, TAG_PARA);
293*25b329d5SDavid du Colombier 				vAddStartTag(pDiag, TAG_PARA, NULL);
294*25b329d5SDavid du Colombier 			}
295*25b329d5SDavid du Colombier 		} else {
296*25b329d5SDavid du Colombier 			vPrintChar(pDiag, *pcTmp);
297*25b329d5SDavid du Colombier 		}
298*25b329d5SDavid du Colombier 	}
299*25b329d5SDavid du Colombier 
300*25b329d5SDavid du Colombier 	/* End a footnote */
301*25b329d5SDavid du Colombier 	vAddEndTag(pDiag, TAG_PARA);
302*25b329d5SDavid du Colombier 	vAddEndTag(pDiag, TAG_FOOTNOTE);
303*25b329d5SDavid du Colombier 
304*25b329d5SDavid du Colombier 	/* Repair the subscript/superscript (if any) */
305*25b329d5SDavid du Colombier 	if (bSuScript) {
306*25b329d5SDavid du Colombier 		vAddStartTag(pDiag, ucTopTag, NULL);
307*25b329d5SDavid du Colombier 	}
308*25b329d5SDavid du Colombier } /* end of vPrintFootnote */
309*25b329d5SDavid du Colombier 
310*25b329d5SDavid du Colombier /*
311f5736e95SDavid du Colombier  * vPrintChar - print a character with XML encoding
312f5736e95SDavid du Colombier  */
313f5736e95SDavid du Colombier static void
vPrintChar(diagram_type * pDiag,char cChar)314*25b329d5SDavid du Colombier vPrintChar(diagram_type *pDiag, char cChar)
315f5736e95SDavid du Colombier {
316*25b329d5SDavid du Colombier 	fail(pDiag == NULL);
317*25b329d5SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
318*25b329d5SDavid du Colombier 
319f5736e95SDavid du Colombier 	switch (cChar) {
320*25b329d5SDavid du Colombier 	case FOOTNOTE_OR_ENDNOTE:
321*25b329d5SDavid du Colombier 		uiFootnoteNumber++;
322*25b329d5SDavid du Colombier 		vPrintFootnote(pDiag, uiFootnoteNumber - 1);
323*25b329d5SDavid du Colombier 		break;
324f5736e95SDavid du Colombier 	case '<':
325*25b329d5SDavid du Colombier 		fprintf(pDiag->pOutFile, "%s", "&lt;");
326f5736e95SDavid du Colombier 		break;
327f5736e95SDavid du Colombier 	case '>':
328*25b329d5SDavid du Colombier 		fprintf(pDiag->pOutFile, "%s", "&gt;");
329f5736e95SDavid du Colombier 		break;
330f5736e95SDavid du Colombier 	case '&':
331*25b329d5SDavid du Colombier 		fprintf(pDiag->pOutFile, "%s", "&amp;");
332f5736e95SDavid du Colombier 		break;
333f5736e95SDavid du Colombier 	default:
334*25b329d5SDavid du Colombier 		(void)putc(cChar, pDiag->pOutFile);
335f5736e95SDavid du Colombier 		break;
336f5736e95SDavid du Colombier 	}
337f5736e95SDavid du Colombier } /* end of vPrintChar */
338f5736e95SDavid du Colombier 
339f5736e95SDavid du Colombier /*
340*25b329d5SDavid du Colombier  * vPrintSpecialChar - convert and print a character
341f5736e95SDavid du Colombier  */
342f5736e95SDavid du Colombier static void
vPrintSpecialChar(diagram_type * pDiag,USHORT usChar)343*25b329d5SDavid du Colombier vPrintSpecialChar(diagram_type *pDiag, USHORT usChar)
344f5736e95SDavid du Colombier {
345f5736e95SDavid du Colombier 	ULONG   ulChar;
346f5736e95SDavid du Colombier 	size_t  tLen, tIndex;
347f5736e95SDavid du Colombier 	char    szResult[4];
348f5736e95SDavid du Colombier 
349*25b329d5SDavid du Colombier 	fail(pDiag == NULL);
350*25b329d5SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
351*25b329d5SDavid du Colombier 	fail(iWordVersion < 0);
352*25b329d5SDavid du Colombier 	fail(eEncoding == encoding_neutral);
353f5736e95SDavid du Colombier 
354f5736e95SDavid du Colombier 	ulChar = ulTranslateCharacters(usChar, 0, iWordVersion,
355f5736e95SDavid du Colombier 				conversion_xml, eEncoding, bOldMacFile);
356f5736e95SDavid du Colombier 	tLen = tUcs2Utf8(ulChar, szResult, sizeof(szResult));
357f5736e95SDavid du Colombier 	if (tLen == 1) {
358*25b329d5SDavid du Colombier 		vPrintChar(pDiag, szResult[0]);
359f5736e95SDavid du Colombier 	} else {
360f5736e95SDavid du Colombier 		for (tIndex = 0; tIndex < tLen; tIndex++) {
361*25b329d5SDavid du Colombier 			(void)putc(szResult[tIndex], pDiag->pOutFile);
362f5736e95SDavid du Colombier 		}
363f5736e95SDavid du Colombier 	}
364*25b329d5SDavid du Colombier } /* end of vPrintSpecialChar */
365*25b329d5SDavid du Colombier 
366*25b329d5SDavid du Colombier /*
367*25b329d5SDavid du Colombier  * vPrintSpecialString - convert and print a string
368*25b329d5SDavid du Colombier  */
369*25b329d5SDavid du Colombier static void
vPrintSpecialString(diagram_type * pDiag,const char * szString)370*25b329d5SDavid du Colombier vPrintSpecialString(diagram_type *pDiag, const char *szString)
371*25b329d5SDavid du Colombier {
372*25b329d5SDavid du Colombier 	int	iIndex;
373*25b329d5SDavid du Colombier 	USHORT	usChar;
374*25b329d5SDavid du Colombier 
375*25b329d5SDavid du Colombier 	fail(pDiag == NULL);
376*25b329d5SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
377*25b329d5SDavid du Colombier 	fail(szString == NULL);
378*25b329d5SDavid du Colombier 
379*25b329d5SDavid du Colombier 	for (iIndex = 0; szString[iIndex] != '\0'; iIndex++) {
380*25b329d5SDavid du Colombier 		usChar = (USHORT)(UCHAR)szString[iIndex];
381*25b329d5SDavid du Colombier 		vPrintSpecialChar(pDiag, usChar);
382f5736e95SDavid du Colombier 	}
383*25b329d5SDavid du Colombier } /* end of vPrintSpecialString */
384f5736e95SDavid du Colombier 
385f5736e95SDavid du Colombier /*
386f5736e95SDavid du Colombier  * vAddStartTag - add the specified start tag to the file
387f5736e95SDavid du Colombier  */
388f5736e95SDavid du Colombier static void
vAddStartTag(diagram_type * pDiag,UCHAR ucTag,const char * szAttribute)389f5736e95SDavid du Colombier vAddStartTag(diagram_type *pDiag, UCHAR ucTag, const char *szAttribute)
390f5736e95SDavid du Colombier {
391f5736e95SDavid du Colombier 	fail(pDiag == NULL);
392f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
393f5736e95SDavid du Colombier 	fail((size_t)ucTag >= elementsof(atDocBookTags));
394f5736e95SDavid du Colombier 
395*25b329d5SDavid du Colombier 	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
396f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "\n");
397f5736e95SDavid du Colombier 		vPrintLevel(pDiag->pOutFile);
398f5736e95SDavid du Colombier 	}
399f5736e95SDavid du Colombier 
400f5736e95SDavid du Colombier 	if (szAttribute == NULL || szAttribute[0] == '\0') {
401f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "<%s>",
402f5736e95SDavid du Colombier 			atDocBookTags[(UINT)ucTag].szTagname);
403f5736e95SDavid du Colombier 	} else {
404f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "<%s %s>",
405f5736e95SDavid du Colombier 			atDocBookTags[(UINT)ucTag].szTagname, szAttribute);
406f5736e95SDavid du Colombier 	}
407f5736e95SDavid du Colombier 
408*25b329d5SDavid du Colombier 	if (atDocBookTags[(UINT)ucTag].bAddNewlineEnd) {
409f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "\n");
410f5736e95SDavid du Colombier 		pDiag->lXleft = 0;
411f5736e95SDavid du Colombier 	}
412f5736e95SDavid du Colombier 
413f5736e95SDavid du Colombier 	vPushStack(ucTag);
414f5736e95SDavid du Colombier 
415f5736e95SDavid du Colombier 	/* Set global variables */
416f5736e95SDavid du Colombier 	switch (ucTag) {
417f5736e95SDavid du Colombier 	case TAG_CHAPTER:
418f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 1;
419f5736e95SDavid du Colombier 		bEmptyHeaderLevel = TRUE;
420f5736e95SDavid du Colombier 		break;
421f5736e95SDavid du Colombier 	case TAG_SECT1:
422f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 2;
423f5736e95SDavid du Colombier 		bEmptyHeaderLevel = TRUE;
424f5736e95SDavid du Colombier 		break;
425f5736e95SDavid du Colombier 	case TAG_SECT2:
426f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 3;
427f5736e95SDavid du Colombier 		bEmptyHeaderLevel = TRUE;
428f5736e95SDavid du Colombier 		break;
429f5736e95SDavid du Colombier 	case TAG_SECT3:
430f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 4;
431f5736e95SDavid du Colombier 		bEmptyHeaderLevel = TRUE;
432f5736e95SDavid du Colombier 		break;
433f5736e95SDavid du Colombier 	case TAG_SECT4:
434f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 5;
435f5736e95SDavid du Colombier 		bEmptyHeaderLevel = TRUE;
436f5736e95SDavid du Colombier 		break;
437f5736e95SDavid du Colombier 	case TAG_SECT5:
438f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 6;
439f5736e95SDavid du Colombier 		bEmptyHeaderLevel = TRUE;
440f5736e95SDavid du Colombier 		break;
441f5736e95SDavid du Colombier 	case TAG_TITLE:
442f5736e95SDavid du Colombier 		fail(uiParagraphLevel != 0);
443f5736e95SDavid du Colombier 		bTitleOpen = TRUE;
444f5736e95SDavid du Colombier 		break;
445*25b329d5SDavid du Colombier 	case TAG_FOOTNOTE:
446*25b329d5SDavid du Colombier 		bFootnoteOpen = TRUE;
447*25b329d5SDavid du Colombier 		break;
448f5736e95SDavid du Colombier 	case TAG_PARA:
449*25b329d5SDavid du Colombier 		fail(bTitleOpen && !bFootnoteOpen);
450f5736e95SDavid du Colombier 		uiParagraphLevel++;
451f5736e95SDavid du Colombier 		bEmptyHeaderLevel = FALSE;
452f5736e95SDavid du Colombier 		break;
453f5736e95SDavid du Colombier 	case TAG_EMPHASIS:
454f5736e95SDavid du Colombier 		bEmphasisOpen = TRUE;
455f5736e95SDavid du Colombier 		break;
456f5736e95SDavid du Colombier 	case TAG_ITEMIZEDLIST:
457f5736e95SDavid du Colombier 	case TAG_ORDEREDLIST:
458f5736e95SDavid du Colombier 		uiListLevel++;
459f5736e95SDavid du Colombier 		bEmptyListLevel = TRUE;
460f5736e95SDavid du Colombier 		bEmptyHeaderLevel = FALSE;
461f5736e95SDavid du Colombier 		break;
462f5736e95SDavid du Colombier 	case TAG_LISTITEM:
463f5736e95SDavid du Colombier 		bEmptyListLevel = FALSE;
464f5736e95SDavid du Colombier 		break;
465f5736e95SDavid du Colombier 	case TAG_SUPERSCRIPT:
466f5736e95SDavid du Colombier 		bSuperscriptOpen = TRUE;
467f5736e95SDavid du Colombier 		break;
468f5736e95SDavid du Colombier 	case TAG_SUBSCRIPT:
469f5736e95SDavid du Colombier 		bSubscriptOpen = TRUE;
470f5736e95SDavid du Colombier 		break;
471f5736e95SDavid du Colombier 	case TAG_INFORMALTABLE:
472f5736e95SDavid du Colombier 		bTableOpen = TRUE;
473f5736e95SDavid du Colombier 		bEmptyHeaderLevel = FALSE;
474f5736e95SDavid du Colombier 		break;
475f5736e95SDavid du Colombier 	default:
476f5736e95SDavid du Colombier 		break;
477f5736e95SDavid du Colombier 	}
478f5736e95SDavid du Colombier } /* end of vAddStartTag */
479f5736e95SDavid du Colombier 
480f5736e95SDavid du Colombier /*
481f5736e95SDavid du Colombier  * vAddEndTag - add the specified end tag to the file
482f5736e95SDavid du Colombier  */
483f5736e95SDavid du Colombier static void
vAddEndTag(diagram_type * pDiag,UCHAR ucTag)484f5736e95SDavid du Colombier vAddEndTag(diagram_type *pDiag, UCHAR ucTag)
485f5736e95SDavid du Colombier {
486f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
487f5736e95SDavid du Colombier 
488f5736e95SDavid du Colombier 	fail(pDiag == NULL);
489f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
490f5736e95SDavid du Colombier 	fail((size_t)ucTag >= elementsof(atDocBookTags));
491f5736e95SDavid du Colombier 
492f5736e95SDavid du Colombier #if defined(DEBUG)
493f5736e95SDavid du Colombier 	ucTopTag = ucReadStack();
494f5736e95SDavid du Colombier 	if (ucTag != ucTopTag) {
495f5736e95SDavid du Colombier 		DBG_DEC(ucTag);
496f5736e95SDavid du Colombier 		DBG_MSG(atDocBookTags[(UINT)ucTag].szTagname);
497f5736e95SDavid du Colombier 		vStackTrace();
498f5736e95SDavid du Colombier 	}
499f5736e95SDavid du Colombier #endif /* DEBUG */
500f5736e95SDavid du Colombier 
501f5736e95SDavid du Colombier 	ucTopTag = ucPopStack();
502f5736e95SDavid du Colombier 	fail((size_t)ucTopTag >= elementsof(atDocBookTags));
503f5736e95SDavid du Colombier 	if (ucTag != ucTopTag) {
504f5736e95SDavid du Colombier 		DBG_DEC(ucTag);
505f5736e95SDavid du Colombier 		DBG_DEC(ucTopTag);
506f5736e95SDavid du Colombier 		DBG_FIXME();
507f5736e95SDavid du Colombier 		werr(1, "Impossible tag sequence, unable to continue");
508f5736e95SDavid du Colombier 	}
509f5736e95SDavid du Colombier 
510*25b329d5SDavid du Colombier 	if (atDocBookTags[(UINT)ucTag].bAddNewlineEnd) {
511f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "\n");
512f5736e95SDavid du Colombier 		vPrintLevel(pDiag->pOutFile);
513f5736e95SDavid du Colombier 	}
514f5736e95SDavid du Colombier 
515f5736e95SDavid du Colombier 	fprintf(pDiag->pOutFile, "</%s>", atDocBookTags[(UINT)ucTag].szTagname);
516f5736e95SDavid du Colombier 
517*25b329d5SDavid du Colombier 	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
518f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "\n");
519f5736e95SDavid du Colombier 		pDiag->lXleft = 0;
520f5736e95SDavid du Colombier 	}
521f5736e95SDavid du Colombier 
522f5736e95SDavid du Colombier 	/* Set global variables */
523f5736e95SDavid du Colombier 	switch (ucTag) {
524f5736e95SDavid du Colombier 	case TAG_CHAPTER:
525f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 0;
526f5736e95SDavid du Colombier 		break;
527f5736e95SDavid du Colombier 	case TAG_SECT1:
528f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 1;
529f5736e95SDavid du Colombier 		break;
530f5736e95SDavid du Colombier 	case TAG_SECT2:
531f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 2;
532f5736e95SDavid du Colombier 		break;
533f5736e95SDavid du Colombier 	case TAG_SECT3:
534f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 3;
535f5736e95SDavid du Colombier 		break;
536f5736e95SDavid du Colombier 	case TAG_SECT4:
537f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 4;
538f5736e95SDavid du Colombier 		break;
539f5736e95SDavid du Colombier 	case TAG_SECT5:
540f5736e95SDavid du Colombier 		usHeaderLevelCurrent = 5;
541f5736e95SDavid du Colombier 		break;
542f5736e95SDavid du Colombier 	case TAG_TITLE:
543f5736e95SDavid du Colombier 		bTitleOpen = FALSE;
544f5736e95SDavid du Colombier 		break;
545*25b329d5SDavid du Colombier 	case TAG_FOOTNOTE:
546*25b329d5SDavid du Colombier 		bFootnoteOpen = FALSE;
547*25b329d5SDavid du Colombier 		break;
548f5736e95SDavid du Colombier 	case TAG_PARA:
549f5736e95SDavid du Colombier 		uiParagraphLevel--;
550f5736e95SDavid du Colombier 		break;
551f5736e95SDavid du Colombier 	case TAG_EMPHASIS:
552f5736e95SDavid du Colombier 		bEmphasisOpen = FALSE;
553f5736e95SDavid du Colombier 		break;
554f5736e95SDavid du Colombier 	case TAG_SUPERSCRIPT:
555f5736e95SDavid du Colombier 		bSuperscriptOpen = FALSE;
556f5736e95SDavid du Colombier 		break;
557f5736e95SDavid du Colombier 	case TAG_ITEMIZEDLIST:
558f5736e95SDavid du Colombier 	case TAG_ORDEREDLIST:
559f5736e95SDavid du Colombier 		uiListLevel--;
560f5736e95SDavid du Colombier 		break;
561f5736e95SDavid du Colombier 	case TAG_SUBSCRIPT:
562f5736e95SDavid du Colombier 		bSubscriptOpen = FALSE;
563f5736e95SDavid du Colombier 		break;
564f5736e95SDavid du Colombier 	case TAG_INFORMALTABLE:
565f5736e95SDavid du Colombier 		bTableOpen = FALSE;
566f5736e95SDavid du Colombier 		iTableColumnsCurrent = 0;
567f5736e95SDavid du Colombier 		break;
568f5736e95SDavid du Colombier 	default:
569f5736e95SDavid du Colombier 		break;
570f5736e95SDavid du Colombier 	}
571f5736e95SDavid du Colombier } /* end of vAddEndTag */
572f5736e95SDavid du Colombier 
573f5736e95SDavid du Colombier /*
574f5736e95SDavid du Colombier  * vAddEndTagOptional - add the specified end tag to the file if needed
575f5736e95SDavid du Colombier  */
576f5736e95SDavid du Colombier static void
vAddEndTagOptional(diagram_type * pDiag,UCHAR ucTag)577f5736e95SDavid du Colombier vAddEndTagOptional(diagram_type *pDiag, UCHAR ucTag)
578f5736e95SDavid du Colombier {
579f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
580f5736e95SDavid du Colombier 
581f5736e95SDavid du Colombier 	ucTopTag = ucReadStack();
582f5736e95SDavid du Colombier 	if (ucTag == ucTopTag) {
583f5736e95SDavid du Colombier 		vAddEndTag(pDiag, ucTag);
584f5736e95SDavid du Colombier 	}
585f5736e95SDavid du Colombier } /* end of vAddEndTagOptional */
586f5736e95SDavid du Colombier 
587f5736e95SDavid du Colombier /*
588f5736e95SDavid du Colombier  * vAddCombinedTag - add the specified start and end tag to the file
589f5736e95SDavid du Colombier  */
590f5736e95SDavid du Colombier static void
vAddCombinedTag(diagram_type * pDiag,UCHAR ucTag,const char * szAttribute)591f5736e95SDavid du Colombier vAddCombinedTag(diagram_type *pDiag, UCHAR ucTag, const char *szAttribute)
592f5736e95SDavid du Colombier {
593f5736e95SDavid du Colombier 	fail(pDiag == NULL);
594f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
595f5736e95SDavid du Colombier 	fail((size_t)ucTag >= elementsof(atDocBookTags));
596f5736e95SDavid du Colombier 
597*25b329d5SDavid du Colombier 	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
598f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "\n");
599f5736e95SDavid du Colombier 		vPrintLevel(pDiag->pOutFile);
600f5736e95SDavid du Colombier 	}
601f5736e95SDavid du Colombier 
602f5736e95SDavid du Colombier 	if (szAttribute == NULL || szAttribute[0] == '\0') {
603f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "<%s/>",
604f5736e95SDavid du Colombier 			atDocBookTags[(UINT)ucTag].szTagname);
605f5736e95SDavid du Colombier 	} else {
606f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "<%s %s/>",
607f5736e95SDavid du Colombier 			atDocBookTags[(UINT)ucTag].szTagname, szAttribute);
608f5736e95SDavid du Colombier 	}
609f5736e95SDavid du Colombier 
610*25b329d5SDavid du Colombier 	if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
611f5736e95SDavid du Colombier 		fprintf(pDiag->pOutFile, "\n");
612f5736e95SDavid du Colombier 		pDiag->lXleft = 0;
613f5736e95SDavid du Colombier 	}
614f5736e95SDavid du Colombier } /* end of vAddCombinedTag */
615f5736e95SDavid du Colombier 
616f5736e95SDavid du Colombier /*
617f5736e95SDavid du Colombier  * vAddEndTagsUntil2 - add end tags until one the specified tags is seen
618f5736e95SDavid du Colombier  */
619f5736e95SDavid du Colombier static void
vAddEndTagsUntil2(diagram_type * pDiag,UCHAR ucTag1,UCHAR ucTag2)620f5736e95SDavid du Colombier vAddEndTagsUntil2(diagram_type *pDiag, UCHAR ucTag1, UCHAR ucTag2)
621f5736e95SDavid du Colombier {
622f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
623f5736e95SDavid du Colombier 
624f5736e95SDavid du Colombier 	do {
625f5736e95SDavid du Colombier 		ucTopTag = ucReadStack();
626f5736e95SDavid du Colombier 		switch (ucTopTag) {
627f5736e95SDavid du Colombier                 case TAG_CHAPTER:
628f5736e95SDavid du Colombier                 case TAG_SECT1:
629f5736e95SDavid du Colombier                 case TAG_SECT2:
630f5736e95SDavid du Colombier                 case TAG_SECT3:
631f5736e95SDavid du Colombier                 case TAG_SECT4:
632f5736e95SDavid du Colombier                 case TAG_SECT5:
633f5736e95SDavid du Colombier 			if (bEmptyHeaderLevel) {
634f5736e95SDavid du Colombier 				/*
635f5736e95SDavid du Colombier 				 * An empty chapter is legal in Word,
636f5736e95SDavid du Colombier 				 * but not in DocBook.
637f5736e95SDavid du Colombier 				 */
638f5736e95SDavid du Colombier 				vAddCombinedTag(pDiag, TAG_PARA, NULL);
639f5736e95SDavid du Colombier 				bEmptyHeaderLevel = FALSE;
640f5736e95SDavid du Colombier 			}
641f5736e95SDavid du Colombier 			break;
642f5736e95SDavid du Colombier 		case TAG_ITEMIZEDLIST:
643f5736e95SDavid du Colombier 		case TAG_ORDEREDLIST:
644f5736e95SDavid du Colombier 			if (bEmptyListLevel) {
645f5736e95SDavid du Colombier 				/*
646f5736e95SDavid du Colombier 				 * A list without items is legal in Word,
647f5736e95SDavid du Colombier 				 * but not in DocBook. (Nor are empty items)
648f5736e95SDavid du Colombier 				 */
649f5736e95SDavid du Colombier 				vAddStartTag(pDiag, TAG_LISTITEM, NULL);
650f5736e95SDavid du Colombier 				vAddCombinedTag(pDiag, TAG_PARA, NULL);
651f5736e95SDavid du Colombier 				vAddEndTag(pDiag, TAG_LISTITEM);
652f5736e95SDavid du Colombier 				bEmptyListLevel = FALSE;
653f5736e95SDavid du Colombier 			}
654f5736e95SDavid du Colombier 			break;
655f5736e95SDavid du Colombier 		default:
656f5736e95SDavid du Colombier 			break;
657f5736e95SDavid du Colombier 		}
658f5736e95SDavid du Colombier 		vAddEndTag(pDiag, ucTopTag);
659f5736e95SDavid du Colombier 	} while (ucTopTag != ucTag1 && ucTopTag != ucTag2);
660f5736e95SDavid du Colombier } /* end of vAddEndTagsUntil2 */
661f5736e95SDavid du Colombier 
662f5736e95SDavid du Colombier /*
663f5736e95SDavid du Colombier  * vCreateBookIntro - create title and bookinfo
664f5736e95SDavid du Colombier  */
665f5736e95SDavid du Colombier void
vCreateBookIntro(diagram_type * pDiag,int iVersion)666*25b329d5SDavid du Colombier vCreateBookIntro(diagram_type *pDiag, int iVersion)
667f5736e95SDavid du Colombier {
668f5736e95SDavid du Colombier 	const char	*szTitle, *szSubject, *szAuthor;
669f5736e95SDavid du Colombier 	const char	*szLastSaveDtm, *szCompany;
670f5736e95SDavid du Colombier 	const char	*szLanguage;
671f5736e95SDavid du Colombier 	char		szTmp[13];
672f5736e95SDavid du Colombier 
673f5736e95SDavid du Colombier 	fail(pDiag == NULL);
674f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
675*25b329d5SDavid du Colombier 	fail(iVersion < 0);
676f5736e95SDavid du Colombier 	fail(eEncoding == encoding_neutral);
677f5736e95SDavid du Colombier 
678*25b329d5SDavid du Colombier 	iWordVersion = iVersion;
679*25b329d5SDavid du Colombier 	bOldMacFile = bIsOldMacFile();
680f5736e95SDavid du Colombier 	szTitle = szGetTitle();
681f5736e95SDavid du Colombier 	szSubject = szGetSubject();
682f5736e95SDavid du Colombier 	szAuthor = szGetAuthor();
683f5736e95SDavid du Colombier 	szLastSaveDtm = szGetLastSaveDtm();
684f5736e95SDavid du Colombier 	szCompany = szGetCompany();
685f5736e95SDavid du Colombier 
686f5736e95SDavid du Colombier 	/* Start Book */
687f5736e95SDavid du Colombier 	szLanguage = szGetLanguage();
688f5736e95SDavid du Colombier 	if (szLanguage != NULL) {
689f5736e95SDavid du Colombier 		DBG_MSG(szLanguage);
690f5736e95SDavid du Colombier 		sprintf(szTmp, "lang='%.5s'", szLanguage);
691f5736e95SDavid du Colombier 		szLanguage = szTmp;
692f5736e95SDavid du Colombier 	}
693f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_BOOK, szLanguage);
694f5736e95SDavid du Colombier 
695f5736e95SDavid du Colombier 	/* Book title */
696f5736e95SDavid du Colombier 	if (szTitle != NULL && szTitle[0] != '\0') {
697f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_TITLE, NULL);
698*25b329d5SDavid du Colombier 		vPrintSpecialString(pDiag, szTitle);
699f5736e95SDavid du Colombier 		vAddEndTag(pDiag, TAG_TITLE);
700f5736e95SDavid du Colombier 	}
701f5736e95SDavid du Colombier 	/* Bookinfo */
702f5736e95SDavid du Colombier 	if ((szTitle != NULL && szTitle[0] != '\0') ||
703f5736e95SDavid du Colombier 	    (szSubject != NULL && szSubject[0] != '\0') ||
704f5736e95SDavid du Colombier 	    (szAuthor != NULL && szAuthor[0] != '\0') ||
705f5736e95SDavid du Colombier 	    (szLastSaveDtm != NULL && szLastSaveDtm[0] != '\0') ||
706f5736e95SDavid du Colombier 	    (szCompany != NULL && szCompany[0] != '\0')) {
707f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_BOOKINFO, NULL);
708f5736e95SDavid du Colombier 		if (szTitle != NULL && szTitle[0] != '\0') {
709f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_TITLE, NULL);
710*25b329d5SDavid du Colombier 			vPrintSpecialString(pDiag, szTitle);
711f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_TITLE);
712f5736e95SDavid du Colombier 		}
713f5736e95SDavid du Colombier 		if (szSubject != NULL && szSubject[0] != '\0') {
714f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_SUBTITLE, NULL);
715*25b329d5SDavid du Colombier 			vPrintSpecialString(pDiag, szSubject);
716f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_SUBTITLE);
717f5736e95SDavid du Colombier 		}
718f5736e95SDavid du Colombier 		if (szAuthor != NULL && szAuthor[0] != '\0') {
719f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_AUTHOR, NULL);
720f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_SURNAME, NULL);
721*25b329d5SDavid du Colombier 			vPrintSpecialString(pDiag, szAuthor);
722f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_SURNAME);
723f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_AUTHOR);
724f5736e95SDavid du Colombier 		}
725f5736e95SDavid du Colombier 		if (szLastSaveDtm != NULL && szLastSaveDtm[0] != '\0') {
726f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_DATE, NULL);
727*25b329d5SDavid du Colombier 			vPrintSpecialString(pDiag, szLastSaveDtm);
728f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_DATE);
729f5736e95SDavid du Colombier 		}
730f5736e95SDavid du Colombier 		if (szCompany != NULL && szCompany[0] != '\0') {
731f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_CORPNAME, NULL);
732*25b329d5SDavid du Colombier 			vPrintSpecialString(pDiag, szCompany);
733f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_CORPNAME);
734f5736e95SDavid du Colombier 		}
735f5736e95SDavid du Colombier 		vAddEndTag(pDiag, TAG_BOOKINFO);
736f5736e95SDavid du Colombier 	}
737f5736e95SDavid du Colombier } /* end of vCreateBookIntro */
738f5736e95SDavid du Colombier 
739f5736e95SDavid du Colombier /*
740f5736e95SDavid du Colombier  * vPrologueXML - perform the XML initialization
741f5736e95SDavid du Colombier  */
742f5736e95SDavid du Colombier void
vPrologueXML(diagram_type * pDiag,const options_type * pOptions)743*25b329d5SDavid du Colombier vPrologueXML(diagram_type *pDiag, const options_type *pOptions)
744f5736e95SDavid du Colombier {
745f5736e95SDavid du Colombier 
746f5736e95SDavid du Colombier 	fail(pDiag == NULL);
747f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
748*25b329d5SDavid du Colombier 	fail(pOptions == NULL);
749f5736e95SDavid du Colombier 
750f5736e95SDavid du Colombier #if defined(DEBUG)
751f5736e95SDavid du Colombier 	vCheckTagTable();
752f5736e95SDavid du Colombier #endif /* DEBUG */
753f5736e95SDavid du Colombier 
754f5736e95SDavid du Colombier 	/* Set global variables to their start values */
755*25b329d5SDavid du Colombier 	eEncoding = pOptions->eEncoding;
756f5736e95SDavid du Colombier 	bEmphasisOpen = FALSE;
757f5736e95SDavid du Colombier 	bSuperscriptOpen = FALSE;
758f5736e95SDavid du Colombier 	bSubscriptOpen = FALSE;
759f5736e95SDavid du Colombier 	bTitleOpen = FALSE;
760f5736e95SDavid du Colombier 	bTableOpen = FALSE;
761*25b329d5SDavid du Colombier 	bFootnoteOpen = FALSE;
762f5736e95SDavid du Colombier 	uiParagraphLevel = 0;
763f5736e95SDavid du Colombier 	uiListLevel = 0;
764f5736e95SDavid du Colombier 	bEmptyListLevel = TRUE;
765f5736e95SDavid du Colombier 	usHeaderLevelCurrent = 0;
766f5736e95SDavid du Colombier 	bEmptyHeaderLevel = TRUE;
767f5736e95SDavid du Colombier 	iTableColumnsCurrent = 0;
768*25b329d5SDavid du Colombier 	uiFootnoteNumber = 0;
769f5736e95SDavid du Colombier 
770f5736e95SDavid du Colombier 	pDiag->lXleft = 0;
771f5736e95SDavid du Colombier 	pDiag->lYtop = 0;
772f5736e95SDavid du Colombier 
773f5736e95SDavid du Colombier 	/* Create an empty stack */
774f5736e95SDavid du Colombier 	tStacksize = INITIAL_STACK_SIZE;
775f5736e95SDavid du Colombier 	aucStack = xcalloc(tStacksize, sizeof(UCHAR));
776f5736e95SDavid du Colombier 	tStackNextFree = 0;
777f5736e95SDavid du Colombier } /* end of vPrologueXML */
778f5736e95SDavid du Colombier 
779f5736e95SDavid du Colombier /*
780f5736e95SDavid du Colombier  * vEpilogueXML - clean up after everything is done
781f5736e95SDavid du Colombier  */
782f5736e95SDavid du Colombier void
vEpilogueXML(diagram_type * pDiag)783f5736e95SDavid du Colombier vEpilogueXML(diagram_type *pDiag)
784f5736e95SDavid du Colombier {
785f5736e95SDavid du Colombier 	vStackTrace();
786f5736e95SDavid du Colombier 
787f5736e95SDavid du Colombier 	vAddEndTagsUntil1(pDiag, TAG_BOOK);
788f5736e95SDavid du Colombier 
789f5736e95SDavid du Colombier 	vStackTrace();
790f5736e95SDavid du Colombier 
791f5736e95SDavid du Colombier 	/* Destroy the stack */
792f5736e95SDavid du Colombier 	fail(tStackNextFree != 0);
793f5736e95SDavid du Colombier 	tStacksize = 0;
794f5736e95SDavid du Colombier 	aucStack = xfree(aucStack);
795f5736e95SDavid du Colombier 	tStackNextFree = 0;
796f5736e95SDavid du Colombier } /* end of vEpilogueXML */
797f5736e95SDavid du Colombier 
798f5736e95SDavid du Colombier /*
799f5736e95SDavid du Colombier  * vPrintXML - print a XML string
800f5736e95SDavid du Colombier  */
801f5736e95SDavid du Colombier static void
vPrintXML(diagram_type * pDiag,const char * szString,size_t tStringLength,USHORT usFontstyle)802f5736e95SDavid du Colombier vPrintXML(diagram_type *pDiag, const char *szString, size_t tStringLength,
803f5736e95SDavid du Colombier 		USHORT usFontstyle)
804f5736e95SDavid du Colombier {
805*25b329d5SDavid du Colombier 	const char	*szAttr;
806f5736e95SDavid du Colombier 	int	iCount;
807f5736e95SDavid du Colombier 	size_t	tNextFree;
808f5736e95SDavid du Colombier 	BOOL	bNotReady, bEmphasisNew, bSuperscriptNew, bSubscriptNew;
809f5736e95SDavid du Colombier 	UCHAR	ucTopTag, aucStorage[3];
810f5736e95SDavid du Colombier 
811f5736e95SDavid du Colombier 	fail(szString == NULL);
812f5736e95SDavid du Colombier 
813f5736e95SDavid du Colombier 	if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
814f5736e95SDavid du Colombier 		return;
815f5736e95SDavid du Colombier 	}
816f5736e95SDavid du Colombier 
817*25b329d5SDavid du Colombier 	if (tStringLength == 1 && szString[0] == FOOTNOTE_OR_ENDNOTE) {
818*25b329d5SDavid du Colombier 		/* Don't do anything special for just a single footnote */
819*25b329d5SDavid du Colombier 		bEmphasisNew = FALSE;
820*25b329d5SDavid du Colombier 		bSuperscriptNew = FALSE;
821*25b329d5SDavid du Colombier 		bSubscriptNew = FALSE;
822*25b329d5SDavid du Colombier 	} else {
823*25b329d5SDavid du Colombier 		/* Situation normal */
824f5736e95SDavid du Colombier 		bEmphasisNew = bIsBold(usFontstyle) ||
825f5736e95SDavid du Colombier 				bIsItalic(usFontstyle) ||
826f5736e95SDavid du Colombier 				bIsUnderline(usFontstyle) ||
827f5736e95SDavid du Colombier 				bIsStrike(usFontstyle);
828f5736e95SDavid du Colombier 		bSuperscriptNew = bIsSuperscript(usFontstyle);
829f5736e95SDavid du Colombier 		bSubscriptNew = bIsSubscript(usFontstyle);
830*25b329d5SDavid du Colombier 	}
831f5736e95SDavid du Colombier 
832f5736e95SDavid du Colombier 	/* End what has to be ended (or more to keep the stack happy) */
833f5736e95SDavid du Colombier 	tNextFree = 0;
834f5736e95SDavid du Colombier 	bNotReady = TRUE;
835f5736e95SDavid du Colombier 	do {
836f5736e95SDavid du Colombier 		ucTopTag = ucReadStack();
837f5736e95SDavid du Colombier 		switch (ucTopTag) {
838f5736e95SDavid du Colombier 		case TAG_EMPHASIS:
839f5736e95SDavid du Colombier 			fail(!bEmphasisOpen);
840f5736e95SDavid du Colombier 			if (bEmphasisNew) {
841f5736e95SDavid du Colombier 				aucStorage[tNextFree++] = ucTopTag;
842f5736e95SDavid du Colombier 			}
843f5736e95SDavid du Colombier 			vAddEndTag(pDiag, ucTopTag);
844f5736e95SDavid du Colombier 			break;
845f5736e95SDavid du Colombier 		case TAG_SUPERSCRIPT:
846f5736e95SDavid du Colombier 			fail(!bSuperscriptOpen);
847f5736e95SDavid du Colombier 			if (bSuperscriptNew) {
848f5736e95SDavid du Colombier 				aucStorage[tNextFree++] = ucTopTag;
849f5736e95SDavid du Colombier 			}
850f5736e95SDavid du Colombier 			vAddEndTag(pDiag, ucTopTag);
851f5736e95SDavid du Colombier 			break;
852f5736e95SDavid du Colombier 		case TAG_SUBSCRIPT:
853f5736e95SDavid du Colombier 			fail(!bSubscriptOpen);
854f5736e95SDavid du Colombier 			if (bSubscriptNew) {
855f5736e95SDavid du Colombier 				aucStorage[tNextFree++] = ucTopTag;
856f5736e95SDavid du Colombier 			}
857f5736e95SDavid du Colombier 			vAddEndTag(pDiag, ucTopTag);
858f5736e95SDavid du Colombier 			break;
859f5736e95SDavid du Colombier 		default:
860f5736e95SDavid du Colombier 			bNotReady = FALSE;
861f5736e95SDavid du Colombier 			break;
862f5736e95SDavid du Colombier 		}
863f5736e95SDavid du Colombier 		fail(tNextFree > elementsof(aucStorage));
864f5736e95SDavid du Colombier 		fail(bNotReady && tNextFree == elementsof(aucStorage));
865f5736e95SDavid du Colombier 	} while (bNotReady);
866f5736e95SDavid du Colombier 
867f5736e95SDavid du Colombier 	/* Just te make sure */
868f5736e95SDavid du Colombier 	vStartOfParagraphXML(pDiag, 1);
869f5736e95SDavid du Colombier 
870f5736e95SDavid du Colombier 	/* Restart to keep the stack happy */
871f5736e95SDavid du Colombier 	for (iCount = (int)tNextFree - 1; iCount > 0; iCount--) {
872f5736e95SDavid du Colombier 		vAddStartTag(pDiag, aucStorage[iCount], NULL);
873f5736e95SDavid du Colombier 	}
874f5736e95SDavid du Colombier 
875f5736e95SDavid du Colombier 	/* Start what has to be started */
876f5736e95SDavid du Colombier 	if (bEmphasisNew && !bEmphasisOpen) {
877*25b329d5SDavid du Colombier 		if (bIsBold(usFontstyle)) {
878*25b329d5SDavid du Colombier 			szAttr = "role='bold'";
879*25b329d5SDavid du Colombier 		} else if (bIsItalic(usFontstyle)) {
880*25b329d5SDavid du Colombier 			szAttr = NULL;
881*25b329d5SDavid du Colombier 		} else if (bIsUnderline(usFontstyle)) {
882*25b329d5SDavid du Colombier 			szAttr = "role='underline'";
883*25b329d5SDavid du Colombier 		} else if (bIsStrike(usFontstyle)) {
884*25b329d5SDavid du Colombier 			szAttr = "role='strikethrough'";
885*25b329d5SDavid du Colombier 		} else {
886*25b329d5SDavid du Colombier 			szAttr = NULL;
887*25b329d5SDavid du Colombier 		}
888*25b329d5SDavid du Colombier 		vAddStartTag(pDiag, TAG_EMPHASIS, szAttr);
889f5736e95SDavid du Colombier 	}
890f5736e95SDavid du Colombier 	if (bSuperscriptNew && !bSuperscriptOpen) {
891f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_SUPERSCRIPT, NULL);
892f5736e95SDavid du Colombier 	}
893f5736e95SDavid du Colombier 	if (bSubscriptNew && !bSubscriptOpen) {
894f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_SUBSCRIPT, NULL);
895f5736e95SDavid du Colombier 	}
896f5736e95SDavid du Colombier 
897f5736e95SDavid du Colombier 	/* The print the string */
898f5736e95SDavid du Colombier 	for (iCount = 0; iCount < (int)tStringLength; iCount++) {
899*25b329d5SDavid du Colombier 		vPrintChar(pDiag, szString[iCount]);
900f5736e95SDavid du Colombier 	}
901f5736e95SDavid du Colombier } /* end of vPrintXML */
902f5736e95SDavid du Colombier 
903f5736e95SDavid du Colombier /*
904f5736e95SDavid du Colombier  * vMove2NextLineXML - move to the next line
905f5736e95SDavid du Colombier  */
906f5736e95SDavid du Colombier void
vMove2NextLineXML(diagram_type * pDiag)907f5736e95SDavid du Colombier vMove2NextLineXML(diagram_type *pDiag)
908f5736e95SDavid du Colombier {
909f5736e95SDavid du Colombier 	fail(pDiag == NULL);
910f5736e95SDavid du Colombier 
911*25b329d5SDavid du Colombier 	/*
912f5736e95SDavid du Colombier 	if (uiParagraphLevel != 0) {
913*25b329d5SDavid du Colombier 		We need something like HTML's <BR> tag
914f5736e95SDavid du Colombier 	}
915*25b329d5SDavid du Colombier 	*/
916f5736e95SDavid du Colombier } /* end of vMove2NextLineXML */
917f5736e95SDavid du Colombier 
918f5736e95SDavid du Colombier /*
919f5736e95SDavid du Colombier  * vSubstringXML - put a sub string into a diagram
920f5736e95SDavid du Colombier  */
921f5736e95SDavid du Colombier void
vSubstringXML(diagram_type * pDiag,const char * szString,size_t tStringLength,long lStringWidth,USHORT usFontstyle)922f5736e95SDavid du Colombier vSubstringXML(diagram_type *pDiag,
923f5736e95SDavid du Colombier 	const char *szString, size_t tStringLength, long lStringWidth,
924f5736e95SDavid du Colombier 	USHORT usFontstyle)
925f5736e95SDavid du Colombier {
926f5736e95SDavid du Colombier 	fail(pDiag == NULL || szString == NULL);
927f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
928f5736e95SDavid du Colombier 	fail(pDiag->lXleft < 0);
929f5736e95SDavid du Colombier 	fail(tStringLength != strlen(szString));
930f5736e95SDavid du Colombier 
931f5736e95SDavid du Colombier 	if (szString[0] == '\0' || tStringLength == 0) {
932f5736e95SDavid du Colombier 		return;
933f5736e95SDavid du Colombier 	}
934f5736e95SDavid du Colombier 
935f5736e95SDavid du Colombier 	vPrintXML(pDiag, szString, tStringLength, usFontstyle);
936f5736e95SDavid du Colombier 	pDiag->lXleft += lStringWidth;
937f5736e95SDavid du Colombier } /* end of vSubstringXML */
938f5736e95SDavid du Colombier 
939f5736e95SDavid du Colombier /*
940f5736e95SDavid du Colombier  * Create an start of a paragraph
941f5736e95SDavid du Colombier  * Only works on paragraph level one, because Word doesn't allow paragraphs
942f5736e95SDavid du Colombier  * in paragraphs. Other paragraph levels result from DocBooks special needs.
943f5736e95SDavid du Colombier  */
944f5736e95SDavid du Colombier void
vStartOfParagraphXML(diagram_type * pDiag,UINT uiMaxLevel)945*25b329d5SDavid du Colombier vStartOfParagraphXML(diagram_type *pDiag, UINT uiMaxLevel)
946f5736e95SDavid du Colombier {
947f5736e95SDavid du Colombier 	fail(pDiag == NULL);
948f5736e95SDavid du Colombier 
949*25b329d5SDavid du Colombier 	if (uiParagraphLevel >= uiMaxLevel || bTitleOpen) {
950*25b329d5SDavid du Colombier 		/* In Word a title is just a paragraph */
951f5736e95SDavid du Colombier 		return;
952f5736e95SDavid du Colombier 	}
953f5736e95SDavid du Colombier 	if (uiListLevel != 0 && bEmptyListLevel) {
954f5736e95SDavid du Colombier 		/* No paragraphs in a list before the first listitem */
955f5736e95SDavid du Colombier 		return;
956f5736e95SDavid du Colombier 	}
957f5736e95SDavid du Colombier 	if (usHeaderLevelCurrent == 0) {
958f5736e95SDavid du Colombier 		/* No paragraphs without an open header */
959f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_CHAPTER, NULL);
960f5736e95SDavid du Colombier 		/* Dummy title */
961f5736e95SDavid du Colombier 		vAddCombinedTag(pDiag, TAG_TITLE, NULL);
962f5736e95SDavid du Colombier 	}
963f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_PARA, NULL);
964f5736e95SDavid du Colombier } /* end of vStartOfParagraphXML */
965f5736e95SDavid du Colombier 
966f5736e95SDavid du Colombier /*
967f5736e95SDavid du Colombier  * Create an end of a paragraph
968f5736e95SDavid du Colombier  * Only for paragraph level one and for titles
969f5736e95SDavid du Colombier  */
970f5736e95SDavid du Colombier void
vEndOfParagraphXML(diagram_type * pDiag,UINT uiMaxLevel)971*25b329d5SDavid du Colombier vEndOfParagraphXML(diagram_type *pDiag, UINT uiMaxLevel)
972f5736e95SDavid du Colombier {
973f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
974f5736e95SDavid du Colombier 
975f5736e95SDavid du Colombier 	fail(pDiag == NULL);
976f5736e95SDavid du Colombier 
977*25b329d5SDavid du Colombier 	if (uiParagraphLevel > uiMaxLevel) {
978f5736e95SDavid du Colombier 		DBG_DEC(uiParagraphLevel);
979f5736e95SDavid du Colombier 		return;
980f5736e95SDavid du Colombier 	}
981f5736e95SDavid du Colombier 
982f5736e95SDavid du Colombier 	for(;;) {
983f5736e95SDavid du Colombier 		ucTopTag = ucReadStack();
984f5736e95SDavid du Colombier 		switch (ucTopTag) {
985f5736e95SDavid du Colombier 		case TAG_EMPHASIS:
986f5736e95SDavid du Colombier 			fail(!bEmphasisOpen);
987f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_EMPHASIS);
988f5736e95SDavid du Colombier 			break;
989f5736e95SDavid du Colombier 		case TAG_SUPERSCRIPT:
990f5736e95SDavid du Colombier 			fail(!bSuperscriptOpen);
991f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_SUPERSCRIPT);
992f5736e95SDavid du Colombier 			break;
993f5736e95SDavid du Colombier 		case TAG_SUBSCRIPT:
994f5736e95SDavid du Colombier 			fail(!bSubscriptOpen);
995f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_SUBSCRIPT);
996f5736e95SDavid du Colombier 			break;
997f5736e95SDavid du Colombier 		case TAG_TITLE:
998f5736e95SDavid du Colombier 			fail(!bTitleOpen);
999f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_TITLE);
1000f5736e95SDavid du Colombier 			return;
1001f5736e95SDavid du Colombier 		case TAG_PARA:
1002f5736e95SDavid du Colombier 			fail(uiParagraphLevel == 0);
1003f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_PARA);
1004f5736e95SDavid du Colombier 			return;
1005f5736e95SDavid du Colombier 		case TAG_TBODY:
1006f5736e95SDavid du Colombier 		case TAG_TGROUP:
1007f5736e95SDavid du Colombier 		case TAG_INFORMALTABLE:
1008f5736e95SDavid du Colombier 			fail(!bTableOpen);
1009f5736e95SDavid du Colombier 			vAddEndTag(pDiag, ucTopTag);
1010f5736e95SDavid du Colombier 			break;
1011f5736e95SDavid du Colombier 		case TAG_NOTAG:
1012f5736e95SDavid du Colombier 			DBG_FIXME();
1013f5736e95SDavid du Colombier 			werr(1, "Impossible tag sequence, unable to continue");
1014f5736e95SDavid du Colombier 			break;
1015f5736e95SDavid du Colombier 		default:
1016f5736e95SDavid du Colombier 			DBG_DEC(ucTopTag);
1017f5736e95SDavid du Colombier 			DBG_MSG_C((size_t)ucTopTag < elementsof(atDocBookTags),
1018f5736e95SDavid du Colombier 				atDocBookTags[(UINT)ucTopTag].szTagname);
1019f5736e95SDavid du Colombier 			return;
1020f5736e95SDavid du Colombier 		}
1021f5736e95SDavid du Colombier 	}
1022f5736e95SDavid du Colombier } /* end of vEndOfParagraphXML */
1023f5736e95SDavid du Colombier 
1024f5736e95SDavid du Colombier /*
1025f5736e95SDavid du Colombier  * Create an end of a page
1026f5736e95SDavid du Colombier  */
1027f5736e95SDavid du Colombier void
vEndOfPageXML(diagram_type * pDiag)1028f5736e95SDavid du Colombier vEndOfPageXML(diagram_type *pDiag)
1029f5736e95SDavid du Colombier {
1030f5736e95SDavid du Colombier 	if (bTableOpen || usHeaderLevelCurrent == 0) {
1031f5736e95SDavid du Colombier 		/* No beginpage in a table or outside a chapter */
1032f5736e95SDavid du Colombier 		return;
1033f5736e95SDavid du Colombier 	}
1034f5736e95SDavid du Colombier 	if (bTitleOpen) {
1035f5736e95SDavid du Colombier 		/* A beginpage is not allowed when in a title */
1036f5736e95SDavid du Colombier 		/* So start a new paragraph */
1037*25b329d5SDavid du Colombier 		vEndOfParagraphXML(pDiag, UINT_MAX);
1038*25b329d5SDavid du Colombier 		vStartOfParagraphXML(pDiag, UINT_MAX);
1039f5736e95SDavid du Colombier 		return;
1040f5736e95SDavid du Colombier 	}
1041f5736e95SDavid du Colombier 	vAddCombinedTag(pDiag, TAG_BEGINPAGE, NULL);
1042f5736e95SDavid du Colombier } /* end of vEndOfPageXML */
1043f5736e95SDavid du Colombier 
1044f5736e95SDavid du Colombier /*
1045f5736e95SDavid du Colombier  * vCloseHeaderLevels - close the specified header levels
1046f5736e95SDavid du Colombier  */
1047f5736e95SDavid du Colombier static void
vCloseHeaderLevels(diagram_type * pDiag,USHORT usIstd)1048f5736e95SDavid du Colombier vCloseHeaderLevels(diagram_type *pDiag, USHORT usIstd)
1049f5736e95SDavid du Colombier {
1050f5736e95SDavid du Colombier 	BOOL	bNotReady;
1051f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
1052f5736e95SDavid du Colombier 
1053f5736e95SDavid du Colombier 	DBG_MSG("vCloseHeaderLevels");
1054f5736e95SDavid du Colombier 	DBG_DEC(usIstd);
1055f5736e95SDavid du Colombier 	DBG_DEC(usHeaderLevelCurrent);
1056f5736e95SDavid du Colombier 
1057f5736e95SDavid du Colombier 	vStackTrace();
1058f5736e95SDavid du Colombier 
1059f5736e95SDavid du Colombier 	bNotReady = TRUE;
1060f5736e95SDavid du Colombier 	do {
1061f5736e95SDavid du Colombier 		ucTopTag = ucReadStack();
1062f5736e95SDavid du Colombier 		switch (ucTopTag) {
1063f5736e95SDavid du Colombier 		case TAG_TITLE:
1064f5736e95SDavid du Colombier 		case TAG_PARA:
1065f5736e95SDavid du Colombier 			vAddEndTag(pDiag, ucTopTag);
1066f5736e95SDavid du Colombier 			break;
1067f5736e95SDavid du Colombier 		default:
1068f5736e95SDavid du Colombier 			bNotReady = FALSE;
1069f5736e95SDavid du Colombier 			break;
1070f5736e95SDavid du Colombier 		}
1071f5736e95SDavid du Colombier 	} while (bNotReady);
1072f5736e95SDavid du Colombier 
1073f5736e95SDavid du Colombier 	vStackTrace();
1074f5736e95SDavid du Colombier 
1075f5736e95SDavid du Colombier 	while (usHeaderLevelCurrent >= usIstd) {
1076f5736e95SDavid du Colombier 		if (bEmptyHeaderLevel) {
1077f5736e95SDavid du Colombier 			vAddCombinedTag(pDiag, TAG_PARA, NULL);
1078f5736e95SDavid du Colombier 			bEmptyHeaderLevel = FALSE;
1079f5736e95SDavid du Colombier 		}
1080f5736e95SDavid du Colombier 		switch (usHeaderLevelCurrent) {
1081f5736e95SDavid du Colombier 		case 1: vAddEndTag(pDiag, TAG_CHAPTER); break;
1082f5736e95SDavid du Colombier 		case 2: vAddEndTag(pDiag, TAG_SECT1); break;
1083f5736e95SDavid du Colombier 		case 3: vAddEndTag(pDiag, TAG_SECT2); break;
1084f5736e95SDavid du Colombier 		case 4: vAddEndTag(pDiag, TAG_SECT3); break;
1085f5736e95SDavid du Colombier 		case 5: vAddEndTag(pDiag, TAG_SECT4); break;
1086f5736e95SDavid du Colombier 		case 6: vAddEndTag(pDiag, TAG_SECT5); break;
1087f5736e95SDavid du Colombier 		default:
1088f5736e95SDavid du Colombier 			DBG_DEC(usHeaderLevelCurrent);
1089f5736e95SDavid du Colombier 			DBG_FIXME();
1090f5736e95SDavid du Colombier 			return;
1091f5736e95SDavid du Colombier 		}
1092f5736e95SDavid du Colombier 	}
1093f5736e95SDavid du Colombier 
1094f5736e95SDavid du Colombier 	DBG_DEC(usHeaderLevelCurrent);
1095f5736e95SDavid du Colombier 
1096f5736e95SDavid du Colombier 	vStackTrace();
1097f5736e95SDavid du Colombier } /* end of vCloseHeaderLevels */
1098f5736e95SDavid du Colombier 
1099f5736e95SDavid du Colombier /*
1100f5736e95SDavid du Colombier  * vSetHeadersXML - set the headers
1101f5736e95SDavid du Colombier  */
1102f5736e95SDavid du Colombier void
vSetHeadersXML(diagram_type * pDiag,USHORT usIstd)1103f5736e95SDavid du Colombier vSetHeadersXML(diagram_type *pDiag, USHORT usIstd)
1104f5736e95SDavid du Colombier {
1105f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1106f5736e95SDavid du Colombier 
1107f5736e95SDavid du Colombier 	if (usIstd == 0 || usIstd > 6) {
1108f5736e95SDavid du Colombier 		DBG_DEC_C(usIstd != 0 && usIstd <= 9, usIstd);
1109f5736e95SDavid du Colombier 		return;
1110f5736e95SDavid du Colombier 	}
1111f5736e95SDavid du Colombier 	DBG_DEC(usIstd);
1112f5736e95SDavid du Colombier 
1113f5736e95SDavid du Colombier 	if (bTableOpen || uiListLevel != 0) {
1114f5736e95SDavid du Colombier 		/* No headers when you're in a table or in a list */
1115f5736e95SDavid du Colombier 		return;
1116f5736e95SDavid du Colombier 	}
1117f5736e95SDavid du Colombier 
1118f5736e95SDavid du Colombier 	/* Close levels */
1119f5736e95SDavid du Colombier 	vCloseHeaderLevels(pDiag, usIstd);
1120f5736e95SDavid du Colombier 
1121f5736e95SDavid du Colombier 	DBG_DEC(usHeaderLevelCurrent);
1122f5736e95SDavid du Colombier 
1123f5736e95SDavid du Colombier 	/* Open levels */
1124f5736e95SDavid du Colombier 	while (usHeaderLevelCurrent < usIstd) {
1125f5736e95SDavid du Colombier 		switch (usHeaderLevelCurrent) {
1126f5736e95SDavid du Colombier 		case 0: vAddStartTag(pDiag, TAG_CHAPTER, NULL); break;
1127f5736e95SDavid du Colombier 		case 1: vAddStartTag(pDiag, TAG_SECT1, NULL); break;
1128f5736e95SDavid du Colombier 		case 2: vAddStartTag(pDiag, TAG_SECT2, NULL); break;
1129f5736e95SDavid du Colombier 		case 3: vAddStartTag(pDiag, TAG_SECT3, NULL); break;
1130f5736e95SDavid du Colombier 		case 4: vAddStartTag(pDiag, TAG_SECT4, NULL); break;
1131f5736e95SDavid du Colombier 		case 5: vAddStartTag(pDiag, TAG_SECT5, NULL); break;
1132f5736e95SDavid du Colombier 		default:
1133f5736e95SDavid du Colombier 			DBG_DEC(usHeaderLevelCurrent);
1134f5736e95SDavid du Colombier 			DBG_FIXME();
1135f5736e95SDavid du Colombier 			return;
1136f5736e95SDavid du Colombier 		}
1137f5736e95SDavid du Colombier 		fail(usIstd == 0);
1138f5736e95SDavid du Colombier 		/* The next paragraph should be a title */
1139f5736e95SDavid du Colombier 		if (usHeaderLevelCurrent < usIstd) {
1140f5736e95SDavid du Colombier 			/* This chapter level is not in the Word document */
1141f5736e95SDavid du Colombier 			vAddCombinedTag(pDiag, TAG_TITLE, NULL);
1142f5736e95SDavid du Colombier 		} else {
1143f5736e95SDavid du Colombier 			vAddStartTag(pDiag, TAG_TITLE, NULL);
1144f5736e95SDavid du Colombier 		}
1145f5736e95SDavid du Colombier 	}
1146f5736e95SDavid du Colombier } /* end of vSetHeadersXML */
1147f5736e95SDavid du Colombier 
1148f5736e95SDavid du Colombier /*
1149f5736e95SDavid du Colombier  * Create a start of a list
1150f5736e95SDavid du Colombier  */
1151f5736e95SDavid du Colombier void
vStartOfListXML(diagram_type * pDiag,UCHAR ucNFC,BOOL bIsEndOfTable)1152f5736e95SDavid du Colombier vStartOfListXML(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
1153f5736e95SDavid du Colombier {
1154f5736e95SDavid du Colombier 	const char	*szAttr;
1155f5736e95SDavid du Colombier 	UCHAR		ucTag;
1156f5736e95SDavid du Colombier 
1157f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1158f5736e95SDavid du Colombier 
1159f5736e95SDavid du Colombier 	if (bIsEndOfTable) {
1160f5736e95SDavid du Colombier 		/* FIXME: until a list in a table is allowed */
1161f5736e95SDavid du Colombier 		vEndOfTableXML(pDiag);
1162f5736e95SDavid du Colombier 	}
1163f5736e95SDavid du Colombier 
1164f5736e95SDavid du Colombier 	if (bTableOpen) {
1165f5736e95SDavid du Colombier 		/* FIXME: a list in a table should be allowed */
1166f5736e95SDavid du Colombier 		return;
1167f5736e95SDavid du Colombier 	}
1168f5736e95SDavid du Colombier 
1169f5736e95SDavid du Colombier 	if (usHeaderLevelCurrent == 0) {
1170f5736e95SDavid du Colombier 		/* No list without an open header */
1171f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_CHAPTER, NULL);
1172f5736e95SDavid du Colombier 		/* Dummy title */
1173f5736e95SDavid du Colombier 		vAddCombinedTag(pDiag, TAG_TITLE, NULL);
1174f5736e95SDavid du Colombier 	}
1175f5736e95SDavid du Colombier 
1176f5736e95SDavid du Colombier 	switch (ucNFC) {
1177f5736e95SDavid du Colombier 	case LIST_ARABIC_NUM:
1178f5736e95SDavid du Colombier 	case LIST_ORDINAL_NUM:
1179*25b329d5SDavid du Colombier 	case LIST_NUMBER_TXT:
1180*25b329d5SDavid du Colombier 	case LIST_ORDINAL_TXT:
1181*25b329d5SDavid du Colombier 	case LIST_OUTLINE_NUM:
1182f5736e95SDavid du Colombier 		ucTag = TAG_ORDEREDLIST;
1183f5736e95SDavid du Colombier 		szAttr = "numeration='arabic'";
1184f5736e95SDavid du Colombier 		break;
1185f5736e95SDavid du Colombier 	case LIST_UPPER_ROMAN:
1186f5736e95SDavid du Colombier 		ucTag = TAG_ORDEREDLIST;
1187f5736e95SDavid du Colombier 		szAttr = "numeration='upperroman'";
1188f5736e95SDavid du Colombier 		break;
1189f5736e95SDavid du Colombier 	case LIST_LOWER_ROMAN:
1190f5736e95SDavid du Colombier 		ucTag = TAG_ORDEREDLIST;
1191f5736e95SDavid du Colombier 		szAttr = "numeration='lowerroman'";
1192f5736e95SDavid du Colombier 		break;
1193f5736e95SDavid du Colombier 	case LIST_UPPER_ALPHA:
1194f5736e95SDavid du Colombier 		ucTag = TAG_ORDEREDLIST;
1195f5736e95SDavid du Colombier 		szAttr = "numeration='upperalpha'";
1196f5736e95SDavid du Colombier 		break;
1197f5736e95SDavid du Colombier 	case LIST_LOWER_ALPHA:
1198f5736e95SDavid du Colombier 		ucTag = TAG_ORDEREDLIST;
1199f5736e95SDavid du Colombier 		szAttr = "numeration='loweralpha'";
1200f5736e95SDavid du Colombier 		break;
1201f5736e95SDavid du Colombier 	case LIST_SPECIAL:
1202*25b329d5SDavid du Colombier 	case LIST_SPECIAL2:
1203f5736e95SDavid du Colombier 	case LIST_BULLETS:
1204f5736e95SDavid du Colombier 		ucTag = TAG_ITEMIZEDLIST;
1205f5736e95SDavid du Colombier 		szAttr = "mark='bullet'";
1206f5736e95SDavid du Colombier 		break;
1207f5736e95SDavid du Colombier 	default:
1208f5736e95SDavid du Colombier 		ucTag = TAG_ORDEREDLIST;
1209f5736e95SDavid du Colombier 		szAttr = "numeration='arabic'";
1210*25b329d5SDavid du Colombier 		DBG_HEX(ucNFC);
1211f5736e95SDavid du Colombier 		DBG_FIXME();
1212f5736e95SDavid du Colombier 		break;
1213f5736e95SDavid du Colombier 	}
1214f5736e95SDavid du Colombier 	vAddStartTag(pDiag, ucTag, szAttr);
1215f5736e95SDavid du Colombier } /* end of vStartOfListXML */
1216f5736e95SDavid du Colombier 
1217f5736e95SDavid du Colombier /*
1218f5736e95SDavid du Colombier  * Create an end of a list
1219f5736e95SDavid du Colombier  */
1220f5736e95SDavid du Colombier void
vEndOfListXML(diagram_type * pDiag)1221f5736e95SDavid du Colombier vEndOfListXML(diagram_type *pDiag)
1222f5736e95SDavid du Colombier {
1223f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1224f5736e95SDavid du Colombier 
1225f5736e95SDavid du Colombier 	if (bTableOpen) {
1226f5736e95SDavid du Colombier 		/* FIXME: a list in a table should be allowed */
1227f5736e95SDavid du Colombier 		return;
1228f5736e95SDavid du Colombier 	}
1229f5736e95SDavid du Colombier 
1230f5736e95SDavid du Colombier 	if (uiListLevel != 0) {
1231f5736e95SDavid du Colombier 		vStackTrace();
1232f5736e95SDavid du Colombier 		vAddEndTagsUntil2(pDiag, TAG_ITEMIZEDLIST, TAG_ORDEREDLIST);
1233f5736e95SDavid du Colombier 		vStackTrace();
1234f5736e95SDavid du Colombier 	}
1235f5736e95SDavid du Colombier } /* end of vEndOfListXML */
1236f5736e95SDavid du Colombier 
1237f5736e95SDavid du Colombier /*
1238f5736e95SDavid du Colombier  * Create a start of a list item
1239f5736e95SDavid du Colombier  */
1240f5736e95SDavid du Colombier void
vStartOfListItemXML(diagram_type * pDiag,BOOL bNoMarks)1241f5736e95SDavid du Colombier vStartOfListItemXML(diagram_type *pDiag, BOOL bNoMarks)
1242f5736e95SDavid du Colombier {
1243f5736e95SDavid du Colombier 	const char	*szAttr;
1244f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
1245f5736e95SDavid du Colombier 
1246f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1247f5736e95SDavid du Colombier 
1248f5736e95SDavid du Colombier 	if (bTableOpen) {
1249f5736e95SDavid du Colombier 		/* FIXME: a list in a table should be allowed */
1250f5736e95SDavid du Colombier 		return;
1251f5736e95SDavid du Colombier 	}
1252f5736e95SDavid du Colombier 
1253f5736e95SDavid du Colombier 	ucTopTag = ucReadStack();
1254f5736e95SDavid du Colombier 	if (ucTopTag != TAG_ITEMIZEDLIST && ucTopTag != TAG_ORDEREDLIST) {
1255f5736e95SDavid du Colombier 		/* Must end a previous list item first */
1256f5736e95SDavid du Colombier 		vAddEndTagsUntil1(pDiag, TAG_LISTITEM);
1257f5736e95SDavid du Colombier 	}
1258f5736e95SDavid du Colombier 
1259f5736e95SDavid du Colombier 	DBG_DEC_C(ucReadStack() != TAG_ITEMIZEDLIST &&
1260f5736e95SDavid du Colombier 		ucReadStack() != TAG_ORDEREDLIST, ucReadStack());
1261f5736e95SDavid du Colombier 
1262f5736e95SDavid du Colombier 	/* Start a new list item */
1263f5736e95SDavid du Colombier 	szAttr = bNoMarks ? "override='none'" : NULL;
1264f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_LISTITEM, szAttr);
1265f5736e95SDavid du Colombier 	/* Start a new paragraph (independant of level) */
1266f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_PARA, NULL);
1267f5736e95SDavid du Colombier } /* end of vStartOfListItemXML */
1268f5736e95SDavid du Colombier 
1269f5736e95SDavid du Colombier /*
1270f5736e95SDavid du Colombier  * Create a start of a table
1271f5736e95SDavid du Colombier  */
1272f5736e95SDavid du Colombier static void
vStartOfTable(diagram_type * pDiag,UCHAR ucBorderInfo)1273f5736e95SDavid du Colombier vStartOfTable(diagram_type *pDiag, UCHAR ucBorderInfo)
1274f5736e95SDavid du Colombier {
1275f5736e95SDavid du Colombier 	const char	*szFrame;
1276f5736e95SDavid du Colombier 	BOOL	bNotReady;
1277f5736e95SDavid du Colombier 	UCHAR	ucTopTag;
1278f5736e95SDavid du Colombier 	char	cColSep, cRowSep;
1279f5736e95SDavid du Colombier 	char	szAttr[40];
1280f5736e95SDavid du Colombier 
1281f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1282f5736e95SDavid du Colombier 
1283f5736e95SDavid du Colombier 	/* Close elements that cannot contain a table */
1284f5736e95SDavid du Colombier 	bNotReady = TRUE;
1285f5736e95SDavid du Colombier 	do {
1286f5736e95SDavid du Colombier 		ucTopTag = ucReadStack();
1287f5736e95SDavid du Colombier 		switch (ucTopTag) {
1288f5736e95SDavid du Colombier 		case TAG_TITLE:
1289f5736e95SDavid du Colombier 			fail(!bTitleOpen);
1290f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_TITLE);
1291f5736e95SDavid du Colombier 			break;
1292f5736e95SDavid du Colombier 		case TAG_EMPHASIS:
1293f5736e95SDavid du Colombier 			fail(!bEmphasisOpen);
1294f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_EMPHASIS);
1295f5736e95SDavid du Colombier 			break;
1296f5736e95SDavid du Colombier 		case TAG_SUPERSCRIPT:
1297f5736e95SDavid du Colombier 			fail(!bSuperscriptOpen);
1298f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_SUPERSCRIPT);
1299f5736e95SDavid du Colombier 			break;
1300f5736e95SDavid du Colombier 		case TAG_SUBSCRIPT:
1301f5736e95SDavid du Colombier 			fail(!bSubscriptOpen);
1302f5736e95SDavid du Colombier 			vAddEndTag(pDiag, TAG_SUBSCRIPT);
1303f5736e95SDavid du Colombier 			break;
1304f5736e95SDavid du Colombier 		default:
1305f5736e95SDavid du Colombier 			bNotReady = FALSE;
1306f5736e95SDavid du Colombier 			break;
1307f5736e95SDavid du Colombier 		}
1308f5736e95SDavid du Colombier 	} while (bNotReady);
1309f5736e95SDavid du Colombier 
1310f5736e95SDavid du Colombier 	/* Create table attributes */
1311f5736e95SDavid du Colombier 	switch (ucBorderInfo) {
1312f5736e95SDavid du Colombier 	case TABLE_BORDER_TOP:
1313f5736e95SDavid du Colombier 		szFrame = "top";
1314f5736e95SDavid du Colombier 		break;
1315f5736e95SDavid du Colombier 	case TABLE_BORDER_LEFT|TABLE_BORDER_RIGHT:
1316f5736e95SDavid du Colombier 		szFrame = "sides";
1317f5736e95SDavid du Colombier 		break;
1318f5736e95SDavid du Colombier 	case TABLE_BORDER_TOP|TABLE_BORDER_BOTTOM:
1319f5736e95SDavid du Colombier 		szFrame = "topbot";
1320f5736e95SDavid du Colombier 		break;
1321f5736e95SDavid du Colombier 	case TABLE_BORDER_BOTTOM:
1322f5736e95SDavid du Colombier 		szFrame = "bottom";
1323f5736e95SDavid du Colombier 		break;
1324f5736e95SDavid du Colombier 	case TABLE_BORDER_TOP|TABLE_BORDER_LEFT|
1325f5736e95SDavid du Colombier 	     TABLE_BORDER_BOTTOM|TABLE_BORDER_RIGHT:
1326f5736e95SDavid du Colombier 		szFrame = "all";
1327f5736e95SDavid du Colombier 		break;
1328f5736e95SDavid du Colombier 	default:
1329f5736e95SDavid du Colombier 		szFrame = "none";
1330f5736e95SDavid du Colombier 		break;
1331f5736e95SDavid du Colombier 	}
1332f5736e95SDavid du Colombier 	cColSep = bIsTableBorderLeft(ucBorderInfo) ||
1333f5736e95SDavid du Colombier 		  bIsTableBorderRight(ucBorderInfo) ? '1' : '0';
1334f5736e95SDavid du Colombier 	cRowSep = bIsTableBorderTop(ucBorderInfo) ||
1335f5736e95SDavid du Colombier 		  bIsTableBorderBottom(ucBorderInfo) ? '1' : '0';
1336f5736e95SDavid du Colombier 
1337f5736e95SDavid du Colombier 	sprintf(szAttr, "frame='%.6s' colsep='%c' rowsep='%c'",
1338f5736e95SDavid du Colombier 			szFrame, cColSep, cRowSep);
1339f5736e95SDavid du Colombier 
1340f5736e95SDavid du Colombier 	if (usHeaderLevelCurrent == 0) {
1341f5736e95SDavid du Colombier 		/* No table without an open header */
1342f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_CHAPTER, NULL);
1343f5736e95SDavid du Colombier 		/* Dummy title */
1344f5736e95SDavid du Colombier 		vAddCombinedTag(pDiag, TAG_TITLE, NULL);
1345f5736e95SDavid du Colombier 	}
1346f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_INFORMALTABLE, szAttr);
1347f5736e95SDavid du Colombier } /* end of vStartOfTable */
1348f5736e95SDavid du Colombier 
1349f5736e95SDavid du Colombier /*
1350f5736e95SDavid du Colombier  * Create a start of a table group
1351f5736e95SDavid du Colombier  */
1352f5736e95SDavid du Colombier static void
vStartOfTableGroup(diagram_type * pDiag,int iNbrOfColumns,const short * asColumnWidth)1353f5736e95SDavid du Colombier vStartOfTableGroup(diagram_type *pDiag,
1354f5736e95SDavid du Colombier 	int iNbrOfColumns, const short *asColumnWidth)
1355f5736e95SDavid du Colombier {
1356f5736e95SDavid du Colombier 	double	dWidth;
1357f5736e95SDavid du Colombier 	int	iIndex;
1358f5736e95SDavid du Colombier 	char	szCols[6 + 3 * sizeof(int) + 1 + 1];
1359f5736e95SDavid du Colombier 	char	szColWidth[10 + 3 * sizeof(short) + 3 + 3 + 1];
1360f5736e95SDavid du Colombier 
1361f5736e95SDavid du Colombier 	fail(iNbrOfColumns < 1);
1362f5736e95SDavid du Colombier 	fail(asColumnWidth == NULL);
1363f5736e95SDavid du Colombier 
1364f5736e95SDavid du Colombier 	sprintf(szCols, "cols='%d'", iNbrOfColumns);
1365f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_TGROUP, szCols);
1366f5736e95SDavid du Colombier 
1367f5736e95SDavid du Colombier 	for (iIndex= 0; iIndex < iNbrOfColumns; iIndex++) {
1368f5736e95SDavid du Colombier 		fail(asColumnWidth[iIndex] < 0);
1369f5736e95SDavid du Colombier 		dWidth = dTwips2Points(asColumnWidth[iIndex]);
1370f5736e95SDavid du Colombier 		if (dWidth <= 1.0) {
1371f5736e95SDavid du Colombier 			strcpy(szColWidth, "colwidth='1.00pt'");
1372f5736e95SDavid du Colombier 		} else {
1373f5736e95SDavid du Colombier 			sprintf(szColWidth, "colwidth='%.2fpt'", dWidth);
1374f5736e95SDavid du Colombier 		}
1375f5736e95SDavid du Colombier 		vAddCombinedTag(pDiag, TAG_COLSPEC, szColWidth);
1376f5736e95SDavid du Colombier 	}
1377f5736e95SDavid du Colombier } /* end of vStartOfTableGroup */
1378f5736e95SDavid du Colombier 
1379f5736e95SDavid du Colombier /*
1380f5736e95SDavid du Colombier  * Create an end of a table
1381f5736e95SDavid du Colombier  */
1382f5736e95SDavid du Colombier void
vEndOfTableXML(diagram_type * pDiag)1383f5736e95SDavid du Colombier vEndOfTableXML(diagram_type *pDiag)
1384f5736e95SDavid du Colombier {
1385f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1386f5736e95SDavid du Colombier 
1387f5736e95SDavid du Colombier 	if (bTableOpen) {
1388f5736e95SDavid du Colombier 		vAddEndTag(pDiag, TAG_TBODY);
1389f5736e95SDavid du Colombier 		vAddEndTag(pDiag, TAG_TGROUP);
1390f5736e95SDavid du Colombier 		vAddEndTag(pDiag, TAG_INFORMALTABLE);
1391f5736e95SDavid du Colombier 	}
1392f5736e95SDavid du Colombier } /* end of vEndOfTableXML */
1393f5736e95SDavid du Colombier 
1394f5736e95SDavid du Colombier /*
1395f5736e95SDavid du Colombier  * Add a table row
1396f5736e95SDavid du Colombier  */
1397f5736e95SDavid du Colombier void
vAddTableRowXML(diagram_type * pDiag,char ** aszColTxt,int iNbrOfColumns,const short * asColumnWidth,UCHAR ucBorderInfo)1398f5736e95SDavid du Colombier vAddTableRowXML(diagram_type *pDiag, char **aszColTxt,
1399f5736e95SDavid du Colombier 	int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
1400f5736e95SDavid du Colombier {
1401f5736e95SDavid du Colombier 	size_t	tCount, tStringLength;
1402f5736e95SDavid du Colombier 	int	iIndex;
1403f5736e95SDavid du Colombier 
1404f5736e95SDavid du Colombier 	fail(pDiag == NULL);
1405f5736e95SDavid du Colombier 	fail(pDiag->pOutFile == NULL);
1406f5736e95SDavid du Colombier 	fail(aszColTxt == NULL);
1407f5736e95SDavid du Colombier 	fail(iNbrOfColumns < 1);
1408f5736e95SDavid du Colombier 	fail(asColumnWidth == NULL);
1409f5736e95SDavid du Colombier 
1410f5736e95SDavid du Colombier 	if (iNbrOfColumns != iTableColumnsCurrent) {
1411f5736e95SDavid du Colombier 		/* A new number of columns */
1412f5736e95SDavid du Colombier 		/* End the old table body and table group (if they exist) */
1413f5736e95SDavid du Colombier 		vAddEndTagOptional(pDiag, TAG_TBODY);
1414f5736e95SDavid du Colombier 		vAddEndTagOptional(pDiag, TAG_TGROUP);
1415f5736e95SDavid du Colombier 		if (!bTableOpen) {
1416f5736e95SDavid du Colombier 			/* No table yet. Start a new table */
1417f5736e95SDavid du Colombier 			vStartOfTable(pDiag, ucBorderInfo);
1418f5736e95SDavid du Colombier 		}
1419f5736e95SDavid du Colombier 		/* Start a new table group and a new table body */
1420f5736e95SDavid du Colombier 		vStartOfTableGroup(pDiag, iNbrOfColumns, asColumnWidth);
1421f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_TBODY, NULL);
1422f5736e95SDavid du Colombier 		iTableColumnsCurrent = iNbrOfColumns;
1423f5736e95SDavid du Colombier 	}
1424f5736e95SDavid du Colombier 
1425f5736e95SDavid du Colombier 	/* Add the table row */
1426f5736e95SDavid du Colombier 	vAddStartTag(pDiag, TAG_ROW, NULL);
1427f5736e95SDavid du Colombier 	for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
1428f5736e95SDavid du Colombier 		/* Add a table cell */
1429f5736e95SDavid du Colombier 		fail(aszColTxt[iIndex] == NULL);
1430f5736e95SDavid du Colombier 		vAddStartTag(pDiag, TAG_ENTRY, NULL);
1431f5736e95SDavid du Colombier 		tStringLength = strlen(aszColTxt[iIndex]);
1432f5736e95SDavid du Colombier 		for (tCount = 0; tCount < tStringLength; tCount++) {
1433*25b329d5SDavid du Colombier 			vPrintChar(pDiag, aszColTxt[iIndex][tCount]);
1434f5736e95SDavid du Colombier 		}
1435f5736e95SDavid du Colombier 		vAddEndTag(pDiag, TAG_ENTRY);
1436f5736e95SDavid du Colombier 	}
1437f5736e95SDavid du Colombier 	vAddEndTag(pDiag, TAG_ROW);
1438f5736e95SDavid du Colombier } /* end of vAddTableRowXML */
1439