#ifndef __RTFPARSER_H__ #define __RTFPARSER_H__ #include "levelhandler.h" struct RtfParserOptions { RtfParserOptions() { memset(this, 0, sizeof(*this)); } bool doColors; }; class RtfParser : public LevelHandler { public: RtfParser(const RtfParserOptions& options); virtual ~RtfParser(); virtual void startDocument(RtfReader* 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); // Element management functions DOM::Element createElement(const string& name); void pushElement(const DOM::Element& element); void replaceElement(const DOM::Element& element); DOM::Element popElement(); void setAttribute(const string& name, const wstring& value, DOM::Element el = DOM::Element()); // Changing the current parser functions void setAnalyser(AnalyserPtr analy); void setDestination(DestinationPtr dest); DestinationPtr replaceDestination(DestinationPtr dest); // Current status functions RtfFormatting& getTextFormatting(); AnalyserPtr getAnalyser(); DestinationPtr getDestination(); DOM::Document getDocument() { return m_document; } static bool isElement(const DOM::Node& node, const string& name); static bool isEqualElement(const DOM::Element& el1, const DOM::Element& el2); static void copyAttributes(const DOM::Element& src, DOM::Element& dest, const char** hideList); static void insertAfter(DOM::Node& parent, const DOM::Node& node, const DOM::Node& ref); static DOM::Element getContainingElement(const DOM::Node& node, const string& name); static DOM::Element getPriorElement(const DOM::Node& node, const string& name); static wstring formatInt(int num); const RtfParserOptions& getOptions() { return m_options; } protected: // Cleanup Functions void fixBlocks(DOM::Document doc); void fixLists(const DOM::Document doc); void fixStyles(const DOM::Document doc); bool breakElement(const DOM::Element& el, const string& contain); void breakBreak(DOM::Document& doc, const string& contain, const string& tag); void breakLists(DOM::Document& document); void breakTables(DOM::Document& document); void breakTags(DOM::Document& doc, const string& parentName, const string& tagName); void breakBlocks(DOM::Document& document); void wrapTags(DOM::Document& document, const string& tagName, const string& wrapName); void removeTags(const DOM::Document& doc); void removeDuplicates(const DOM::Document& doc); virtual void clear(); // Data protected: DOM::DOMImplementation m_impl; DOM::Document m_document; RtfParserOptions m_options; // Sub classes protected: #define DESTINATION(cls) class cls : public Destination { public: #define END_DESTINATION }; #define ANALYSER(cls) class cls : public ParseAnalyser { 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(); DESTINATION(Content) INITIALIZE CHARDATA DATA_PORTION bool created; DOM::Element parent; END_DESTINATION DESTINATION(Null) END_DESTINATION DESTINATION(Raw) CHARDATA END_DESTINATION DESTINATION(Attribute) Attribute(const string& nm) : name(nm) {} INITIALIZE CHARDATA DATA_PORTION string name; DOM::Element element; END_DESTINATION class ParseAnalyser : public Analyser { public: virtual void controlWord(const string& cw, int flags, int param) { processDefault(cw, flags, param); } protected: // Some helper functions bool processDefault(const string& cw, int flags, int param); bool processTextFormatting(const string& cw, int flags, int param, RtfFormatting& format); bool processTextContent(const string& cw, int flags, int param); bool processTextFormatting(const string& cw, int flags, int param); DOM::Element getCurrentBlock(); void applyParaFormatting(RtfFormatting* format, DOM::Element& el); }; ANALYSER(Skip) INITIALIZE GROUPSTART END_ANALYSER #if 0 ANALYSER(Table) INITIALIZE CONTROLWORD DATA_PORTION int stack; LevelPtr level; END_ANALYSER #endif ANALYSER(Upr) Upr(AnalyserPtr prv); GROUPSTART GROUPEND DATA_PORTION AnalyserPtr prev; END_ANALYSER ANALYSER(Stylesheet) INITIALIZE GROUPSTART END_ANALYSER ANALYSER(Style) INITIALIZE CONTROLWORD GROUPSTART GROUPEND DATA_PORTION bool haveStyle; END_ANALYSER ANALYSER(ListTable) INITIALIZE GROUPSTART END_ANALYSER ANALYSER(List) INITIALIZE CONTROLWORD GROUPSTART DATA_PORTION int levelsSeen; END_ANALYSER ANALYSER(ListOverrideTable) INITIALIZE CONTROLWORD GROUPSTART GROUPEND DATA_PORTION DOM::NodeList lists; int lsId; DOM::Element curList; END_ANALYSER ANALYSER(Info) INITIALIZE CONTROLWORD END_ANALYSER ANALYSER(Root) INITIALIZE CONTROLWORD END_ANALYSER }; #endif // __RTFPARSER_H__