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