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