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