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