]> git.lyx.org Git - lyx.git/blob - src/ParagraphParameters.C
fix some C++ parsing bugs
[lyx.git] / src / ParagraphParameters.C
1 #include <config.h>
2
3 #include "ParagraphParameters.h"
4 #include "ParameterStruct.h"
5 #include "tex-strings.h"
6 #include "lyxlex.h"
7
8 #include "buffer.h"
9 #include "BufferView.h"
10 #include "gettext.h"
11 #include "paragraph.h"
12 #include "lyxtext.h"
13 #include "frontends/LyXView.h"
14
15 #include "support/lstrings.h"
16
17 #include <iostream>
18
19 using std::ostream;
20
21 // Initialize static member var.
22 ShareContainer<ParameterStruct> ParagraphParameters::container;
23
24 ParagraphParameters::ParagraphParameters()
25 {
26         ParameterStruct tmp;
27         set_from_struct(tmp);
28 }
29
30
31 void ParagraphParameters::clear()
32 {
33         ParameterStruct tmp(*param);
34         tmp.line_top = false;
35         tmp.line_bottom = false;
36         tmp.pagebreak_top = false;
37         tmp.pagebreak_bottom = false;
38         tmp.added_space_top = VSpace(VSpace::NONE);
39         tmp.added_space_bottom = VSpace(VSpace::NONE);
40         tmp.spacing.set(Spacing::Default);
41         tmp.align = LYX_ALIGN_LAYOUT;
42         tmp.depth = 0;
43         tmp.noindent = false;
44         tmp.labelstring.erase();
45         tmp.labelwidthstring.erase();
46         tmp.start_of_appendix = false;
47         set_from_struct(tmp);
48 }
49
50
51 bool ParagraphParameters::sameLayout(ParagraphParameters const & pp) const
52 {
53         return param->align == pp.param->align &&
54                 param->line_bottom == pp.param->line_bottom &&
55                 param->pagebreak_bottom == pp.param->pagebreak_bottom &&
56                 param->added_space_bottom == pp.param->added_space_bottom &&
57
58                 param->line_top == pp.param->line_top &&
59                 param->pagebreak_top == pp.param->pagebreak_top &&
60                 param->added_space_top == pp.param->added_space_top &&
61                 param->spacing == pp.param->spacing &&
62                 param->noindent == pp.param->noindent &&
63                 param->depth == pp.param->depth;
64 }
65
66
67 void ParagraphParameters::set_from_struct(ParameterStruct const & ps)
68 {
69         // get new param from container with tmp as template
70         param = container.get(ps);
71 }
72
73
74 VSpace const & ParagraphParameters::spaceTop() const
75 {
76         return param->added_space_top;
77 }
78
79
80 void ParagraphParameters::spaceTop(VSpace const & vs)
81 {
82         ParameterStruct tmp(*param);
83         tmp.added_space_top = vs;
84         set_from_struct(tmp);
85 }
86
87
88 VSpace const & ParagraphParameters::spaceBottom() const
89 {
90         return param->added_space_bottom;
91 }
92
93
94 void ParagraphParameters::spaceBottom(VSpace const & vs)
95 {
96         ParameterStruct tmp(*param);
97         tmp.added_space_bottom = vs;
98         set_from_struct(tmp);
99 }
100
101
102 Spacing const & ParagraphParameters::spacing() const
103 {
104         return param->spacing;
105 }
106
107
108 void ParagraphParameters::spacing(Spacing const & s)
109 {
110         ParameterStruct tmp(*param);
111         tmp.spacing = s;
112         set_from_struct(tmp);
113 }
114
115
116 bool ParagraphParameters::noindent() const
117 {
118         return param->noindent;
119 }
120
121
122 void ParagraphParameters::noindent(bool ni)
123 {
124         ParameterStruct tmp(*param);
125         tmp.noindent = ni;
126         set_from_struct(tmp);
127 }
128
129
130 bool ParagraphParameters::lineTop() const
131 {
132         return param->line_top;
133 }
134
135
136 void ParagraphParameters::lineTop(bool lt)
137 {
138         ParameterStruct tmp(*param);
139         tmp.line_top = lt;
140         set_from_struct(tmp);
141 }
142
143
144 bool ParagraphParameters::lineBottom() const
145 {
146         return param->line_bottom;
147 }
148
149
150 void ParagraphParameters::lineBottom(bool lb)
151 {
152         ParameterStruct tmp(*param);
153         tmp.line_bottom = lb;
154         set_from_struct(tmp);
155 }
156
157
158 bool ParagraphParameters::pagebreakTop() const
159 {
160         return param->pagebreak_top;
161 }
162
163
164 void ParagraphParameters::pagebreakTop(bool pbt)
165 {
166         ParameterStruct tmp(*param);
167         tmp.pagebreak_top = pbt;
168         set_from_struct(tmp);
169 }
170
171
172 bool ParagraphParameters::pagebreakBottom() const
173 {
174         return param->pagebreak_bottom;
175 }
176
177
178 void ParagraphParameters::pagebreakBottom(bool pbb)
179 {
180         ParameterStruct tmp(*param);
181         tmp.pagebreak_bottom = pbb;
182         set_from_struct(tmp);
183 }
184
185
186 LyXAlignment ParagraphParameters::align() const
187 {
188         return param->align;
189 }
190
191
192 void ParagraphParameters::align(LyXAlignment la)
193 {
194         ParameterStruct tmp(*param);
195         tmp.align = la;
196         set_from_struct(tmp);
197 }
198
199
200 void ParagraphParameters::depth(depth_type d)
201 {
202         ParameterStruct tmp(*param);
203         tmp.depth = d;
204         set_from_struct(tmp);
205 }
206
207
208 bool ParagraphParameters::startOfAppendix() const
209 {
210         return param->start_of_appendix;
211 }
212
213
214 void ParagraphParameters::startOfAppendix(bool soa)
215 {
216         ParameterStruct tmp(*param);
217         tmp.start_of_appendix = soa;
218         set_from_struct(tmp);
219 }
220
221
222 bool ParagraphParameters::appendix() const
223 {
224         return param->appendix;
225 }
226
227
228 void ParagraphParameters::appendix(bool a)
229 {
230         ParameterStruct tmp(*param);
231         tmp.appendix = a;
232         set_from_struct(tmp);
233 }
234
235
236 string const & ParagraphParameters::labelString() const
237 {
238         return param->labelstring;
239 }
240
241
242 void ParagraphParameters::labelString(string const & ls)
243 {
244         ParameterStruct tmp(*param);
245         tmp.labelstring = ls;
246         set_from_struct(tmp);
247 }
248
249
250 string const & ParagraphParameters::labelWidthString() const
251 {
252         return param->labelwidthstring;
253 }
254
255
256 void ParagraphParameters::labelWidthString(string const & lws)
257 {
258         ParameterStruct tmp(*param);
259         tmp.labelwidthstring = lws;
260         set_from_struct(tmp);
261 }
262
263
264 LyXLength const & ParagraphParameters::leftIndent() const
265 {
266         return param->leftindent;
267 }
268
269
270 void ParagraphParameters::leftIndent(LyXLength const & li)
271 {
272         ParameterStruct tmp(*param);
273         tmp.leftindent = li;
274         set_from_struct(tmp);
275 }
276
277
278 void ParagraphParameters::read(LyXLex & lex)
279 {
280         while (lex.isOK()) {
281                 lex.nextToken();
282                 string const token = lex.getString();
283
284                 if (token.empty())
285                         continue;
286
287                 if (token[0] != '\\') {
288                         lex.pushToken(token);
289                         break;
290                 }
291
292                 if (token == "\\noindent") {
293                         noindent(true);
294                 } else if (token == "\\leftindent") {
295                         lex.nextToken();
296                         LyXLength value(lex.getString());
297                         leftIndent(value);
298                 } else if (token == "\\fill_top") {
299                         spaceTop(VSpace(VSpace::VFILL));
300                 } else if (token == "\\fill_bottom") {
301                         spaceBottom(VSpace(VSpace::VFILL));
302                 } else if (token == "\\line_top") {
303                         lineTop(true);
304                 } else if (token == "\\line_bottom") {
305                         lineBottom(true);
306                 } else if (token == "\\pagebreak_top") {
307                         pagebreakTop(true);
308                 } else if (token == "\\pagebreak_bottom") {
309                         pagebreakBottom(true);
310                 } else if (token == "\\start_of_appendix") {
311                         startOfAppendix(true);
312                 } else if (token == "\\paragraph_spacing") {
313                         lex.next();
314                         string const tmp = rtrim(lex.getString());
315                         if (tmp == "single") {
316                                 spacing(Spacing(Spacing::Single));
317                         } else if (tmp == "onehalf") {
318                                 spacing(Spacing(Spacing::Onehalf));
319                         } else if (tmp == "double") {
320                                 spacing(Spacing(Spacing::Double));
321                         } else if (tmp == "other") {
322                                 lex.next();
323                                 spacing(Spacing(Spacing::Other,
324                                                  lex.getFloat()));
325                         } else {
326                                 lex.printError("Unknown spacing token: '$$Token'");
327                         }
328                 } else if (token == "\\align") {
329                         int tmpret = lex.findToken(string_align);
330                         if (tmpret == -1)
331                                 ++tmpret;
332                         align(LyXAlignment(1 << tmpret));
333                 } else if (token == "\\added_space_top") {
334                         lex.nextToken();
335                         VSpace value = VSpace(lex.getString());
336                         // only add the length when value > 0 or
337                         // with option keep
338                         if ((value.length().len().value() != 0) ||
339                             value.keep() ||
340                             (value.kind() != VSpace::LENGTH))
341                                 spaceTop(value);
342                 } else if (token == "\\added_space_bottom") {
343                         lex.nextToken();
344                         VSpace value = VSpace(lex.getString());
345                         // only add the length when value > 0 or
346                         // with option keep
347                         if ((value.length().len().value() != 0) ||
348                            value.keep() ||
349                             (value.kind() != VSpace::LENGTH))
350                                 spaceBottom(value);
351                 } else if (token == "\\labelwidthstring") {
352                         lex.eatLine();
353                         labelWidthString(lex.getString());
354                 } else {
355                         lex.pushToken(token);
356                         break;
357                 }
358         }
359 }
360
361
362 void ParagraphParameters::write(ostream & os) const
363 {
364         // Maybe some vertical spaces.
365         if (spaceTop().kind() != VSpace::NONE)
366                 os << "\\added_space_top "
367                    << spaceTop().asLyXCommand() << ' ';
368         if (spaceBottom().kind() != VSpace::NONE)
369                 os << "\\added_space_bottom "
370                    << spaceBottom().asLyXCommand() << ' ';
371
372         // Maybe the paragraph has special spacing
373         spacing().writeFile(os, true);
374
375         // The labelwidth string used in lists.
376         if (!labelWidthString().empty())
377                 os << "\\labelwidthstring "
378                    << labelWidthString() << '\n';
379
380         // Lines above or below?
381         if (lineTop())
382                 os << "\\line_top ";
383         if (lineBottom())
384                 os << "\\line_bottom ";
385
386         // Pagebreaks above or below?
387         if (pagebreakTop())
388                 os << "\\pagebreak_top ";
389         if (pagebreakBottom())
390                 os << "\\pagebreak_bottom ";
391
392         // Start of appendix?
393         if (startOfAppendix())
394                 os << "\\start_of_appendix ";
395
396         // Noindent?
397         if (noindent())
398                 os << "\\noindent ";
399
400         // Do we have a manual left indent?
401         if (!leftIndent().zero())
402                 os << "\\leftindent " << leftIndent().asString()
403                    << ' ';
404
405         // Alignment?
406         if (align() != LYX_ALIGN_LAYOUT) {
407                 int h = 0;
408                 switch (align()) {
409                 case LYX_ALIGN_LEFT: h = 1; break;
410                 case LYX_ALIGN_RIGHT: h = 2; break;
411                 case LYX_ALIGN_CENTER: h = 3; break;
412                 default: h = 0; break;
413                 }
414                 os << "\\align " << string_align[h] << ' ';
415         }
416 }
417
418
419 void setParagraphParams(BufferView & bv, string const & data)
420 {
421         istringstream is(data);
422         LyXLex lex(0,0);
423         lex.setStream(is);
424
425         ParagraphParameters params;
426         params.read(lex);
427
428         LyXText * text = bv.getLyXText();
429         text->setParagraph(params.lineTop(),
430                            params.lineBottom(),
431                            params.pagebreakTop(),
432                            params.pagebreakBottom(),
433                            params.spaceTop(),
434                            params.spaceBottom(),
435                            params.spacing(),
436                            params.align(),
437                            params.labelWidthString(),
438                            params.noindent());
439
440         // Actually apply these settings
441         bv.update(text, BufferView::SELECT);
442
443         bv.owner()->message(_("Paragraph layout set"));
444 }
445
446
447 void params2string(Paragraph const & par, string & data)
448 {
449         // A local copy
450         ParagraphParameters params = par.params();
451
452         // This needs to be done separately
453         params.labelWidthString(par.getLabelWidthString());
454
455         // Alignment
456         LyXLayout_ptr const & layout = par.layout();
457         if (params.align() == LYX_ALIGN_LAYOUT)
458                 params.align(layout->align);
459
460         ostringstream os;
461         params.write(os);
462
463         // Is alignment possible
464         os << '\n' << "\\alignpossible " << layout->alignpossible << '\n';
465
466         /// set default alignment
467         os << "\\aligndefault " << layout->align << '\n';
468
469         /// is paragraph in inset
470         os << "\\ininset " << par.inInset() << '\n';
471
472         data = os.str();
473 }