Another minor change, but this should almost get us to the point that we
[lyx.git] / src / output_plaintext.cpp
blob97e3ab11270c5fab649507d74e8ae2a679c32a88
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 "Layout.h"
18 #include "output.h"
19 #include "OutputParams.h"
20 #include "Paragraph.h"
21 #include "ParagraphList.h"
22 #include "ParagraphParameters.h"
24 #include "support/debug.h"
25 #include "support/gettext.h"
26 #include "support/lstrings.h"
28 using namespace std;
29 using namespace lyx::support;
31 namespace lyx {
34 void writePlaintextFile(Buffer const & buf, FileName const & fname,
35 OutputParams const & runparams)
37 ofdocstream ofs;
38 if (!openFileWrite(ofs, fname))
39 return;
40 writePlaintextFile(buf, ofs, runparams);
44 void writePlaintextFile(Buffer const & buf, odocstream & os,
45 OutputParams const & runparams)
47 bool ref_printed = false;
48 ParagraphList const & par = buf.paragraphs();
49 ParagraphList::const_iterator beg = par.begin();
50 ParagraphList::const_iterator end = par.end();
51 ParagraphList::const_iterator it = beg;
52 for (; it != end; ++it) {
53 writePlaintextParagraph(buf, *it, os, runparams, ref_printed);
54 os << "\n";
55 if (runparams.linelen > 0)
56 os << "\n";
61 static pair<int, docstring> addDepth(int depth, int ldepth)
63 int d = depth * 2;
64 if (ldepth > depth)
65 d += (ldepth - depth) * 2;
66 return make_pair(d, docstring(d, ' '));
69 void writePlaintextParagraph(Buffer const & buf,
70 Paragraph const & par,
71 odocstream & os,
72 OutputParams const & runparams,
73 bool & ref_printed)
75 int ltype = 0;
76 depth_type ltype_depth = 0;
77 depth_type depth = par.params().depth();
79 // First write the layout
80 string const tmp = to_utf8(par.layout().name());
81 if (compare_ascii_no_case(tmp, "itemize") == 0) {
82 ltype = 1;
83 ltype_depth = depth + 1;
84 } else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
85 ltype = 2;
86 ltype_depth = depth + 1;
87 } else if (contains(ascii_lowercase(tmp), "ection")) {
88 ltype = 3;
89 ltype_depth = depth + 1;
90 } else if (contains(ascii_lowercase(tmp), "aragraph")) {
91 ltype = 4;
92 ltype_depth = depth + 1;
93 } else if (compare_ascii_no_case(tmp, "description") == 0) {
94 ltype = 5;
95 ltype_depth = depth + 1;
96 } else if (compare_ascii_no_case(tmp, "abstract") == 0) {
97 ltype = 6;
98 ltype_depth = 0;
99 } else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
100 ltype = 7;
101 ltype_depth = 0;
102 } else {
103 ltype = 0;
104 ltype_depth = 0;
107 /* the labelwidthstring used in lists */
109 /* noindent ? */
111 /* what about the alignment */
113 // runparams.linelen == 0 is special and means we don't have paragraph breaks
115 string::size_type currlinelen = 0;
117 os << docstring(depth * 2, ' ');
118 currlinelen += depth * 2;
120 //--
121 // we should probably change to the paragraph language in the
122 // support/gettext.here (if possible) so that strings are output in
123 // the correct language! (20012712 Jug)
124 //--
125 switch (ltype) {
126 case 0: // Standard
127 case 4: // (Sub)Paragraph
128 case 5: // Description
129 break;
131 case 6: // Abstract
132 if (runparams.linelen > 0) {
133 os << buf.B_("Abstract") << "\n\n";
134 currlinelen = 0;
135 } else {
136 docstring const abst = buf.B_("Abstract: ");
137 os << abst;
138 currlinelen += abst.length();
140 break;
142 case 7: // Bibliography
143 if (!ref_printed) {
144 if (runparams.linelen > 0) {
145 os << buf.B_("References") << "\n\n";
146 currlinelen = 0;
147 } else {
148 docstring const refs = buf.B_("References: ");
149 os << refs;
150 currlinelen += refs.length();
152 ref_printed = true;
154 break;
156 default: {
157 docstring const label = par.params().labelString();
158 if (!label.empty()) {
159 os << label << ' ';
160 currlinelen += label.length() + 1;
162 break;
167 if (currlinelen == 0) {
168 pair<int, docstring> p = addDepth(depth, ltype_depth);
169 os << p.second;
170 currlinelen += p.first;
173 docstring word;
175 for (pos_type i = 0; i < par.size(); ++i) {
176 // deleted characters don't make much sense in plain text output
177 if (par.isDeleted(i))
178 continue;
180 char_type c = par.getUChar(buf.params(), i);
182 if (par.isInset(i) || c == ' ') {
183 if (runparams.linelen > 0 &&
184 currlinelen + word.length() > runparams.linelen) {
185 os << '\n';
186 pair<int, docstring> p = addDepth(depth, ltype_depth);
187 os << p.second;
188 currlinelen = p.first;
190 os << word;
191 currlinelen += word.length();
192 word.erase();
195 if (par.isInset(i)) {
196 OutputParams rp = runparams;
197 rp.depth = par.params().depth();
198 int len = par.getInset(i)->plaintext(os, rp);
199 if (len >= Inset::PLAINTEXT_NEWLINE)
200 currlinelen = len - Inset::PLAINTEXT_NEWLINE;
201 else
202 currlinelen += len;
203 continue;
206 switch (c) {
207 case ' ':
208 os << ' ';
209 currlinelen++;
210 break;
212 case '\0':
213 LYXERR(Debug::INFO, "writePlaintextFile: NUL char in structure.");
214 break;
216 default:
217 word += c;
218 break;
222 // currlinelen may be greater than runparams.linelen!
223 // => check whether word is empty and do nothing in this case
224 if (!word.empty()) {
225 if (runparams.linelen > 0 &&
226 currlinelen + word.length() > runparams.linelen) {
227 os << '\n';
228 pair<int, docstring> p = addDepth(depth, ltype_depth);
229 os << p.second;
230 currlinelen = p.first;
232 os << word;
237 } // namespace lyx