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