1 // -*- C++ -*- 2 /** 3 * \file output_xhtml.h 4 * This file is part of LyX, the document processor. 5 * Licence details can be found in the file COPYING. 6 * 7 * \author Richard Heck 8 * 9 * Full author contact details are available in file CREDITS. 10 */ 11 12 #ifndef OUTPUT_XHTML_H 13 #define OUTPUT_XHTML_H 14 15 #include "LayoutEnums.h" 16 17 #include "support/docstream.h" 18 #include "support/strfwd.h" 19 20 #include <deque> 21 #include <memory> 22 23 24 namespace lyx { 25 26 class Buffer; 27 class OutputParams; 28 class Text; 29 30 // Inspiration for the *Tag structs and for XHTMLStream 31 // came from MathStream and its cousins. 32 33 namespace html { 34 35 struct FontTag; 36 struct EndFontTag; 37 38 /// Attributes will be escaped automatically and so should NOT 39 /// be escaped before being passed to the constructor. 40 struct StartTag 41 { 42 /// StartTagStartTag43 explicit StartTag(std::string const & tag) : tag_(tag), keepempty_(false) {} 44 /// 45 explicit StartTag(std::string const & tag, std::string const & attr, 46 bool keepempty = false) tag_StartTag47 : tag_(tag), attr_(attr), keepempty_(keepempty) {} 48 /// ~StartTagStartTag49 virtual ~StartTag() {} 50 /// <tag_ attr_> 51 virtual docstring writeTag() const; 52 /// </tag_> 53 virtual docstring writeEndTag() const; 54 /// asFontTagStartTag55 virtual FontTag const * asFontTag() const { return 0; } 56 /// 57 virtual bool operator==(StartTag const & rhs) const 58 { return tag_ == rhs.tag_; } 59 /// 60 virtual bool operator!=(StartTag const & rhs) const 61 { return !(*this == rhs); } 62 /// 63 virtual bool operator==(FontTag const & rhs) const; 64 /// 65 std::string tag_; 66 /// 67 std::string attr_; 68 /// whether to keep things like "<tag></tag>" or discard them 69 /// you would want this for td, e.g, but maybe not for a div 70 bool keepempty_; 71 }; 72 73 74 /// 75 struct EndTag 76 { 77 /// EndTagEndTag78 explicit EndTag(std::string tag) : tag_(tag) {} 79 /// ~EndTagEndTag80 virtual ~EndTag() {} 81 /// </tag_> 82 virtual docstring writeEndTag() const; 83 /// 84 bool operator==(StartTag const & rhs) const 85 { return tag_ == rhs.tag_; } 86 /// 87 bool operator!=(StartTag const & rhs) const 88 { return !(*this == rhs); } 89 /// asFontTagEndTag90 virtual EndFontTag const * asFontTag() const { return 0; } 91 /// 92 std::string tag_; 93 }; 94 95 96 /// Tags like <img /> 97 /// Attributes will be escaped automatically and so should NOT 98 /// be escaped before being passed to the constructor. 99 struct CompTag 100 { 101 /// CompTagCompTag102 explicit CompTag(std::string const & tag) 103 : tag_(tag) {} 104 /// CompTagCompTag105 explicit CompTag(std::string const & tag, std::string const & attr) 106 : tag_(tag), attr_(attr) {} 107 /// <tag_ attr_ /> 108 docstring writeTag() const; 109 /// 110 std::string tag_; 111 /// 112 std::string attr_; 113 }; 114 115 116 /// A special case of StartTag, used exclusively for tags that wrap paragraphs. 117 struct ParTag : public StartTag 118 { 119 /// 120 explicit ParTag(std::string const & tag, std::string attr, 121 std::string const & parid); 122 /// ~ParTagParTag123 ~ParTag() {} 124 }; 125 126 127 /// 128 enum FontTypes { 129 // ranges 130 FT_EMPH, 131 FT_NOUN, 132 FT_UBAR, 133 FT_DBAR, 134 FT_WAVE, 135 FT_SOUT, 136 FT_XOUT, 137 // bold 138 FT_BOLD, 139 // shapes 140 FT_UPRIGHT, 141 FT_ITALIC, 142 FT_SLANTED, 143 FT_SMALLCAPS, 144 // families 145 FT_ROMAN, 146 FT_SANS, 147 FT_TYPE, 148 // sizes 149 FT_SIZE_TINY, 150 FT_SIZE_SCRIPT, 151 FT_SIZE_FOOTNOTE, 152 FT_SIZE_SMALL, 153 FT_SIZE_NORMAL, 154 FT_SIZE_LARGE, 155 FT_SIZE_LARGER, 156 FT_SIZE_LARGEST, 157 FT_SIZE_HUGE, 158 FT_SIZE_HUGER, 159 FT_SIZE_INCREASE, 160 FT_SIZE_DECREASE 161 }; 162 163 164 /// 165 struct FontTag : public StartTag 166 { 167 /// 168 explicit FontTag(FontTypes type); 169 /// asFontTagFontTag170 FontTag const * asFontTag() const { return this; } 171 /// 172 bool operator==(StartTag const &) const; 173 /// 174 FontTypes font_type_; 175 }; 176 177 178 /// 179 struct EndFontTag : public EndTag 180 { 181 /// 182 explicit EndFontTag(FontTypes type); 183 /// asFontTagEndFontTag184 EndFontTag const * asFontTag() const { return this; } 185 /// 186 FontTypes font_type_; 187 }; 188 189 190 // trivial struct for output of newlines 191 struct CR{}; 192 193 } // namespace html 194 195 class XHTMLStream { 196 public: 197 /// 198 explicit XHTMLStream(odocstream & os); 199 /// os()200 odocstream & os() { return os_; } 201 /// 202 // int & tab() { return tab_; } 203 /// closes any font tags that are eligible to be closed, 204 /// i.e., last on the tag_stack_. 205 /// \return false if there are open font tags we could not close. 206 /// because they are "blocked" by open non-font tags on the stack. 207 bool closeFontTags(); 208 /// sets a mark so we know what tags to close at the end. 209 /// normally called at the start of a paragraph. 210 void startDivision(bool keep_empty); 211 /// clears the mark set by previous method. 212 /// there should not be any other tags open before it on the stack, 213 /// but if there are, we will close them. 214 void endDivision(); 215 /// 216 XHTMLStream & operator<<(docstring const &); 217 /// 218 XHTMLStream & operator<<(const char *); 219 /// 220 XHTMLStream & operator<<(char_type); 221 /// 222 XHTMLStream & operator<<(int); 223 /// 224 XHTMLStream & operator<<(char); 225 /// 226 XHTMLStream & operator<<(html::StartTag const &); 227 /// 228 XHTMLStream & operator<<(html::EndTag const &); 229 /// 230 XHTMLStream & operator<<(html::CompTag const &); 231 /// 232 XHTMLStream & operator<<(html::ParTag const &); 233 /// 234 XHTMLStream & operator<<(html::FontTag const &); 235 /// 236 XHTMLStream & operator<<(html::CR const &); 237 /// 238 enum EscapeSettings { 239 ESCAPE_NONE, 240 ESCAPE_AND, // meaning & 241 ESCAPE_ALL // meaning <, >, &, at present 242 }; 243 /// Sets what we are going to escape on the NEXT write. 244 /// Everything is reset for the next time. 245 XHTMLStream & operator<<(EscapeSettings); 246 /// This routine is for debugging the tag stack, etc. Code 247 /// for it is disabled by default, however, so you will need 248 /// to enable it if you want to use it. 249 void dumpTagStack(std::string const & msg); 250 private: 251 /// 252 void clearTagDeque(); 253 /// 254 bool isTagOpen(html::StartTag const &) const; 255 /// 256 bool isTagOpen(html::EndTag const &) const; 257 /// 258 bool isTagPending(html::StartTag const &) const; 259 /// 260 void writeError(std::string const &) const; 261 /// 262 odocstream & os_; 263 /// 264 EscapeSettings escape_; 265 // What we would really like to do here is simply use a 266 // deque<StartTag>. But we want to store both StartTags and 267 // sub-classes thereof on this stack, which means we run into the 268 // so-called polymorphic class problem with the STL. We therefore have 269 // to use a deque<StartTag *>, which leads to the question who will 270 // own these pointers and how they will be deleted, so we use shared 271 // pointers. 272 /// 273 typedef std::shared_ptr<html::StartTag> TagPtr; 274 typedef std::deque<TagPtr> TagDeque; 275 /// 276 template <typename T> makeTagPtr(T const & tag)277 TagPtr makeTagPtr(T const & tag) { return std::make_shared<T>(tag); } 278 /// 279 TagDeque pending_tags_; 280 /// 281 TagDeque tag_stack_; 282 }; 283 284 /// 285 void xhtmlParagraphs(Text const & text, 286 Buffer const & buf, 287 XHTMLStream & xs, 288 OutputParams const & runparams); 289 290 /// \return a string appropriate for setting alignment in CSS 291 /// Does NOT return "justify" for "block" 292 std::string alignmentToCSS(LyXAlignment align); 293 294 namespace html { 295 /// 296 docstring escapeChar(char_type c, XHTMLStream::EscapeSettings e); 297 /// converts a string to a form safe for links, etc 298 docstring htmlize(docstring const & str, XHTMLStream::EscapeSettings e); 299 /// cleans \param str for use as an atttribute by replacing 300 /// all non-alnum by "_" 301 docstring cleanAttr(docstring const & str); 302 /// \p c must be ASCII 303 docstring escapeChar(char c, XHTMLStream::EscapeSettings e); 304 305 } // namespace html 306 } // namespace lyx 307 308 #endif 309