1 /**
2 * \file ParagraphParameters.cpp
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 "support/gettext.h"
21 #include "Layout.h"
22 #include "Lexer.h"
23 #include "Text.h"
24 #include "Paragraph.h"
25
26 #include "support/lstrings.h"
27
28 #include <sstream>
29
30 using namespace std;
31 using namespace lyx::support;
32
33 namespace lyx {
34
35
36 //NOTE The order of these MUST be the same as in Layout.h.
37 static char const * const string_align[] = {
38 "block", "left", "right", "center", "default", ""
39 };
40
41
ParagraphParameters()42 ParagraphParameters::ParagraphParameters()
43 : noindent_(false),
44 start_of_appendix_(false), appendix_(false),
45 align_(LYX_ALIGN_LAYOUT), depth_(0)
46 {}
47
48
clear()49 void ParagraphParameters::clear()
50 {
51 operator=(ParagraphParameters());
52 }
53
54
depth() const55 depth_type ParagraphParameters::depth() const
56 {
57 return depth_;
58 }
59
60
sameLayout(ParagraphParameters const & pp) const61 bool ParagraphParameters::sameLayout(ParagraphParameters const & pp) const
62 {
63 return align_ == pp.align_
64 && spacing_ == pp.spacing_
65 && noindent_ == pp.noindent_
66 && depth_ == pp.depth_;
67 }
68
69
spacing() const70 Spacing const & ParagraphParameters::spacing() const
71 {
72 return spacing_;
73 }
74
75
spacing(Spacing const & s)76 void ParagraphParameters::spacing(Spacing const & s)
77 {
78 spacing_ = s;
79 }
80
81
noindent() const82 bool ParagraphParameters::noindent() const
83 {
84 return noindent_;
85 }
86
87
noindent(bool ni)88 void ParagraphParameters::noindent(bool ni)
89 {
90 noindent_ = ni;
91 }
92
93
align() const94 LyXAlignment ParagraphParameters::align() const
95 {
96 return align_;
97 }
98
99
align(LyXAlignment la)100 void ParagraphParameters::align(LyXAlignment la)
101 {
102 align_ = la;
103 }
104
105
depth(depth_type d)106 void ParagraphParameters::depth(depth_type d)
107 {
108 depth_ = d;
109 }
110
111
startOfAppendix() const112 bool ParagraphParameters::startOfAppendix() const
113 {
114 return start_of_appendix_;
115 }
116
117
startOfAppendix(bool soa)118 void ParagraphParameters::startOfAppendix(bool soa)
119 {
120 start_of_appendix_ = soa;
121 }
122
123
appendix() const124 bool ParagraphParameters::appendix() const
125 {
126 return appendix_;
127 }
128
129
appendix(bool a)130 void ParagraphParameters::appendix(bool a)
131 {
132 appendix_ = a;
133 }
134
135
labelString() const136 docstring const & ParagraphParameters::labelString() const
137 {
138 return labelstring_;
139 }
140
141
labelString(docstring const & ls)142 void ParagraphParameters::labelString(docstring const & ls)
143 {
144 labelstring_ = ls;
145 }
146
147
labelWidthString() const148 docstring const & ParagraphParameters::labelWidthString() const
149 {
150 return labelwidthstring_;
151 }
152
153
labelWidthString(docstring const & lws)154 void ParagraphParameters::labelWidthString(docstring const & lws)
155 {
156 labelwidthstring_ = lws;
157 }
158
159
leftIndent() const160 Length const & ParagraphParameters::leftIndent() const
161 {
162 return leftindent_;
163 }
164
165
leftIndent(Length const & li)166 void ParagraphParameters::leftIndent(Length const & li)
167 {
168 leftindent_ = li;
169 }
170
171
read(string str,bool merge)172 void ParagraphParameters::read(string str, bool merge)
173 {
174 istringstream is(str);
175 Lexer lex;
176 lex.setStream(is);
177 read(lex, merge);
178 }
179
180
read(Lexer & lex,bool merge)181 void ParagraphParameters::read(Lexer & lex, bool merge)
182 {
183 if (!merge)
184 clear();
185 while (lex.isOK()) {
186 lex.nextToken();
187 string const token = lex.getString();
188
189 if (token.empty())
190 continue;
191
192 if (token[0] != '\\') {
193 lex.pushToken(token);
194 break;
195 }
196
197 if (token == "\\noindent") {
198 noindent(true);
199 } else if (token == "\\indent") {
200 //not found in LyX files but can be used with lfuns
201 noindent(false);
202 } else if (token == "\\indent-toggle") {
203 //not found in LyX files but can be used with lfuns
204 noindent(!noindent());
205 } else if (token == "\\leftindent") {
206 lex.next();
207 Length value(lex.getString());
208 leftIndent(value);
209 } else if (token == "\\start_of_appendix") {
210 startOfAppendix(true);
211 } else if (token == "\\paragraph_spacing") {
212 lex.next();
213 string const tmp = rtrim(lex.getString());
214 if (tmp == "default") {
215 //not found in LyX files but can be used with lfuns
216 spacing(Spacing(Spacing::Default));
217 } else if (tmp == "single") {
218 spacing(Spacing(Spacing::Single));
219 } else if (tmp == "onehalf") {
220 spacing(Spacing(Spacing::Onehalf));
221 } else if (tmp == "double") {
222 spacing(Spacing(Spacing::Double));
223 } else if (tmp == "other") {
224 lex.next();
225 spacing(Spacing(Spacing::Other,
226 lex.getString()));
227 } else {
228 lex.printError("Unknown spacing token: '$$Token'");
229 }
230 } else if (token == "\\align") {
231 lex.next();
232 int tmpret = findToken(string_align, lex.getString());
233 if (tmpret == -1)
234 ++tmpret;
235 align(LyXAlignment(1 << tmpret));
236 } else if (token == "\\labelwidthstring") {
237 lex.eatLine();
238 labelWidthString(lex.getDocString());
239 } else {
240 lex.pushToken(token);
241 break;
242 }
243 }
244 }
245
246
apply(ParagraphParameters const & p,Layout const & layout)247 void ParagraphParameters::apply(
248 ParagraphParameters const & p, Layout const & layout)
249 {
250 spacing(p.spacing());
251 // does the layout allow the new alignment?
252 if (p.align() & layout.alignpossible)
253 align(p.align());
254 labelWidthString(p.labelWidthString());
255 noindent(p.noindent());
256 }
257
258
write(ostream & os) const259 void ParagraphParameters::write(ostream & os) const
260 {
261 // Maybe the paragraph has special spacing
262 spacing().writeFile(os, true);
263
264 // The labelwidth string used in lists.
265 if (!labelWidthString().empty())
266 os << "\\labelwidthstring "
267 << to_utf8(labelWidthString()) << '\n';
268
269 // Start of appendix?
270 if (startOfAppendix())
271 os << "\\start_of_appendix\n";
272
273 // Noindent?
274 if (noindent())
275 os << "\\noindent\n";
276
277 // Do we have a manual left indent?
278 if (!leftIndent().zero())
279 os << "\\leftindent " << leftIndent().asString() << '\n';
280
281 // Alignment?
282 if (align() != LYX_ALIGN_LAYOUT) {
283 int h = 0;
284 switch (align()) {
285 case LYX_ALIGN_LEFT: h = 1; break;
286 case LYX_ALIGN_RIGHT: h = 2; break;
287 case LYX_ALIGN_CENTER: h = 3; break;
288 default: h = 0; break;
289 }
290 os << "\\align " << string_align[h] << '\n';
291 }
292 }
293
294
params2string(Paragraph const & par,string & data)295 void params2string(Paragraph const & par, string & data)
296 {
297 // A local copy
298 ParagraphParameters params = par.params();
299
300 // This needs to be done separately
301 params.labelWidthString(par.getLabelWidthString());
302
303 ostringstream os;
304 params.write(os);
305
306 Layout const & layout = par.layout();
307
308 // Is alignment possible
309 os << "\\alignpossible " << layout.alignpossible << '\n';
310
311 /// set default alignment
312 os << "\\aligndefault " << layout.align << '\n';
313
314 /// paragraph is always in inset. This is redundant.
315 os << "\\ininset " << 1 << '\n';
316
317 data = os.str();
318 }
319
320
321 /*
322 bool operator==(ParagraphParameeters const & ps1,
323 ParagraphParameeters const & ps2)
324 {
325 return
326 ps1.spacing == ps2.spacing
327 && ps1.noindent == ps2.noindent
328 && ps1.align == ps2.align
329 && ps1.depth == ps2.depth
330 && ps1.start_of_appendix == ps2.start_of_appendix
331 && ps1.appendix == ps2.appendix
332 && ps1.labelstring == ps2.labelstring
333 && ps1.labelwidthstring == ps2.labelwidthstring
334 && ps1.leftindent == ps2.leftindent;
335 }
336 */
337
338
339 } // namespace lyx
340