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