/* * 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 * */ #ifndef __XMLCOMPOSER_H__ #define __XMLCOMPOSER_H__ #include "levelhandler.h" struct XmlComposerOptions { XmlComposerOptions() { memset(this, 0, sizeof(*this)); } bool extras; }; /* * XmlComposer * * This is where the RTF gets initially converted to XML. RtfParser sends * notifications to this class's RtfHandler interface. It forwards them to * the current analysers and destinations which produce XML content. * (see xmlcomposehelpers.h) * * Not all conversion is completed here. Because RTF is so very wierd we * have to run lots of fixups are run in endDocument (see rtffixups.h) */ class XmlComposer : public LevelHandler { public: XmlComposer(const XmlComposerOptions& options); virtual ~XmlComposer(); // Handler Overrides virtual void startDocument(RtfParser* reader); virtual void endDocument(); virtual void controlWord(const string& cw, int flags, int param); virtual void groupStart(); virtual void groupEnd(); virtual void charData(wstring data); // Create an XML element with given name DOM::Element createElement(const string& name); // Push an XML element on the current level void pushElement(const DOM::Element& element); // Push an element at the top of the document void pushTopElement(const DOM::Element& element); // Replace current XML element with given element void replaceElement(const DOM::Element& element); // Move up one XML element level without changing RTF level DOM::Element popElement(); // Set attributes on the current XML Element void setAttribute(const string& name, const wstring& value, DOM::Element el = DOM::Element()); void setAttribute(const string& name, int value, DOM::Element el = DOM::Element()); // The current analyser in use AnalyserPtr getAnalyser(); void setAnalyser(AnalyserPtr analy); // The current destination in use DestinationPtr getDestination(); void setDestination(DestinationPtr dest); // Replace the current destination (sets level deep) DestinationPtr replaceDestination(DestinationPtr dest); // The types of auto numbering enum { AUTOCOUNT_FOOTNOTE, AUTOCOUNT_MAX }; // Functions for RTF auto numbering int getAutoCount(int type); void incrementAutoCount(int type); // Add a document option to the option block void addDocumentOption(DOM::Element& option); // Get the current formatting options RtfFormatting& getTextFormatting(); DOM::Document getDocument() { return m_document; } const XmlComposerOptions& getOptions() { return m_options; } // LevelHandler override protected: virtual void clear(); // Data protected: DOM::DOMImplementation m_impl; // For creating the document DOM::Document m_document; // The current document XmlComposerOptions m_options; // Configurable options for parsing int m_autocount[AUTOCOUNT_MAX]; // Auto counters for the document DOM::Element m_docOptions; // For storing document options // Sub classes protected: #define DESTINATION(cls) class cls : public Destination { public: #define END_DESTINATION }; #define ANALYSER(cls) class cls : public BaseAnalyser { public: #define END_ANALYSER }; #define DATA_PORTION protected: #define INITIALIZE virtual void initialize(); #define CHARDATA virtual void charData(wstring data); #define CONTROLWORD virtual void controlWord(const string& cw, int flags, int param); #define GROUPSTART virtual void groupStart(); #define GROUPEND virtual void groupEnd(); #define DONE virtual void done(); // Main destination for document character content DESTINATION(Content) INITIALIZE CHARDATA DATA_PORTION bool created; DOM::Element parent; END_DESTINATION // Discards character data DESTINATION(Null) END_DESTINATION // Copies raw character data to output DESTINATION(Raw) CHARDATA END_DESTINATION // Copies character data to an XML attribute DESTINATION(Attribute) Attribute(const string& nm) : name(nm) {} INITIALIZE CHARDATA DATA_PORTION string name; DOM::Element element; END_DESTINATION // Base class for analysers with some helper functions class BaseAnalyser : public Analyser { public: virtual void controlWord(const string& cw, int flags, int param) { processDefault(cw, flags, param); } protected: // Process a standard set of tags that can be found anywhere bool processDefault(const string& cw, int flags, int param); // Process text formatting tags bool processTextFormatting(const string& cw, int flags, int param, RtfFormatting& format); bool processTextFormatting(const string& cw, int flags, int param); // Creates 'fix' tags for paragraph formatting in element void applyParaFormatting(RtfFormatting* format, DOM::Element& el); // Process tags that are either text content, or change context bool processTextContent(const string& cw, int flags, int param); // Process tags that generate text content (like auto-numbering, fields) bool processTextAutoContent(const string& cw, int flags, int param); // Convenience function DOM::Element getCurrentBlock(); }; // Skip tags and groups ANALYSER(Skip) INITIALIZE GROUPSTART END_ANALYSER // Unicode block analyser ANALYSER(Upr) Upr(AnalyserPtr prv); GROUPSTART GROUPEND DATA_PORTION AnalyserPtr prev; END_ANALYSER // Handle Stylesheets ANALYSER(Stylesheet) INITIALIZE GROUPSTART END_ANALYSER // Handle a style in a stylesheet ANALYSER(Style) INITIALIZE CONTROLWORD GROUPSTART GROUPEND DATA_PORTION bool haveStyle; END_ANALYSER // Handle the Font Table ANALYSER(FontTable) INITIALIZE GROUPSTART DONE END_ANALYSER // Handle a Font in the Table ANALYSER(Font) INITIALIZE CONTROLWORD GROUPSTART END_ANALYSER // Handle the list definitions ANALYSER(ListTable) INITIALIZE GROUPSTART END_ANALYSER // Handle a list in the list definitions ANALYSER(List) INITIALIZE CONTROLWORD GROUPSTART DATA_PORTION int levelsSeen; END_ANALYSER // Handle list overrides ANALYSER(ListOverrideTable) INITIALIZE CONTROLWORD GROUPSTART DATA_PORTION DOM::NodeList lists; int lsId; DOM::Element curList; END_ANALYSER // Creates the info block ANALYSER(Info) INITIALIZE CONTROLWORD END_ANALYSER // The main root analyser ANALYSER(Root) INITIALIZE CONTROLWORD END_ANALYSER // Handles footnotes ANALYSER(FootNote) INITIALIZE CONTROLWORD DONE END_ANALYSER }; #endif // __XMLCOMPOSER_H__