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