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_inset.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  11KB  |  540 lines

  1. /*
  2.  *  File:        math_inset.C
  3.  *  Purpose:     Implementation of insets for mathed
  4.  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
  5.  *  Created:     January 1996
  6.  *  Description: 
  7.  *
  8.  *  Dependencies: Xlib, XForms
  9.  *
  10.  *  Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra
  11.  *
  12.  *   Version: 0.8beta.
  13.  *
  14.  *   You are free to use and modify this code under the terms of
  15.  *   the GNU General Public Licence version 2 or later.
  16.  */
  17.  
  18. #include <config.h>
  19.  
  20. #ifdef __GNUG__
  21. #pragma implementation "math_inset.h"
  22. #endif
  23.  
  24. #include "math_iter.h"
  25. #include "math_inset.h"
  26. #include "symbol_def.h"
  27.  
  28.  
  29. inline
  30. char *strnew(char const* s)
  31. {
  32.    char *s1 = new char[strlen(s)+1];
  33.    return strcpy(s1, s);
  34. }
  35.  
  36.  
  37. MathedInset::MathedInset(MathedInset* inset) 
  38. {
  39.    if (inset) {
  40.       name = inset->GetName();
  41.       objtype = inset->GetType();
  42.       size = inset->GetStyle();
  43.       width = inset->Width();
  44.       ascent = inset->Ascent();
  45.       descent = inset->Descent();
  46.    } else {
  47.       objtype = LM_OT_UNDEF;
  48.       size = LM_ST_TEXT;
  49.       width = ascent = descent = 0;
  50.       name = 0;
  51.    }
  52. }
  53.  
  54.  
  55. MathFuncInset::MathFuncInset(char const *nm, short ot, short st):
  56.     MathedInset("", ot, st)
  57. {
  58.    ln = 0;
  59.    lims = (GetType()==LM_OT_FUNCLIM);
  60.     if (GetType()==LM_OT_UNDEF) {
  61.     fname = strnew(nm);
  62.     SetName(fname);
  63.     } else {
  64.     fname = 0;
  65.     SetName(nm);
  66.     }
  67. }
  68.  
  69. MathedInset *MathFuncInset::Clone()
  70.    MathedInset *l = new MathFuncInset(name, GetType(), GetStyle());
  71.    return l;
  72. }
  73.  
  74. MathSpaceInset::MathSpaceInset(int sp, short ot, short st):
  75.     MathedInset("", ot, st), space(sp)
  76. {
  77. }
  78.  
  79. MathedInset *MathSpaceInset::Clone()
  80.    MathedInset *l = new MathSpaceInset(space, GetType(), GetStyle());
  81.    return l;
  82. }
  83.  
  84. MathParInset::MathParInset(short st, char const *nm, short ot):
  85.    MathedInset(nm, ot, st)
  86. {
  87.     array = 0;
  88.     ascent = 8;
  89.     width = 4;
  90.     descent = 0;
  91.     flag = 1;
  92.     if (objtype==LM_OT_SCRIPT)
  93.       flag |= LMPF_SCRIPT;
  94. }
  95.  
  96. MathParInset::MathParInset(MathParInset* p): MathedInset(p)
  97. {
  98.     flag = p->flag;
  99.     p->setArgumentIdx(0);
  100.     MathedIter it(p->GetData());
  101.     SetData(it.Copy());
  102. }
  103.  
  104.  
  105. MathParInset::~MathParInset()
  106. {
  107.    if (array) {
  108.       MathedIter it(array);
  109.       it.Clear();
  110.       delete array;
  111.    }
  112. }
  113.  
  114.  
  115. MathedInset *MathParInset::Clone()
  116. {   
  117.    MathParInset* p = new MathParInset(this);
  118.    return p;
  119. }
  120.  
  121.  
  122. void MathParInset::SetData(LyxArrayBase *a)
  123. {
  124.     array = a;
  125.    
  126.     // A standard paragraph shouldn't have any tabs nor CRs.
  127.     if (array) {
  128.     MathedIter it(array);
  129.     while (it.OK()) {
  130.         char c = it.GetChar();
  131.         if (c==LM_TC_TAB || c==LM_TC_CR) 
  132.           it.Delete();
  133.         else
  134.           it.Next();
  135.     }
  136.    }
  137. }
  138.  
  139.  
  140. MathSqrtInset::MathSqrtInset(short st): MathParInset(st, "sqrt", LM_OT_SQRT)
  141. {    
  142. }
  143.  
  144.  
  145. MathedInset *MathSqrtInset::Clone()
  146. {   
  147.    MathSqrtInset* p = new MathSqrtInset(GetStyle());
  148.    MathedIter it(array);
  149.    p->SetData(it.Copy());
  150.    return p;
  151. }
  152.  
  153.  
  154. bool MathSqrtInset::Inside(int x, int y) 
  155. {
  156.     return (x>=xo-hmax && x<=xo+width-hmax && y<=yo+descent && y>=yo-ascent);
  157. }
  158.  
  159.  
  160. MathDelimInset::MathDelimInset(int l, int r, short st): 
  161.   MathParInset(st, "", LM_OT_DELIM), left(l), right(r)
  162. {
  163. }
  164.  
  165. MathedInset *MathDelimInset::Clone()
  166. {   
  167.    MathDelimInset* p = new MathDelimInset(left, right, GetStyle());
  168.    MathedIter it(array);
  169.    p->SetData(it.Copy());
  170.    return p;
  171. }
  172.  
  173.  
  174. MathDecorationInset::MathDecorationInset(int d, short st): 
  175.   MathParInset(st, "", LM_OT_DECO), deco(d)
  176. {
  177.    upper = (deco!=LM_underline && deco!=LM_underbrace);
  178. }
  179.  
  180. MathedInset *MathDecorationInset::Clone()
  181. {   
  182.    MathDecorationInset* p = new MathDecorationInset(deco, GetStyle());
  183.    MathedIter it(array);
  184.    p->SetData(it.Copy());
  185.    return p;
  186. }
  187.  
  188. MathFracInset::MathFracInset(short ot): MathParInset(LM_ST_TEXT, "frac", ot)
  189. {
  190.     
  191.     den = new MathParInset(LM_ST_TEXT); // this leaks
  192.     dh = 0;
  193.     idx = 0;
  194.     if (objtype==LM_OT_STACKREL) {
  195.     flag |= LMPF_SCRIPT;
  196.     SetName("stackrel");
  197.     }
  198. }
  199.  
  200. MathFracInset::~MathFracInset()
  201. {
  202.     delete den;
  203. }
  204.  
  205. MathedInset *MathFracInset::Clone()
  206. {   
  207.     MathFracInset* p = new MathFracInset(GetType());
  208.     MathedIter itn(array);
  209.     MathedIter itd(den->GetData());
  210.     p->SetData(itn.Copy(), itd.Copy());
  211.     p->idx = idx;
  212.     p->dh = dh;
  213.    return p;
  214. }
  215.  
  216. bool MathFracInset::setArgumentIdx(int i)
  217. {
  218.    if (i==0 || i==1) {
  219.        idx = i;
  220.        return true;
  221.    } else 
  222.       return false;
  223. }
  224.  
  225.  
  226. void MathFracInset::SetStyle(short st)
  227. {
  228.     MathParInset::SetStyle(st);
  229.     dh = 0;
  230.     den->SetStyle((size==LM_ST_DISPLAY) ? LM_ST_TEXT: size);
  231. }
  232.  
  233. void MathFracInset::SetData(LyxArrayBase *n, LyxArrayBase *d)
  234. {
  235.    den->SetData(d);
  236.    MathParInset::SetData(n);
  237. }
  238.  
  239. void MathFracInset::SetData(LyxArrayBase *d)
  240. {
  241.    if (idx==0)
  242.      MathParInset::SetData(d);
  243.    else {
  244.       den->SetData(d);
  245.    }
  246. }
  247.  
  248. void MathFracInset::GetXY(int& x, int& y) const
  249. {  
  250.    if (idx==0)
  251.      MathParInset::GetXY(x, y);
  252.    else
  253.      den->GetXY(x, y);
  254. }
  255.    
  256. LyxArrayBase *MathFracInset::GetData()
  257. {
  258.    if (idx==0)
  259.      return array;
  260.    else
  261.      return den->GetData();
  262. }
  263.  
  264.  
  265. bool MathFracInset::Inside(int x, int y) 
  266. {
  267.     int xx = xo - (width-w0)/2;
  268.     
  269.     return (x>=xx && x<=xx+width && y<=yo+descent && y>=yo-ascent);
  270. }
  271.  
  272. void MathFracInset::SetFocus(int /*x*/, int y)
  273. {  
  274. //    fprintf(stderr, "y %d %d %d ", y, yo, den->yo);
  275.     idx = (y > yo) ? 1: 0;
  276. }
  277.  
  278.  
  279. MathMatrixInset::MathMatrixInset(int m, int n, short st): 
  280.    MathParInset(st, "array", LM_OT_MATRIX), nc(m)
  281. {
  282.     ws = new int[nc]; 
  283.     v_align = 0;
  284.     h_align = new char[nc+1];
  285.     for (int i =0; i<nc; i++) h_align[i] = 'c'; 
  286.     h_align[nc] = '\0';
  287.     nr = 0;
  288.     row = 0;
  289.     flag = 15;
  290.     if (n>0) {
  291.         row = new MathedRowSt(nc+1);
  292.     MathedXIter it(this);
  293.     for (int i=1; i<n; i++) it.addRow();
  294.     nr = n;
  295.     if (nr==1 && nc>1) {
  296.         for (int i=0; i<nc-1; i++) 
  297.           it.Insert('T', LM_TC_TAB);
  298.     }
  299.     } else if (n<0) {
  300.         row = new MathedRowSt(nc+1);
  301.     nr = 1;
  302.     }
  303. }
  304.  
  305.  
  306. MathMatrixInset::MathMatrixInset(MathMatrixInset *mt): 
  307.    MathParInset(mt->GetStyle(), mt->GetName(), mt->GetType())
  308. {
  309.     nc = mt->nc;
  310.     nr = mt->nr;
  311.     ws = new int[nc];
  312.     h_align = new char[nc+1];
  313.     strcpy(h_align, mt->GetAlign(&v_align));
  314.     MathedIter it;   
  315.     it.SetData(mt->GetData());
  316.     array = it.Copy();
  317.     if (mt->row && (objtype==LM_OT_MPARN)) {
  318.     MathedRowSt *r, *ro=0, *mrow = mt->row;
  319.     for (int i=0; i<nr; i++) {
  320.         r = new MathedRowSt(nc+1);
  321.         r->numbered = mrow->numbered;
  322.         if (mrow->label) 
  323.           r->label = strnew(mrow->label);
  324.         if (!ro) 
  325.         row = r;
  326.         else
  327.           ro->next = r;
  328.         mrow = mrow->next;
  329.         ro = r;
  330.     } 
  331.     } else
  332.       row = 0;
  333.     
  334.     flag = mt->flag;
  335. }
  336.  
  337.  
  338. MathMatrixInset::~MathMatrixInset()
  339. {
  340.     delete[] ws;
  341.     
  342.     MathedRowSt *r = row;    
  343.     while (r) {
  344.     MathedRowSt *q = r->next;
  345.     delete r;
  346.     r = q;
  347.     }
  348. }
  349.  
  350. MathedInset *MathMatrixInset::Clone()
  351. {   
  352.    MathMatrixInset* mt = new MathMatrixInset(this);
  353.    return mt;
  354. }
  355.  
  356. void MathMatrixInset::SetAlign(char vv, char const* hh)
  357. {
  358.    v_align = vv;
  359.    strncpy(h_align, hh, nc);
  360. }
  361.  
  362.  
  363. // Check the number of tabs and crs
  364. void MathMatrixInset::SetData(LyxArrayBase *a)
  365. {
  366.     if (!a) return;
  367.     MathedIter it(a);
  368.     int nn = nc-1;
  369.     nr = 1;
  370.     // count tabs per row
  371.     while (it.OK()) {
  372.     if (it.IsTab()) {
  373.         if (nn<0) { 
  374.         it.Delete();
  375.         continue;
  376.         } else {
  377. //          it.Next();
  378.         nn--;
  379.         }
  380.     }
  381.     if (it.IsCR()) {
  382.         while (nn>0) {
  383.         it.Insert(' ', LM_TC_TAB);
  384.         nn--;
  385.         }
  386.         nn = nc-1;
  387.         nr++;
  388.     }
  389.     it.Next();
  390.     }  
  391.     it.Reset();
  392.  
  393.     // Automatically inserts tabs around bops
  394.     // DISABLED because it's very easy to insert tabs 
  395.     array = a;
  396. }
  397.  
  398.  
  399. void MathMatrixInset::Draw(int x, int baseline)
  400. {
  401.     MathParInset::Draw(x, baseline);
  402. }                
  403.  
  404. void MathMatrixInset::Metrics()
  405. {
  406.     int i, /*cy,*/ hl, h=0;
  407.     MathedRowSt *cprow=0, *cxrow;
  408.  
  409.     if (!row) {
  410. //    fprintf(stderr, " MIDA ");
  411.     MathedXIter it(this);
  412.     row = it.adjustVerticalSt();
  413.     } 
  414.     
  415.     // Clean the arrays      
  416.     cxrow = row;
  417.     while (cxrow) {   
  418.     for (i=0; i<=nc; i++) cxrow->w[i] = 0;
  419.     cxrow = cxrow->next;
  420.     }
  421.     
  422.     // Basic metrics
  423.     MathParInset::Metrics();
  424.         
  425.     if (nc<=1 && !row->next) {
  426.     row->asc = ascent;
  427.     row->desc = descent;
  428.     }
  429.     
  430.     // Vertical positions of each row
  431.     cxrow = row;     
  432.     while (cxrow) {
  433.     for (i=0; i<nc; i++) {
  434.         if (cxrow==row || ws[i]<cxrow->w[i]) ws[i]=cxrow->w[i];
  435.         if (cxrow->next==0 && ws[i]==0) ws[i] = df_width;
  436.     }
  437.     
  438.     cxrow->y = (cxrow==row) ? cxrow->asc:
  439.                cxrow->asc + cprow->desc + MATH_ROWSEP + cprow->y;
  440.     h += cxrow->asc + cxrow->desc + MATH_ROWSEP;     
  441.     cprow = cxrow;
  442.     cxrow = cxrow->next;
  443.     }
  444.     
  445.     hl = Descent();
  446.     h -= MATH_ROWSEP;
  447.  
  448.     //  Compute vertical align
  449.     switch (v_align) {
  450.      case 't': ascent = row->y; break;
  451.      case 'b': ascent = h - hl; break;
  452.      default:  ascent = (row->next) ? h/2: h - hl; break;
  453.     }
  454.     descent = h - ascent + 2;
  455.     
  456.    
  457.    // Adjust local tabs
  458.     cxrow = row;
  459.     width = MATH_COLSEP;
  460.     while (cxrow) {   
  461.     int rg=MATH_COLSEP, ww, lf=0, *w = cxrow->w;
  462.     for (i=0; i<nc; i++) {
  463.         bool isvoid = false;
  464.         if (w[i]<=0) {
  465.         w[i] = df_width;
  466.         isvoid = true;
  467.         }
  468.         switch (h_align[i]) {
  469.          case 'l': lf = 0; break;
  470.          case 'c': lf = (ws[i] - w[i])/2; 
  471.                break;
  472.          case 'r': lf = ws[i] - w[i]; break;
  473.         }
  474.         ww = (isvoid) ? lf: lf + w[i];
  475.         w[i] = lf + rg;
  476.         rg = ws[i] - ww + MATH_COLSEP;
  477.         if (cxrow==row) width += ws[i] + MATH_COLSEP;
  478.     }
  479.     cxrow->y -= ascent;
  480.     cxrow = cxrow->next;
  481.     }
  482. }
  483.  
  484. MathAccentInset::MathAccentInset(byte cx, MathedTextCodes f, int cd, short st): 
  485.   MathedInset("", LM_OT_ACCENT, st), c(cx), fn(f), code(cd)
  486. {
  487.     inset = 0;
  488. }
  489.  
  490. MathAccentInset::MathAccentInset(MathedInset *ins, int cd, short st):
  491.   MathedInset("", LM_OT_ACCENT, st), c(0), fn(LM_TC_MIN), code(cd), inset(ins)
  492. {
  493. }
  494.  
  495.  
  496. MathAccentInset::~MathAccentInset()
  497. {
  498.     if (inset)
  499.       delete inset;
  500. }
  501.  
  502. MathedInset *MathAccentInset::Clone()
  503. {   
  504.     MathAccentInset* p;
  505.     
  506.     if (inset) 
  507.       p = new MathAccentInset(inset->Clone(), code, GetStyle());
  508.     else
  509.       p = new MathAccentInset(c, fn, code, GetStyle());
  510.     
  511.     return p;
  512. }
  513.  
  514.  
  515. MathBigopInset::MathBigopInset(char const* name, int id, short st): 
  516.   MathedInset(name, LM_OT_BIGOP, st), sym(id)
  517. {
  518.    lims = -1;
  519. }
  520.  
  521. MathedInset *MathBigopInset::Clone()
  522. {   
  523.    MathBigopInset* p = new MathBigopInset(name, sym, GetStyle());
  524.    return p;
  525. }
  526.  
  527. MathDotsInset::MathDotsInset(char const* name, int id, short st):
  528.   MathedInset(name, LM_OT_DOTS, st), code(id)
  529. {
  530. }
  531.  
  532. MathedInset *MathDotsInset::Clone()
  533. {
  534.    MathDotsInset* p = new MathDotsInset(name, code, GetStyle());
  535.    return p;
  536. }     
  537.  
  538.