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