]> git.lyx.org Git - lyx.git/blob - src/VSpace.cpp
Avoid full metrics computation with Update:FitCursor
[lyx.git] / src / VSpace.cpp
1 /**
2  * \file VSpace.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Matthias Ettrich
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "VSpace.h"
14
15 #include "Buffer.h"
16 #include "BufferParams.h"
17 #include "BufferView.h"
18 #include "support/gettext.h"
19 #include "TextMetrics.h" // for defaultRowHeight()
20
21 #include "support/convert.h"
22 #include "support/Length.h"
23 #include "support/lstrings.h"
24 #include "support/qstring_helpers.h"
25
26 #include "support/lassert.h"
27
28 using namespace std;
29 using namespace lyx::support;
30
31
32 namespace lyx {
33
34 //
35 //  VSpace class
36 //
37
38 VSpace::VSpace()
39         : kind_(DEFSKIP), len_(), keep_(false)
40 {}
41
42
43 VSpace::VSpace(VSpaceKind k)
44         : kind_(k), len_(), keep_(false)
45 {}
46
47
48 VSpace::VSpace(Length const & l)
49         : kind_(LENGTH), len_(l), keep_(false)
50 {}
51
52
53 VSpace::VSpace(GlueLength const & l)
54         : kind_(LENGTH), len_(l), keep_(false)
55 {}
56
57
58 VSpace::VSpace(string const & data)
59         : kind_(DEFSKIP), len_(), keep_(false)
60 {
61         if (data.empty())
62                 return;
63
64         string input = rtrim(data);
65
66         size_t const length = input.length();
67
68         if (length > 1 && input[length - 1] == '*') {
69                 keep_ = true;
70                 input.erase(length - 1);
71         }
72
73         if (prefixIs(input, "defskip"))
74                 kind_ = DEFSKIP;
75         else if (prefixIs(input, "smallskip"))
76                 kind_ = SMALLSKIP;
77         else if (prefixIs(input, "medskip"))
78                 kind_ = MEDSKIP;
79         else if (prefixIs(input, "bigskip"))
80                 kind_ = BIGSKIP;
81         else if (prefixIs(input, "halfline"))
82                 kind_ = HALFLINE;
83         else if (prefixIs(input, "fullline"))
84                 kind_ = FULLLINE;
85         else if (prefixIs(input, "vfill"))
86                 kind_ = VFILL;
87         else if (isValidGlueLength(input, &len_))
88                 kind_ = LENGTH;
89         else if (isStrDbl(input)) {
90                 // This last one is for reading old .lyx files
91                 // without units in added_space_top/bottom.
92                 // Let unit default to centimeters here.
93                 kind_ = LENGTH;
94                 len_  = GlueLength(Length(convert<double>(input), Length::CM));
95         }
96 }
97
98
99 bool VSpace::operator==(VSpace const & other) const
100 {
101         if (kind_ != other.kind_)
102                 return false;
103
104         if (kind_ != LENGTH)
105                 return this->keep_ == other.keep_;
106
107         if (len_ != other.len_)
108                 return false;
109
110         return keep_ == other.keep_;
111 }
112
113
114 string const VSpace::asLyXCommand() const
115 {
116         string result;
117         switch (kind_) {
118         case DEFSKIP:
119                 result = "defskip";
120                 break;
121         case SMALLSKIP:
122                 result = "smallskip";
123                 break;
124         case MEDSKIP:
125                 result = "medskip";
126                 break;
127         case BIGSKIP:
128                 result = "bigskip";
129                 break;
130         case HALFLINE:
131                 result = "halfline";
132                 break;
133         case FULLLINE:
134                 result = "fullline";
135                 break;
136         case VFILL:
137                 result = "vfill";
138                 break;
139         case LENGTH:
140                 result = len_.asString();
141                 break;
142         }
143         if (keep_)
144                 result += '*';
145         return result;
146 }
147
148
149 string const VSpace::asLatexCommand(BufferParams const & params) const
150 {
151         switch (kind_) {
152         case DEFSKIP:
153                 return params.getDefSkip().asLatexCommand(params);
154
155         case SMALLSKIP:
156                 return keep_ ? "\\vspace*{\\smallskipamount}" : "\\smallskip{}";
157
158         case MEDSKIP:
159                 return keep_ ? "\\vspace*{\\medskipamount}" : "\\medskip{}";
160
161         case BIGSKIP:
162                 return keep_ ? "\\vspace*{\\bigskipamount}" : "\\bigskip{}";
163         
164         case HALFLINE:
165                 return keep_ ? "\\vspace*{.5\\baselineskip}" : "\\vspace{.5\\baselineskip}";
166
167         case FULLLINE:
168                 return keep_ ? "\\vspace*{\\baselineskip}" : "\\vspace{\\baselineskip}";
169
170         case VFILL:
171                 return keep_ ? "\\vspace*{\\fill}" : "\\vfill{}";
172
173         case LENGTH:
174                 return keep_ ? "\\vspace*{" + len_.asLatexString() + '}'
175                         : "\\vspace{" + len_.asLatexString() + '}';
176
177         default:
178                 LATTEST(false);
179                 // fall through in release mode
180         }
181         return string();
182 }
183
184
185 docstring const VSpace::asGUIName() const
186 {
187         docstring result;
188         switch (kind_) {
189         case DEFSKIP:
190                 result = _("Default skip");
191                 break;
192         case SMALLSKIP:
193                 result = _("Small skip");
194                 break;
195         case MEDSKIP:
196                 result = _("Medium skip");
197                 break;
198         case BIGSKIP:
199                 result = _("Big skip");
200                 break;
201         case HALFLINE:
202                 result = _("Half line height");
203                 break;
204         case FULLLINE:
205                 result = _("Line height");
206                 break;
207         case VFILL:
208                 result = _("Vertical fill");
209                 break;
210         case LENGTH:
211                 result = locLengthDocString(from_ascii(len_.asString()));
212                 break;
213         }
214         if (keep_)
215                 result += ", " + _("protected");
216         return result;
217 }
218
219
220 string VSpace::asHTMLLength() const
221 {
222         string result;
223         switch (kind_) {
224                 case DEFSKIP:
225                         result = "2ex";
226                         break;
227                 case SMALLSKIP:
228                         result = "1ex";
229                         break;
230                 case MEDSKIP:
231                         result = "3ex";
232                         break;
233                 case BIGSKIP:
234                         result = "5ex";
235                         break;
236                 case HALFLINE:
237                         result = "0.6em";
238                         break;
239                 case FULLLINE:
240                         result = "1.2em";
241                         break;
242                 case LENGTH: {
243                         Length tmp = len_.len();
244                         if (tmp.value() > 0)
245                                 result = tmp.asHTMLString();
246                 }
247                 case VFILL:
248                         break;
249         }
250         return result;
251 }
252
253
254 int VSpace::inPixels(BufferView const & bv) const
255 {
256         // Height of a normal line in pixels (zoom factor considered)
257         int const default_height = defaultRowHeight();
258
259         switch (kind_) {
260
261         case DEFSKIP:
262                 return bv.buffer().params().getDefSkip().inPixels(bv);
263
264         // This is how the skips are normally defined by LaTeX.
265         // But there should be some way to change this per document.
266         case SMALLSKIP:
267                 return default_height / 4;
268
269         case MEDSKIP:
270                 return default_height / 2;
271
272         case BIGSKIP:
273                 return default_height;
274
275         case VFILL:
276                 // leave space for the vfill symbol
277                 return 3 * default_height;
278
279         case HALFLINE:
280                 return default_height / 2;
281
282         case FULLLINE:
283                 return default_height;
284
285         case LENGTH:
286                 return bv.inPixels(len_.len());
287
288         default:
289                 LATTEST(false);
290                 // fall through in release mode
291         }
292         return 0;
293 }
294
295
296 } // namespace lyx