4 * Purpose: Implementation of macro class for mathed
5 * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
6 * Created: November 1996
7 * Description: WYSIWYG math macros
11 * Copyright: 1996, 1997 Alejandro Aguilar Sierra
13 * Version: 0.2, Mathed & Lyx project.
15 * This code is under the GNU General Public Licence version 2 or later.
19 #include FORMS_H_LOCATION
22 #pragma implementation "math_macro.h"
23 #pragma implementation "math_defs.h"
27 #include "math_macro.h"
28 #include "math_iter.h"
29 #include "math_inset.h"
30 #include "support/lstrings.h"
36 ostream & operator<<(ostream & o, MathedTextCodes mtc)
41 enum MathedMacroFlag {
47 ostream & operator<<(ostream & o, MathedMacroFlag mmf)
52 extern int mathed_string_width(short type, int style, string const & s);
53 extern int mathed_string_height(short, int, string const &, int &, int &);
56 MathMacro::MathMacro(MathMacroTemplate* t):
57 MathParInset(LM_ST_TEXT, "", LM_OT_MACRO), tmplate(t)
59 nargs = tmplate->getNoArgs();
60 tcode = tmplate->getTCode();
62 for (int i = 0; i < nargs; ++i) {
66 SetName(tmplate->GetName());
70 MathMacro::MathMacro(MathMacro * m):
71 MathParInset(LM_ST_TEXT, m->GetName(), LM_OT_MACRO)
74 nargs = tmplate->getNoArgs();
75 tcode = tmplate->getTCode();
78 SetName(tmplate->GetName());
79 for (int i = 0; i < tmplate->nargs; ++i) {
81 MathedIter it(m->GetData());
82 args_[i].row = m->args_[i].row;
83 args_[i].array = it.Copy();
87 MathMacro::~MathMacro()
89 for (idx = 0; idx < nargs; ++idx) {
90 MathedIter it(args_[idx].array);
92 delete args_[idx].row;
97 MathedInset * MathMacro::Clone()
99 return new MathMacro(this);
103 void MathMacro::Metrics()
106 tmplate->update(this);
107 tmplate->SetStyle(size);
109 width = tmplate->Width();
110 ascent = tmplate->Ascent();
111 descent = tmplate->Descent();
115 void MathMacro::draw(Painter & pain, int x, int y)
119 tmplate->update(this);
120 tmplate->SetStyle(size);
121 tmplate->draw(pain, x, y);
122 for (int i = 0; i < nargs; ++i) {
123 tmplate->GetMacroXY(i, args_[i].x, args_[i].y);
128 int MathMacro::GetColumns() const
130 return tmplate->getMacroPar(idx)->GetColumns();
134 void MathMacro::GetXY(int & x, int & y) const
136 x = args_[idx].x; y = args_[idx].y;
140 bool MathMacro::Permit(short f) const
143 tmplate->getMacroPar(idx)->Permit(f) : MathParInset::Permit(f);
147 void MathMacro::SetFocus(int x, int y)
149 tmplate->update(this);
150 tmplate->SetMacroFocus(idx, x, y);
154 void MathMacro::Write(ostream & os, bool fragile)
156 if (tmplate->flags & MMF_Exp) {
157 lyxerr[Debug::MATHED] << "Expand " << tmplate->flags
158 << ' ' << MMF_Exp << endl;
159 tmplate->update(this);
160 tmplate->Write(os, fragile);
162 if (tmplate->flags & MMF_Env) {
175 if (!(tmplate->flags & MMF_Env) && nargs > 0)
178 for (int i = 0; i < nargs; ++i) {
179 array = args_[i].array;
180 MathParInset::Write(os, fragile);
184 if (tmplate->flags & MMF_Env) {
198 /*--------------- Macro argument -----------------------------------*/
200 MathMacroArgument::MathMacroArgument(int n)
204 SetType(LM_OT_MACRO_ARG);
208 void MathMacroArgument::draw(Painter & pain, int x, int baseline)
211 MathParInset::draw(pain, x, baseline);
214 std::ostringstream ost;
215 ost << '#' << number;
216 drawStr(pain, LM_TC_TEX, size, x, baseline, ost.str().c_str());
221 void MathMacroArgument::Metrics()
224 MathParInset::Metrics();
227 std::ostringstream ost;
228 ost << '#' << number;
229 width = mathed_string_width(LM_TC_TEX, size, ost.str().c_str());
230 mathed_string_height(LM_TC_TEX, size, ost.str().c_str(),
236 void MathMacroArgument::Write(ostream & os, bool fragile)
239 MathParInset::Write(os, fragile);
241 os << '#' << number << ' ';
246 /* --------------------- MathMacroTemplate ---------------------------*/
248 MathMacroTemplate::MathMacroTemplate(string const & nm, int na, int flg):
249 MathParInset(LM_ST_TEXT, nm, LM_OT_MACRO),
250 flags(flg), nargs(na)
253 tcode = LM_TC_ACTIVE_INSET;
255 for (int i = 0; i < nargs; ++i) {
256 args_[i].setNumber(i + 1);
260 // Here is nargs != args_.size()
266 MathMacroTemplate::~MathMacroTemplate()
268 // prevent to delete already deleted objects
269 for (int i = 0; i < nargs; ++i) {
275 void MathMacroTemplate::setEditMode(bool ed)
279 for (int i = 0; i < nargs; ++i) {
280 args_[i].setExpand(false);
285 for (int i = 0; i < nargs; ++i) {
286 args_[i].setExpand(true);
292 void MathMacroTemplate::draw(Painter & pain, int x, int y)
295 bool expnd = (nargs > 0) ? args_[0].getExpand(): false;
296 if (flags & MMF_Edit) {
297 for (int i = 0; i < nargs; ++i) {
298 args_[i].setExpand(false);
302 for (int i = 0; i < nargs; ++i) {
303 args_[i].setExpand(true);
307 MathParInset::draw(pain, x, y);
310 for (int i = 0; i < nargs; ++i) {
311 args_[i].setExpand(expnd);
316 void MathMacroTemplate::Metrics()
318 bool expnd = (nargs > 0) ? args_[0].getExpand(): false;
320 if (flags & MMF_Edit) {
321 for (int i = 0; i < nargs; ++i) {
322 args_[i].setExpand(false);
325 for (int i = 0; i < nargs; ++i) {
326 args_[i].setExpand(true);
329 MathParInset::Metrics();
331 for (int i = 0; i < nargs; ++i) {
332 args_[i].setExpand(expnd);
337 void MathMacroTemplate::update(MathMacro * macro)
339 int idx = (macro) ? macro->getArgumentIdx() : 0;
340 for (int i = 0; i < nargs; ++i) {
342 macro->setArgumentIdx(i);
343 args_[i].SetData(macro->GetData());
344 MathedRowSt * row = macro->getRowSt();
345 args_[i].setRowSt(row);
349 macro->setArgumentIdx(idx);
353 void MathMacroTemplate::WriteDef(ostream & os, bool fragile)
355 os << "\n\\newcommand{\\" << name << "}";
358 os << "[" << nargs << "]";
362 for (int i = 0; i < nargs; ++i) {
363 args_[i].setExpand(false);
370 void MathMacroTemplate::setArgument(MathedArray * a, int i)
376 void MathMacroTemplate::GetMacroXY(int i, int & x, int & y) const
378 args_[i].GetXY(x, y);
382 MathParInset * MathMacroTemplate::getMacroPar(int i) const
384 if (i >= 0 && i < nargs)
385 return const_cast<MathParInset *>
386 (static_cast<MathParInset const *>(&args_[i]));
392 void MathMacroTemplate::SetMacroFocus(int &idx, int x, int y)
394 for (int i = 0; i < nargs; ++i) {
395 if (args_[i].Inside(x, y)) {
403 /* -------------------------- MathMacroTable -----------------------*/
405 MathMacroTable::MathMacroTable(int n) : max_macros(n)
407 macro_table = new MathMacroTemplateP[max_macros];
412 MathMacroTable::~MathMacroTable()
414 delete[] macro_table;
418 // The search is currently linear but will be binary or hash, later.
419 MathMacroTemplate * MathMacroTable::getTemplate(string const & name) const
421 for (int i = 0; i < num_macros; ++i) {
422 if (name == macro_table[i]->GetName())
423 return macro_table[i];
429 void MathMacroTable::addTemplate(MathMacroTemplate * m)
431 if (num_macros < max_macros)
432 macro_table[num_macros++] = m;
434 lyxerr << "Error (MathMacroTable::addTemplate): "
435 "Macro table exhausted!" << endl;
439 // All this stuff aparently leaks because it's created here and is not
440 // deleted never, but it have to live all the LyX sesion. OK, would not
441 // so hard to do it in the MacroTable destructor, but this doesn't harm
442 // seriously, so don't bother me with purify results here. ;-)
444 void MathMacroTable::builtinMacros()
447 MathParInset * inset;// *arg;
448 MathedArray * array2;
452 lyxerr[Debug::MATHED] << "Building macros" << endl;
454 // This macro doesn't have arguments
455 MathMacroTemplate * m = new MathMacroTemplate("notin"); // this leaks
457 MathedArray * array = new MathedArray; // this leaks
459 iter.Insert(new MathAccentInset(LM_in, LM_TC_BOPS, LM_not)); // this leaks
462 // These two are only while we are still with LyX 2.x
463 m = new MathMacroTemplate("emptyset"); // this leaks
465 array = new MathedArray; // this leaks
467 iter.Insert(new MathAccentInset('O', LM_TC_RM, LM_not)); // this leaks
470 m = new MathMacroTemplate("perp"); // this leaks
472 array = new MathedArray; // this leaks
474 iter.Insert(LM_bot, LM_TC_BOP);
477 // binom has two arguments
478 m = new MathMacroTemplate("binom", 2);
480 array = new MathedArray;
483 inset = new MathDelimInset('(', ')');
484 iter.Insert(inset, LM_TC_ACTIVE_INSET);
485 array = new MathedArray;
487 MathFracInset *frac = new MathFracInset(LM_OT_ATOP);
488 iter.Insert(frac, LM_TC_ACTIVE_INSET);
489 inset->SetData(array);
490 array = new MathedArray;
491 array2 = new MathedArray;
493 iter.Insert(m->getMacroPar(0));
494 iter.SetData(array2);
495 iter.Insert(m->getMacroPar(1));
496 frac->SetData(array, array2);
499 // Cases has 1 argument
500 m = new MathMacroTemplate("cases", 1, MMF_Env); // this leaks
502 array = new MathedArray; // this leaks
504 arg = new MathMatrixInset(2, 1); // this leaks
507 arg->SetAlign('c', "ll");
508 iter.Insert(arg, LM_TC_ACTIVE_INSET);
509 inset = new MathDelimInset('{', '.'); // this leaks
510 inset->SetData(array);
511 array = new MathedArray; // this leaks
513 iter.Insert(inset, LM_TC_ACTIVE_INSET);
517 // the environment substack has 1 argument
518 m = new MathMacroTemplate("substack", 1, MMF_Env); // this leaks
520 arg = new MathMatrixInset(1, 1); // this leaks
522 arg->SetType(LM_OT_MACRO);
523 array = new MathedArray; // this leaks
525 iter.Insert(arg, LM_TC_ACTIVE_INSET);
530 MathMacroTable MathMacroTable::mathMTable(255);
531 bool MathMacroTable::built = false;