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