X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fxml.h;h=902007581ea4f64dc377e465c76f190746ff5f8a;hb=19f5aa58aa55fe210c689052967ade0f943f82fb;hp=45fb52f0cdaeb6bcacff7d286397df9511411ac8;hpb=a6b07608d8e9de24383d3ebaec20b6b265ed9314;p=lyx.git diff --git a/src/xml.h b/src/xml.h index 45fb52f0cd..902007581e 100644 --- a/src/xml.h +++ b/src/xml.h @@ -38,93 +38,103 @@ struct CR; class XMLStream { public: - /// - explicit XMLStream(odocstream & os): os_(os), escape_(ESCAPE_ALL) {} - /// - odocstream & os() { return os_; } - /// - // int & tab() { return tab_; } - /// closes any font tags that are eligible to be closed, - /// i.e., last on the tag_stack_. - /// \return false if there are open font tags we could not close. - /// because they are "blocked" by open non-font tags on the stack. - bool closeFontTags(); - /// sets a mark so we know what tags to close at the end. - /// normally called at the start of a paragraph. - void startDivision(bool keep_empty); - /// clears the mark set by previous method. - /// there should not be any other tags open before it on the stack, - /// but if there are, we will close them. - void endDivision(); - /// - XMLStream & operator<<(docstring const &); - /// - XMLStream & operator<<(const char *); - /// - XMLStream & operator<<(char_type); - /// - XMLStream & operator<<(int); - /// - XMLStream & operator<<(char); - /// - XMLStream & operator<<(xml::StartTag const &); - /// - XMLStream & operator<<(xml::EndTag const &); - /// - XMLStream & operator<<(xml::CompTag const &); - /// - XMLStream & operator<<(xml::ParTag const &); - /// - XMLStream & operator<<(xml::FontTag const &); - /// - XMLStream & operator<<(xml::CR const &); - /// - enum EscapeSettings { - ESCAPE_NONE, - ESCAPE_AND, // meaning & - ESCAPE_ALL // meaning <, >, &, at present - }; - /// Sets what we are going to escape on the NEXT write. - /// Everything is reset for the next time. - XMLStream & operator<<(EscapeSettings); - /// This routine is for debugging the tag stack, etc. Code - /// for it is disabled by default, however, so you will need - /// to enable it if you want to use it. - void dumpTagStack(std::string const & msg); + /// + explicit XMLStream(odocstream & os): os_(os), escape_(ESCAPE_ALL), is_last_tag_cr_(true) {} + /// + odocstream & os() { return os_; } + /// + // int & tab() { return tab_; } + /// closes any font tags that are eligible to be closed, + /// i.e., last on the tag_stack_. + /// \return false if there are open font tags we could not close. + /// because they are "blocked" by open non-font tags on the stack. + bool closeFontTags(); + /// sets a mark so we know what tags to close at the end. + /// normally called at the start of a paragraph. + void startDivision(bool keep_empty); + /// clears the mark set by previous method. + /// there should not be any other tags open before it on the stack, + /// but if there are, we will close them. + void endDivision(); + /// + XMLStream & operator<<(docstring const &); + /// + XMLStream & operator<<(const char *); + /// + XMLStream & operator<<(char_type); + /// + XMLStream & operator<<(int); + /// + XMLStream & operator<<(char); + /// + XMLStream & operator<<(xml::StartTag const &); + /// + XMLStream & operator<<(xml::EndTag const &); + /// + XMLStream & operator<<(xml::CompTag const &); + /// + XMLStream & operator<<(xml::ParTag const &); + /// + XMLStream & operator<<(xml::FontTag const &); + /// + XMLStream & operator<<(xml::CR const &); + /// + enum EscapeSettings { + ESCAPE_NONE, + ESCAPE_AND, // meaning & + ESCAPE_ALL, // meaning <, >, &, at present, except things that are forbidden in comments + ESCAPE_COMMENTS // Anything that is forbidden within comments + }; + /// Sets what we are going to escape on the NEXT write. + /// Everything is reset for the next time. + XMLStream & operator<<(EscapeSettings); + /// This routine is for debugging the tag stack, etc. Code + /// for it is disabled by default, however, so you will need + /// to enable it if you want to use it. + void dumpTagStack(std::string const & msg); + /// + bool isTagOpen(xml::StartTag const &, int maxdepth = -1) const; + /// + bool isTagOpen(xml::EndTag const &, int maxdepth = -1) const; + /// + bool isTagPending(xml::StartTag const &, int maxdepth = -1) const; + /// Is the last tag that was added to the stream a new line (CR)? This is mostly to known + /// whether a new line must be added. Therefore, consider that an empty stream just had a CR, + /// that simplifies the logic using this code. + bool isLastTagCR() const { return is_last_tag_cr_; }; + /// + void writeError(std::string const &); + /// + void writeError(docstring const &); + /// + typedef std::shared_ptr TagPtr; + /// Returns the last element on the tag stack. XMLStream keeps ownership of the item. + TagPtr getLastStackTag(); private: - /// - void clearTagDeque(); - /// - bool isTagOpen(xml::StartTag const &) const; - /// - bool isTagOpen(xml::EndTag const &) const; - /// - bool isTagPending(xml::StartTag const &) const; - /// - void writeError(std::string const &) const; - /// - void writeError(docstring const &) const; - /// - odocstream & os_; - /// - EscapeSettings escape_; - // What we would really like to do here is simply use a - // deque. But we want to store both StartTags and - // sub-classes thereof on this stack, which means we run into the - // so-called polymorphic class problem with the STL. We therefore have - // to use a deque, which leads to the question who will - // own these pointers and how they will be deleted, so we use shared - // pointers. - /// - typedef std::shared_ptr TagPtr; - typedef std::deque TagDeque; - /// - template - TagPtr makeTagPtr(T const & tag) { return std::make_shared(tag); } - /// - TagDeque pending_tags_; - /// - TagDeque tag_stack_; + /// + void clearTagDeque(); + /// + odocstream & os_; + /// + EscapeSettings escape_; + // What we would really like to do here is simply use a + // deque. But we want to store both StartTags and + // sub-classes thereof on this stack, which means we run into the + // so-called polymorphic class problem with the STL. We therefore have + // to use a deque, which leads to the question who will + // own these pointers and how they will be deleted, so we use shared + // pointers. + /// + typedef std::deque TagDeque; + /// + template + TagPtr makeTagPtr(T const & tag) { return std::make_shared(tag); } + /// + TagDeque pending_tags_; + /// + TagDeque tag_stack_; + /// + bool is_last_tag_cr_; }; namespace xml { @@ -138,9 +148,6 @@ docstring escapeChar(char c, XMLStream::EscapeSettings e); /// Escape a word instead of a single character docstring escapeString(docstring const & raw, XMLStream::EscapeSettings e=XMLStream::ESCAPE_ALL); -/// Converts a string to a form safe for links, etc. -docstring xmlize(docstring const &str, XMLStream::EscapeSettings e); - /// cleans \param str for use as an attribute by replacing all non-altnum by "_" docstring cleanAttr(docstring const & str); @@ -151,7 +158,13 @@ docstring escapeChar(char c, XMLStream::EscapeSettings e); docstring cleanID(docstring const &orig); /// returns a unique numeric ID -docstring const uniqueID(docstring const & label); +docstring uniqueID(docstring const & label); + +/// determines whether a string only contains space characters +bool isNotOnlySpace(docstring const & str); + +/// trims the string to the left, i.e. remove any space-like character at the beginning of the string +docstring trimLeft(docstring const & str); struct FontTag; struct EndFontTag; @@ -160,69 +173,76 @@ struct EndFontTag; /// be escaped before being passed to the constructor. struct StartTag { - /// - explicit StartTag(std::string const & tag) : tag_(from_ascii(tag)), keepempty_(false) {} - /// - explicit StartTag(docstring const & tag) : tag_(tag), keepempty_(false) {} - /// - explicit StartTag(docstring const & tag, docstring const & attr, - bool keepempty = false) - : tag_(tag), attr_(attr), keepempty_(keepempty) {} - /// - explicit StartTag(std::string const & tag, std::string const & attr, - bool keepempty = false) - : tag_(from_ascii(tag)), attr_(from_ascii(attr)), keepempty_(keepempty) {} - /// - explicit StartTag(std::string const & tag, docstring const & attr, - bool keepempty = false) - : tag_(from_ascii(tag)), attr_(attr), keepempty_(keepempty) {} - /// - virtual ~StartTag() {} - /// - virtual docstring writeTag() const; - /// - virtual docstring writeEndTag() const; - /// - virtual FontTag const * asFontTag() const { return 0; } - /// - virtual bool operator==(StartTag const & rhs) const - { return tag_ == rhs.tag_; } - /// - virtual bool operator!=(StartTag const & rhs) const - { return !(*this == rhs); } - /// - virtual bool operator==(FontTag const & rhs) const; - /// - docstring tag_; - /// - docstring attr_; - /// whether to keep things like "" or discard them - /// you would want this for td, e.g, but maybe not for a div - bool keepempty_; + /// + explicit StartTag(std::string const & tag) : tag_(from_ascii(tag)), keepempty_(false), tagtype_("none") {} + /// + explicit StartTag(docstring const & tag) : tag_(tag), keepempty_(false), tagtype_("none") {} + /// + explicit StartTag(docstring const & tag, docstring const & attr, + bool keepempty = false, std::string const & tagtype = "none") + : tag_(tag), attr_(attr), keepempty_(keepempty), tagtype_(tagtype) {} + /// + explicit StartTag(std::string const & tag, std::string const & attr, + bool keepempty = false, std::string const & tagtype = "none") + : tag_(from_ascii(tag)), attr_(from_utf8(attr)), keepempty_(keepempty), tagtype_(tagtype) {} + /// + explicit StartTag(std::string const & tag, docstring const & attr, + bool keepempty = false, std::string const & tagtype = "none") + : tag_(from_ascii(tag)), attr_(attr), keepempty_(keepempty), tagtype_(tagtype) {} + /// + virtual ~StartTag() = default; + /// + virtual docstring writeTag() const; + /// + virtual docstring writeEndTag() const; + /// + virtual FontTag const * asFontTag() const { return nullptr; } + /// + virtual bool operator==(StartTag const & rhs) const + { return tag_ == rhs.tag_; } + /// + virtual bool operator!=(StartTag const & rhs) const + { return !(*this == rhs); } + /// + virtual bool operator==(FontTag const & rhs) const; + /// + docstring tag_; + /// + docstring attr_; + /// whether to keep things like "" or discard them + /// you would want this for td, e.g, but maybe not for a div + bool keepempty_; + /// Type of tag for new-line behaviour. Either "paragraph", "inline", "block", or "none" (default). + std::string tagtype_; }; /// struct EndTag { - /// - explicit EndTag(std::string tag) : tag_(from_ascii(tag)) {} - /// - explicit EndTag(docstring tag) : tag_(tag) {} - /// - virtual ~EndTag() {} - /// - virtual docstring writeEndTag() const; - /// - bool operator==(StartTag const & rhs) const - { return tag_ == rhs.tag_; } - /// - bool operator!=(StartTag const & rhs) const - { return !(*this == rhs); } - /// - virtual EndFontTag const * asFontTag() const { return 0; } - /// - docstring tag_; + /// + explicit EndTag(std::string const & tag, std::string const & tagtype = "none") + : tag_(from_ascii(tag)), tagtype_(tagtype) {} + /// + explicit EndTag(docstring const & tag, std::string const & tagtype = "none") + : tag_(tag), tagtype_(tagtype) {} + /// + virtual ~EndTag() = default; + /// + virtual docstring writeEndTag() const; + /// + bool operator==(StartTag const & rhs) const + { return tag_ == rhs.tag_; } + /// + bool operator!=(StartTag const & rhs) const + { return !(*this == rhs); } + /// + virtual EndFontTag const * asFontTag() const { return nullptr; } + /// + docstring tag_; + /// Type of tag for new-line behaviour. Either "paragraph", "inline", "block", or "none" (default). + /// The value should match that of the corresponding xml::StartTag. + std::string tagtype_; }; @@ -231,100 +251,116 @@ struct EndTag /// be escaped before being passed to the constructor. struct CompTag { - /// - explicit CompTag(std::string const & tag) - : tag_(tag) {} - /// - explicit CompTag(std::string const & tag, std::string const & attr) - : tag_(tag), attr_(attr) {} - /// - docstring writeTag() const; - /// - std::string tag_; - /// - std::string attr_; + /// + explicit CompTag(std::string const & tag) + : tag_(from_utf8(tag)), tagtype_("none") {} + /// + explicit CompTag(docstring const & tag) + : tag_(tag), tagtype_("none") {} + /// + explicit CompTag(std::string const & tag, std::string const & attr, std::string const & tagtype = "none") + : tag_(from_utf8(tag)), attr_(from_utf8(attr)), tagtype_(tagtype) {} + /// + explicit CompTag(std::string const & tag, docstring const & attr, std::string const & tagtype = "none") + : tag_(from_utf8(tag)), attr_(attr), tagtype_(tagtype) {} + /// + explicit CompTag(docstring const & tag, std::string const & attr, std::string const & tagtype = "none") + : tag_(tag), attr_(from_utf8(attr)), tagtype_(tagtype) {} + /// + explicit CompTag(docstring const & tag, docstring const & attr, std::string const & tagtype = "none") + : tag_(tag), attr_(attr), tagtype_(tagtype) {} + /// + docstring writeTag() const; + /// + docstring tag_; + /// + docstring attr_; + /// Type of tag for new-line behaviour. Either "paragraph", "inline", "block", or "none" (default). + std::string tagtype_; }; /// A special case of StartTag, used exclusively for tags that wrap paragraphs. -/// parid is only used for HTML output; XML is supposed to use attr for this. TODO: REMOVE PARID. struct ParTag : public StartTag { - /// - explicit ParTag(std::string const & tag, const std::string & attr): StartTag(tag, from_utf8(attr)) {} - /// - explicit ParTag(std::string const & tag, const std::string & attr, const std::string & parid): - StartTag(tag, from_utf8(attr + (parid.empty() ? (" id='" + parid + "'") : ""))) {} - /// - ~ParTag() {} + /// + explicit ParTag(std::string const & tag, const std::string & attr): StartTag(tag, from_utf8(attr)) {} + /// + ~ParTag() override = default; }; /// enum FontTypes { - // ranges - FT_EMPH, - FT_NOUN, - FT_UBAR, - FT_DBAR, - FT_WAVE, - FT_SOUT, - FT_XOUT, - // bold - FT_BOLD, - // shapes - FT_UPRIGHT, - FT_ITALIC, - FT_SLANTED, - FT_SMALLCAPS, - // families - FT_ROMAN, - FT_SANS, - FT_TYPE, - // sizes - FT_SIZE_TINY, - FT_SIZE_SCRIPT, - FT_SIZE_FOOTNOTE, - FT_SIZE_SMALL, - FT_SIZE_NORMAL, - FT_SIZE_LARGE, - FT_SIZE_LARGER, - FT_SIZE_LARGEST, - FT_SIZE_HUGE, - FT_SIZE_HUGER, - FT_SIZE_INCREASE, - FT_SIZE_DECREASE - - // When updating this list, also update fontToTag in both output_docbook.cpp and output_xhtml.cpp, - // fontToRole in output_docbook.cpp, and fontToAttribute in output_xhtml.cpp. + // ranges + FT_EMPH, + FT_NOUN, + FT_UBAR, + FT_DBAR, + FT_WAVE, + FT_SOUT, + FT_XOUT, + // bold + FT_BOLD, + // shapes + FT_UPRIGHT, + FT_ITALIC, + FT_SLANTED, + FT_SMALLCAPS, + // families + FT_ROMAN, + FT_SANS, + FT_TYPE, + // sizes + FT_SIZE_TINY, + FT_SIZE_SCRIPT, + FT_SIZE_FOOTNOTE, + FT_SIZE_SMALL, + FT_SIZE_NORMAL, + FT_SIZE_LARGE, + FT_SIZE_LARGER, + FT_SIZE_LARGEST, + FT_SIZE_HUGE, + FT_SIZE_HUGER, + FT_SIZE_INCREASE, + FT_SIZE_DECREASE + + // When updating this list, also update fontToTag in both output_docbook.cpp and output_xhtml.cpp, + // fontToRole in output_docbook.cpp, and fontToAttribute in output_xhtml.cpp. }; /// struct FontTag : public StartTag { - /// - FontTag(docstring const & tag, FontTypes type): StartTag(tag), font_type_(type) {} - /// - FontTag(docstring const & tag, docstring const & attr, FontTypes type): StartTag(tag, attr), font_type_(type) {} - /// - FontTag const * asFontTag() const override { return this; } - /// - bool operator==(StartTag const &) const override; - /// - FontTypes font_type_; + /// + FontTag(docstring const & tag, FontTypes type): StartTag(tag), font_type_(type) {} + /// + FontTag(std::string const & tag, FontTypes type): StartTag(from_utf8(tag)), font_type_(type) {} + /// + FontTag(docstring const & tag, docstring const & attr, FontTypes type): StartTag(tag, attr), font_type_(type) {} + /// + FontTag(std::string const & tag, std::string const & attr, FontTypes type): StartTag(from_utf8(tag), from_utf8(attr)), font_type_(type) {} + /// + FontTag const * asFontTag() const override { return this; } + /// + bool operator==(StartTag const &) const override; + /// + FontTypes font_type_; }; /// struct EndFontTag : public EndTag { - /// - EndFontTag(docstring const & tag, FontTypes type): EndTag(tag), font_type_(type) {} - /// - EndFontTag const * asFontTag() const override { return this; } - /// - FontTypes font_type_; + /// + EndFontTag(docstring const & tag, FontTypes type): EndTag(tag), font_type_(type) {} + /// + EndFontTag(std::string const & tag, FontTypes type): EndTag(from_utf8(tag)), font_type_(type) {} + /// + EndFontTag const * asFontTag() const override { return this; } + /// + FontTypes font_type_; }; @@ -348,6 +384,41 @@ void closeTag(odocstream & os, std::string const & name); /// Close tag void closeTag(odocstream & os, Paragraph const & par); +// Convenience functions to open and close tags. First, very low-level ones to ensure a consistent new-line behaviour. +// Block style: +// Content before +// +// Contents of the block. +// +// Content after +// Paragraph style: +// Content before +// Contents of the paragraph. +// Content after +// Inline style: +// Content beforeContents of the paragraph.Content after + +/// +void openTag(XMLStream & xs, const docstring & tag, const docstring & attr, const std::string & tagtype); +/// +void openTag(XMLStream & xs, const std::string & tag, const std::string & attr, const std::string & tagtype); +/// +void openTag(XMLStream & xs, const docstring & tag, const std::string & attr, const std::string & tagtype); +/// +void openTag(XMLStream & xs, const std::string & tag, const docstring & attr, const std::string & tagtype); +/// +void closeTag(XMLStream & xs, const docstring & tag, const std::string & tagtype); +/// +void closeTag(XMLStream & xs, const std::string & tag, const std::string & tagtype); +/// +void compTag(XMLStream & xs, const docstring & tag, const docstring & attr, const std::string & tagtype); +/// +void compTag(XMLStream & xs, const std::string & tag, const std::string & attr, const std::string & tagtype); +/// +void compTag(XMLStream & xs, const docstring & tag, const std::string & attr, const std::string & tagtype); +/// +void compTag(XMLStream & xs, const std::string & tag, const docstring & attr, const std::string & tagtype); + } // namespace xml } // namespace lyx