]> git.lyx.org Git - lyx.git/blob - src/mathed/math_nestinset.C
344d91933bab9c9c4cfcc867350c810e1a20c75f
[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
15 #include "math_arrayinset.h"
16 #include "math_data.h"
17 #include "math_deliminset.h"
18 #include "math_factory.h"
19 #include "math_hullinset.h"
20 #include "math_mathmlstream.h"
21 #include "math_parser.h"
22 #include "math_spaceinset.h"
23 #include "math_support.h"
24 #include "math_mboxinset.h"
25
26 #include "BufferView.h"
27 #include "bufferview_funcs.h"
28 #include "cursor.h"
29 #include "debug.h"
30 #include "dispatchresult.h"
31 #include "funcrequest.h"
32 #include "gettext.h"
33 #include "LColor.h"
34 #include "undo.h"
35
36 #include "support/std_sstream.h"
37 #include "support/lstrings.h"
38
39 #include "frontends/Dialogs.h"
40 #include "frontends/LyXView.h"
41 #include "frontends/Painter.h"
42
43
44 using std::endl;
45 using std::string;
46 using std::istringstream;
47
48
49 MathNestInset::MathNestInset(idx_type nargs)
50         : cells_(nargs), lock_(false)
51 {}
52
53
54 MathInset::idx_type MathNestInset::nargs() const
55 {
56         return cells_.size();
57 }
58
59
60 MathArray & MathNestInset::cell(idx_type i)
61 {
62         return cells_[i];
63 }
64
65
66 MathArray const & MathNestInset::cell(idx_type i) const
67 {
68         return cells_[i];
69 }
70
71
72 void MathNestInset::getCursorPos(CursorSlice const & cur,
73         int & x, int & y) const
74 {
75         MathArray const & ar = cur.cell();
76         x = ar.xo() + ar.pos2x(cur.pos());
77         y = ar.yo();
78         // move cursor visually into empty cells ("blue rectangles");
79         if (cur.cell().empty())
80                 x += 2;
81 }
82
83
84 void MathNestInset::substitute(MathMacro const & m)
85 {
86         for (idx_type i = 0; i < nargs(); ++i)
87                 cell(i).substitute(m);
88 }
89
90
91 void MathNestInset::metrics(MetricsInfo const & mi) const
92 {
93         MetricsInfo m = mi;
94         for (idx_type i = 0; i < nargs(); ++i)
95                 cell(i).metrics(m);
96 }
97
98
99 bool MathNestInset::idxNext(LCursor & cur) const
100 {
101         if (cur.idx() + 1 >= nargs())
102                 return false;
103         ++cur.idx();
104         cur.pos() = 0;
105         return true;
106 }
107
108
109 bool MathNestInset::idxRight(LCursor & cur) const
110 {
111         return idxNext(cur);
112 }
113
114
115 bool MathNestInset::idxPrev(LCursor & cur) const
116 {
117         if (cur.idx() == 0)
118                 return false;
119         --cur.idx();
120         cur.pos() = cur.lastpos();
121         return true;
122 }
123
124
125 bool MathNestInset::idxLeft(LCursor & cur) const
126 {
127         return idxPrev(cur);
128 }
129
130
131 bool MathNestInset::idxFirst(LCursor & cur) const
132 {
133         if (nargs() == 0)
134                 return false;
135         cur.idx() = 0;
136         cur.pos() = 0;
137         return true;
138 }
139
140
141 bool MathNestInset::idxLast(LCursor & cur) const
142 {
143         if (nargs() == 0)
144                 return false;
145         cur.idx() = nargs() - 1;
146         cur.pos() = cur.lastpos();
147         return true;
148 }
149
150
151 bool MathNestInset::idxHome(LCursor & cur) const
152 {
153         if (cur.pos() == 0)
154                 return false;
155         cur.pos() = 0;
156         return true;
157 }
158
159
160 bool MathNestInset::idxEnd(LCursor & cur) const
161 {
162         if (cur.lastpos() == cur.lastpos())
163                 return false;
164         cur.pos() = cur.lastpos();
165         return true;
166 }
167
168
169 void MathNestInset::dump() const
170 {
171         WriteStream os(lyxerr);
172         os << "---------------------------------------------\n";
173         write(os);
174         os << "\n";
175         for (idx_type i = 0; i < nargs(); ++i)
176                 os << cell(i) << "\n";
177         os << "---------------------------------------------\n";
178 }
179
180
181 //void MathNestInset::draw(PainterInfo & pi, int x, int y) const
182 void MathNestInset::draw(PainterInfo &, int, int) const
183 {
184 #if 0
185         if (lock_)
186                 pi.pain.fillRectangle(x, y - ascent(), width(), height(),
187                                         LColor::mathlockbg);
188 #endif
189 }
190
191
192 void MathNestInset::drawSelection(PainterInfo & pi,
193                 idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const
194 {
195         if (idx1 == idx2) {
196                 MathArray const & c = cell(idx1);
197                 int x1 = c.xo() + c.pos2x(pos1);
198                 int y1 = c.yo() - c.ascent();
199                 int x2 = c.xo() + c.pos2x(pos2);
200                 int y2 = c.yo() + c.descent();
201                 pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
202         } else {
203                 for (idx_type i = 0; i < nargs(); ++i) {
204                         if (idxBetween(i, idx1, idx2)) {
205                                 MathArray const & c = cell(i);
206                                 int x1 = c.xo();
207                                 int y1 = c.yo() - c.ascent();
208                                 int x2 = c.xo() + c.width();
209                                 int y2 = c.yo() + c.descent();
210                                 pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
211                         }
212                 }
213         }
214 }
215
216
217 void MathNestInset::validate(LaTeXFeatures & features) const
218 {
219         for (idx_type i = 0; i < nargs(); ++i)
220                 cell(i).validate(features);
221 }
222
223
224 void MathNestInset::replace(ReplaceData & rep)
225 {
226         for (idx_type i = 0; i < nargs(); ++i)
227                 cell(i).replace(rep);
228 }
229
230
231 bool MathNestInset::contains(MathArray const & ar) const
232 {
233         for (idx_type i = 0; i < nargs(); ++i)
234                 if (cell(i).contains(ar))
235                         return true;
236         return false;
237 }
238
239
240 bool MathNestInset::lock() const
241 {
242         return lock_;
243 }
244
245
246 void MathNestInset::lock(bool l)
247 {
248         lock_ = l;
249 }
250
251
252 bool MathNestInset::isActive() const
253 {
254         return nargs() > 0;
255 }
256
257
258 MathArray MathNestInset::glue() const
259 {
260         MathArray ar;
261         for (size_t i = 0; i < nargs(); ++i)
262                 ar.append(cell(i));
263         return ar;
264 }
265
266
267 void MathNestInset::write(WriteStream & os) const
268 {
269         os << '\\' << name().c_str();
270         for (size_t i = 0; i < nargs(); ++i)
271                 os << '{' << cell(i) << '}';
272         if (nargs() == 0)
273                 os.pendingSpace(true);
274         if (lock_ && !os.latex()) {
275                 os << "\\lyxlock";
276                 os.pendingSpace(true);
277         }
278 }
279
280
281 void MathNestInset::normalize(NormalStream & os) const
282 {
283         os << '[' << name().c_str();
284         for (size_t i = 0; i < nargs(); ++i)
285                 os << ' ' << cell(i);
286         os << ']';
287 }
288
289
290 void MathNestInset::notifyCursorLeaves(idx_type idx)
291 {
292         cell(idx).notifyCursorLeaves();
293 }
294
295
296 void MathNestInset::handleFont
297         (LCursor & cur, string const & arg, string const & font)
298 {
299         // this whole function is a hack and won't work for incremental font
300         // changes...
301         recordUndo(cur, Undo::ATOMIC);
302
303         if (cur.inset()->asMathInset()->name() == font)
304                 cur.handleFont(font);
305         else {
306                 cur.handleNest(createMathInset(font));
307                 cur.insert(arg);
308         }
309 }
310
311
312 void MathNestInset::handleFont2(LCursor & cur, string const & arg)
313 {
314         recordUndo(cur, Undo::ATOMIC);
315         LyXFont font;
316         bool b;
317         bv_funcs::string2font(arg, font, b);
318         if (font.color() != LColor::inherit) {
319                 MathAtom at = createMathInset("color");
320                 asArray(lcolor.getGUIName(font.color()), at.nucleus()->cell(0));
321                 cur.handleNest(at, 1);
322         }
323 }
324
325
326 DispatchResult
327 MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd)
328 {
329         lyxerr << "*** MathNestInset: request: " << cmd << std::endl;
330         //lyxerr << "InsetFormulaBase::localDispatch: act: " << cmd.action
331         //      << " arg: '" << cmd.argument
332         //      << "' x: '" << cmd.x
333         //      << " y: '" << cmd.y
334         //      << "' button: " << cmd.button() << endl;
335
336         switch (cmd.action) {
337
338         case LFUN_PASTE:
339                 if (!cmd.argument.empty()) {
340                         MathArray ar;
341                         mathed_parse_cell(ar, cmd.argument);
342                         cur.cell().insert(cur.pos(), ar);
343                         cur.pos() += ar.size();
344                 }
345                 return DispatchResult(true, true);
346 /*
347         case LFUN_PASTE: {
348                 size_t n = 0;
349                 istringstream is(cmd.argument.c_str());
350                 is >> n;
351                 if (was_macro)
352                         cur.macroModeClose();
353                 recordUndo(cur, Undo::ATOMIC);
354                 cur.selPaste(n);
355                 return DispatchResult(true, true);
356         }
357 */
358
359         case LFUN_PASTESELECTION:
360                 return dispatch(cur, FuncRequest(LFUN_PASTE, cur.bv().getClipboard())); 
361
362         case LFUN_MOUSE_PRESS:
363                 if (cmd.button() == mouse_button::button2)
364                         return priv_dispatch(cur, FuncRequest(LFUN_PASTESELECTION));
365                 return DispatchResult(false);
366
367         case LFUN_RIGHTSEL:
368                 cur.selection() = true; // fall through...
369         case LFUN_RIGHT:
370                 return cur.right() ?
371                         DispatchResult(true, true) : DispatchResult(false, FINISHED_RIGHT);
372                 //lyxerr << "calling scroll 20" << endl;
373                 //scroll(&cur.bv(), 20);
374                 // write something to the minibuffer
375                 //cur.bv().owner()->message(cur.info());
376
377         case LFUN_LEFTSEL:
378                 cur.selection() = true; // fall through
379         case LFUN_LEFT:
380                 return cur.left() ?
381                         DispatchResult(true, true) : DispatchResult(false, FINISHED);
382
383         case LFUN_UPSEL:
384                 cur.selection() = true; // fall through
385         case LFUN_UP:
386                 return cur.up() ?
387                         DispatchResult(true, true) : DispatchResult(false, FINISHED_UP);
388
389         case LFUN_DOWNSEL:
390                 cur.selection() = true; // fall through
391         case LFUN_DOWN:
392                 return cur.down() ?
393                         DispatchResult(true, true) : DispatchResult(false, FINISHED_DOWN);
394
395         case LFUN_WORDSEL:
396                 cur.home();
397                 cur.selection() = true;
398                 cur.end();
399                 return DispatchResult(true, true);
400
401         case LFUN_UP_PARAGRAPHSEL:
402         case LFUN_UP_PARAGRAPH:
403         case LFUN_DOWN_PARAGRAPHSEL:
404         case LFUN_DOWN_PARAGRAPH:
405                 return DispatchResult(true, FINISHED);
406
407         case LFUN_HOMESEL:
408         case LFUN_WORDLEFTSEL:
409                 cur.selection() = true; // fall through
410         case LFUN_HOME:
411         case LFUN_WORDLEFT:
412                 return cur.home()
413                         ? DispatchResult(true, true) : DispatchResult(true, FINISHED);
414
415         case LFUN_ENDSEL:
416         case LFUN_WORDRIGHTSEL:
417                 cur.selection() = true; // fall through
418         case LFUN_END:
419         case LFUN_WORDRIGHT:
420                 return cur.end()
421                         ? DispatchResult(true, true) : DispatchResult(false, FINISHED_RIGHT);
422
423         case LFUN_PRIORSEL:
424         case LFUN_PRIOR:
425         case LFUN_BEGINNINGBUFSEL:
426         case LFUN_BEGINNINGBUF:
427                 return DispatchResult(true, FINISHED);
428
429         case LFUN_NEXTSEL:
430         case LFUN_NEXT:
431         case LFUN_ENDBUFSEL:
432         case LFUN_ENDBUF:
433                 return DispatchResult(false, FINISHED_RIGHT);
434
435         case LFUN_CELL_FORWARD:
436                 cur.inset()->idxNext(cur);
437                 return DispatchResult(true, true);
438
439         case LFUN_CELL_BACKWARD:
440                 cur.inset()->idxPrev(cur);
441                 return DispatchResult(true, true);
442
443         case LFUN_DELETE_WORD_BACKWARD:
444         case LFUN_BACKSPACE:
445                 recordUndo(cur, Undo::ATOMIC);
446                 cur.backspace();
447                 return DispatchResult(true, true);
448
449         case LFUN_DELETE_WORD_FORWARD:
450         case LFUN_DELETE:
451                 recordUndo(cur, Undo::ATOMIC);
452                 cur.erase();
453                 return DispatchResult(true, FINISHED);
454
455         case LFUN_ESCAPE:
456                 if (!cur.selection())
457                         return DispatchResult(true, true);
458                 cur.selClear();
459                 return DispatchResult(false);
460
461         case LFUN_INSET_TOGGLE:
462                 cur.lockToggle();
463                 return DispatchResult(true, true);
464
465         case LFUN_SELFINSERT:
466                 if (!cmd.argument.empty()) {
467                         recordUndo(cur, Undo::ATOMIC);
468                         if (cmd.argument.size() == 1) {
469                                 if (cur.interpret(cmd.argument[0]))
470                                         return DispatchResult(true, true);
471                                 else
472                                         return DispatchResult(false, FINISHED_RIGHT);
473                         }
474                         cur.insert(cmd.argument);
475                 }
476                 return DispatchResult(false, FINISHED_RIGHT);
477
478
479 #if 0
480 //
481 // this needs to be incorporated
482 //
483         //lyxerr << "InsetFormulaBase::localDispatch: act: " << cmd.action
484         //      << " arg: '" << cmd.argument
485         //      << "' x: '" << cmd.x
486         //      << " y: '" << cmd.y
487         //      << "' button: " << cmd.button() << endl;
488
489         // delete empty mathbox (LFUN_BACKSPACE and LFUN_DELETE)
490         bool remove_inset = false;
491
492         switch (cmd.action) {
493                 case LFUN_MOUSE_PRESS:
494                         //lyxerr << "Mouse single press" << endl;
495                         return lfunMousePress(cur, cmd);
496                 case LFUN_MOUSE_MOTION:
497                         //lyxerr << "Mouse motion" << endl;
498                         return lfunMouseMotion(cur, cmd);
499                 case LFUN_MOUSE_RELEASE:
500                         //lyxerr << "Mouse single release" << endl;
501                         return lfunMouseRelease(cur, cmd);
502                 case LFUN_MOUSE_DOUBLE:
503                         //lyxerr << "Mouse double" << endl;
504                         return dispatch(cur, FuncRequest(LFUN_WORDSEL));
505                 default:
506                         break;
507         }
508
509         DispatchResult result(true);
510         bool was_macro     = cur.inMacroMode();
511
512         cur.normalize();
513         cur.touch();
514
515         switch (cmd.action) {
516
517         case LFUN_MATH_LIMITS:
518                 recordUndo(cur, Undo::ATOMIC);
519                 cur.dispatch(cmd);
520                 break;
521 #endif
522
523         //    case LFUN_GETXY:
524         //      sprintf(dispatch_buffer, "%d %d",);
525         //      DispatchResult= dispatch_buffer;
526         //      break;
527         case LFUN_SETXY: {
528                 lyxerr << "LFUN_SETXY broken!" << endl;
529                 int x = 0;
530                 int y = 0;
531                 istringstream is(cmd.argument.c_str());
532                 is >> x >> y;
533                 cur.setScreenPos(x, y);
534                 return DispatchResult(true, true);
535         }
536
537         case LFUN_CUT:
538                 recordUndo(cur, Undo::DELETE);
539                 cur.selCut();
540                 return DispatchResult(true, true);
541
542         case LFUN_COPY:
543                 cur.selCopy();
544                 return DispatchResult(true, true);
545
546
547         // Special casing for superscript in case of LyX handling
548         // dead-keys:
549         case LFUN_CIRCUMFLEX:
550                 if (cmd.argument.empty()) {
551                         // do superscript if LyX handles
552                         // deadkeys
553                         recordUndo(cur, Undo::ATOMIC);
554                         cur.script(true);
555                 }
556                 return DispatchResult(true, true);
557
558         case LFUN_UMLAUT:
559         case LFUN_ACUTE:
560         case LFUN_GRAVE:
561         case LFUN_BREVE:
562         case LFUN_DOT:
563         case LFUN_MACRON:
564         case LFUN_CARON:
565         case LFUN_TILDE:
566         case LFUN_CEDILLA:
567         case LFUN_CIRCLE:
568         case LFUN_UNDERDOT:
569         case LFUN_TIE:
570         case LFUN_OGONEK:
571         case LFUN_HUNG_UMLAUT:
572                 return DispatchResult(true, true);
573
574         //  Math fonts
575         case LFUN_FREEFONT_APPLY:
576         case LFUN_FREEFONT_UPDATE:
577                 handleFont2(cur, cmd.argument);
578                 return DispatchResult(true, true);
579
580         case LFUN_BOLD:
581                 handleFont(cur, cmd.argument, "mathbf");
582                 return DispatchResult(true, true);
583         case LFUN_SANS:
584                 handleFont(cur, cmd.argument, "mathsf");
585                 return DispatchResult(true, true);
586         case LFUN_EMPH:
587                 handleFont(cur, cmd.argument, "mathcal");
588                 return DispatchResult(true, true);
589         case LFUN_ROMAN:
590                 handleFont(cur, cmd.argument, "mathrm");
591                 return DispatchResult(true, true);
592         case LFUN_CODE:
593                 handleFont(cur, cmd.argument, "texttt");
594                 return DispatchResult(true, true);
595         case LFUN_FRAK:
596                 handleFont(cur, cmd.argument, "mathfrak");
597                 return DispatchResult(true, true);
598         case LFUN_ITAL:
599                 handleFont(cur, cmd.argument, "mathit");
600                 return DispatchResult(true, true);
601         case LFUN_NOUN:
602                 handleFont(cur, cmd.argument, "mathbb");
603                 return DispatchResult(true, true);
604         //case LFUN_FREEFONT_APPLY:
605                 handleFont(cur, cmd.argument, "textrm");
606                 return DispatchResult(true, true);
607         case LFUN_DEFAULT:
608                 handleFont(cur, cmd.argument, "textnormal");
609                 return DispatchResult(true, true);
610
611         case LFUN_MATH_MODE:
612 #if 1
613                 cur.macroModeClose();
614                 cur.selClearOrDel();
615                 cur.plainInsert(MathAtom(new MathMBoxInset(cur.bv())));
616                 cur.posLeft();
617                 cur.pushLeft(cur.nextAtom().nucleus());
618 #else
619                 if (cur.currentMode() == InsetBase::TEXT_MODE)
620                         cur.niceInsert(MathAtom(new MathHullInset("simple")));
621                 else
622                         handleFont(cur, cmd.argument, "textrm");
623                 //cur.owner()->message(_("math text mode toggled"));
624 #endif
625                 return DispatchResult(true, true);
626
627         case LFUN_MATH_SIZE:
628 #if 0
629                 if (!arg.empty()) {
630                         recordUndo(cur, Undo::ATOMIC);
631                         cur.setSize(arg);
632                 }
633 #endif
634                 return DispatchResult(true, true);
635
636         case LFUN_INSERT_MATRIX: {
637                 recordUndo(cur, Undo::ATOMIC);
638                 unsigned int m = 1;
639                 unsigned int n = 1;
640                 string v_align;
641                 string h_align;
642                 istringstream is(cmd.argument);
643                 is >> m >> n >> v_align >> h_align;
644                 if (m < 1)
645                         m = 1;
646                 if (n < 1)
647                         n = 1;
648                 v_align += 'c';
649                 cur.niceInsert(
650                         MathAtom(new MathArrayInset("array", m, n, v_align[0], h_align)));
651                 return DispatchResult(true, true);
652         }
653
654         case LFUN_MATH_DELIM: {
655                 //lyxerr << "formulabase::LFUN_MATH_DELIM, arg: '" << arg << "'" << endl;
656                 string ls;
657                 string rs = lyx::support::split(cmd.argument, ls, ' ');
658                 // Reasonable default values
659                 if (ls.empty())
660                         ls = '(';
661                 if (rs.empty())
662                         rs = ')';
663                 recordUndo(cur, Undo::ATOMIC);
664                 cur.handleNest(MathAtom(new MathDelimInset(ls, rs)));
665                 return DispatchResult(true, true);
666         }
667
668         case LFUN_SPACE_INSERT:
669         case LFUN_MATH_SPACE:
670                 recordUndo(cur, Undo::ATOMIC);
671                 cur.insert(MathAtom(new MathSpaceInset(",")));
672                 return DispatchResult(true, true);
673
674         case LFUN_UNDO:
675 #warning look here
676                 //cur.bv().owner()->message(_("Invalid action in math mode!"));
677                 return DispatchResult(true, true);
678
679         case LFUN_INSET_ERT:
680                 // interpret this as if a backslash was typed
681                 recordUndo(cur, Undo::ATOMIC);
682                 cur.interpret('\\');
683                 return DispatchResult(true, true);
684
685 #if 0
686         case LFUN_BREAKPARAGRAPH:
687         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
688         case LFUN_BREAKPARAGRAPH_SKIP:
689                 cmd.argument = "\n";
690                 recordUndo(cur, Undo::ATOMIC);
691                 cur.niceInsert(argument);
692                 return DispatchResult(true, true);
693 #endif
694
695 // FIXME: We probably should swap parts of "math-insert" and "self-insert"
696 // handling such that "self-insert" works on "arbitrary stuff" too, and
697 // math-insert only handles special math things like "matrix".
698         case LFUN_INSERT_MATH:
699                 recordUndo(cur, Undo::ATOMIC);
700                 cur.niceInsert(cmd.argument);
701                 return DispatchResult(true, true);
702
703         case LFUN_DIALOG_SHOW:
704                 return DispatchResult(false);
705
706         case LFUN_DIALOG_SHOW_NEW_INSET: {
707                 string const & name = cmd.argument;
708                 string data;
709 #if 0
710                 if (name == "ref") {
711                         RefInset tmp(name);
712                         data = tmp.createDialogStr(name);
713                 }
714 #endif
715                 if (data.empty())
716                         return DispatchResult(false);
717                 cur.bv().owner()->getDialogs().show(name, data, 0);
718                 return DispatchResult(true, true);
719         }
720
721         case LFUN_INSET_APPLY: {
722                 string const name = cmd.getArg(0);
723                 InsetBase * base = cur.bv().owner()->getDialogs().getOpenInset(name);
724
725                 if (base) {
726                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument);
727                         return base->dispatch(cur, fr);
728                 }
729                 MathArray ar;
730                 if (createMathInset_fromDialogStr(cmd.argument, ar)) {
731                         cur.insert(ar);
732                         return DispatchResult(true, true);
733                 }
734                 return DispatchResult(false);
735         }
736
737 #warning look here
738 #if 0
739
740         case LFUN_WORD_REPLACE:
741         case LFUN_WORD_FIND:
742                 return
743                         searchForward(&cur.bv(), cmd.getArg(0), false, false)
744                                 ? DispatchResult(true, true) : DispatchResult(false);
745
746         case LFUN_INSERT_MATH:
747         case LFUN_INSERT_MATRIX:
748         case LFUN_MATH_DELIM: {
749                 MathHullInset * f = new MathHullInset;
750                 if (openNewInset(cur, f)) {
751                         cur.inset()->dispatch(cur, FuncRequest(LFUN_MATH_MUTATE, "simple"));
752                         cur.inset()->dispatch(cur, cmd);
753                 }
754                 return DispatchResult(true, true);
755         }
756
757         cur.normalize();
758         cur.touch();
759
760         BOOST_ASSERT(cur.inMathed());
761
762         if (result.dispatched()) {
763                 revealCodes(cur);
764                 cur.bv().stuffClipboard(cur.grabSelection());
765         } else {
766                 cur.releaseMathCursor();
767                 if (remove_inset)
768                         cur.bv().owner()->dispatch(FuncRequest(LFUN_DELETE));
769         }
770
771         return result;  // original version
772 #endif
773
774         default:
775                 return MathDimInset::priv_dispatch(cur, cmd);
776         }
777 }
778
779
780 void MathNestInset::edit(LCursor & cur, int x, int y)
781 {
782         lyxerr << "Called MathHullInset::edit with '" << x << ' ' << y << "'" << endl;
783         cur.push(this);
784         int idx_min = 0;
785         int dist_min = 1000000;
786         for (idx_type i = 0; i < nargs(); ++i) {
787                 int d = cell(i).dist(x, y);
788                 if (d < dist_min) {
789                         dist_min = d;
790                         idx_min = i;
791                 }
792         }
793         MathArray & ar = cell(idx_min);
794         cur.push(this);
795         cur.idx() = idx_min;
796         cur.pos() = ar.x2pos(x - ar.xo());
797         lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl;
798         if (dist_min == 0) {
799                 // hit inside cell
800                 for (pos_type i = 0, n = ar.size(); i < n; ++i)
801                         if (ar[i]->covers(x, y))
802                                 ar[i].nucleus()->edit(cur, x, y);
803         }
804 }