]> git.lyx.org Git - features.git/blob - src/mathed/formulabase.C
static_cast-based key/mouse-state. Kill insetKeyPress.
[features.git] / src / mathed / formulabase.C
1 /*
2 *  File:        formulabase.C
3 *  Purpose:     Implementation of common parts of the LyX  math insets
4 *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5 *  Created:     January 1996
6 *
7 *  Copyright: 1996-1998 Alejandro Aguilar Sierra
8 *
9 *  Version: 0.4, Lyx project.
10 *
11 *   You are free to use and modify this code under the terms of
12 *   the GNU General Public Licence version 2 or later.
13 */
14
15 #include <config.h>
16 #include <fstream>
17
18 #include "Lsstream.h"
19 #include "support/LAssert.h"
20
21 #ifdef __GNUG__
22 #pragma implementation
23 #endif
24
25 #include "formula.h"
26 #include "formulamacro.h"
27 #include "commandtags.h"
28 #include "BufferView.h"
29 #include "lyxtext.h"
30 #include "lyxfunc.h"
31 #include "gettext.h"
32 #include "LaTeXFeatures.h"
33 #include "debug.h"
34 #include "math_support.h"
35 #include "support/lstrings.h"
36 #include "frontends/LyXView.h"
37 #include "frontends/font_metrics.h"
38 #include "frontends/mouse_state.h"
39 #include "Lsstream.h"
40 #include "math_arrayinset.h"
41 #include "math_charinset.h"
42 #include "math_cursor.h"
43 #include "math_factory.h"
44 #include "math_hullinset.h"
45 #include "math_iterator.h"
46 #include "math_macrotable.h"
47 #include "math_parser.h"
48 #include "math_pos.h"
49 #include "math_spaceinset.h"
50 #include "undo_funcs.h"
51 #include "textpainter.h"
52 #include "frontends/Dialogs.h"
53 #include "intl.h"
54
55 using std::endl;
56 using std::ostream;
57 using std::vector;
58
59 MathCursor * mathcursor = 0;
60
61
62 namespace {
63
64
65 // local global
66 int first_x;
67 int first_y;
68
69
70 bool openNewInset(BufferView * bv, UpdatableInset * new_inset)
71 {
72         if (!bv->insertInset(new_inset)) {
73                 delete new_inset;
74                 return false;
75         }
76         new_inset->edit(bv, 0, 0, mouse_button::none);
77         return true;
78 }
79
80
81 } // namespace anon
82
83
84
85 InsetFormulaBase::InsetFormulaBase()
86         : view_(0), font_(), xo_(0), yo_(0)
87 {
88         // This is needed as long the math parser is not re-entrant
89         MathMacroTable::builtinMacros();
90         //lyxerr << "sizeof MathInset: " << sizeof(MathInset) << "\n";
91         //lyxerr << "sizeof(MathMetricsInfo): " << sizeof(MathMetricsInfo) << "\n";
92         //lyxerr << "sizeof(MathCharInset): " << sizeof(MathCharInset) << "\n";
93 }
94
95
96 // simply scrap this function if you want
97 void InsetFormulaBase::mutateToText()
98 {
99 #if 0
100         // translate to latex
101         ostringstream os;
102         latex(NULL, os, false, false);
103         string str = os.str();
104
105         // insert this text
106         LyXText * lt = view_->getLyXText();
107         string::const_iterator cit = str.begin();
108         string::const_iterator end = str.end();
109         for (; cit != end; ++cit)
110                 view_->owner()->getIntl()->getTrans().TranslateAndInsert(*cit, lt);
111
112         // remove ourselves
113         //view_->owner()->getLyXFunc()->dispatch(LFUN_ESCAPE);
114 #endif
115 }
116
117
118 // Check if uses AMS macros
119 void InsetFormulaBase::validate(LaTeXFeatures &) const
120 {}
121
122
123 void InsetFormulaBase::metrics(BufferView * bv, LyXFont const & f) const
124 {
125         font_ = f;
126         metrics(bv);
127 }
128
129
130 void InsetFormulaBase::metrics(BufferView * bv) const
131 {
132         if (bv)
133                 view_ = bv;
134         MathMetricsInfo mi(view_, font_, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
135         par()->metrics(mi);
136 }
137
138
139 string const InsetFormulaBase::editMessage() const
140 {
141         return _("Math editor mode");
142 }
143
144
145 void InsetFormulaBase::edit(BufferView * bv, int x, int y, mouse_button::state)
146 {
147         if (!bv->lockInset(this))
148                 lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl;
149         delete mathcursor;
150         mathcursor = new MathCursor(this, true);
151         metrics(bv);
152         mathcursor->setPos(x, y);
153         //lyxerr << "setting pos to " << x << "," << y << "\n";
154
155         // if that is removed, we won't get the magenta box when entering an
156         // inset for the first time
157         bv->updateInset(this, false);
158 }
159
160
161 void InsetFormulaBase::edit(BufferView * bv, bool front)
162 {
163         if (!bv->lockInset(this))
164                 lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl;
165         delete mathcursor;
166         mathcursor = new MathCursor(this, front);
167         metrics(bv);
168         bv->updateInset(this, false);
169 }
170
171
172 void InsetFormulaBase::handleFont
173         (BufferView * bv, string const & arg, MathTextCodes t)
174 {
175         if (mathcursor->selection()) {
176                 bv->lockedInsetStoreUndo(Undo::EDIT);
177                 updateLocal(bv, true);
178         }
179         mathcursor->handleFont(t);
180         for (string::const_iterator it = arg.begin(); it != arg.end(); ++it)
181                 mathcursor->insert(*it);
182         updateLocal(bv, false);
183 }
184
185
186 void InsetFormulaBase::insetUnlock(BufferView * bv)
187 {
188         if (mathcursor) {
189                 if (mathcursor->inMacroMode()) {
190                         mathcursor->macroModeClose();
191                         updateLocal(bv, true);
192                 }
193                 delete mathcursor;
194                 mathcursor = 0;
195         }
196         bv->updateInset(this, false);
197 }
198
199
200 void InsetFormulaBase::getCursorPos(BufferView *, int & x, int & y) const
201 {
202         mathcursor->getPos(x, y);
203         //x -= xo_;
204         y -= yo_;
205         //lyxerr << "getCursorPos: " << x << " " << y << "\n";
206 }
207
208
209 void InsetFormulaBase::toggleInsetCursor(BufferView * bv)
210 {
211         if (!mathcursor)
212                 return;
213
214         if (isCursorVisible())
215                 bv->hideLockedInsetCursor();
216         else {
217                 metrics(bv);
218                 int x;
219                 int y;
220                 mathcursor->getPos(x, y);
221                 y -= yo_;
222                 int asc = 0;
223                 int des = 0;
224                 math_font_max_dim(font_, asc, des);
225                 bv->showLockedInsetCursor(x, y, asc, des);
226                 //lyxerr << "toggleInsetCursor: " << x << " " << y << "\n";
227         }
228
229         toggleCursorVisible();
230 }
231
232
233 void InsetFormulaBase::showInsetCursor(BufferView * bv, bool)
234 {
235         if (isCursorVisible())
236                 return;
237         if (mathcursor) {
238                 metrics(bv);
239                 int x;
240                 int y;
241                 mathcursor->getPos(x, y);
242                 y -= yo_;
243                 int asc = 0;
244                 int des = 0;
245                 math_font_max_dim(font_, asc, des);
246                 bv->fitLockedInsetCursor(x, y, asc, des);
247                 //lyxerr << "showInsetCursor: x: " << x << " y: " << y << " yo: " << yo_ << "\n";
248         }
249         toggleInsetCursor(bv);
250 }
251
252
253 void InsetFormulaBase::hideInsetCursor(BufferView * bv)
254 {
255         if (isCursorVisible())
256                 toggleInsetCursor(bv);
257 }
258
259
260 void InsetFormulaBase::toggleInsetSelection(BufferView * bv)
261 {
262         if (mathcursor)
263                 bv->updateInset(this, false);
264 }
265
266
267 vector<string> const InsetFormulaBase::getLabelList() const
268 {
269   return vector<string>();
270 }
271
272
273 void InsetFormulaBase::updateLocal(BufferView * bv, bool dirty)
274 {
275         metrics(bv);
276         bv->updateInset(this, dirty);
277 }
278
279
280 bool InsetFormulaBase::insetButtonRelease(BufferView * bv,
281                                           int /*x*/, int /*y*/, mouse_button::state button)
282 {
283         //lyxerr << "insetButtonRelease: " << x << " " << y << "\n";
284
285         if (!mathcursor)
286                 return false;
287         hideInsetCursor(bv);
288         showInsetCursor(bv);
289         bv->updateInset(this, false);
290
291         if (button == mouse_button::button3) {
292                 // launch math panel for right mouse button
293                 bv->owner()->getDialogs()->showMathPanel();
294                 return true;
295         }
296         return false;
297 }
298
299
300 void InsetFormulaBase::insetButtonPress(BufferView * bv,
301                                         int x, int y, mouse_button::state button)
302 {
303         //lyxerr << "insetButtonPress: "
304         //      << x << " " << y << " but: " << button << "\n";
305 #if 0
306         switch (button) {
307                 default:
308                 case 1:
309                         // left click
310                         delete mathcursor;
311                         mathcursor = new MathCursor(this, x == 0);
312                         metrics(bv);
313                         first_x = x;
314                         first_y = y;
315                         mathcursor->selClear();
316                         mathcursor->setPos(x + xo_, y + yo_);
317                         break;
318 /*
319                 case 2:
320                         lyxerr << "insetButtonPress: 2\n";
321                         // insert stuff
322                         if (mathcursor) {
323                                 bv->lockedInsetStoreUndo(Undo::EDIT);
324                                 MathArray ar;
325                                 mathcursor->selGet(ar);
326                                 mathcursor->setPos(x + xo_, y + yo_);
327                                 string sel =
328                                         bv->getLyXText()->selectionAsString(bv->buffer(), false);
329                                 mathed_parse_cell(ar, sel);
330                                 mathcursor->insert(ar);
331                         }
332                         break;
333 */
334                 case 3:
335                         // launch math panel for right mouse button
336                         bv->owner()->getDialogs()->showMathPanel();
337                         break;
338         }
339 #else
340         if (button == mouse_button::button1 || !mathcursor) {
341                 delete mathcursor;
342                 mathcursor = new MathCursor(this, x == 0);
343                 metrics(bv);
344                 first_x = x;
345                 first_y = y;
346                 mathcursor->selClear();
347                 mathcursor->setPos(x + xo_, y + yo_);
348         }
349 #if 0
350 #warning Never launch a Dialog on "Press" event ONLY on "Release" event!
351         if (button == 3) {
352                 // launch math panel for right mouse button
353                 bv->owner()->getDialogs()->showMathPanel();
354         }
355 #endif
356 #endif
357         bv->updateInset(this, false);
358 }
359
360
361 void InsetFormulaBase::insetMotionNotify(BufferView * bv,
362         int x, int y, mouse_button::state)
363 {
364         if (!mathcursor)
365                 return;
366
367         if (abs(x - first_x) < 2 && abs(y - first_y) < 2) {
368                 //lyxerr << "insetMotionNotify: ignored\n";
369                 return;
370         }
371         first_x = x;
372         first_y = y;
373
374         if (!mathcursor->selection())
375                 mathcursor->selStart();
376
377         //lyxerr << "insetMotionNotify: " << x + xo_ << ' ' << y + yo_
378         //      << ' ' << button << "\n";
379         hideInsetCursor(bv);
380         mathcursor->setPos(x + xo_, y + yo_);
381         showInsetCursor(bv);
382         bv->updateInset(this, false);
383 }
384
385
386 UpdatableInset::RESULT
387 InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
388                             string const & arg)
389 {
390         //lyxerr << "InsetFormulaBase::localDispatch: act: " << action
391         //      << " arg: '" << arg << "' cursor: " << mathcursor << "\n";
392
393         if (!mathcursor)
394                 return UNDISPATCHED;
395
396         RESULT result      = DISPATCHED;
397         bool sel           = false;
398         bool was_macro     = mathcursor->inMacroMode();
399         bool was_selection = mathcursor->selection();
400
401         hideInsetCursor(bv);
402
403         mathcursor->normalize();
404         mathcursor->touch();
405
406         switch (action) {
407
408                 // --- Cursor Movements ---------------------------------------------
409
410         case LFUN_RIGHTSEL:
411                 sel = true; // fall through...
412
413         case LFUN_RIGHT:
414                 result = mathcursor->right(sel) ? DISPATCHED : FINISHED_RIGHT;
415                 //lyxerr << "calling scroll 20\n";
416                 //scroll(bv, 20);
417                 updateLocal(bv, false);
418                 // write something to the minibuffer
419                 //bv->owner()->message(mathcursor->info());
420                 break;
421
422
423         case LFUN_LEFTSEL:
424                 sel = true; // fall through
425
426         case LFUN_LEFT:
427                 result = mathcursor->left(sel) ? DISPATCHED : FINISHED;
428                 updateLocal(bv, false);
429                 break;
430
431
432         case LFUN_UPSEL:
433                 sel = true;
434
435         case LFUN_UP:
436                 result = mathcursor->up(sel) ? DISPATCHED : FINISHED_UP;
437                 updateLocal(bv, false);
438                 break;
439
440
441         case LFUN_DOWNSEL:
442                 sel = true;
443
444         case LFUN_DOWN:
445                 result = mathcursor->down(sel) ? DISPATCHED : FINISHED_DOWN;
446                 updateLocal(bv, false);
447                 break;
448
449         case LFUN_HOMESEL:
450                 sel = true;
451
452         case LFUN_HOME:
453                 mathcursor->home(sel);
454                 updateLocal(bv, false);
455                 break;
456
457         case LFUN_ENDSEL:
458                 sel = true;
459
460         case LFUN_END:
461                 mathcursor->end(sel);
462                 updateLocal(bv, false);
463                 break;
464
465         case LFUN_DELETE_LINE_FORWARD:
466                 bv->lockedInsetStoreUndo(Undo::DELETE);
467                 mathcursor->delLine();
468                 updateLocal(bv, true);
469                 break;
470
471         case LFUN_TAB:
472                 mathcursor->idxNext();
473                 updateLocal(bv, false);
474                 break;
475
476         case LFUN_SHIFT_TAB:
477                 mathcursor->idxPrev();
478                 updateLocal(bv, false);
479                 break;
480
481         case LFUN_TABINSERT:
482                 bv->lockedInsetStoreUndo(Undo::EDIT);
483                 mathcursor->splitCell();
484                 updateLocal(bv, true);
485                 break;
486
487         case LFUN_DELETE_WORD_BACKWARD:
488         case LFUN_BACKSPACE:
489                 bv->lockedInsetStoreUndo(Undo::DELETE);
490                 mathcursor->backspace();
491                 bv->updateInset(this, true);
492                 break;
493
494         case LFUN_DELETE_WORD_FORWARD:
495         case LFUN_DELETE:
496                 bv->lockedInsetStoreUndo(Undo::DELETE);
497                 mathcursor->erase();
498                 bv->updateInset(this, true);
499                 break;
500
501         //    case LFUN_GETXY:
502         //      sprintf(dispatch_buffer, "%d %d",);
503         //      dispatch_result = dispatch_buffer;
504         //      break;
505         case LFUN_SETXY: {
506                 lyxerr << "LFUN_SETXY broken!\n";
507                 int x = 0;
508                 int y = 0;
509                 istringstream is(arg.c_str());
510                 is >> x >> y;
511                 mathcursor->setPos(x, y);
512                 updateLocal(bv, false);
513                 break;
514         }
515
516         case LFUN_PASTE:
517                 if (was_macro)
518                         mathcursor->macroModeClose();
519                 bv->lockedInsetStoreUndo(Undo::EDIT);
520                 mathcursor->selPaste();
521                 updateLocal(bv, true);
522                 break;
523
524         case LFUN_CUT:
525                 bv->lockedInsetStoreUndo(Undo::DELETE);
526                 mathcursor->selCut();
527                 updateLocal(bv, true);
528                 break;
529
530         case LFUN_COPY:
531                 mathcursor->selCopy();
532                 break;
533
534         case LFUN_WORDRIGHTSEL:
535         case LFUN_WORDLEFTSEL:
536                 break;
537
538         // Special casing for superscript in case of LyX handling
539         // dead-keys:
540         case LFUN_CIRCUMFLEX:
541                 if (arg.empty()) {
542                         // do superscript if LyX handles
543                         // deadkeys
544                         bv->lockedInsetStoreUndo(Undo::EDIT);
545                         mathcursor->script(true);
546                         updateLocal(bv, true);
547                 }
548                 break;
549         case LFUN_UMLAUT:
550         case LFUN_ACUTE:
551         case LFUN_GRAVE:
552         case LFUN_BREVE:
553         case LFUN_DOT:
554         case LFUN_MACRON:
555         case LFUN_CARON:
556         case LFUN_TILDE:
557         case LFUN_CEDILLA:
558         case LFUN_CIRCLE:
559         case LFUN_UNDERDOT:
560         case LFUN_TIE:
561         case LFUN_OGONEK:
562         case LFUN_HUNG_UMLAUT:
563                 break;
564
565         //  Math fonts
566         case LFUN_GREEK_TOGGLE: handleFont(bv, arg, LM_TC_GREEK); break;
567         case LFUN_BOLD:         handleFont(bv, arg, LM_TC_BF); break;
568         case LFUN_SANS:         handleFont(bv, arg, LM_TC_SF); break;
569         case LFUN_EMPH:         handleFont(bv, arg, LM_TC_CAL); break;
570         case LFUN_ROMAN:        handleFont(bv, arg, LM_TC_RM); break;
571         case LFUN_CODE:         handleFont(bv, arg, LM_TC_TT); break;
572         case LFUN_FRAK:         handleFont(bv, arg, LM_TC_EUFRAK); break;
573         case LFUN_ITAL:         handleFont(bv, arg, LM_TC_IT); break;
574         case LFUN_NOUN:         handleFont(bv, arg, LM_TC_BB); break;
575         case LFUN_DEFAULT:      handleFont(bv, arg, LM_TC_VAR); break;
576         case LFUN_FREE:         handleFont(bv, arg, LM_TC_TEXTRM); break;
577
578         case LFUN_GREEK:
579                 handleFont(bv, arg, LM_TC_GREEK1);
580                 if (arg.size())
581                         mathcursor->interpret(arg);
582                 break;
583
584         case LFUN_MATH_MODE:
585 #if 1
586                 handleFont(bv, arg, LM_TC_TEXTRM);
587 #endif
588
589 #if 0
590                 mathcursor->niceInsert(MathAtom(new MathHullInset(LM_OT_SIMPLE)));
591                 updateLocal(bv, true);
592 #endif
593
594                 //bv->owner()->message(_("math text mode toggled"));
595                 break;
596
597         case LFUN_MATH_LIMITS:
598                 bv->lockedInsetStoreUndo(Undo::EDIT);
599                 if (mathcursor->toggleLimits())
600                         updateLocal(bv, true);
601                 break;
602
603         case LFUN_MATH_SIZE:
604 #if 0
605                 if (!arg.empty()) {
606                         bv->lockedInsetStoreUndo(Undo::EDIT);
607                         mathcursor->setSize(arg);
608                         updateLocal(bv, true);
609                 }
610 #endif
611                 break;
612
613         case LFUN_INSERT_MATRIX:
614                 if (!arg.empty()) {
615                         bv->lockedInsetStoreUndo(Undo::EDIT);
616                         mathcursor->interpret("matrix " + arg);
617                         updateLocal(bv, true);
618                 }
619                 break;
620
621         case LFUN_SUPERSCRIPT:
622         case LFUN_SUBSCRIPT:
623         {
624                 bv->lockedInsetStoreUndo(Undo::EDIT);
625                 mathcursor->script(action == LFUN_SUPERSCRIPT);
626                 updateLocal(bv, true);
627                 break;
628         }
629
630         case LFUN_MATH_DELIM:
631         {
632                 //lyxerr << "formulabase::LFUN_MATH_DELIM, arg: '" << arg << "'\n";
633                 string ls;
634                 string rs = split(arg, ls, ' ');
635                 // Reasonable default values
636                 if (ls.empty())
637                         ls = '(';
638                 if (rs.empty())
639                         rs = ')';
640
641                 bv->lockedInsetStoreUndo(Undo::EDIT);
642                 mathcursor->handleDelim(ls, rs);
643                 updateLocal(bv, true);
644                 break;
645         }
646
647         case LFUN_PROTECTEDSPACE:
648         case LFUN_MATH_SPACE:
649                 bv->lockedInsetStoreUndo(Undo::EDIT);
650                 mathcursor->insert(MathAtom(new MathSpaceInset(1)));
651                 updateLocal(bv, true);
652                 break;
653
654         case LFUN_UNDO:
655                 bv->owner()->message(_("Invalid action in math mode!"));
656                 break;
657
658
659         case LFUN_MATH_HALIGN:
660         case LFUN_MATH_VALIGN:
661         case LFUN_MATH_ROW_INSERT:
662         case LFUN_MATH_ROW_DELETE:
663         case LFUN_MATH_COLUMN_INSERT:
664         case LFUN_MATH_COLUMN_DELETE:
665         {
666                 MathInset::idx_type idx = 0;
667                 MathGridInset * p = mathcursor ? mathcursor->enclosingGrid(idx) : 0;
668                 if (p) {
669                         mathcursor->popToEnclosingGrid();
670                         bv->lockedInsetStoreUndo(Undo::EDIT);
671                         char align = arg.size() ? arg[0] : 'c';
672                         switch (action) {
673                                 case LFUN_MATH_HALIGN: p->halign(align, p->col(idx)); break;
674                                 case LFUN_MATH_VALIGN: p->valign(align); break;
675                                 case LFUN_MATH_ROW_INSERT: p->addRow(p->row(idx)); break;
676                                 case LFUN_MATH_ROW_DELETE: p->delRow(p->row(idx)); break;
677                                 case LFUN_MATH_COLUMN_INSERT: p->addCol(p->col(idx)); break;
678                                 case LFUN_MATH_COLUMN_DELETE: p->delCol(p->col(idx)); break;
679                                 default: ;
680                         }
681                         updateLocal(bv, true);
682                 }
683                 break;
684         }
685
686         case LFUN_EXEC_COMMAND:
687                 result = UNDISPATCHED;
688                 break;
689
690         case LFUN_BREAKPARAGRAPH:
691         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
692                 //lyxerr << "LFUN ignored\n";
693                 break;
694
695         case LFUN_INSET_ERT:
696                 // interpret this as if a backslash was typed
697                 bv->lockedInsetStoreUndo(Undo::EDIT);
698                 mathcursor->interpret('\\');
699                 updateLocal(bv, true);
700                 break;
701
702         case -1:
703         case LFUN_INSERT_MATH:
704         case LFUN_SELFINSERT:
705                 if (!arg.empty()) {
706                         bv->lockedInsetStoreUndo(Undo::EDIT);
707                         if (arg.size() == 1)
708                                 result = mathcursor->interpret(arg[0]) ? DISPATCHED : FINISHED_RIGHT;
709                         else
710                                 result = mathcursor->interpret(arg) ? DISPATCHED : FINISHED_RIGHT;
711                         updateLocal(bv, true);
712                 }
713                 break;
714
715         case LFUN_MATH_PANEL:
716                 result = UNDISPATCHED;
717                 break;
718
719         case LFUN_ESCAPE:
720                 if (mathcursor->selection())
721                         mathcursor->selClear();
722                 else
723                         result = UNDISPATCHED;
724                 break;
725
726         default:
727                 result = UNDISPATCHED;
728         }
729
730         mathcursor->normalize();
731         mathcursor->touch();
732
733         lyx::Assert(mathcursor);
734
735         if (mathcursor->selection() || was_selection)
736                 toggleInsetSelection(bv);
737
738         if (result == DISPATCHED || result == DISPATCHED_NOUPDATE ||
739             result == UNDISPATCHED)
740                 showInsetCursor(bv);
741         else
742                 bv->unlockInset(this);
743
744         revealCodes(bv);
745
746         return result;  // original version
747 }
748
749
750 void InsetFormulaBase::revealCodes(BufferView * /*bv*/) const
751 {
752         if (!mathcursor)
753                 return;
754 #if 0
755         // write something to the minibuffer
756         // translate to latex
757         mathcursor->markInsert();
758         ostringstream os;
759         write(NULL, os);
760         string str = os.str();
761         mathcursor->markErase();
762         string::size_type pos = 0;
763         string res;
764         for (string::iterator it = str.begin(); it != str.end(); ++it) {
765                 if (*it == '\n')
766                         res += ' ';
767                 else if (*it == '\0') {
768                         res += "  -X-  ";
769                         pos = it - str.begin();
770                 }
771                 else
772                         res += *it;
773         }
774         if (pos > 30)
775                 res = res.substr(pos - 30);
776         if (res.size() > 60)
777                 res = res.substr(0, 60);
778         bv->owner()->message(res);
779 #endif
780 }
781
782
783 Inset::Code InsetFormulaBase::lyxCode() const
784 {
785         return Inset::MATH_CODE;
786 }
787
788
789 int InsetFormulaBase::ylow() const
790 {
791         return yo_ - ascent(view_, font_);
792 }
793
794
795 int InsetFormulaBase::yhigh() const
796 {
797         return yo_ + descent(view_, font_);
798 }
799
800
801 int InsetFormulaBase::xlow() const
802 {
803         return xo_;
804 }
805
806
807 int InsetFormulaBase::xhigh() const
808 {
809         return xo_ + width(view_, font_);
810 }
811
812
813 /////////////////////////////////////////////////////////////////////
814
815
816 bool InsetFormulaBase::searchForward(BufferView * bv, string const & str,
817                                      bool, bool)
818 {
819 #ifdef WITH_WARNINGS
820 #warning pretty ugly
821 #endif
822         static InsetFormulaBase * lastformula = 0;
823         static MathIterator current = MathIterator(ibegin(par().nucleus()));
824         static MathArray ar;
825         static string laststr;
826
827         if (lastformula != this || laststr != str) {
828                 //lyxerr << "reset lastformula to " << this << "\n";
829                 lastformula = this;
830                 laststr = str;
831                 current = ibegin(par().nucleus());
832                 ar.clear();
833                 mathed_parse_cell(ar, str);
834         } else {
835                 ++current;
836         }
837         //lyxerr << "searching '" << str << "' in " << this << ar << endl;
838
839         for (MathIterator it = current; it != iend(par().nucleus()); ++it) {
840                 if (it.cell().matchpart(ar, it.position().pos_)) {
841                         mathcursor->setSelection(it.cursor(), ar.size());
842                         current = it;
843                         it.jump(ar.size());
844                         // I guess some of the following can go
845                         bv->toggleSelection(true);
846                         hideInsetCursor(bv);
847                         updateLocal(bv, true);
848                         showInsetCursor(bv);
849                         metrics(bv);
850                         return true;
851                 }
852         }
853
854         //lyxerr << "not found!\n";
855         lastformula = 0;
856         // we have to unlock ourself in this function by default!
857         // don't ask me why...
858         bv->unlockInset(this);
859         return false;
860 }
861
862
863 bool InsetFormulaBase::searchBackward(BufferView * bv, string const & what,
864                                       bool a, bool b)
865 {
866         lyxerr << "searching backward not implemented in mathed" << endl;
867         return searchForward(bv, what, a, b);
868 }
869
870
871 /////////////////////////////////////////////////////////////////////
872
873
874 void mathDispatchCreation(BufferView * bv, string const & arg, bool display)
875 {
876         if (bv->available()) {
877                 // use selection if available..
878                 //string sel;
879                 //if (action == LFUN_MATH_IMPORT_SELECTION)
880                 //      sel = "";
881                 //else
882
883                 string sel = bv->getLyXText()->selectionAsString(bv->buffer(), false);
884
885                 InsetFormulaBase * f;
886                 if (sel.empty()) {
887                         f = new InsetFormula;
888                         if (openNewInset(bv, f)) {
889                                 // don't do that also for LFUN_MATH_MODE unless you want end up with
890                                 // always changing to mathrm when opening an inlined inset
891                                 // -- I really hate "LyXfunc overloading"...
892                                 if (display)
893                                         f->localDispatch(bv, LFUN_MATH_DISPLAY, string());
894                                 f->localDispatch(bv, LFUN_INSERT_MATH, arg);
895                         }
896                 } else {
897                         // create a macro if we see "\\newcommand" somewhere, and an ordinary
898                         // formula otherwise
899                         if (sel.find("\\newcommand") == string::npos &&
900                                   sel.find("\\def") == string::npos)
901                                 f = new InsetFormula(sel);
902                         else {
903                                 string name;
904                                 if (!mathed_parse_macro(name, sel))
905                                         return;
906                                 f = new InsetFormulaMacro(sel);
907                         }
908                         bv->getLyXText()->cutSelection(bv);
909                         openNewInset(bv, f);
910                 }
911         }
912         bv->owner()->getLyXFunc()->setMessage(N_("Math editor mode"));
913 }
914
915
916 void mathDispatchMathDisplay(BufferView * bv, string const & arg)
917 {
918         mathDispatchCreation(bv, arg, true);
919 }
920
921
922 void mathDispatchMathMode(BufferView * bv, string const & arg)
923 {
924         mathDispatchCreation(bv, arg, false);
925 }
926
927
928 void mathDispatchMathImportSelection(BufferView * bv, string const & arg)
929 {
930         mathDispatchCreation(bv, arg, true);
931 }
932
933
934 void mathDispatchMathMacro(BufferView * bv, string const & arg)
935 {
936         if (bv->available()) {
937                 if (arg.empty())
938                         bv->owner()->getLyXFunc()->setErrorMessage(N_("Missing argument"));
939                 else {
940                         string s = arg;
941                         string const s1 = token(s, ' ', 1);
942                         int const na = s1.empty() ? 0 : lyx::atoi(s1);
943                         openNewInset(bv, new InsetFormulaMacro(token(s, ' ', 0), na));
944                 }
945         }
946 }
947
948
949 void mathDispatchMathDelim(BufferView * bv, string const & arg)
950 {
951         if (bv->available()) {
952                 if (openNewInset(bv, new InsetFormula))
953                         bv->theLockingInset()->localDispatch(bv, LFUN_MATH_DELIM, arg);
954         }
955 }
956
957
958 void mathDispatchInsertMatrix(BufferView * bv, string const & arg)
959 {
960         if (bv->available()) {
961                 if (openNewInset(bv, new InsetFormula))
962                         bv->theLockingInset()->localDispatch(bv, LFUN_INSERT_MATRIX, arg);
963         }
964 }
965
966
967 void mathDispatchInsertMath(BufferView * bv, string const & arg)
968 {
969         if (bv->available()) {
970                 if (arg.size() && arg[0] == '\\') {
971                         InsetFormula * f = new InsetFormula(arg);
972                         if (!bv->insertInset(f))
973                                 delete f;
974                         else if (!mathcursor) // hotfix
975                                 bv->getLyXText()->cursorRight(bv);
976                 } else {
977                         mathDispatchMathMode(bv, arg);
978                 }
979         }
980 }
981
982
983 void mathDispatchGreek(BufferView * bv, string const & arg)
984 {
985         if (bv->available()) {
986                 InsetFormula * f = new InsetFormula;
987                 if (openNewInset(bv, f)) {
988                         bv->theLockingInset()->localDispatch(bv, LFUN_GREEK, arg);
989                         bv->unlockInset(f);
990                 }
991         }
992 }
993
994
995 void mathDispatch(BufferView *, kb_action, string const &)
996 {}