commit 79f11f4e7daadcbf6977e50820d6bd01e6e690b3
Author: Georg Baum <[email protected]>
Date: Thu Oct 15 20:52:28 2015 +0200
Fix std::string docstream output error
This was made visible by aab1b145a57c, since xhtml export for
lib/doc/Additional.lyx caused an exception. However, the cause for this was
already present earlier: All attempts to output a std::string to an
odocstream resulted in trying to change the encoding of the stream instead,
since there is no operator<<(odocstream &, std::string) defined, and an
implicit conversion to SetEnc happened instead.
This is fixed by making the SetEnc constructor explicit and adjusting all
code parts that did not compile anymore after that. The parts of the code
that did use the wrong output operator were the std::string version of
htmlize() from output_xhtml.cpp and all changed parts in the other .cpp
files.
I also removed the std::string versions of html::htmlize() and
html::cleanAttr(), since it was difficult to see which encodings were used
with these. Now we are always explcit when using html::cleanAttr() and
html::htmlize().
diff --git a/src/Length.cpp b/src/Length.cpp
index 35f6b0c..44c3c81 100644
--- a/src/Length.cpp
+++ b/src/Length.cpp
@@ -75,7 +75,8 @@ docstring const Length::asDocstring() const
{
odocstringstream os;
if (unit_ != UNIT_NONE)
- os << formatFPNumber(val_) << unit_name[unit_]; // setw?
+ os << from_ascii(formatFPNumber(val_))
+ << from_ascii(unit_name[unit_]); // setw?
return os.str();
}
diff --git a/src/insets/Inset.cpp b/src/insets/Inset.cpp
index 3d9b5e6..0fce648 100644
--- a/src/insets/Inset.cpp
+++ b/src/insets/Inset.cpp
@@ -194,7 +194,7 @@ Buffer & Inset::buffer()
string const iname = insetName(lyxCode());
LYXERR0("Inset: " << this << " LyX Code: " << lyxCode()
<< " name: " << iname);
- s << "LyX Code: " << lyxCode() << " name: " << iname;
+ s << "LyX Code: " << lyxCode() << " name: " <<
from_ascii(iname);
LATTEST(false);
throw ExceptionMessage(BufferException,
from_ascii("Inset::buffer_ member not initialized!"),
s.str());
diff --git a/src/insets/InsetLabel.cpp b/src/insets/InsetLabel.cpp
index 9171cd1..553c6d7 100644
--- a/src/insets/InsetLabel.cpp
+++ b/src/insets/InsetLabel.cpp
@@ -295,8 +295,8 @@ docstring InsetLabel::xhtml(XHTMLStream & xs, OutputParams
const &) const
// id here to get the document to validate as XHTML 1.1. This will
cause a
// problem with some browsers, though, I'm sure. (Guess which!) So we
will
// have to figure out what to do about this later.
- string const attr = "id=\"" +
html::cleanAttr(to_utf8(getParam("name"))) + "\"";
- xs << html::CompTag("a", attr);
+ docstring const attr = "id=\"" + html::cleanAttr(getParam("name")) +
'"';
+ xs << html::CompTag("a", to_utf8(attr));
return docstring();
}
diff --git a/src/insets/InsetPhantom.cpp b/src/insets/InsetPhantom.cpp
index 84971fd..c6efe9a 100644
--- a/src/insets/InsetPhantom.cpp
+++ b/src/insets/InsetPhantom.cpp
@@ -359,13 +359,13 @@ int InsetPhantom::plaintext(odocstringstream & os,
int InsetPhantom::docbook(odocstream & os, OutputParams const & runparams)
const
{
- string cmdname;
+ docstring cmdname;
switch (params_.type) {
case InsetPhantomParams::Phantom:
case InsetPhantomParams::HPhantom:
case InsetPhantomParams::VPhantom:
default:
- cmdname = "phantom";
+ cmdname = from_ascii("phantom");
break;
}
os << "<" + cmdname + ">";
diff --git a/src/insets/InsetRef.cpp b/src/insets/InsetRef.cpp
index db8ca6e..c85f166 100644
--- a/src/insets/InsetRef.cpp
+++ b/src/insets/InsetRef.cpp
@@ -244,8 +244,8 @@ docstring InsetRef::xhtml(XHTMLStream & xs, OutputParams
const & op) const
// FIXME What we'd really like to do is to be able to output some
// appropriate sort of text here. But to do that, we need to associate
// some sort of counter with the label, and we don't have that yet.
- string const attr = "href=\"#" + html::cleanAttr(to_utf8(ref)) + "\"";
- xs << html::StartTag("a", attr);
+ docstring const attr = "href=\"#" + html::cleanAttr(ref) + '"';
+ xs << html::StartTag("a", to_utf8(attr));
xs << display_string;
xs << html::EndTag("a");
return docstring();
diff --git a/src/insets/InsetScript.cpp b/src/insets/InsetScript.cpp
index 3d912d3..f8aae1e 100644
--- a/src/insets/InsetScript.cpp
+++ b/src/insets/InsetScript.cpp
@@ -362,13 +362,13 @@ int InsetScript::plaintext(odocstringstream & os,
int InsetScript::docbook(odocstream & os, OutputParams const & runparams) const
{
- string cmdname;
+ docstring cmdname;
switch (params_.type) {
case InsetScriptParams::Subscript:
- cmdname = "subscript";
+ cmdname = from_ascii("subscript");
break;
case InsetScriptParams::Superscript:
- cmdname = "superscript";
+ cmdname = from_ascii("superscript");
break;
}
os << '<' + cmdname + '>';
diff --git a/src/output_xhtml.cpp b/src/output_xhtml.cpp
index 9463573..e960e2c 100644
--- a/src/output_xhtml.cpp
+++ b/src/output_xhtml.cpp
@@ -85,53 +85,10 @@ docstring htmlize(docstring const & str,
XHTMLStream::EscapeSettings e)
}
-string escapeChar(char c, XHTMLStream::EscapeSettings e)
+docstring escapeChar(char c, XHTMLStream::EscapeSettings e)
{
- string str;
- switch (e) {
- case XHTMLStream::ESCAPE_NONE:
- str += c;
- break;
- case XHTMLStream::ESCAPE_ALL:
- if (c == '<') {
- str += "<";
- break;
- } else if (c == '>') {
- str += ">";
- break;
- }
- // fall through
- case XHTMLStream::ESCAPE_AND:
- if (c == '&')
- str += "&";
- else
- str +=c ;
- break;
- }
- return str;
-}
-
-
-// escape what needs escaping
-string htmlize(string const & str, XHTMLStream::EscapeSettings e)
-{
- ostringstream d;
- string::const_iterator it = str.begin();
- string::const_iterator en = str.end();
- for (; it != en; ++it)
- d << escapeChar(*it, e);
- return d.str();
-}
-
-
-string cleanAttr(string const & str)
-{
- string newname;
- string::const_iterator it = str.begin();
- string::const_iterator en = str.end();
- for (; it != en; ++it)
- newname += isAlnumASCII(*it) ? *it : '_';
- return newname;
+ LATTEST(static_cast<unsigned char>(c) < 0x80);
+ return escapeChar(static_cast<char_type>(c), e);
}
@@ -150,11 +107,11 @@ docstring cleanAttr(docstring const & str)
docstring StartTag::writeTag() const
{
- string output = "<" + tag_;
+ docstring output = '<' + from_utf8(tag_);
if (!attr_.empty())
- output += " " + html::htmlize(attr_, XHTMLStream::ESCAPE_NONE);
+ output += ' ' + html::htmlize(from_utf8(attr_),
XHTMLStream::ESCAPE_NONE);
output += ">";
- return from_utf8(output);
+ return output;
}
@@ -193,11 +150,11 @@ docstring ParTag::writeTag() const
docstring CompTag::writeTag() const
{
- string output = "<" + tag_;
+ docstring output = '<' + from_utf8(tag_);
if (!attr_.empty())
- output += " " + html::htmlize(attr_, XHTMLStream::ESCAPE_NONE);
+ output += ' ' + html::htmlize(from_utf8(attr_),
XHTMLStream::ESCAPE_NONE);
output += " />";
- return from_utf8(output);
+ return output;
}
diff --git a/src/output_xhtml.h b/src/output_xhtml.h
index 8ee5149..473ebe3 100644
--- a/src/output_xhtml.h
+++ b/src/output_xhtml.h
@@ -41,8 +41,8 @@ struct StartTag
///
explicit StartTag(std::string const & tag) : tag_(tag),
keepempty_(false) {}
///
- explicit StartTag(std::string const & tag, std::string const & attr,
- bool keepempty = false)
+ explicit StartTag(std::string const & tag, std::string const & attr,
+ bool keepempty = false)
: tag_(tag), attr_(attr), keepempty_(keepempty) {}
///
virtual ~StartTag() {}
@@ -210,10 +210,10 @@ public:
/// because they are "blocked" by open non-font tags on the stack.
bool closeFontTags();
/// call at start of paragraph. sets a mark so we know what tags
- /// to close at the end.
+ /// to close at the end.
void startParagraph(bool keep_empty);
/// call at end of paragraph to clear that mark. note that this
- /// will also close any tags still open.
+ /// will also close any tags still open.
void endParagraph();
///
XHTMLStream & operator<<(docstring const &);
@@ -265,11 +265,11 @@ private:
void writeError(std::string const &) const;
///
odocstream & os_;
- ///
+ ///
EscapeSettings escape_;
// What we would really like to do here is simply use a
// deque<StartTag>. But we want to store both StartTags and
- // sub-classes thereof on this stack, which means we run into the
+ // 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<StartTag *>, which leads to the question who will
// own these pointers and how they will be deleted, so we use shared
@@ -278,8 +278,8 @@ private:
typedef shared_ptr<html::StartTag> TagPtr;
typedef std::deque<TagPtr> TagDeque;
///
- template <typename T>
- shared_ptr<T> makeTagPtr(T const & tag)
+ template <typename T>
+ shared_ptr<T> makeTagPtr(T const & tag)
{ return shared_ptr<T>(new T(tag)); }
///
TagDeque pending_tags_;
@@ -305,12 +305,8 @@ docstring htmlize(docstring const & str,
XHTMLStream::EscapeSettings e);
/// cleans \param str for use as an atttribute by replacing
/// all non-alnum by "_"
docstring cleanAttr(docstring const & str);
-///
-std::string escapeChar(char c, XHTMLStream::EscapeSettings e);
-///
-std::string htmlize(std::string const & str, XHTMLStream::EscapeSettings e);
-///
-std::string cleanAttr(std::string const & str);
+/// \p c must be ASCII
+docstring escapeChar(char c, XHTMLStream::EscapeSettings e);
} // namespace html
} // namespace lyx
diff --git a/src/support/docstream.h b/src/support/docstream.h
index a544082..52916b0 100644
--- a/src/support/docstream.h
+++ b/src/support/docstream.h
@@ -85,7 +85,15 @@ typedef odocstream & (*odocstream_manip)(odocstream &);
/// Helper struct for changing stream encoding
struct SetEnc {
- SetEnc(std::string const & e) : encoding(e) {}
+ /**
+ * It is important that this constructor is explicit.
+ * Otherwise the attempt to output a std::string to an odocstream
+ * would compile, but cause a (probably failing) encoding change
+ * instead of string output (we do not define
+ * operator<<(odocstream &, std::string) since we want to avoid
+ * outputting strings with unspecified encoding)
+ */
+ explicit SetEnc(std::string const & e) : encoding(e) {}
std::string encoding;
};