]> git.lyx.org Git - lyx.git/blob - src/mathed/math_nestinset.C
Part of IU.
[lyx.git] / src / mathed / math_nestinset.C
1 /**
2  * \file math_nestinset.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_nestinset.h"
14 #include "math_cursor.h"
15 #include "math_mathmlstream.h"
16 #include "math_parser.h"
17 #include "BufferView.h"
18 #include "dispatchresult.h"
19 #include "debug.h"
20 #include "funcrequest.h"
21 #include "LColor.h"
22 #include "undo.h"
23
24 #include "frontends/Painter.h"
25
26
27 MathNestInset::MathNestInset(idx_type nargs)
28         : cells_(nargs), lock_(false)
29 {}
30
31
32 MathInset::idx_type MathNestInset::nargs() const
33 {
34         return cells_.size();
35 }
36
37
38 MathArray & MathNestInset::cell(idx_type i)
39 {
40         return cells_[i];
41 }
42
43
44 MathArray const & MathNestInset::cell(idx_type i) const
45 {
46         return cells_[i];
47 }
48
49
50 void MathNestInset::getScreenPos(idx_type idx, pos_type pos, int & x, int & y) const
51 {
52         MathArray const & ar = cell(idx);
53         x = ar.xo() + ar.pos2x(pos);
54         y = ar.yo();
55         // move cursor visually into empty cells ("blue rectangles");
56         if (cell(idx).empty())
57                 x += 2;
58 }
59
60
61 void MathNestInset::substitute(MathMacro const & m)
62 {
63         for (idx_type i = 0; i < nargs(); ++i)
64                 cell(i).substitute(m);
65 }
66
67
68 void MathNestInset::metrics(MetricsInfo const & mi) const
69 {
70         MetricsInfo m = mi;
71         for (idx_type i = 0; i < nargs(); ++i)
72                 cell(i).metrics(m);
73 }
74
75
76 bool MathNestInset::idxNext(LCursor & cur) const
77 {
78         if (cur.idx() + 1 >= nargs())
79                 return false;
80         ++cur.idx();
81         cur.pos() = 0;
82         return true;
83 }
84
85
86 bool MathNestInset::idxRight(LCursor & cur) const
87 {
88         return idxNext(cur);
89 }
90
91
92 bool MathNestInset::idxPrev(LCursor & cur) const
93 {
94         if (cur.idx() == 0)
95                 return false;
96         --cur.idx();
97         cur.pos() = cur.lastpos();
98         return true;
99 }
100
101
102 bool MathNestInset::idxLeft(LCursor & cur) const
103 {
104         return idxPrev(cur);
105 }
106
107
108 bool MathNestInset::idxFirst(LCursor & cur) const
109 {
110         if (nargs() == 0)
111                 return false;
112         cur.idx() = 0;
113         cur.pos() = 0;
114         return true;
115 }
116
117
118 bool MathNestInset::idxLast(LCursor & cur) const
119 {
120         if (nargs() == 0)
121                 return false;
122         cur.idx() = nargs() - 1;
123         cur.pos() = cur.lastpos();
124         return true;
125 }
126
127
128 bool MathNestInset::idxHome(LCursor & cur) const
129 {
130         if (cur.pos() == 0)
131                 return false;
132         cur.pos() = 0;
133         return true;
134 }
135
136
137 bool MathNestInset::idxEnd(LCursor & cur) const
138 {
139         if (cur.lastpos() == cur.lastpos())
140                 return false;
141         cur.pos() = cur.lastpos();
142         return true;
143 }
144
145
146 void MathNestInset::dump() const
147 {
148         WriteStream os(lyxerr);
149         os << "---------------------------------------------\n";
150         write(os);
151         os << "\n";
152         for (idx_type i = 0; i < nargs(); ++i)
153                 os << cell(i) << "\n";
154         os << "---------------------------------------------\n";
155 }
156
157
158 //void MathNestInset::draw(PainterInfo & pi, int x, int y) const
159 void MathNestInset::draw(PainterInfo &, int, int) const
160 {
161 #if 0
162         if (lock_)
163                 pi.pain.fillRectangle(x, y - ascent(), width(), height(),
164                                         LColor::mathlockbg);
165 #endif
166 }
167
168
169 void MathNestInset::drawSelection(PainterInfo & pi,
170                 idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const
171 {
172         if (idx1 == idx2) {
173                 MathArray const & c = cell(idx1);
174                 int x1 = c.xo() + c.pos2x(pos1);
175                 int y1 = c.yo() - c.ascent();
176                 int x2 = c.xo() + c.pos2x(pos2);
177                 int y2 = c.yo() + c.descent();
178                 pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
179         } else {
180                 for (idx_type i = 0; i < nargs(); ++i) {
181                         if (idxBetween(i, idx1, idx2)) {
182                                 MathArray const & c = cell(i);
183                                 int x1 = c.xo();
184                                 int y1 = c.yo() - c.ascent();
185                                 int x2 = c.xo() + c.width();
186                                 int y2 = c.yo() + c.descent();
187                                 pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
188                         }
189                 }
190         }
191 }
192
193
194 void MathNestInset::validate(LaTeXFeatures & features) const
195 {
196         for (idx_type i = 0; i < nargs(); ++i)
197                 cell(i).validate(features);
198 }
199
200
201 void MathNestInset::replace(ReplaceData & rep)
202 {
203         for (idx_type i = 0; i < nargs(); ++i)
204                 cell(i).replace(rep);
205 }
206
207
208 bool MathNestInset::contains(MathArray const & ar) const
209 {
210         for (idx_type i = 0; i < nargs(); ++i)
211                 if (cell(i).contains(ar))
212                         return true;
213         return false;
214 }
215
216
217 bool MathNestInset::editing() const
218 {
219         return inMathed() && mathcursor::isInside(this);
220 }
221
222
223 bool MathNestInset::lock() const
224 {
225         return lock_;
226 }
227
228
229 void MathNestInset::lock(bool l)
230 {
231         lock_ = l;
232 }
233
234
235 bool MathNestInset::isActive() const
236 {
237         return nargs() > 0;
238 }
239
240
241 MathArray MathNestInset::glue() const
242 {
243         MathArray ar;
244         for (size_t i = 0; i < nargs(); ++i)
245                 ar.append(cell(i));
246         return ar;
247 }
248
249
250 void MathNestInset::write(WriteStream & os) const
251 {
252         os << '\\' << name().c_str();
253         for (size_t i = 0; i < nargs(); ++i)
254                 os << '{' << cell(i) << '}';
255         if (nargs() == 0)
256                 os.pendingSpace(true);
257         if (lock_ && !os.latex()) {
258                 os << "\\lyxlock";
259                 os.pendingSpace(true);
260         }
261 }
262
263
264 void MathNestInset::normalize(NormalStream & os) const
265 {
266         os << '[' << name().c_str();
267         for (size_t i = 0; i < nargs(); ++i)
268                 os << ' ' << cell(i);
269         os << ']';
270 }
271
272
273 void MathNestInset::notifyCursorLeaves(idx_type idx)
274 {
275         cell(idx).notifyCursorLeaves();
276 }
277
278
279 DispatchResult
280 MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd)
281 {
282         //lyxerr << "InsetFormulaBase::localDispatch: act: " << cmd.action
283         //      << " arg: '" << cmd.argument
284         //      << "' x: '" << cmd.x
285         //      << " y: '" << cmd.y
286         //      << "' button: " << cmd.button() << endl;
287
288         switch (cmd.action) {
289
290         case LFUN_PASTE: {
291                 MathArray ar;
292                 mathed_parse_cell(ar, cmd.argument);
293                 cur.cell().insert(cur.pos(), ar);
294                 cur.pos() += ar.size();
295                 return DispatchResult(true, true);
296         }
297
298         case LFUN_PASTESELECTION:
299                 return dispatch(cur, FuncRequest(LFUN_PASTE, cur.bv().getClipboard())); 
300
301         case LFUN_MOUSE_PRESS:
302                 if (cmd.button() == mouse_button::button2)
303                         return priv_dispatch(cur, FuncRequest(LFUN_PASTESELECTION));
304                 return DispatchResult(false);
305
306         case LFUN_RIGHTSEL:
307                 cur.selection() = true; // fall through...
308         case LFUN_RIGHT:
309                 return mathcursor::right(cur, cur.selection()) ?
310                         DispatchResult(true, true) : DispatchResult(false, FINISHED_RIGHT);
311                 //lyxerr << "calling scroll 20" << endl;
312                 //scroll(&cur.bv(), 20);
313                 // write something to the minibuffer
314                 //cur.bv().owner()->message(mathcursor::info());
315
316         case LFUN_LEFTSEL:
317                 cur.selection() = true; // fall through
318         case LFUN_LEFT:
319                 return mathcursor::left(cur, cur.selection()) ?
320                         DispatchResult(true, true) : DispatchResult(false, FINISHED);
321
322         case LFUN_UPSEL:
323                 cur.selection() = true; // fall through
324         case LFUN_UP:
325                 return mathcursor::up(cur, cur.selection()) ?
326                         DispatchResult(true, true) : DispatchResult(false, FINISHED_UP);
327
328         case LFUN_DOWNSEL:
329                 cur.selection() = true; // fall through
330         case LFUN_DOWN:
331                 return mathcursor::down(cur, cur.selection()) ?
332                         DispatchResult(true, true) : DispatchResult(false, FINISHED_DOWN);
333
334         case LFUN_SELFINSERT:
335                 if (!cmd.argument.empty()) {
336                         recordUndo(cur, Undo::ATOMIC);
337                         if (cmd.argument.size() == 1) {
338                                 if (mathcursor::interpret(cur, cmd.argument[0]))
339                                         return DispatchResult(true, true);
340                                 else
341                                         return DispatchResult(false, FINISHED_RIGHT);
342                         }
343                         mathcursor::insert(cur, cmd.argument);
344                 }
345                 break;
346
347         default:
348                 return MathInset::priv_dispatch(cur, cmd);
349         }
350 }
351
352
353 void MathNestInset::metricsMarkers(int) const
354 {
355         dim_.wid += 2;
356         dim_.asc += 1;
357 }
358
359
360 void MathNestInset::metricsMarkers2(int) const
361 {
362         dim_.wid += 2;
363         dim_.asc += 1;
364         dim_.des += 1;
365 }
366
367 void MathNestInset::drawMarkers(PainterInfo & pi, int x, int y) const
368 {
369         if (!editing())
370                 return;
371         int t = x + dim_.width() - 1;
372         int d = y + dim_.descent();
373         pi.pain.line(x, d - 3, x, d, LColor::mathframe);
374         pi.pain.line(t, d - 3, t, d, LColor::mathframe);
375         pi.pain.line(x, d, x + 3, d, LColor::mathframe);
376         pi.pain.line(t - 3, d, t, d, LColor::mathframe);
377 }
378
379
380 void MathNestInset::drawMarkers2(PainterInfo & pi, int x, int y) const
381 {
382         if (!editing())
383                 return;
384         drawMarkers(pi, x, y);
385         int t = x + dim_.width() - 1;
386         int a = y - dim_.ascent();
387         pi.pain.line(x, a + 3, x, a, LColor::mathframe);
388         pi.pain.line(t, a + 3, t, a, LColor::mathframe);
389         pi.pain.line(x, a, x + 3, a, LColor::mathframe);
390         pi.pain.line(t - 3, a, t, a, LColor::mathframe);
391 }