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