home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / math_macro.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  12KB  |  552 lines

  1. // -*- C++ -*-
  2. /*
  3.  *  File:        math_macro.C
  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
  8.  *
  9.  *  Dependencies: Mathed
  10.  *
  11.  *  Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra
  12.  *
  13.  *  Version: 0.2, Mathed & Lyx project.
  14.  *
  15.  *  This code is under the GNU General Public Licence version 2 or later.
  16.  */
  17.  
  18. #include <config.h>
  19. #include FORMS_H_LOCATION
  20.  
  21. #ifdef __GNUG__
  22. #pragma implementation "math_macro.h"
  23. #pragma implementation "math_defs.h"
  24. #endif
  25.  
  26. #include "LString.h"
  27. #include "math_macro.h"
  28. #include "math_iter.h"
  29. #include "math_inset.h"
  30. #include "error.h"
  31.  
  32.  
  33. enum MathedMacroFlag {
  34.     MMF_Env=1,
  35.     MMF_Exp=2,
  36.     MMF_Edit=4
  37. };
  38.  
  39.  
  40. extern GC mathGC, mathFrameGC, latexGC;
  41. extern int mathed_string_width(short type, int style, byte const* s, int ls);
  42. extern int mathed_string_height(short, int, byte const*, int, int&, int&);
  43.  
  44.  
  45. MathMacro::MathMacro(MathMacroTemplate* t): 
  46.     MathParInset(LM_ST_TEXT, "", LM_OT_MACRO), tmplate(t)
  47. {
  48.     nargs = tmplate->getNoArgs();
  49.     tcode = tmplate->getTCode();
  50.     args = new MacroArgumentBase[nargs];
  51.     for (int i=0; i<nargs; i++) {
  52. //    if (tmplate->getMacroPar(i)->Permit(LMPF_ALLOW_CR))
  53. //      args[i].row = new MathedRowSt(tmplate->getMacroPar(i)->GetColumns());
  54. //    else 
  55.       args[i].row = 0;
  56. /*    int k = tmplate->getMacroPar(i)->GetColumns();
  57.     if (k>0) {
  58.         args[i].array = new LyxArrayBase;
  59.         for (int j=0; j<k-1; j++) args[i].array->Insert(j, LM_TC_TAB);
  60.     }*/
  61.     }
  62.     idx = 0;
  63.     SetName(tmplate->GetName());
  64. }
  65.  
  66. MathMacro::MathMacro(MathMacro* m): 
  67.     MathParInset(LM_ST_TEXT, m->GetName(), LM_OT_MACRO)
  68. {
  69.     tmplate = m->tmplate;
  70.     nargs = tmplate->getNoArgs();
  71.     tcode = tmplate->getTCode();
  72.     args = new MacroArgumentBase[nargs];
  73.     idx = 0;
  74.     SetName(tmplate->GetName());
  75.     for (int i=0; i<tmplate->nargs; i++) {
  76.     m->setArgumentIdx(i);
  77.     MathedIter it(m->GetData());
  78.     args[i].row = m->args[i].row;
  79.     args[i].array = it.Copy();
  80.     }
  81. }
  82.  
  83. MathMacro::~MathMacro()
  84. {
  85.     for (idx=0; idx<nargs; idx++) {
  86.     MathedIter it(args[idx].array);
  87.     it. Clear();
  88.     delete args[idx].row;
  89.     }
  90.     delete[] args;
  91. }
  92.  
  93.  
  94. MathedInset *MathMacro::Clone()
  95. {
  96.     MathMacro *m = new MathMacro(this);
  97.     return m;
  98. }
  99.  
  100.  
  101. void MathMacro::Metrics()
  102. {
  103.     if (nargs>0)
  104.       tmplate->update(this);
  105.     tmplate->Metrics();
  106.     width = tmplate->Width();
  107.     ascent = tmplate->Ascent();
  108.     descent = tmplate->Descent();
  109. }
  110.  
  111.  
  112. void MathMacro::Draw(int x, int y)
  113. {
  114.     xo = x;  yo = y;
  115.     Metrics();
  116.     tmplate->update(this);
  117.     tmplate->SetStyle(size);
  118.     mathGC = latexGC;
  119.     tmplate->Draw(x, y);
  120.     for (int i=0; i<nargs; i++)
  121.       tmplate->GetMacroXY(i, args[i].x, args[i].y);
  122. }
  123.  
  124.  
  125. int MathMacro::GetColumns()
  126. {
  127.     return tmplate->getMacroPar(idx)->GetColumns();
  128. }
  129.  
  130.  
  131. void MathMacro::GetXY(int& x, int& y) const
  132. {
  133.     x = args[idx].x;  y = args[idx].y;
  134. }
  135.  
  136.  
  137. bool MathMacro::Permit(short f)
  138. {
  139.     return ((nargs>0) ? tmplate->getMacroPar(idx)->Permit(f): MathParInset::Permit(f));
  140. }
  141.  
  142. void MathMacro::SetFocus(int x, int y)
  143. {
  144.     tmplate->update(this);
  145.     tmplate->SetMacroFocus(idx, x, y);
  146. }
  147.  
  148.  
  149. void MathMacro::Write(FILE *file)
  150. {
  151.    LString output;
  152.    MathMacro::Write(output);
  153.    fprintf(file, "%s", output.c_str());
  154. }
  155.  
  156.  
  157. void MathMacro::Write(LString &file)
  158. {
  159.     if (tmplate->flags & MMF_Exp) {
  160.     lyxerr.debug(LString("Expand ")+tmplate->flags+' '+int(MMF_Exp), 
  161.              Error::MATHED);
  162.     tmplate->update(this);
  163.     tmplate->Write(file);
  164.     } else {
  165.     if (tmplate->flags & MMF_Env) {
  166.       file += "\\begin{";
  167.       file += name;
  168.       file += "} ";
  169.     } else {
  170.       file += '\\';
  171.       file += name;
  172.     }
  173. //    if (options) { 
  174. //      file += '[';
  175. //      file += options;
  176. //      file += ']';
  177. //      }
  178.     
  179.     if (!(tmplate->flags & MMF_Env) && nargs>0) 
  180.       file += '{';
  181.     
  182.     for (int i=0; i<nargs; i++) {
  183.         array = args[i].array;
  184.         MathParInset::Write(file);
  185.         if (i<nargs-1)  
  186.           file += "}{";
  187.     }   
  188.     if (tmplate->flags & MMF_Env) {
  189.         file += "\\end{";
  190.         file += name;
  191.         file += '}';
  192.     } else {
  193.         if (nargs>0) 
  194.             file += '}';
  195.         else
  196.             file += ' ';
  197.     }
  198.     }
  199. }
  200.  
  201.  
  202.  
  203. /*---------------  Macro argument -----------------------------------*/
  204.  
  205. MathMacroArgument::MathMacroArgument(int n)
  206. {
  207.     number = n;
  208.     expnd_mode = false;
  209.     SetType(LM_OT_MACRO_ARG);
  210. }
  211.  
  212. void MathMacroArgument::Draw(int x, int baseline)
  213. {
  214.     if (expnd_mode) {
  215.     MathParInset::Draw(x, baseline);
  216.     } else {
  217.     unsigned char s[3];
  218.     sprintf((char*)s, "#%d", number);
  219.     drawStr(LM_TC_TEX, size, x, baseline, &s[0], 2);
  220.     }
  221. }
  222.  
  223.  
  224. void MathMacroArgument::Metrics()
  225. {
  226.     if (expnd_mode) {
  227.     MathParInset::Metrics();
  228.     } else {
  229.     unsigned char s[3];
  230.     sprintf((char*)s, "#%d", number);
  231.     width = mathed_string_width(LM_TC_TEX, size, &s[0], 2);
  232.     mathed_string_height(LM_TC_TEX, size, &s[0], 2, ascent, descent);
  233.     }
  234. }
  235.  
  236. void MathMacroArgument::Write(FILE *file)
  237. {
  238.    LString output;
  239.    MathMacroArgument::Write(output);
  240.    fprintf(file, "%s", output.c_str());
  241. }
  242.  
  243. void MathMacroArgument::Write(LString &file)
  244. {
  245.     if (expnd_mode) {
  246.     MathParInset::Write(file);
  247.     } else {
  248.     file += '#';
  249.     file += number;
  250.     file += ' ';
  251.     }
  252. }
  253.  
  254.  
  255. /* --------------------- MathMacroTemplate ---------------------------*/
  256.  
  257. MathMacroTemplate::MathMacroTemplate(char const *nm, int na, int flg):
  258.     MathParInset(LM_ST_TEXT, nm, LM_OT_MACRO), 
  259.     flags(flg), nargs(na)
  260. {
  261.     if (nargs>0) {
  262.     tcode = LM_TC_ACTIVE_INSET;
  263.     args = new MathMacroArgument[nargs];
  264.     for (int i=0; i<nargs; i++) {
  265.         args[i].setNumber(i+1);
  266.     }
  267.     } else 
  268.       tcode = LM_TC_INSET;
  269. }
  270.  
  271.  
  272. MathMacroTemplate::~MathMacroTemplate()
  273. {
  274.     // prevent to delete already deleted objects
  275.     for (int i=0; i<nargs; i++) {
  276.     args[i].SetData(0);
  277.     }
  278.     delete[] args;
  279. }
  280.  
  281.  
  282. void MathMacroTemplate::setEditMode(bool ed)
  283. {
  284.     if (ed) {
  285.     flags |= MMF_Edit;
  286.     for (int i=0; i<nargs; i++) {
  287.         args[i].setExpand(false);
  288.     }
  289.     } else {
  290.     flags &= ~MMF_Edit;
  291.     for (int i=0; i<nargs; i++) {
  292.         args[i].setExpand(true);
  293.     }
  294.     }
  295. }
  296.  
  297.  
  298. void MathMacroTemplate::Draw(int x, int y)
  299. {
  300.     int x2, y2;
  301.     bool expnd = (nargs>0) ? args[0].getExpand(): false;
  302.     if (flags & MMF_Edit) {
  303.     for (int i=0; i<nargs; i++) {
  304.         args[i].setExpand(false);
  305.     }
  306.       x2 = x; y2 = y;
  307.     } else {
  308.     for (int i=0; i<nargs; i++) {
  309.         args[i].setExpand(true);
  310.     }
  311.       x2 = xo; y2 = yo;
  312.     }
  313.     MathParInset::Draw(x, y);
  314.     xo = x2; yo = y2;
  315.     
  316.     for (int i=0; i<nargs; i++) {
  317.     args[i].setExpand(expnd);
  318.     }
  319. }
  320.  
  321. void MathMacroTemplate::Metrics()
  322. {
  323.     bool expnd = (nargs>0) ? args[0].getExpand(): false;
  324.     
  325.     if (flags & MMF_Edit) {
  326.     for (int i=0; i<nargs; i++) {
  327.         args[i].setExpand(false);
  328.     }
  329.     } else {
  330.     for (int i=0; i<nargs; i++) {
  331.         args[i].setExpand(true);
  332.     }
  333.     }
  334.     MathParInset::Metrics();
  335.     
  336.     for (int i=0; i<nargs; i++) {
  337.     args[i].setExpand(expnd);
  338.     }
  339. }
  340.  
  341. void MathMacroTemplate::update(MathMacro* macro)
  342. {
  343.     int idx = (macro) ? macro->getArgumentIdx(): 0;
  344.     for (int i=0; i<nargs; i++) {
  345.     if (macro) {
  346.         macro->setArgumentIdx(i);
  347.         args[i].SetData(macro->GetData());
  348.         MathedRowSt *row = macro->getRowSt();
  349.         args[i].setRowSt(row);
  350.     }
  351.     }    
  352.     if (macro)
  353.       macro->setArgumentIdx(idx);
  354. }
  355.     
  356.  
  357. void MathMacroTemplate::WriteDef(FILE *file)
  358. {
  359.     fprintf(file, "\n\\newcommand{\\%s}", name);
  360.       
  361.     if (nargs > 0 ) 
  362.       fprintf(file, "[%d]", nargs);
  363.     
  364.     fprintf(file, "{");
  365.     
  366.     for (int i=0; i<nargs; i++) {
  367.     args[i].setExpand(false);
  368.     }     
  369.     Write(file); 
  370.     fprintf(file, "}\n");
  371. }
  372.  
  373. void MathMacroTemplate::WriteDef(LString &file)
  374. {
  375.     file += "\n\\newcommand{\\";
  376.     file += name;
  377.     file += '}';
  378.       
  379.     if (nargs > 0 ) {
  380.       file += '[';
  381.       file += nargs;
  382.       file += ']';
  383.     }
  384.     
  385.     file += '{';
  386.     
  387.     for (int i=0; i<nargs; i++) {
  388.     args[i].setExpand(false);
  389.     }     
  390.     Write(file); 
  391.     file += "}\n";
  392. }
  393.  
  394. void MathMacroTemplate::setArgument(LyxArrayBase *a, int i)
  395. {
  396.     args[i].SetData(a);
  397. }
  398.  
  399. void MathMacroTemplate::GetMacroXY(int i, int& x, int& y) const
  400. {
  401.     args[i].GetXY(x, y);
  402. }
  403.  
  404.  
  405. MathParInset *MathMacroTemplate::getMacroPar(int i) const
  406. {
  407.     return ((i>=0 && i<nargs) ? (MathParInset*)&args[i]: 0);
  408. }
  409.  
  410.  
  411. void MathMacroTemplate::SetMacroFocus(int &idx, int x, int y)
  412. {
  413.     for (int i=0; i<nargs; i++) {
  414.     if (args[i].Inside(x, y)) {
  415.         idx = i;
  416.         break;
  417.     }
  418.     }
  419. }
  420.  
  421.  
  422. /* -------------------------- MathMacroTable -----------------------*/
  423.  
  424. MathMacroTable::MathMacroTable(int n): max_macros(n)
  425. {
  426.     macro_table = new MathMacroTemplateP[max_macros];
  427.     num_macros = 0;
  428. }
  429.  
  430.  
  431. MathMacroTable::~MathMacroTable()
  432. {
  433.     delete[] macro_table;
  434. }
  435.  
  436.  
  437. // The search is currently linear but will be binary or hash, later.
  438. MathMacroTemplate *MathMacroTable::getTemplate(char const* name) const
  439. {
  440.     for (int i=0; i<num_macros; i++) {
  441.       if (strcmp(name, macro_table[i]->GetName())==0) 
  442.     return macro_table[i];
  443.     }
  444.     
  445.     return 0;
  446. }
  447.  
  448. void MathMacroTable::addTemplate(MathMacroTemplate *m)
  449. {
  450.     if (num_macros<max_macros)
  451.       macro_table[num_macros++] = m;
  452.     else
  453.       lyxerr.print("Error (MathMacroTable::addTemplate): "
  454.            "Macro table exhausted!");
  455. }
  456.  
  457.  
  458. // All this stuff aparently leaks because it's created here and is not 
  459. // deleted never, but it have to live all the LyX sesion. OK, would not
  460. // so hard to do it in the MacroTable destructor, but this doesn't harm
  461. // seriously, so don't bother me with purify results here.   ;-)
  462.  
  463. void MathMacroTable::builtinMacros()
  464. {
  465.     MathMacroTemplate *m;
  466.     MathedIter iter;
  467.     MathParInset* inset;// *arg;
  468.     LyxArrayBase *array, *array2;
  469.     
  470.     built = true;
  471.     
  472.     lyxerr.debug("Building macros", Error::MATHED);
  473.     
  474.     // This macro doesn't have arguments
  475.     m = new MathMacroTemplate("notin");  // this leaks
  476.     addTemplate(m);
  477.     array = new LyxArrayBase; // this leaks
  478.     iter.SetData(array);
  479.     iter.Insert(new MathAccentInset(LM_in, LM_TC_BOPS, LM_not)); // this leaks
  480.     m->SetData(array);
  481.     
  482.     // These two are only while we are still with LyX 2.x
  483.     m = new MathMacroTemplate("emptyset"); // this leaks
  484.     addTemplate(m);
  485.     array = new LyxArrayBase; // this leaks
  486.     iter.SetData(array);
  487.     iter.Insert(new MathAccentInset('O', LM_TC_RM, LM_not)); // this leaks
  488.     m->SetData(array);
  489.     
  490.     m = new MathMacroTemplate("perp"); // this leaks
  491.     addTemplate(m);
  492.     array = new LyxArrayBase; // this leaks
  493.     iter.SetData(array);
  494.     iter.Insert(LM_bot, LM_TC_BOP);
  495.     m->SetData(array);
  496.  
  497.     // binom has two arguments
  498.     m = new MathMacroTemplate("binom", 2);
  499.     addTemplate(m);
  500.     array = new LyxArrayBase; 
  501.     m->SetData(array);
  502.     iter.SetData(array);
  503.     inset = new MathDelimInset('(', ')');
  504.     iter.Insert(inset, LM_TC_ACTIVE_INSET);
  505.     array = new LyxArrayBase; 
  506.     iter.SetData(array);
  507.     MathFracInset *frac = new MathFracInset(LM_OT_ATOP);
  508.     iter.Insert(frac, LM_TC_ACTIVE_INSET);
  509.     inset->SetData(array);
  510.     array = new LyxArrayBase;
  511.     array2 = new LyxArrayBase;  
  512.     iter.SetData(array);
  513.     iter.Insert(m->getMacroPar(0));
  514.     iter.SetData(array2);
  515.     iter.Insert(m->getMacroPar(1));
  516.     frac->SetData(array, array2);
  517.  
  518. /*
  519.     // Cases has 1 argument
  520.     m = new MathMacroTemplate("cases", 1, MMF_Env); // this leaks
  521.     addTemplate(m);
  522.     array = new LyxArrayBase; // this leaks
  523.     iter.SetData(array);
  524.     arg = new MathMatrixInset(2,1); // this leaks
  525.  
  526.     m->setArgument(arg);
  527.     arg->SetAlign('c',"ll");
  528.     iter.Insert(arg, LM_TC_ACTIVE_INSET);
  529.     inset = new MathDelimInset('{', '.'); // this leaks
  530.     inset->SetData(array);
  531.     array = new LyxArrayBase; // this leaks
  532.     iter.SetData(array);
  533.     iter.Insert(inset, LM_TC_ACTIVE_INSET);
  534.     m->SetData(array);
  535.   
  536.  
  537.     // the environment substack has 1 argument
  538.     m = new MathMacroTemplate("substack", 1, MMF_Env); // this leaks
  539.     addTemplate(m);     
  540.     arg = new MathMatrixInset(1,1); // this leaks
  541.     m->setArgument(arg);
  542.     arg->SetType(LM_OT_MACRO);
  543.     array = new LyxArrayBase; // this leaks
  544.     iter.SetData(array);
  545.     iter.Insert(arg, LM_TC_ACTIVE_INSET);
  546.     m->SetData(array);*/
  547. }
  548.  
  549. MathMacroTable MathMacroTable::mathMTable(255);
  550. bool  MathMacroTable::built = false;
  551.  
  552.