]> git.lyx.org Git - lyx.git/blob - src/ParagraphMetrics.C
* output_plaintext.C: cosmetics in comment: line length cannot be < 0
[lyx.git] / src / ParagraphMetrics.C
1 /**
2  * \file paragraph.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  * \author Dekel Tsur
13  * \author Jürgen Vigna
14  *
15  * Full author contact details are available in file CREDITS.
16  */
17
18 #include <config.h>
19
20 #include "ParagraphMetrics.h"
21
22 #include "buffer.h"
23 #include "bufferparams.h"
24 #include "counters.h"
25 #include "encoding.h"
26 #include "debug.h"
27 #include "gettext.h"
28 #include "language.h"
29 #include "LaTeXFeatures.h"
30 #include "lyxfont.h"
31 #include "lyxrc.h"
32 #include "lyxrow.h"
33 #include "outputparams.h"
34 #include "paragraph_funcs.h"
35 #include "ParagraphList_fwd.h"
36
37 #include "rowpainter.h"
38
39 #include "sgml.h"
40 #include "texrow.h"
41 #include "vspace.h"
42
43 #include "frontends/FontMetrics.h"
44
45 #include "insets/insetbibitem.h"
46 #include "insets/insetoptarg.h"
47
48 #include "support/lstrings.h"
49 #include "support/textutils.h"
50 #include "support/convert.h"
51 #include "support/unicode.h"
52
53 #include <boost/bind.hpp>
54 #include <boost/crc.hpp>
55
56 #include <algorithm>
57 #include <list>
58 #include <stack>
59 #include <sstream>
60
61
62 namespace lyx {
63
64 using lyx::support::contains;
65 using lyx::support::rsplit;
66 using support::subst;
67
68 using std::distance;
69 using std::endl;
70 using std::list;
71 using std::stack;
72 using std::string;
73 using std::ostream;
74 using std::ostringstream;
75
76
77 ParagraphMetrics::ParagraphMetrics(Paragraph const & par): par_(&par)
78 {
79 }
80
81
82 ParagraphMetrics & ParagraphMetrics::operator=(
83         ParagraphMetrics const & pm)
84 {
85         rows_ = pm.rows_;
86         dim_ = pm.dim_;
87         par_ = pm.par_;
88         return *this;
89 }
90
91
92 size_type ParagraphMetrics::calculateRowSignature(Row const & row)
93 {
94         boost::crc_32_type crc;
95         for (pos_type i = row.pos(); i < row.endpos(); ++i) {
96                 char_type const b[] = { par_->getChar(i) };
97                 crc.process_bytes(b, 1);
98         }
99         return crc.checksum();
100 }
101
102
103 void ParagraphMetrics::updateRowChangeStatus()
104 {
105         size_t const size = rows_.size();
106         row_change_status_.resize(size);
107         row_signature_.resize(size);
108
109         for (size_t i = 0; i != size; ++i) {
110                 // Row signature; has row changed since last update?
111                 size_type const row_sig = calculateRowSignature(rows_[i]);
112                 row_change_status_[i] = row_signature_[i] != row_sig;
113                 row_signature_[i] = row_sig;
114         }
115 }
116
117
118 Row & ParagraphMetrics::getRow(pos_type pos, bool boundary)
119 {
120         BOOST_ASSERT(!rows().empty());
121
122         // If boundary is set we should return the row on which
123         // the character before is inside.
124         if (pos > 0 && boundary)
125                 --pos;
126
127         RowList::iterator rit = rows_.end();
128         RowList::iterator const begin = rows_.begin();
129
130         for (--rit; rit != begin && rit->pos() > pos; --rit)
131                 ;
132
133         return *rit;
134 }
135
136
137 Row const & ParagraphMetrics::getRow(pos_type pos, bool boundary) const
138 {
139         BOOST_ASSERT(!rows().empty());
140
141         // If boundary is set we should return the row on which
142         // the character before is inside.
143         if (pos > 0 && boundary)
144                 --pos;
145
146         RowList::const_iterator rit = rows_.end();
147         RowList::const_iterator const begin = rows_.begin();
148
149         for (--rit; rit != begin && rit->pos() > pos; --rit)
150                 ;
151
152         return *rit;
153 }
154
155
156 size_t ParagraphMetrics::pos2row(pos_type pos) const
157 {
158         BOOST_ASSERT(!rows().empty());
159
160         RowList::const_iterator rit = rows_.end();
161         RowList::const_iterator const begin = rows_.begin();
162
163         for (--rit; rit != begin && rit->pos() > pos; --rit)
164                 ;
165
166         return rit - begin;
167 }
168
169
170 void ParagraphMetrics::dump() const
171 {
172         lyxerr << "Paragraph::dump: rows.size(): " << rows_.size() << endl;
173         for (size_t i = 0; i != rows_.size(); ++i) {
174                 lyxerr << "  row " << i << ":   ";
175                 rows_[i].dump();
176         }
177 }
178
179 int ParagraphMetrics::rightMargin(Buffer const & buffer) const
180 {
181         BufferParams const & params = buffer.params();
182         LyXTextClass const & tclass = params.getLyXTextClass();
183         docstring trmarg = from_utf8(tclass.rightmargin());
184         docstring lrmarg = from_utf8(par_->layout()->rightmargin);
185         frontend::FontMetrics const & fm = theFontMetrics(params.getFont());
186         int const r_margin =
187                 lyx::rightMargin()
188                 + fm.signedWidth(trmarg)
189                 + fm.signedWidth(lrmarg)
190                 * 4 / (par_->getDepth() + 4);
191
192         return r_margin;
193 }
194
195 } // namespace lyx