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