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