examples/PIPS/antiword/src/xml.c

00001 /*
00002  * xml.c
00003  * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL
00004  *
00005  * Description:
00006  * Functions to deal with the XML/DocBook format
00007  *
00008  */
00009 
00010 #include <string.h>
00011 #include "antiword.h"
00012 
00013 
00014 #define vAddEndTagsUntil1(p,t)  vAddEndTagsUntil2(p,t,TAG_NOTAG)        
00015 
00016 #if defined(DEBUG)
00017 #define vStackTrace()   __vStackTrace(__LINE__)
00018 #else
00019 #define vStackTrace()   /* EMPTY */
00020 #endif /* DEBUG */
00021 
00022 /* The character set */
00023 static encoding_type    eEncoding = encoding_neutral;
00024 /* Word version */
00025 static int      iWordVersion = -1;
00026 /* Special treatment for files from Word 4/5/6 on an Apple Macintosh */
00027 static BOOL     bOldMacFile = FALSE;
00028 /* Text is emphasised */
00029 static BOOL     bEmphasisOpen = FALSE;
00030 /* Text is superscript */
00031 static BOOL     bSuperscriptOpen = FALSE;
00032 /* Text is subscript */
00033 static BOOL     bSubscriptOpen = FALSE;
00034 /* Title is open */
00035 static BOOL     bTitleOpen = FALSE;
00036 /* Table is open */
00037 static BOOL     bTableOpen = FALSE;
00038 /* Footnote is open */
00039 static BOOL     bFootnoteOpen = FALSE;
00040 /* Current paragraph level */
00041 static UINT     uiParagraphLevel = 0;
00042 /* Current list level */
00043 static UINT     uiListLevel = 0;
00044 /* Current list level is still empty */
00045 static BOOL     bEmptyListLevel = TRUE;
00046 /* Current header level */
00047 static USHORT   usHeaderLevelCurrent = 0;
00048 /* Current header level is still empty */
00049 static BOOL     bEmptyHeaderLevel = TRUE;
00050 /* Number of columns in the current table */
00051 static int      iTableColumnsCurrent = 0;
00052 /* Footnote number */
00053 static UINT     uiFootnoteNumber = 0;
00054 
00055 /* Constants for the stack */
00056 #define INITIAL_STACK_SIZE      10
00057 #if defined(DEBUG)
00058 #define EXTENSION_STACK_SIZE     2
00059 #else
00060 #define EXTENSION_STACK_SIZE    10
00061 #endif /* DEBUG */
00062 
00063 /* Variables for the stack */
00064 static UCHAR    *aucStack = NULL;
00065 static size_t   tStacksize = 0;
00066 static size_t   tStackNextFree = 0;
00067 
00068 /* Constants for the tags */
00069 #define TAG_NOTAG               (UCHAR)0
00070 #define TAG_AUTHOR              (UCHAR)1
00071 #define TAG_BEGINPAGE           (UCHAR)2
00072 #define TAG_BOOK                (UCHAR)3
00073 #define TAG_BOOKINFO            (UCHAR)4
00074 #define TAG_CHAPTER             (UCHAR)5
00075 #define TAG_COLSPEC             (UCHAR)6
00076 #define TAG_CORPNAME            (UCHAR)7
00077 #define TAG_DATE                (UCHAR)8
00078 #define TAG_EMPHASIS            (UCHAR)9
00079 #define TAG_ENTRY               (UCHAR)10
00080 #define TAG_FILENAME            (UCHAR)11
00081 #define TAG_FOOTNOTE            (UCHAR)12
00082 #define TAG_INFORMALTABLE       (UCHAR)13
00083 #define TAG_ITEMIZEDLIST        (UCHAR)14
00084 #define TAG_LISTITEM            (UCHAR)15
00085 #define TAG_ORDEREDLIST         (UCHAR)16
00086 #define TAG_PARA                (UCHAR)17
00087 #define TAG_ROW                 (UCHAR)18
00088 #define TAG_SECT1               (UCHAR)19
00089 #define TAG_SECT2               (UCHAR)20
00090 #define TAG_SECT3               (UCHAR)21
00091 #define TAG_SECT4               (UCHAR)22
00092 #define TAG_SECT5               (UCHAR)23
00093 #define TAG_SUBSCRIPT           (UCHAR)24
00094 #define TAG_SUBTITLE            (UCHAR)25
00095 #define TAG_SUPERSCRIPT         (UCHAR)26
00096 #define TAG_SURNAME             (UCHAR)27
00097 #define TAG_TBODY               (UCHAR)28
00098 #define TAG_TGROUP              (UCHAR)29
00099 #define TAG_TITLE               (UCHAR)30
00100 
00101 typedef struct docbooktags_tag {
00102         UCHAR   ucTagnumber;
00103         char    szTagname[15];
00104         BOOL    bAddNewlineStart;
00105         BOOL    bAddNewlineEnd;
00106 } docbooktags_type;
00107 
00108 static const docbooktags_type atDocBookTags[] = {
00109         {       TAG_NOTAG,              "!ERROR!",      TRUE,   TRUE    },
00110         {       TAG_AUTHOR,             "author",       TRUE,   TRUE    },
00111         {       TAG_BEGINPAGE,          "beginpage",    TRUE,   TRUE    },
00112         {       TAG_BOOK,               "book",         TRUE,   TRUE    },
00113         {       TAG_BOOKINFO,           "bookinfo",     TRUE,   TRUE    },
00114         {       TAG_CHAPTER,            "chapter",      TRUE,   TRUE    },
00115         {       TAG_COLSPEC,            "colspec",      TRUE,   TRUE    },
00116         {       TAG_CORPNAME,           "corpname",     FALSE,  FALSE   },
00117         {       TAG_DATE,               "date",         FALSE,  FALSE   },
00118         {       TAG_EMPHASIS,           "emphasis",     FALSE,  FALSE   },
00119         {       TAG_ENTRY,              "entry",        TRUE,   TRUE    },
00120         {       TAG_FILENAME,           "filename",     FALSE,  FALSE   },
00121         {       TAG_FOOTNOTE,           "footnote",     FALSE,  FALSE   },
00122         {       TAG_INFORMALTABLE,      "informaltable",TRUE,   TRUE    },
00123         {       TAG_ITEMIZEDLIST,       "itemizedlist", TRUE,   TRUE    },
00124         {       TAG_LISTITEM,           "listitem",     TRUE,   TRUE    },
00125         {       TAG_ORDEREDLIST,        "orderedlist",  TRUE,   TRUE    },
00126         {       TAG_PARA,               "para",         TRUE,   TRUE    },
00127         {       TAG_ROW,                "row",          TRUE,   TRUE    },
00128         {       TAG_SECT1,              "sect1",        TRUE,   TRUE    },
00129         {       TAG_SECT2,              "sect2",        TRUE,   TRUE    },
00130         {       TAG_SECT3,              "sect3",        TRUE,   TRUE    },
00131         {       TAG_SECT4,              "sect4",        TRUE,   TRUE    },
00132         {       TAG_SECT5,              "sect5",        TRUE,   TRUE    },
00133         {       TAG_SUBSCRIPT,          "subscript",    FALSE,  FALSE   },
00134         {       TAG_SUBTITLE,           "subtitle",     FALSE,  FALSE   },
00135         {       TAG_SUPERSCRIPT,        "superscript",  FALSE,  FALSE   },
00136         {       TAG_SURNAME,            "surname",      FALSE,  FALSE   },
00137         {       TAG_TBODY,              "tbody",        TRUE,   TRUE    },
00138         {       TAG_TGROUP,             "tgroup",       TRUE,   TRUE    },
00139         {       TAG_TITLE,              "title",        FALSE,  FALSE   },
00140 };
00141 
00142 static void     vAddStartTag(diagram_type *, UCHAR, const char *);
00143 static void     vAddEndTag(diagram_type *, UCHAR);
00144 static void     vAddCombinedTag(diagram_type *, UCHAR, const char *);
00145 static void     vPrintChar(diagram_type *, char);
00146 
00147 
00148 #if defined(DEBUG)
00149 /*
00150  * vCheckTagTable - check the tag table
00151  */
00152 static void
00153 vCheckTagTable(void)
00154 {
00155         size_t  tIndex;
00156 
00157         for (tIndex = 0; tIndex < elementsof(atDocBookTags); tIndex++) {
00158                 if (tIndex != (size_t)atDocBookTags[tIndex].ucTagnumber) {
00159                         DBG_DEC(tIndex);
00160                         werr(1, "Array atDocBookTags is broken");
00161                 }
00162         }
00163 } /* end of vCheckTagTable */
00164 
00165 /*
00166  * __vStackTrace - show a stack trace
00167  */
00168 static void
00169 __vStackTrace(int iLine)
00170 {
00171         int     iIndex;
00172 
00173         fprintf(stderr, "%s[%3d]:\n", __FILE__, iLine);
00174 
00175         if (tStackNextFree == 0) {
00176                 fprintf(stderr, "The stack is empty\n");
00177                 return;
00178         }
00179         for (iIndex = (int)tStackNextFree - 1; iIndex >= 0; iIndex--) {
00180                 fprintf(stderr, "%2d: %2d: '%s'\n",
00181                         iIndex,
00182                         (int)atDocBookTags[(UINT)aucStack[iIndex]].ucTagnumber,
00183                         atDocBookTags[(UINT)aucStack[iIndex]].szTagname);
00184         }
00185 } /* end of __vStackTrace */
00186 #endif /* DEBUG */
00187 
00188 /*
00189  * vPushStack - push a tag onto the stack
00190  */
00191 static void
00192 vPushStack(UCHAR ucTag)
00193 {
00194         fail(tStackNextFree > tStacksize);
00195 
00196         if (tStackNextFree == tStacksize) {
00197                 /* The stack is full; enlarge the stack */
00198                 tStacksize += EXTENSION_STACK_SIZE;
00199                 aucStack = xrealloc(aucStack, tStacksize * sizeof(UCHAR));
00200                 DBG_DEC(tStacksize);
00201         }
00202 
00203         fail(tStackNextFree >= tStacksize);
00204 
00205         aucStack[tStackNextFree++] = ucTag;
00206 } /* end of vPushStack */
00207 
00208 /*
00209  * vPopStack - pop a tag from the stack
00210  */
00211 static UCHAR
00212 ucPopStack(void)
00213 {
00214         DBG_DEC_C(tStackNextFree > tStacksize, tStackNextFree);
00215         DBG_DEC_C(tStackNextFree > tStacksize, tStacksize);
00216         fail(tStackNextFree > tStacksize);
00217         fail(tStackNextFree == 0);
00218 
00219         if (tStackNextFree == 0) {
00220                 werr(1, "The stack is empty, unable to continue");
00221                 return TAG_NOTAG;
00222         }
00223         return aucStack[--tStackNextFree];
00224 } /* end of ucPopStack */
00225 
00226 /*
00227  * vReadStack - read a tag from the top of the stack
00228  */
00229 static UCHAR
00230 ucReadStack(void)
00231 {
00232         DBG_DEC_C(tStackNextFree > tStacksize, tStackNextFree);
00233         DBG_DEC_C(tStackNextFree > tStacksize, tStacksize);
00234         fail(tStackNextFree > tStacksize);
00235 
00236         if (tStackNextFree == 0) {
00237                 /* The stack is empty */
00238                 return TAG_NOTAG;
00239         }
00240         return aucStack[tStackNextFree - 1];
00241 } /* end of ucReadStack */
00242 
00243 /*
00244  * vPrintLevel - print the tag level
00245  */
00246 static void
00247 vPrintLevel(FILE *pOutFile)
00248 {
00249         size_t  tIndex;
00250 
00251         fail(pOutFile == NULL);
00252 
00253         for (tIndex = 0; tIndex < tStackNextFree; tIndex++) {
00254                 (void)putc(' ', pOutFile);
00255         }
00256 } /* end of vPrintLevel */
00257 
00258 /*
00259  * vPrintFootnote - print a footnote
00260  */
00261 static void
00262 vPrintFootnote(diagram_type *pDiag, UINT uiFootnoteIndex)
00263 {
00264         const char      *szText, *pcTmp;
00265         BOOL    bSuScript;
00266         UCHAR   ucTopTag;
00267 
00268         TRACE_MSG("vPrintFootnote");
00269 
00270         szText = szGetFootnootText(uiFootnoteIndex);
00271 
00272         if (szText == NULL) {
00273                 szText = "";
00274         }
00275 
00276         /* Remove the subscript/superscript (if any) */
00277         ucTopTag = ucReadStack();
00278         bSuScript = ucTopTag == TAG_SUBSCRIPT || ucTopTag == TAG_SUPERSCRIPT;
00279         if (bSuScript) {
00280                 vAddEndTag(pDiag, ucTopTag);
00281         }
00282 
00283         /* Start a footnote */
00284         vAddStartTag(pDiag, TAG_FOOTNOTE, NULL);
00285         vAddStartTag(pDiag, TAG_PARA, NULL);
00286 
00287         /* Print a footnote */
00288         for (pcTmp = szText; *pcTmp != '\0'; pcTmp++) {
00289                 if (*pcTmp == PAR_END) {
00290                         if (*(pcTmp + 1) != PAR_END && *(pcTmp + 1) != '\0') {
00291                                 /* PAR_END is not empty and not last */
00292                                 vAddEndTag(pDiag, TAG_PARA);
00293                                 vAddStartTag(pDiag, TAG_PARA, NULL);
00294                         }
00295                 } else {
00296                         vPrintChar(pDiag, *pcTmp);
00297                 }
00298         }
00299 
00300         /* End a footnote */
00301         vAddEndTag(pDiag, TAG_PARA);
00302         vAddEndTag(pDiag, TAG_FOOTNOTE);
00303 
00304         /* Repair the subscript/superscript (if any) */
00305         if (bSuScript) {
00306                 vAddStartTag(pDiag, ucTopTag, NULL);
00307         }
00308 } /* end of vPrintFootnote */
00309 
00310 /*
00311  * vPrintChar - print a character with XML encoding
00312  */
00313 static void
00314 vPrintChar(diagram_type *pDiag, char cChar)
00315 {
00316         fail(pDiag == NULL);
00317         fail(pDiag->pOutFile == NULL);
00318 
00319         switch (cChar) {
00320         case FOOTNOTE_OR_ENDNOTE:
00321                 uiFootnoteNumber++;
00322                 vPrintFootnote(pDiag, uiFootnoteNumber - 1);
00323                 break;
00324         case '<':
00325                 fprintf(pDiag->pOutFile, "%s", "&lt;");
00326                 break;
00327         case '>':
00328                 fprintf(pDiag->pOutFile, "%s", "&gt;");
00329                 break;
00330         case '&':
00331                 fprintf(pDiag->pOutFile, "%s", "&amp;");
00332                 break;
00333         default:
00334                 (void)putc(cChar, pDiag->pOutFile);
00335                 break;
00336         }
00337 } /* end of vPrintChar */
00338 
00339 /*
00340  * vPrintSpecialChar - convert and print a character
00341  */
00342 static void
00343 vPrintSpecialChar(diagram_type *pDiag, USHORT usChar)
00344 {
00345         ULONG   ulChar;
00346         size_t  tLen, tIndex;
00347         char    szResult[4];
00348 
00349         fail(pDiag == NULL);
00350         fail(pDiag->pOutFile == NULL);
00351         fail(iWordVersion < 0);
00352         fail(eEncoding == encoding_neutral);
00353 
00354         ulChar = ulTranslateCharacters(usChar, 0, iWordVersion,
00355                                 conversion_xml, eEncoding, bOldMacFile);
00356         tLen = tUcs2Utf8(ulChar, szResult, sizeof(szResult));
00357         if (tLen == 1) {
00358                 vPrintChar(pDiag, szResult[0]);
00359         } else {
00360                 for (tIndex = 0; tIndex < tLen; tIndex++) {
00361                         (void)putc(szResult[tIndex], pDiag->pOutFile);
00362                 }
00363         }
00364 } /* end of vPrintSpecialChar */
00365 
00366 /*
00367  * vPrintSpecialString - convert and print a string
00368  */
00369 static void
00370 vPrintSpecialString(diagram_type *pDiag, const char *szString)
00371 {
00372         int     iIndex;
00373         USHORT  usChar;
00374 
00375         fail(pDiag == NULL);
00376         fail(pDiag->pOutFile == NULL);
00377         fail(szString == NULL);
00378 
00379         for (iIndex = 0; szString[iIndex] != '\0'; iIndex++) {
00380                 usChar = (USHORT)(UCHAR)szString[iIndex];
00381                 vPrintSpecialChar(pDiag, usChar);
00382         }
00383 } /* end of vPrintSpecialString */
00384 
00385 /*
00386  * vAddStartTag - add the specified start tag to the file
00387  */
00388 static void
00389 vAddStartTag(diagram_type *pDiag, UCHAR ucTag, const char *szAttribute)
00390 {
00391         fail(pDiag == NULL);
00392         fail(pDiag->pOutFile == NULL);
00393         fail((size_t)ucTag >= elementsof(atDocBookTags));
00394 
00395         if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
00396                 fprintf(pDiag->pOutFile, "\n");
00397                 vPrintLevel(pDiag->pOutFile);
00398         }
00399 
00400         if (szAttribute == NULL || szAttribute[0] == '\0') {
00401                 fprintf(pDiag->pOutFile, "<%s>",
00402                         atDocBookTags[(UINT)ucTag].szTagname);
00403         } else {
00404                 fprintf(pDiag->pOutFile, "<%s %s>",
00405                         atDocBookTags[(UINT)ucTag].szTagname, szAttribute);
00406         }
00407 
00408         if (atDocBookTags[(UINT)ucTag].bAddNewlineEnd) {
00409                 fprintf(pDiag->pOutFile, "\n");
00410                 pDiag->lXleft = 0;
00411         }
00412 
00413         vPushStack(ucTag);
00414 
00415         /* Set global variables */
00416         switch (ucTag) {
00417         case TAG_CHAPTER:
00418                 usHeaderLevelCurrent = 1;
00419                 bEmptyHeaderLevel = TRUE;
00420                 break;
00421         case TAG_SECT1:
00422                 usHeaderLevelCurrent = 2;
00423                 bEmptyHeaderLevel = TRUE;
00424                 break;
00425         case TAG_SECT2:
00426                 usHeaderLevelCurrent = 3;
00427                 bEmptyHeaderLevel = TRUE;
00428                 break;
00429         case TAG_SECT3:
00430                 usHeaderLevelCurrent = 4;
00431                 bEmptyHeaderLevel = TRUE;
00432                 break;
00433         case TAG_SECT4:
00434                 usHeaderLevelCurrent = 5;
00435                 bEmptyHeaderLevel = TRUE;
00436                 break;
00437         case TAG_SECT5:
00438                 usHeaderLevelCurrent = 6;
00439                 bEmptyHeaderLevel = TRUE;
00440                 break;
00441         case TAG_TITLE:
00442                 fail(uiParagraphLevel != 0);
00443                 bTitleOpen = TRUE;
00444                 break;
00445         case TAG_FOOTNOTE:
00446                 bFootnoteOpen = TRUE;
00447                 break;
00448         case TAG_PARA:
00449                 fail(bTitleOpen && !bFootnoteOpen);
00450                 uiParagraphLevel++;
00451                 bEmptyHeaderLevel = FALSE;
00452                 break;
00453         case TAG_EMPHASIS:
00454                 bEmphasisOpen = TRUE;
00455                 break;
00456         case TAG_ITEMIZEDLIST:
00457         case TAG_ORDEREDLIST:
00458                 uiListLevel++;
00459                 bEmptyListLevel = TRUE;
00460                 bEmptyHeaderLevel = FALSE;
00461                 break;
00462         case TAG_LISTITEM:
00463                 bEmptyListLevel = FALSE;
00464                 break;
00465         case TAG_SUPERSCRIPT:
00466                 bSuperscriptOpen = TRUE;
00467                 break;
00468         case TAG_SUBSCRIPT:
00469                 bSubscriptOpen = TRUE;
00470                 break;
00471         case TAG_INFORMALTABLE:
00472                 bTableOpen = TRUE;
00473                 bEmptyHeaderLevel = FALSE;
00474                 break;
00475         default:
00476                 break;
00477         }
00478 } /* end of vAddStartTag */
00479 
00480 /*
00481  * vAddEndTag - add the specified end tag to the file
00482  */
00483 static void
00484 vAddEndTag(diagram_type *pDiag, UCHAR ucTag)
00485 {
00486         UCHAR   ucTopTag;
00487 
00488         fail(pDiag == NULL);
00489         fail(pDiag->pOutFile == NULL);
00490         fail((size_t)ucTag >= elementsof(atDocBookTags));
00491 
00492 #if defined(DEBUG)
00493         ucTopTag = ucReadStack();
00494         if (ucTag != ucTopTag) {
00495                 DBG_DEC(ucTag);
00496                 DBG_MSG(atDocBookTags[(UINT)ucTag].szTagname);
00497                 vStackTrace();
00498         }
00499 #endif /* DEBUG */
00500 
00501         ucTopTag = ucPopStack();
00502         fail((size_t)ucTopTag >= elementsof(atDocBookTags));
00503         if (ucTag != ucTopTag) {
00504                 DBG_DEC(ucTag);
00505                 DBG_DEC(ucTopTag);
00506                 DBG_FIXME();
00507                 werr(1, "Impossible tag sequence, unable to continue");
00508         }
00509 
00510         if (atDocBookTags[(UINT)ucTag].bAddNewlineEnd) {
00511                 fprintf(pDiag->pOutFile, "\n");
00512                 vPrintLevel(pDiag->pOutFile);
00513         }
00514 
00515         fprintf(pDiag->pOutFile, "</%s>", atDocBookTags[(UINT)ucTag].szTagname);
00516 
00517         if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
00518                 fprintf(pDiag->pOutFile, "\n");
00519                 pDiag->lXleft = 0;
00520         }
00521 
00522         /* Set global variables */
00523         switch (ucTag) {
00524         case TAG_CHAPTER:
00525                 usHeaderLevelCurrent = 0;
00526                 break;
00527         case TAG_SECT1:
00528                 usHeaderLevelCurrent = 1;
00529                 break;
00530         case TAG_SECT2:
00531                 usHeaderLevelCurrent = 2;
00532                 break;
00533         case TAG_SECT3:
00534                 usHeaderLevelCurrent = 3;
00535                 break;
00536         case TAG_SECT4:
00537                 usHeaderLevelCurrent = 4;
00538                 break;
00539         case TAG_SECT5:
00540                 usHeaderLevelCurrent = 5;
00541                 break;
00542         case TAG_TITLE:
00543                 bTitleOpen = FALSE;
00544                 break;
00545         case TAG_FOOTNOTE:
00546                 bFootnoteOpen = FALSE;
00547                 break;
00548         case TAG_PARA:
00549                 uiParagraphLevel--;
00550                 break;
00551         case TAG_EMPHASIS:
00552                 bEmphasisOpen = FALSE;
00553                 break;
00554         case TAG_SUPERSCRIPT:
00555                 bSuperscriptOpen = FALSE;
00556                 break;
00557         case TAG_ITEMIZEDLIST:
00558         case TAG_ORDEREDLIST:
00559                 uiListLevel--;
00560                 break;
00561         case TAG_SUBSCRIPT:
00562                 bSubscriptOpen = FALSE;
00563                 break;
00564         case TAG_INFORMALTABLE:
00565                 bTableOpen = FALSE;
00566                 iTableColumnsCurrent = 0;
00567                 break;
00568         default:
00569                 break;
00570         }
00571 } /* end of vAddEndTag */
00572 
00573 /*
00574  * vAddEndTagOptional - add the specified end tag to the file if needed
00575  */
00576 static void
00577 vAddEndTagOptional(diagram_type *pDiag, UCHAR ucTag)
00578 {
00579         UCHAR   ucTopTag;
00580 
00581         ucTopTag = ucReadStack();
00582         if (ucTag == ucTopTag) {
00583                 vAddEndTag(pDiag, ucTag);
00584         }
00585 } /* end of vAddEndTagOptional */
00586 
00587 /*
00588  * vAddCombinedTag - add the specified start and end tag to the file
00589  */
00590 static void
00591 vAddCombinedTag(diagram_type *pDiag, UCHAR ucTag, const char *szAttribute)
00592 {
00593         fail(pDiag == NULL);
00594         fail(pDiag->pOutFile == NULL);
00595         fail((size_t)ucTag >= elementsof(atDocBookTags));
00596 
00597         if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
00598                 fprintf(pDiag->pOutFile, "\n");
00599                 vPrintLevel(pDiag->pOutFile);
00600         }
00601 
00602         if (szAttribute == NULL || szAttribute[0] == '\0') {
00603                 fprintf(pDiag->pOutFile, "<%s/>",
00604                         atDocBookTags[(UINT)ucTag].szTagname);
00605         } else {
00606                 fprintf(pDiag->pOutFile, "<%s %s/>",
00607                         atDocBookTags[(UINT)ucTag].szTagname, szAttribute);
00608         }
00609 
00610         if (atDocBookTags[(UINT)ucTag].bAddNewlineStart) {
00611                 fprintf(pDiag->pOutFile, "\n");
00612                 pDiag->lXleft = 0;
00613         }
00614 } /* end of vAddCombinedTag */
00615 
00616 /*
00617  * vAddEndTagsUntil2 - add end tags until one the specified tags is seen
00618  */
00619 static void
00620 vAddEndTagsUntil2(diagram_type *pDiag, UCHAR ucTag1, UCHAR ucTag2)
00621 {
00622         UCHAR   ucTopTag;
00623 
00624         do {
00625                 ucTopTag = ucReadStack();
00626                 switch (ucTopTag) {
00627                 case TAG_CHAPTER:
00628                 case TAG_SECT1:
00629                 case TAG_SECT2:
00630                 case TAG_SECT3:
00631                 case TAG_SECT4:
00632                 case TAG_SECT5:
00633                         if (bEmptyHeaderLevel) {
00634                                 /*
00635                                  * An empty chapter is legal in Word,
00636                                  * but not in DocBook.
00637                                  */
00638                                 vAddCombinedTag(pDiag, TAG_PARA, NULL);
00639                                 bEmptyHeaderLevel = FALSE;
00640                         }
00641                         break;
00642                 case TAG_ITEMIZEDLIST:
00643                 case TAG_ORDEREDLIST:
00644                         if (bEmptyListLevel) {
00645                                 /*
00646                                  * A list without items is legal in Word,
00647                                  * but not in DocBook. (Nor are empty items)
00648                                  */
00649                                 vAddStartTag(pDiag, TAG_LISTITEM, NULL);
00650                                 vAddCombinedTag(pDiag, TAG_PARA, NULL);
00651                                 vAddEndTag(pDiag, TAG_LISTITEM);
00652                                 bEmptyListLevel = FALSE;
00653                         }
00654                         break;
00655                 default:
00656                         break;
00657                 }
00658                 vAddEndTag(pDiag, ucTopTag);
00659         } while (ucTopTag != ucTag1 && ucTopTag != ucTag2);
00660 } /* end of vAddEndTagsUntil2 */
00661 
00662 /*
00663  * vCreateBookIntro - create title and bookinfo
00664  */
00665 void
00666 vCreateBookIntro(diagram_type *pDiag, int iVersion)
00667 {
00668         const char      *szTitle, *szSubject, *szAuthor;
00669         const char      *szLastSaveDtm, *szCompany;
00670         const char      *szLanguage;
00671         char            szTmp[13];
00672 
00673         fail(pDiag == NULL);
00674         fail(pDiag->pOutFile == NULL);
00675         fail(iVersion < 0);
00676         fail(eEncoding == encoding_neutral);
00677 
00678         iWordVersion = iVersion;
00679         bOldMacFile = bIsOldMacFile();
00680         szTitle = szGetTitle();
00681         szSubject = szGetSubject();
00682         szAuthor = szGetAuthor();
00683         szLastSaveDtm = szGetLastSaveDtm();
00684         szCompany = szGetCompany();
00685 
00686         /* Start Book */
00687         szLanguage = szGetLanguage();
00688         if (szLanguage != NULL) {
00689                 DBG_MSG(szLanguage);
00690                 sprintf(szTmp, "lang='%.5s'", szLanguage);
00691                 szLanguage = szTmp;
00692         }
00693         vAddStartTag(pDiag, TAG_BOOK, szLanguage);
00694 
00695         /* Book title */
00696         if (szTitle != NULL && szTitle[0] != '\0') {
00697                 vAddStartTag(pDiag, TAG_TITLE, NULL);
00698                 vPrintSpecialString(pDiag, szTitle);
00699                 vAddEndTag(pDiag, TAG_TITLE);
00700         }
00701         /* Bookinfo */
00702         if ((szTitle != NULL && szTitle[0] != '\0') ||
00703             (szSubject != NULL && szSubject[0] != '\0') ||
00704             (szAuthor != NULL && szAuthor[0] != '\0') ||
00705             (szLastSaveDtm != NULL && szLastSaveDtm[0] != '\0') ||
00706             (szCompany != NULL && szCompany[0] != '\0')) {
00707                 vAddStartTag(pDiag, TAG_BOOKINFO, NULL);
00708                 if (szTitle != NULL && szTitle[0] != '\0') {
00709                         vAddStartTag(pDiag, TAG_TITLE, NULL);
00710                         vPrintSpecialString(pDiag, szTitle);
00711                         vAddEndTag(pDiag, TAG_TITLE);
00712                 }
00713                 if (szSubject != NULL && szSubject[0] != '\0') {
00714                         vAddStartTag(pDiag, TAG_SUBTITLE, NULL);
00715                         vPrintSpecialString(pDiag, szSubject);
00716                         vAddEndTag(pDiag, TAG_SUBTITLE);
00717                 }
00718                 if (szAuthor != NULL && szAuthor[0] != '\0') {
00719                         vAddStartTag(pDiag, TAG_AUTHOR, NULL);
00720                         vAddStartTag(pDiag, TAG_SURNAME, NULL);
00721                         vPrintSpecialString(pDiag, szAuthor);
00722                         vAddEndTag(pDiag, TAG_SURNAME);
00723                         vAddEndTag(pDiag, TAG_AUTHOR);
00724                 }
00725                 if (szLastSaveDtm != NULL && szLastSaveDtm[0] != '\0') {
00726                         vAddStartTag(pDiag, TAG_DATE, NULL);
00727                         vPrintSpecialString(pDiag, szLastSaveDtm);
00728                         vAddEndTag(pDiag, TAG_DATE);
00729                 }
00730                 if (szCompany != NULL && szCompany[0] != '\0') {
00731                         vAddStartTag(pDiag, TAG_CORPNAME, NULL);
00732                         vPrintSpecialString(pDiag, szCompany);
00733                         vAddEndTag(pDiag, TAG_CORPNAME);
00734                 }
00735                 vAddEndTag(pDiag, TAG_BOOKINFO);
00736         }
00737 } /* end of vCreateBookIntro */
00738 
00739 /*
00740  * vPrologueXML - perform the XML initialization
00741  */
00742 void
00743 vPrologueXML(diagram_type *pDiag, const options_type *pOptions)
00744 {
00745 
00746         fail(pDiag == NULL);
00747         fail(pDiag->pOutFile == NULL);
00748         fail(pOptions == NULL);
00749 
00750 #if defined(DEBUG)
00751         vCheckTagTable();
00752 #endif /* DEBUG */
00753 
00754         /* Set global variables to their start values */
00755         eEncoding = pOptions->eEncoding;
00756         bEmphasisOpen = FALSE;
00757         bSuperscriptOpen = FALSE;
00758         bSubscriptOpen = FALSE;
00759         bTitleOpen = FALSE;
00760         bTableOpen = FALSE;
00761         bFootnoteOpen = FALSE;
00762         uiParagraphLevel = 0;
00763         uiListLevel = 0;
00764         bEmptyListLevel = TRUE;
00765         usHeaderLevelCurrent = 0;
00766         bEmptyHeaderLevel = TRUE;
00767         iTableColumnsCurrent = 0;
00768         uiFootnoteNumber = 0;
00769 
00770         pDiag->lXleft = 0;
00771         pDiag->lYtop = 0;
00772 
00773         /* Create an empty stack */
00774         tStacksize = INITIAL_STACK_SIZE;
00775         aucStack = xcalloc(tStacksize, sizeof(UCHAR));
00776         tStackNextFree = 0;
00777 } /* end of vPrologueXML */
00778 
00779 /*
00780  * vEpilogueXML - clean up after everything is done
00781  */
00782 void
00783 vEpilogueXML(diagram_type *pDiag)
00784 {
00785         vStackTrace();
00786 
00787         vAddEndTagsUntil1(pDiag, TAG_BOOK);
00788 
00789         vStackTrace();
00790 
00791         /* Destroy the stack */
00792         fail(tStackNextFree != 0);
00793         tStacksize = 0;
00794         aucStack = xfree(aucStack);
00795         tStackNextFree = 0;
00796 } /* end of vEpilogueXML */
00797 
00798 /*
00799  * vPrintXML - print a XML string
00800  */
00801 static void
00802 vPrintXML(diagram_type *pDiag, const char *szString, size_t tStringLength,
00803                 USHORT usFontstyle)
00804 {
00805         const char      *szAttr;
00806         int     iCount;
00807         size_t  tNextFree;
00808         BOOL    bNotReady, bEmphasisNew, bSuperscriptNew, bSubscriptNew;
00809         UCHAR   ucTopTag, aucStorage[3];
00810 
00811         fail(szString == NULL);
00812 
00813         if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
00814                 return;
00815         }
00816 
00817         if (tStringLength == 1 && szString[0] == FOOTNOTE_OR_ENDNOTE) {
00818                 /* Don't do anything special for just a single footnote */
00819                 bEmphasisNew = FALSE;
00820                 bSuperscriptNew = FALSE;
00821                 bSubscriptNew = FALSE;
00822         } else {
00823                 /* Situation normal */
00824                 bEmphasisNew = bIsBold(usFontstyle) ||
00825                                 bIsItalic(usFontstyle) ||
00826                                 bIsUnderline(usFontstyle) ||
00827                                 bIsStrike(usFontstyle);
00828                 bSuperscriptNew = bIsSuperscript(usFontstyle);
00829                 bSubscriptNew = bIsSubscript(usFontstyle);
00830         }
00831 
00832         /* End what has to be ended (or more to keep the stack happy) */
00833         tNextFree = 0;
00834         bNotReady = TRUE;
00835         do {
00836                 ucTopTag = ucReadStack();
00837                 switch (ucTopTag) {
00838                 case TAG_EMPHASIS:
00839                         fail(!bEmphasisOpen);
00840                         if (bEmphasisNew) {
00841                                 aucStorage[tNextFree++] = ucTopTag;
00842                         }
00843                         vAddEndTag(pDiag, ucTopTag);
00844                         break;
00845                 case TAG_SUPERSCRIPT:
00846                         fail(!bSuperscriptOpen);
00847                         if (bSuperscriptNew) {
00848                                 aucStorage[tNextFree++] = ucTopTag;
00849                         }
00850                         vAddEndTag(pDiag, ucTopTag);
00851                         break;
00852                 case TAG_SUBSCRIPT:
00853                         fail(!bSubscriptOpen);
00854                         if (bSubscriptNew) {
00855                                 aucStorage[tNextFree++] = ucTopTag;
00856                         }
00857                         vAddEndTag(pDiag, ucTopTag);
00858                         break;
00859                 default:
00860                         bNotReady = FALSE;
00861                         break;
00862                 }
00863                 fail(tNextFree > elementsof(aucStorage));
00864                 fail(bNotReady && tNextFree == elementsof(aucStorage));
00865         } while (bNotReady);
00866 
00867         /* Just te make sure */
00868         vStartOfParagraphXML(pDiag, 1);
00869 
00870         /* Restart to keep the stack happy */
00871         for (iCount = (int)tNextFree - 1; iCount > 0; iCount--) {
00872                 vAddStartTag(pDiag, aucStorage[iCount], NULL);
00873         }
00874 
00875         /* Start what has to be started */
00876         if (bEmphasisNew && !bEmphasisOpen) {
00877                 if (bIsBold(usFontstyle)) {
00878                         szAttr = "role='bold'";
00879                 } else if (bIsItalic(usFontstyle)) {
00880                         szAttr = NULL;
00881                 } else if (bIsUnderline(usFontstyle)) {
00882                         szAttr = "role='underline'";
00883                 } else if (bIsStrike(usFontstyle)) {
00884                         szAttr = "role='strikethrough'";
00885                 } else {
00886                         szAttr = NULL;
00887                 }
00888                 vAddStartTag(pDiag, TAG_EMPHASIS, szAttr);
00889         }
00890         if (bSuperscriptNew && !bSuperscriptOpen) {
00891                 vAddStartTag(pDiag, TAG_SUPERSCRIPT, NULL);
00892         }
00893         if (bSubscriptNew && !bSubscriptOpen) {
00894                 vAddStartTag(pDiag, TAG_SUBSCRIPT, NULL);
00895         }
00896 
00897         /* The print the string */
00898         for (iCount = 0; iCount < (int)tStringLength; iCount++) {
00899                 vPrintChar(pDiag, szString[iCount]);
00900         }
00901 } /* end of vPrintXML */
00902 
00903 /*
00904  * vMove2NextLineXML - move to the next line
00905  */
00906 void
00907 vMove2NextLineXML(diagram_type *pDiag)
00908 {
00909         fail(pDiag == NULL);
00910 
00911         /*
00912         if (uiParagraphLevel != 0) {
00913                 We need something like HTML's <BR> tag
00914         }
00915         */
00916 } /* end of vMove2NextLineXML */
00917 
00918 /*
00919  * vSubstringXML - put a sub string into a diagram
00920  */
00921 void
00922 vSubstringXML(diagram_type *pDiag,
00923         const char *szString, size_t tStringLength, long lStringWidth,
00924         USHORT usFontstyle)
00925 {
00926         fail(pDiag == NULL || szString == NULL);
00927         fail(pDiag->pOutFile == NULL);
00928         fail(pDiag->lXleft < 0);
00929         fail(tStringLength != strlen(szString));
00930 
00931         if (szString[0] == '\0' || tStringLength == 0) {
00932                 return;
00933         }
00934 
00935         vPrintXML(pDiag, szString, tStringLength, usFontstyle);
00936         pDiag->lXleft += lStringWidth;
00937 } /* end of vSubstringXML */
00938 
00939 /*
00940  * Create an start of a paragraph
00941  * Only works on paragraph level one, because Word doesn't allow paragraphs
00942  * in paragraphs. Other paragraph levels result from DocBooks special needs.
00943  */
00944 void
00945 vStartOfParagraphXML(diagram_type *pDiag, UINT uiMaxLevel)
00946 {
00947         fail(pDiag == NULL);
00948 
00949         if (uiParagraphLevel >= uiMaxLevel || bTitleOpen) {
00950                 /* In Word a title is just a paragraph */
00951                 return;
00952         }
00953         if (uiListLevel != 0 && bEmptyListLevel) {
00954                 /* No paragraphs in a list before the first listitem */
00955                 return;
00956         }
00957         if (usHeaderLevelCurrent == 0) {
00958                 /* No paragraphs without an open header */
00959                 vAddStartTag(pDiag, TAG_CHAPTER, NULL);
00960                 /* Dummy title */
00961                 vAddCombinedTag(pDiag, TAG_TITLE, NULL);
00962         }
00963         vAddStartTag(pDiag, TAG_PARA, NULL);
00964 } /* end of vStartOfParagraphXML */
00965 
00966 /*
00967  * Create an end of a paragraph
00968  * Only for paragraph level one and for titles
00969  */
00970 void
00971 vEndOfParagraphXML(diagram_type *pDiag, UINT uiMaxLevel)
00972 {
00973         UCHAR   ucTopTag;
00974 
00975         fail(pDiag == NULL);
00976 
00977         if (uiParagraphLevel > uiMaxLevel) {
00978                 DBG_DEC(uiParagraphLevel);
00979                 return;
00980         }
00981 
00982         for(;;) {
00983                 ucTopTag = ucReadStack();
00984                 switch (ucTopTag) {
00985                 case TAG_EMPHASIS:
00986                         fail(!bEmphasisOpen);
00987                         vAddEndTag(pDiag, TAG_EMPHASIS);
00988                         break;
00989                 case TAG_SUPERSCRIPT:
00990                         fail(!bSuperscriptOpen);
00991                         vAddEndTag(pDiag, TAG_SUPERSCRIPT);
00992                         break;
00993                 case TAG_SUBSCRIPT:
00994                         fail(!bSubscriptOpen);
00995                         vAddEndTag(pDiag, TAG_SUBSCRIPT);
00996                         break;
00997                 case TAG_TITLE:
00998                         fail(!bTitleOpen);
00999                         vAddEndTag(pDiag, TAG_TITLE);
01000                         return;
01001                 case TAG_PARA:
01002                         fail(uiParagraphLevel == 0);
01003                         vAddEndTag(pDiag, TAG_PARA);
01004                         return;
01005                 case TAG_TBODY:
01006                 case TAG_TGROUP:
01007                 case TAG_INFORMALTABLE:
01008                         fail(!bTableOpen);
01009                         vAddEndTag(pDiag, ucTopTag);
01010                         break;
01011                 case TAG_NOTAG:
01012                         DBG_FIXME();
01013                         werr(1, "Impossible tag sequence, unable to continue");
01014                         break;
01015                 default:
01016                         DBG_DEC(ucTopTag);
01017                         DBG_MSG_C((size_t)ucTopTag < elementsof(atDocBookTags),
01018                                 atDocBookTags[(UINT)ucTopTag].szTagname);
01019                         return;
01020                 }
01021         }
01022 } /* end of vEndOfParagraphXML */
01023 
01024 /*
01025  * Create an end of a page
01026  */
01027 void
01028 vEndOfPageXML(diagram_type *pDiag)
01029 {
01030         if (bTableOpen || usHeaderLevelCurrent == 0) {
01031                 /* No beginpage in a table or outside a chapter */
01032                 return;
01033         }
01034         if (bTitleOpen) {
01035                 /* A beginpage is not allowed when in a title */
01036                 /* So start a new paragraph */
01037                 vEndOfParagraphXML(pDiag, UINT_MAX);
01038                 vStartOfParagraphXML(pDiag, UINT_MAX);
01039                 return;
01040         }
01041         vAddCombinedTag(pDiag, TAG_BEGINPAGE, NULL);
01042 } /* end of vEndOfPageXML */
01043 
01044 /*
01045  * vCloseHeaderLevels - close the specified header levels
01046  */
01047 static void
01048 vCloseHeaderLevels(diagram_type *pDiag, USHORT usIstd)
01049 {
01050         BOOL    bNotReady;
01051         UCHAR   ucTopTag;
01052 
01053         DBG_MSG("vCloseHeaderLevels");
01054         DBG_DEC(usIstd);
01055         DBG_DEC(usHeaderLevelCurrent);
01056 
01057         vStackTrace();
01058 
01059         bNotReady = TRUE;
01060         do {
01061                 ucTopTag = ucReadStack();
01062                 switch (ucTopTag) {
01063                 case TAG_TITLE:
01064                 case TAG_PARA:
01065                         vAddEndTag(pDiag, ucTopTag);
01066                         break;
01067                 default:
01068                         bNotReady = FALSE;
01069                         break;
01070                 }
01071         } while (bNotReady);
01072 
01073         vStackTrace();
01074 
01075         while (usHeaderLevelCurrent >= usIstd) {
01076                 if (bEmptyHeaderLevel) {
01077                         vAddCombinedTag(pDiag, TAG_PARA, NULL);
01078                         bEmptyHeaderLevel = FALSE;
01079                 }
01080                 switch (usHeaderLevelCurrent) {
01081                 case 1: vAddEndTag(pDiag, TAG_CHAPTER); break;
01082                 case 2: vAddEndTag(pDiag, TAG_SECT1); break;
01083                 case 3: vAddEndTag(pDiag, TAG_SECT2); break;
01084                 case 4: vAddEndTag(pDiag, TAG_SECT3); break;
01085                 case 5: vAddEndTag(pDiag, TAG_SECT4); break;
01086                 case 6: vAddEndTag(pDiag, TAG_SECT5); break;
01087                 default:
01088                         DBG_DEC(usHeaderLevelCurrent);
01089                         DBG_FIXME();
01090                         return;
01091                 }
01092         }
01093 
01094         DBG_DEC(usHeaderLevelCurrent);
01095 
01096         vStackTrace();
01097 } /* end of vCloseHeaderLevels */
01098 
01099 /*
01100  * vSetHeadersXML - set the headers
01101  */
01102 void
01103 vSetHeadersXML(diagram_type *pDiag, USHORT usIstd)
01104 {
01105         fail(pDiag == NULL);
01106 
01107         if (usIstd == 0 || usIstd > 6) {
01108                 DBG_DEC_C(usIstd != 0 && usIstd <= 9, usIstd);
01109                 return;
01110         }
01111         DBG_DEC(usIstd);
01112 
01113         if (bTableOpen || uiListLevel != 0) {
01114                 /* No headers when you're in a table or in a list */
01115                 return;
01116         }
01117 
01118         /* Close levels */
01119         vCloseHeaderLevels(pDiag, usIstd);
01120 
01121         DBG_DEC(usHeaderLevelCurrent);
01122 
01123         /* Open levels */
01124         while (usHeaderLevelCurrent < usIstd) {
01125                 switch (usHeaderLevelCurrent) {
01126                 case 0: vAddStartTag(pDiag, TAG_CHAPTER, NULL); break;
01127                 case 1: vAddStartTag(pDiag, TAG_SECT1, NULL); break;
01128                 case 2: vAddStartTag(pDiag, TAG_SECT2, NULL); break;
01129                 case 3: vAddStartTag(pDiag, TAG_SECT3, NULL); break;
01130                 case 4: vAddStartTag(pDiag, TAG_SECT4, NULL); break;
01131                 case 5: vAddStartTag(pDiag, TAG_SECT5, NULL); break;
01132                 default:
01133                         DBG_DEC(usHeaderLevelCurrent);
01134                         DBG_FIXME();
01135                         return;
01136                 }
01137                 fail(usIstd == 0);
01138                 /* The next paragraph should be a title */
01139                 if (usHeaderLevelCurrent < usIstd) {
01140                         /* This chapter level is not in the Word document */
01141                         vAddCombinedTag(pDiag, TAG_TITLE, NULL);
01142                 } else {
01143                         vAddStartTag(pDiag, TAG_TITLE, NULL);
01144                 }
01145         }
01146 } /* end of vSetHeadersXML */
01147 
01148 /*
01149  * Create a start of a list
01150  */
01151 void
01152 vStartOfListXML(diagram_type *pDiag, UCHAR ucNFC, BOOL bIsEndOfTable)
01153 {
01154         const char      *szAttr;
01155         UCHAR           ucTag;
01156 
01157         fail(pDiag == NULL);
01158 
01159         if (bIsEndOfTable) {
01160                 /* FIXME: until a list in a table is allowed */
01161                 vEndOfTableXML(pDiag);
01162         }
01163 
01164         if (bTableOpen) {
01165                 /* FIXME: a list in a table should be allowed */
01166                 return;
01167         }
01168 
01169         if (usHeaderLevelCurrent == 0) {
01170                 /* No list without an open header */
01171                 vAddStartTag(pDiag, TAG_CHAPTER, NULL);
01172                 /* Dummy title */
01173                 vAddCombinedTag(pDiag, TAG_TITLE, NULL);
01174         }
01175 
01176         switch (ucNFC) {
01177         case LIST_ARABIC_NUM:
01178         case LIST_ORDINAL_NUM:
01179         case LIST_NUMBER_TXT:
01180         case LIST_ORDINAL_TXT:
01181         case LIST_OUTLINE_NUM:
01182                 ucTag = TAG_ORDEREDLIST;
01183                 szAttr = "numeration='arabic'";
01184                 break;
01185         case LIST_UPPER_ROMAN:
01186                 ucTag = TAG_ORDEREDLIST;
01187                 szAttr = "numeration='upperroman'";
01188                 break;
01189         case LIST_LOWER_ROMAN:
01190                 ucTag = TAG_ORDEREDLIST;
01191                 szAttr = "numeration='lowerroman'";
01192                 break;
01193         case LIST_UPPER_ALPHA:
01194                 ucTag = TAG_ORDEREDLIST;
01195                 szAttr = "numeration='upperalpha'";
01196                 break;
01197         case LIST_LOWER_ALPHA:
01198                 ucTag = TAG_ORDEREDLIST;
01199                 szAttr = "numeration='loweralpha'";
01200                 break;
01201         case LIST_SPECIAL:
01202         case LIST_SPECIAL2:
01203         case LIST_BULLETS:
01204                 ucTag = TAG_ITEMIZEDLIST;
01205                 szAttr = "mark='bullet'";
01206                 break;
01207         default:
01208                 ucTag = TAG_ORDEREDLIST;
01209                 szAttr = "numeration='arabic'";
01210                 DBG_HEX(ucNFC);
01211                 DBG_FIXME();
01212                 break;
01213         }
01214         vAddStartTag(pDiag, ucTag, szAttr);
01215 } /* end of vStartOfListXML */
01216 
01217 /*
01218  * Create an end of a list
01219  */
01220 void
01221 vEndOfListXML(diagram_type *pDiag)
01222 {
01223         fail(pDiag == NULL);
01224 
01225         if (bTableOpen) {
01226                 /* FIXME: a list in a table should be allowed */
01227                 return;
01228         }
01229 
01230         if (uiListLevel != 0) {
01231                 vStackTrace();
01232                 vAddEndTagsUntil2(pDiag, TAG_ITEMIZEDLIST, TAG_ORDEREDLIST);
01233                 vStackTrace();
01234         }
01235 } /* end of vEndOfListXML */
01236 
01237 /*
01238  * Create a start of a list item
01239  */
01240 void
01241 vStartOfListItemXML(diagram_type *pDiag, BOOL bNoMarks)
01242 {
01243         const char      *szAttr;
01244         UCHAR   ucTopTag;
01245 
01246         fail(pDiag == NULL);
01247 
01248         if (bTableOpen) {
01249                 /* FIXME: a list in a table should be allowed */
01250                 return;
01251         }
01252 
01253         ucTopTag = ucReadStack();
01254         if (ucTopTag != TAG_ITEMIZEDLIST && ucTopTag != TAG_ORDEREDLIST) {
01255                 /* Must end a previous list item first */
01256                 vAddEndTagsUntil1(pDiag, TAG_LISTITEM);
01257         }
01258 
01259         DBG_DEC_C(ucReadStack() != TAG_ITEMIZEDLIST &&
01260                 ucReadStack() != TAG_ORDEREDLIST, ucReadStack());
01261 
01262         /* Start a new list item */
01263         szAttr = bNoMarks ? "override='none'" : NULL;
01264         vAddStartTag(pDiag, TAG_LISTITEM, szAttr);
01265         /* Start a new paragraph (independant of level) */
01266         vAddStartTag(pDiag, TAG_PARA, NULL);
01267 } /* end of vStartOfListItemXML */
01268 
01269 /*
01270  * Create a start of a table
01271  */
01272 static void
01273 vStartOfTable(diagram_type *pDiag, UCHAR ucBorderInfo)
01274 {
01275         const char      *szFrame;
01276         BOOL    bNotReady;
01277         UCHAR   ucTopTag;
01278         char    cColSep, cRowSep;
01279         char    szAttr[40];
01280 
01281         fail(pDiag == NULL);
01282 
01283         /* Close elements that cannot contain a table */
01284         bNotReady = TRUE;
01285         do {
01286                 ucTopTag = ucReadStack();
01287                 switch (ucTopTag) {
01288                 case TAG_TITLE:
01289                         fail(!bTitleOpen);
01290                         vAddEndTag(pDiag, TAG_TITLE);
01291                         break;
01292                 case TAG_EMPHASIS:
01293                         fail(!bEmphasisOpen);
01294                         vAddEndTag(pDiag, TAG_EMPHASIS);
01295                         break;
01296                 case TAG_SUPERSCRIPT:
01297                         fail(!bSuperscriptOpen);
01298                         vAddEndTag(pDiag, TAG_SUPERSCRIPT);
01299                         break;
01300                 case TAG_SUBSCRIPT:
01301                         fail(!bSubscriptOpen);
01302                         vAddEndTag(pDiag, TAG_SUBSCRIPT);
01303                         break;
01304                 default:
01305                         bNotReady = FALSE;
01306                         break;
01307                 }
01308         } while (bNotReady);
01309 
01310         /* Create table attributes */
01311         switch (ucBorderInfo) {
01312         case TABLE_BORDER_TOP:
01313                 szFrame = "top";
01314                 break;
01315         case TABLE_BORDER_LEFT|TABLE_BORDER_RIGHT:
01316                 szFrame = "sides";
01317                 break;
01318         case TABLE_BORDER_TOP|TABLE_BORDER_BOTTOM:
01319                 szFrame = "topbot";
01320                 break;
01321         case TABLE_BORDER_BOTTOM:
01322                 szFrame = "bottom";
01323                 break;
01324         case TABLE_BORDER_TOP|TABLE_BORDER_LEFT|
01325              TABLE_BORDER_BOTTOM|TABLE_BORDER_RIGHT:
01326                 szFrame = "all";
01327                 break;
01328         default:
01329                 szFrame = "none";
01330                 break;
01331         }
01332         cColSep = bIsTableBorderLeft(ucBorderInfo) ||
01333                   bIsTableBorderRight(ucBorderInfo) ? '1' : '0';
01334         cRowSep = bIsTableBorderTop(ucBorderInfo) ||
01335                   bIsTableBorderBottom(ucBorderInfo) ? '1' : '0';
01336 
01337         sprintf(szAttr, "frame='%.6s' colsep='%c' rowsep='%c'",
01338                         szFrame, cColSep, cRowSep);
01339 
01340         if (usHeaderLevelCurrent == 0) {
01341                 /* No table without an open header */
01342                 vAddStartTag(pDiag, TAG_CHAPTER, NULL);
01343                 /* Dummy title */
01344                 vAddCombinedTag(pDiag, TAG_TITLE, NULL);
01345         }
01346         vAddStartTag(pDiag, TAG_INFORMALTABLE, szAttr);
01347 } /* end of vStartOfTable */
01348 
01349 /*
01350  * Create a start of a table group
01351  */
01352 static void
01353 vStartOfTableGroup(diagram_type *pDiag,
01354         int iNbrOfColumns, const short *asColumnWidth)
01355 {
01356         double  dWidth;
01357         int     iIndex;
01358         char    szCols[6 + 3 * sizeof(int) + 1 + 1];
01359         char    szColWidth[10 + 3 * sizeof(short) + 3 + 3 + 1];
01360 
01361         fail(iNbrOfColumns < 1);
01362         fail(asColumnWidth == NULL);
01363 
01364         sprintf(szCols, "cols='%d'", iNbrOfColumns);
01365         vAddStartTag(pDiag, TAG_TGROUP, szCols);
01366 
01367         for (iIndex= 0; iIndex < iNbrOfColumns; iIndex++) {
01368                 fail(asColumnWidth[iIndex] < 0);
01369                 dWidth = dTwips2Points(asColumnWidth[iIndex]);
01370                 if (dWidth <= 1.0) {
01371                         strcpy(szColWidth, "colwidth='1.00pt'");
01372                 } else {
01373                         sprintf(szColWidth, "colwidth='%.2fpt'", dWidth);
01374                 }
01375                 vAddCombinedTag(pDiag, TAG_COLSPEC, szColWidth);
01376         }
01377 } /* end of vStartOfTableGroup */
01378 
01379 /*
01380  * Create an end of a table
01381  */
01382 void
01383 vEndOfTableXML(diagram_type *pDiag)
01384 {
01385         fail(pDiag == NULL);
01386 
01387         if (bTableOpen) {
01388                 vAddEndTag(pDiag, TAG_TBODY);
01389                 vAddEndTag(pDiag, TAG_TGROUP);
01390                 vAddEndTag(pDiag, TAG_INFORMALTABLE);
01391         }
01392 } /* end of vEndOfTableXML */
01393 
01394 /*
01395  * Add a table row
01396  */
01397 void
01398 vAddTableRowXML(diagram_type *pDiag, char **aszColTxt,
01399         int iNbrOfColumns, const short *asColumnWidth, UCHAR ucBorderInfo)
01400 {
01401         size_t  tCount, tStringLength;
01402         int     iIndex;
01403 
01404         fail(pDiag == NULL);
01405         fail(pDiag->pOutFile == NULL);
01406         fail(aszColTxt == NULL);
01407         fail(iNbrOfColumns < 1);
01408         fail(asColumnWidth == NULL);
01409 
01410         if (iNbrOfColumns != iTableColumnsCurrent) {
01411                 /* A new number of columns */
01412                 /* End the old table body and table group (if they exist) */
01413                 vAddEndTagOptional(pDiag, TAG_TBODY);
01414                 vAddEndTagOptional(pDiag, TAG_TGROUP);
01415                 if (!bTableOpen) {
01416                         /* No table yet. Start a new table */
01417                         vStartOfTable(pDiag, ucBorderInfo);
01418                 }
01419                 /* Start a new table group and a new table body */
01420                 vStartOfTableGroup(pDiag, iNbrOfColumns, asColumnWidth);
01421                 vAddStartTag(pDiag, TAG_TBODY, NULL);
01422                 iTableColumnsCurrent = iNbrOfColumns;
01423         }
01424 
01425         /* Add the table row */
01426         vAddStartTag(pDiag, TAG_ROW, NULL);
01427         for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
01428                 /* Add a table cell */
01429                 fail(aszColTxt[iIndex] == NULL);
01430                 vAddStartTag(pDiag, TAG_ENTRY, NULL);
01431                 tStringLength = strlen(aszColTxt[iIndex]);
01432                 for (tCount = 0; tCount < tStringLength; tCount++) {
01433                         vPrintChar(pDiag, aszColTxt[iIndex][tCount]);
01434                 }
01435                 vAddEndTag(pDiag, TAG_ENTRY);
01436         }
01437         vAddEndTag(pDiag, TAG_ROW);
01438 } /* end of vAddTableRowXML */

Generated by  doxygen 1.6.2