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