]> git.lyx.org Git - lyx.git/blob - src/mathed/math_textinset.C
the monster patch
[lyx.git] / src / mathed / math_textinset.C
1 /**
2  * \file math_textinset.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "math_textinset.h"
14 #include "math_data.h"
15 #include "metricsinfo.h"
16 #include "debug.h"
17
18 using std::auto_ptr;
19 using std::endl;
20
21
22 MathTextInset::MathTextInset()
23         : MathNestInset(1)
24 {}
25
26
27 auto_ptr<InsetBase> MathTextInset::clone() const
28 {
29         return auto_ptr<InsetBase>(new MathTextInset(*this));
30 }
31
32
33 MathInset::idx_type MathTextInset::pos2row(pos_type pos) const
34 {
35         for (pos_type r = 0, n = cache_.nargs(); r < n; ++r)
36                 if (pos >= cache_.cellinfo_[r].begin_ && pos <= cache_.cellinfo_[r].end_)
37                         return r;
38         lyxerr << "illegal row for pos " << pos << endl;
39         return 0;
40 }
41
42
43 void MathTextInset::getScreenPos(idx_type /*idx*/, pos_type pos, int & x, int & y) const
44 {
45         idx_type const i = pos2row(pos);
46         pos_type const p = pos - cache_.cellinfo_[i].begin_;
47         cache_.getScreenPos(i, p, x, y);
48         y = cache_.cell(i).yo();
49 }
50
51
52 #if 0
53 bool MathTextInset::idxUpDown2(BufferView & pos, bool up,
54         int /*targetx*/) const
55 {
56         // try to move only one screen row up or down if possible
57         idx_type i = pos2row(pos);
58         //lyxerr << "\nMathTextInset::idxUpDown()  i: " << i << endl;
59         MathGridInset::CellInfo const & cell1 = cache_.cellinfo_[i];
60         int const x = cache_.cell(i).pos2x(pos - cell1.begin_, cell1.glue_);
61         if (up) {
62                 if (i == 0)
63                         return false;
64                 --i;
65         } else {
66                 ++i;
67                 if (i == cache_.nargs())
68                         return false;
69         }
70         MathGridInset::CellInfo const & cell2 = cache_.cellinfo_[i];
71         pos = cell2.begin_ + cache_.cell(i).x2pos(x, cell2.glue_);
72         return true;
73 }
74 #endif
75
76
77 void MathTextInset::metrics(MetricsInfo & mi, Dimension & dim) const
78 {
79         cell(0).metrics(mi);
80
81         // we do our own metrics fiddling
82         // save old positional information
83         int const old_xo = cache_.cell(0).xo();
84         int const old_yo = cache_.cell(0).yo();
85
86         // delete old cache
87         cache_ = MathGridInset(1, 0);
88
89         int spaces  = 0;
90         int safe    = 0;
91         int curr    = 0;
92         int begin   = 0;
93         int safepos = 0;
94         for (size_type i = 0, n = cell(0).size(); i < n; ++i) {
95                 //lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos
96                 //      << " curr: " << curr << " safe: " << safe
97                 //      << " spaces: " << spaces << endl;
98
99                 //   0      1      2      3       4      5      6
100                 // <char> <char> <char> <space> <char> <char> <char>
101                 // ................... <safe>
102                 //                      ..........................<curr>
103                 // ....................<safepos>
104
105                 // Special handling of spaces. We reached a safe position for breaking.
106                 char const c = cell(0)[i]->getChar();
107                 if (c == ' ') {
108                         //lyxerr << "reached safe pos" << endl;
109                         // we don't count the space into the safe pos
110                         safe += curr;
111                         // we reset to this safepos if the next chunk does not fit
112                         safepos = i;
113                         ++spaces;
114                         // restart chunk with size of the space
115                         curr = cell(0)[i].width_;
116                         continue;
117                 }
118
119                 if (c != '\n') {
120                         // This is a regular char. Go on if we either don't care for
121                         // the width limit or have not reached that limit.
122                         curr += cell(0)[i].width_;
123                         if (curr + safe <= mi.base.textwidth)
124                                 continue;
125                 }
126
127                 // We passed the limit. Create a row entry.
128                 //lyxerr << "passed limit" << endl;
129                 cache_.appendRow();
130                 MathArray & ar = cache_.cell(cache_.nargs() - 1);
131                 MathGridInset::CellInfo & row = cache_.cellinfo_.back();
132                 if (c == '\n') {
133                         // we are here because we hit a hard newline
134                         row.begin_ = begin;
135                         row.end_   = i + 1;
136                         begin      = i + 1;    // next chunk starts after the newline
137                         spaces     = 0;
138                 } else if (spaces) {
139                         // but we had a space break before this position.
140                         // so retreat to this position
141                         //lyxerr << "... but had safe pos." << endl;
142                         row.begin_ = begin;
143                         row.end_   = safepos;  // this is position of the safe space
144                         i          = safepos;  // i gets incremented at end of loop
145                         begin      = i + 1;    // next chunk starts after the space
146                         spaces     = 0;
147                 } else {
148                         // This item is too large and it is the only one.
149                         // We have no choice but to produce an overfull box.
150                         lyxerr << "... without safe pos" << endl;
151                         row.begin_ = begin;
152                         row.end_   = i + 1;
153                         begin      = i + 1;
154                 }
155                 ar = MathArray(cell(0).begin() + row.begin_, cell(0).begin() + row.end_);
156                 //lyxerr << "line: " << ar << endl;
157                 // in any case, start the new row with empty boxes
158                 curr = 0;
159                 safe = 0;
160         }
161         // last row: put in everything else
162         cache_.appendRow();
163         MathArray & ar = cache_.cell(cache_.nargs() - 1);
164         MathGridInset::CellInfo & row = cache_.cellinfo_.back();
165         row.begin_ = begin;
166         row.end_   = cell(0).size();
167         ar = MathArray(cell(0).begin() + row.begin_, cell(0).begin() + row.end_);
168         //lyxerr << "last line: " << ar.data() << endl;
169
170         // what to report?
171         cache_.metrics(mi, dim_);
172         //lyxerr << "outer dim: " << dim_ << endl;
173
174         // reset position cache
175         for (idx_type i = 0; i < cache_.nargs(); ++i)
176                 cache_.cell(i).setXY(old_xo, old_yo);
177
178         dim = dim_;
179 }
180
181
182 void MathTextInset::draw(PainterInfo & pi, int x, int y) const
183 {
184         cache_.draw(pi, x + 1, y);
185 }
186
187
188 void MathTextInset::drawSelection(PainterInfo & pi,
189                 idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const
190 {
191         cache_.drawSelection(pi, idx1, pos1, idx2, pos2);
192 }