]> git.lyx.org Git - lyx.git/blob - src/output_plaintext.C
Fix bug 2195: Slowness in rendering inside insets, especially on the Mac
[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/lstrings.h"
26
27 #include <fstream>
28
29 using lyx::support::ascii_lowercase;
30 using lyx::support::compare_ascii_no_case;
31 using lyx::support::compare_no_case;
32 using lyx::support::contains;
33
34 using lyx::pos_type;
35 using std::endl;
36 using std::ostream;
37 using std::ofstream;
38 using std::pair;
39 using std::string;
40
41
42 void writeFileAscii(Buffer const & buf,
43                     string const & fname,
44                     OutputParams const & runparams)
45 {
46         ofstream ofs;
47         if (!::openFileWrite(ofs, fname))
48                 return;
49         writeFileAscii(buf, ofs, runparams);
50 }
51
52
53 void writeFileAscii(Buffer const & buf, ostream & os,
54         OutputParams const & runparams)
55 {
56         bool ref_printed = false;
57         ParagraphList const par = buf.paragraphs();
58         ParagraphList::const_iterator beg = par.begin();
59         ParagraphList::const_iterator end = par.end();
60         ParagraphList::const_iterator it = beg;
61         for (; it != end; ++it) {
62                 asciiParagraph(buf, *it, os, runparams, ref_printed);
63         }
64         os << "\n";
65 }
66
67
68 namespace {
69
70 pair<int, string> const addDepth(int depth, int ldepth)
71 {
72         int d = depth * 2;
73         if (ldepth > depth)
74                 d += (ldepth - depth) * 2;
75         return make_pair(d, string(d, ' '));
76 }
77
78 }
79
80
81 void asciiParagraph(Buffer const & buf,
82                     Paragraph const & par,
83                     ostream & os,
84                     OutputParams const & runparams,
85                     bool & ref_printed)
86 {
87         int ltype = 0;
88         Paragraph::depth_type ltype_depth = 0;
89         Paragraph::depth_type depth = par.params().depth();
90
91         // First write the layout
92         string const & tmp = par.layout()->name();
93         if (compare_no_case(tmp, "itemize") == 0) {
94                 ltype = 1;
95                 ltype_depth = depth + 1;
96         } else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
97                 ltype = 2;
98                 ltype_depth = depth + 1;
99         } else if (contains(ascii_lowercase(tmp), "ection")) {
100                 ltype = 3;
101                 ltype_depth = depth + 1;
102         } else if (contains(ascii_lowercase(tmp), "aragraph")) {
103                 ltype = 4;
104                 ltype_depth = depth + 1;
105         } else if (compare_ascii_no_case(tmp, "description") == 0) {
106                 ltype = 5;
107                 ltype_depth = depth + 1;
108         } else if (compare_ascii_no_case(tmp, "abstract") == 0) {
109                 ltype = 6;
110                 ltype_depth = 0;
111         } else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
112                 ltype = 7;
113                 ltype_depth = 0;
114         } else {
115                 ltype = 0;
116                 ltype_depth = 0;
117         }
118
119         /* maybe some vertical spaces */
120
121         /* the labelwidthstring used in lists */
122
123         /* some lines? */
124
125         /* some pagebreaks? */
126
127         /* noindent ? */
128
129         /* what about the alignment */
130
131         // runparams.linelen <= 0 is special and means we don't have paragraph breaks
132
133         string::size_type currlinelen = 0;
134
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         if (!currlinelen) {
187                 pair<int, string> p = addDepth(depth, ltype_depth);
188                 os << p.second;
189                 currlinelen += p.first;
190         }
191
192         // this is to change the linebreak to do it by word a bit more
193         // intelligent hopefully! (only in the case where we have a
194         // max runparams.linelength!) (Jug)
195
196         string word;
197
198         for (pos_type i = 0; i < par.size(); ++i) {
199                 char c = par.getUChar(buf.params(), i);
200                 switch (c) {
201                 case Paragraph::META_INSET: {
202                         InsetBase const * inset = par.getInset(i);
203                         if (runparams.linelen > 0) {
204                                 os << word;
205                                 currlinelen += word.length();
206                                 word.erase();
207                         }
208                         OutputParams rp = runparams;
209                         rp.depth = par.params().depth();
210                         if (inset->plaintext(buf, os, rp)) {
211                                 // to be sure it breaks paragraph
212                                 currlinelen += runparams.linelen;
213                         }
214                         break;
215                 }
216
217                 case ' ':
218                         if (runparams.linelen > 0 &&
219                             currlinelen + word.length() > runparams.linelen - 10) {
220                                 os << "\n";
221                                 pair<int, string> p = addDepth(depth, ltype_depth);
222                                 os << p.second;
223                                 currlinelen = p.first;
224                         }
225                         os << word << ' ';
226                         currlinelen += word.length() + 1;
227                         word.erase();
228                         break;
229
230                 case '\0':
231                         lyxerr[Debug::INFO] <<
232                                 "writeAsciiFile: NULL char in structure." << endl;
233                         break;
234
235                 default:
236                         word += c;
237                         if (runparams.linelen > 0 &&
238                             currlinelen + word.length() > runparams.linelen)
239                         {
240                                 os << "\n";
241                                 pair<int, string> p = addDepth(depth, ltype_depth);
242                                 os << p.second;
243                                 currlinelen = p.first;
244                         }
245                         break;
246                 }
247         }
248         os << word;
249 }