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