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