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