]> git.lyx.org Git - lyx.git/blob - src/lyxrow_funcs.C
If I ever see another licence blurb again, it'll be too soon...
[lyx.git] / src / lyxrow_funcs.C
1 /**
2  * \file lyxrow_funcs.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 André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "lyxrow_funcs.h"
15 #include "lyxtext.h"
16 #include "paragraph.h"
17 #include "lyxlayout.h"
18 #include "debug.h"
19
20 #include "support/LAssert.h"
21
22 #include <boost/next_prior.hpp>
23 #include <algorithm>
24
25 using lyx::pos_type;
26 using lyx::support::Assert;
27
28 using std::max;
29 using std::min;
30 using std::endl;
31
32
33 bool isParEnd(Paragraph const & par, RowList::iterator rit)
34 {
35 #if 0
36         if ((boost::next(rit) == par.rows.end()) != (rit->end() >= par.size())) {
37                 lyxerr << endl;
38                 lyxerr << "broken row 1: end: " << rit->end() << " next: "
39                         << boost::next(rit)->pos() << endl;
40                 lyxerr << endl;
41                 Assert(false);
42         }
43 #endif
44         return boost::next(rit) == par.rows.end();
45 }
46
47
48 pos_type lastPos(Paragraph const & par, RowList::iterator rit)
49 {
50         if (par.empty())
51                 return 0;
52
53         if (isParEnd(par, rit))
54                 return par.size() - 1;
55
56         if (1 && boost::next(rit)->pos() != rit->end()) {
57                 lyxerr << endl;
58                 lyxerr << "broken row 2: end: " << rit->end() << " next: "
59                         << boost::next(rit)->pos() << endl;
60                 lyxerr << endl;
61                 Assert(false);
62         }
63         return boost::next(rit)->pos() - 1;
64 }
65
66
67 namespace {
68
69 bool nextRowIsAllInset(Paragraph const & par, pos_type last)
70 {
71         if (last + 1 >= par.size())
72                 return false;
73
74         if (!par.isInset(last + 1))
75                 return false;
76
77         InsetOld const * i = par.getInset(last + 1);
78         return i->needFullRow() || i->display();
79 }
80
81 } // anon namespace
82
83
84 pos_type lastPrintablePos(Paragraph const & par, RowList::iterator rit)
85 {
86         pos_type const last = lastPos(par, rit);
87
88         // if this row is an end of par, just act like lastPos()
89         if (isParEnd(par, rit))
90                 return last;
91
92         if (!nextRowIsAllInset(par, last) && par.isSeparator(last))
93                 return last - 1;
94
95         return last;
96 }
97
98
99 int numberOfSeparators(Paragraph const & par, RowList::iterator rit)
100 {
101         pos_type const last = lastPrintablePos(par, rit);
102         int n = 0;
103         pos_type p = max(rit->pos(), par.beginningOfBody());
104         for ( ; p < last; ++p)
105                 if (par.isSeparator(p))
106                         ++n;
107         return n;
108 }
109
110
111 // This is called _once_ from LyXText and should at least be moved into
112 // an anonymous namespace there. (Lgb)
113 int numberOfHfills(Paragraph const & par, RowList::iterator rit)
114 {
115         pos_type const last = lastPos(par, rit);
116         pos_type first = rit->pos();
117
118         // hfill *DO* count at the beginning of paragraphs!
119         if (first) {
120                 while (first < last && par.isHfill(first))
121                         ++first;
122         }
123
124         first = max(first, par.beginningOfBody());
125
126         int n = 0;
127
128         // last, because the end is ignored!
129         for (pos_type p = first; p < last; ++p)
130                 if (par.isHfill(p))
131                         ++n;
132
133         return n;
134 }
135
136
137 // This is called _once_ from LyXText and should at least be moved into
138 // an anonymous namespace there. (Lgb)
139 int numberOfLabelHfills(Paragraph const & par, RowList::iterator rit)
140 {
141         pos_type last = lastPos(par, rit);
142         pos_type first = rit->pos();
143
144         // hfill *DO* count at the beginning of paragraphs!
145         if (first) {
146                 while (first < last && par.isHfill(first))
147                         ++first;
148         }
149
150         last = min(last, par.beginningOfBody());
151         int n = 0;
152
153         // last, because the end is ignored!
154         for (pos_type p = first; p < last; ++p) {
155                 if (par.isHfill(p))
156                         ++n;
157         }
158         return n;
159 }
160
161
162 bool hfillExpansion(Paragraph const & par, RowList::iterator rit, pos_type pos)
163 {
164         if (!par.isHfill(pos))
165                 return false;
166
167         // at the end of a row it does not count
168         // unless another hfill exists on the line
169         if (pos >= lastPos(par, rit))
170                 for (pos_type i = rit->pos(); i < pos && !par.isHfill(i); ++i)
171                         return false;
172
173         // at the beginning of a row it does not count, if it is not
174         // the first row of a paragaph
175         if (rit->isParStart())
176                 return true;
177
178         // in some labels it does not count
179         if (par.layout()->margintype != MARGIN_MANUAL
180             && pos < par.beginningOfBody())
181                 return false;
182
183         // if there is anything between the first char of the row and
184         // the specified position that is not a newline and not a hfill,
185         // the hfill will count, otherwise not
186         pos_type i = rit->pos();
187         while (i < pos && (par.isNewline(i) || par.isHfill(i)))
188                 ++i;
189
190         return i != pos;
191 }