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