scramble email addresses
[lyx.git] / src / output_plaintext.cpp
blob39c5f1a13403a7522241eb311048c2bfaf104c5a
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.
6 * \author Lars Gullik Bjønnes
8 * Full author contact details are available in file CREDITS.
9 */
11 #include <config.h>
13 #include "output_plaintext.h"
15 #include "Buffer.h"
16 #include "BufferParams.h"
17 #include "debug.h"
18 #include "gettext.h"
19 #include "Layout.h"
20 #include "output.h"
21 #include "OutputParams.h"
22 #include "Paragraph.h"
23 #include "ParagraphList.h"
24 #include "ParagraphParameters.h"
26 #include "support/lstrings.h"
29 namespace lyx {
31 using support::ascii_lowercase;
32 using support::compare_ascii_no_case;
33 using support::contains;
34 using support::FileName;
36 using std::endl;
37 using std::ostream;
38 using std::pair;
39 using std::string;
42 void writePlaintextFile(Buffer const & buf, FileName const & fname,
43 OutputParams const & runparams)
45 odocfstream ofs;
46 if (!openFileWrite(ofs, fname))
47 return;
48 writePlaintextFile(buf, ofs, runparams);
52 void writePlaintextFile(Buffer const & buf, odocstream & os,
53 OutputParams const & runparams)
55 bool ref_printed = false;
56 ParagraphList const par = buf.paragraphs();
57 ParagraphList::const_iterator beg = par.begin();
58 ParagraphList::const_iterator end = par.end();
59 ParagraphList::const_iterator it = beg;
60 for (; it != end; ++it) {
61 writePlaintextParagraph(buf, *it, os, runparams, ref_printed);
62 os << "\n";
63 if (runparams.linelen > 0)
64 os << "\n";
69 namespace {
71 pair<int, docstring> const addDepth(int depth, int ldepth)
73 int d = depth * 2;
74 if (ldepth > depth)
75 d += (ldepth - depth) * 2;
76 return make_pair(d, docstring(d, ' '));
82 void writePlaintextParagraph(Buffer const & buf,
83 Paragraph const & par,
84 odocstream & os,
85 OutputParams const & runparams,
86 bool & ref_printed)
88 int ltype = 0;
89 depth_type ltype_depth = 0;
90 depth_type depth = par.params().depth();
92 // First write the layout
93 string const tmp = to_utf8(par.layout()->name());
94 if (compare_ascii_no_case(tmp, "itemize") == 0) {
95 ltype = 1;
96 ltype_depth = depth + 1;
97 } else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
98 ltype = 2;
99 ltype_depth = depth + 1;
100 } else if (contains(ascii_lowercase(tmp), "ection")) {
101 ltype = 3;
102 ltype_depth = depth + 1;
103 } else if (contains(ascii_lowercase(tmp), "aragraph")) {
104 ltype = 4;
105 ltype_depth = depth + 1;
106 } else if (compare_ascii_no_case(tmp, "description") == 0) {
107 ltype = 5;
108 ltype_depth = depth + 1;
109 } else if (compare_ascii_no_case(tmp, "abstract") == 0) {
110 ltype = 6;
111 ltype_depth = 0;
112 } else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
113 ltype = 7;
114 ltype_depth = 0;
115 } else {
116 ltype = 0;
117 ltype_depth = 0;
120 /* the labelwidthstring used in lists */
122 /* noindent ? */
124 /* what about the alignment */
126 // runparams.linelen == 0 is special and means we don't have paragraph breaks
128 string::size_type currlinelen = 0;
130 os << docstring(depth * 2, ' ');
131 currlinelen += depth * 2;
133 //--
134 // we should probably change to the paragraph language in the
135 // gettext here (if possible) so that strings are output in
136 // the correct language! (20012712 Jug)
137 //--
138 switch (ltype) {
139 case 0: // Standard
140 case 4: // (Sub)Paragraph
141 case 5: // Description
142 break;
144 case 6: // Abstract
145 if (runparams.linelen > 0) {
146 os << buf.B_("Abstract") << "\n\n";
147 currlinelen = 0;
148 } else {
149 docstring const abst = buf.B_("Abstract: ");
150 os << abst;
151 currlinelen += abst.length();
153 break;
155 case 7: // Bibliography
156 if (!ref_printed) {
157 if (runparams.linelen > 0) {
158 os << buf.B_("References") << "\n\n";
159 currlinelen = 0;
160 } else {
161 docstring const refs = buf.B_("References: ");
162 os << refs;
163 currlinelen += refs.length();
165 ref_printed = true;
167 break;
169 default: {
170 docstring const label = par.params().labelString();
171 if (!label.empty()) {
172 os << label << ' ';
173 currlinelen += label.length() + 1;
175 break;
180 if (currlinelen == 0) {
181 pair<int, docstring> p = addDepth(depth, ltype_depth);
182 os << p.second;
183 currlinelen += p.first;
186 docstring word;
188 for (pos_type i = 0; i < par.size(); ++i) {
189 // deleted characters don't make much sense in plain text output
190 if (par.isDeleted(i))
191 continue;
193 char_type c = par.getUChar(buf.params(), i);
195 if (c == Paragraph::META_INSET || c == ' ') {
196 if (runparams.linelen > 0 &&
197 currlinelen + word.length() > runparams.linelen) {
198 os << '\n';
199 pair<int, docstring> p = addDepth(depth, ltype_depth);
200 os << p.second;
201 currlinelen = p.first;
203 os << word;
204 currlinelen += word.length();
205 word.erase();
208 switch (c) {
209 case Paragraph::META_INSET: {
210 OutputParams rp = runparams;
211 rp.depth = par.params().depth();
212 int len = par.getInset(i)->plaintext(buf, os, rp);
213 if (len >= Inset::PLAINTEXT_NEWLINE)
214 currlinelen = len - Inset::PLAINTEXT_NEWLINE;
215 else
216 currlinelen += len;
217 break;
220 case ' ':
221 os << ' ';
222 currlinelen++;
223 break;
225 case '\0':
226 LYXERR(Debug::INFO) <<
227 "writePlaintextFile: NULL char in structure." << endl;
228 break;
230 default:
231 word += c;
232 break;
236 // currlinelen may be greater than runparams.linelen!
237 // => check whether word is empty and do nothing in this case
238 if (!word.empty()) {
239 if (runparams.linelen > 0 &&
240 currlinelen + word.length() > runparams.linelen) {
241 os << '\n';
242 pair<int, docstring> p = addDepth(depth, ltype_depth);
243 os << p.second;
244 currlinelen = p.first;
246 os << word;
251 } // namespace lyx