]> git.lyx.org Git - lyx.git/blob - src/output_plaintext.cpp
#9130 Text in main work area isn't rendered with high resolution
[lyx.git] / src / output_plaintext.cpp
1 /**
2  * \file output_plaintext.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "output_plaintext.h"
14
15 #include "Buffer.h"
16 #include "BufferParams.h"
17 #include "Layout.h"
18 #include "output.h"
19 #include "OutputParams.h"
20 #include "Paragraph.h"
21 #include "ParagraphList.h"
22 #include "ParagraphParameters.h"
23
24 #include "support/debug.h"
25 #include "support/gettext.h"
26 #include "support/lstrings.h"
27
28 using namespace std;
29 using namespace lyx::support;
30
31 namespace lyx {
32
33
34 void writePlaintextFile(Buffer const & buf, FileName const & fname,
35         OutputParams const & runparams)
36 {
37         ofdocstream ofs;
38         if (!openFileWrite(ofs, fname))
39                 return;
40
41         // make sure we are ready to export
42         buf.updateBuffer();
43         buf.updateMacroInstances(OutputUpdate);
44         buf.makeCitationLabels();
45
46         writePlaintextFile(buf, ofs, runparams);
47 }
48
49
50 void writePlaintextFile(Buffer const & buf, odocstream & os,
51         OutputParams const & runparams)
52 {
53         bool ref_printed = false;
54         ParagraphList const & par = buf.paragraphs();
55         ParagraphList::const_iterator beg = par.begin();
56         ParagraphList::const_iterator end = par.end();
57         ParagraphList::const_iterator it = beg;
58         for (; it != end; ++it) {
59                 writePlaintextParagraph(buf, *it, os, runparams, ref_printed);
60                 os << "\n";
61                 if (runparams.linelen > 0)
62                         os << "\n";
63         }
64 }
65
66
67 static pair<int, docstring> addDepth(int depth, int ldepth)
68 {
69         int d = depth * 2;
70         if (ldepth > depth)
71                 d += (ldepth - depth) * 2;
72         return make_pair(d, docstring(d, ' '));
73 }
74
75
76 void writePlaintextParagraph(Buffer const & buf,
77                     Paragraph const & par,
78                     odocstream & ods,
79                     OutputParams const & runparams,
80                     bool & ref_printed, size_t max_length)
81 {
82         int ltype = 0;
83         depth_type ltype_depth = 0;
84         depth_type depth = par.params().depth();
85
86         // First write the layout
87         string const tmp = to_utf8(par.layout().name());
88         if (compare_ascii_no_case(tmp, "itemize") == 0) {
89                 ltype = 1;
90                 ltype_depth = depth + 1;
91         } else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
92                 ltype = 2;
93                 ltype_depth = depth + 1;
94         } else if (contains(ascii_lowercase(tmp), "ection")) {
95                 ltype = 3;
96                 ltype_depth = depth + 1;
97         } else if (contains(ascii_lowercase(tmp), "aragraph")) {
98                 ltype = 4;
99                 ltype_depth = depth + 1;
100         } else if (compare_ascii_no_case(tmp, "description") == 0) {
101                 ltype = 5;
102                 ltype_depth = depth + 1;
103         } else if (compare_ascii_no_case(tmp, "abstract") == 0) {
104                 ltype = 6;
105                 ltype_depth = 0;
106         } else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
107                 ltype = 7;
108                 ltype_depth = 0;
109         } else {
110                 ltype = 0;
111                 ltype_depth = 0;
112         }
113
114         /* the labelwidthstring used in lists */
115
116         /* noindent ? */
117
118         /* what about the alignment */
119
120         // runparams.linelen == 0 is special and means we don't have paragraph breaks
121
122         string::size_type currlinelen = 0;
123
124         odocstringstream os;
125         os << docstring(depth * 2, ' ');
126         currlinelen += depth * 2;
127
128         //--
129         // we should probably change to the paragraph language in the
130         // support/gettext.here (if possible) so that strings are output in
131         // the correct language! (20012712 Jug)
132         //--
133         switch (ltype) {
134         case 0: // Standard
135         case 4: // (Sub)Paragraph
136         case 5: // Description
137                 break;
138
139         case 6: // Abstract
140                 if (runparams.linelen > 0) {
141                         os << buf.B_("Abstract") << "\n\n";
142                         currlinelen = 0;
143                 } else {
144                         docstring const abst = buf.B_("Abstract: ");
145                         os << abst;
146                         currlinelen += abst.length();
147                 }
148                 break;
149
150         case 7: // Bibliography
151                 if (!ref_printed) {
152                         if (runparams.linelen > 0) {
153                                 os << buf.B_("References") << "\n\n";
154                                 currlinelen = 0;
155                         } else {
156                                 docstring const refs = buf.B_("References: ");
157                                 os << refs;
158                                 currlinelen += refs.length();
159                         }
160                         ref_printed = true;
161                 }
162                 break;
163
164         default: {
165                 docstring const label = par.params().labelString();
166                 if (!label.empty()) {
167                         os << label << ' ';
168                         currlinelen += label.length() + 1;
169                 }
170                 break;
171         }
172
173         }
174
175         if (currlinelen == 0) {
176                 pair<int, docstring> p = addDepth(depth, ltype_depth);
177                 os << p.second;
178                 currlinelen += p.first;
179         }
180
181         docstring word;
182
183         for (pos_type i = 0; i < par.size(); ++i) {
184                 // deleted characters don't make much sense in plain text output
185                 if (par.isDeleted(i))
186                         continue;
187
188                 if (os.str().size() > max_length)
189                         break;
190
191                 char_type c = par.getUChar(buf.params(), i);
192
193                 if (par.isInset(i) || c == ' ') {
194                         if (runparams.linelen > 0 &&
195                             currlinelen + word.length() > runparams.linelen) {
196                                 os << '\n';
197                                 pair<int, docstring> p = addDepth(depth, ltype_depth);
198                                 os << p.second;
199                                 currlinelen = p.first;
200                         }
201                         os << word;
202                         currlinelen += word.length();
203                         word.erase();
204                 }
205
206                 if (par.isInset(i)) {
207                         OutputParams rp = runparams;
208                         rp.depth = par.params().depth();
209                         int len = par.getInset(i)->plaintext(os, rp, max_length);
210                         if (len >= Inset::PLAINTEXT_NEWLINE)
211                                 currlinelen = len - Inset::PLAINTEXT_NEWLINE;
212                         else
213                                 currlinelen += len;
214                         continue;
215                 }
216
217                 switch (c) {
218                 case ' ':
219                         os << ' ';
220                         ++currlinelen;
221                         break;
222
223                 case '\0':
224                         LYXERR(Debug::INFO, "writePlaintextFile: NUL char in structure.");
225                         break;
226
227                 default:
228                         word += c;
229                         break;
230                 }
231         }
232
233         // currlinelen may be greater than runparams.linelen!
234         // => check whether word is empty and do nothing in this case
235         if (!word.empty()) {
236                 if (runparams.linelen > 0 &&
237                     currlinelen + word.length() > runparams.linelen) {
238                         os << '\n';
239                         pair<int, docstring> p = addDepth(depth, ltype_depth);
240                         os << p.second;
241                         currlinelen = p.first;
242                 }
243                 os << word;
244         }
245         ods << os.str();
246 }
247
248
249 } // namespace lyx