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