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.
8 * Copyright: (c) 1996-1998 Alejandro Aguilar Sierra
10 * Version: 0.4, Lyx project.
12 * You are free to use and modify this code under the terms of
13 * the GNU General Public Licence version 2 or later.
22 #pragma implementation "formula.h"
26 #include "commandtags.h"
27 #include "math_cursor.h"
28 #include "math_parser.h"
30 #include "bufferlist.h"
32 #include "minibuffer.h"
33 #include "BufferView.h"
34 #include "lyxscreen.h"
38 #include "LaTeXFeatures.h"
40 #include "lyx_gui_misc.h"
42 // $Id: formula.C,v 1.1 1999/09/27 18:44:40 larsbj Exp $
44 #if !defined(lint) && !defined(WITH_WARNINGS)
45 static char vcid[] = "$Id: formula.C,v 1.1 1999/09/27 18:44:40 larsbj Exp $";
48 extern void UpdateInset(Inset* inset, bool mark_dirty = true);
49 extern void LockedInsetStoreUndo(Undo::undo_kind);
50 extern MiniBuffer *minibuffer;
51 extern void ShowLockedInsetCursor(long, long, int, int);
52 extern void HideLockedInsetCursor(long, long, int, int);
53 extern void FitLockedInsetCursor(long, long, int, int);
54 extern int LockInset(UpdatableInset*);
55 extern int UnlockInset(UpdatableInset*);
58 extern GC canvasGC, mathGC, mathLineGC, latexGC, cursorGC, mathFrameGC;
59 extern char *mathed_label;
61 extern int mono_video;
62 extern int fast_selection;
64 extern BufferView *current_view;
65 extern BufferList bufferlist;
66 extern char const *latex_special_chars;
68 short greek_kb_flag = 0;
70 LyXFont *Math_Fonts = NULL; // this is only used by Whichfont and mathed_init_fonts (Lgb)
72 static LyXFont::FONT_SIZE lfont_size = LyXFont::SIZE_NORMAL;
75 static int sel_x, sel_y;
77 MathedCursor* InsetFormula::mathcursor = NULL;
80 int MathedInset::df_asc;
81 int MathedInset::df_des;
82 int MathedInset::df_width;
84 // wrong name on this one should be called "IsAscii"
85 inline bool IsAlpha(char c)
87 return ('A' <= c && c<='Z' || 'a' <= c && c<='z');
90 inline bool IsDigit(char c)
92 return ('0' <= c && c <='9');
95 inline bool IsMacro(short token, int id)
97 return (token!=LM_TK_FRAC && token!=LM_TK_SQRT &&
98 !((token==LM_TK_SYM || token==LM_TC_BSYM) && id<255));
101 void mathedValidate(LaTeXFeatures &features, MathParInset *par);
103 LyXFont WhichFont(short type, int size)
133 case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
143 f.setSize(lfont_size);
147 if (type==LM_TC_BSYM) {
157 case LM_ST_SCRIPTSCRIPT:
162 fprintf(stderr, "Mathed Error: wrong font size: %d\n", size);
166 if (type!=LM_TC_TEXTRM)
167 f.setColor(LyXFont::MATH);
172 void mathed_init_fonts() //removed 'static' because DEC cxx does not
176 Math_Fonts = new LyXFont[8]; //DEC cxx cannot initialize all fonts
178 for (int i=0 ; i<8 ; i++){
179 Math_Fonts[i] = LyXFont::ALL_SANE;
181 Math_Fonts[0].setShape(LyXFont::ITALIC_SHAPE);
183 Math_Fonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
185 Math_Fonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
186 Math_Fonts[2].setShape(LyXFont::ITALIC_SHAPE);
188 Math_Fonts[3].setSeries(LyXFont::BOLD_SERIES);
190 Math_Fonts[4].setFamily(LyXFont::SANS_FAMILY);
191 Math_Fonts[4].setShape(LyXFont::ITALIC_SHAPE);
193 Math_Fonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
195 Math_Fonts[6].setFamily(LyXFont::ROMAN_FAMILY);
197 Math_Fonts[7].setFamily(LyXFont::SANS_FAMILY);
199 LyXFont f = WhichFont(LM_TC_VAR, LM_ST_TEXT);
200 MathedInset::df_asc = f.maxAscent();
201 MathedInset::df_des = f.maxDescent();
202 MathedInset::df_width = f.width('I');
206 void mathed_set_font(short type, int size)
209 cursorGC = getGC(gc_thin_on_off_line);
210 canvasGC = getGC(gc_lighted);
211 latexGC = getGC(gc_latex);
212 mathLineGC = getGC(gc_math);
213 mathFrameGC = getGC(gc_math_frame);
215 LyXFont f = WhichFont(type, size);
216 if (type==LM_TC_TEX) {
217 f.setLatex(LyXFont::ON);
224 int mathed_string_width(short type, int size, byte const* s, int ls)
226 LyXFont f = WhichFont(type, size);
229 if (MathIsBinary(type)) {
231 for (int i=0; i<ls && i<75; i++) {
240 return f.textWidth((const char*)s, ls);;
243 int mathed_char_width(short type, int size, byte c)
245 int t= (MathIsBinary(type)) ? mathed_string_width(type, size, &c, 1):
246 WhichFont(type, size).width(c);
250 int mathed_string_height(short type, int size, byte const * s, int ls, int& asc, int& des)
252 LyXFont font = WhichFont(type, size);
254 for (int i=0; i<ls; i++) {
255 if (font.descent(s[i]) > des)
256 des = font.descent(s[i]);
257 if (font.ascent(s[i]) > asc)
258 asc = font.ascent(s[i]);
263 int mathed_char_height(short type, int size, byte c, int& asc, int& des)
265 LyXFont font = WhichFont(type, size);
267 des = font.descent(c);
268 asc = font.ascent(c);
273 // In a near future maybe we use a better fonts renderer
274 void MathedInset::drawStr(short type, int size, int x, int y, byte* s, int ls)
276 mathed_set_font(type, size);
278 if (MathIsBinary(type)) {
280 for (int i=0; i<ls && i < 75; i++) {
289 GC gc = (type==LM_TC_TEX) ? latexGC: mathGC;
290 XDrawString(fl_display, pm, gc, x, y, (char*)s, ls);
295 InsetFormula::InsetFormula(bool display)
297 par = new MathParInset; // this leaks
298 // mathcursor = NULL;
302 par->SetType(LM_OT_PAR);
303 par->SetStyle(LM_ST_DISPLAY);
307 InsetFormula::InsetFormula(MathParInset *p)
309 par = (p->GetType()>=LM_OT_MPAR) ?
310 new MathMatrixInset((MathMatrixInset*)p):
312 // mathcursor = NULL;
314 disp_flag = (par->GetType()>0);
318 InsetFormula::~InsetFormula()
321 //if (label) delete label;
324 Inset* InsetFormula::Clone()
326 InsetFormula* f = new InsetFormula(par);
331 void InsetFormula::Write(FILE *file)
333 fprintf(file, "Formula ");
337 int InsetFormula::Latex(FILE *file, signed char fragile)
340 //#warning Alejandro, the number of lines is not returned in this case
341 // This problem will disapear at 0.13.
343 InsetFormula::Latex(output, fragile);
344 fprintf(file, "%s", output.c_str());
348 int InsetFormula::Latex(LString &file, signed char fragile)
351 //#warning Alejandro, the number of lines is not returned in this case
352 // This problem will disapear at 0.13.
356 mathed_write(par, file, &ret, fragile, label.c_str());
361 int InsetFormula::Linuxdoc(LString &/*file*/)
367 int InsetFormula::DocBook(LString &/*file*/)
373 // Check if uses AMS macros
374 void InsetFormula::Validate(LaTeXFeatures &features) const
376 // Validation only necesary if not using an AMS Style
377 if (!features.amsstyle)
378 mathedValidate(features, par);
382 void InsetFormula::Read(LyXLex &lex)
384 FILE *file = lex.getFile();
386 mathed_parser_file(file, lex.GetLineNo());
388 // Silly hack to read labels.
390 mathed_parse(0, NULL, &par);
392 disp_flag = (par->GetType()>0);
394 // Update line number
395 lex.setLineNo(mathed_parser_lineno());
398 label = mathed_label;
408 int InsetFormula::Ascent(LyXFont const &) const
410 return par->Ascent() + ((disp_flag) ? 8: 1);
413 int InsetFormula::Descent(LyXFont const &) const
415 return par->Descent() + ((disp_flag) ? 8: 1);
418 int InsetFormula::Width(LyXFont const &f) const
420 lfont_size = f.size();
422 return par->Width(); //+2;
425 void InsetFormula::Draw(LyXFont f, LyXScreen &scr, int baseline, float &x)
427 // This is Alejandros domain so I'll use this
428 unsigned long pm = scr.getForeground();
430 lfont_size = f.size();
431 mathed_set_font(LM_TC_TEXTRM, LM_ST_TEXT); // otherwise a segfault could occur
432 // in some XDrawRectangles (i.e. matrix) (Matthias)
433 if (mathcursor && mathcursor->GetPar()==par) {
434 if (mathcursor->Selection()) {
436 XPoint * p = mathcursor->SelGetArea(n);
437 XFillPolygon(fl_display, pm, getGC(gc_selection), //LyXGetSelectionGC(),
438 p, n, Nonconvex, CoordModeOrigin);
440 mathcursor->Draw(pm, (int)x, baseline);
443 par->setDrawable(pm);
444 par->Draw((int)x, baseline);
446 x += (float)Width(f);
448 if (par->GetType()==LM_OT_PARN || par->GetType()==LM_OT_MPARN) {
450 LyXFont font = WhichFont(LM_TC_BF, par->size);
451 font.setLatex(LyXFont::OFF);
453 if (par->GetType()==LM_OT_PARN) {
455 sprintf(s, "(%s)", label.c_str());
458 font.drawString(s, pm, baseline, int(x+20));
460 if (par->GetType()==LM_OT_MPARN) {
461 MathMatrixInset *mt = (MathMatrixInset*)par;
464 MathedRowSt const* crow = mt->getRowSt();
466 y = baseline + crow->getBaseline();
467 if (crow->isNumbered()) {
468 if (crow->getLabel())
469 sprintf(s, "(%s)", crow->getLabel());
472 font.drawString(s, pm, y, int(x+20));
474 crow = crow->getNext();
478 cursor_visible = false;
482 void InsetFormula::Edit(int x, int y)
484 mathcursor = new MathedCursor(par);
487 UpdateInset(this, false);
490 mathcursor->SetPos(x, y);
495 void InsetFormula::InsetUnlock()
498 if (mathcursor->InMacroMode()) {
499 mathcursor->MacroModeClose();
505 UpdateInset(this, false);
508 // Now a symbol can be inserted only if the inset is locked
509 void InsetFormula::InsertSymbol(char const* s)
511 if (!s || !mathcursor) return;
512 mathcursor->Interpret(s);
516 void InsetFormula::GetCursorPos(int& x, int& y)
518 mathcursor->GetPos(x, y);
523 void InsetFormula::ToggleInsetCursor()
529 mathcursor->GetPos(x, y);
532 LyXFont font = WhichFont(LM_TC_TEXTRM, LM_ST_TEXT);
533 asc = font.maxAscent();
534 desc = font.maxDescent();
537 HideLockedInsetCursor(x, y, asc, desc);
539 ShowLockedInsetCursor(x, y, asc, desc);
540 cursor_visible = !cursor_visible;
543 void InsetFormula::ShowInsetCursor(){
544 if (!cursor_visible){
547 mathcursor->GetPos(x, y);
550 LyXFont font = WhichFont(LM_TC_TEXTRM, LM_ST_TEXT);
551 asc = font.maxAscent();
552 desc = font.maxDescent();
553 FitLockedInsetCursor(x, y, asc, desc);
559 void InsetFormula::HideInsetCursor(){
564 void InsetFormula::ToggleInsetSelection()
572 //mathcursor->SelGetArea(n);
573 // XFillPolygon(fl_display, pm, LyXGetSelectionGC(), p, n, Nonconvex, CoordModeOrigin);
577 UpdateInset(this, false);
581 void InsetFormula::SetDisplay(bool dspf)
583 if (dspf!=disp_flag) {
585 par->SetType(LM_OT_PAR);
586 par->SetStyle(LM_ST_DISPLAY);
588 if (par->GetType()>=LM_OT_MPAR) {
589 MathParInset *p = new MathParInset(par);
593 mathcursor->SetPar(par);
595 par->SetType(LM_OT_MIN);
596 par->SetStyle(LM_ST_TEXT);
597 if (!label.empty() && par->GetType()!=LM_OT_MPARN) {
607 int InsetFormula::GetNumberOfLabels() const
609 // This is dirty, I know. I'll clean it at 0.13
610 if (par->GetType()==LM_OT_MPARN) {
611 MathMatrixInset *mt = (MathMatrixInset*)par;
613 MathedRowSt const* crow = mt->getRowSt();
615 if (crow->getLabel()) nl++;
616 crow = crow->getNext();
627 LString InsetFormula::getLabel(int il) const
629 //#warning This is dirty, I know. Ill clean it at 0.11
630 // Correction, the only way to clean this is with a new kernel: 0.13.
631 if (par->GetType()==LM_OT_MPARN) {
633 MathMatrixInset *mt = (MathMatrixInset*)par;
635 MathedRowSt const* crow = mt->getRowSt();
637 if (crow->getLabel()) {
639 label = crow->getLabel();
644 crow = crow->getNext();
651 void InsetFormula::UpdateLocal()
653 par->Metrics(); // To inform lyx kernel the exact size
654 // (there were problems with arrays).
660 void InsetFormula::InsetButtonRelease(int x, int y, int /*button*/)
665 mathcursor->SetPos(x, y);
670 UpdateInset(this,false);
674 void InsetFormula::InsetButtonPress(int x, int y, int /*button*/)
677 sel_x = x; sel_y = y;
678 if (mathcursor->Selection()) {
679 mathcursor->SelClear();
680 UpdateInset(this, false);
684 void InsetFormula::InsetMotionNotify(int x, int y, int /*button*/)
686 if (sel_x && sel_y && abs(x-sel_x)>4 && !sel_flag) {
689 mathcursor->SetPos(sel_x + par->xo, sel_y + par->yo);
690 mathcursor->SelStart();
692 mathcursor->GetPos(sel_x, sel_y);
698 mathcursor->SetPos(x, y);
700 mathcursor->GetPos(x, y);
701 if (sel_x!=x || sel_y!=y)
702 UpdateInset(this, false);
703 sel_x = x; sel_y = y;
707 void InsetFormula::InsetKeyPress(XKeyEvent *)
709 lyxerr.debug("Used InsetFormula::InsetKeyPress.", Error::MATHED);
712 // Special Mathed functions
713 bool InsetFormula::SetNumber(bool numbf)
716 short type = par->GetType();
717 bool oldf = (type==LM_OT_PARN || type==LM_OT_MPARN);
718 if (numbf && !oldf) type++;
719 if (!numbf && oldf) type--;
726 bool InsetFormula::LocalDispatch(int action, char const *arg)
728 // extern char *dispatch_result;
729 MathedTextCodes varcode = LM_TC_MIN;
730 bool was_macro = mathcursor->InMacroMode();
732 bool space_on = false;
733 bool was_selection = mathcursor->Selection();
735 static MathSpaceInset* sp=NULL;
738 if (mathcursor->Selection() && (fast_selection || mono_video)) ToggleInsetSelection();
740 if (mathcursor->getLastCode()==LM_TC_TEX) {
745 // --- Cursor Movements ---------------------------------------------
746 case LFUN_RIGHTSEL: sel = true;
749 result = mathcursor->Right(sel);
752 case LFUN_LEFTSEL: sel = true;
755 result = mathcursor->Left(sel);
758 case LFUN_UPSEL: sel = true;
760 result = mathcursor->Up(sel);
763 case LFUN_DOWNSEL: sel = true;
765 result = mathcursor->Down(sel);
773 case LFUN_DELETE_LINE_FORWARD:
774 //LockedInsetStoreUndo(Undo::INSERT);
775 LockedInsetStoreUndo(Undo::DELETE);
776 mathcursor->DelLine();
780 LockedInsetStoreUndo(Undo::INSERT);
781 mathcursor->Insert(' ', LM_TC_CR);
782 par = mathcursor->GetPar();
786 LockedInsetStoreUndo(Undo::INSERT);
787 mathcursor->Insert(0, LM_TC_TAB);
791 LockedInsetStoreUndo(Undo::INSERT);
792 mathcursor->Insert('T', LM_TC_TAB);
796 if (!mathcursor->Left())
799 if (!mathcursor-> InMacroMode() && mathcursor->pullArg()) {
805 //LockedInsetStoreUndo(Undo::INSERT);
806 LockedInsetStoreUndo(Undo::DELETE);
807 mathcursor->Delete();
811 // sprintf(dispatch_buffer, "%d %d",);
812 // dispatch_result = dispatch_buffer;
817 sscanf(arg, "%d %d", &x, &y);
819 mathcursor->SetPos(x1+x, y1+y);
823 /* cursor selection ---------------------------- */
827 mathcursor->MacroModeClose();
828 LockedInsetStoreUndo(Undo::INSERT);
829 mathcursor->SelPaste(); UpdateLocal(); break;
831 LockedInsetStoreUndo(Undo::DELETE);
832 mathcursor->SelCut(); UpdateLocal(); break;
833 case LFUN_COPY: mathcursor->SelCopy(); break;
836 case LFUN_WORDRIGHTSEL:
837 case LFUN_WORDLEFTSEL:
840 // --- accented characters ------------------------------
842 case LFUN_UMLAUT: mathcursor->setAccent(LM_ddot); break;
843 case LFUN_CIRCUMFLEX: mathcursor->setAccent(LM_hat); break;
844 case LFUN_GRAVE: mathcursor->setAccent(LM_grave); break;
845 case LFUN_ACUTE: mathcursor->setAccent(LM_acute); break;
846 case LFUN_TILDE: mathcursor->setAccent(LM_tilde); break;
847 case LFUN_MACRON: mathcursor->setAccent(LM_bar); break;
848 case LFUN_DOT: mathcursor->setAccent(LM_dot); break;
849 case LFUN_CARON: mathcursor->setAccent(LM_check); break;
850 case LFUN_BREVE: mathcursor->setAccent(LM_breve); break;
851 case LFUN_VECTOR: mathcursor->setAccent(LM_vec); break;
856 if (!greek_kb_flag) {
858 minibuffer->Set(_("Math greek mode on"));
865 case LFUN_GREEK_TOGGLE:
867 greek_kb_flag = (greek_kb_flag) ? 0: 2;
869 minibuffer->Set(_("Math greek keyboard on"));
871 minibuffer->Set(_("Math greek keyboard off"));
876 case LFUN_BOLD: mathcursor->setLastCode(LM_TC_BF); break;
877 case LFUN_SANS: mathcursor->setLastCode( LM_TC_SF); break;
878 case LFUN_EMPH: mathcursor->setLastCode(LM_TC_CAL); break;
879 case LFUN_ROMAN: mathcursor->setLastCode(LM_TC_RM); break;
880 case LFUN_CODE: mathcursor->setLastCode(LM_TC_TT); break;
881 case LFUN_DEFAULT: mathcursor->setLastCode(LM_TC_VAR ) ; break;
884 // varcode = LM_TC_TEX;
885 mathcursor->setLastCode(LM_TC_TEX);
886 minibuffer->Set(_("TeX mode"));
890 case LFUN_MATH_NUMBER:
892 LockedInsetStoreUndo(Undo::INSERT);
894 short type = par->GetType();
895 bool oldf = (type==LM_OT_PARN || type==LM_OT_MPARN);
898 if (!label.empty()) {
901 minibuffer->Set(_("No number"));
904 minibuffer->Set(_("Number"));
912 case LFUN_MATH_NONUMBER:
914 if (par->GetType()==LM_OT_MPARN) {
915 // MathMatrixInset *mt = (MathMatrixInset*)par;
917 // mt->SetNumbered(!mt->IsNumbered());
919 mathcursor->setNumbered();
925 case LFUN_MATH_LIMITS:
927 LockedInsetStoreUndo(Undo::INSERT);
928 if (mathcursor->Limits())
934 latexkeys *l = in_word_set (arg, strlen(arg));
935 int sz = (l) ? l->id: -1;
936 mathcursor->SetSize(sz);
941 case LFUN_INSERT_MATH:
943 LockedInsetStoreUndo(Undo::INSERT);
948 case LFUN_INSERT_MATRIX:
950 LockedInsetStoreUndo(Undo::INSERT);
952 char s[80], arg2[80];
953 // This is just so that too long args won't ooze out of s.
954 strncpy(arg2,arg,80); arg2[79]=(char)0;
955 k = sscanf(arg2, "%d %d %s", &m, &n, s);
964 MathMatrixInset *p = new MathMatrixInset(m, n);
965 if (mathcursor && p) {
966 if (k>2 && (int)strlen(s)>m)
967 p->SetAlign(s[0], &s[1]);
968 mathcursor->Insert(p, LM_TC_ACTIVE_INSET);
974 case LFUN_MATH_DELIM:
976 LockedInsetStoreUndo(Undo::INSERT);
977 char lf[40], rg[40], arg2[40];
978 int ilf = '(', irg = '.';
980 LString vdelim("(){}[]./|");
983 strncpy(arg2,arg,40); arg2[39]=(char)0;
984 int n = sscanf(arg2, "%s %s", lf, rg);
985 lf[39] = (char)0; rg[39] = (char)0;
992 l = in_word_set(lf, strlen(lf));
993 // Long words will cause l==0; so check.
996 if (vdelim.charPos(lf[0])>=0)
1004 l = in_word_set(rg, strlen(rg));
1007 if (vdelim.charPos(rg[0])>=0)
1012 MathDelimInset* p = new MathDelimInset(ilf, irg);
1013 mathcursor->Insert(p, LM_TC_ACTIVE_INSET);
1018 case LFUN_PROTECTEDSPACE:
1020 LockedInsetStoreUndo(Undo::INSERT);
1021 sp = new MathSpaceInset(1);
1022 mathcursor->Insert(sp);
1028 case LFUN_INSERT_LABEL:
1030 LockedInsetStoreUndo(Undo::INSERT);
1031 if (par->GetType()<LM_OT_PAR) break;
1034 lb = LString(askForText(_("Enter new label to insert:")));
1035 if (!lb.empty() && lb[0]> ' ') {
1037 if (par->GetType()==LM_OT_MPARN) {
1038 mathcursor->setLabel(lb.c_str());
1039 // MathMatrixInset *mt = (MathMatrixInset*)par;
1040 // mt->SetLabel(lb);
1042 //if (label.notEmpty()) delete label;
1052 case LFUN_MATH_DISPLAY:
1053 //LockedInsetStoreUndo(Undo::INSERT);
1054 LockedInsetStoreUndo(Undo::EDIT);
1055 SetDisplay(!disp_flag);
1059 // Invalid actions under math mode
1060 case LFUN_MATH_MODE:
1062 if (mathcursor->getLastCode()!=LM_TC_TEXTRM) {
1063 minibuffer->Set(_("math text mode"));
1064 varcode = LM_TC_TEXTRM;
1066 varcode = LM_TC_VAR;
1068 mathcursor->setLastCode(varcode);
1072 minibuffer->Set(_("Invalid action in math mode!"));
1075 //------- dummy actions
1076 case LFUN_EXEC_COMMAND:
1077 minibuffer->ExecCommand();
1081 if ((action==-1 || action==LFUN_SELFINSERT) && arg) {
1082 unsigned char c = arg[0];
1083 LockedInsetStoreUndo(Undo::INSERT);
1085 if (c==' ' && mathcursor->getAccent()==LM_hat) {
1087 mathcursor->setAccent(0);
1089 if (c==0) { // Dead key, do nothing
1090 //fprintf(stderr, "deadkey");
1094 if (mathcursor->getLastCode()==LM_TC_TEX) {
1095 mathcursor->MacroModeOpen();
1096 mathcursor->clearLastCode();
1097 varcode = LM_TC_MIN;
1100 short f = (mathcursor->getLastCode()) ?
1101 mathcursor->getLastCode():
1102 (MathedTextCodes)mathcursor->GetFCode();
1103 varcode = MathIsAlphaFont(f) ? (MathedTextCodes)f:LM_TC_VAR;
1106 // fprintf(stderr, "Varcode %d ", varcode);
1107 mathcursor->Insert(c, (greek_kb_flag) ? LM_TC_SYMB: varcode);
1108 varcode = LM_TC_MIN;
1109 if (greek_kb_flag<2) greek_kb_flag = 0;
1111 if (strchr("!,:;{}", c) && (varcode==LM_TC_TEX||was_macro)) {
1112 mathcursor->Insert(c, LM_TC_TEX);
1114 mathcursor->Insert('}', LM_TC_TEX);
1117 mathcursor->clearLastCode();
1118 // varcode = LM_TC_MIN;
1120 if (c=='_' && varcode==LM_TC_TEX) {
1121 mathcursor->Insert(c, LM_TC_SPECIAL);
1122 mathcursor->clearLastCode();
1123 // varcode = LM_TC_MIN;
1125 if (('0'<=c && c<='9') && (varcode==LM_TC_TEX||was_macro)) {
1126 mathcursor->MacroModeOpen();
1127 mathcursor->clearLastCode();
1128 mathcursor->Insert(c, LM_TC_MIN);
1131 if (('0'<=c && c<='9') || strchr(";:!|[]().,?", c))
1132 mathcursor->Insert(c, LM_TC_CONST);
1134 if (strchr("+/-*<>=", c))
1135 mathcursor->Insert(c, LM_TC_BOP);
1137 if (strchr(latex_special_chars, c) && c!='_')
1138 mathcursor->Insert(c, LM_TC_SPECIAL);
1140 if (c=='_' || c=='^') {
1144 mathcursor->Interpret (s);
1148 short f = (mathcursor->getLastCode()) ?
1149 mathcursor->getLastCode():
1150 (MathedTextCodes)mathcursor->GetFCode();
1151 varcode = MathIsAlphaFont(f) ? (MathedTextCodes)f:LM_TC_VAR;
1153 if (varcode==LM_TC_TEXTRM) {
1154 mathcursor->Insert(c, LM_TC_TEXTRM);
1157 mathcursor->MacroModeClose();
1160 int isp = (sp->GetSpace()<5) ? sp->GetSpace()+1: 0;
1164 if (!mathcursor->Pop() && mathcursor->IsEnd())
1169 mathcursor->Insert (c, LM_TC_VAR);
1173 mathcursor->MacroModeClose();
1174 minibuffer->Set(_("TeX mode"));
1175 mathcursor->setLastCode(LM_TC_TEX);
1179 // fprintf(stderr, "Closed by action %d\n", action);
1183 if (was_macro!=mathcursor->InMacroMode()&&action>=0&&action!=LFUN_BACKSPACE)
1185 if (sp && !space_on) sp = NULL;
1186 if (mathcursor->Selection() || (was_selection && !(fast_selection || mono_video)))
1187 ToggleInsetSelection();
1199 MathFuncInset::Draw(int x, int y)
1201 if (name && name[0]>' ') {
1202 LyXFont font = WhichFont(LM_TC_TEXTRM, size);
1203 font.setLatex(LyXFont::ON);
1204 x += (font.textWidth("I", 1)+3)/4;
1206 int a=font.maxAscent(), d=font.maxDescent();
1207 XFillRectangle (fl_display, pm, getGC(gc_copy),
1209 font.textWidth(name, strlen(name)), a+d);
1212 font.drawString(name, pm, y, x);
1217 void MathFuncInset::Metrics()
1219 ln = (name) ? strlen(name): 0;
1220 LyXFont font = WhichFont(LM_TC_TEXTRM, size);
1221 font.setLatex(LyXFont::ON);
1222 width = font.textWidth(name, ln) + font.textWidth("I", 1)/2;
1223 mathed_string_height(LM_TC_TEXTRM, size, (byte const *) name,
1224 strlen(name), ascent, descent);
1228 void mathedValidate(LaTeXFeatures &features, MathParInset *par)
1230 MathedIter it(par->GetData());
1232 while (it.OK() && !(features.binom && features.boldsymbol)) {
1235 MathParInset *p = it.GetActiveInset();
1236 if (!features.binom && p->GetType()==LM_OT_MACRO &&
1237 strcmp(p->GetName(), "binom")==0) {
1238 features.binom = true;
1240 for (int i=0; i<=p->getMaxArgumentIdx(); i++) {
1241 p->setArgumentIdx(i);
1242 mathedValidate(features, p);
1246 MathedInset* p = it.GetInset();
1247 if (!features.boldsymbol && p->GetName() &&
1248 strcmp(p->GetName(), "boldsymbol")==0) {
1249 features.boldsymbol = true;