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_iter.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  19KB  |  956 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, 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_iter.h"
  22. #endif
  23.  
  24. #include "math_iter.h"
  25. #include "math_inset.h"
  26. #include "symbol_def.h"
  27. #include "error.h"
  28.  
  29. const int SizeInset = sizeof(char*) + 2;
  30. const int SizeFont = 2;
  31.  
  32. extern int mathed_char_width(short type, int style, byte c);
  33. extern int mathed_string_width(short type, int style, byte const* s, int ls);
  34. extern int mathed_char_height(short, int, byte, int&, int&);
  35.  
  36.  
  37. void MathedIter::Reset()
  38. {
  39.     if (array->last>0 && MathIsFont(array->bf[0])) {
  40.     fcode = array->bf[0];
  41.     pos = 1;
  42.     } else {
  43.     fcode = -1;
  44.     pos = 0;
  45.     }
  46.     col = row = 0;
  47. }
  48.  
  49.  
  50. byte MathedIter::GetChar()
  51. {
  52.     if (IsFont()) { 
  53.     fcode = array->bf[pos];
  54.     pos++;
  55.     }
  56.     return array->bf[pos];
  57. }
  58.  
  59.  
  60. byte* MathedIter::GetString(int& len)
  61. {
  62.     if (IsFont()) { 
  63.     fcode = array->bf[++pos];
  64.     pos++;
  65.     }
  66.     byte *s = &array->bf[pos];
  67.     len = pos;
  68.     while (array->bf[pos]>=' ' && pos<array->last) pos++;
  69.     len = pos-len;   
  70.    
  71.    return s;
  72. }
  73.  
  74. MathedInset* MathedIter::GetInset()
  75. {
  76.    if (IsInset()) {
  77.       MathedInset* p;
  78.       memcpy(&p, &array->bf[pos+1], sizeof(p));
  79.       return p;
  80.    } else {
  81.       fprintf(stderr,"Math Error: This is not an inset[%d]\n", array->bf[pos]);
  82.      return 0;
  83.    }
  84. }
  85.  
  86. // An active math inset MUST be derived from MathParInset because it 
  87. // must have at least one paragraph to edit
  88. MathParInset* MathedIter::GetActiveInset()
  89. {
  90.     if (IsActive()) {
  91.     return (MathParInset*)GetInset();
  92.     } 
  93.     
  94.     fprintf(stderr,"Math Error: This is not an active inset\n");
  95.     return 0;
  96. }
  97.  
  98. bool MathedIter::Next()
  99. {  
  100.     if (!OK()) return false;
  101.    
  102.     if (array->bf[pos]<' ') {
  103.     fcode = -1;     
  104.     if (IsTab()) col++;
  105.     if (IsCR())  {
  106.         col = 0;
  107.         row++;
  108.     }
  109.     }
  110.     
  111.     if (IsInset())
  112.       pos += sizeof(char*) + 2;
  113.     else 
  114.       pos++;
  115.     
  116.     if (IsFont()) {
  117.     fcode = array->bf[pos++];
  118.     }
  119.  
  120.     return true;   
  121. }
  122.  
  123.  
  124. bool MathedIter::goNextCode(MathedTextCodes code)
  125. {  
  126.     while (Next()) {
  127.     if (array->bf[pos]==code) 
  128.       return true;
  129.     }
  130.     
  131.     return false;
  132. }
  133.  
  134.  
  135. void MathedIter::goPosAbs(int p)
  136. {  
  137.     Reset();
  138.     while (pos<p && Next());
  139. }
  140.  
  141.  
  142. void MathedIter::goPosRel(int dp)
  143. {  
  144.     int posx = pos+dp;
  145.  
  146.     // is posx a valid position?
  147.     if (dp<0)
  148.       Reset();
  149.     while (pos<posx && Next());
  150. }
  151.  
  152.  
  153. void MathedIter::Insert(byte c, MathedTextCodes t)
  154. {
  155.     if (c<' ') return;
  156.     
  157.     if (t==LM_TC_TAB && col>=ncols-1) 
  158.       return;
  159.     
  160.     // Never more than one space // array->bf[pos-1] gives error from purify:
  161.     //       Reading 1 byte from 0x47b857 in the heap.
  162.     //  Address 0x47b857 is 1 byte before start of malloc'd block at 0x47b858 of 16 bytes.
  163.     if (c==' ' && (array->bf[pos]==' ' || array->bf[pos-1]==' ')) 
  164.       return;
  165.     
  166.     if (IsFont() && array->bf[pos]==t) {
  167.     fcode = t;
  168.     pos++;
  169.     } else
  170.       if (t!=fcode && pos>0 && MathIsFont(array->bf[pos-1])) {
  171.       pos--;
  172.       int k;
  173.       for (k=pos-1; k>=0 && array->bf[k]>=' '; k--);
  174.       fcode = (k >= 0 && MathIsFont(array->bf[k])) ? array->bf[k]: -1;
  175.       }
  176.     short f = (array->bf[pos]<' ') ? 0: fcode;
  177.     int shift = (t==fcode) ? 1: ((f) ? 3: 2);
  178.     
  179.     if (t==LM_TC_TAB || t==LM_TC_CR) {
  180.     shift--;
  181.     c = t;
  182.     if (t==LM_TC_CR) {
  183.         row++;
  184.         col = 0;
  185.     } else
  186.       col++;
  187.     }
  188.  
  189.     if (pos < array->last)
  190.         array->Move(pos, shift);
  191.     else {
  192.     if (array->last+shift>=array->maxsize) {
  193.         array->Resize(array->last+shift);
  194.     }
  195.     array->last += shift;
  196.     array->bf[array->last] = '\0';
  197.     }
  198.     if (t != fcode) {
  199.     if (f)  
  200.       array->bf[pos+shift-1] = fcode;
  201.      if (c>=' ') {
  202.         array->bf[pos++] = t;
  203.         fcode = t;
  204.     } else {
  205.         fcode = 0;
  206.     }
  207.     }      
  208.     array->bf[pos++] = c;
  209. }
  210.  
  211.  
  212. // Prepare to insert a non-char object
  213. void MathedIter::split(int shift)
  214. {
  215.    if (pos < array->last) {
  216.       bool fg = false;
  217.       if (array->bf[pos]>=' ') {
  218.      if (pos> 0 && MathIsFont(array->bf[pos-1]))
  219.        pos--;
  220.      else { 
  221.         fg = true; 
  222.         shift++;
  223.      }
  224.       }      
  225.       array->Move(pos, shift);
  226.       if (fg) array->bf[pos+shift-1] = fcode;
  227.    } else {
  228.       if (array->last+shift>=array->maxsize) {
  229.       array->Resize(array->last+shift);
  230.       }
  231.       array->last += shift;
  232.    }
  233.    array->bf[array->last] = '\0';
  234. }
  235.  
  236.  
  237. // I assume that both pos and pos2 are legal positions
  238. void MathedIter::join(int pos2)
  239. {   
  240.     if (!OK() || pos2<=pos)
  241.       return;    
  242.  
  243.     short f=fcode;        
  244.     if (pos>0 && array->bf[pos]>=' ' && MathIsFont(array->bf[pos-1])) 
  245.       pos--;    
  246.             
  247.     if (MathIsFont(array->bf[pos2-1]))
  248.       pos2--;
  249.     
  250.     if (array->bf[pos2]>=' ') {
  251.     for (int p=pos2; p>0; p--) 
  252.       if (MathIsFont(array->bf[p])) {
  253.           f = array->bf[p];
  254.           break;
  255.       }
  256.     array->bf[pos++] = f;
  257.     }    
  258.  
  259.     array->Move(pos2, pos-pos2);
  260. }
  261.  
  262. void MathedIter::Insert(MathedInset* p, int type)
  263. {
  264.     int shift = SizeInset;
  265.     if (!MathIsInset(type))
  266.       type = LM_TC_INSET;
  267.     split(shift);
  268.     array->bf[pos] = type;
  269.     memcpy(&array->bf[pos+1], &p, sizeof(p));
  270.     pos += SizeInset;
  271.     array->bf[pos-1] = type;
  272.     array->bf[array->last] = '\0';
  273.     fcode = -1;
  274. }
  275.  
  276.  
  277. bool MathedIter::Delete()
  278. {   
  279.    if (!OK())
  280.      return false;
  281.    
  282.    int shift = 0;
  283.    byte c = GetChar();
  284.    if (c>=' ') { 
  285.       if (MathIsFont(array->bf[pos-1]) && array->bf[pos+1]<' ') {
  286.      int i;
  287.      shift = 2;
  288.      pos--;
  289.      for (i=pos-1; i>0 && !MathIsFont(array->bf[i]); i--);
  290.      if (i>0 && MathIsFont(array->bf[i]))
  291.        fcode = array->bf[i];
  292.       } else
  293.     shift = 1;      
  294.    } else {
  295.       if (MathIsInset(array->bf[pos]))
  296.     shift = sizeof(char*) + 2;
  297.      else 
  298.       if (c==LM_TC_TAB || c==LM_TC_CR) {
  299.      shift++;
  300. //     fprintf(stderr, "Es un tab.");
  301.       }
  302.      else {
  303.     fprintf(stderr, "Math Warning: expected inset.");
  304.     fflush(stderr);
  305.      }
  306.    } 
  307.     
  308.    if (shift!=0) {
  309.       array->Move(pos+shift, -shift);
  310.       if (pos>=array->last) 
  311.      pos = (array->last>0) ? array->last: 0;
  312.        return true;
  313.    } else
  314.      return false;
  315. }
  316.  
  317.  
  318. LyxArrayBase *MathedIter::Copy(int pos1, int pos2)
  319. {
  320.    if (!array) {
  321. //      fprintf(stderr, "Math error: Attempting to copy a void array.\n");
  322.       return 0;
  323.    }
  324.       
  325. //   int posx = pos;
  326.    ipush(); 
  327.    LyxArrayBase *t=array, *a;
  328.     
  329.    if (pos1>0 || pos2<=array->last) {       
  330.        short fc=0;
  331.        if (pos1>0 && array->bf[pos1]>' ') {
  332.        for (int p=pos1; p>=0; p--) 
  333.          if (MathIsFont(array->bf[p])) {
  334.          if (p!=pos1-1)
  335.            fc = array->bf[p];
  336.          else
  337.            pos1--;
  338.          break;
  339.          }
  340.        }
  341.  
  342.        if (pos2>0 && array->bf[pos2]>=' ' && MathIsFont(array->bf[pos2-1])) 
  343.      pos2--;
  344.  
  345.        int dx = pos2 - pos1;
  346.        a = new LyxArrayBase(dx+LyxArrayBase::ARRAY_MIN_SIZE);
  347. //       fprintf(stderr, "VA %d %d %d ", pos1, pos2, dx); fflush(stderr);
  348.        memcpy(&a->bf[(fc) ? 1: 0], &array->bf[pos1], dx);
  349.        if (fc) {
  350.        a->bf[0] = fc;
  351.        dx++;
  352.        }
  353.        a->last = dx;
  354.        a->bf[dx] = '\0';
  355.    }  else   
  356.       a = new LyxArrayBase(*array);
  357.    SetData(a);
  358.    while (OK()) {
  359.       if (IsInset()) {
  360.      MathedInset* inset = GetInset();
  361.      inset = inset->Clone();
  362.      memcpy(&array->bf[pos+1], &inset, sizeof(inset));
  363.       }
  364.       Next();
  365.    }
  366. //   pos = posx;
  367.    array = t;
  368.    ipop(); 
  369.    return a;
  370. }
  371.  
  372.  
  373. void MathedIter::Clear()
  374. {
  375.    if (!array) {
  376.       fprintf(stderr, "Math error: Attempting to clean a void array.\n");
  377.       return;
  378.    }   
  379.    Reset();  
  380.    while (OK()) {
  381.       if (IsInset()) {
  382.      MathedInset* inset = GetInset();
  383.       Delete();
  384.       if (inset->GetType()!=LM_OT_MACRO_ARG)
  385.         delete inset;
  386.       } else
  387.       Next();
  388.    }
  389. }
  390.  
  391.  
  392. // Check consistency of tabs and crs
  393. void MathedIter::checkTabs()
  394. {
  395.     ipush();
  396.     
  397. //    MathedIter:Reset();
  398.     while (OK()) {
  399.         if ((IsTab() && col>=ncols-1) || (IsCR() && !(MthIF_CR&flags))) {
  400.             Delete();
  401.             continue;
  402.         }
  403.         if (IsCR() && col<ncols-2) {
  404.             Insert(' ', LM_TC_TAB);
  405.     }
  406.         MathedIter::Next();
  407.     }
  408.     if (col<ncols-2) {
  409.     Insert(' ', LM_TC_TAB);
  410.     }
  411.     ipop();
  412. }         
  413.  
  414.  
  415. //  Try to adjust tabs in the expected place, as used in eqnarrays
  416. //  Rules:
  417. //   - If there are a relation operator, put tabs around it
  418. //   - If tehre are not a relation operator, put everything in the
  419. //     3rd column.
  420. void MathedIter::adjustTabs()
  421. {
  422.  
  423. }         
  424.  
  425.  
  426. void MathedXIter::Clean(int pos2)
  427. {
  428.     if (!array) {
  429.     fprintf(stderr, "Math error: Attempting to clean a void array.\n");
  430.     return;
  431.     } 
  432.     
  433.     int pos1 = pos;
  434.     
  435.     if (pos2<pos1) {  
  436.     GoBegin();
  437.     while (pos<pos2 && OK()) { Next();
  438.     }
  439.     pos2 = pos1;
  440.     pos1 = pos;
  441.     }
  442.  
  443.     ipush();
  444.     while (OK() && pos<pos2) {
  445.     if (IsInset()) {
  446.         MathedInset* inset = GetInset();
  447.         if (inset->GetType()!=LM_OT_MACRO_ARG)
  448.           delete inset;
  449.     } 
  450.     if (IsCR()) {
  451.         if (crow) {
  452.         MathedRowSt *r = crow->next;
  453.         if (r) {
  454.             crow->next = r->next;
  455.             delete r;
  456.         }       
  457.         }
  458.     }
  459.     Next();
  460.     }    
  461.     ipop();
  462.     
  463.     if (pos2<=array->Last()) {
  464.     pos = pos1;
  465.     join(pos2);
  466.     checkTabs();
  467.     } 
  468. }
  469.  
  470.  
  471. void MathedXIter::Merge(LyxArrayBase *a0)
  472. {
  473.     if (!a0) {
  474.     lyxerr.debug("Math error: Attempting to merge a void array.",
  475.              Error::MATHED);
  476.     return;
  477.     }
  478.     // All insets must be clonned
  479.     MathedIter it(a0);
  480.     LyxArrayBase *a = it.Copy();
  481.     
  482.     // make rom for the data 
  483.     split(a->Last());
  484.     array->MergeF(a, pos, a->Last());
  485.  
  486.     int pos1=pos, pos2 = pos + a->Last(); // pos3=0;
  487.  
  488.     goPosAbs(pos1);
  489.     
  490.     // Complete rows
  491.     while (pos<pos2 && OK()) {
  492.     if (IsCR()) {
  493.         if (p && p->Permit(LMPF_ALLOW_CR)) {
  494.         MathedRowSt *r = new MathedRowSt(ncols+1);
  495.         if (crow) {
  496.             r->next = crow->next;
  497.             crow->next = r;
  498.           } else {
  499.               r->next = 0;
  500.           }
  501.         crow = r;
  502.         } else {
  503.         Delete();
  504.         pos2--;
  505.         }
  506.     }
  507.         Next();    
  508.     }
  509.     pos2 = getPos();
  510.     goPosAbs(pos1);
  511.     checkTabs();
  512.     goPosAbs(pos2);
  513.     
  514.     delete a;
  515. }
  516.  
  517.  
  518. //-----------  XIter
  519.  
  520.  
  521. MathedXIter::MathedXIter(MathParInset* pp): p(pp) 
  522.     x = y = 0;
  523.     sx = sw = 0;   
  524.     limits = false;
  525.     s_type = 0;  
  526.     if (p) 
  527.       SetData(p);
  528.     else {
  529.     crow = 0;
  530.     size = 0;
  531.     }
  532. }
  533.  
  534. void MathedXIter::SetData(MathParInset *pp)
  535. {
  536.     p = pp;
  537.     x = y = 0;
  538.     array = p->GetData();
  539.     ncols = p->GetColumns();
  540.     crow = p->getRowSt();
  541.     if (p->Permit(LMPF_ALLOW_CR))
  542.       flags |= MthIF_CR;
  543.     if (p->Permit(LMPF_ALLOW_TAB))
  544.       flags |= MthIF_Tabs;
  545.     
  546.     if (crow) {
  547.     x = crow->getTab(0);
  548.     y = crow->getBaseline();
  549.     } 
  550.     if (!array) {
  551.         array = new LyxArrayBase; // this leaks
  552.     p->SetData(array);
  553.     }
  554.     size = p->GetStyle();
  555.     Reset();
  556. }
  557.  
  558. byte* MathedXIter::GetString(int& ls)
  559. {  
  560.    static byte s[255];
  561.    byte const *sx =  MathedIter::GetString(ls);
  562.    if (ls>0) {
  563.        strncpy((char *)s, (char const*)sx, ls);
  564.        x += mathed_string_width(fcode, size, s, ls);
  565.        return &s[0];
  566.    }         
  567.     return 0;
  568. }
  569.  
  570.  
  571. bool MathedXIter::Next()
  572. {  
  573. //    fprintf(stderr, "Ne[%d]", pos);
  574.    if (!OK()) return false;
  575.    int w=0;
  576. //   fprintf(stderr, "xt ");
  577.    if (IsInset()) {
  578.       MathedInset* px = GetInset();
  579.       w = px->Width();
  580.       if (px->GetType()==LM_OT_SCRIPT) {
  581.      if (w>sw) sw = w;
  582.      w = 0;
  583.       } else
  584.     sx = (px->GetLimits()) ? w: 0;
  585.    } else {  
  586.       byte c = GetChar();
  587.       if (c>=' ') {
  588. //      fprintf(stderr, "WD[%d %d %c] ", fcode, size, c); fflush(stderr);
  589.       w = mathed_char_width(fcode, size, c);
  590.       } else
  591.       if (c==LM_TC_TAB && p) {
  592. //     w = p->GetTab(col+1);
  593.       w = (crow) ? crow->getTab(col+1): 0;
  594.      //fprintf(stderr, "WW[%d]", w);
  595.       } else
  596.       if (c==LM_TC_CR && p) {
  597.       x = 0;
  598.       if (crow && crow->next) {
  599.           crow = crow->next;
  600.           y = crow->getBaseline();
  601.           w = crow->getTab(0);
  602.       }
  603. //      fprintf(stderr, "WW[%d %d|%d]", col, row, w);
  604.       } else 
  605.     fprintf(stderr, "No hubo w[%d]!", (int)c);   
  606.    }
  607.    if (MathedIter::Next()) {
  608. //       fprintf(stderr, "LNX %d ", pos); fflush(stderr);
  609. //       if (sw>0 && GetChar()!=LM_TC_UP && GetChar()!=LM_TC_DOWN) {
  610. //       w = (sx>sw) ? 0: sw-sx;
  611.       if ((sw>0 || sx>0) && GetChar()!=LM_TC_UP && GetChar()!=LM_TC_DOWN) {
  612.       if (sw>0)
  613.         w = (sx>sw) ? 0: sw-sx;
  614.       sx = sw = 0;
  615.       }
  616.       x += w;
  617.       return true;
  618.    } else
  619.      return false;
  620. }
  621.  
  622.  
  623. void MathedXIter::GoBegin()
  624. {
  625.    Reset();
  626.    x = y = 0;   
  627.    sw = sx = 0;
  628.    if (p) {
  629.        crow = p->getRowSt();
  630.        if (crow) {
  631.        x = crow->getTab(0);
  632.        y = crow->getBaseline();
  633.        }
  634.    }
  635. }
  636.  
  637. void MathedXIter::GoLast()
  638. {
  639.    while (Next());
  640. }
  641.  
  642.  
  643. void MathedXIter::Adjust()
  644. {
  645.    int posx = pos;
  646.    GoBegin();
  647.    while (posx>pos && OK()) Next();  
  648. }
  649.  
  650.  
  651. bool MathedXIter::Prev()
  652. {  
  653.     if (pos==0 || (pos==1 && GetChar()>=' '))
  654.       return false;
  655.     
  656.     int pos2 = pos; // pos1
  657.     GoBegin();
  658.     do {
  659.     ipush();
  660.     Next();
  661.     } while (pos<pos2);
  662.     ipop();
  663.     
  664.     return (!IsCR());
  665. }
  666.  
  667.  
  668. bool MathedXIter::goNextColumn()
  669. {  
  670.     int rowp = row, colp=col;
  671.     while (Next() && col==colp);
  672.     
  673.     return (col!=colp+1 || rowp!=row);
  674. }
  675.  
  676.  
  677. bool MathedXIter::Up()
  678. {
  679.     if (row==0) return false;
  680.     int xp = x, rowp = row, colp=col;
  681.     GoBegin();
  682.     while (row<rowp-1) Next();
  683.     while (x<xp && OK() && !IsCR()) {
  684.     ipush();
  685.     Next();
  686.     }
  687.     if (col>colp) // || (stck.col==colp && stck.x<=xp && x>xp))
  688.       ipop();
  689.     
  690.     return true;
  691. }
  692.  
  693.  
  694. bool MathedXIter::Down()
  695. {
  696.     int xp = x, colp=col; // ,rowp = row
  697.     
  698.     bool res = (IsCR()) ? true: goNextCode(LM_TC_CR);
  699.     if (res) {
  700.         Next();
  701.     ipush();
  702.     while (x<xp && OK()) {
  703.         ipush();
  704.         Next();
  705.     }
  706.     if (col>colp || (stck.col==colp && stck.x<=xp && x>xp)) 
  707.       ipop();       
  708.         return true;
  709.     }
  710.     return false;
  711. }
  712.  
  713.  
  714. void MathedXIter::addRow()
  715. {
  716.     if (!crow) {
  717.     lyxerr.debug(LString("MathErr: Attempt to insert new"
  718.                  " line in a subparagraph. ")
  719.              + long(this), Error::MATHED);
  720.     return;
  721.     }    
  722.     // Create new item for the structure    
  723.     MathedRowSt *r = new MathedRowSt(ncols+1);
  724.     if (crow) {
  725.     r->next = crow->next;
  726.     crow->next = r;
  727.     } else {
  728.     crow = r;
  729.     r->next = 0;
  730.     }    
  731.     // Fill missed tabs in current row
  732.     while (col<ncols-1) 
  733.       Insert('T', LM_TC_TAB); 
  734.     //newline
  735.     Insert('K', LM_TC_CR);
  736.     
  737.     ipush();
  738.     if (!IsCR())
  739.       goNextCode(LM_TC_CR);
  740.     
  741.     // Fill missed tabs in new row
  742.     while (col<ncols-1) 
  743.       Insert('T', LM_TC_TAB);
  744.     ipop();
  745. }
  746.  
  747.  
  748. void MathedXIter::delRow()
  749. {
  750.     if (!crow) {
  751.     lyxerr.debug("MathErr: Attempt to delete a line in a subparagraph.",
  752.              Error::MATHED);
  753.     return;
  754.     }
  755.     bool line_empty = true;
  756.     ipush();
  757. //    while (Next()) {
  758.     do {
  759.     if (IsCR()){
  760.         break;
  761.     } else if (!IsTab()) {
  762.         line_empty = false;
  763.     }
  764.     } while (Next());
  765.     int p1 = getPos();
  766.     ipop();
  767.     
  768.     if (line_empty) {
  769.     
  770.     MathedRowSt *r = crow->next;
  771.     if (r) {
  772.         crow->next = r->next;
  773.         delete r;
  774.     }
  775.     join(p1);
  776.     Delete();
  777.     } else
  778.       Clean(p1);
  779.     
  780.     checkTabs();    
  781. }
  782.  
  783. void MathedXIter::ipush()
  784.     MathedIter::ipush();
  785.     stck.x = x;
  786.     stck.y = y;
  787. }
  788.  
  789.  
  790. void MathedXIter::ipop()
  791.     MathedIter::ipop();
  792.     x = stck.x;
  793.     y = stck.y;
  794.     if (p) {
  795.     crow = p->getRowSt();
  796.     if (crow)
  797.       for (int i=0; i<row; i++) 
  798.         crow = crow->next;
  799.     }
  800. }
  801.  
  802.  
  803. void MathedXIter::fitCoord(int /*xx*/, int yy)
  804. {
  805.     int xo = 0, yo = 0;
  806.     
  807.     GoBegin();
  808.     if (p) 
  809.       p->GetXY(xo, yo);
  810.     // first fit vertically
  811.     while (crow && OK()) {
  812.     if (yy>=yo+y-crow->asc && yy<= yo+y+crow->desc) 
  813.       break;
  814.     goNextCode(LM_TC_CR);
  815.     Next();
  816.     }
  817.     // now horizontally
  818. //    while (x<xx && Next());
  819. }
  820.  
  821. void MathedXIter::setTab(int tx, int tab)
  822. {
  823.     if (crow && tab<=ncols) {
  824.     crow->w[tab] = tx;
  825.     }
  826.     else 
  827.       fprintf(stderr, "MathErr: No tabs allowed here");
  828. }
  829.  
  830.  
  831. void MathedXIter::subMetrics(int a, int d)
  832. {
  833.     if (!crow) {
  834. //    fprintf(stderr, "MathErr: Attempt to submetric a subparagraph.");
  835.     return;
  836.     }    
  837.     crow->asc = a;
  838.     crow->desc = d;
  839. }
  840.  
  841.  
  842. // This function is not recursive, as MathPar::Metrics is
  843. void MathedXIter::IMetrics(int pos2, int& width, int& ascent, int& descent)
  844. {  
  845.     byte cx, cxp=0;// *s;
  846.     int x1;// ls;
  847.     int asc=0, des=0;
  848.     bool limits = false;
  849.   
  850.     descent = ascent = width = 0;
  851.     if (!array) return;
  852.     if (array->Empty()) return;
  853. //    if  (pos2 > array->last) return;
  854.     x1 = x; 
  855.     while (pos<pos2) {
  856.     cx = GetChar();
  857.     if (cx >= ' ') {
  858.         mathed_char_height(FCode(), size, cx, asc, des);
  859.         if (asc > ascent) ascent = asc;
  860.         if (des > descent) descent = des;
  861.         limits = false;
  862.     } else
  863.     if (MathIsInset(cx)) {
  864.         MathedInset *pp = GetInset();
  865.         if (cx==LM_TC_UP) {
  866.         if (!asc && p) {
  867.             int xx, yy;
  868.             p->GetXY(xx, yy);
  869.             ((MathParInset*)pp)->GetXY(xx, asc);
  870.             asc = yy - asc;
  871.         }
  872.         asc += ((limits) ? pp->Height()+4: pp->Ascent());
  873.         } else
  874.           if (cx==LM_TC_DOWN) {
  875.           if (!des && p) {
  876.               int xx, yy;
  877.               p->GetXY(xx, yy);
  878.               ((MathParInset*)pp)->GetXY(xx, des);
  879.               if (des-pp->Height()<yy && !asc)
  880.             asc = yy - (des-pp->Height());
  881.               des -= yy;
  882.           }
  883.           des += ((limits) ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
  884.           } else {
  885.           asc = pp->Ascent();
  886.           des = pp->Descent();
  887.           }
  888.         if (asc > ascent) ascent = asc;
  889.         if (des > descent) descent = des;
  890.         if (cx!=LM_TC_UP && cx!=LM_TC_DOWN)
  891.           limits = pp->GetLimits();
  892.     } else 
  893.     if (cx==LM_TC_TAB) {
  894.         limits = false;                   
  895.     }      
  896.     else {
  897.         lyxerr.debug(LString("Mathed Sel-Error: Unrecognized code[")
  898.              + int(cx) + ']', Error::MATHED);
  899.         break;
  900.     }       
  901.     if (pos<pos2)  Next();
  902.     cxp = cx;
  903.    }
  904.     width = x - x1;
  905. }
  906.  
  907.  
  908. bool MathedXIter::setNumbered(bool numb)
  909. {  
  910.     if (crow) {
  911.     crow->setNumbered(numb);
  912.     return true;
  913.     }
  914.     
  915.     return false;
  916. }
  917.  
  918.  
  919. bool MathedXIter::setLabel(char* label)
  920. {  
  921.     if (label && crow) {
  922.     crow->setLabel(label);
  923.     return true;
  924.     }
  925.     
  926.     return false;
  927. }
  928.  
  929.  
  930. MathedRowSt *MathedXIter::adjustVerticalSt()
  931. {
  932.     GoBegin();
  933.     if (!crow) {
  934. //    fprintf(stderr, " CRW%d ", ncols);
  935.         crow = new MathedRowSt(ncols+1); // this leaks
  936.     }
  937. //    fprintf(stderr, " CRW[%p] ", crow);
  938.     MathedRowSt *row = crow;
  939.     while (OK()) {
  940.     if (IsCR()) {
  941.         if (col>=ncols) ncols = col+1; 
  942.         MathedRowSt *r = new MathedRowSt(ncols+1); // this leaks
  943. //        r->next = crow->next;
  944.         crow->next = r;
  945.         crow = r;
  946. //        fprintf(stderr, " CX[%p]", crow);
  947.     }   
  948.     Next();    
  949.     }
  950.     return row;
  951. }
  952.  
  953.