]> git.lyx.org Git - lyx.git/blob - src/output_plaintext.C
d0da1d04dc56c3310efd38fc54b6169842dce883
[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_fwd.h"
23 #include "ParagraphParameters.h"
24
25 #include "support/gzstream.h"
26 #include "support/lstrings.h"
27
28 using lyx::support::ascii_lowercase;
29 using lyx::support::compare_ascii_no_case;
30 using lyx::support::compare_no_case;
31 using lyx::support::contains;
32
33 using lyx::pos_type;
34 using std::endl;
35 using std::ostream;
36 using std::ofstream;
37 using std::pair;
38 using std::string;
39
40
41 void writeFileAscii(Buffer const & buf,
42                     string const & fname,
43                     OutputParams const & runparams)
44 {
45         ofstream ofs;
46         if (!::openFileWrite(ofs, fname))
47                 return;
48         writeFileAscii(buf, ofs, runparams);
49 }
50
51
52 void writeFileAscii(Buffer const & buf, ostream & os,
53         OutputParams const & runparams)
54 {
55         ParagraphList const par = buf.paragraphs();
56         ParagraphList::const_iterator beg = par.begin();
57         ParagraphList::const_iterator end = par.end();
58         ParagraphList::const_iterator it = beg;
59         for (; it != end; ++it) {
60                 asciiParagraph(buf, *it, os, runparams, it == beg);
61         }
62         os << "\n";
63 }
64
65
66 namespace {
67
68 pair<int, string> const addDepth(int depth, int ldepth)
69 {
70         int d = depth * 2;
71         if (ldepth > depth)
72                 d += (ldepth - depth) * 2;
73         return make_pair(d, string(d, ' '));
74 }
75
76 }
77
78
79 void asciiParagraph(Buffer const & buf,
80                     Paragraph const & par,
81                     ostream & os,
82                     OutputParams const & runparams,
83                     bool noparbreak)
84 {
85         int ltype = 0;
86         Paragraph::depth_type ltype_depth = 0;
87         static bool ref_printed = false;
88         Paragraph::depth_type depth = par.params().depth();
89
90         // First write the layout
91         string const & tmp = par.layout()->name();
92         if (compare_no_case(tmp, "itemize") == 0) {
93                 ltype = 1;
94                 ltype_depth = depth + 1;
95         } else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
96                 ltype = 2;
97                 ltype_depth = depth + 1;
98         } else if (contains(ascii_lowercase(tmp), "ection")) {
99                 ltype = 3;
100                 ltype_depth = depth + 1;
101         } else if (contains(ascii_lowercase(tmp), "aragraph")) {
102                 ltype = 4;
103                 ltype_depth = depth + 1;
104         } else if (compare_ascii_no_case(tmp, "description") == 0) {
105                 ltype = 5;
106                 ltype_depth = depth + 1;
107         } else if (compare_ascii_no_case(tmp, "abstract") == 0) {
108                 ltype = 6;
109                 ltype_depth = 0;
110         } else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
111                 ltype = 7;
112                 ltype_depth = 0;
113         } else {
114                 ltype = 0;
115                 ltype_depth = 0;
116         }
117
118         /* maybe some vertical spaces */
119
120         /* the labelwidthstring used in lists */
121
122         /* some lines? */
123
124         /* some pagebreaks? */
125
126         /* noindent ? */
127
128         /* what about the alignment */
129
130         // runparams.linelen <= 0 is special and means we don't have paragraph breaks
131
132         string::size_type currlinelen = 0;
133
134         if (!noparbreak) {
135                 if (runparams.linelen > 0)
136                         os << "\n\n";
137
138                 os << string(depth * 2, ' ');
139                 currlinelen += depth * 2;
140
141                 //--
142                 // we should probably change to the paragraph language in the
143                 // gettext here (if possible) so that strings are output in
144                 // the correct language! (20012712 Jug)
145                 //--
146                 switch (ltype) {
147                 case 0: // Standard
148                 case 4: // (Sub)Paragraph
149                 case 5: // Description
150                         break;
151
152                 case 6: // Abstract
153                         if (runparams.linelen > 0) {
154                                 os << _("Abstract") << "\n\n";
155                                 currlinelen = 0;
156                         } else {
157                                 string const abst = _("Abstract: ");
158                                 os << abst;
159                                 currlinelen += abst.length();
160                         }
161                         break;
162
163                 case 7: // Bibliography
164                         if (!ref_printed) {
165                                 if (runparams.linelen > 0) {
166                                         os << _("References") << "\n\n";
167                                         currlinelen = 0;
168                                 } else {
169                                         string const refs = _("References: ");
170                                         os << refs;
171                                         currlinelen += refs.length();
172                                 }
173                                 ref_printed = true;
174                         }
175                         break;
176
177                 default: {
178                         string const label = par.params().labelString();
179                         os << label << ' ';
180                         currlinelen += label.length() + 1;
181                         break;
182                 }
183
184                 }
185         }
186
187         if (!currlinelen) {
188                 pair<int, string> p = addDepth(depth, ltype_depth);
189                 os << p.second;
190                 currlinelen += p.first;
191         }
192
193         // this is to change the linebreak to do it by word a bit more
194         // intelligent hopefully! (only in the case where we have a
195         // max runparams.linelength!) (Jug)
196
197         string word;
198
199         for (pos_type i = 0; i < par.size(); ++i) {
200                 char c = par.getUChar(buf.params(), i);
201                 switch (c) {
202                 case Paragraph::META_INSET: {
203                         InsetBase const * inset = par.getInset(i);
204                         if (runparams.linelen > 0) {
205                                 os << word;
206                                 currlinelen += word.length();
207                                 word.erase();
208                         }
209                         OutputParams rp = runparams;
210                         rp.depth = par.params().depth();
211                         if (inset->plaintext(buf, os, rp)) {
212                                 // to be sure it breaks paragraph
213                                 currlinelen += runparams.linelen;
214                         }
215                         break;
216                 }
217
218                 case ' ':
219                         if (runparams.linelen > 0 &&
220                             currlinelen + word.length() > runparams.linelen - 10) {
221                                 os << "\n";
222                                 pair<int, string> p = addDepth(depth, ltype_depth);
223                                 os << p.second;
224                                 currlinelen = p.first;
225                         }
226                         os << word << ' ';
227                         currlinelen += word.length() + 1;
228                         word.erase();
229                         break;
230
231                 case '\0':
232                         lyxerr[Debug::INFO] <<
233                                 "writeAsciiFile: NULL char in structure." << endl;
234                         break;
235
236                 default:
237                         word += c;
238                         if (runparams.linelen > 0 &&
239                             currlinelen + word.length() > runparams.linelen)
240                         {
241                                 os << "\n";
242                                 pair<int, string> p = addDepth(depth, ltype_depth);
243                                 os << p.second;
244                                 currlinelen = p.first;
245                         }
246                         break;
247                 }
248         }
249         os << word;
250 }