]> git.lyx.org Git - lyx.git/blob - src/output_plaintext.cpp
Small fixups to r40663
[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
45         writePlaintextFile(buf, ofs, runparams);
46 }
47
48
49 void writePlaintextFile(Buffer const & buf, odocstream & os,
50         OutputParams const & runparams)
51 {
52         bool ref_printed = false;
53         ParagraphList const & par = buf.paragraphs();
54         ParagraphList::const_iterator beg = par.begin();
55         ParagraphList::const_iterator end = par.end();
56         ParagraphList::const_iterator it = beg;
57         for (; it != end; ++it) {
58                 writePlaintextParagraph(buf, *it, os, runparams, ref_printed);
59                 os << "\n";
60                 if (runparams.linelen > 0)
61                         os << "\n";
62         }
63 }
64
65
66 static pair<int, docstring> addDepth(int depth, int ldepth)
67 {
68         int d = depth * 2;
69         if (ldepth > depth)
70                 d += (ldepth - depth) * 2;
71         return make_pair(d, docstring(d, ' '));
72 }
73
74 void writePlaintextParagraph(Buffer const & buf,
75                     Paragraph const & par,
76                     odocstream & os,
77                     OutputParams const & runparams,
78                     bool & ref_printed)
79 {
80         int ltype = 0;
81         depth_type ltype_depth = 0;
82         depth_type depth = par.params().depth();
83
84         // First write the layout
85         string const tmp = to_utf8(par.layout().name());
86         if (compare_ascii_no_case(tmp, "itemize") == 0) {
87                 ltype = 1;
88                 ltype_depth = depth + 1;
89         } else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
90                 ltype = 2;
91                 ltype_depth = depth + 1;
92         } else if (contains(ascii_lowercase(tmp), "ection")) {
93                 ltype = 3;
94                 ltype_depth = depth + 1;
95         } else if (contains(ascii_lowercase(tmp), "aragraph")) {
96                 ltype = 4;
97                 ltype_depth = depth + 1;
98         } else if (compare_ascii_no_case(tmp, "description") == 0) {
99                 ltype = 5;
100                 ltype_depth = depth + 1;
101         } else if (compare_ascii_no_case(tmp, "abstract") == 0) {
102                 ltype = 6;
103                 ltype_depth = 0;
104         } else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
105                 ltype = 7;
106                 ltype_depth = 0;
107         } else {
108                 ltype = 0;
109                 ltype_depth = 0;
110         }
111
112         /* the labelwidthstring used in lists */
113
114         /* noindent ? */
115
116         /* what about the alignment */
117
118         // runparams.linelen == 0 is special and means we don't have paragraph breaks
119
120         string::size_type currlinelen = 0;
121
122         os << docstring(depth * 2, ' ');
123         currlinelen += depth * 2;
124
125         //--
126         // we should probably change to the paragraph language in the
127         // support/gettext.here (if possible) so that strings are output in
128         // the correct language! (20012712 Jug)
129         //--
130         switch (ltype) {
131         case 0: // Standard
132         case 4: // (Sub)Paragraph
133         case 5: // Description
134                 break;
135
136         case 6: // Abstract
137                 if (runparams.linelen > 0) {
138                         os << buf.B_("Abstract") << "\n\n";
139                         currlinelen = 0;
140                 } else {
141                         docstring const abst = buf.B_("Abstract: ");
142                         os << abst;
143                         currlinelen += abst.length();
144                 }
145                 break;
146
147         case 7: // Bibliography
148                 if (!ref_printed) {
149                         if (runparams.linelen > 0) {
150                                 os << buf.B_("References") << "\n\n";
151                                 currlinelen = 0;
152                         } else {
153                                 docstring const refs = buf.B_("References: ");
154                                 os << refs;
155                                 currlinelen += refs.length();
156                         }
157                         ref_printed = true;
158                 }
159                 break;
160
161         default: {
162                 docstring const label = par.params().labelString();
163                 if (!label.empty()) {
164                         os << label << ' ';
165                         currlinelen += label.length() + 1;
166                 }
167                 break;
168         }
169
170         }
171
172         if (currlinelen == 0) {
173                 pair<int, docstring> p = addDepth(depth, ltype_depth);
174                 os << p.second;
175                 currlinelen += p.first;
176         }
177
178         docstring word;
179
180         for (pos_type i = 0; i < par.size(); ++i) {
181                 // deleted characters don't make much sense in plain text output
182                 if (par.isDeleted(i))
183                         continue;
184
185                 char_type c = par.getUChar(buf.params(), i);
186
187                 if (par.isInset(i) || c == ' ') {
188                         if (runparams.linelen > 0 &&
189                             currlinelen + word.length() > runparams.linelen) {
190                                 os << '\n';
191                                 pair<int, docstring> p = addDepth(depth, ltype_depth);
192                                 os << p.second;
193                                 currlinelen = p.first;
194                         }
195                         os << word;
196                         currlinelen += word.length();
197                         word.erase();
198                 }
199
200                 if (par.isInset(i)) {
201                         OutputParams rp = runparams;
202                         rp.depth = par.params().depth();
203                         int len = par.getInset(i)->plaintext(os, rp);
204                         if (len >= Inset::PLAINTEXT_NEWLINE)
205                                 currlinelen = len - Inset::PLAINTEXT_NEWLINE;
206                         else
207                                 currlinelen += len;
208                         continue;
209                 }
210
211                 switch (c) {
212                 case ' ':
213                         os << ' ';
214                         currlinelen++;
215                         break;
216
217                 case '\0':
218                         LYXERR(Debug::INFO, "writePlaintextFile: NUL char in structure.");
219                         break;
220
221                 default:
222                         word += c;
223                         break;
224                 }
225         }
226
227         // currlinelen may be greater than runparams.linelen!
228         // => check whether word is empty and do nothing in this case
229         if (!word.empty()) {
230                 if (runparams.linelen > 0 &&
231                     currlinelen + word.length() > runparams.linelen) {
232                         os << '\n';
233                         pair<int, docstring> p = addDepth(depth, ltype_depth);
234                         os << p.second;
235                         currlinelen = p.first;
236                 }
237                 os << word;
238         }
239 }
240
241
242 } // namespace lyx