summaryrefslogtreecommitdiff
path: root/src/xmlcomposer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmlcomposer.cpp')
-rw-r--r--src/xmlcomposer.cpp1245
1 files changed, 0 insertions, 1245 deletions
diff --git a/src/xmlcomposer.cpp b/src/xmlcomposer.cpp
deleted file mode 100644
index 6f41b29..0000000
--- a/src/xmlcomposer.cpp
+++ /dev/null
@@ -1,1245 +0,0 @@
-/*
- * Copyright (c) 2004, Nate Nielsen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * * The names of contributors to this software may not be
- * used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- *
- * CONTRIBUTORS
- * Nate Nielsen <nielsen@memberwebs.com>
- *
- */
-
-#include "usuals.h"
-#include "xmlcomposer.h"
-#include "xmlfixups.h"
-#include "domhelpers.h"
-#include "tags.h"
-
-
-wstring formatInt(int num)
-{
- char buff[16];
-
- // Certain OSs don't support swprintf :(
- sprintf(buff, "%d", num);
-
- wstring n;
- for(char* s = buff; *s; s++)
- n.append(1, *s);
-
- return n;
-}
-
-/* ----------------------------------------------------------------------------------
- * CONSTRUCTION
- */
-
-XmlComposer::XmlComposer(const XmlComposerOptions& options)
-{
- m_document = NULL;
- memcpy(&m_options, &options, sizeof(options));
-
- // All autocounters start at 1
- for(int i = 0; i < AUTOCOUNT_MAX; i++)
- m_autocount[i] = 1;
-}
-
-XmlComposer::~XmlComposer()
-{
- clear();
-
- if(m_impl != NULL)
- m_impl.release();
-}
-
-void XmlComposer::clear()
-{
- if(m_document != NULL)
- {
- try
- {
- m_document.release();
- }
- catch(...) { }
-
- m_document = NULL;
- }
- LevelHandler::clear();
-}
-
-
-/* ----------------------------------------------------------------------------------
- * HANDLER OVERRIDES
- */
-
-void XmlComposer::startDocument(RtfParser* reader)
-{
- LevelHandler::startDocument(reader);
- ASSERT(m_curLevel != NULL);
-
- // Create a new document
- m_document = m_impl.createDocument("", kElDoc, DOM::DocumentType());
-
- // TODO: Throw error if document is null
- ASSERT(m_document != NULL);
-
- // Hook up the top level element
- DOM::Element top = m_document.getDocumentElement();
- m_curLevel->setElement(top, true);
-
- // Set the attributes on the top level
- setAnalyser(AnalyserPtr(new Root));
- setDestination(DestinationPtr(new Content));
- getTextFormatting().resetPara();
- getTextFormatting().resetText();
-
- // Create the options element
- m_docOptions = m_document.createElement(kElOptions);
- top.appendChild(m_docOptions);
-}
-
-void XmlComposer::endDocument()
-{
- LevelHandler::endDocument();
-
- XmlFixups fix;
-
- // Pass 0: Cleanup the tree
- // XmlFixups::combineDuplicates(m_document);
- // XmlFixups::consolidateStartTags(m_document);
- // XmlFixups::consolidateEndTags(m_document);
-
- // Pass 1: Block breakout
- fix.breakTables(m_document);
- fix.breakTags(m_document, kElTable, kElRow);
- fix.breakTags(m_document, kElRow, kElCell);
- fix.wrapTags(m_document, kElCell, kElDest);
- fix.breakBlocks(m_document);
- fix.breakLists(m_document);
-
- // Pass 2: Fixups
- fix.runPassTwo(m_document);
-
- // XmlFixups::fixLists(m_document);
- // XmlFixups::fixStyles(m_document);
- // XmlFixups::fixBlocks(m_document);
- // XmlFixups::removeTags(m_document);
- // XmlFixups::breakBreak(m_document, kElDoc, kElPage);
- // XmlFixups::breakBreak(m_document, kElDoc, kElSect);
-
- // Pass 3: Final cleanup
- // XmlFixups::combineDuplicates(m_document);
-
- DOM::Element top = m_document.getDocumentElement();
- ASSERT(top != NULL);
- top.setAttribute(kNSPrefix, kNSRtfx);
-
- return;
-}
-
-void XmlComposer::charData(wstring data)
-{
- ASSERT(m_curLevel != NULL);
- DestinationPtr destination = m_curLevel->getDestination();
-
- if(!destination)
- {
- destination = DestinationPtr(new Content);
- setDestination(destination);
- }
-
- destination->charData(data);
-}
-
-void XmlComposer::controlWord(const string& cw, int flags, int param)
-{
- ASSERT(m_curLevel != NULL);
- AnalyserPtr analyser = m_curLevel->getAnalyser();
- if(analyser)
- analyser->controlWord(cw, flags, param);
-}
-
-void XmlComposer::groupStart()
-{
- LevelHandler::groupStart();
-
- ASSERT(m_curLevel != NULL);
- AnalyserPtr analyser = m_curLevel->getAnalyser();
- if(analyser)
- analyser->groupStart();
-}
-
-void XmlComposer::groupEnd()
-{
- LevelHandler::groupEnd();
-
- ASSERT(m_curLevel != NULL);
- AnalyserPtr analyser = m_curLevel->getAnalyser();
- if(analyser)
- analyser->groupEnd();
-}
-
-
-/* ----------------------------------------------------------------------------------
- * HELPER FUNCTIONS
- */
-
-DOM::Element XmlComposer::createElement(const string& name)
-{
- ASSERT(name.length() > 0);
- return m_document.createElement(name);
-}
-
-void XmlComposer::replaceElement(const DOM::Element& element)
-{
- ASSERT(m_curLevel != NULL);
- m_curLevel->setElement(element, true);
-}
-
-void XmlComposer::pushElement(const DOM::Element& element)
-{
- ASSERT(m_curLevel != NULL);
- getElement().appendChild(element);
- m_curLevel->setElement(element);
-}
-
-void XmlComposer::pushTopElement(const DOM::Element& element)
-{
- ASSERT(m_curLevel != NULL);
- DOM::Element top = m_document.getDocumentElement();
- if(top.hasChildNodes())
- top.insertBefore(element, top.getFirstChild());
- else
- top.appendChild(element);
-
- m_curLevel->setElement(element);
-}
-
-DOM::Element XmlComposer::popElement()
-{
- DOM::Element element = getElement();
- ASSERT(m_curLevel != NULL);
-
- DOM::Node parent = element.getParentNode();
- ASSERT(parent != NULL && parent.getNodeType() == DOM::Node::ELEMENT_NODE);
-
- // Set it deep so it replaces the current element
- m_curLevel->setElement((DOM::Element&)parent, true);
- return element;
-}
-
-void XmlComposer::setAttribute(const string& name, const wstring& value, DOM::Element el)
-{
- ASSERT(name.length() > 0);
- if(el == NULL)
- el = getElement();
- el.setAttribute(name, value);
-}
-
-void XmlComposer::setAttribute(const string& name, int value, DOM::Element el)
-{
- ASSERT(name.length() > 0);
- if(el == NULL)
- el = getElement();
- el.setAttribute(name, formatInt(value));
-}
-
-void XmlComposer::setDestination(DestinationPtr dest)
-{
- ASSERT(m_curLevel);
-
- m_curLevel->setDestination(dest);
- dest->m_composer = this;
- dest->initialize();
-}
-
-DestinationPtr XmlComposer::replaceDestination(DestinationPtr dest)
-{
- ASSERT(m_curLevel);
-
- DestinationPtr old = m_curLevel->getDestination();
- m_curLevel->setDestination(dest, true);
- dest->m_composer = this;
- dest->initialize();
-
- return old;
-}
-
-
-void XmlComposer::setAnalyser(AnalyserPtr analy)
-{
- ASSERT(m_curLevel);
- ASSERT(analy != NULL);
-
- analy->m_composer = this;
- m_curLevel->setAnalyser(analy);
- analy->initialize();
-}
-
-AnalyserPtr XmlComposer::getAnalyser()
-{
- ASSERT(m_curLevel);
- return m_curLevel->getAnalyser();
-}
-
-DestinationPtr XmlComposer::getDestination()
-{
- ASSERT(m_curLevel);
- return m_curLevel->getDestination();
-}
-
-RtfFormatting& XmlComposer::getTextFormatting()
-{
- ASSERT(m_curLevel);
- return m_curLevel->getFormatting();
-}
-
-int XmlComposer::getAutoCount(int type)
-{
- ASSERT(type < AUTOCOUNT_MAX);
- return m_autocount[type];
-}
-
-void XmlComposer::incrementAutoCount(int type)
-{
- ASSERT(type < AUTOCOUNT_MAX);
- m_autocount[type]++;
-}
-
-void XmlComposer::addDocumentOption(DOM::Element& option)
-{
- ASSERT(m_docOptions != NULL);
- m_docOptions.appendChild(option);
-}
-
-
-/* ----------------------------------------------------------------------------------
- * CONVENIENCE MACROS USED BELOW
- */
-
-#define AN_ELEMENT(name) \
- m_composer->pushElement(m_composer->createElement(name))
-#define AN_TOP_ELEMENT(name) \
- m_composer->pushTopElement(m_composer->createElement(name))
-#define AN_POP_ELEMENT() \
- m_composer->popElement()
-#define AN_ATTRIBUTE(name, value) \
- m_composer->setAttribute(name, value)
-#define AN_DESTINATION_ATTR(name) \
- m_composer->setDestination(new Attribute(name))
-#define AN_DESTINATION(cls) \
- m_composer->setDestination(new cls)
-#define AN_ANALYSER(cls) \
- m_composer->setAnalyser(AnalyserPtr(new cls))
-#define AN_SET_ANALYSER(cls) \
- m_composer->setAnalyser(AnalyserPtr(cls))
-#define HAS_PARAM (flags & kHasParam)
-#define DEFAULT_CONTROLWORD processDefault(cw, flags, param)
-#define DUMMY 1 == 1
-#define NUM_ATTR(x) formatInt(x)
-#define DO_EXTRAS() (m_composer->getOptions().extras)
-
-/* ----------------------------------------------------------------------------------
- * BASE ANALYSER
- */
-
-bool XmlComposer::BaseAnalyser::processDefault(const string& cw, int flags, int param)
-{
- // Unicode blocks go to a special analyser
- if(cw == "upr")
- {
- AnalyserPtr analy = m_composer->getAnalyser();
- ASSERT(analy != NULL);
- AN_SET_ANALYSER(new Upr(analy));
- return true;
- }
-
- return false;
-}
-
-void XmlComposer::BaseAnalyser::applyParaFormatting(RtfFormatting* format,
- DOM::Element& el)
-{
- if(format == NULL)
- format = &(m_composer->getTextFormatting());
-
- wstring fix = kValPara;
-
- // Is it a list?
- int list = format->paraList();
- if(list != -1)
- el.setAttribute(kAtList, NUM_ATTR(list));
- else
- el.removeAttribute(kAtList);
-
- // Is it a cell?
- if(format->paraInTable())
- el.setAttribute(kAtCell, L"1");
- else
- el.removeAttribute(kAtCell);
-
- // Paragraph styles
- int style = format->paraStyle();
- if(style != -1)
- el.setAttribute(kElStyle, NUM_ATTR(style));
- else
- el.removeAttribute(kElStyle);
-
- // These fix elements are later picked up in XmlFixups::fixBlocks
- el.setAttribute(kAtFix, fix);
-}
-
-DOM::Element XmlComposer::BaseAnalyser::getCurrentBlock()
-{
- DOM::Node node = m_composer->getElement();
-
- if(node.hasChildNodes())
- node = node.getLastChild();
-
- return DOMHelpers::getPriorElement(node, kElBlock);
-}
-
-bool XmlComposer::BaseAnalyser::processTextContent(const string& cw, int flags, int param)
-{
- DOM::Element el;
- bool process = false;
-
- RtfFormatting& format = m_composer->getTextFormatting();
-
- // New paragraph
- if(cw == "par")
- {
- el = getCurrentBlock();
- if(el != NULL)
- applyParaFormatting(&format, el);
-
- el = m_composer->createElement(kElBlock);
- applyParaFormatting(&format, el);
- }
-
- // Cells (used later in applyParaFormatting)
- else if(cw == "intbl")
- format.paraSetTable(true);
-
- // Start of a cell
- else if(cw == "cell")
- {
- el = getCurrentBlock();
- if(el != NULL)
- applyParaFormatting(&format, el);
-
- el = m_composer->createElement(kElCell);
- m_composer->pushElement(el);
- m_composer->popElement();
- el = m_composer->createElement(kElBlock);
- applyParaFormatting(&format, el);
- }
-
- // Start of a row
- else if(cw == "trowd")
- el = m_composer->createElement(kElRow);
-
- // A tab
- else if(cw == "tab")
- el = m_composer->createElement(kElTab);
-
- // A section break
- else if(cw == "sect")
- el = m_composer->createElement(kElSect);
-
- // A page break
- else if(cw == "page")
- el = m_composer->createElement(kElPage);
-
- // A paragraph style
- else if(cw == "s" && HAS_PARAM)
- format.paraSetStyle(param);
-
- // A line break
- else if(cw == "line")
- el = m_composer->createElement(kElLine);
-
- // A page header (not implemented)
- else if(cw == "header")
- AN_ANALYSER(Skip);
-
- // A page footer (not implemented)
- else if(cw == "footer")
- AN_ANALYSER(Skip);
-
- // A bookmark (not implemented)
- else if(cw == "bkmkstart")
- AN_ANALYSER(Skip);
-
- // List text (not implemented)
- else if(cw == "listtext")
- AN_ANALYSER(Skip);
-
- // Set list style (used in applyFormatting)
- else if(cw == "ls" && HAS_PARAM)
- format.paraSetList(param);
-
- if(el != NULL)
- {
- // This ensures that our content destination is open and ready
- DestinationPtr dest = m_composer->getDestination();
- ASSERT(dest != NULL);
- dest->charData(kValNull);
-
- m_composer->pushElement(el);
- m_composer->popElement();
- }
-
- return (el != NULL) || process;
-}
-
-bool XmlComposer::BaseAnalyser::processTextFormatting(const string& cw, int flags,
- int param, RtfFormatting& format)
-{
- bool on = true;
- if(flags & HAS_PARAM && param == 0)
- on = false;
-
- // Clears all paragraph formatting
- if(cw == "pard")
- {
- format.resetPara();
- // applyParaFormatting();
- }
-
- // Rest are pretty much self-explanatory
- else if(cw == "plain")
- format.resetText();
- else if(cw == "b")
- format.textSetBold(on);
- else if(cw == "i")
- format.textSetItalic(on);
- else if(cw == "v")
- format.textSetHidden(on);
- else if(cw == "ul")
- format.textSetUnderline(on);
- else if(cw == "super")
- format.textSetSuScript(RtfFormatting::SUPERSCRIPT);
- else if(cw == "sub")
- format.textSetSuScript(RtfFormatting::SUBSCRIPT);
- else if(cw == "cf" && HAS_PARAM)
- format.textSetColor(param);
- else if(cw == "f" && HAS_PARAM)
- format.textSetFont(param);
- else if(cw == "fs" && HAS_PARAM)
- format.textSetFontSize(param);
- else
- return false;
-
- return true;
-}
-
-bool XmlComposer::BaseAnalyser::processTextFormatting(const string& cw, int flags, int param)
-{
- return processTextFormatting(cw, flags, param, m_composer->getTextFormatting());
-}
-
-bool XmlComposer::BaseAnalyser::processTextAutoContent(const string& cw, int flags, int param)
-{
- DestinationPtr dest = m_composer->getDestination();
- ASSERT(dest != NULL);
- dest->charData(kValNull);
-
- // Auto generated content
-
- if(cw == "chftn")
- {
- // Footnote auto numbering
- int ac = m_composer->getAutoCount(AUTOCOUNT_FOOTNOTE);
-
- AN_ELEMENT(kElRef);
- AN_ATTRIBUTE(kAtType, kValFootNote);
- AN_ATTRIBUTE(kAtTo, ac);
-
- // Only output the actual link text in this case
- if(DO_EXTRAS())
- dest->charData(formatInt(ac));
-
- AN_POP_ELEMENT();
- return true;
- }
-
- return false;
-}
-
-/* ----------------------------------------------------------------------------------
- * ANALYSER/DESTINATION DEFINITIONS
- */
-
-#define ON_INITIALIZE(cls) \
- void XmlComposer::cls::initialize()
-#define ON_CONTROLWORD(cls) \
- void XmlComposer::cls::controlWord(const string& cw, int flags, int param)
-#define ON_CHARDATA(cls) \
- void XmlComposer::cls::charData(wstring data)
-#define ON_GROUPSTART(cls) \
- void XmlComposer::cls::groupStart()
-#define ON_GROUPEND(cls) \
- void XmlComposer::cls::groupEnd()
-#define ON_DONE(cls) \
- void XmlComposer::cls::done()
-
-
-// Skip Analyser --------------------------------------------------------------------
-
-ON_INITIALIZE(Skip)
- { AN_DESTINATION(Null); }
-
-ON_GROUPSTART(Skip)
- { AN_ANALYSER(Skip); }
-
-
-// Upr Analyser ---------------------------------------------------------------------
-
-XmlComposer::Upr::Upr(AnalyserPtr prv)
-{
- ASSERT(prv);
- prev = prv;
-}
-
-ON_GROUPSTART(Upr)
-{
- AN_ANALYSER(Skip);
-}
-
-ON_GROUPEND(Upr)
-{
- ASSERT(prev);
- m_composer->setAnalyser(prev);
- prev = NULL;
-}
-
-
-// Stylesheet Analyser --------------------------------------------------------------
-
-ON_INITIALIZE(Stylesheet)
-{
- AN_TOP_ELEMENT(kElStylesheet);
-}
-
-ON_GROUPSTART(Stylesheet)
-{
- // Each group should be a style
- AN_ANALYSER(Style);
-
- // Without any character data
- AN_DESTINATION(Null);
-}
-
-
-// Stylesheet Style Analyser --------------------------------------------------------
-
-ON_INITIALIZE(Style)
-{
- // Were not sure if this element is really something
- // so we can't always create
- haveStyle = false;
-}
-
-ON_CONTROLWORD(Style)
-{
- // Get the style id
- if(flags & kAsterisk)
- {
- AN_ANALYSER(Skip);
- return;
- }
-
- // Create the style tag if necessary
- if(!haveStyle)
- {
- AN_ELEMENT(kElStyle);
- AN_DESTINATION_ATTR(kAtName);
- haveStyle = true;
- }
-
- // The style id
- if(cw == "s" && flags & kHasParam)
- {
- AN_ATTRIBUTE(kAtId, param);
- }
-
- // Otherwise get as much formatting out of the tag as possible
- else if(processTextFormatting(cw, flags, param))
- DUMMY;
-
- else
- DEFAULT_CONTROLWORD;
-}
-
-ON_GROUPSTART(Style)
-{
- AN_ANALYSER(Skip);
-}
-
-ON_GROUPEND(Style)
-{
- RtfFormatting& props = m_composer->getTextFormatting();
-
- // Dig out all the formatting attributes
- if(props.textIsBold())
- AN_ATTRIBUTE(kAtBold, kValTrue);
- if(props.textIsHidden())
- AN_ATTRIBUTE(kAtHidden, kValTrue);
- if(props.textIsItalic())
- AN_ATTRIBUTE(kAtItalic, kValTrue);
- if(props.textIsStrike())
- AN_ATTRIBUTE(kAtStrike, kValTrue);
- if(props.textIsUnderline())
- AN_ATTRIBUTE(kAtUnderline, kValTrue);
-
- // TODO: Do fonts and colors here
-}
-
-
-// Font Table Analyser --------------------------------------------------------------
-
-ON_INITIALIZE(FontTable)
-{
- AN_TOP_ELEMENT(kElFontTable);
- AN_DESTINATION(Null);
-}
-
-ON_GROUPSTART(FontTable)
-{
- // Each group should be a font
- AN_ANALYSER(Font);
-}
-
-ON_DONE(FontTable)
-{
- DOM::Element deffont = m_composer->createElement(kElFont);
-
- // Default font is always the first in the list
- deffont->setAttribute(kAtId, kValZero);
-
- // Default size is always 12 pt
- deffont->setAttribute(kAtSize, L"12");
-
- // TODO: Is this correct?
- deffont->setAttribute(kAtColor, kValZero);
-
- m_composer->addDocumentOption(deffont);
-}
-
-// Font Analyser --------------------------------------------------------------------
-
-ON_INITIALIZE(Font)
-{
- AN_ELEMENT(kElFontDef);
- AN_DESTINATION_ATTR(kAtName);
-}
-
-ON_CONTROLWORD(Font)
-{
- // The font id
- if(cw == "f" && flags & kHasParam)
- AN_ATTRIBUTE(kAtId, param);
-
- else
- DEFAULT_CONTROLWORD;
-}
-
-ON_GROUPSTART(Font)
-{
- AN_ANALYSER(Skip);
-}
-
-
-// List Table Analyser --------------------------------------------------------------
-
-ON_INITIALIZE(ListTable)
-{
- AN_TOP_ELEMENT(kElListtable);
-}
-
-ON_GROUPSTART(ListTable)
-{
- // Everything in here should be a list
- AN_ANALYSER(List);
-
- // Content doesn't matter
- AN_DESTINATION(Null);
-}
-
-
-// List (in List Table) Analyser ----------------------------------------------------
-
-ON_INITIALIZE(List)
-{
- // Create a default element
- AN_ELEMENT(kElListdef);
-
- if(DO_EXTRAS())
- AN_ATTRIBUTE(kAtType, kValDisc);
-
- AN_ATTRIBUTE(kAtOrdered, L"0");
- levelsSeen = 0;
-}
-
-ON_CONTROLWORD(List)
-{
- // The name
- if(cw == "listname")
- AN_DESTINATION_ATTR(kAtName);
-
- // The list id
- else if(cw == "listid" && HAS_PARAM)
- AN_ATTRIBUTE(kAtId, param);
-
- // We let listlevel in here too
- else if(cw == "levelstartat" && HAS_PARAM)
- AN_ATTRIBUTE(kAtStart, param);
-
- // The list type
- else if(cw == "levelnfc" && HAS_PARAM)
- {
- if(DO_EXTRAS())
- {
- switch(param)
- {
- case 0: // 1, 2, 3
- case 5: // 1st, 2nd, 3rd
- case 6: // One, Two, Three
- case 7: // First, Second, Third
- case 22: // 01, 02, 03
- AN_ATTRIBUTE(kAtType, kValArabic);
- break;
- case 1: // I, II, III
- AN_ATTRIBUTE(kAtType, kValUpperRoman);
- break;
- case 2: // i, ii, iii
- AN_ATTRIBUTE(kAtType, kValLowerRoman);
- break;
- case 3: // A, B, C
- AN_ATTRIBUTE(kAtType, kValUpperAlpha);
- break;
- case 4: // a, b, c
- AN_ATTRIBUTE(kAtType, kValLowerAlpha);
- break;
- default:
- AN_ATTRIBUTE(kAtType, kValDisc);
- break;
- }
- }
-
- switch(param)
- {
- case 0: case 5: case 6: case 7: case 22:
- case 1: case 2: case 3: case 4:
- AN_ATTRIBUTE(kAtOrdered, L"1");
- break;
- default:
- AN_ATTRIBUTE(kAtOrdered, L"0");
- }
- }
-
- else
- DEFAULT_CONTROLWORD;
-}
-
-ON_GROUPSTART(List)
-{
- // Skip internal groups and content
-
- if(levelsSeen > 0)
- AN_ANALYSER(Skip);
-
- levelsSeen++;
-}
-
-
-// The List Override Table ----------------------------------------------------------
-
-ON_INITIALIZE(ListOverrideTable)
-{
- // Get all of the current lists
- DOM::Document document = m_composer->getDocument();
- lists = document.getElementsByTagName(kElListdef);
- curList = NULL;
- lsId = -1;
-}
-
-ON_GROUPSTART(ListOverrideTable)
-{
- // Content doesn't matter
- AN_DESTINATION(Null);
-}
-
-ON_CONTROLWORD(ListOverrideTable)
-{
- // New list override clear
- if(cw == "listoverride")
- curList = NULL;
-
- // List id for current listoverride
- else if(cw == "listid" && HAS_PARAM)
- {
- wstring id = formatInt(param);
-
- if(lists != NULL)
- {
- // Find the list in question
- for(int i = 0; i < lists->getLength(); i++)
- {
- DOM::Node node = lists->item(i);
- if(node != NULL && node.getNodeType() == DOM::Node::ELEMENT_NODE)
- {
- DOM::Element element = (DOM::Element&)node;
- if(element.getAttribute(kAtId) == id)
- {
- curList = element;
- break;
- }
- }
- }
- }
- }
-
- // The actual list code
- else if(cw == "ls" && HAS_PARAM)
- lsId = param;
-
- // Override the starting level for the node
- else if(cw == "levelstartat" && HAS_PARAM)
- {
- if(curList != NULL)
- curList.setAttribute(kAtStart, NUM_ATTR(param));
- }
-
- else
- DEFAULT_CONTROLWORD;
-
-
- // Okay before any overrides take effect we need to duplicate
- // the list node for overriding, using the 'listid' and 'ls' we gathered
- if(curList != NULL && lsId != -1)
- {
- DOM::Element parent = (const DOM::Element&)curList.getParentNode();
- if(parent != NULL)
- {
- curList = (const DOM::Element&)curList.cloneNode(true);
- if(curList != NULL)
- {
- parent.appendChild(curList);
- curList.setAttribute(kAtId, NUM_ATTR(lsId));
- }
- }
-
- lsId = -1;
- }
-
-}
-
-
-// Info Block Analyser --------------------------------------------------------------
-
-ON_INITIALIZE(Info)
-{
- // Create a new element
- AN_TOP_ELEMENT(kElInfo);
- AN_DESTINATION(Null);
-}
-
-ON_CONTROLWORD(Info)
-{
- if(cw == "title")
- {
- AN_ELEMENT(kElTitle);
- AN_DESTINATION(Raw);
- }
-
- else if(cw == "author")
- {
- AN_ELEMENT(kElAuthor);
- AN_DESTINATION(Raw);
- }
-
- else if(cw == "operator")
- {
- AN_ELEMENT(kElOperator);
- AN_DESTINATION(Raw);
- }
-
- else if(flags & kAsterisk)
- AN_ANALYSER(Skip);
-
- else
- DEFAULT_CONTROLWORD;
-}
-
-
-// Root Analyser --------------------------------------------------------------------
-
-ON_INITIALIZE(Root)
-{
-
-}
-
-ON_CONTROLWORD(Root)
-{
- // All the main RTF sections
- if(cw == "stylesheet")
- AN_ANALYSER(Stylesheet);
- else if(cw == "listtable")
- AN_ANALYSER(ListTable);
- else if(cw == "listoverridetable")
- AN_ANALYSER(ListOverrideTable);
- else if(cw == "info")
- AN_ANALYSER(Info);
- else if(cw == "fonttbl")
- {
- if(DO_EXTRAS())
- AN_ANALYSER(FontTable);
- else
- AN_ANALYSER(Skip);
- }
- else if(cw == "colortbl")
- AN_ANALYSER(Skip);
- else if(cw == "footnote")
- AN_ANALYSER(FootNote);
- else if(cw == "pict")
- {
- AN_ANALYSER(Skip);
- AN_DESTINATION(Null);
- }
- else if(flags & kAsterisk)
- AN_ANALYSER(Skip);
- else if(processTextContent(cw, flags, param))
- DUMMY;
- else if(processTextAutoContent(cw, flags, param))
- DUMMY;
- else if(processTextFormatting(cw, flags, param))
- DUMMY;
- else
- DEFAULT_CONTROLWORD;
-}
-
-
-// Content Destination --------------------------------------------------------------
-
-ON_INITIALIZE(Content)
-{
- parent = m_composer->getElement();
- created = false;
-}
-
-ON_CHARDATA(Content)
-{
- // Create the first time we get content
- if(!created)
- {
- DOM::Element dest = m_composer->createElement(kElDest);
- parent.appendChild(dest);
- m_composer->replaceElement(dest);
-
- DOM::Element el = m_composer->createElement(kElBlock);
- m_composer->pushElement(el);
- m_composer->popElement();
-
- created = true;
- }
-
- if(data.length() == 0)
- return;
-
- int elements = 0;
- RtfFormatting& format = m_composer->getTextFormatting();
-
- // Extra elements written out here are consolidated in
- // XmlFixups::combineDuplicates
-
- // Handle fonts etc...
- if(DO_EXTRAS())
- {
- int font = format.textFont();
- int fontsize = format.textFontSize();
-
- if(font != -1 || fontsize != -1)
- {
- AN_ELEMENT(kElFont);
-
- if(font != -1)
- AN_ATTRIBUTE(kAtName, font);
-
- if(fontsize != -1)
- {
- // Little hack for half point sizes
- wstring size = NUM_ATTR(fontsize / 2);
- if(fontsize % 2)
- size.append(L".5");
-
- AN_ATTRIBUTE(kAtSize, size);
- }
-
- if(format.textColor() != -1)
- AN_ATTRIBUTE(kAtColor, format.textColor());
-
- elements++;
- }
- }
-
- // Now do text Properties if necessary
-
- if(format.textIsBold())
- {
- AN_ELEMENT(kElB);
- elements++;
- }
-
- if(format.textIsHidden())
- {
- AN_ELEMENT(kElHide);
- elements++;
- }
-
- if(format.textIsItalic())
- {
- AN_ELEMENT(kElI);
- elements++;
- }
-
- if(format.textIsStrike())
- {
- AN_ELEMENT(kElStrike);
- elements++;
- }
-
- if(format.textIsUnderline())
- {
- AN_ELEMENT(kElU);
- elements++;
- }
-
- if(format.textSuScript() == RtfFormatting::SUPERSCRIPT)
- {
- AN_ELEMENT(kElSuper);
- elements++;
- }
-
- if(format.textSuScript() == RtfFormatting::SUBSCRIPT)
- {
- AN_ELEMENT(kElSub);
- elements++;
- }
-
- // Write the data to the element
- m_composer->getElement().appendChild(
- m_composer->getDocument().createTextNode(data));
-
- // Now drop out of all the above formatting
- while(elements-- > 0)
- AN_POP_ELEMENT();
-}
-
-
-// FootNote Analyser ----------------------------------------------------------------
-
-ON_INITIALIZE(FootNote)
-{
- int ac = m_composer->getAutoCount(AUTOCOUNT_FOOTNOTE);
-
- AN_ELEMENT(kElFootNote);
- AN_ATTRIBUTE(kAtId, ac);
- AN_DESTINATION(Content);
-}
-
-ON_CONTROLWORD(FootNote)
-{
- // Inside foot notes there's no link to the foot note
- if(cw == "chftn")
- {
- // Only put actual text when in extras mode
- if(DO_EXTRAS())
- {
- DestinationPtr dest = m_composer->getDestination();
- ASSERT(dest != NULL);
- int ac = m_composer->getAutoCount(AUTOCOUNT_FOOTNOTE);
- dest->charData(formatInt(ac));
- }
-
- return;
- }
-
- // Process text content in the foot note
- else if(processTextContent(cw, flags, param))
- DUMMY;
- else if(processTextAutoContent(cw, flags, param))
- DUMMY;
- else if(processTextFormatting(cw, flags, param))
- DUMMY;
- else
- DEFAULT_CONTROLWORD;
-}
-
-ON_DONE(FootNote)
-{
- m_composer->incrementAutoCount(AUTOCOUNT_FOOTNOTE);
-}
-
-
-// Raw Destination ------------------------------------------------------------------
-
-ON_CHARDATA(Raw)
-{
- // Write the data to the element
- m_composer->getElement().appendChild(
- m_composer->getDocument().createTextNode(data));
-}
-
-
-// Attribute Destination ------------------------------------------------------------
-
-ON_INITIALIZE(Attribute)
-{
- element = m_composer->getElement();
- ASSERT(element != NULL);
-}
-
-ON_CHARDATA(Attribute)
-{
- // Get the current value
- wstring cur = element.getAttribute(name);
-
- if(data.at(data.size() - 1) == L';')
- data.resize(data.size() - 1);
-
- // Append data
- cur.append(data);
-
- // Write it back
- element.setAttribute(name, cur);
-}
-