/* * File: math_inset.C * Purpose: Implementation of insets for mathed * Author: Alejandro Aguilar Sierra * Created: January 1996 * Description: * * Dependencies: Xlib, XForms * * Copyright: 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" 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(string const & nm, short ot, short st) : MathedInset("", ot, st) { ln = 0; lims = (GetType() == LM_OT_FUNCLIM); if (GetType() == LM_OT_UNDEF) { fname = nm; SetName(fname); } else { //fname = 0; SetName(nm); } } MathedInset * MathFuncInset::Clone() { return new MathFuncInset(name, GetType(), GetStyle()); } MathSpaceInset::MathSpaceInset(int sp, short ot, short st) : MathedInset("", ot, st), space(sp) {} MathedInset * MathSpaceInset::Clone() { return new MathSpaceInset(space, GetType(), GetStyle()); } MathParInset::MathParInset(short st, string 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() { return new MathParInset(this); } 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) ? static_cast(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), v_align(0), h_align(nc, 'c') { ws = new int[nc]; 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()), nc(mt->nc), v_align(mt->v_align), h_align(mt->h_align) { nr = 0; ws = new int[nc]; MathedIter it; it.SetData(mt->GetData()); array = it.Copy(); if (mt->row != 0) { MathedRowSt * r, * ro= 0, * mrow = mt->row; //mrow = mt->row; // This must be redundant... while (mrow) { r = new MathedRowSt(nc + 1); r->setNumbered(mrow->isNumbered()); //if (mrow->label) r->setLabel(mrow->getLabel()); if (!ro) row = r; else ro->setNext(r); mrow = mrow->getNext(); ro = r; ++nr; } } else row = 0; flag = mt->flag; } MathMatrixInset::~MathMatrixInset() { delete[] ws; MathedRowSt * r = row; while (r) { MathedRowSt * q = r->getNext(); delete r; r = q; } } MathedInset * MathMatrixInset::Clone() { return new MathMatrixInset(this); } void MathMatrixInset::SetAlign(char vv, string const & hh) { v_align = vv; h_align = hh.substr(0, nc); // usr just h_align = hh; perhaps } // 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(Painter & pain, int x, int baseline) { MathParInset::draw(pain, x, baseline); } void MathMatrixInset::Metrics() { int i, hl, h = 0; MathedRowSt * cprow= 0; if (!row) { // lyxerr << " MIDA "; MathedXIter it(this); row = it.adjustVerticalSt(); } // Clean the arrays MathedRowSt * cxrow = row; while (cxrow) { for (i = 0; i <= nc; ++i) cxrow->setTab(i, 0); cxrow = cxrow->getNext(); } // Basic metrics MathParInset::Metrics(); if (nc <= 1 && !row->getNext()) { row->ascent(ascent); row->descent(descent); } // Vertical positions of each row cxrow = row; while (cxrow) { for (i = 0; i < nc; ++i) { if (cxrow == row || ws[i] < cxrow->getTab(i)) ws[i] = cxrow->getTab(i); if (cxrow->getNext() == 0 && ws[i] == 0) ws[i] = df_width; } cxrow->setBaseline((cxrow == row) ? cxrow->ascent() : cxrow->ascent() + cprow->descent() + MATH_ROWSEP + cprow->getBaseline()); h += cxrow->ascent() + cxrow->descent() + MATH_ROWSEP; cprow = cxrow; cxrow = cxrow->getNext(); } hl = Descent(); h -= MATH_ROWSEP; // Compute vertical align switch (v_align) { case 't': ascent = row->getBaseline(); break; case 'b': ascent = h - hl; break; default: ascent = (row->getNext()) ? h / 2: h - hl; break; } descent = h - ascent + 2; // Increase ws[i] for 'R' columns (except the first one) for (i = 1; i < nc; ++i) if (h_align[i] == 'R') ws[i] += 10*df_width; // Adjust local tabs cxrow = row; width = MATH_COLSEP; while (cxrow) { int rg = MATH_COLSEP, ww, lf = 0; //, * w = cxrow->w; for (i = 0; i < nc; ++i) { bool isvoid = false; if (cxrow->getTab(i) <= 0) { cxrow->setTab(i, df_width); isvoid = true; } switch (h_align[i]) { case 'l': lf = 0; break; case 'c': lf = (ws[i] - cxrow->getTab(i))/2; break; case 'r': case 'R': lf = ws[i] - cxrow->getTab(i); break; } ww = (isvoid) ? lf : lf + cxrow->getTab(i); cxrow->setTab(i, lf + rg); rg = ws[i] - ww + MATH_COLSEP; if (cxrow == row) width += ws[i] + MATH_COLSEP; } cxrow->setBaseline(cxrow->getBaseline() - ascent); cxrow = cxrow->getNext(); } } 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() { 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(string const & nam, int id, short st) : MathedInset(nam, LM_OT_BIGOP, st), sym(id) { lims = -1; } MathedInset * MathBigopInset::Clone() { return new MathBigopInset(name, sym, GetStyle()); } MathDotsInset::MathDotsInset(string const & nam, int id, short st) : MathedInset(nam, LM_OT_DOTS, st), code(id) {} MathedInset * MathDotsInset::Clone() { return new MathDotsInset(name, code, GetStyle()); }