#ifndef __RTF_h_ #define __RTF_h_ #include "../shared/MiscSupport.h" namespace rtf { // Rich Text Format (RTF) Version 1.5 Specification can be found at // http://www.biblioscape.com/rtf15_spec.htm std::string escapeString(std::string s); inline std::string startBold() { // The {} seems a little silly, but it is required by Delphi's TRichEdit // control. Basically, Delphi squashes all white space to look like a // single space, much like HTML. So "a b" and "a b" are identical; // only one space will appear on the output. This, by itself, would // not be so bad. But Delphi also treats "a\B b\B0 c" and "a\B b\B0 c" // as the same. Both will product "abc" on the output, with the b in // bold and no spaces. // // Adding a {} after each space seems to solve this problem. Each space // is considered a seperate space. This works for spaces which are part // of the plain text and spaces which end a control word. // // I can't find any references to this odd behavior in the RTF spec. And // WordPad does not do this. In WordPad spaces are not squashed; "a b" // and "a b" are different. The second one will produce output with // three spaces between the a and the b, exactly like the input. // // {} is a no-op, so in theory this trick should not cause any harm for // a reader which works like WordPad. return "\\b {}"; } inline std::string endBold() { return "\\b0 {}"; } inline std::string bold(std::string s) { return startBold() + s + endBold(); } inline std::string startItalic() { return "\\i {}"; } inline std::string endItalic() { return "\\i0 {}"; } inline std::string italic(std::string s) { return startItalic() + s + endItalic(); } inline std::string startUnderline() { return "\\ul {}"; } inline std::string endUnderline() { return "\\ulnone {}"; } inline std::string underline(std::string s) { return startUnderline() + s + endUnderline(); } inline std::string paragraph() { return "\\par "; } class Color { private: unsigned char _red; unsigned char _green; unsigned char _blue; public: Color(unsigned char red, unsigned char green, unsigned char blue) : _red(red), _green(green), _blue(blue) { } Color() : _red(0), _green(0), _blue(0) { } bool operator <(Color const &other) const; bool operator ==(Color const &other) const; operator std::string() const; }; extern Color red; extern Color green; class ColorTable { private: std::map< Color, int > _byColor; std::vector< Color > _byIndex; public: int getColorIndex(); // The default color. int getColorIndex(Color c); std::string startForegroundColor(); // The default color. std::string startForegroundColor(Color c); std::string foregroundColor(std::string s, Color c); std::string startHighlightColor(); // The default color. std::string startHighlightColor(Color c); std::string highlightColor(std::string s, Color c); operator std::string() const; std::string operator +(std::string const &s) const; }; inline int ColorTable::getColorIndex() { // For simplicity we always make this index 0. But this function is not // const, just in case we change the implementation. return 0; } inline std::string ColorTable::startForegroundColor() { return "\\cf" + itoa(getColorIndex()) + " {}"; } inline std::string ColorTable::startForegroundColor(Color c) { return "\\cf" + itoa(getColorIndex(c)) + " {}"; } inline std::string ColorTable::foregroundColor(std::string s, Color c) { return "{" + startForegroundColor(c) + s + "}"; } inline std::string ColorTable::startHighlightColor() { // The hightlight attribute is the background color of the text. There // is also an attribute \cb which is defined the be the background // color. This does not appear to be supported by anyone! return "\\highlight" + itoa(getColorIndex()) + " {}"; } inline std::string ColorTable::startHighlightColor(Color c) { return "\\highlight" + itoa(getColorIndex(c)) + " {}"; } inline std::string ColorTable::highlightColor(std::string s, Color c) { return "{" + startHighlightColor(c) + s + "}"; } inline std::string ColorTable::operator +(std::string const &s) const { return (std::string)*this + s; } } #endif