3 * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
6 * Functions to deal with the XML/DocBook format
14 #define vAddEndTagsUntil1(p,t) vAddEndTagsUntil2(p,t,TAG_NOTAG)
17 #define vStackTrace() __vStackTrace(__LINE__)
19 #define vStackTrace() /* EMPTY */
22 /* The character set */
23 static encoding_type eEncoding
= encoding_neutral
;
25 static int iWordVersion
= -1;
26 /* Special treatment for files from Word 4/5/6 on an Apple Macintosh */
27 static BOOL bOldMacFile
= FALSE
;
28 /* Text is emphasised */
29 static BOOL bEmphasisOpen
= FALSE
;
30 /* Text is superscript */
31 static BOOL bSuperscriptOpen
= FALSE
;
32 /* Text is subscript */
33 static BOOL bSubscriptOpen
= FALSE
;
35 static BOOL bTitleOpen
= FALSE
;
37 static BOOL bTableOpen
= FALSE
;
38 /* Footnote is open */
39 static BOOL bFootnoteOpen
= FALSE
;
40 /* Current paragraph level */
41 static UINT uiParagraphLevel
= 0;
42 /* Current list level */
43 static UINT uiListLevel
= 0;
44 /* Current list level is still empty */
45 static BOOL bEmptyListLevel
= TRUE
;
46 /* Current header level */
47 static USHORT usHeaderLevelCurrent
= 0;
48 /* Current header level is still empty */
49 static BOOL bEmptyHeaderLevel
= TRUE
;
50 /* Number of columns in the current table */
51 static int iTableColumnsCurrent
= 0;
53 static UINT uiFootnoteNumber
= 0;
55 /* Constants for the stack */
56 #define INITIAL_STACK_SIZE 10
58 #define EXTENSION_STACK_SIZE 2
60 #define EXTENSION_STACK_SIZE 10
63 /* Variables for the stack */
64 static UCHAR
*aucStack
= NULL
;
65 static size_t tStacksize
= 0;
66 static size_t tStackNextFree
= 0;
68 /* Constants for the tags */
69 #define TAG_NOTAG (UCHAR)0
70 #define TAG_AUTHOR (UCHAR)1
71 #define TAG_BEGINPAGE (UCHAR)2
72 #define TAG_BOOK (UCHAR)3
73 #define TAG_BOOKINFO (UCHAR)4
74 #define TAG_CHAPTER (UCHAR)5
75 #define TAG_COLSPEC (UCHAR)6
76 #define TAG_CORPNAME (UCHAR)7
77 #define TAG_DATE (UCHAR)8
78 #define TAG_EMPHASIS (UCHAR)9
79 #define TAG_ENTRY (UCHAR)10
80 #define TAG_FILENAME (UCHAR)11
81 #define TAG_FOOTNOTE (UCHAR)12
82 #define TAG_INFORMALTABLE (UCHAR)13
83 #define TAG_ITEMIZEDLIST (UCHAR)14
84 #define TAG_LISTITEM (UCHAR)15
85 #define TAG_ORDEREDLIST (UCHAR)16
86 #define TAG_PARA (UCHAR)17
87 #define TAG_ROW (UCHAR)18
88 #define TAG_SECT1 (UCHAR)19
89 #define TAG_SECT2 (UCHAR)20
90 #define TAG_SECT3 (UCHAR)21
91 #define TAG_SECT4 (UCHAR)22
92 #define TAG_SECT5 (UCHAR)23
93 #define TAG_SUBSCRIPT (UCHAR)24
94 #define TAG_SUBTITLE (UCHAR)25
95 #define TAG_SUPERSCRIPT (UCHAR)26
96 #define TAG_SURNAME (UCHAR)27
97 #define TAG_TBODY (UCHAR)28
98 #define TAG_TGROUP (UCHAR)29
99 #define TAG_TITLE (UCHAR)30
101 typedef struct docbooktags_tag
{
104 BOOL bAddNewlineStart
;
108 static const docbooktags_type atDocBookTags
[] = {
109 { TAG_NOTAG
, "!ERROR!", TRUE
, TRUE
},
110 { TAG_AUTHOR
, "author", TRUE
, TRUE
},
111 { TAG_BEGINPAGE
, "beginpage", TRUE
, TRUE
},
112 { TAG_BOOK
, "book", TRUE
, TRUE
},
113 { TAG_BOOKINFO
, "bookinfo", TRUE
, TRUE
},
114 { TAG_CHAPTER
, "chapter", TRUE
, TRUE
},
115 { TAG_COLSPEC
, "colspec", TRUE
, TRUE
},
116 { TAG_CORPNAME
, "corpname", FALSE
, FALSE
},
117 { TAG_DATE
, "date", FALSE
, FALSE
},
118 { TAG_EMPHASIS
, "emphasis", FALSE
, FALSE
},
119 { TAG_ENTRY
, "entry", TRUE
, TRUE
},
120 { TAG_FILENAME
, "filename", FALSE
, FALSE
},
121 { TAG_FOOTNOTE
, "footnote", FALSE
, FALSE
},
122 { TAG_INFORMALTABLE
, "informaltable",TRUE
, TRUE
},
123 { TAG_ITEMIZEDLIST
, "itemizedlist", TRUE
, TRUE
},
124 { TAG_LISTITEM
, "listitem", TRUE
, TRUE
},
125 { TAG_ORDEREDLIST
, "orderedlist", TRUE
, TRUE
},
126 { TAG_PARA
, "para", TRUE
, TRUE
},
127 { TAG_ROW
, "row", TRUE
, TRUE
},
128 { TAG_SECT1
, "sect1", TRUE
, TRUE
},
129 { TAG_SECT2
, "sect2", TRUE
, TRUE
},
130 { TAG_SECT3
, "sect3", TRUE
, TRUE
},
131 { TAG_SECT4
, "sect4", TRUE
, TRUE
},
132 { TAG_SECT5
, "sect5", TRUE
, TRUE
},
133 { TAG_SUBSCRIPT
, "subscript", FALSE
, FALSE
},
134 { TAG_SUBTITLE
, "subtitle", FALSE
, FALSE
},
135 { TAG_SUPERSCRIPT
, "superscript", FALSE
, FALSE
},
136 { TAG_SURNAME
, "surname", FALSE
, FALSE
},
137 { TAG_TBODY
, "tbody", TRUE
, TRUE
},
138 { TAG_TGROUP
, "tgroup", TRUE
, TRUE
},
139 { TAG_TITLE
, "title", FALSE
, FALSE
},
142 static void vAddStartTag(diagram_type
*, UCHAR
, const char *);
143 static void vAddEndTag(diagram_type
*, UCHAR
);
144 static void vAddCombinedTag(diagram_type
*, UCHAR
, const char *);
145 static void vPrintChar(diagram_type
*, char);
150 * vCheckTagTable - check the tag table
157 for (tIndex
= 0; tIndex
< elementsof(atDocBookTags
); tIndex
++) {
158 if (tIndex
!= (size_t)atDocBookTags
[tIndex
].ucTagnumber
) {
160 werr(1, "Array atDocBookTags is broken");
163 } /* end of vCheckTagTable */
166 * __vStackTrace - show a stack trace
169 __vStackTrace(int iLine
)
173 fprintf(stderr
, "%s[%3d]:\n", __FILE__
, iLine
);
175 if (tStackNextFree
== 0) {
176 fprintf(stderr
, "The stack is empty\n");
179 for (iIndex
= (int)tStackNextFree
- 1; iIndex
>= 0; iIndex
--) {
180 fprintf(stderr
, "%2d: %2d: '%s'\n",
182 (int)atDocBookTags
[(UINT
)aucStack
[iIndex
]].ucTagnumber
,
183 atDocBookTags
[(UINT
)aucStack
[iIndex
]].szTagname
);
185 } /* end of __vStackTrace */
189 * vPushStack - push a tag onto the stack
192 vPushStack(UCHAR ucTag
)
194 fail(tStackNextFree
> tStacksize
);
196 if (tStackNextFree
== tStacksize
) {
197 /* The stack is full; enlarge the stack */
198 tStacksize
+= EXTENSION_STACK_SIZE
;
199 aucStack
= xrealloc(aucStack
, tStacksize
* sizeof(UCHAR
));
203 fail(tStackNextFree
>= tStacksize
);
205 aucStack
[tStackNextFree
++] = ucTag
;
206 } /* end of vPushStack */
209 * vPopStack - pop a tag from the stack
214 DBG_DEC_C(tStackNextFree
> tStacksize
, tStackNextFree
);
215 DBG_DEC_C(tStackNextFree
> tStacksize
, tStacksize
);
216 fail(tStackNextFree
> tStacksize
);
217 fail(tStackNextFree
== 0);
219 if (tStackNextFree
== 0) {
220 werr(1, "The stack is empty, unable to continue");
223 return aucStack
[--tStackNextFree
];
224 } /* end of ucPopStack */
227 * vReadStack - read a tag from the top of the stack
232 DBG_DEC_C(tStackNextFree
> tStacksize
, tStackNextFree
);
233 DBG_DEC_C(tStackNextFree
> tStacksize
, tStacksize
);
234 fail(tStackNextFree
> tStacksize
);
236 if (tStackNextFree
== 0) {
237 /* The stack is empty */
240 return aucStack
[tStackNextFree
- 1];
241 } /* end of ucReadStack */
244 * vPrintLevel - print the tag level
247 vPrintLevel(FILE *pOutFile
)
251 fail(pOutFile
== NULL
);
253 for (tIndex
= 0; tIndex
< tStackNextFree
; tIndex
++) {
254 (void)putc(' ', pOutFile
);
256 } /* end of vPrintLevel */
259 * vPrintFootnote - print a footnote
262 vPrintFootnote(diagram_type
*pDiag
, UINT uiFootnoteIndex
)
264 const char *szText
, *pcTmp
;
268 TRACE_MSG("vPrintFootnote");
270 szText
= szGetFootnootText(uiFootnoteIndex
);
272 if (szText
== NULL
) {
276 /* Remove the subscript/superscript (if any) */
277 ucTopTag
= ucReadStack();
278 bSuScript
= ucTopTag
== TAG_SUBSCRIPT
|| ucTopTag
== TAG_SUPERSCRIPT
;
280 vAddEndTag(pDiag
, ucTopTag
);
283 /* Start a footnote */
284 vAddStartTag(pDiag
, TAG_FOOTNOTE
, NULL
);
285 vAddStartTag(pDiag
, TAG_PARA
, NULL
);
287 /* Print a footnote */
288 for (pcTmp
= szText
; *pcTmp
!= '\0'; pcTmp
++) {
289 if (*pcTmp
== PAR_END
) {
290 if (*(pcTmp
+ 1) != PAR_END
&& *(pcTmp
+ 1) != '\0') {
291 /* PAR_END is not empty and not last */
292 vAddEndTag(pDiag
, TAG_PARA
);
293 vAddStartTag(pDiag
, TAG_PARA
, NULL
);
296 vPrintChar(pDiag
, *pcTmp
);
301 vAddEndTag(pDiag
, TAG_PARA
);
302 vAddEndTag(pDiag
, TAG_FOOTNOTE
);
304 /* Repair the subscript/superscript (if any) */
306 vAddStartTag(pDiag
, ucTopTag
, NULL
);
308 } /* end of vPrintFootnote */
311 * vPrintChar - print a character with XML encoding
314 vPrintChar(diagram_type
*pDiag
, char cChar
)
317 fail(pDiag
->pOutFile
== NULL
);
320 case FOOTNOTE_OR_ENDNOTE
:
322 vPrintFootnote(pDiag
, uiFootnoteNumber
- 1);
325 fprintf(pDiag
->pOutFile
, "%s", "<");
328 fprintf(pDiag
->pOutFile
, "%s", ">");
331 fprintf(pDiag
->pOutFile
, "%s", "&");
334 (void)putc(cChar
, pDiag
->pOutFile
);
337 } /* end of vPrintChar */
340 * vPrintSpecialChar - convert and print a character
343 vPrintSpecialChar(diagram_type
*pDiag
, USHORT usChar
)
350 fail(pDiag
->pOutFile
== NULL
);
351 fail(iWordVersion
< 0);
352 fail(eEncoding
== encoding_neutral
);
354 ulChar
= ulTranslateCharacters(usChar
, 0, iWordVersion
,
355 conversion_xml
, eEncoding
, bOldMacFile
);
356 tLen
= tUcs2Utf8(ulChar
, szResult
, sizeof(szResult
));
358 vPrintChar(pDiag
, szResult
[0]);
360 for (tIndex
= 0; tIndex
< tLen
; tIndex
++) {
361 (void)putc(szResult
[tIndex
], pDiag
->pOutFile
);
364 } /* end of vPrintSpecialChar */
367 * vPrintSpecialString - convert and print a string
370 vPrintSpecialString(diagram_type
*pDiag
, const char *szString
)
376 fail(pDiag
->pOutFile
== NULL
);
377 fail(szString
== NULL
);
379 for (iIndex
= 0; szString
[iIndex
] != '\0'; iIndex
++) {
380 usChar
= (USHORT
)(UCHAR
)szString
[iIndex
];
381 vPrintSpecialChar(pDiag
, usChar
);
383 } /* end of vPrintSpecialString */
386 * vAddStartTag - add the specified start tag to the file
389 vAddStartTag(diagram_type
*pDiag
, UCHAR ucTag
, const char *szAttribute
)
392 fail(pDiag
->pOutFile
== NULL
);
393 fail((size_t)ucTag
>= elementsof(atDocBookTags
));
395 if (atDocBookTags
[(UINT
)ucTag
].bAddNewlineStart
) {
396 fprintf(pDiag
->pOutFile
, "\n");
397 vPrintLevel(pDiag
->pOutFile
);
400 if (szAttribute
== NULL
|| szAttribute
[0] == '\0') {
401 fprintf(pDiag
->pOutFile
, "<%s>",
402 atDocBookTags
[(UINT
)ucTag
].szTagname
);
404 fprintf(pDiag
->pOutFile
, "<%s %s>",
405 atDocBookTags
[(UINT
)ucTag
].szTagname
, szAttribute
);
408 if (atDocBookTags
[(UINT
)ucTag
].bAddNewlineEnd
) {
409 fprintf(pDiag
->pOutFile
, "\n");
415 /* Set global variables */
418 usHeaderLevelCurrent
= 1;
419 bEmptyHeaderLevel
= TRUE
;
422 usHeaderLevelCurrent
= 2;
423 bEmptyHeaderLevel
= TRUE
;
426 usHeaderLevelCurrent
= 3;
427 bEmptyHeaderLevel
= TRUE
;
430 usHeaderLevelCurrent
= 4;
431 bEmptyHeaderLevel
= TRUE
;
434 usHeaderLevelCurrent
= 5;
435 bEmptyHeaderLevel
= TRUE
;
438 usHeaderLevelCurrent
= 6;
439 bEmptyHeaderLevel
= TRUE
;
442 fail(uiParagraphLevel
!= 0);
446 bFootnoteOpen
= TRUE
;
449 fail(bTitleOpen
&& !bFootnoteOpen
);
451 bEmptyHeaderLevel
= FALSE
;
454 bEmphasisOpen
= TRUE
;
456 case TAG_ITEMIZEDLIST
:
457 case TAG_ORDEREDLIST
:
459 bEmptyListLevel
= TRUE
;
460 bEmptyHeaderLevel
= FALSE
;
463 bEmptyListLevel
= FALSE
;
465 case TAG_SUPERSCRIPT
:
466 bSuperscriptOpen
= TRUE
;
469 bSubscriptOpen
= TRUE
;
471 case TAG_INFORMALTABLE
:
473 bEmptyHeaderLevel
= FALSE
;
478 } /* end of vAddStartTag */
481 * vAddEndTag - add the specified end tag to the file
484 vAddEndTag(diagram_type
*pDiag
, UCHAR ucTag
)
489 fail(pDiag
->pOutFile
== NULL
);
490 fail((size_t)ucTag
>= elementsof(atDocBookTags
));
493 ucTopTag
= ucReadStack();
494 if (ucTag
!= ucTopTag
) {
496 DBG_MSG(atDocBookTags
[(UINT
)ucTag
].szTagname
);
501 ucTopTag
= ucPopStack();
502 fail((size_t)ucTopTag
>= elementsof(atDocBookTags
));
503 if (ucTag
!= ucTopTag
) {
507 werr(1, "Impossible tag sequence, unable to continue");
510 if (atDocBookTags
[(UINT
)ucTag
].bAddNewlineEnd
) {
511 fprintf(pDiag
->pOutFile
, "\n");
512 vPrintLevel(pDiag
->pOutFile
);
515 fprintf(pDiag
->pOutFile
, "</%s>", atDocBookTags
[(UINT
)ucTag
].szTagname
);
517 if (atDocBookTags
[(UINT
)ucTag
].bAddNewlineStart
) {
518 fprintf(pDiag
->pOutFile
, "\n");
522 /* Set global variables */
525 usHeaderLevelCurrent
= 0;
528 usHeaderLevelCurrent
= 1;
531 usHeaderLevelCurrent
= 2;
534 usHeaderLevelCurrent
= 3;
537 usHeaderLevelCurrent
= 4;
540 usHeaderLevelCurrent
= 5;
546 bFootnoteOpen
= FALSE
;
552 bEmphasisOpen
= FALSE
;
554 case TAG_SUPERSCRIPT
:
555 bSuperscriptOpen
= FALSE
;
557 case TAG_ITEMIZEDLIST
:
558 case TAG_ORDEREDLIST
:
562 bSubscriptOpen
= FALSE
;
564 case TAG_INFORMALTABLE
:
566 iTableColumnsCurrent
= 0;
571 } /* end of vAddEndTag */
574 * vAddEndTagOptional - add the specified end tag to the file if needed
577 vAddEndTagOptional(diagram_type
*pDiag
, UCHAR ucTag
)
581 ucTopTag
= ucReadStack();
582 if (ucTag
== ucTopTag
) {
583 vAddEndTag(pDiag
, ucTag
);
585 } /* end of vAddEndTagOptional */
588 * vAddCombinedTag - add the specified start and end tag to the file
591 vAddCombinedTag(diagram_type
*pDiag
, UCHAR ucTag
, const char *szAttribute
)
594 fail(pDiag
->pOutFile
== NULL
);
595 fail((size_t)ucTag
>= elementsof(atDocBookTags
));
597 if (atDocBookTags
[(UINT
)ucTag
].bAddNewlineStart
) {
598 fprintf(pDiag
->pOutFile
, "\n");
599 vPrintLevel(pDiag
->pOutFile
);
602 if (szAttribute
== NULL
|| szAttribute
[0] == '\0') {
603 fprintf(pDiag
->pOutFile
, "<%s/>",
604 atDocBookTags
[(UINT
)ucTag
].szTagname
);
606 fprintf(pDiag
->pOutFile
, "<%s %s/>",
607 atDocBookTags
[(UINT
)ucTag
].szTagname
, szAttribute
);
610 if (atDocBookTags
[(UINT
)ucTag
].bAddNewlineStart
) {
611 fprintf(pDiag
->pOutFile
, "\n");
614 } /* end of vAddCombinedTag */
617 * vAddEndTagsUntil2 - add end tags until one the specified tags is seen
620 vAddEndTagsUntil2(diagram_type
*pDiag
, UCHAR ucTag1
, UCHAR ucTag2
)
625 ucTopTag
= ucReadStack();
633 if (bEmptyHeaderLevel
) {
635 * An empty chapter is legal in Word,
636 * but not in DocBook.
638 vAddCombinedTag(pDiag
, TAG_PARA
, NULL
);
639 bEmptyHeaderLevel
= FALSE
;
642 case TAG_ITEMIZEDLIST
:
643 case TAG_ORDEREDLIST
:
644 if (bEmptyListLevel
) {
646 * A list without items is legal in Word,
647 * but not in DocBook. (Nor are empty items)
649 vAddStartTag(pDiag
, TAG_LISTITEM
, NULL
);
650 vAddCombinedTag(pDiag
, TAG_PARA
, NULL
);
651 vAddEndTag(pDiag
, TAG_LISTITEM
);
652 bEmptyListLevel
= FALSE
;
658 vAddEndTag(pDiag
, ucTopTag
);
659 } while (ucTopTag
!= ucTag1
&& ucTopTag
!= ucTag2
);
660 } /* end of vAddEndTagsUntil2 */
663 * vCreateBookIntro - create title and bookinfo
666 vCreateBookIntro(diagram_type
*pDiag
, int iVersion
)
668 const char *szTitle
, *szSubject
, *szAuthor
;
669 const char *szLastSaveDtm
, *szCompany
;
670 const char *szLanguage
;
674 fail(pDiag
->pOutFile
== NULL
);
676 fail(eEncoding
== encoding_neutral
);
678 iWordVersion
= iVersion
;
679 bOldMacFile
= bIsOldMacFile();
680 szTitle
= szGetTitle();
681 szSubject
= szGetSubject();
682 szAuthor
= szGetAuthor();
683 szLastSaveDtm
= szGetLastSaveDtm();
684 szCompany
= szGetCompany();
687 szLanguage
= szGetLanguage();
688 if (szLanguage
!= NULL
) {
690 sprintf(szTmp
, "lang='%.5s'", szLanguage
);
693 vAddStartTag(pDiag
, TAG_BOOK
, szLanguage
);
696 if (szTitle
!= NULL
&& szTitle
[0] != '\0') {
697 vAddStartTag(pDiag
, TAG_TITLE
, NULL
);
698 vPrintSpecialString(pDiag
, szTitle
);
699 vAddEndTag(pDiag
, TAG_TITLE
);
702 if ((szTitle
!= NULL
&& szTitle
[0] != '\0') ||
703 (szSubject
!= NULL
&& szSubject
[0] != '\0') ||
704 (szAuthor
!= NULL
&& szAuthor
[0] != '\0') ||
705 (szLastSaveDtm
!= NULL
&& szLastSaveDtm
[0] != '\0') ||
706 (szCompany
!= NULL
&& szCompany
[0] != '\0')) {
707 vAddStartTag(pDiag
, TAG_BOOKINFO
, NULL
);
708 if (szTitle
!= NULL
&& szTitle
[0] != '\0') {
709 vAddStartTag(pDiag
, TAG_TITLE
, NULL
);
710 vPrintSpecialString(pDiag
, szTitle
);
711 vAddEndTag(pDiag
, TAG_TITLE
);
713 if (szSubject
!= NULL
&& szSubject
[0] != '\0') {
714 vAddStartTag(pDiag
, TAG_SUBTITLE
, NULL
);
715 vPrintSpecialString(pDiag
, szSubject
);
716 vAddEndTag(pDiag
, TAG_SUBTITLE
);
718 if (szAuthor
!= NULL
&& szAuthor
[0] != '\0') {
719 vAddStartTag(pDiag
, TAG_AUTHOR
, NULL
);
720 vAddStartTag(pDiag
, TAG_SURNAME
, NULL
);
721 vPrintSpecialString(pDiag
, szAuthor
);
722 vAddEndTag(pDiag
, TAG_SURNAME
);
723 vAddEndTag(pDiag
, TAG_AUTHOR
);
725 if (szLastSaveDtm
!= NULL
&& szLastSaveDtm
[0] != '\0') {
726 vAddStartTag(pDiag
, TAG_DATE
, NULL
);
727 vPrintSpecialString(pDiag
, szLastSaveDtm
);
728 vAddEndTag(pDiag
, TAG_DATE
);
730 if (szCompany
!= NULL
&& szCompany
[0] != '\0') {
731 vAddStartTag(pDiag
, TAG_CORPNAME
, NULL
);
732 vPrintSpecialString(pDiag
, szCompany
);
733 vAddEndTag(pDiag
, TAG_CORPNAME
);
735 vAddEndTag(pDiag
, TAG_BOOKINFO
);
737 } /* end of vCreateBookIntro */
740 * vPrologueXML - perform the XML initialization
743 vPrologueXML(diagram_type
*pDiag
, const options_type
*pOptions
)
747 fail(pDiag
->pOutFile
== NULL
);
748 fail(pOptions
== NULL
);
754 /* Set global variables to their start values */
755 eEncoding
= pOptions
->eEncoding
;
756 bEmphasisOpen
= FALSE
;
757 bSuperscriptOpen
= FALSE
;
758 bSubscriptOpen
= FALSE
;
761 bFootnoteOpen
= FALSE
;
762 uiParagraphLevel
= 0;
764 bEmptyListLevel
= TRUE
;
765 usHeaderLevelCurrent
= 0;
766 bEmptyHeaderLevel
= TRUE
;
767 iTableColumnsCurrent
= 0;
768 uiFootnoteNumber
= 0;
773 /* Create an empty stack */
774 tStacksize
= INITIAL_STACK_SIZE
;
775 aucStack
= xcalloc(tStacksize
, sizeof(UCHAR
));
777 } /* end of vPrologueXML */
780 * vEpilogueXML - clean up after everything is done
783 vEpilogueXML(diagram_type
*pDiag
)
787 vAddEndTagsUntil1(pDiag
, TAG_BOOK
);
791 /* Destroy the stack */
792 fail(tStackNextFree
!= 0);
794 aucStack
= xfree(aucStack
);
796 } /* end of vEpilogueXML */
799 * vPrintXML - print a XML string
802 vPrintXML(diagram_type
*pDiag
, const char *szString
, size_t tStringLength
,
808 BOOL bNotReady
, bEmphasisNew
, bSuperscriptNew
, bSubscriptNew
;
809 UCHAR ucTopTag
, aucStorage
[3];
811 fail(szString
== NULL
);
813 if (szString
== NULL
|| szString
[0] == '\0' || tStringLength
== 0) {
817 if (tStringLength
== 1 && szString
[0] == FOOTNOTE_OR_ENDNOTE
) {
818 /* Don't do anything special for just a single footnote */
819 bEmphasisNew
= FALSE
;
820 bSuperscriptNew
= FALSE
;
821 bSubscriptNew
= FALSE
;
823 /* Situation normal */
824 bEmphasisNew
= bIsBold(usFontstyle
) ||
825 bIsItalic(usFontstyle
) ||
826 bIsUnderline(usFontstyle
) ||
827 bIsStrike(usFontstyle
);
828 bSuperscriptNew
= bIsSuperscript(usFontstyle
);
829 bSubscriptNew
= bIsSubscript(usFontstyle
);
832 /* End what has to be ended (or more to keep the stack happy) */
836 ucTopTag
= ucReadStack();
839 fail(!bEmphasisOpen
);
841 aucStorage
[tNextFree
++] = ucTopTag
;
843 vAddEndTag(pDiag
, ucTopTag
);
845 case TAG_SUPERSCRIPT
:
846 fail(!bSuperscriptOpen
);
847 if (bSuperscriptNew
) {
848 aucStorage
[tNextFree
++] = ucTopTag
;
850 vAddEndTag(pDiag
, ucTopTag
);
853 fail(!bSubscriptOpen
);
855 aucStorage
[tNextFree
++] = ucTopTag
;
857 vAddEndTag(pDiag
, ucTopTag
);
863 fail(tNextFree
> elementsof(aucStorage
));
864 fail(bNotReady
&& tNextFree
== elementsof(aucStorage
));
867 /* Just te make sure */
868 vStartOfParagraphXML(pDiag
, 1);
870 /* Restart to keep the stack happy */
871 for (iCount
= (int)tNextFree
- 1; iCount
> 0; iCount
--) {
872 vAddStartTag(pDiag
, aucStorage
[iCount
], NULL
);
875 /* Start what has to be started */
876 if (bEmphasisNew
&& !bEmphasisOpen
) {
877 if (bIsBold(usFontstyle
)) {
878 szAttr
= "role='bold'";
879 } else if (bIsItalic(usFontstyle
)) {
881 } else if (bIsUnderline(usFontstyle
)) {
882 szAttr
= "role='underline'";
883 } else if (bIsStrike(usFontstyle
)) {
884 szAttr
= "role='strikethrough'";
888 vAddStartTag(pDiag
, TAG_EMPHASIS
, szAttr
);
890 if (bSuperscriptNew
&& !bSuperscriptOpen
) {
891 vAddStartTag(pDiag
, TAG_SUPERSCRIPT
, NULL
);
893 if (bSubscriptNew
&& !bSubscriptOpen
) {
894 vAddStartTag(pDiag
, TAG_SUBSCRIPT
, NULL
);
897 /* The print the string */
898 for (iCount
= 0; iCount
< (int)tStringLength
; iCount
++) {
899 vPrintChar(pDiag
, szString
[iCount
]);
901 } /* end of vPrintXML */
904 * vMove2NextLineXML - move to the next line
907 vMove2NextLineXML(diagram_type
*pDiag
)
912 if (uiParagraphLevel != 0) {
913 We need something like HTML's <BR> tag
916 } /* end of vMove2NextLineXML */
919 * vSubstringXML - put a sub string into a diagram
922 vSubstringXML(diagram_type
*pDiag
,
923 const char *szString
, size_t tStringLength
, long lStringWidth
,
926 fail(pDiag
== NULL
|| szString
== NULL
);
927 fail(pDiag
->pOutFile
== NULL
);
928 fail(pDiag
->lXleft
< 0);
929 fail(tStringLength
!= strlen(szString
));
931 if (szString
[0] == '\0' || tStringLength
== 0) {
935 vPrintXML(pDiag
, szString
, tStringLength
, usFontstyle
);
936 pDiag
->lXleft
+= lStringWidth
;
937 } /* end of vSubstringXML */
940 * Create an start of a paragraph
941 * Only works on paragraph level one, because Word doesn't allow paragraphs
942 * in paragraphs. Other paragraph levels result from DocBooks special needs.
945 vStartOfParagraphXML(diagram_type
*pDiag
, UINT uiMaxLevel
)
949 if (uiParagraphLevel
>= uiMaxLevel
|| bTitleOpen
) {
950 /* In Word a title is just a paragraph */
953 if (uiListLevel
!= 0 && bEmptyListLevel
) {
954 /* No paragraphs in a list before the first listitem */
957 if (usHeaderLevelCurrent
== 0) {
958 /* No paragraphs without an open header */
959 vAddStartTag(pDiag
, TAG_CHAPTER
, NULL
);
961 vAddCombinedTag(pDiag
, TAG_TITLE
, NULL
);
963 vAddStartTag(pDiag
, TAG_PARA
, NULL
);
964 } /* end of vStartOfParagraphXML */
967 * Create an end of a paragraph
968 * Only for paragraph level one and for titles
971 vEndOfParagraphXML(diagram_type
*pDiag
, UINT uiMaxLevel
)
977 if (uiParagraphLevel
> uiMaxLevel
) {
978 DBG_DEC(uiParagraphLevel
);
983 ucTopTag
= ucReadStack();
986 fail(!bEmphasisOpen
);
987 vAddEndTag(pDiag
, TAG_EMPHASIS
);
989 case TAG_SUPERSCRIPT
:
990 fail(!bSuperscriptOpen
);
991 vAddEndTag(pDiag
, TAG_SUPERSCRIPT
);
994 fail(!bSubscriptOpen
);
995 vAddEndTag(pDiag
, TAG_SUBSCRIPT
);
999 vAddEndTag(pDiag
, TAG_TITLE
);
1002 fail(uiParagraphLevel
== 0);
1003 vAddEndTag(pDiag
, TAG_PARA
);
1007 case TAG_INFORMALTABLE
:
1009 vAddEndTag(pDiag
, ucTopTag
);
1013 werr(1, "Impossible tag sequence, unable to continue");
1017 DBG_MSG_C((size_t)ucTopTag
< elementsof(atDocBookTags
),
1018 atDocBookTags
[(UINT
)ucTopTag
].szTagname
);
1022 } /* end of vEndOfParagraphXML */
1025 * Create an end of a page
1028 vEndOfPageXML(diagram_type
*pDiag
)
1030 if (bTableOpen
|| usHeaderLevelCurrent
== 0) {
1031 /* No beginpage in a table or outside a chapter */
1035 /* A beginpage is not allowed when in a title */
1036 /* So start a new paragraph */
1037 vEndOfParagraphXML(pDiag
, UINT_MAX
);
1038 vStartOfParagraphXML(pDiag
, UINT_MAX
);
1041 vAddCombinedTag(pDiag
, TAG_BEGINPAGE
, NULL
);
1042 } /* end of vEndOfPageXML */
1045 * vCloseHeaderLevels - close the specified header levels
1048 vCloseHeaderLevels(diagram_type
*pDiag
, USHORT usIstd
)
1053 DBG_MSG("vCloseHeaderLevels");
1055 DBG_DEC(usHeaderLevelCurrent
);
1061 ucTopTag
= ucReadStack();
1065 vAddEndTag(pDiag
, ucTopTag
);
1071 } while (bNotReady
);
1075 while (usHeaderLevelCurrent
>= usIstd
) {
1076 if (bEmptyHeaderLevel
) {
1077 vAddCombinedTag(pDiag
, TAG_PARA
, NULL
);
1078 bEmptyHeaderLevel
= FALSE
;
1080 switch (usHeaderLevelCurrent
) {
1081 case 1: vAddEndTag(pDiag
, TAG_CHAPTER
); break;
1082 case 2: vAddEndTag(pDiag
, TAG_SECT1
); break;
1083 case 3: vAddEndTag(pDiag
, TAG_SECT2
); break;
1084 case 4: vAddEndTag(pDiag
, TAG_SECT3
); break;
1085 case 5: vAddEndTag(pDiag
, TAG_SECT4
); break;
1086 case 6: vAddEndTag(pDiag
, TAG_SECT5
); break;
1088 DBG_DEC(usHeaderLevelCurrent
);
1094 DBG_DEC(usHeaderLevelCurrent
);
1097 } /* end of vCloseHeaderLevels */
1100 * vSetHeadersXML - set the headers
1103 vSetHeadersXML(diagram_type
*pDiag
, USHORT usIstd
)
1105 fail(pDiag
== NULL
);
1107 if (usIstd
== 0 || usIstd
> 6) {
1108 DBG_DEC_C(usIstd
!= 0 && usIstd
<= 9, usIstd
);
1113 if (bTableOpen
|| uiListLevel
!= 0) {
1114 /* No headers when you're in a table or in a list */
1119 vCloseHeaderLevels(pDiag
, usIstd
);
1121 DBG_DEC(usHeaderLevelCurrent
);
1124 while (usHeaderLevelCurrent
< usIstd
) {
1125 switch (usHeaderLevelCurrent
) {
1126 case 0: vAddStartTag(pDiag
, TAG_CHAPTER
, NULL
); break;
1127 case 1: vAddStartTag(pDiag
, TAG_SECT1
, NULL
); break;
1128 case 2: vAddStartTag(pDiag
, TAG_SECT2
, NULL
); break;
1129 case 3: vAddStartTag(pDiag
, TAG_SECT3
, NULL
); break;
1130 case 4: vAddStartTag(pDiag
, TAG_SECT4
, NULL
); break;
1131 case 5: vAddStartTag(pDiag
, TAG_SECT5
, NULL
); break;
1133 DBG_DEC(usHeaderLevelCurrent
);
1138 /* The next paragraph should be a title */
1139 if (usHeaderLevelCurrent
< usIstd
) {
1140 /* This chapter level is not in the Word document */
1141 vAddCombinedTag(pDiag
, TAG_TITLE
, NULL
);
1143 vAddStartTag(pDiag
, TAG_TITLE
, NULL
);
1146 } /* end of vSetHeadersXML */
1149 * Create a start of a list
1152 vStartOfListXML(diagram_type
*pDiag
, UCHAR ucNFC
, BOOL bIsEndOfTable
)
1157 fail(pDiag
== NULL
);
1159 if (bIsEndOfTable
) {
1160 /* FIXME: until a list in a table is allowed */
1161 vEndOfTableXML(pDiag
);
1165 /* FIXME: a list in a table should be allowed */
1169 if (usHeaderLevelCurrent
== 0) {
1170 /* No list without an open header */
1171 vAddStartTag(pDiag
, TAG_CHAPTER
, NULL
);
1173 vAddCombinedTag(pDiag
, TAG_TITLE
, NULL
);
1177 case LIST_ARABIC_NUM
:
1178 case LIST_ORDINAL_NUM
:
1179 case LIST_NUMBER_TXT
:
1180 case LIST_ORDINAL_TXT
:
1181 case LIST_OUTLINE_NUM
:
1182 ucTag
= TAG_ORDEREDLIST
;
1183 szAttr
= "numeration='arabic'";
1185 case LIST_UPPER_ROMAN
:
1186 ucTag
= TAG_ORDEREDLIST
;
1187 szAttr
= "numeration='upperroman'";
1189 case LIST_LOWER_ROMAN
:
1190 ucTag
= TAG_ORDEREDLIST
;
1191 szAttr
= "numeration='lowerroman'";
1193 case LIST_UPPER_ALPHA
:
1194 ucTag
= TAG_ORDEREDLIST
;
1195 szAttr
= "numeration='upperalpha'";
1197 case LIST_LOWER_ALPHA
:
1198 ucTag
= TAG_ORDEREDLIST
;
1199 szAttr
= "numeration='loweralpha'";
1204 ucTag
= TAG_ITEMIZEDLIST
;
1205 szAttr
= "mark='bullet'";
1208 ucTag
= TAG_ORDEREDLIST
;
1209 szAttr
= "numeration='arabic'";
1214 vAddStartTag(pDiag
, ucTag
, szAttr
);
1215 } /* end of vStartOfListXML */
1218 * Create an end of a list
1221 vEndOfListXML(diagram_type
*pDiag
)
1223 fail(pDiag
== NULL
);
1226 /* FIXME: a list in a table should be allowed */
1230 if (uiListLevel
!= 0) {
1232 vAddEndTagsUntil2(pDiag
, TAG_ITEMIZEDLIST
, TAG_ORDEREDLIST
);
1235 } /* end of vEndOfListXML */
1238 * Create a start of a list item
1241 vStartOfListItemXML(diagram_type
*pDiag
, BOOL bNoMarks
)
1246 fail(pDiag
== NULL
);
1249 /* FIXME: a list in a table should be allowed */
1253 ucTopTag
= ucReadStack();
1254 if (ucTopTag
!= TAG_ITEMIZEDLIST
&& ucTopTag
!= TAG_ORDEREDLIST
) {
1255 /* Must end a previous list item first */
1256 vAddEndTagsUntil1(pDiag
, TAG_LISTITEM
);
1259 DBG_DEC_C(ucReadStack() != TAG_ITEMIZEDLIST
&&
1260 ucReadStack() != TAG_ORDEREDLIST
, ucReadStack());
1262 /* Start a new list item */
1263 szAttr
= bNoMarks
? "override='none'" : NULL
;
1264 vAddStartTag(pDiag
, TAG_LISTITEM
, szAttr
);
1265 /* Start a new paragraph (independant of level) */
1266 vAddStartTag(pDiag
, TAG_PARA
, NULL
);
1267 } /* end of vStartOfListItemXML */
1270 * Create a start of a table
1273 vStartOfTable(diagram_type
*pDiag
, UCHAR ucBorderInfo
)
1275 const char *szFrame
;
1278 char cColSep
, cRowSep
;
1281 fail(pDiag
== NULL
);
1283 /* Close elements that cannot contain a table */
1286 ucTopTag
= ucReadStack();
1290 vAddEndTag(pDiag
, TAG_TITLE
);
1293 fail(!bEmphasisOpen
);
1294 vAddEndTag(pDiag
, TAG_EMPHASIS
);
1296 case TAG_SUPERSCRIPT
:
1297 fail(!bSuperscriptOpen
);
1298 vAddEndTag(pDiag
, TAG_SUPERSCRIPT
);
1301 fail(!bSubscriptOpen
);
1302 vAddEndTag(pDiag
, TAG_SUBSCRIPT
);
1308 } while (bNotReady
);
1310 /* Create table attributes */
1311 switch (ucBorderInfo
) {
1312 case TABLE_BORDER_TOP
:
1315 case TABLE_BORDER_LEFT
|TABLE_BORDER_RIGHT
:
1318 case TABLE_BORDER_TOP
|TABLE_BORDER_BOTTOM
:
1321 case TABLE_BORDER_BOTTOM
:
1324 case TABLE_BORDER_TOP
|TABLE_BORDER_LEFT
|
1325 TABLE_BORDER_BOTTOM
|TABLE_BORDER_RIGHT
:
1332 cColSep
= bIsTableBorderLeft(ucBorderInfo
) ||
1333 bIsTableBorderRight(ucBorderInfo
) ? '1' : '0';
1334 cRowSep
= bIsTableBorderTop(ucBorderInfo
) ||
1335 bIsTableBorderBottom(ucBorderInfo
) ? '1' : '0';
1337 sprintf(szAttr
, "frame='%.6s' colsep='%c' rowsep='%c'",
1338 szFrame
, cColSep
, cRowSep
);
1340 if (usHeaderLevelCurrent
== 0) {
1341 /* No table without an open header */
1342 vAddStartTag(pDiag
, TAG_CHAPTER
, NULL
);
1344 vAddCombinedTag(pDiag
, TAG_TITLE
, NULL
);
1346 vAddStartTag(pDiag
, TAG_INFORMALTABLE
, szAttr
);
1347 } /* end of vStartOfTable */
1350 * Create a start of a table group
1353 vStartOfTableGroup(diagram_type
*pDiag
,
1354 int iNbrOfColumns
, const short *asColumnWidth
)
1358 char szCols
[6 + 3 * sizeof(int) + 1 + 1];
1359 char szColWidth
[10 + 3 * sizeof(short) + 3 + 3 + 1];
1361 fail(iNbrOfColumns
< 1);
1362 fail(asColumnWidth
== NULL
);
1364 sprintf(szCols
, "cols='%d'", iNbrOfColumns
);
1365 vAddStartTag(pDiag
, TAG_TGROUP
, szCols
);
1367 for (iIndex
= 0; iIndex
< iNbrOfColumns
; iIndex
++) {
1368 fail(asColumnWidth
[iIndex
] < 0);
1369 dWidth
= dTwips2Points(asColumnWidth
[iIndex
]);
1370 if (dWidth
<= 1.0) {
1371 strcpy(szColWidth
, "colwidth='1.00pt'");
1373 sprintf(szColWidth
, "colwidth='%.2fpt'", dWidth
);
1375 vAddCombinedTag(pDiag
, TAG_COLSPEC
, szColWidth
);
1377 } /* end of vStartOfTableGroup */
1380 * Create an end of a table
1383 vEndOfTableXML(diagram_type
*pDiag
)
1385 fail(pDiag
== NULL
);
1388 vAddEndTag(pDiag
, TAG_TBODY
);
1389 vAddEndTag(pDiag
, TAG_TGROUP
);
1390 vAddEndTag(pDiag
, TAG_INFORMALTABLE
);
1392 } /* end of vEndOfTableXML */
1398 vAddTableRowXML(diagram_type
*pDiag
, char **aszColTxt
,
1399 int iNbrOfColumns
, const short *asColumnWidth
, UCHAR ucBorderInfo
)
1401 size_t tCount
, tStringLength
;
1404 fail(pDiag
== NULL
);
1405 fail(pDiag
->pOutFile
== NULL
);
1406 fail(aszColTxt
== NULL
);
1407 fail(iNbrOfColumns
< 1);
1408 fail(asColumnWidth
== NULL
);
1410 if (iNbrOfColumns
!= iTableColumnsCurrent
) {
1411 /* A new number of columns */
1412 /* End the old table body and table group (if they exist) */
1413 vAddEndTagOptional(pDiag
, TAG_TBODY
);
1414 vAddEndTagOptional(pDiag
, TAG_TGROUP
);
1416 /* No table yet. Start a new table */
1417 vStartOfTable(pDiag
, ucBorderInfo
);
1419 /* Start a new table group and a new table body */
1420 vStartOfTableGroup(pDiag
, iNbrOfColumns
, asColumnWidth
);
1421 vAddStartTag(pDiag
, TAG_TBODY
, NULL
);
1422 iTableColumnsCurrent
= iNbrOfColumns
;
1425 /* Add the table row */
1426 vAddStartTag(pDiag
, TAG_ROW
, NULL
);
1427 for (iIndex
= 0; iIndex
< iNbrOfColumns
; iIndex
++) {
1428 /* Add a table cell */
1429 fail(aszColTxt
[iIndex
] == NULL
);
1430 vAddStartTag(pDiag
, TAG_ENTRY
, NULL
);
1431 tStringLength
= strlen(aszColTxt
[iIndex
]);
1432 for (tCount
= 0; tCount
< tStringLength
; tCount
++) {
1433 vPrintChar(pDiag
, aszColTxt
[iIndex
][tCount
]);
1435 vAddEndTag(pDiag
, TAG_ENTRY
);
1437 vAddEndTag(pDiag
, TAG_ROW
);
1438 } /* end of vAddTableRowXML */