]> git.lyx.org Git - lyx.git/blob - src/mathed/formulabase.C
remove more forms.h cruft
[lyx.git] / src / mathed / formulabase.C
1 /*
2 *  File:        formula.C
3 *  Purpose:     Implementation of formula inset
4 *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5 *  Created:     January 1996
6 *  Description: Allows the edition of math paragraphs inside Lyx.
7 *
8 *  Copyright: 1996-1998 Alejandro Aguilar Sierra
9 *
10 *  Version: 0.4, Lyx project.
11 *
12 *   You are free to use and modify this code under the terms of
13 *   the GNU General Public Licence version 2 or later.
14 */
15
16 #include <config.h>
17 #include <fstream>
18
19 #include "Lsstream.h"
20
21 #ifdef __GNUG__
22 #pragma implementation
23 #endif
24
25 #include "formula.h"
26 #include "commandtags.h"
27 #include "math_cursor.h"
28 #include "math_parser.h"
29 #include "BufferView.h"
30 #include "lyxtext.h"
31 #include "gettext.h"
32 #include "LaTeXFeatures.h"
33 #include "debug.h"
34 #include "support/LOstream.h"
35 #include "LyXView.h"
36 #include "Painter.h"
37 #include "font.h"
38 #include "math_arrayinset.h"
39 #include "math_spaceinset.h"
40 #include "math_deliminset.h"
41 #include "support/lyxlib.h"
42 #include "mathed/support.h"
43
44 using std::endl;
45 using std::ostream;
46 using std::vector;
47
48 extern char const * latex_special_chars;
49
50 int greek_kb_flag = 0;
51 extern char const * latex_mathenv[];
52 LyXFont           * Math_Fonts = 0;
53 MathCursor        * mathcursor = 0;
54
55
56 namespace {
57
58
59 // local global
60 int sel_x;
61 int sel_y;
62 bool sel_flag;
63
64 void mathed_init_fonts();
65
66 string nicelabel(string const & label)
67 {
68         return label.empty() ? string("(#)") : "(" + label + ")";
69 }
70
71 void handleFont(BufferView * bv, MathTextCodes t) 
72 {
73         if (mathcursor->Selection())
74                 bv->lockedInsetStoreUndo(Undo::EDIT);
75         mathcursor->handleFont(t);
76 }
77
78 } // namespaces
79
80
81
82 LyXFont WhichFont(short type, int size)
83 {
84         LyXFont f;
85         
86         if (!Math_Fonts)
87                 mathed_init_fonts();
88
89         switch (type) {
90         case LM_TC_SYMB:        
91                 f = Math_Fonts[2];
92                 break;
93
94         case LM_TC_BSYM:        
95                 f = Math_Fonts[2];
96                 break;
97
98         case LM_TC_VAR:
99         case LM_TC_IT:
100                 f = Math_Fonts[0];
101                 break;
102
103         case LM_TC_BF:
104                 f = Math_Fonts[3];
105                 break;
106
107         case LM_TC_SF:
108                 f = Math_Fonts[7];
109                 break;
110
111         case LM_TC_CAL:
112                 f = Math_Fonts[4];
113                 break;
114
115         case LM_TC_TT:
116                 f = Math_Fonts[5];
117                 break;
118
119         case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
120         case LM_TC_TEXTRM:
121         case LM_TC_RM:
122                 f = Math_Fonts[6];
123                 break;
124
125         default:
126                 f = Math_Fonts[1];
127                 break;
128         }
129
130         switch (size) {
131         case LM_ST_DISPLAY:
132                 if (type == LM_TC_BSYM) {
133                         f.incSize();
134                         f.incSize();
135                 }
136                 break;
137
138         case LM_ST_TEXT:
139                 break;
140
141         case LM_ST_SCRIPT:
142                 f.decSize();
143                 break;
144
145         case LM_ST_SCRIPTSCRIPT:
146                 f.decSize();
147                 f.decSize();
148                 break;
149
150         default:
151                 lyxerr << "Math Error: wrong font size: " << size << endl;
152                 break;
153         }
154
155         if (type != LM_TC_TEXTRM)
156                 f.setColor(LColor::math);
157
158         return f;
159 }
160
161
162 namespace {
163
164 void mathed_init_fonts()
165 {
166         Math_Fonts = new LyXFont[8]; //DEC cxx cannot initialize all fonts
167         //at once (JMarc) rc
168
169         for (int i = 0 ; i < 8 ; ++i) {
170                 Math_Fonts[i] = LyXFont(LyXFont::ALL_SANE);
171         }
172
173         Math_Fonts[0].setShape(LyXFont::ITALIC_SHAPE);
174
175         Math_Fonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
176
177         Math_Fonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
178         Math_Fonts[2].setShape(LyXFont::ITALIC_SHAPE);
179
180         Math_Fonts[3].setSeries(LyXFont::BOLD_SERIES);
181
182         Math_Fonts[4].setFamily(LyXFont::SANS_FAMILY);
183         Math_Fonts[4].setShape(LyXFont::ITALIC_SHAPE);
184
185         Math_Fonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
186
187         Math_Fonts[6].setFamily(LyXFont::ROMAN_FAMILY);
188
189         Math_Fonts[7].setFamily(LyXFont::SANS_FAMILY);
190 }
191
192
193 // returns the nearest enclosing matrix
194 MathArrayInset * matrixpar(int & idx)
195 {
196         idx = 0;
197         return
198                 static_cast<MathArrayInset *> 
199                         (mathcursor ? mathcursor->enclosing(LM_OT_MATRIX, idx) : 0); 
200 }
201
202
203 } // namespace anon
204
205
206 InsetFormulaBase::InsetFormulaBase(MathInset * par)
207         : par_(par)
208 {}
209
210
211 InsetFormulaBase::InsetFormulaBase(InsetFormulaBase const & f)
212         : UpdatableInset(f), par_(static_cast<MathInset *>(f.par_->clone()))
213 {}
214
215
216 InsetFormulaBase::~InsetFormulaBase()
217 {
218 #ifdef WITH_WARNINGS
219 #warning leak this for a while...
220 #endif
221         //delete par_;
222 }
223
224
225 void InsetFormulaBase::write(Buffer const * buf, ostream & os) const
226 {
227         os << "Formula ";
228         latex(buf, os, false, false);
229 }
230
231
232 int InsetFormulaBase::ascii(Buffer const *, ostream & os, int) const
233 {
234         par_->Write(os, false);
235         return 0;
236 }
237
238
239 int InsetFormulaBase::linuxdoc(Buffer const * buf, ostream & os) const
240 {
241         return ascii(buf, os, 0);
242 }
243
244
245 int InsetFormulaBase::docBook(Buffer const * buf, ostream & os) const
246 {
247         return ascii(buf, os, 0);
248 }
249
250
251 // Check if uses AMS macros
252 void InsetFormulaBase::validate(LaTeXFeatures &) const
253 {}
254
255
256 string const InsetFormulaBase::editMessage() const
257 {
258         return _("Math editor mode");
259 }
260
261
262 void InsetFormulaBase::edit(BufferView * bv, int x, int /*y*/, unsigned int)
263 {
264         mathcursor = new MathCursor(this);
265
266         if (!bv->lockInset(this))
267                 lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl;
268
269         par_->Metrics(LM_ST_TEXT);
270         bv->updateInset(this, false);
271         if (x == 0) {
272                 mathcursor->first();
273         } else {
274                 mathcursor->last();
275         }
276         sel_x = 0;
277         sel_y = 0;
278         sel_flag = false;
279 }
280
281
282 void InsetFormulaBase::insetUnlock(BufferView * bv)
283 {
284         if (mathcursor) {
285                 if (mathcursor->InMacroMode()) {
286                         mathcursor->MacroModeClose();
287                         updateLocal(bv);
288                 }
289                 delete mathcursor;
290         }
291         mathcursor = 0;
292         bv->updateInset(this, false);
293 }
294
295
296 void InsetFormulaBase::getCursorPos(BufferView *, int & x, int & y) const
297 {
298         mathcursor->GetPos(x, y);
299         x -= par_->xo();
300         y -= par_->yo();
301 }
302
303
304 void InsetFormulaBase::toggleInsetCursor(BufferView * bv)
305 {
306         if (!mathcursor)
307                 return;
308
309         if (isCursorVisible())
310                 bv->hideLockedInsetCursor();
311         else {
312                 int x;
313                 int y;
314                 mathcursor->GetPos(x, y);
315                 //x -= par_->xo();
316                 y -= par_->yo();
317
318                 LyXFont   font = WhichFont(LM_TC_TEXTRM, LM_ST_TEXT);
319                 int const asc  = lyxfont::maxAscent(font);
320                 int const desc = lyxfont::maxDescent(font);
321
322                 bv->showLockedInsetCursor(x, y, asc, desc);
323         }
324
325         toggleCursorVisible();
326 }
327
328
329 void InsetFormulaBase::showInsetCursor(BufferView * bv, bool)
330 {
331         if (!isCursorVisible()) {
332                 if (mathcursor) {
333                         int x;
334                         int y;
335                         mathcursor->GetPos(x, y);
336                         x -= par_->xo();
337                         y -= par_->yo();
338                         LyXFont font   = WhichFont(LM_TC_TEXTRM, LM_ST_TEXT);
339                         int const asc  = lyxfont::maxAscent(font);
340                         int const desc = lyxfont::maxDescent(font);
341                         bv->fitLockedInsetCursor(x, y, asc, desc);
342                 }
343                 toggleInsetCursor(bv);
344         }
345 }
346
347
348 void InsetFormulaBase::hideInsetCursor(BufferView * bv)
349 {
350         if (isCursorVisible())
351                 toggleInsetCursor(bv);
352 }
353
354
355 void InsetFormulaBase::toggleInsetSelection(BufferView * bv)
356 {
357         if (!mathcursor)
358                 return;
359
360         bv->updateInset(this, false);
361 }
362
363
364 vector<string> const InsetFormulaBase::getLabelList() const
365 {
366   return std::vector<string>();
367 }
368
369
370 void InsetFormulaBase::updateLocal(BufferView * bv)
371 {
372         par_->Metrics(LM_ST_TEXT);
373         bv->updateInset(this, true);
374 }
375
376
377 void InsetFormulaBase::insetButtonRelease(BufferView * bv,
378                                           int x, int y, int /*button*/)
379 {
380         if (mathcursor) {
381                 hideInsetCursor(bv);
382                 x += par_->xo();
383                 y += par_->yo();
384                 mathcursor->SetPos(x, y);
385                 showInsetCursor(bv);
386                 if (sel_flag) {
387                         sel_flag = false;
388                         sel_x = 0;
389                         sel_y = 0;
390                         bv->updateInset(this, false);
391                 }
392         }
393 }
394
395
396 void InsetFormulaBase::insetButtonPress(BufferView * bv,
397                                         int x, int y, int /*button*/)
398 {
399         sel_flag = false;
400         sel_x = x;
401         sel_y = y;
402         if (mathcursor && mathcursor->Selection()) {
403                 mathcursor->SelClear();
404                 bv->updateInset(this, false);
405         }
406 }
407
408
409 void InsetFormulaBase::insetMotionNotify(BufferView * bv,
410                                          int x, int y, int /*button*/)
411 {
412         if (sel_x && sel_y && abs(x-sel_x) > 4 && !sel_flag) {
413                 sel_flag = true;
414                 hideInsetCursor(bv);
415                 mathcursor->SetPos(sel_x + par_->xo(), sel_y + par_->yo());
416                 mathcursor->SelStart();
417                 showInsetCursor(bv);
418                 mathcursor->GetPos(sel_x, sel_y);
419         } else if (sel_flag) {
420                 hideInsetCursor(bv);
421                 x += par_->xo();
422                 y += par_->yo();
423                 mathcursor->SetPos(x, y);
424                 showInsetCursor(bv);
425                 mathcursor->GetPos(x, y);
426                 if (sel_x != x || sel_y != y)
427                         bv->updateInset(this, false);
428                 sel_x = x;
429                 sel_y = y;
430         }
431 }
432
433
434 void InsetFormulaBase::insetKeyPress(XKeyEvent *)
435 {
436         lyxerr[Debug::MATHED]
437                 << "Used InsetFormulaBase::InsetKeyPress." << endl;
438 }
439
440
441
442 UpdatableInset::RESULT
443 InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
444                             string const & arg)
445 {
446         //lyxerr << "InsetFormulaBase::LocalDispatch: act: " << action
447         //      << " arg: '" << arg << "' cursor: " << mathcursor << "\n";
448         //   extern char *dispatch_result;
449
450         if (!mathcursor) 
451                 return UNDISPATCHED;
452
453         MathTextCodes varcode = LM_TC_MIN;
454         bool was_macro = mathcursor->InMacroMode();
455         bool sel = false;
456         bool space_on = false;
457         bool was_selection = mathcursor->Selection();
458         RESULT result = DISPATCHED;
459         static MathSpaceInset * sp = 0;
460
461         hideInsetCursor(bv);
462
463         if (mathcursor->getLastCode() == LM_TC_TEX)
464                 varcode = LM_TC_TEX;
465
466         mathcursor->normalize();
467
468         switch (action) {
469
470                 // --- Cursor Movements ---------------------------------------------
471
472         case LFUN_RIGHTSEL:
473                 sel = true; // fall through...
474
475         case LFUN_RIGHT:
476                 result = DISPATCH_RESULT(mathcursor->Right(sel));
477                 updateLocal(bv);
478                 break;
479
480
481         case LFUN_LEFTSEL:
482                 sel = true; // fall through
483
484         case LFUN_LEFT:
485                 result = DISPATCH_RESULT(mathcursor->Left(sel));
486                 updateLocal(bv);
487                 break;
488
489
490         case LFUN_UPSEL:
491                 sel = true;
492
493         case LFUN_UP:
494                 result = DISPATCH_RESULT(mathcursor->Up(sel));
495                 updateLocal(bv);
496                 break;
497
498
499         case LFUN_DOWNSEL:
500                 sel = true;
501
502         case LFUN_DOWN:
503                 result = DISPATCH_RESULT(mathcursor->Down(sel));
504                 updateLocal(bv);
505                 break;
506
507
508         case LFUN_HOME:
509                 mathcursor->Home();
510                 result = DISPATCHED_NOUPDATE;
511                 break;
512
513         case LFUN_END:
514                 mathcursor->End();
515                 result = DISPATCHED_NOUPDATE;
516                 break;
517
518         case LFUN_DELETE_LINE_FORWARD:
519                 bv->lockedInsetStoreUndo(Undo::DELETE);
520                 mathcursor->DelLine();
521                 updateLocal(bv);
522                 break;
523
524         case LFUN_TAB:
525                 bv->lockedInsetStoreUndo(Undo::INSERT);
526                 mathcursor->idxRight();
527                 updateLocal(bv);
528                 break;
529
530         case LFUN_TABINSERT:
531                 bv->lockedInsetStoreUndo(Undo::INSERT);
532                 mathcursor->idxRight();
533                 updateLocal(bv);
534                 break;
535
536         case LFUN_BACKSPACE:
537                 if (!mathcursor->InMacroMode() && mathcursor->pos() == 0) {
538                         bv->lockedInsetStoreUndo(Undo::DELETE);
539                         mathcursor->pullArg();
540                         bv->updateInset(this, true);
541                         break;
542                 }
543                 if (!mathcursor->Left())
544                         break;
545                 // fall through...
546
547         case LFUN_DELETE:
548                 bv->lockedInsetStoreUndo(Undo::DELETE);
549                 mathcursor->Delete();
550                 bv->updateInset(this, true);
551                 break;
552
553                 //    case LFUN_GETXY:
554                 //      sprintf(dispatch_buffer, "%d %d",);
555                 //      dispatch_result = dispatch_buffer;
556                 //      break;
557         case LFUN_SETXY:
558         {
559                 lyxerr << "LFUN_SETXY broken!\n";
560                 int x;
561                 int y;
562                 int x1;
563                 int y1;
564                 istringstream is(arg.c_str());
565                 is >> x >> y;
566                 lyxerr << "LFUN_SETXY: x: " << x << " y: " << y << "\n";
567                 par_->GetXY(x1, y1);
568                 mathcursor->SetPos(x1 + x, y1 + y);
569         }
570         break;
571
572                 // cursor selection ---------------------------- 
573
574         case LFUN_PASTE:
575                 if (was_macro)
576                         mathcursor->MacroModeClose();
577                 bv->lockedInsetStoreUndo(Undo::INSERT);
578                 mathcursor->SelPaste();
579                 updateLocal(bv);
580                 break;
581
582         case LFUN_CUT:
583                 bv->lockedInsetStoreUndo(Undo::DELETE);
584                 mathcursor->SelCut();
585                 updateLocal(bv);
586                 break;
587
588         case LFUN_COPY:
589                 mathcursor->SelCopy();
590                 break;
591
592         case LFUN_HOMESEL:
593         case LFUN_ENDSEL:
594         case LFUN_WORDRIGHTSEL:
595         case LFUN_WORDLEFTSEL:
596                 break;
597
598                 // --- accented characters ------------------------------
599
600         case LFUN_UMLAUT:     mathcursor->setAccent(LM_ddot); break;
601         case LFUN_CIRCUMFLEX: mathcursor->setAccent(LM_hat); break;
602         case LFUN_GRAVE:      mathcursor->setAccent(LM_grave); break;
603         case LFUN_ACUTE:      mathcursor->setAccent(LM_acute); break;
604         case LFUN_TILDE:      mathcursor->setAccent(LM_tilde); break;
605         case LFUN_MACRON:     mathcursor->setAccent(LM_bar); break;
606         case LFUN_DOT:        mathcursor->setAccent(LM_dot); break;
607         case LFUN_CARON:      mathcursor->setAccent(LM_check); break;
608         case LFUN_BREVE:      mathcursor->setAccent(LM_breve); break;
609         case LFUN_VECTOR:     mathcursor->setAccent(LM_vec); break;
610
611                 // Greek mode
612         case LFUN_GREEK:
613                 if (!greek_kb_flag) {
614                         greek_kb_flag = 1;
615                         bv->owner()->message(_("Math greek mode on"));
616                 } else
617                         greek_kb_flag = 0;
618                 break;
619
620                 // Greek keyboard
621         case LFUN_GREEK_TOGGLE:
622                 greek_kb_flag = greek_kb_flag ? 0 : 2;
623                 if (greek_kb_flag)
624                         bv->owner()->message(_("Math greek keyboard on"));
625                 else
626                         bv->owner()->message(_("Math greek keyboard off"));
627                 break;
628
629                 //  Math fonts
630         case LFUN_BOLD:    handleFont(bv, LM_TC_BF); break;
631         case LFUN_SANS:    handleFont(bv, LM_TC_SF); break;
632         case LFUN_EMPH:    handleFont(bv, LM_TC_CAL); break;
633         case LFUN_ROMAN:   handleFont(bv, LM_TC_RM); break;
634         case LFUN_CODE:    handleFont(bv, LM_TC_TT); break;
635         case LFUN_DEFAULT: handleFont(bv, LM_TC_VAR); break;
636
637         case LFUN_MATH_MODE:
638                 handleFont(bv, LM_TC_TEXTRM);
639                 //bv->owner()->message(_("math text mode toggled"));
640                 break;
641
642 #ifndef NO_LATEX
643         case LFUN_TEX:
644                 if (!mathcursor->Selection()) {
645                         mathcursor->handleFont(LM_TC_TEX);
646                         //bv->owner()->message(_("TeX mode toggled"));
647                 }
648                 break;
649 #endif
650
651         case LFUN_MATH_LIMITS:
652                 bv->lockedInsetStoreUndo(Undo::INSERT);
653                 if (mathcursor->toggleLimits())
654                         updateLocal(bv);
655                 break;
656
657         case LFUN_MATH_SIZE:
658                 if (!arg.empty()) {
659                         bv->lockedInsetStoreUndo(Undo::INSERT);
660                         latexkeys const * l = in_word_set(arg);
661                         mathcursor->SetSize(MathStyles(l ? l->id : static_cast<unsigned int>(-1)));
662                         updateLocal(bv);
663                 }
664                 break;
665
666         case LFUN_INSERT_MATH:
667                 if (!arg.empty()) {
668                         bv->lockedInsetStoreUndo(Undo::INSERT);
669                         mathcursor->Interpret(arg);
670                         updateLocal(bv);
671                 }
672                 break;
673
674         case LFUN_INSERT_MATRIX:
675                 if (mathcursor) {
676                         bv->lockedInsetStoreUndo(Undo::INSERT);
677                         int m = 1;
678                         int n = 1;
679                         string v_align;
680                         string h_align;
681                         istringstream is(arg.c_str());
682                         is >> m >> n >> v_align >> h_align;
683                         MathArrayInset * p = new MathArrayInset(m, n);
684                         p->valign(v_align[0]);
685                         p->halign(h_align);
686                         mathcursor->insert(p);
687                         updateLocal(bv);
688                 }
689                 break;
690
691         case LFUN_MATH_DELIM:
692         {
693                 bv->lockedInsetStoreUndo(Undo::INSERT);
694                 int ilt = '(';
695                 int irt = '.';
696                 static const string vdelim("(){}[]./|");
697                 lyxerr << "formulabase::LFUN_MATH_DELIM, arg: '" << arg << "'\n";
698
699                 if (arg.empty())
700                         break;
701
702                 istringstream is(arg.c_str());
703                 string lt;
704                 string rt;
705                 is >> lt >> rt;
706                 lyxerr << "formulabase::LFUN_MATH_DELIM, lt: '" << lt << "'\n";
707                 lyxerr << "formulabase::LFUN_MATH_DELIM, rt: '" << rt << "'\n";
708
709                 if (lt.size() > 1) {
710                         latexkeys const * l = in_word_set(lt);
711                         if (l)
712                                 ilt = l->id;
713                 } else if (vdelim.find(lt[0]) != string::npos)
714                                 ilt = lt[0];
715
716                 if (rt.size() > 1) {
717                         latexkeys const * l = in_word_set(rt);
718                         if (l)
719                                 irt = l->id;
720                 } else if (vdelim.find(rt[0]) != string::npos)
721                                 irt = rt[0];
722
723                 if (mathcursor->selection) {
724                         MathDelimInset * p = new MathDelimInset(ilt, irt);
725                         MathArray ar;
726                         mathcursor->selArray(ar);
727                         lyxerr << "selarray: " << ar << "\n";
728                         p->cell(0) = ar; 
729                         mathcursor->insert(p);
730                 } else {
731                         mathcursor->insert(new MathDelimInset(ilt, irt));
732                 }
733                 updateLocal(bv);
734                 break;
735         }
736
737         case LFUN_PROTECTEDSPACE:
738                 bv->lockedInsetStoreUndo(Undo::INSERT);
739                 mathcursor->insert(new MathSpaceInset(1));
740                 space_on = true;
741                 updateLocal(bv);
742                 break;
743
744         case LFUN_UNDO:
745                 bv->owner()->message(_("Invalid action in math mode!"));
746                 break;
747
748
749         case LFUN_MATH_HALIGN:
750         {
751                 bv->lockedInsetStoreUndo(Undo::INSERT);
752                 lyxerr << "handling halign '" << arg << "'\n";
753                 int idx;
754                 MathArrayInset * p = matrixpar(idx);
755                 if (!p)
756                         break; 
757                 p->halign(arg.size() ? arg[0] : 'c', p->col(idx));
758                 updateLocal(bv);
759                 break;
760         }
761
762         case LFUN_MATH_VALIGN:
763         {
764                 bv->lockedInsetStoreUndo(Undo::INSERT);
765                 lyxerr << "handling valign '" << arg << "'\n";
766                 int idx;
767                 MathArrayInset * p = matrixpar(idx);
768                 if (!p)
769                         break; 
770                 p->valign(arg.size() ? arg[0] : 'c');
771                 updateLocal(bv);
772                 break;
773         }
774
775         case LFUN_MATH_ROW_INSERT:
776         {
777                 bv->lockedInsetStoreUndo(Undo::INSERT);
778                 int idx;
779                 MathArrayInset * p = matrixpar(idx);
780                 lyxerr << " calling LFUN_MATH_ROW_INSERT on " << p << endl;
781                 if (!p)
782                         break; 
783                 p->addRow(p->row(idx));
784                 updateLocal(bv);
785                 break;
786         }
787
788         case LFUN_MATH_ROW_DELETE:
789         {
790                 bv->lockedInsetStoreUndo(Undo::INSERT);
791                 int idx;
792                 MathArrayInset * p = matrixpar(idx);
793                 lyxerr << " calling LFUN_MATH_ROW_DELETE on " << p << endl;
794                 if (!p)
795                         break; 
796                 p->delRow(p->row(idx));
797                 updateLocal(bv);
798                 break;
799         }
800
801         case LFUN_MATH_COLUMN_INSERT:
802         {
803                 bv->lockedInsetStoreUndo(Undo::INSERT);
804                 int idx;
805                 MathArrayInset * p = matrixpar(idx);
806                 if (!p)
807                         break; 
808                 p->addCol(p->col(idx));
809                 updateLocal(bv);
810                 break;
811         }
812
813         case LFUN_MATH_COLUMN_DELETE:
814         {
815                 bv->lockedInsetStoreUndo(Undo::INSERT);
816                 int idx;
817                 MathArrayInset * p = matrixpar(idx);
818                 if (!p)
819                         break; 
820                 p->delCol(p->col(idx));
821                 updateLocal(bv);
822                 break;
823         }
824
825         case LFUN_EXEC_COMMAND:
826                 result = UNDISPATCHED;
827                 break;
828
829         default:
830                 if ((action == -1 || action == LFUN_SELFINSERT) && !arg.empty()) {
831                         unsigned char c = arg[0];
832                         bv->lockedInsetStoreUndo(Undo::INSERT);
833
834                         if (c == ' ' && mathcursor->getAccent() == LM_hat) {
835                                 c = '^';
836                                 mathcursor->setAccent(0);
837                         }
838
839                         if (c == 0) {      // Dead key, do nothing
840                                 //lyxerr << "deadkey" << endl;
841                                 break;
842                         }
843
844                         if (isalpha(c)) {
845                                 if (mathcursor->getLastCode() == LM_TC_TEX) {
846                                         mathcursor->MacroModeOpen();
847                                         mathcursor->clearLastCode();
848                                         varcode = LM_TC_MIN;
849                                 } else if (!varcode) {          
850                                         short f = mathcursor->getLastCode() ?
851                                                 mathcursor->getLastCode() :
852                                                 mathcursor->nextCode();
853                                         varcode = MathIsAlphaFont(f) ?
854                                                 static_cast<MathTextCodes>(f) :
855                                                 LM_TC_VAR;
856                                 }
857                                 
858                                 //           lyxerr << "Varcode << vardoce;
859                                 MathTextCodes char_code = varcode;
860                                 if (greek_kb_flag) {
861                                         char greek[26] =
862                                         {'A', 'B', 'X',  0 , 'E',  0 ,  0 , 'H', 'I',  0 ,
863                                          'K',  0 , 'M', 'N', 'O',  0 ,  0 , 'P',  0 , 'T',
864                                          'Y',  0,   0,   0,   0 , 'Z' };
865                                         
866                                         if ('A' <= c && c <= 'Z' && greek[c - 'A']) {
867                                                 char_code = LM_TC_RM;
868                                                 c = greek[c - 'A'];
869                                         } else
870                                                 char_code = LM_TC_SYMB;
871                                 }
872                                 
873                                 mathcursor->insert(c, char_code);
874                                 
875                                 if (greek_kb_flag && char_code == LM_TC_RM )
876                                         mathcursor->setLastCode(LM_TC_VAR);
877                                 
878                                 varcode = LM_TC_MIN;
879                                 
880                                 if (greek_kb_flag < 2)
881                                         greek_kb_flag = 0;
882                                 
883                         } else if (strchr("!,:;{}", c) && (varcode == LM_TC_TEX||was_macro)) {
884                                 mathcursor->insert(c, LM_TC_TEX);
885                                 if (c == '{') {
886                                         mathcursor->insert('}', LM_TC_TEX);
887                                         mathcursor->Left();
888                                 }
889                                 mathcursor->clearLastCode();
890                                 //             varcode = LM_TC_MIN;
891                         } else if (c == '_' && varcode == LM_TC_TEX) {
892                                 mathcursor->insert(c, LM_TC_SPECIAL);
893                                 mathcursor->clearLastCode();
894                                 //             varcode = LM_TC_MIN;
895                         } else if ('0' <= c && c <= '9' && (varcode == LM_TC_TEX||was_macro)) {
896                                 mathcursor->MacroModeOpen();
897                                 mathcursor->clearLastCode();
898                                 mathcursor->insert(c, LM_TC_MIN);
899                         } else if (('0' <= c && c <= '9') || strchr(";:!|[]().,?", c)) {
900                                 MathTextCodes code = mathcursor->getLastCode();
901                                 if (code != LM_TC_TEXTRM)
902                                         code = LM_TC_CONST;
903                                 mathcursor->insert(c, code);
904                         } else if (strchr("+/-*<>=", c)) {
905                                 MathTextCodes code = mathcursor->getLastCode();
906                                 if (code != LM_TC_TEXTRM)
907                                         code = LM_TC_BOP;
908                                 mathcursor->insert(c, code);
909                         } else if (strchr(latex_special_chars, c) && c!= '_') {
910                                 MathTextCodes code = mathcursor->getLastCode();
911                                 if (code != LM_TC_TEXTRM)
912                                         code = LM_TC_SPECIAL;
913                                 mathcursor->insert(c, code);
914                         } else if (c == '_' || c == '^') {
915                                 char s[2];
916                                 s[0] = c;
917                                 s[1] = 0;
918                                 mathcursor->Interpret(s);
919                         } else if (c == ' ') {  
920                                 if (!varcode) { 
921                                         short f = (mathcursor->getLastCode()) ?
922                                                 mathcursor->getLastCode() :
923                                                 mathcursor->nextCode();
924                                         varcode = MathIsAlphaFont(f) ?
925                                                 static_cast<MathTextCodes>(f) :
926                                                 LM_TC_VAR;
927                                 }
928                                 
929                                 if (varcode == LM_TC_TEXTRM) {
930                                         mathcursor->insert(c, LM_TC_TEXTRM);
931                                 } else if (was_macro) {
932                                         mathcursor->MacroModeClose();
933                                 } else if (sp) {
934                                         int isp = (sp->GetSpace()<5) ? sp->GetSpace()+1: 0;
935                                         sp->SetSpace(isp);
936                                         space_on = true;
937                                 } else {
938                                         if (!mathcursor->pop())
939                                                 result = FINISHED;
940                                         mathcursor->plainRight();
941                                 }
942                         } else if (c == '\'' || c == '@') {
943                                 mathcursor->insert (c, LM_TC_VAR);
944                         } else if (c == '\\') {
945                                 if (was_macro)
946                                         mathcursor->MacroModeClose();
947                                 bv->owner()->message(_("TeX mode"));
948                                 mathcursor->setLastCode(LM_TC_TEX);
949                         }
950                         updateLocal(bv);
951                 } else if (action == LFUN_MATH_PANEL) {
952                         result = UNDISPATCHED;
953                 } else {
954                         lyxerr << "Closed by action " << action << endl;
955                         result =  FINISHED;
956                 }
957         }
958
959         if (mathcursor)
960                 mathcursor->normalize();
961
962         if (mathcursor && was_macro != mathcursor->InMacroMode()
963                                 && action >= 0
964                                 && action != LFUN_BACKSPACE) 
965                 updateLocal(bv);
966         
967         //if (mathcursor)
968         //              updateLocal(bv);
969
970         if (sp && !space_on)
971                 sp = 0;
972
973         if (mathcursor && (mathcursor->Selection() || was_selection))
974                 toggleInsetSelection(bv);
975
976         if (result == DISPATCHED || result == DISPATCHED_NOUPDATE ||
977             result == UNDISPATCHED)
978                 showInsetCursor(bv);
979         else
980                 bv->unlockInset(this);
981
982         return result;  // original version
983 }
984
985
986
987 /* FIXME: math-greek-toggle seems to work OK, but math-greek doesn't turn
988  * on greek mode */
989 bool math_insert_greek(BufferView * bv, char c)
990 {
991         if (!bv->available())
992                 return false;
993
994         if (!isalpha(c))
995                 return false;
996
997         string tmp;
998         tmp = c;
999         if (!bv->theLockingInset() || bv->theLockingInset()->isTextInset()) {
1000                 int greek_kb_flag_save = greek_kb_flag;
1001                 InsetFormula * new_inset = new InsetFormula();
1002                 bv->beforeChange(bv->text);
1003                 if (!bv->insertInset(new_inset)) {
1004                         delete new_inset;
1005                         return false;
1006                 }
1007                 //Update(1);//BUG
1008                 new_inset->edit(bv, 0, 0, 0);
1009                 new_inset->localDispatch(bv, LFUN_SELFINSERT, tmp);
1010                 if (greek_kb_flag_save < 2) {
1011                         bv->unlockInset(new_inset); // bv->theLockingInset());
1012                         bv->text->cursorRight(bv, true);
1013                 }
1014         } else
1015                 if (bv->theLockingInset()->lyxCode() == Inset::MATH_CODE ||
1016                                 bv->theLockingInset()->lyxCode() == Inset::MATHMACRO_CODE)
1017                         static_cast<InsetFormula*>(bv->theLockingInset())->localDispatch(bv, LFUN_SELFINSERT, tmp);
1018                 else
1019                         lyxerr << "Math error: attempt to write on a wrong "
1020                                 "class of inset." << endl;
1021         return true;
1022 }
1023
1024
1025
1026 Inset::Code InsetFormulaBase::lyxCode() const
1027 {
1028         return Inset::MATH_CODE;
1029 }
1030
1031
1032 LyXFont const InsetFormulaBase::convertFont(LyXFont const & f) const
1033 {
1034         // We have already discussed what was here
1035         LyXFont font(f);
1036 #ifndef NO_LATEX
1037         font.setLatex(LyXFont::OFF);
1038 #endif
1039         return font;
1040 }
1041
1042 MathInset * InsetFormulaBase::par() const
1043 {
1044         return par_;
1045 }
1046