]> git.lyx.org Git - lyx.git/blob - src/lyxrow.C
956c350ee607b569786a3531ff1ee64ecaf7aade
[lyx.git] / src / lyxrow.C
1 /**
2  * \file lyxrow.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author unknown
7  *
8  * Full author contact details are available in file CREDITS
9  *
10  * Metrics for an on-screen text row.
11  */
12
13 #include <config.h>
14
15 #include "lyxrow.h"
16 #include "paragraph.h"
17 #include "layout.h"
18 #include "lyxlayout.h"
19
20 using lyx::pos_type;
21
22 using std::max;
23 using std::min;
24
25 Row::Row()
26         : par_(0), pos_(0), fill_(0), height_(0), width_(0),
27           ascent_of_text_(0), baseline_(0), next_(0), previous_(0)
28 {}
29
30
31 Row::Row(Paragraph * pa, pos_type po)
32         : par_(pa), pos_(po), fill_(0), height_(0), width_(0),
33           ascent_of_text_(0), baseline_(0), next_(0), previous_(0)
34 {}
35
36
37 Paragraph * Row::par()
38 {
39         return par_;
40 }
41
42
43 Paragraph * Row::par() const
44 {
45         return par_;
46 }
47
48
49 unsigned short Row::height() const
50 {
51         return height_;
52 }
53
54
55 Row * Row::next() const
56 {
57         return next_;
58 }
59
60
61 void Row::par(Paragraph * p)
62 {
63         par_ = p;
64 }
65
66
67 void Row::pos(pos_type p)
68 {
69         pos_ = p;
70 }
71
72
73 pos_type Row::pos() const
74 {
75         return pos_;
76 }
77
78
79 void Row::fill(int f)
80 {
81         fill_ = f;
82 }
83
84
85 int Row::fill() const
86 {
87         return fill_;
88 }
89
90
91 void Row::height(unsigned short h)
92 {
93         height_ = h;
94 }
95
96
97 void Row::width(unsigned int w)
98 {
99         width_ = w;
100 }
101
102
103 unsigned int Row::width() const
104 {
105         return width_;
106 }
107
108
109 void Row::ascent_of_text(unsigned short a)
110 {
111         ascent_of_text_ = a;
112 }
113
114
115 unsigned short Row::ascent_of_text() const
116 {
117         return ascent_of_text_;
118 }
119
120
121 void Row::top_of_text(unsigned int top)
122 {
123         top_of_text_ = top;
124 }
125
126
127 unsigned int Row::top_of_text() const
128 {
129         return top_of_text_;
130 }
131
132
133 void Row::baseline(unsigned int b)
134 {
135         baseline_ = b;
136 }
137
138
139 unsigned int Row::baseline() const
140 {
141         return baseline_;
142 }
143
144
145 void Row::next(Row * r)
146 {
147         next_ = r;
148 }
149
150
151 void Row::previous(Row * r)
152 {
153         previous_ = r;
154 }
155
156
157 Row * Row::previous() const
158 {
159         return previous_;
160 }
161
162
163 bool Row::isParStart() const
164 {
165         return !pos();
166 }
167
168
169 bool Row::isParEnd() const
170 {
171         return !next() || next()->par() != par();
172 }
173
174
175 pos_type Row::lastPos() const
176 {
177         if (par()->empty())
178                 return 0;
179
180         if (isParEnd()) {
181                 return par()->size() - 1;
182         } else {
183                 return next()->pos() - 1;
184         }
185 }
186
187
188 namespace {
189
190 bool nextRowIsAllInset(Row const & row, pos_type last)
191 {
192         if (last + 1 >= row.par()->size())
193                 return false;
194
195         if (!row.par()->isInset(last + 1))
196                 return false;
197
198         Inset * i = row.par()->getInset(last + 1);
199         return i->needFullRow() || i->display();
200 }
201
202 };
203
204
205 pos_type Row::lastPrintablePos() const
206 {
207         pos_type const last = lastPos();
208
209         // if this row is an end of par, just act like lastPos()
210         if (isParEnd())
211                 return last;
212
213         bool const nextrownotinset = !nextRowIsAllInset(*this, last);
214
215         if (nextrownotinset && par()->isSeparator(last))
216                 return last - 1;
217
218         return last;
219 }
220
221
222 int Row::numberOfSeparators() const
223 {
224         pos_type const last = lastPrintablePos();
225         pos_type p = max(pos(), par()->beginningOfBody());
226
227         int n = 0;
228         for (; p < last; ++p) {
229                 if (par()->isSeparator(p)) {
230                         ++n;
231                 }
232         }
233         return n;
234 }
235
236
237 int Row::numberOfHfills() const
238 {
239         pos_type const last = lastPos();
240         pos_type first = pos();
241
242         // hfill *DO* count at the beginning of paragraphs!
243         if (first) {
244                 while (first < last && par()->isHfill(first)) {
245                         ++first;
246                 }
247         }
248
249         first = max(first, par()->beginningOfBody());
250
251         int n = 0;
252
253         // last, because the end is ignored!
254         for (pos_type p = first; p < last; ++p) {
255                 if (par()->isHfill(p))
256                         ++n;
257         }
258         return n;
259 }
260
261
262 int Row::numberOfLabelHfills() const
263 {
264         pos_type last = lastPos();
265         pos_type first = pos();
266
267         // hfill *DO* count at the beginning of paragraphs!
268         if (first) {
269                 while (first < last && par()->isHfill(first))
270                         ++first;
271         }
272
273         last = min(last, par()->beginningOfBody());
274         int n = 0;
275
276         // last, because the end is ignored!
277         for (pos_type p = first; p < last; ++p) {
278                 if (par()->isHfill(p))
279                         ++n;
280         }
281         return n;
282 }
283
284
285 bool Row::hfillExpansion(pos_type pos) const
286 {
287         if (!par()->isHfill(pos))
288                 return false;
289
290         // at the end of a row it does not count
291         // unless another hfill exists on the line
292         if (pos >= lastPos()) {
293                 pos_type i = this->pos();
294                 while (i < pos && !par()->isHfill(i)) {
295                         ++i;
296                 }
297                 if (i == pos) {
298                         return false;
299                 }
300         }
301
302         // at the beginning of a row it does not count, if it is not
303         // the first row of a paragaph
304         if (isParStart())
305                 return true;
306
307         // in some labels it does not count
308         if (par()->layout()->margintype != MARGIN_MANUAL
309             && pos < par()->beginningOfBody())
310                 return false;
311
312         // if there is anything between the first char of the row and
313         // the specified position that is not a newline and not a hfill,
314         // the hfill will count, otherwise not
315         pos_type i = this->pos();
316         while (i < pos && (par()->isNewline(i) || par()->isHfill(i)))
317                 ++i;
318
319         return i != pos;
320 }