X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftexstream.cpp;h=1523ca9470ebf2447af87ec8f8dc7e446c58403e;hb=3209e6604ef132c8488ad14719b29406899d8b00;hp=e1c0fe77e0b6e3d332989fe472ca7a74d3dfaaa4;hpb=8f2828197cb97d6909843b15455036490b074aa3;p=lyx.git diff --git a/src/texstream.cpp b/src/texstream.cpp index e1c0fe77e0..1523ca9470 100644 --- a/src/texstream.cpp +++ b/src/texstream.cpp @@ -11,6 +11,9 @@ #include #include "texstream.h" + +#include "TexRow.h" + #include "support/lstrings.h" #include "support/unicode.h" @@ -29,59 +32,188 @@ using lyx::support::split; namespace lyx { + +otexrowstream::otexrowstream(odocstream & os) + : os_(os), texrow_(make_unique()) +{} + + +otexrowstream::~otexrowstream() = default; + + +unique_ptr otexrowstream::releaseTexRow() +{ + auto p = make_unique(); + swap(texrow_, p); + return p; +} + + +void otexrowstream::put(char_type const & c) +{ + os_.put(c); + if (c == '\n') + texrow_->newline(); +} + + void otexstream::put(char_type const & c) { + bool isprotected = false; if (protectspace_) { - if (!canbreakline_ && c == ' ') - os_ << "{}"; + if (!canbreakline_ && c == ' ') { + os() << "{}"; + isprotected = true; + } protectspace_ = false; } - os_.put(c); + if (terminate_command_) { + if ((c == ' ' || c == '\0' || c == '\n') && !isprotected) + // A space or line break follows. Terminate with brackets. + os() << "{}"; + else if (c != '\\' && c != '{' && c != '}') + // Non-terminating character follows. Terminate with space. + os() << " "; + terminate_command_ = false; + } + otexrowstream::put(c); lastChar(c); - if (c == '\n') - texrow_.newline(); +} + + +size_t otexstringstream::length() +{ + auto pos = ods_.tellp(); + return (pos >= 0) ? size_t(pos) : 0; +} + + +TexString otexstringstream::release() +{ + TexString ts(ods_.str(), move(texrow())); + // reset this + texrow() = TexRow(); + ods_.clear(); + ods_.str(docstring()); + return ts; } BreakLine breakln; SafeBreakLine safebreakln; +TerminateCommand termcmd; otexstream & operator<<(otexstream & ots, BreakLine) { if (ots.canBreakLine()) { - ots.os().put('\n'); + if (ots.terminateCommand()) + ots << "{}"; + ots.otexrowstream::put('\n'); ots.lastChar('\n'); - ots.texrow().newline(); } ots.protectSpace(false); + ots.terminateCommand(false); return ots; } otexstream & operator<<(otexstream & ots, SafeBreakLine) { + otexrowstream & otrs = ots; if (ots.canBreakLine()) { - ots.os() << "%\n"; + if (ots.terminateCommand()) + otrs << "{}"; + otrs << "%\n"; ots.lastChar('\n'); - ots.texrow().newline(); } ots.protectSpace(false); + ots.terminateCommand(false); return ots; } -otexstream & operator<<(otexstream & ots, odocstream_manip pf) +otexstream & operator<<(otexstream & ots, TerminateCommand) +{ + ots.terminateCommand(true); + return ots; +} + + +otexrowstream & operator<<(otexrowstream & ots, odocstream_manip pf) { ots.os() << pf; if (pf == static_cast(endl)) { - ots.lastChar('\n'); ots.texrow().newline(); } return ots; } +otexstream & operator<<(otexstream & ots, odocstream_manip pf) +{ + otexrowstream & otrs = ots; + otrs << pf; + if (pf == static_cast(endl)) { + ots.lastChar('\n'); + } + return ots; +} + + +otexrowstream & operator<<(otexrowstream & ots, TexString ts) +{ + ts.validate(); + ots.os() << move(ts.str); + ots.texrow().append(move(ts.texrow)); + return ots; +} + + +otexstream & operator<<(otexstream & ots, TexString ts) +{ + size_t const len = ts.str.length(); + // Check whether there is something to output + if (len == 0) + return ots; + + otexrowstream & otrs = ots; + bool isprotected = false; + char_type const c = ts.str[0]; + if (ots.protectSpace()) { + if (!ots.canBreakLine() && c == ' ') { + otrs << "{}"; + isprotected = true; + } + ots.protectSpace(false); + } + if (ots.terminateCommand()) { + if ((c == ' ' || c == '\0' || c == '\n') && !isprotected) + // A space or line break follows. Terminate with brackets. + otrs << "{}"; + else if (c != '\\' && c != '{' && c != '}') + // Non-terminating character follows. Terminate with space. + otrs << " "; + ots.terminateCommand(false); + } + + if (len > 1) + ots.canBreakLine(ts.str[len - 2] != '\n'); + ots.lastChar(ts.str[len - 1]); + + otrs << move(ts); + return ots; +} + + +otexrowstream & operator<<(otexrowstream & ots, docstring const & s) +{ + ots.os() << s; + ots.texrow().newlines(count(s.begin(), s.end(), '\n')); + return ots; +} + + otexstream & operator<<(otexstream & ots, docstring const & s) { size_t const len = s.length(); @@ -89,12 +221,25 @@ otexstream & operator<<(otexstream & ots, docstring const & s) // Check whether there's something to output if (len == 0) return ots; - + otexrowstream & otrs = ots; + bool isprotected = false; + char_type const c = s[0]; if (ots.protectSpace()) { - if (!ots.canBreakLine() && s[0] == ' ') - ots.os() << "{}"; + if (!ots.canBreakLine() && c == ' ') { + otrs << "{}"; + isprotected = true; + } ots.protectSpace(false); } + if (ots.terminateCommand()) { + if ((c == ' ' || c == '\0' || c == '\n') && !isprotected) + // A space or line break follows. Terminate with brackets. + otrs << "{}"; + else if (c != '\\' && c != '{' && c != '}') + // Non-terminating character follows. Terminate with space. + otrs << " "; + ots.terminateCommand(false); + } if (contains(s, 0xF0000)) { // Some encoding changes for the underlying stream are embedded @@ -106,7 +251,7 @@ otexstream & operator<<(otexstream & ots, docstring const & s) docstring s2 = split(s, s1, 0xF0000); while (true) { if (!s1.empty()) - ots.os() << s1; + otrs << s1; if (s2.empty()) break; docstring enc; @@ -114,17 +259,23 @@ otexstream & operator<<(otexstream & ots, docstring const & s) if (!contains(s2, 0xF0001)) s2 = split(enc, s1, 0xF0000); else { - ots.os() << setEncoding(to_ascii(enc)); + otrs << setEncoding(to_ascii(enc)); s2 = split(s3, s1, 0xF0000); } } } else - ots.os() << s; + otrs << s; if (len > 1) ots.canBreakLine(s[len - 2] != '\n'); ots.lastChar(s[len - 1]); - ots.texrow().newlines(count(s.begin(), s.end(), '\n')); + return ots; +} + + +otexrowstream & operator<<(otexrowstream & ots, string const & s) +{ + ots << from_utf8(s); return ots; } @@ -136,6 +287,13 @@ otexstream & operator<<(otexstream & ots, string const & s) } +otexrowstream & operator<<(otexrowstream & ots, char const * s) +{ + ots << from_utf8(s); + return ots; +} + + otexstream & operator<<(otexstream & ots, char const * s) { ots << from_utf8(s); @@ -143,27 +301,48 @@ otexstream & operator<<(otexstream & ots, char const * s) } +otexrowstream & operator<<(otexrowstream & ots, char c) +{ + ots.put(c); + return ots; +} + + otexstream & operator<<(otexstream & ots, char c) { - if (ots.protectSpace()) { - if (!ots.canBreakLine() && c == ' ') - ots.os() << "{}"; - ots.protectSpace(false); - } - ots.os() << c; - ots.lastChar(c); - if (c == '\n') - ots.texrow().newline(); + ots.put(c); return ots; } +template +otexrowstream & operator<<(otexrowstream & ots, Type value) +{ + ots.os() << value; + return ots; +} + +template otexrowstream & operator<< (otexrowstream & os, SetEnc); +template otexrowstream & operator<< (otexrowstream &, double); +template otexrowstream & operator<< (otexrowstream &, int); +template otexrowstream & operator<< (otexrowstream &, + unsigned int); +template otexrowstream & operator<< (otexrowstream &, + unsigned long); + +#ifdef HAVE_LONG_LONG_INT +template otexrowstream & operator<< (otexrowstream &, + unsigned long long); +#endif + + template otexstream & operator<<(otexstream & ots, Type value) { ots.os() << value; ots.lastChar(0); ots.protectSpace(false); + ots.terminateCommand(false); return ots; } @@ -172,5 +351,8 @@ template otexstream & operator<< (otexstream &, double); template otexstream & operator<< (otexstream &, int); template otexstream & operator<< (otexstream &, unsigned int); template otexstream & operator<< (otexstream &, unsigned long); +#ifdef HAVE_LONG_LONG_INT +template otexstream & operator<< (otexstream &, unsigned long long); +#endif -} +} // namespace lyx