]> git.lyx.org Git - lyx.git/blob - src/output_plaintext.C
* GuiView.C (updateTab): do not update early if current tab has
[lyx.git] / src / output_plaintext.C
1 /**
2  * \file output_plaintext.C
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 "debug.h"
18 #include "gettext.h"
19 #include "output.h"
20 #include "outputparams.h"
21 #include "paragraph.h"
22 #include "ParagraphList.h"
23 #include "ParagraphParameters.h"
24
25 #include "support/lstrings.h"
26
27
28 namespace lyx {
29
30 using support::ascii_lowercase;
31 using support::compare_ascii_no_case;
32 using support::compare_no_case;
33 using support::contains;
34 using support::FileName;
35
36 using std::endl;
37 using std::ostream;
38 using std::pair;
39 using std::string;
40
41
42 void writePlaintextFile(Buffer const & buf, FileName const & fname,
43         OutputParams const & runparams)
44 {
45         odocfstream ofs;
46         if (!openFileWrite(ofs, fname))
47                 return;
48         writePlaintextFile(buf, ofs, runparams);
49 }
50
51
52 void writePlaintextFile(Buffer const & buf, odocstream & os,
53         OutputParams const & runparams)
54 {
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";
65         }
66 }
67
68
69 namespace {
70
71 pair<int, docstring> const addDepth(int depth, int ldepth)
72 {
73         int d = depth * 2;
74         if (ldepth > depth)
75                 d += (ldepth - depth) * 2;
76         return make_pair(d, docstring(d, ' '));
77 }
78
79 }
80
81
82 void writePlaintextParagraph(Buffer const & buf,
83                     Paragraph const & par,
84                     odocstream & os,
85                     OutputParams const & runparams,
86                     bool & ref_printed)
87 {
88         int ltype = 0;
89         depth_type ltype_depth = 0;
90         depth_type depth = par.params().depth();
91
92         // First write the layout
93         string const & tmp = par.layout()->name();
94         if (compare_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;
118         }
119
120         /* the labelwidthstring used in lists */
121
122         /* noindent ? */
123
124         /* what about the alignment */
125
126         // runparams.linelen == 0 is special and means we don't have paragraph breaks
127
128         string::size_type currlinelen = 0;
129
130         os << docstring(depth * 2, ' ');
131         currlinelen += depth * 2;
132
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;
143
144         case 6: // Abstract
145                 if (runparams.linelen > 0) {
146                         os << _("Abstract") << "\n\n";
147                         currlinelen = 0;
148                 } else {
149                         docstring const abst = _("Abstract: ");
150                         os << abst;
151                         currlinelen += abst.length();
152                 }
153                 break;
154
155         case 7: // Bibliography
156                 if (!ref_printed) {
157                         if (runparams.linelen > 0) {
158                                 os << _("References") << "\n\n";
159                                 currlinelen = 0;
160                         } else {
161                                 docstring const refs = _("References: ");
162                                 os << refs;
163                                 currlinelen += refs.length();
164                         }
165                         ref_printed = true;
166                 }
167                 break;
168
169         default: {
170                 docstring const label = par.params().labelString();
171                 if (!label.empty()) {
172                         os << label << ' ';
173                         currlinelen += label.length() + 1;
174                 }
175                 break;
176         }
177
178         }
179
180         if (currlinelen == 0) {
181                 pair<int, docstring> p = addDepth(depth, ltype_depth);
182                 os << p.second;
183                 currlinelen += p.first;
184         }
185
186         docstring word;
187
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;
192
193                 char_type c = par.getUChar(buf.params(), i);
194
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;
202                         }
203                         os << word;
204                         currlinelen += word.length();
205                         word.erase();
206                 }
207
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 >= InsetBase::PLAINTEXT_NEWLINE)
214                                 currlinelen = len - InsetBase::PLAINTEXT_NEWLINE;
215                         else
216                                 currlinelen += len;
217                         break;
218                 }
219
220                 case ' ':
221                         os << ' ';
222                         currlinelen++;
223                         break;
224
225                 case '\0':
226                         lyxerr[Debug::INFO] <<
227                                 "writePlaintextFile: NULL char in structure." << endl;
228                         break;
229
230                 default:
231                         word += c;
232                         break;
233                 }
234         }
235
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;
245                 }
246                 os << word;
247         }
248 }
249
250
251 } // namespace lyx