File indexing completed on 2025-01-19 10:49:27

0001 /* This file is part of the KDE project
0002 
0003    SPDX-FileCopyrightText: 2012-2013 Inge Wallin <inge@lysator.liu.se>
0004 
0005    SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 
0009 // Own
0010 #include "OdfTextReader.h"
0011 
0012 // Qt
0013 #include <QStringList>
0014 #include <QBuffer>
0015 
0016 // KF5
0017 #include <klocalizedstring.h>
0018 
0019 // Calligra, libodf{,2}
0020 #include <KoXmlNS.h>
0021 #include <KoXmlStreamReader.h>
0022 #include <KoXmlUtils.h>
0023 
0024 // Reader library
0025 #include "OdfReader.h"
0026 #include "OdfTextReaderBackend.h"
0027 #include "OdfReaderContext.h"
0028 #include "OdfDrawReader.h"
0029 #include "OdfReaderDebug.h"
0030 
0031 
0032 #if 1
0033 static int debugIndent = 0;
0034 #define DEBUGSTART() \
0035     ++debugIndent; \
0036     DEBUG_READING("entering")
0037 #define DEBUGEND() \
0038     DEBUG_READING("exiting"); \
0039     --debugIndent
0040 #define DEBUG_READING(param) \
0041     debugOdfReader << QString("%1").arg(" ", debugIndent * 2) << param << ": " \
0042     << (reader.isStartElement() ? "start": (reader.isEndElement() ? "end" : "other")) \
0043     << reader.qualifiedName().toString()
0044 #else
0045 #define DEBUGSTART() \
0046     // NOTHING
0047 #define DEBUGEND() \
0048     // NOTHING
0049 #define DEBUG_READING(param) \
0050     // NOTHING
0051 #endif
0052 
0053 
0054 OdfTextReader::OdfTextReader()
0055     : m_parent(0)
0056     , m_backend(0)
0057     , m_context(0)
0058 {
0059 }
0060 
0061 OdfTextReader::~OdfTextReader()
0062 {
0063 }
0064 
0065 
0066 // ----------------------------------------------------------------
0067 
0068 
0069 void OdfTextReader::setParent(OdfReader *parent)
0070 {
0071     m_parent = parent;
0072 }
0073 
0074 void OdfTextReader::setBackend(OdfTextReaderBackend *backend)
0075 {
0076     m_backend = backend;
0077 }
0078 
0079 void OdfTextReader::setContext(OdfReaderContext *context)
0080 {
0081     m_context = context;
0082 }
0083 
0084 
0085 // ----------------------------------------------------------------
0086 
0087 
0088 #if 0
0089 // This is a template function for the reader library.
0090 // Copy this one and change the name and fill in the code.
0091 void OdfTextReader::readElementNamespaceTagname(KoXmlStreamReader &reader)
0092 {
0093    DEBUGSTART();
0094     m_backend->elementNamespaceTagname(reader, m_context);
0095 
0096     // <namespace:tagname> has the following children in ODF 1.2:
0097     //   FILL IN THE CHILDREN LIKE THIS EXAMPLE (taken from office:document-content):
0098     //          <office:automatic-styles> 3.15.3
0099     //          <office:body> 3.3
0100     //          <office:font-face-decls> 3.14
0101     //          <office:scripts> 3.12.
0102     while (reader.readNextStartElement()) {
0103         QString tagName = reader.qualifiedName().toString();
0104         
0105         if (tagName == "office:automatic-styles") {
0106             // FIXME: NYI
0107             reader.skipCurrentElement();
0108         }
0109         else if (tagName == "office:body") {
0110             readElementOfficeBody(reader);
0111         }
0112         ...  MORE else if () HERE
0113         else {
0114             reader.skipCurrentElement();
0115         }
0116     }
0117 
0118     m_backend->elementNamespaceTagname(reader, m_context);
0119     DEBUGEND();
0120 }
0121 #endif
0122 
0123 
0124 
0125 
0126 // ----------------------------------------------------------------
0127 //                         Text level functions
0128 
0129 
0130 // This function is a bit special since it doesn't handle a specific
0131 // element.  Instead it handles the common child elements between a
0132 // number of text-level elements.
0133 //
0134 void OdfTextReader::readTextLevelElement(KoXmlStreamReader &reader)
0135 {
0136     DEBUGSTART();
0137 
0138     // We should not call any backend functions here.  That is already
0139     // done in the functions that call this one.
0140 
0141     // We define the common elements on the text level as the
0142     // following list.  They are the basic text level contents that
0143     // can be found in a text box (<draw:text-box>) but also in many
0144     // other places like <table:table-cell>, <text:section>,
0145     // <office:text>, etc.
0146     //
0147     // The ones that are not text boxes can also have other children
0148     // but these are the ones we have found to be the common ones.
0149     //
0150     //          <dr3d:scene> 10.5.2
0151     //          <draw:a> 10.4.12
0152     //          <draw:caption> 10.3.11
0153     //          <draw:circle> 10.3.8
0154     //          <draw:connector> 10.3.10
0155     //          <draw:control> 10.3.13
0156     //          <draw:custom-shape> 10.6.1
0157     //          <draw:ellipse> 10.3.9
0158     //          <draw:frame> 10.4.2
0159     //          <draw:g> 10.3.15
0160     //          <draw:line> 10.3.3
0161     //          <draw:measure> 10.3.12
0162     //          <draw:page-thumbnail> 10.3.14
0163     //          <draw:path> 10.3.7
0164     //          <draw:polygon> 10.3.5
0165     //          <draw:polyline> 10.3.4
0166     //          <draw:rect> 10.3.2
0167     //          <draw:regular-polygon> 10.3.6
0168     // All of the above are sent to the draw reader.
0169     //
0170     //   [done] <table:table> 9.1.2
0171     //          <text:alphabetical-index> 8.8
0172     //          <text:bibliography> 8.9
0173     //          <text:change> 5.5.7.4
0174     //          <text:change-end> 5.5.7.3
0175     //          <text:change-start> 5.5.7.2
0176     //   [done] <text:h> 5.1.2
0177     //          <text:illustration-index> 8.4
0178     //   [done] <text:list> 5.3.1
0179     //          <text:numbered-paragraph> 5.3.6
0180     //          <text:object-index> 8.6
0181     //   [done] <text:p> 5.1.3
0182     //          <text:section> 5.4
0183     //   [done] <text:soft-page-break> 5.6
0184     //          <text:table-index> 8.5
0185     //          <text:table-of-content> 8.3
0186     //          <text:user-index> 8.7
0187 
0188     QString tagName = reader.qualifiedName().toString();
0189         
0190     if (reader.prefix() == "draw" || reader.prefix() == "dr3d") {
0191     OdfDrawReader *drawReader = m_parent->drawReader();
0192     if (drawReader) {
0193         drawReader->readCommonGraphicsElements(reader);
0194     }
0195     else {
0196         reader.skipCurrentElement();
0197     }
0198     } // draw | dr3d namespace
0199     else if (tagName == "text:h") {
0200         readElementTextH(reader);
0201     }
0202     else if (tagName == "text:p") {
0203         readElementTextP(reader);
0204     }
0205     else if (tagName == "text:list") {
0206         readElementTextList(reader);
0207     }
0208     else if (tagName == "table:table") {
0209         readElementTableTable(reader);
0210     }
0211     else if (tagName == "text:soft-page-break") {
0212         readElementTextSoftPageBreak(reader);
0213     }
0214     else {
0215         readUnknownElement(reader);
0216     }
0217 
0218     DEBUGEND();
0219 }
0220 
0221 
0222 void OdfTextReader::readElementTextH(KoXmlStreamReader &reader)
0223 {
0224     DEBUGSTART();
0225     m_backend->elementTextH(reader, m_context);
0226 
0227     // The function readParagraphContents() expects to have the reader
0228     // point to the contents of the paragraph so we have to read past
0229     // the text:h start tag here.
0230     reader.readNext();
0231     m_context->setIsInsideParagraph(true);
0232     readParagraphContents(reader);
0233     m_context->setIsInsideParagraph(false);
0234 
0235     m_backend->elementTextH(reader, m_context);
0236     DEBUGEND();
0237 }
0238 
0239 void OdfTextReader::readElementTextP(KoXmlStreamReader &reader)
0240 {
0241     DEBUGSTART();
0242     m_backend->elementTextP(reader, m_context);
0243 
0244     // The function readParagraphContents() expects to have the reader
0245     // point to the contents of the paragraph so we have to read past
0246     // the text:p start tag here.
0247     reader.readNext();
0248     m_context->setIsInsideParagraph(true);
0249     readParagraphContents(reader);
0250     m_context->setIsInsideParagraph(false);
0251 
0252     m_backend->elementTextP(reader, m_context);
0253     DEBUGEND();
0254 }
0255 
0256 void OdfTextReader::readElementTextList(KoXmlStreamReader &reader)
0257 {
0258     DEBUGSTART();
0259     m_backend->elementTextList(reader, m_context);
0260 
0261     // <text:list> has the following children in ODF 1.2:
0262     //   [done] <text:list-header> 5.3.3
0263     //   [done] <text:list-item> 5.3.4
0264 
0265     m_context->setIsInsideParagraph(true);
0266     while (reader.readNextStartElement()) {
0267         DEBUG_READING("loop-start");
0268 
0269         QString tagName = reader.qualifiedName().toString();
0270         //debugOdfReader << "list child:" << tagName;
0271         if (tagName == "text:list-item") {
0272             readElementTextListItem(reader);
0273         }
0274         else if (tagName == "text:list-header") {
0275             readElementTextListHeader(reader);
0276         }
0277         else {
0278             readUnknownElement(reader);
0279         }
0280         DEBUG_READING("loop-end");
0281     }
0282     m_context->setIsInsideParagraph(false);
0283 
0284     m_backend->elementTextList(reader, m_context);
0285     DEBUGEND();
0286 }
0287 
0288 // ----------------------------------------------------------------
0289 //                             Tables
0290 
0291 
0292 void OdfTextReader::readElementTableTable(KoXmlStreamReader &reader)
0293 {
0294     DEBUGSTART();
0295     m_backend->elementTableTable(reader, m_context);
0296 
0297     // <table:table> has the following children in ODF 1.2:
0298     //          <office:dde-source> 14.6.5
0299     //          <office:forms> 13.2
0300     //   [done] <table:desc> 9.1.14
0301     //          <table:named-expressions> 9.4.11
0302     //          <table:scenario> 9.2.7
0303     //          <table:shapes> 9.2.8
0304     //   [done] <table:table-column> 9.1.6
0305     //   [done] <table:table-column-group> 9.1.10
0306     //   [done] <table:table-columns> 9.1.12
0307     //   [done] <table:table-header-columns> 9.1.11
0308     //   [done] <table:table-header-rows> 9.1.7
0309     //   [done] <table:table-row> 9.1.3
0310     //   [done] <table:table-row-group> 9.1.9
0311     //   [done] <table:table-rows> 9.1.8
0312     //          <table:table-source> 9.2.6
0313     //   [done] <table:title> 9.1.13
0314     //   [done] <text:soft-page-break> 5.6
0315     while (reader.readNextStartElement()) {
0316         QString tagName = reader.qualifiedName().toString();
0317         
0318         if (tagName == "table:table-column") {
0319             readElementTableTableColumn(reader);
0320         }
0321         else if (tagName == "table:table-column-group") {
0322             readElementTableTableColumnGroup(reader);
0323         }
0324         else if (tagName == "table:table-columns") {
0325             readElementTableTableColumns(reader);
0326         }
0327         else if (tagName == "table:table-header-columns") {
0328             readElementTableTableHeaderColumns(reader);
0329         }
0330         else if (tagName == "table:table-header-rows") {
0331             readElementTableTableHeaderRows(reader);
0332         }
0333         else if (tagName == "table:table-row") {
0334             readElementTableTableRow(reader);
0335         }
0336         else if (tagName == "table:table-row-group") {
0337             readElementTableTableRowGroup(reader);
0338         }
0339         else if (tagName == "table:table-rows") {
0340             readElementTableTableRows(reader);
0341         }
0342         else if (tagName == "table:title") {
0343         QString value;
0344         readCharacterData(reader, value);
0345         m_backend->textVariable(tagName, value);
0346         }
0347         else if (tagName == "table:desc") {
0348         QString value;
0349         readCharacterData(reader, value);
0350         m_backend->textVariable(tagName, value);
0351         }
0352         else if (tagName == "text:soft-page-break") {
0353             readElementTextSoftPageBreak(reader);
0354         }
0355         else {
0356             reader.skipCurrentElement();
0357         }
0358     }
0359 
0360     m_backend->elementTableTable(reader, m_context);
0361     DEBUGEND();
0362 }
0363 
0364 void OdfTextReader::readElementTableTableColumnGroup(KoXmlStreamReader &reader)
0365 {
0366    DEBUGSTART();
0367     m_backend->elementTableTableColumnGroup(reader, m_context);
0368 
0369     // <table:table-column-group> has the following children in ODF 1.2:
0370     //          <table:table-header-columns> 9.1.11
0371     //          <table:table-column> 9.1.6
0372     //          <table:table-column-group> 9.1.10
0373     //          <table:table-columns> 9.1.12
0374     //
0375     while (reader.readNextStartElement()) {
0376         QString tagName = reader.qualifiedName().toString();
0377         
0378     if (tagName == "table:table-header-columns") {
0379             readElementTableTableHeaderColumns(reader);
0380         }
0381         else if (tagName == "table:table-column") {
0382             readElementTableTableColumn(reader);
0383         }
0384         else if (tagName == "table:table-column-group") {
0385             readElementTableTableColumnGroup(reader);
0386         }
0387         else if (tagName == "table:table-columns") {
0388             readElementTableTableColumns(reader);
0389         }
0390         else {
0391             reader.skipCurrentElement();
0392         }
0393     }
0394 
0395     m_backend->elementTableTableColumnGroup(reader, m_context);
0396     DEBUGEND();
0397 }
0398 
0399 void OdfTextReader::readElementTableTableColumns(KoXmlStreamReader &reader)
0400 {
0401     DEBUGSTART();
0402     m_backend->elementTableTableColumns(reader, m_context);
0403 
0404     // <table:table-columns> has the following children in ODF 1.2:
0405     //   [done] <table:table-column> 9.1.6
0406     while (reader.readNextStartElement()) {
0407         QString tagName = reader.qualifiedName().toString();
0408         
0409         if (tagName == "table:table-column") {
0410             readElementTableTableColumn(reader);
0411         }
0412         else {
0413             reader.skipCurrentElement();
0414         }
0415     }
0416 
0417     m_backend->elementTableTableColumns(reader, m_context);
0418     DEBUGEND();
0419 }
0420 
0421 void OdfTextReader::readElementTableTableHeaderColumns(KoXmlStreamReader &reader)
0422 {
0423     DEBUGSTART();
0424     m_backend->elementTableTableHeaderColumns(reader, m_context);
0425 
0426     // <table:table-header-columns> has the following children in ODF 1.2:
0427     //   [done] <table:table-column> 9.1.6
0428     while (reader.readNextStartElement()) {
0429         QString tagName = reader.qualifiedName().toString();
0430         
0431         if (tagName == "table:table-column") {
0432             readElementTableTableColumn(reader);
0433         }
0434         else {
0435             reader.skipCurrentElement();
0436         }
0437     }
0438 
0439     m_backend->elementTableTableHeaderColumns(reader, m_context);
0440     DEBUGEND();
0441 }
0442 
0443 void OdfTextReader::readElementTableTableHeaderRows(KoXmlStreamReader &reader)
0444 {
0445     DEBUGSTART();
0446     m_backend->elementTableTableHeaderRows(reader, m_context);
0447 
0448     // <table:table-header-rows> has the following children in ODF 1.2:
0449     //   [done] <table:table-row> 9.1.3
0450     //   [done] <text:soft-page-break> 5.6.
0451     while (reader.readNextStartElement()) {
0452         QString tagName = reader.qualifiedName().toString();
0453         
0454         if (tagName == "table:table-row") {
0455             readElementTableTableRow(reader);
0456         }
0457         else if (tagName == "text:soft-page-break") {
0458             readElementTextSoftPageBreak(reader);
0459         }
0460         else {
0461             reader.skipCurrentElement();
0462         }
0463     }
0464 
0465     m_backend->elementTableTableHeaderRows(reader, m_context);
0466     DEBUGEND();
0467 }
0468 
0469 void OdfTextReader::readElementTableTableColumn(KoXmlStreamReader &reader)
0470 {
0471     DEBUGSTART();
0472     m_backend->elementTableTableColumn(reader, m_context);
0473 
0474     // <table:table-column> has no children in ODF 1.2
0475     reader.skipCurrentElement();
0476 
0477     m_backend->elementTableTableColumn(reader, m_context);
0478     DEBUGEND();
0479 }
0480 
0481 void OdfTextReader::readElementTableTableRowGroup(KoXmlStreamReader &reader)
0482 {
0483    DEBUGSTART();
0484     m_backend->elementTableTableRowGroup(reader, m_context);
0485 
0486     // <table:table-row-group> has the following children in ODF 1.2:
0487     //          <table:table-header-rows> 9.1.7
0488     //          <table:table-row> 9.1.3
0489     //          <table:table-row-group> 9.1.9
0490     //          <table:table-rows> 9.1.8
0491     //          <text:soft-page-break> 5.6
0492    //
0493     while (reader.readNextStartElement()) {
0494         QString tagName = reader.qualifiedName().toString();
0495         
0496     if (tagName == "table:table-header-rows") {
0497             readElementTableTableHeaderRows(reader);
0498         }
0499         else if (tagName == "table:table-row") {
0500             readElementTableTableRow(reader);
0501         }
0502         else if (tagName == "table:table-row-group") {
0503             readElementTableTableRowGroup(reader);
0504         }
0505         else if (tagName == "table:table-rows") {
0506             readElementTableTableRows(reader);
0507         }
0508         else if (tagName == "text:soft-page-break") {
0509             readElementTextSoftPageBreak(reader);
0510         }
0511         else {
0512             reader.skipCurrentElement();
0513         }
0514     }
0515 
0516     m_backend->elementTableTableRowGroup(reader, m_context);
0517     DEBUGEND();
0518 }
0519 
0520 void OdfTextReader::readElementTableTableRow(KoXmlStreamReader &reader)
0521 {
0522     DEBUGSTART();
0523     m_backend->elementTableTableRow(reader, m_context);
0524 
0525     // <table:table-row> has the following children in ODF 1.2:
0526     //   [done] <table:covered-table-cell> 9.1.5
0527     //   [done] <table:table-cell> 9.1.4.
0528     while (reader.readNextStartElement()) {
0529         QString tagName = reader.qualifiedName().toString();
0530         
0531         if (tagName == "table:covered-table-cell") {
0532             readElementTableCoveredTableCell(reader);
0533         }
0534         else if (tagName == "table:table-cell") {
0535             readElementTableTableCell(reader);
0536         }
0537         else {
0538             reader.skipCurrentElement();
0539         }
0540     }
0541 
0542     m_backend->elementTableTableRow(reader, m_context);
0543     DEBUGEND();
0544 }
0545 
0546 void OdfTextReader::readElementTableTableRows(KoXmlStreamReader &reader)
0547 {
0548     DEBUGSTART();
0549     m_backend->elementTableTableRows(reader, m_context);
0550 
0551     // <table:table-header-rows> has the following children in ODF 1.2:
0552     //   [done] <table:table-row> 9.1.3
0553     //   [done] <text:soft-page-break> 5.6.
0554     while (reader.readNextStartElement()) {
0555         QString tagName = reader.qualifiedName().toString();
0556         
0557         if (tagName == "table:table-row") {
0558             readElementTableTableRow(reader);
0559         }
0560         else if (tagName == "text:soft-page-break") {
0561             readElementTextSoftPageBreak(reader);
0562         }
0563         else {
0564             reader.skipCurrentElement();
0565         }
0566     }
0567 
0568     m_backend->elementTableTableRows(reader, m_context);
0569     DEBUGEND();
0570 }
0571 
0572 void OdfTextReader::readElementTableTableCell(KoXmlStreamReader &reader)
0573 {
0574     DEBUGSTART();
0575     m_backend->elementTableTableCell(reader, m_context);
0576 
0577     // <table:table-cell> has the following children in ODF 1.2:
0578     //
0579     // In addition to the text level tags like <text:p> etc that can
0580     // be found in any textbox, table cell or similar, it has the
0581     // following text document children:
0582     //
0583     //   [done] <office:annotation> 14.1
0584     //          <table:cell-range-source> 9.3.1
0585     //          <table:detective> 9.3.2
0586 
0587     while (reader.readNextStartElement()) {
0588         DEBUG_READING("loop-start");
0589         
0590         QString tagName = reader.qualifiedName().toString();
0591         if (tagName == "office:annotation") {
0592         readElementOfficeAnnotation(reader);
0593         }
0594         else if (tagName == "table:cell-range-source") {
0595             // FIXME: NYI
0596             reader.skipCurrentElement();
0597         }
0598         else if (tagName == "table:detective") {
0599             // FIXME: NYI
0600             reader.skipCurrentElement();
0601         }
0602         else {
0603             readTextLevelElement(reader);
0604         }
0605         DEBUG_READING("loop-end");
0606     }
0607 
0608     m_backend->elementTableTableCell(reader, m_context);
0609     DEBUGEND();
0610 }
0611 
0612 void OdfTextReader::readElementTableCoveredTableCell(KoXmlStreamReader &reader)
0613 {
0614     DEBUGSTART();
0615     m_backend->elementTableCoveredTableCell(reader, m_context);
0616 
0617     // <table:covered-table-cell> has the following children in ODF 1.2:
0618     //
0619     // In addition to the text level tags like <text:p> etc that can
0620     // be found in any textbox, table cell or similar, it has the
0621     // following text document children:
0622     //
0623     //   [done] <office:annotation> 14.1
0624     //          <table:cell-range-source> 9.3.1
0625     //          <table:detective> 9.3.2
0626 
0627     while (reader.readNextStartElement()) {
0628         DEBUG_READING("loop-start");
0629         
0630         QString tagName = reader.qualifiedName().toString();
0631         if (tagName == "office:annotation") {
0632         readElementOfficeAnnotation(reader);
0633     }
0634         else if (tagName == "table:cell-range-source") {
0635             // FIXME: NYI
0636             reader.skipCurrentElement();
0637         }
0638         else if (tagName == "table:detective") {
0639             // FIXME: NYI
0640             reader.skipCurrentElement();
0641         }
0642         else {
0643             readTextLevelElement(reader);
0644         }
0645         DEBUG_READING("loop-end");
0646     }
0647 
0648     m_backend->elementTableCoveredTableCell(reader, m_context);
0649     DEBUGEND();
0650 }
0651 
0652 
0653 // ----------------------------------------------------------------
0654 //                     Paragraph level functions
0655 
0656 
0657 // This function is a bit special since it doesn't handle a specific
0658 // element.  Instead it handles the common child elements between a
0659 // number of paragraph-level elements.
0660 //
0661 void OdfTextReader::readParagraphContents(KoXmlStreamReader &reader)
0662 {
0663     DEBUGSTART();
0664 
0665     // We enter this function with the reader pointing to the first
0666     // element *inside* the paragraph.
0667     //
0668     // We should not call any backend functions here.  That is already
0669     // done in the functions that call this one.
0670 
0671     while (!reader.atEnd() && !reader.isEndElement()) {
0672         DEBUG_READING("loop-start");
0673 
0674         if (reader.isCharacters()) {
0675             //debugOdfReader << "Found character data";
0676             m_backend->characterData(reader, m_context);
0677             reader.readNext();
0678             continue;
0679         }
0680 
0681         if (!reader.isStartElement())
0682             continue;
0683 
0684         // We define the common elements on the paragraph level as the
0685         // following list.  They are the basic paragraph level contents that
0686         // can be found in a paragraph (text:p), heading (text:h), etc
0687         //
0688         // The common paragraph level elements are the following in ODF 1.2:
0689         //
0690         //          <dr3d:scene> 10.5.2
0691         //          <draw:a> 10.4.12
0692         //          <draw:caption> 10.3.11
0693         //          <draw:circle> 10.3.8
0694         //          <draw:connector> 10.3.10
0695         //          <draw:control> 10.3.13
0696         //          <draw:custom-shape> 10.6.1
0697         //          <draw:ellipse> 10.3.9
0698         //   [done] <draw:frame> 10.4.2
0699         //          <draw:g> 10.3.15
0700         //          <draw:line> 10.3.3
0701         //          <draw:measure> 10.3.12
0702         //          <draw:page-thumbnail> 10.3.14
0703         //          <draw:path> 10.3.7
0704         //          <draw:polygon> 10.3.5
0705         //          <draw:polyline> 10.3.4
0706         //          <draw:rect> 10.3.2
0707         //          <draw:regular-polygon> 10.3.6
0708     // All of the above are sent to the draw reader.
0709     //
0710         //   [done] <office:annotation> 14.1
0711         //   [done] <office:annotation-end> 14.2
0712         //          <presentation:date-time> 10.9.3.5
0713         //          <presentation:footer> 10.9.3.3
0714         //          <presentation:header> 10.9.3.1
0715         //   [done] <text:a> 6.1.8
0716         //          <text:alphabetical-index-mark> 8.1.10
0717         //          <text:alphabetical-index-mark-end> 8.1.9
0718         //          <text:alphabetical-index-mark-start> 8.1.8
0719         //          <text:author-initials> 7.3.7.2
0720         //          <text:author-name> 7.3.7.1
0721         //          <text:bibliography-mark> 8.1.11
0722         //          <text:bookmark> 6.2.1.2
0723         //          <text:bookmark-end> 6.2.1.4
0724         //          <text:bookmark-ref> 7.7.6
0725         //          <text:bookmark-start> 6.2.1.3
0726         //          <text:change> 5.5.7.4
0727         //          <text:change-end> 5.5.7.3
0728         //          <text:change-start> 5.5.7.2
0729         //          <text:chapter> 7.3.8
0730         //          <text:character-count> 7.5.18.5
0731         //          <text:conditional-text> 7.7.3
0732         //          <text:creation-date> 7.5.3
0733         //          <text:creation-time> 7.5.4
0734         //          <text:creator> 7.5.17
0735         //          <text:database-display> 7.6.3
0736         //          <text:database-name> 7.6.7
0737         //          <text:database-next> 7.6.4
0738         //          <text:database-row-number> 7.6.6
0739         //          <text:database-row-select> 7.6.5
0740         //          <text:date> 7.3.2
0741         //          <text:dde-connection> 7.7.12
0742         //          <text:description> 7.5.5
0743         //          <text:editing-cycles> 7.5.13
0744         //          <text:editing-duration> 7.5.14
0745         //          <text:execute-macro> 7.7.10
0746         //          <text:expression> 7.4.14
0747         //          <text:file-name> 7.3.9
0748         //          <text:hidden-paragraph> 7.7.11
0749         //          <text:hidden-text> 7.7.4
0750         //          <text:image-count> 7.5.18.7
0751         //          <text:initial-creator> 7.5.2
0752         //          <text:keywords> 7.5.12
0753         //   [done] <text:line-break> 6.1.5
0754         //          <text:measure> 7.7.13
0755         //          <text:meta> 6.1.9
0756         //          <text:meta-field> 7.5.19
0757         //          <text:modification-date> 7.5.16
0758         //          <text:modification-time> 7.5.15
0759         //          <text:note> 6.3.2
0760         //          <text:note-ref> 7.7.7
0761         //          <text:object-count> 7.5.18.8
0762         //          <text:page-continuation> 7.3.5
0763         //          <text:page-count> 7.5.18.2
0764         //          <text:page-number> 7.3.4
0765         //          <text:page-variable-get> 7.7.1.3
0766         //          <text:page-variable-set> 7.7.1.2
0767         //          <text:paragraph-count> 7.5.18.3
0768         //          <text:placeholder> 7.7.2
0769         //          <text:print-date> 7.5.8
0770         //          <text:printed-by> 7.5.9
0771         //          <text:print-time> 7.5.7
0772         //          <text:reference-mark> 6.2.2.2
0773         //          <text:reference-mark-end> 6.2.2.4
0774         //          <text:reference-mark-start> 6.2.2.3
0775         //          <text:reference-ref> 7.7.5
0776         //          <text:ruby> 6.4
0777         //   [done] <text:s> 6.1.3
0778         //          <text:script> 7.7.9
0779         //          <text:sender-city> 7.3.6.13
0780         //          <text:sender-company> 7.3.6.10
0781         //          <text:sender-country> 7.3.6.15
0782         //          <text:sender-email> 7.3.6.7
0783         //          <text:sender-fax> 7.3.6.9
0784         //          <text:sender-firstname> 7.3.6.2
0785         //          <text:sender-initials> 7.3.6.4
0786         //          <text:sender-lastname> 7.3.6.3
0787         //          <text:sender-phone-private> 7.3.6.8
0788         //          <text:sender-phone-work> 7.3.6.11
0789         //          <text:sender-position> 7.3.6.6
0790         //          <text:sender-postal-code> 7.3.6.14
0791         //          <text:sender-state-or-province> 7.3.6.16
0792         //          <text:sender-street> 7.3.6.12
0793         //          <text:sender-title> 7.3.6.5
0794         //          <text:sequence> 7.4.13
0795         //          <text:sequence-ref> 7.7.8
0796         //          <text:sheet-name> 7.3.11
0797         //   [done] <text:soft-page-break> 5.6
0798         //   [done] <text:span> 6.1.7
0799         //          <text:subject> 7.5.11
0800         //          <text:tab> 6.1.4
0801         //          <text:table-count> 7.5.18.6
0802         //          <text:table-formula> 7.7.14
0803         //          <text:template-name> 7.3.10
0804         //          <text:text-input> 7.4.15
0805         //          <text:time> 7.3.3
0806         //          <text:title> 7.5.10
0807         //          <text:toc-mark> 8.1.4
0808         //          <text:toc-mark-end> 8.1.3
0809         //          <text:toc-mark-start> 8.1.2
0810         //          <text:user-defined> 7.5.6
0811         //          <text:user-field-get> 7.4.9
0812         //          <text:user-field-input> 7.4.10
0813         //          <text:user-index-mark> 8.1.7
0814         //          <text:user-index-mark-end> 8.1.6
0815         //          <text:user-index-mark-start> 8.1.5
0816         //          <text:variable-get> 7.4.5
0817         //          <text:variable-input> 7.4.6
0818         //          <text:variable-set> 7.4.4
0819         //          <text:word-count> 7.5.18.4.
0820         //        
0821         // FIXME: Only very few tags are handled right now.
0822 
0823         QString tagName = reader.qualifiedName().toString();
0824 
0825     if (reader.prefix() == "draw" || reader.prefix() == "dr3d") {
0826         OdfDrawReader *drawReader = m_parent->drawReader();
0827         if (drawReader) {
0828         drawReader->readCommonGraphicsElements(reader);
0829         }
0830         else {
0831         reader.skipCurrentElement();
0832         }
0833         } // draw | dr3d namespace
0834         else if (reader.prefix() == "office") {
0835             if (tagName == "office:annotation") {
0836                 readElementOfficeAnnotation(reader);
0837             }
0838             else if (tagName == "office:annotation-end") {
0839                 readElementOfficeAnnotationEnd(reader);
0840             }
0841             else {
0842                 // Unknown office: element
0843                 readUnknownElement(reader);
0844             }
0845         } // office namespace
0846         else if (reader.prefix() == "text") {
0847 
0848             if (tagName == "text:a") {
0849                 readElementTextA(reader);
0850             }
0851             else if (tagName == "text:line-break") {
0852                 readElementTextLineBreak(reader);
0853             }
0854             else if (tagName == "text:span") {
0855                 readElementTextSpan(reader);
0856             }
0857             else if (tagName == "text:s") {
0858                 readElementTextS(reader);
0859             }
0860             else if (tagName == "text:soft-page-break") {
0861                 readElementTextSoftPageBreak(reader);
0862             }
0863             else {
0864                 // Unknown text: element
0865                 readUnknownElement(reader);
0866             }
0867         } // text namespace
0868         else {
0869             // Unknown namespace
0870             readUnknownElement(reader);
0871         }
0872 
0873         // Read past the end tag of the just parsed element.
0874         reader.readNext();
0875         DEBUG_READING("loop-end");
0876     }
0877 
0878     DEBUGEND();
0879 }
0880 
0881 void OdfTextReader::readElementOfficeAnnotation(KoXmlStreamReader &reader)
0882 {
0883     DEBUGSTART();
0884     m_backend->elementOfficeAnnotation(reader, m_context);
0885 
0886     // <office:annotation> has the following children in ODF 1.2:
0887     //   [done] <dc:creator> 4.3.2.7
0888     //   [done] <dc:date> 4.3.2.10
0889     //   [done] <meta:date-string> 14.3
0890     //   [done] <text:list> 5.3.1
0891     //   [done] <text:p> 5.1.3
0892     while (reader.readNextStartElement()) {
0893         QString tagName = reader.qualifiedName().toString();
0894 
0895         if (tagName == "dc:creator") {
0896             readElementDcCreator(reader);
0897         }
0898         else if (tagName == "dc:date") {
0899             readElementDcDate(reader);
0900         }
0901         else if (tagName == "meta:date-string") {
0902         QString value;
0903         readCharacterData(reader, value);
0904         m_backend->textVariable(tagName, value);
0905         }
0906         else if (tagName == "text:list") {
0907             readElementTextList(reader);
0908         }
0909         else if (tagName == "text:p") {
0910             readElementTextP(reader);
0911         }
0912         else {
0913             reader.skipCurrentElement();
0914         }
0915     }
0916 
0917     m_backend->elementOfficeAnnotation(reader, m_context);
0918     DEBUGEND();
0919 }
0920 
0921 void OdfTextReader::readElementOfficeAnnotationEnd(KoXmlStreamReader &reader)
0922 {
0923     DEBUGSTART();
0924     m_backend->elementOfficeAnnotationEnd(reader, m_context);
0925 
0926     // <office:annotation-end> has no children in ODF 1.2:
0927     // FIXME: Skip current element or call parseUnknownElement?
0928     reader.skipCurrentElement();
0929 
0930     m_backend->elementOfficeAnnotationEnd(reader, m_context);
0931     DEBUGEND();
0932 }
0933 
0934 void OdfTextReader::readElementDcCreator(KoXmlStreamReader &reader)
0935 {
0936     DEBUGSTART();
0937     m_backend->elementDcCreator(reader, m_context);
0938 
0939     reader.readNext();
0940     readParagraphContents(reader);
0941 
0942     m_backend->elementDcCreator(reader, m_context);
0943     DEBUGEND();
0944 }
0945 
0946 void OdfTextReader::readElementDcDate(KoXmlStreamReader &reader)
0947 {
0948     DEBUGSTART();
0949     m_backend->elementDcDate(reader, m_context);
0950 
0951     reader.readNext();
0952     readParagraphContents(reader);
0953 
0954     m_backend->elementDcDate(reader, m_context);
0955     DEBUGEND();
0956 }
0957 
0958 void OdfTextReader::readElementTextA(KoXmlStreamReader &reader)
0959 {
0960     DEBUGSTART();
0961     m_backend->elementTextA(reader, m_context);
0962 
0963     // readParagraphContents expect to have the reader point to the
0964     // contents of the paragraph so we have to read past the text:a
0965     // start tag here.
0966     reader.readNext();
0967     readParagraphContents(reader);
0968 
0969     m_backend->elementTextA(reader, m_context);
0970     DEBUGEND();
0971 }
0972 
0973 void OdfTextReader::readElementTextLineBreak(KoXmlStreamReader &reader)
0974 {
0975     DEBUGSTART();
0976     m_backend->elementTextLineBreak(reader, m_context);
0977 
0978     // This element has no child elements in ODF 1.2.
0979     reader.skipCurrentElement();
0980 
0981     m_backend->elementTextLineBreak(reader, m_context);
0982     DEBUGEND();
0983 }
0984 
0985 void OdfTextReader::readElementTextS(KoXmlStreamReader &reader)
0986 {
0987     DEBUGSTART();
0988     m_backend->elementTextS(reader, m_context);
0989 
0990     // This element has no child elements in ODF 1.2.
0991     reader.skipCurrentElement();
0992 
0993     m_backend->elementTextS(reader, m_context);
0994     DEBUGEND();
0995 }
0996 
0997 void OdfTextReader::readElementTextSpan(KoXmlStreamReader &reader)
0998 {
0999     DEBUGSTART();
1000     m_backend->elementTextSpan(reader, m_context);
1001 
1002     reader.readNext();
1003     readParagraphContents(reader);
1004 
1005     m_backend->elementTextSpan(reader, m_context);
1006     DEBUGEND();
1007 }
1008 
1009 
1010 // ----------------------------------------------------------------
1011 //                        List level functions
1012 
1013 
1014 void OdfTextReader::readElementTextListHeader(KoXmlStreamReader &reader)
1015 {
1016     DEBUGSTART();
1017     m_backend->elementTextListHeader(reader, m_context);
1018 
1019     // <text:list-header> has the following children in ODF 1.2:
1020     //   [done] <text:h> 5.1.2
1021     //   [done] <text:p> 5.1.3
1022     //   [done] <text:list> 5.3.1
1023     //   [done] <text:soft-page-break> 5.6
1024     //          <text:number> 6.1.10
1025     while(reader.readNextStartElement()) {
1026     DEBUG_READING("loop-start");
1027 
1028     QString tagName = reader.qualifiedName().toString();
1029     if (tagName == "text:h") {
1030         readElementTextH(reader);
1031     }
1032     else if (tagName == "text:p") {
1033         readElementTextP(reader);
1034     }
1035     else if (tagName == "text:list") {
1036         readElementTextList(reader);
1037     }
1038         else if (tagName == "text:soft-page-break") {
1039         readElementTextSoftPageBreak(reader);
1040         }
1041         else if (tagName == "text:number") {
1042             // FIXME: NYI
1043             reader.skipCurrentElement();
1044         }
1045     else {
1046         readUnknownElement(reader);
1047     }
1048 
1049     DEBUG_READING("loop-end");
1050     }
1051 
1052     m_backend->elementTextListHeader(reader, m_context);
1053     DEBUGEND();
1054 }
1055 
1056 void OdfTextReader::readElementTextListItem(KoXmlStreamReader &reader)
1057 {
1058     DEBUGSTART();
1059     m_backend->elementTextListItem(reader, m_context);
1060 
1061     // <text:list-item> has the following children in ODF 1.2:
1062     //   [done] <text:h> 5.1.2
1063     //   [done] <text:p> 5.1.3
1064     //   [done] <text:list> 5.3.1
1065     //   [done] <text:soft-page-break> 5.6
1066     //          <text:number> 6.1.10
1067     while(reader.readNextStartElement()) {
1068         DEBUG_READING("loop-start");
1069 
1070         QString tagName = reader.qualifiedName().toString();
1071         debugOdfReader <<tagName;
1072     if (tagName == "text:h") {
1073         readElementTextH(reader);
1074     }
1075     else if (tagName == "text:p") {
1076         readElementTextP(reader);
1077     }
1078         else if (tagName == "text:list") {
1079             readElementTextList(reader);
1080         }
1081         else if (tagName == "text:soft-page-break") {
1082         readElementTextSoftPageBreak(reader);
1083         }
1084         else if (tagName == "text:number") {
1085             //FIXME
1086             reader.skipCurrentElement();
1087         }
1088         else {
1089             readUnknownElement(reader);
1090         }
1091 
1092     DEBUG_READING("loop-end");
1093     }
1094 
1095     m_backend->elementTextListItem(reader, m_context);
1096     DEBUGEND();
1097 }
1098 
1099 // ----------------------------------------------------------------
1100 //                             Other functions
1101 
1102 
1103 void OdfTextReader::readElementTextSoftPageBreak(KoXmlStreamReader &reader)
1104 {
1105     DEBUGSTART();
1106     m_backend->elementTextSoftPageBreak(reader, m_context);
1107 
1108     // <text:soft-page-break> has no children in ODF 1.2
1109     reader.skipCurrentElement();
1110 
1111     m_backend->elementTextSoftPageBreak(reader, m_context);
1112     DEBUGEND();
1113 }
1114 
1115 
1116 void OdfTextReader::readUnknownElement(KoXmlStreamReader &reader)
1117 {
1118     DEBUGSTART();
1119 
1120     if (m_context->isInsideParagraph()) {
1121         // readParagraphContents expect to have the reader point to the
1122         // contents of the paragraph so we have to read past the text:p
1123         // start tag here.
1124         reader.readNext();
1125         readParagraphContents(reader);
1126     }
1127     else {
1128         while (reader.readNextStartElement()) {
1129             readTextLevelElement(reader);
1130         }
1131     }
1132 
1133     DEBUGEND();
1134 }
1135