]> git.lyx.org Git - lyx.git/blob - src/texstream.cpp
Get rid of Inset::setPosCache
[lyx.git] / src / texstream.cpp
1 /**
2  * \file texstream.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Enrico Forestieri
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "texstream.h"
14
15 #include "TexRow.h"
16
17 #include "support/lstrings.h"
18 #include "support/unicode.h"
19
20 #include <algorithm>
21 #include <cerrno>
22 #include <cstdio>
23 #include <cstring>
24 #include <iconv.h>
25 #include <locale>
26
27 using namespace std;
28
29 using lyx::support::contains;
30 using lyx::support::split;
31
32
33 namespace lyx {
34
35
36 otexrowstream::otexrowstream(odocstream & os)
37         : os_(os), texrow_(make_unique<TexRow>())
38 {}
39
40
41 otexrowstream::~otexrowstream() = default;
42
43
44 unique_ptr<TexRow> otexrowstream::releaseTexRow()
45 {
46         auto p = make_unique<TexRow>();
47         swap(texrow_, p);
48         return p;
49 }
50
51
52 void otexrowstream::put(char_type const & c)
53 {
54         os_.put(c);
55         if (c == '\n')
56                 texrow_->newline();
57 }
58
59
60 void otexstream::put(char_type const & c)
61 {
62         if (protectspace_) {
63                 if (!canbreakline_ && c == ' ')
64                         os() << "{}";
65                 protectspace_ = false;
66         }
67         otexrowstream::put(c);
68         lastChar(c);
69 }
70
71
72 size_t otexstringstream::length()
73 {
74         auto pos = ods_.tellp();
75         return (pos >= 0) ? size_t(pos) : 0;
76 }
77
78
79 TexString otexstringstream::release()
80 {
81         TexString ts(ods_.str(), move(texrow()));
82         // reset this
83         texrow() = TexRow();
84         ods_.clear();
85         ods_.str(docstring());
86         return ts;
87 }
88
89
90 BreakLine breakln;
91 SafeBreakLine safebreakln;
92
93
94 otexstream & operator<<(otexstream & ots, BreakLine)
95 {
96         if (ots.canBreakLine()) {
97                 ots.otexrowstream::put('\n');
98                 ots.lastChar('\n');
99         }
100         ots.protectSpace(false);
101         return ots;
102 }
103
104
105 otexstream & operator<<(otexstream & ots, SafeBreakLine)
106 {
107         otexrowstream & otrs = ots;
108         if (ots.canBreakLine()) {
109                 otrs << "%\n";
110                 ots.lastChar('\n');
111         }
112         ots.protectSpace(false);
113         return ots;
114 }
115
116
117 otexrowstream & operator<<(otexrowstream & ots, odocstream_manip pf)
118 {
119         ots.os() << pf;
120         if (pf == static_cast<odocstream_manip>(endl)) {
121                 ots.texrow().newline();
122         }
123         return ots;
124 }
125
126
127 otexstream & operator<<(otexstream & ots, odocstream_manip pf)
128 {
129         otexrowstream & otrs = ots;
130         otrs << pf;
131         if (pf == static_cast<odocstream_manip>(endl)) {
132                 ots.lastChar('\n');
133         }
134         return ots;
135 }
136
137
138 otexrowstream & operator<<(otexrowstream & ots, TexString ts)
139 {
140         ts.validate();
141         ots.os() << move(ts.str);
142         ots.texrow().append(move(ts.texrow));
143         return ots;
144 }
145
146
147 otexstream & operator<<(otexstream & ots, TexString ts)
148 {
149         size_t const len = ts.str.length();
150         // Check whether there is something to output
151         if (len == 0)
152                 return ots;
153
154         otexrowstream & otrs = ots;
155         if (ots.protectSpace()) {
156                 if (!ots.canBreakLine() && ts.str[0] == ' ')
157                         otrs << "{}";
158                 ots.protectSpace(false);
159         }
160
161         if (len > 1)
162                 ots.canBreakLine(ts.str[len - 2] != '\n');
163         ots.lastChar(ts.str[len - 1]);
164
165         otrs << move(ts);
166         return ots;
167 }
168
169
170 otexrowstream & operator<<(otexrowstream & ots, docstring const & s)
171 {
172         ots.os() << s;
173         ots.texrow().newlines(count(s.begin(), s.end(), '\n'));
174         return ots;
175 }
176
177
178 otexstream & operator<<(otexstream & ots, docstring const & s)
179 {
180         size_t const len = s.length();
181
182         // Check whether there's something to output
183         if (len == 0)
184                 return ots;
185         otexrowstream & otrs = ots;
186         if (ots.protectSpace()) {
187                 if (!ots.canBreakLine() && s[0] == ' ')
188                         otrs << "{}";
189                 ots.protectSpace(false);
190         }
191
192         if (contains(s, 0xF0000)) {
193                 // Some encoding changes for the underlying stream are embedded
194                 // in the docstring. The encoding names to be used are enclosed
195                 // between the code points 0xF0000 and 0xF0001, the first two
196                 // characters of plane 15, which is a Private Use Area whose
197                 // codepoints don't have any associated glyph.
198                 docstring s1;
199                 docstring s2 = split(s, s1, 0xF0000);
200                 while (true) {
201                         if (!s1.empty())
202                                 otrs << s1;
203                         if (s2.empty())
204                                 break;
205                         docstring enc;
206                         docstring const s3 = split(s2, enc, 0xF0001);
207                         if (!contains(s2, 0xF0001))
208                                 s2 = split(enc, s1, 0xF0000);
209                         else {
210                                 otrs << setEncoding(to_ascii(enc));
211                                 s2 = split(s3, s1, 0xF0000);
212                         }
213                 }
214         } else
215                 otrs << s;
216
217         if (len > 1)
218                 ots.canBreakLine(s[len - 2] != '\n');
219         ots.lastChar(s[len - 1]);
220         return ots;
221 }
222
223
224 otexrowstream & operator<<(otexrowstream & ots, string const & s)
225 {
226         ots << from_utf8(s);
227         return ots;
228 }
229
230
231 otexstream & operator<<(otexstream & ots, string const & s)
232 {
233         ots << from_utf8(s);
234         return ots;
235 }
236
237
238 otexrowstream & operator<<(otexrowstream & ots, char const * s)
239 {
240         ots << from_utf8(s);
241         return ots;
242 }
243
244
245 otexstream & operator<<(otexstream & ots, char const * s)
246 {
247         ots << from_utf8(s);
248         return ots;
249 }
250
251
252 otexrowstream & operator<<(otexrowstream & ots, char c)
253 {
254         ots.put(c);
255         return ots;
256 }
257
258
259 otexstream & operator<<(otexstream & ots, char c)
260 {
261         ots.put(c);
262         return ots;
263 }
264
265
266 template <typename Type>
267 otexrowstream & operator<<(otexrowstream & ots, Type value)
268 {
269         ots.os() << value;
270         return ots;
271 }
272
273 template otexrowstream & operator<< <SetEnc>(otexrowstream & os, SetEnc);
274 template otexrowstream & operator<< <double>(otexrowstream &, double);
275 template otexrowstream & operator<< <int>(otexrowstream &, int);
276 template otexrowstream & operator<< <unsigned int>(otexrowstream &,
277                                                                                                    unsigned int);
278 template otexrowstream & operator<< <unsigned long>(otexrowstream &,
279                                                                                                         unsigned long);
280
281 #ifdef LYX_USE_LONG_LONG
282 template otexrowstream & operator<< <unsigned long long>(otexrowstream &,
283                                                          unsigned long long);
284 #endif
285
286
287 template <typename Type>
288 otexstream & operator<<(otexstream & ots, Type value)
289 {
290         ots.os() << value;
291         ots.lastChar(0);
292         ots.protectSpace(false);
293         return ots;
294 }
295
296 template otexstream & operator<< <SetEnc>(otexstream & os, SetEnc);
297 template otexstream & operator<< <double>(otexstream &, double);
298 template otexstream & operator<< <int>(otexstream &, int);
299 template otexstream & operator<< <unsigned int>(otexstream &, unsigned int);
300 template otexstream & operator<< <unsigned long>(otexstream &, unsigned long);
301 #ifdef LYX_USE_LONG_LONG
302 template otexstream & operator<< <unsigned long long>(otexstream &, unsigned long long);
303 #endif
304
305 }