X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_macro.C;h=9983cf5f78b523af9c7425a1a17867bf75460d45;hb=d359dd8fca52c4f0100f7cf4bf636113c5c4e49f;hp=6fcd845ad7d0a920b1c9351de97335c5624ed309;hpb=d2b9849fffc03f8278d9d034dbccc59b58a214db;p=lyx.git diff --git a/src/mathed/math_macro.C b/src/mathed/math_macro.C index 6fcd845ad7..9983cf5f78 100644 --- a/src/mathed/math_macro.C +++ b/src/mathed/math_macro.C @@ -1,644 +1,243 @@ -// -*- C++ -*- /* * File: math_macro.C - * Purpose: Implementation of macro class for mathed - * Author: Alejandro Aguilar Sierra + * Purpose: Implementation of macro class for mathed + * Author: Alejandro Aguilar Sierra * Created: November 1996 * Description: WYSIWYG math macros * - * Dependencies: Mathed + * Dependencies: Math * - * Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra + * Copyright: 1996, 1997 Alejandro Aguilar Sierra * - * Version: 0.2, Mathed & Lyx project. + * Version: 0.2, Math & Lyx project. * * This code is under the GNU General Public Licence version 2 or later. */ -#include -#include FORMS_H_LOCATION - #ifdef __GNUG__ -#pragma implementation "math_macro.h" -#pragma implementation "math_defs.h" +#pragma implementation #endif -#include "LString.h" #include "math_macro.h" -#include "math_iter.h" -#include "math_inset.h" +#include "math_support.h" +#include "math_extern.h" +#include "math_macrotable.h" +#include "math_macrotemplate.h" +#include "math_mathmlstream.h" +#include "math_streamstr.h" #include "support/lstrings.h" +#include "support/LAssert.h" #include "debug.h" +#include "LaTeXFeatures.h" -ostream & operator<<(ostream & o, MathedTextCodes mtc) -{ - return o << int(mtc); -} - -enum MathedMacroFlag { - MMF_Env= 1, - MMF_Exp= 2, - MMF_Edit= 4 -}; - -ostream & operator<<(ostream & o, MathedMacroFlag mmf) -{ - return o << int(mmf); -} - -extern int mathed_string_width(short type, int style, byte const* s, int ls); -extern int mathed_string_height(short, int, byte const*, int, int&, int&); - - -MathMacro::MathMacro(MathMacroTemplate* t): - MathParInset(LM_ST_TEXT, "", LM_OT_MACRO), tmplate(t) -{ - nargs = tmplate->getNoArgs(); - tcode = tmplate->getTCode(); - args = new MacroArgumentBase[nargs]; - for (int i = 0; i < nargs; ++i) { -// if (tmplate->getMacroPar(i)->Permit(LMPF_ALLOW_CR)) -// args[i].row = new MathedRowSt(tmplate->getMacroPar(i)->GetColumns()); -// else - args[i].row = 0; -/* int k = tmplate->getMacroPar(i)->GetColumns(); - if (k>0) { - args[i].array = new LyxArrayBase; - for (int j= 0; jInsert(j, LM_TC_TAB); - }*/ - } - idx = 0; - SetName(tmplate->GetName()); -} +using std::max; -MathMacro::MathMacro(MathMacro * m): - MathParInset(LM_ST_TEXT, m->GetName(), LM_OT_MACRO) -{ - tmplate = m->tmplate; - nargs = tmplate->getNoArgs(); - tcode = tmplate->getTCode(); - args = new MacroArgumentBase[nargs]; - idx = 0; - SetName(tmplate->GetName()); - for (int i = 0; i < tmplate->nargs; ++i) { - m->setArgumentIdx(i); - MathedIter it(m->GetData()); - args[i].row = m->args[i].row; - args[i].array = it.Copy(); - } -} +MathMacro::MathMacro(string const & name) + : MathNestInset(MathMacroTable::provide(name)->asMacroTemplate()->numargs()), + tmplate_(MathMacroTable::provide(name)) +{} -MathMacro::~MathMacro() -{ - for (idx = 0; idx < nargs; ++idx) { - MathedIter it(args[idx].array); - it. Clear(); - delete args[idx].row; - } - delete[] args; -} +MathMacro::MathMacro(MathMacro const & m) + : MathNestInset(m), + tmplate_(m.tmplate_) // don't copy 'expanded_'! +{} -MathedInset * MathMacro::Clone() -{ - return new MathMacro(this); -} -void MathMacro::Metrics() +MathInset * MathMacro::clone() const { - if (nargs > 0) - tmplate->update(this); - tmplate->Metrics(); - width = tmplate->Width(); - ascent = tmplate->Ascent(); - descent = tmplate->Descent(); + return new MathMacro(*this); } -void MathMacro::draw(Painter & pain, int x, int y) +string const & MathMacro::name() const { - xo = x; yo = y; - Metrics(); - tmplate->update(this); - tmplate->SetStyle(size); - tmplate->draw(pain, x, y); - for (int i = 0; i < nargs; ++i) - tmplate->GetMacroXY(i, args[i].x, args[i].y); + return tmplate_->asMacroTemplate()->name(); } -int MathMacro::GetColumns() +bool MathMacro::defining() const { - return tmplate->getMacroPar(idx)->GetColumns(); + return 0; + //return mathcursor && mathcursor->formula()->getInsetName() == name(); } -void MathMacro::GetXY(int & x, int & y) const +void MathMacro::expand() const { - x = args[idx].x; y = args[idx].y; + expanded_ = tmplate_->xcell(tmplate_->cell(1).empty() ? 0 : 1); } -bool MathMacro::Permit(short f) +void MathMacro::metrics(MathMetricsInfo & mi) const { - return (nargs > 0) ? - tmplate->getMacroPar(idx)->Permit(f) : MathParInset::Permit(f); -} - + augmentFont(font_, "lyxtex"); + mi_ = mi; -void MathMacro::SetFocus(int x, int y) -{ - tmplate->update(this); - tmplate->SetMacroFocus(idx, x, y); -} - - -void MathMacro::Write(ostream & os) -{ -#ifdef USE_OSTREAM_ONLY - if (tmplate->flags & MMF_Exp) { - lyxerr[Debug::MATHED] << "Expand " << tmplate->flags - << ' ' << MMF_Exp << endl; - tmplate->update(this); - tmplate->Write(os); - } else { - if (tmplate->flags & MMF_Env) { - os << "\\begin{" - << name - << "} "; - } else { - os << '\\' << name; + if (defining()) { + mathed_string_dim(font_, name(), ascent_, descent_, width_); + return; } -// if (options) { -// file += '['; -// file += options; -// file += ']'; -// } - - if (!(tmplate->flags & MMF_Env) && nargs > 0) - os << '{'; - - for (int i = 0; i < nargs; ++i) { - array = args[i].array; - MathParInset::Write(os); - if (i < nargs - 1) - os << "}{"; - } - if (tmplate->flags & MMF_Env) { - os << "\\end{" - << name - << '}'; - } else { - if (nargs > 0) - os << '}'; - else - os << ' '; - } - } -#else - string output; - MathMacro::Write(output); - os << output; -#endif -} - -#ifndef USE_OSTREAM_ONLY -void MathMacro::Write(string &file) -{ - if (tmplate->flags & MMF_Exp) { - lyxerr[Debug::MATHED] << "Expand " << tmplate->flags - << ' ' << MMF_Exp << endl; - tmplate->update(this); - tmplate->Write(file); - } else { - if (tmplate->flags & MMF_Env) { - file += "\\begin{"; - file += name; - file += "} "; - } else { - file += '\\'; - file += name; - } -// if (options) { -// file += '['; -// file += options; -// file += ']'; -// } - - if (!(tmplate->flags & MMF_Env) && nargs > 0) - file += '{'; - - for (int i = 0; i < nargs; ++i) { - array = args[i].array; - MathParInset::Write(file); - if (i < nargs - 1) - file += "}{"; - } - if (tmplate->flags & MMF_Env) { - file += "\\end{"; - file += name; - file += '}'; - } else { - if (nargs > 0) - file += '}'; - else - file += ' '; + if (editing()) { + expand(); + expanded_.metrics(mi_); + width_ = expanded_.width() + 4; + ascent_ = expanded_.ascent() + 2; + descent_ = expanded_.descent() + 2; + + width_ += mathed_string_width(font_, name()) + 10; + + int lasc; + int ldes; + int lwid; + mathed_string_dim(font_, "#1: ", lasc, ldes, lwid); + + for (idx_type i = 0; i < nargs(); ++i) { + MathXArray const & c = xcell(i); + c.metrics(mi_); + width_ = max(width_, c.width() + lwid); + descent_ += max(c.ascent(), lasc) + 5; + descent_ += max(c.descent(), ldes) + 5; + } + return; } - } -} -#endif - -/*--------------- Macro argument -----------------------------------*/ - -MathMacroArgument::MathMacroArgument(int n) -{ - number = n; - expnd_mode = false; - SetType(LM_OT_MACRO_ARG); -} - - -void MathMacroArgument::draw(Painter & pain, int x, int baseline) -{ - if (expnd_mode) { - MathParInset::draw(pain, x, baseline); - } else { -#ifdef HAVE_SSTREAM - ostringstream ost; - ost << '#' << number; - drawStr(pain, LM_TC_TEX, size, x, baseline, ost.str().c_str(), 2); -#else - char s[3]; - ostrstream ost(s, 3); - ost << '#' << number << '\0'; - drawStr(pain, LM_TC_TEX, size, x, baseline, - reinterpret_cast(ost.str()), 2); -#endif - } + expand(); + expanded_.data().substitute(*this); + expanded_.metrics(mi_); + width_ = expanded_.width(); + ascent_ = expanded_.ascent(); + descent_ = expanded_.descent(); } -void MathMacroArgument::Metrics() +void MathMacro::draw(MathPainterInfo & pi, int x, int y) const { - if (expnd_mode) { - MathParInset::Metrics(); - } else { -#ifdef HAVE_SSTREAM - ostringstream ost; - ost << '#' << number; - width = mathed_string_width(LM_TC_TEX, size, ost.str().c_str(), 2); - mathed_string_height(LM_TC_TEX, size, - ost.str().c_str(), 2, ascent, descent); -#else - char s[3]; - ostrstream ost(s, 3); - ost << '#' << number << '\0'; - width = mathed_string_width(LM_TC_TEX, size, - reinterpret_cast - (ost.str()), 2); - mathed_string_height(LM_TC_TEX, size, - reinterpret_cast(ost.str()), - 2, ascent, descent); -#endif - } -} + metrics(mi_); + LyXFont texfont; + augmentFont(texfont, "lyxtex"); -void MathMacroArgument::Write(ostream & os) -{ -#ifdef USE_OSTREAM_ONLY - if (expnd_mode) { - MathParInset::Write(os); - } else { - os << '#' << number << ' '; - } -#else - string output; - MathMacroArgument::Write(output); - os << output; -#endif -} - - -#ifndef USE_OSTREAM_ONLY -void MathMacroArgument::Write(string & file) -{ - if (expnd_mode) { - MathParInset::Write(file); - } else { - file += '#'; - file += tostr(number); - file += ' '; - } -} -#endif - - -/* --------------------- MathMacroTemplate ---------------------------*/ - -MathMacroTemplate::MathMacroTemplate(char const * nm, int na, int flg): - MathParInset(LM_ST_TEXT, nm, LM_OT_MACRO), - flags(flg), nargs(na) -{ - if (nargs > 0) { - tcode = LM_TC_ACTIVE_INSET; - args = new MathMacroArgument[nargs]; - for (int i = 0; i < nargs; ++i) { - args[i].setNumber(i + 1); + if (defining()) { + drawStr(pi, texfont, x, y, name()); + return; } - } else - tcode = LM_TC_INSET; -} - - -MathMacroTemplate::~MathMacroTemplate() -{ - // prevent to delete already deleted objects - for (int i = 0; i < nargs; ++i) { - args[i].SetData(0); - } - delete[] args; -} - -void MathMacroTemplate::setEditMode(bool ed) -{ - if (ed) { - flags |= MMF_Edit; - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(false); + if (editing()) { + int h = y - ascent() + 2 + expanded_.ascent(); + drawStr(pi, font_, x + 3, h, name()); + + int const w = mathed_string_width(font_, name()); + expanded_.draw(pi, x + w + 12, h); + h += expanded_.descent(); + + int lasc; + int ldes; + int lwid; + mathed_string_dim(font_, "#1: ", lasc, ldes, lwid); + + for (idx_type i = 0; i < nargs(); ++i) { + MathXArray const & c = xcell(i); + h += max(c.ascent(), lasc) + 5; + c.draw(pi, x + lwid, h); + char str[] = "#1:"; + str[1] += static_cast(i); + drawStr(pi, texfont, x + 3, h, str); + h += max(c.descent(), ldes) + 5; + } + return; } - } else { - flags &= ~MMF_Edit; - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(true); - } - } -} - -void MathMacroTemplate::draw(Painter & pain, int x, int y) -{ - int x2, y2; - bool expnd = (nargs > 0) ? args[0].getExpand(): false; - if (flags & MMF_Edit) { - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(false); - } - x2 = x; y2 = y; - } else { - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(true); - } - x2 = xo; y2 = yo; - } - MathParInset::draw(pain, x, y); - xo = x2; yo = y2; - - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(expnd); - } + expanded_.draw(pi, x, y); } -void MathMacroTemplate::Metrics() +void MathMacro::dump() const { - bool expnd = (nargs>0) ? args[0].getExpand(): false; - - if (flags & MMF_Edit) { - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(false); - } - } else { - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(true); - } - } - MathParInset::Metrics(); - - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(expnd); - } + MathMacroTable::dump(); + lyxerr << "\n macro: '" << this << "'\n"; + lyxerr << " name: '" << name() << "'\n"; + lyxerr << " template: '"; + WriteStream wi(lyxerr); + tmplate_->write(wi); + lyxerr << "'\n"; } -void MathMacroTemplate::update(MathMacro * macro) +bool MathMacro::idxUpDown(idx_type & idx, bool up) const { - int idx = (macro) ? macro->getArgumentIdx(): 0; - for (int i = 0; i < nargs; ++i) { - if (macro) { - macro->setArgumentIdx(i); - args[i].SetData(macro->GetData()); - MathedRowSt *row = macro->getRowSt(); - args[i].setRowSt(row); - } - } - if (macro) - macro->setArgumentIdx(idx); + pos_type pos; + return + up ? MathNestInset::idxLeft(idx, pos) : MathNestInset::idxRight(idx, pos); } - -void MathMacroTemplate::WriteDef(ostream & os) -{ - os << "\n\\newcommand{\\" << name << "}"; - - if (nargs > 0 ) - os << "[" << nargs << "]"; - - os << "{"; - - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(false); - } - Write(os); - os << "}\n"; -} - -#ifndef USE_OSTREAM_ONLY -void MathMacroTemplate::WriteDef(string & file) +bool MathMacro::idxLeft(idx_type &, pos_type &) const { - file += "\n\\newcommand{\\"; - file += name; - file += '}'; - - if (nargs > 0 ) { - file += '['; - file += tostr(nargs); - file += ']'; - } - - file += '{'; - - for (int i = 0; i < nargs; ++i) { - args[i].setExpand(false); - } - Write(file); - file += "}\n"; + return false; } -#endif -void MathMacroTemplate::setArgument(LyxArrayBase * a, int i) +bool MathMacro::idxRight(idx_type &, pos_type &) const { - args[i].SetData(a); + return false; } -void MathMacroTemplate::GetMacroXY(int i, int & x, int & y) const +void MathMacro::validate(LaTeXFeatures & features) const { - args[i].GetXY(x, y); + if (name() == "binom" || name() == "mathcircumflex") + features.require(name()); + //MathInset::validate(features); } -MathParInset * MathMacroTemplate::getMacroPar(int i) const +void MathMacro::maplize(MapleStream & os) const { - return (i >= 0 && i < nargs) ? static_cast(&args[i]) : 0; + updateExpansion(); + ::maplize(expanded_.data(), os); } -void MathMacroTemplate::SetMacroFocus(int &idx, int x, int y) +void MathMacro::mathmlize(MathMLStream & os) const { - for (int i = 0; i < nargs; ++i) { - if (args[i].Inside(x, y)) { - idx = i; - break; - } - } + updateExpansion(); + ::mathmlize(expanded_.data(), os); } -/* -------------------------- MathMacroTable -----------------------*/ - -MathMacroTable::MathMacroTable(int n) : max_macros(n) +void MathMacro::octavize(OctaveStream & os) const { - macro_table = new MathMacroTemplateP[max_macros]; - num_macros = 0; + updateExpansion(); + ::octavize(expanded_.data(), os); } -MathMacroTable::~MathMacroTable() +void MathMacro::normalize(NormalStream & os) const { - delete[] macro_table; + os << "[macro " << name() << " "; + for (idx_type i = 0; i < nargs(); ++i) + os << cell(i) << ' '; + os << ']'; } -// The search is currently linear but will be binary or hash, later. -MathMacroTemplate * MathMacroTable::getTemplate(char const * name) const -{ - for (int i = 0; i < num_macros; ++i) { - if (strcmp(name, macro_table[i]->GetName()) == 0) - return macro_table[i]; - } - - return 0; -} - -void MathMacroTable::addTemplate(MathMacroTemplate * m) +void MathMacro::write(WriteStream & os) const { - if (num_macros < max_macros) - macro_table[num_macros++] = m; - else - lyxerr << "Error (MathMacroTable::addTemplate): " - "Macro table exhausted!" << endl; + os << '\\' << name(); + for (idx_type i = 0; i < nargs(); ++i) + os << '{' << cell(i) << '}'; + if (nargs() == 0) + os << ' '; } -// All this stuff aparently leaks because it's created here and is not -// deleted never, but it have to live all the LyX sesion. OK, would not -// so hard to do it in the MacroTable destructor, but this doesn't harm -// seriously, so don't bother me with purify results here. ;-) - -void MathMacroTable::builtinMacros() +void MathMacro::updateExpansion() const { - MathedIter iter; - MathParInset * inset;// *arg; - LyxArrayBase * array2; - - built = true; - - lyxerr[Debug::MATHED] << "Building macros" << endl; - - // This macro doesn't have arguments - MathMacroTemplate * m = new MathMacroTemplate("notin"); // this leaks - addTemplate(m); - LyxArrayBase * array = new LyxArrayBase; // this leaks - iter.SetData(array); - iter.Insert(new MathAccentInset(LM_in, LM_TC_BOPS, LM_not)); // this leaks - m->SetData(array); - - // These two are only while we are still with LyX 2.x - m = new MathMacroTemplate("emptyset"); // this leaks - addTemplate(m); - array = new LyxArrayBase; // this leaks - iter.SetData(array); - iter.Insert(new MathAccentInset('O', LM_TC_RM, LM_not)); // this leaks - m->SetData(array); - - m = new MathMacroTemplate("perp"); // this leaks - addTemplate(m); - array = new LyxArrayBase; // this leaks - iter.SetData(array); - iter.Insert(LM_bot, LM_TC_BOP); - m->SetData(array); - - // binom has two arguments - m = new MathMacroTemplate("binom", 2); - addTemplate(m); - array = new LyxArrayBase; - m->SetData(array); - iter.SetData(array); - inset = new MathDelimInset('(', ')'); - iter.Insert(inset, LM_TC_ACTIVE_INSET); - array = new LyxArrayBase; - iter.SetData(array); - MathFracInset *frac = new MathFracInset(LM_OT_ATOP); - iter.Insert(frac, LM_TC_ACTIVE_INSET); - inset->SetData(array); - array = new LyxArrayBase; - array2 = new LyxArrayBase; - iter.SetData(array); - iter.Insert(m->getMacroPar(0)); - iter.SetData(array2); - iter.Insert(m->getMacroPar(1)); - frac->SetData(array, array2); - -/* - // Cases has 1 argument - m = new MathMacroTemplate("cases", 1, MMF_Env); // this leaks - addTemplate(m); - array = new LyxArrayBase; // this leaks - iter.SetData(array); - arg = new MathMatrixInset(2, 1); // this leaks - - m->setArgument(arg); - arg->SetAlign('c', "ll"); - iter.Insert(arg, LM_TC_ACTIVE_INSET); - inset = new MathDelimInset('{', '.'); // this leaks - inset->SetData(array); - array = new LyxArrayBase; // this leaks - iter.SetData(array); - iter.Insert(inset, LM_TC_ACTIVE_INSET); - m->SetData(array); - - - // the environment substack has 1 argument - m = new MathMacroTemplate("substack", 1, MMF_Env); // this leaks - addTemplate(m); - arg = new MathMatrixInset(1, 1); // this leaks - m->setArgument(arg); - arg->SetType(LM_OT_MACRO); - array = new LyxArrayBase; // this leaks - iter.SetData(array); - iter.Insert(arg, LM_TC_ACTIVE_INSET); - m->SetData(array);*/ + expand(); + expanded_.data().substitute(*this); } - - -MathMacroTable MathMacroTable::mathMTable(255); -bool MathMacroTable::built = false;