/* * File: math_inset.C * Purpose: Implementation of insets for mathed * Author: Alejandro Aguilar Sierra * Created: January 1996 * Description: * * Dependencies: Xlib, XForms * * Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra * * Version: 0.8beta. * * You are free to use and modify this code under the terms of * the GNU General Public Licence version 2 or later. */ #include #ifdef __GNUG__ #pragma implementation "math_inset.h" #endif #include "math_iter.h" #include "math_inset.h" #include "symbol_def.h" inline char *strnew(char const* s) { char *s1 = new char[strlen(s)+1]; return strcpy(s1, s); } MathedInset::MathedInset(MathedInset* inset) { if (inset) { name = inset->GetName(); objtype = inset->GetType(); size = inset->GetStyle(); width = inset->Width(); ascent = inset->Ascent(); descent = inset->Descent(); } else { objtype = LM_OT_UNDEF; size = LM_ST_TEXT; width = ascent = descent = 0; name = 0; } } MathFuncInset::MathFuncInset(char const *nm, short ot, short st): MathedInset("", ot, st) { ln = 0; lims = (GetType() == LM_OT_FUNCLIM); if (GetType() == LM_OT_UNDEF) { fname = strnew(nm); SetName(fname); } else { fname = 0; SetName(nm); } } MathedInset *MathFuncInset::Clone() { MathedInset *l = new MathFuncInset(name, GetType(), GetStyle()); return l; } MathSpaceInset::MathSpaceInset(int sp, short ot, short st): MathedInset("", ot, st), space(sp) { } MathedInset *MathSpaceInset::Clone() { MathedInset *l = new MathSpaceInset(space, GetType(), GetStyle()); return l; } MathParInset::MathParInset(short st, char const *nm, short ot): MathedInset(nm, ot, st) { array = 0; ascent = 8; width = 4; descent = 0; flag = 1; if (objtype == LM_OT_SCRIPT) flag |= LMPF_SCRIPT; } MathParInset::MathParInset(MathParInset* p): MathedInset(p) { flag = p->flag; p->setArgumentIdx(0); MathedIter it(p->GetData()); SetData(it.Copy()); } MathParInset::~MathParInset() { if (array) { MathedIter it(array); it.Clear(); delete array; } } MathedInset *MathParInset::Clone() { MathParInset* p = new MathParInset(this); return p; } void MathParInset::SetData(LyxArrayBase *a) { array = a; // A standard paragraph shouldn't have any tabs nor CRs. if (array) { MathedIter it(array); while (it.OK()) { char c = it.GetChar(); if (c == LM_TC_TAB || c == LM_TC_CR) it.Delete(); else it.Next(); } } } MathSqrtInset::MathSqrtInset(short st): MathParInset(st, "sqrt", LM_OT_SQRT) { } MathedInset *MathSqrtInset::Clone() { MathSqrtInset* p = new MathSqrtInset(GetStyle()); MathedIter it(array); p->SetData(it.Copy()); return p; } bool MathSqrtInset::Inside(int x, int y) { return (x>= xo-hmax && x<= xo+width-hmax && y<= yo+descent && y>= yo-ascent); } MathDelimInset::MathDelimInset(int l, int r, short st): MathParInset(st, "", LM_OT_DELIM), left(l), right(r) { } MathedInset *MathDelimInset::Clone() { MathDelimInset* p = new MathDelimInset(left, right, GetStyle()); MathedIter it(array); p->SetData(it.Copy()); return p; } MathDecorationInset::MathDecorationInset(int d, short st): MathParInset(st, "", LM_OT_DECO), deco(d) { upper = (deco!= LM_underline && deco!= LM_underbrace); } MathedInset *MathDecorationInset::Clone() { MathDecorationInset* p = new MathDecorationInset(deco, GetStyle()); MathedIter it(array); p->SetData(it.Copy()); return p; } MathFracInset::MathFracInset(short ot): MathParInset(LM_ST_TEXT, "frac", ot) { den = new MathParInset(LM_ST_TEXT); // this leaks dh = 0; idx = 0; if (objtype == LM_OT_STACKREL) { flag |= LMPF_SCRIPT; SetName("stackrel"); } } MathFracInset::~MathFracInset() { delete den; } MathedInset *MathFracInset::Clone() { MathFracInset* p = new MathFracInset(GetType()); MathedIter itn(array); MathedIter itd(den->GetData()); p->SetData(itn.Copy(), itd.Copy()); p->idx = idx; p->dh = dh; return p; } bool MathFracInset::setArgumentIdx(int i) { if (i == 0 || i == 1) { idx = i; return true; } else return false; } void MathFracInset::SetStyle(short st) { MathParInset::SetStyle(st); dh = 0; den->SetStyle((size == LM_ST_DISPLAY) ? (short)LM_ST_TEXT: size); } void MathFracInset::SetData(LyxArrayBase *n, LyxArrayBase *d) { den->SetData(d); MathParInset::SetData(n); } void MathFracInset::SetData(LyxArrayBase *d) { if (idx == 0) MathParInset::SetData(d); else { den->SetData(d); } } void MathFracInset::GetXY(int& x, int& y) const { if (idx == 0) MathParInset::GetXY(x, y); else den->GetXY(x, y); } LyxArrayBase *MathFracInset::GetData() { if (idx == 0) return array; else return den->GetData(); } bool MathFracInset::Inside(int x, int y) { int xx = xo - (width-w0)/2; return (x>= xx && x<= xx+width && y<= yo+descent && y>= yo-ascent); } void MathFracInset::SetFocus(int /*x*/, int y) { // lyxerr << "y " << y << " " << yo << " " << den->yo << " "; idx = (y > yo) ? 1: 0; } MathMatrixInset::MathMatrixInset(int m, int n, short st): MathParInset(st, "array", LM_OT_MATRIX), nc(m) { ws = new int[nc]; v_align = 0; h_align = new char[nc+1]; for (int i = 0; i < nc; i++) h_align[i] = 'c'; h_align[nc] = '\0'; nr = 0; row = 0; flag = 15; if (n>0) { row = new MathedRowSt(nc+1); MathedXIter it(this); for (int j = 1; j < n; j++) it.addRow(); nr = n; if (nr == 1 && nc>1) { for (int j = 0; j < nc - 1; j++) it.Insert('T', LM_TC_TAB); } } else if (n<0) { row = new MathedRowSt(nc+1); nr = 1; } } MathMatrixInset::MathMatrixInset(MathMatrixInset *mt): MathParInset(mt->GetStyle(), mt->GetName(), mt->GetType()) { nr = 0; nc = mt->nc; ws = new int[nc]; h_align = new char[nc+1]; strcpy(h_align, mt->GetAlign(&v_align)); MathedIter it; it.SetData(mt->GetData()); array = it.Copy(); if (mt->row != 0) { MathedRowSt *r, *ro= 0, *mrow = mt->row; mrow = mt->row; while (mrow) { r = new MathedRowSt(nc+1); r->numbered = mrow->numbered; if (mrow->label) r->label = strnew(mrow->label); if (!ro) row = r; else ro->next = r; mrow = mrow->next; ro = r; nr++; } } else row = 0; flag = mt->flag; } MathMatrixInset::~MathMatrixInset() { delete[] ws; MathedRowSt *r = row; while (r) { MathedRowSt *q = r->next; delete r; r = q; } } MathedInset *MathMatrixInset::Clone() { MathMatrixInset* mt = new MathMatrixInset(this); return mt; } void MathMatrixInset::SetAlign(char vv, char const* hh) { v_align = vv; strncpy(h_align, hh, nc); } // Check the number of tabs and crs void MathMatrixInset::SetData(LyxArrayBase *a) { if (!a) return; MathedIter it(a); int nn = nc-1; nr = 1; // count tabs per row while (it.OK()) { if (it.IsTab()) { if (nn<0) { it.Delete(); continue; } else { // it.Next(); nn--; } } if (it.IsCR()) { while (nn>0) { it.Insert(' ', LM_TC_TAB); nn--; } nn = nc-1; nr++; } it.Next(); } it.Reset(); // Automatically inserts tabs around bops // DISABLED because it's very easy to insert tabs array = a; } void MathMatrixInset::Draw(int x, int baseline) { MathParInset::Draw(x, baseline); } void MathMatrixInset::Metrics() { int i, /*cy,*/ hl, h= 0; MathedRowSt *cprow= 0, *cxrow; if (!row) { // lyxerr << " MIDA "; MathedXIter it(this); row = it.adjustVerticalSt(); } // Clean the arrays cxrow = row; while (cxrow) { for (i= 0; i<= nc; i++) cxrow->w[i] = 0; cxrow = cxrow->next; } // Basic metrics MathParInset::Metrics(); if (nc<= 1 && !row->next) { row->asc = ascent; row->desc = descent; } // Vertical positions of each row cxrow = row; while (cxrow) { for (i= 0; iw[i]) ws[i]= cxrow->w[i]; if (cxrow->next == 0 && ws[i] == 0) ws[i] = df_width; } cxrow->y = (cxrow == row) ? cxrow->asc: cxrow->asc + cprow->desc + MATH_ROWSEP + cprow->y; h += cxrow->asc + cxrow->desc + MATH_ROWSEP; cprow = cxrow; cxrow = cxrow->next; } hl = Descent(); h -= MATH_ROWSEP; // Compute vertical align switch (v_align) { case 't': ascent = row->y; break; case 'b': ascent = h - hl; break; default: ascent = (row->next) ? h/2: h - hl; break; } descent = h - ascent + 2; // Adjust local tabs cxrow = row; width = MATH_COLSEP; while (cxrow) { int rg= MATH_COLSEP, ww, lf= 0, *w = cxrow->w; for (i= 0; iy -= ascent; cxrow = cxrow->next; } } MathAccentInset::MathAccentInset(byte cx, MathedTextCodes f, int cd, short st): MathedInset("", LM_OT_ACCENT, st), c(cx), fn(f), code(cd) { inset = 0; } MathAccentInset::MathAccentInset(MathedInset *ins, int cd, short st): MathedInset("", LM_OT_ACCENT, st), c(0), fn(LM_TC_MIN), code(cd), inset(ins) { } MathAccentInset::~MathAccentInset() { if (inset) delete inset; } MathedInset *MathAccentInset::Clone() { MathAccentInset* p; if (inset) p = new MathAccentInset(inset->Clone(), code, GetStyle()); else p = new MathAccentInset(c, fn, code, GetStyle()); return p; } MathBigopInset::MathBigopInset(char const* nam, int id, short st): MathedInset(nam, LM_OT_BIGOP, st), sym(id) { lims = -1; } MathedInset *MathBigopInset::Clone() { MathBigopInset* p = new MathBigopInset(name, sym, GetStyle()); return p; } MathDotsInset::MathDotsInset(char const* nam, int id, short st): MathedInset(nam, LM_OT_DOTS, st), code(id) { } MathedInset *MathDotsInset::Clone() { MathDotsInset* p = new MathDotsInset(name, code, GetStyle()); return p; }