#include <config.h>
#include "texstream.h"
+
+#include "TexRow.h"
+
#include "support/lstrings.h"
#include "support/unicode.h"
namespace lyx {
-void otexrowstream::append(docstring const & str, TexRow const & texrow)
+otexrowstream::otexrowstream(odocstream & os)
+ : os_(os), texrow_(make_unique<TexRow>())
+{}
+
+
+otexrowstream::~otexrowstream() = default;
+
+
+unique_ptr<TexRow> otexrowstream::releaseTexRow()
{
- os_ << str;
- texrow_.append(texrow);
+ auto p = make_unique<TexRow>();
+ swap(texrow_, p);
+ return p;
}
{
os_.put(c);
if (c == '\n')
- texrow_.newline();
+ texrow_->newline();
}
void otexstream::put(char_type const & c)
{
+ bool isprotected = false;
if (protectspace_) {
- if (!canbreakline_ && c == ' ')
+ if (!canbreakline_ && c == ' ') {
os() << "{}";
+ isprotected = true;
+ }
protectspace_ = false;
}
+ 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);
}
+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()) {
+ if (ots.terminateCommand())
+ ots << "{}";
ots.otexrowstream::put('\n');
ots.lastChar('\n');
}
ots.protectSpace(false);
+ ots.terminateCommand(false);
return ots;
}
{
otexrowstream & otrs = ots;
if (ots.canBreakLine()) {
+ if (ots.terminateCommand())
+ otrs << "{}";
otrs << "%\n";
ots.lastChar('\n');
}
ots.protectSpace(false);
+ ots.terminateCommand(false);
+ return ots;
+}
+
+
+otexstream & operator<<(otexstream & ots, TerminateCommand)
+{
+ ots.terminateCommand(true);
return ots;
}
return ots;
}
+
otexstream & operator<<(otexstream & ots, odocstream_manip pf)
{
otexrowstream & otrs = 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;
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] == ' ')
+ 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
template otexrowstream & operator<< <unsigned long>(otexrowstream &,
unsigned long);
+#ifdef HAVE_LONG_LONG_INT
+template otexrowstream & operator<< <unsigned long long>(otexrowstream &,
+ unsigned long long);
+#endif
+
template <typename Type>
otexstream & operator<<(otexstream & ots, Type value)
ots.os() << value;
ots.lastChar(0);
ots.protectSpace(false);
+ ots.terminateCommand(false);
return ots;
}
template otexstream & operator<< <int>(otexstream &, int);
template otexstream & operator<< <unsigned int>(otexstream &, unsigned int);
template otexstream & operator<< <unsigned long>(otexstream &, unsigned long);
+#ifdef HAVE_LONG_LONG_INT
+template otexstream & operator<< <unsigned long long>(otexstream &, unsigned long long);
+#endif
-}
+} // namespace lyx