3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Enrico Forestieri
8 * Full author contact details are available in file CREDITS.
13 #include "texstream.h"
17 #include "support/lstrings.h"
18 #include "support/unicode.h"
29 using lyx::support::contains;
30 using lyx::support::split;
36 otexrowstream::otexrowstream(odocstream & os)
37 : os_(os), texrow_(make_unique<TexRow>())
41 otexrowstream::~otexrowstream() = default;
44 unique_ptr<TexRow> otexrowstream::releaseTexRow()
46 auto p = make_unique<TexRow>();
52 void otexrowstream::put(char_type const & c)
60 void otexstream::put(char_type const & c)
62 bool isprotected = false;
64 if (!canbreakline_ && c == ' ') {
68 protectspace_ = false;
70 if (terminate_command_) {
71 if ((c == ' ' || c == '\0' || c == '\n') && !isprotected)
72 // A space or line break follows. Terminate with brackets.
74 else if (c != '\\' && c != '{' && c != '}')
75 // Non-terminating character follows. Terminate with space.
77 terminate_command_ = false;
79 otexrowstream::put(c);
84 size_t otexstringstream::length()
86 auto pos = ods_.tellp();
87 return (pos >= 0) ? size_t(pos) : 0;
91 TexString otexstringstream::release()
93 TexString ts(ods_.str(), move(texrow()));
97 ods_.str(docstring());
103 SafeBreakLine safebreakln;
104 TerminateCommand termcmd;
107 otexstream & operator<<(otexstream & ots, BreakLine)
109 if (ots.canBreakLine()) {
110 if (ots.terminateCommand())
112 ots.otexrowstream::put('\n');
115 ots.protectSpace(false);
116 ots.terminateCommand(false);
121 otexstream & operator<<(otexstream & ots, SafeBreakLine)
123 otexrowstream & otrs = ots;
124 if (ots.canBreakLine()) {
125 if (ots.terminateCommand())
130 ots.protectSpace(false);
131 ots.terminateCommand(false);
136 otexstream & operator<<(otexstream & ots, TerminateCommand)
138 ots.terminateCommand(true);
143 otexrowstream & operator<<(otexrowstream & ots, odocstream_manip pf)
146 if (pf == static_cast<odocstream_manip>(endl)) {
147 ots.texrow().newline();
153 otexstream & operator<<(otexstream & ots, odocstream_manip pf)
155 otexrowstream & otrs = ots;
157 if (pf == static_cast<odocstream_manip>(endl)) {
164 otexrowstream & operator<<(otexrowstream & ots, TexString ts)
167 ots.os() << move(ts.str);
168 ots.texrow().append(move(ts.texrow));
173 otexstream & operator<<(otexstream & ots, TexString ts)
175 size_t const len = ts.str.length();
176 // Check whether there is something to output
180 otexrowstream & otrs = ots;
181 bool isprotected = false;
182 char_type const c = ts.str[0];
183 if (ots.protectSpace()) {
184 if (!ots.canBreakLine() && c == ' ') {
188 ots.protectSpace(false);
190 if (ots.terminateCommand()) {
191 if ((c == ' ' || c == '\0' || c == '\n') && !isprotected)
192 // A space or line break follows. Terminate with brackets.
194 else if (c != '\\' && c != '{' && c != '}')
195 // Non-terminating character follows. Terminate with space.
197 ots.terminateCommand(false);
201 ots.canBreakLine(ts.str[len - 2] != '\n');
202 ots.lastChar(ts.str[len - 1]);
209 otexrowstream & operator<<(otexrowstream & ots, docstring const & s)
212 ots.texrow().newlines(count(s.begin(), s.end(), '\n'));
217 otexstream & operator<<(otexstream & ots, docstring const & s)
219 size_t const len = s.length();
221 // Check whether there's something to output
224 otexrowstream & otrs = ots;
225 bool isprotected = false;
226 char_type const c = s[0];
227 if (ots.protectSpace()) {
228 if (!ots.canBreakLine() && c == ' ') {
232 ots.protectSpace(false);
234 if (ots.terminateCommand()) {
235 if ((c == ' ' || c == '\0' || c == '\n') && !isprotected)
236 // A space or line break follows. Terminate with brackets.
238 else if (c != '\\' && c != '{' && c != '}')
239 // Non-terminating character follows. Terminate with space.
241 ots.terminateCommand(false);
244 if (contains(s, 0xF0000)) {
245 // Some encoding changes for the underlying stream are embedded
246 // in the docstring. The encoding names to be used are enclosed
247 // between the code points 0xF0000 and 0xF0001, the first two
248 // characters of plane 15, which is a Private Use Area whose
249 // codepoints don't have any associated glyph.
251 docstring s2 = split(s, s1, 0xF0000);
258 docstring const s3 = split(s2, enc, 0xF0001);
259 if (!contains(s2, 0xF0001))
260 s2 = split(enc, s1, 0xF0000);
262 otrs << setEncoding(to_ascii(enc));
263 s2 = split(s3, s1, 0xF0000);
270 ots.canBreakLine(s[len - 2] != '\n');
271 ots.lastChar(s[len - 1]);
276 otexrowstream & operator<<(otexrowstream & ots, string const & s)
283 otexstream & operator<<(otexstream & ots, string const & s)
290 otexrowstream & operator<<(otexrowstream & ots, char const * s)
297 otexstream & operator<<(otexstream & ots, char const * s)
304 otexrowstream & operator<<(otexrowstream & ots, char c)
311 otexstream & operator<<(otexstream & ots, char c)
318 template <typename Type>
319 otexrowstream & operator<<(otexrowstream & ots, Type value)
325 template otexrowstream & operator<< <SetEnc>(otexrowstream & os, SetEnc);
326 template otexrowstream & operator<< <double>(otexrowstream &, double);
327 template otexrowstream & operator<< <int>(otexrowstream &, int);
328 template otexrowstream & operator<< <unsigned int>(otexrowstream &,
330 template otexrowstream & operator<< <unsigned long>(otexrowstream &,
333 #ifdef HAVE_LONG_LONG_INT
334 template otexrowstream & operator<< <unsigned long long>(otexrowstream &,
339 template <typename Type>
340 otexstream & operator<<(otexstream & ots, Type value)
344 ots.protectSpace(false);
345 ots.terminateCommand(false);
349 template otexstream & operator<< <SetEnc>(otexstream & os, SetEnc);
350 template otexstream & operator<< <double>(otexstream &, double);
351 template otexstream & operator<< <int>(otexstream &, int);
352 template otexstream & operator<< <unsigned int>(otexstream &, unsigned int);
353 template otexstream & operator<< <unsigned long>(otexstream &, unsigned long);
354 #ifdef HAVE_LONG_LONG_INT
355 template otexstream & operator<< <unsigned long long>(otexstream &, unsigned long long);