]> git.lyx.org Git - lyx.git/blob - src/mathed/math_iter.C
Initial revision
[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 "error.h"
28
29 const int SizeInset = sizeof(char*) + 2;
30 const int SizeFont = 2;
31
32 extern int mathed_char_width(short type, int style, byte c);
33 extern int mathed_string_width(short type, int style, byte const* s, int ls);
34 extern int mathed_char_height(short, int, byte, int&, int&);
35
36
37 void MathedIter::Reset()
38 {
39     if (array->last>0 && MathIsFont(array->bf[0])) {
40         fcode = array->bf[0];
41         pos = 1;
42     } else {
43         fcode = -1;
44         pos = 0;
45     }
46     col = row = 0;
47 }
48
49
50 byte MathedIter::GetChar()
51 {
52     if (IsFont()) { 
53         fcode = array->bf[pos];
54         pos++;
55     }
56     return array->bf[pos];
57 }
58
59
60 byte* MathedIter::GetString(int& len)
61 {
62     if (IsFont()) { 
63         fcode = array->bf[++pos];
64         pos++;
65     }
66     byte *s = &array->bf[pos];
67     len = pos;
68     while (array->bf[pos]>=' ' && pos<array->last) pos++;
69     len = pos-len;   
70    
71    return s;
72 }
73
74 MathedInset* MathedIter::GetInset()
75 {
76    if (IsInset()) {
77       MathedInset* p;
78       memcpy(&p, &array->bf[pos+1], sizeof(p));
79       return p;
80    } else {
81       fprintf(stderr,"Math Error: This is not an inset[%d]\n", array->bf[pos]);
82      return 0;
83    }
84 }
85
86 // An active math inset MUST be derived from MathParInset because it 
87 // must have at least one paragraph to edit
88 MathParInset* MathedIter::GetActiveInset()
89 {
90     if (IsActive()) {
91         return (MathParInset*)GetInset();
92     } 
93     
94     fprintf(stderr,"Math Error: This is not an active inset\n");
95     return 0;
96 }
97
98 bool MathedIter::Next()
99 {  
100     if (!OK()) return false;
101    
102     if (array->bf[pos]<' ') {
103         fcode = -1;     
104         if (IsTab()) col++;
105         if (IsCR())  {
106             col = 0;
107             row++;
108         }
109     }
110         
111     if (IsInset())
112       pos += sizeof(char*) + 2;
113     else 
114       pos++;
115     
116     if (IsFont()) {
117         fcode = array->bf[pos++];
118     }
119
120     return true;   
121 }
122
123
124 bool MathedIter::goNextCode(MathedTextCodes code)
125 {  
126     while (Next()) {
127         if (array->bf[pos]==code) 
128           return true;
129     }
130     
131     return false;
132 }
133
134
135 void MathedIter::goPosAbs(int p)
136 {  
137     Reset();
138     while (pos<p && Next());
139 }
140
141
142 void MathedIter::goPosRel(int dp)
143 {  
144     int posx = pos+dp;
145  
146     // is posx a valid position?
147     if (dp<0)
148       Reset();
149     while (pos<posx && Next());
150 }
151
152
153 void MathedIter::Insert(byte c, MathedTextCodes t)
154 {
155     if (c<' ') return;
156     
157     if (t==LM_TC_TAB && col>=ncols-1) 
158       return;
159     
160     // Never more than one space // array->bf[pos-1] gives error from purify:
161     //       Reading 1 byte from 0x47b857 in the heap.
162     //  Address 0x47b857 is 1 byte before start of malloc'd block at 0x47b858 of 16 bytes.
163     if (c==' ' && (array->bf[pos]==' ' || array->bf[pos-1]==' ')) 
164       return;
165         
166     if (IsFont() && array->bf[pos]==t) {
167         fcode = t;
168         pos++;
169     } else
170       if (t!=fcode && pos>0 && MathIsFont(array->bf[pos-1])) {
171           pos--;
172           int k;
173           for (k=pos-1; k>=0 && array->bf[k]>=' '; k--);
174           fcode = (k >= 0 && MathIsFont(array->bf[k])) ? array->bf[k]: -1;
175       }
176     short f = (array->bf[pos]<' ') ? 0: fcode;
177     int shift = (t==fcode) ? 1: ((f) ? 3: 2);
178     
179     if (t==LM_TC_TAB || t==LM_TC_CR) {
180         shift--;
181         c = t;
182         if (t==LM_TC_CR) {
183             row++;
184             col = 0;
185         } else
186           col++;
187     }
188  
189     if (pos < array->last)
190         array->Move(pos, shift);
191     else {
192         if (array->last+shift>=array->maxsize) {
193             array->Resize(array->last+shift);
194         }
195         array->last += shift;
196         array->bf[array->last] = '\0';
197     }
198     if (t != fcode) {
199         if (f)  
200           array->bf[pos+shift-1] = fcode;
201         if (c>=' ') {
202             array->bf[pos++] = t;
203             fcode = t;
204         } else {
205             fcode = 0;
206         }
207     }      
208     array->bf[pos++] = c;
209 }
210
211
212 // Prepare to insert a non-char object
213 void MathedIter::split(int shift)
214 {
215    if (pos < array->last) {
216       bool fg = false;
217       if (array->bf[pos]>=' ') {
218          if (pos> 0 && MathIsFont(array->bf[pos-1]))
219            pos--;
220          else { 
221             fg = true; 
222             shift++;
223          }
224       }      
225       array->Move(pos, shift);
226       if (fg) array->bf[pos+shift-1] = fcode;
227    } else {
228       if (array->last+shift>=array->maxsize) {
229           array->Resize(array->last+shift);
230       }
231       array->last += shift;
232    }
233    array->bf[array->last] = '\0';
234 }
235
236
237 // I assume that both pos and pos2 are legal positions
238 void MathedIter::join(int pos2)
239 {   
240     if (!OK() || pos2<=pos)
241       return;    
242
243     short f=fcode;          
244     if (pos>0 && array->bf[pos]>=' ' && MathIsFont(array->bf[pos-1])) 
245       pos--;    
246             
247     if (MathIsFont(array->bf[pos2-1]))
248       pos2--;
249     
250     if (array->bf[pos2]>=' ') {
251         for (int p=pos2; p>0; p--) 
252           if (MathIsFont(array->bf[p])) {
253               f = array->bf[p];
254               break;
255           }
256         array->bf[pos++] = f;
257     }    
258
259     array->Move(pos2, pos-pos2);
260 }
261
262 void MathedIter::Insert(MathedInset* p, int type)
263 {
264     int shift = SizeInset;
265     if (!MathIsInset(type))
266       type = LM_TC_INSET;
267     split(shift);
268 //      array->bf[pos] = type;
269 //      memcpy(&array->bf[pos+1], &p, sizeof(p));
270 //      pos += SizeInset;
271 //      array->bf[pos-1] = type;
272     {
273         unsigned char *pt = &array->bf[pos];
274         unsigned char *ps = (unsigned char *)&p;
275         size_t i;
276         *pt++ = type;
277         for(i = 0; i < sizeof(p); i++) {
278             *pt++ = *ps++;
279         }
280         *pt = type;
281     }
282     pos += SizeInset;
283     array->bf[array->last] = '\0';
284     fcode = -1;
285 }
286
287
288 bool MathedIter::Delete()
289 {   
290    if (!OK())
291      return false;
292    
293    int shift = 0;
294    byte c = GetChar();
295    if (c>=' ') { 
296       if (MathIsFont(array->bf[pos-1]) && array->bf[pos+1]<' ') {
297          int i;
298          shift = 2;
299          pos--;
300          for (i=pos-1; i>0 && !MathIsFont(array->bf[i]); i--);
301          if (i>0 && MathIsFont(array->bf[i]))
302            fcode = array->bf[i];
303       } else
304         shift = 1;      
305    } else {
306       if (MathIsInset(array->bf[pos]))
307         shift = sizeof(char*) + 2;
308      else 
309       if (c==LM_TC_TAB || c==LM_TC_CR) {
310          shift++;
311 //       fprintf(stderr, "Es un tab.");
312       }
313      else {
314         fprintf(stderr, "Math Warning: expected inset.");
315         fflush(stderr);
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 //      fprintf(stderr, "Math error: Attempting to copy a void array.\n");
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 //       fprintf(stderr, "VA %d %d %d ", pos1, pos2, dx); fflush(stderr);
359        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          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       fprintf(stderr, "Math error: Attempting to clean a void array.\n");
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         fprintf(stderr, "Math error: Attempting to clean a void array.\n");
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("Math error: Attempting to merge a void array.",
488                      Error::MATHED);
489         return;
490     }
491     // All insets must be clonned
492     MathedIter it(a0);
493     LyxArrayBase *a = it.Copy();
494     
495     // make rom for the data 
496     split(a->Last());
497     array->MergeF(a, pos, a->Last());
498
499     int pos1=pos, pos2 = pos + a->Last(); // pos3=0;
500
501     goPosAbs(pos1);
502     
503     // Complete rows
504     while (pos<pos2 && OK()) {
505         if (IsCR()) {
506             if (p && p->Permit(LMPF_ALLOW_CR)) {
507                 MathedRowSt *r = new MathedRowSt(ncols+1);
508                 if (crow) {
509                     r->next = crow->next;
510                     crow->next = r;
511                   } else {
512                       r->next = 0;
513                   }
514                 crow = r;
515             } else {
516                 Delete();
517                 pos2--;
518             }
519         }
520         Next();    
521     }
522     pos2 = getPos();
523     goPosAbs(pos1);
524     checkTabs();
525     goPosAbs(pos2);
526     
527     delete a;
528 }
529
530
531 //-----------  XIter
532
533
534 MathedXIter::MathedXIter(MathParInset* pp): p(pp) 
535
536     x = y = 0;
537     sx = sw = 0;   
538     limits = false;
539     s_type = 0;  
540     if (p) 
541       SetData(p);
542     else {
543         crow = 0;
544         size = 0;
545     }
546 }
547
548 void MathedXIter::SetData(MathParInset *pp)
549 {
550     p = pp;
551     x = y = 0;
552     array = p->GetData();
553     ncols = p->GetColumns();
554     crow = p->getRowSt();
555     if (p->Permit(LMPF_ALLOW_CR))
556       flags |= MthIF_CR;
557     if (p->Permit(LMPF_ALLOW_TAB))
558       flags |= MthIF_Tabs;
559     
560     if (crow) {
561         x = crow->getTab(0);
562         y = crow->getBaseline();
563     } 
564     if (!array) {
565             array = new LyxArrayBase; // this leaks
566         p->SetData(array);
567     }
568     size = p->GetStyle();
569     Reset();
570 }
571
572 byte* MathedXIter::GetString(int& ls)
573 {  
574    static byte s[255];
575    byte const *sx =  MathedIter::GetString(ls);
576    if (ls>0) {
577        strncpy((char *)s, (char const*)sx, ls);
578        x += mathed_string_width(fcode, size, s, ls);
579        return &s[0];
580    }        
581     return 0;
582 }
583
584
585 bool MathedXIter::Next()
586 {  
587 //    fprintf(stderr, "Ne[%d]", pos);
588    if (!OK()) return false;
589    int w=0;
590 //   fprintf(stderr, "xt ");
591    if (IsInset()) {
592       MathedInset* px = GetInset();
593       w = px->Width();
594       if (px->GetType()==LM_OT_SCRIPT) {
595          if (w>sw) sw = w;
596          w = 0;
597       } else
598         sx = (px->GetLimits()) ? w: 0;
599    } else {  
600       byte c = GetChar();
601       if (c>=' ') {
602 //        fprintf(stderr, "WD[%d %d %c] ", fcode, size, c); fflush(stderr);
603           w = mathed_char_width(fcode, size, c);
604       } else
605       if (c==LM_TC_TAB && p) {
606 //       w = p->GetTab(col+1);
607           w = (crow) ? crow->getTab(col+1): 0;
608          //fprintf(stderr, "WW[%d]", w);
609       } else
610       if (c==LM_TC_CR && p) {
611           x = 0;
612           if (crow && crow->next) {
613               crow = crow->next;
614               y = crow->getBaseline();
615               w = crow->getTab(0);
616           }
617 //        fprintf(stderr, "WW[%d %d|%d]", col, row, w);
618       } else 
619         fprintf(stderr, "No hubo w[%d]!", (int)c);   
620    }
621    if (MathedIter::Next()) {
622 //       fprintf(stderr, "LNX %d ", pos); fflush(stderr);
623 //       if (sw>0 && GetChar()!=LM_TC_UP && GetChar()!=LM_TC_DOWN) {
624 //         w = (sx>sw) ? 0: sw-sx;
625       if ((sw>0 || sx>0) && GetChar()!=LM_TC_UP && GetChar()!=LM_TC_DOWN) {
626           if (sw>0)
627             w = (sx>sw) ? 0: sw-sx;
628           sx = sw = 0;
629       }
630       x += w;
631       return true;
632    } else
633      return false;
634 }
635
636
637 void MathedXIter::GoBegin()
638 {
639    Reset();
640    x = y = 0;   
641    sw = sx = 0;
642    if (p) {
643        crow = p->getRowSt();
644        if (crow) {
645            x = crow->getTab(0);
646            y = crow->getBaseline();
647        }
648    }
649 }
650
651 void MathedXIter::GoLast()
652 {
653    while (Next());
654 }
655
656
657 void MathedXIter::Adjust()
658 {
659    int posx = pos;
660    GoBegin();
661    while (posx>pos && OK()) Next();  
662 }
663
664
665 bool MathedXIter::Prev()
666 {  
667     if (pos==0 || (pos==1 && GetChar()>=' '))
668       return false;
669     
670     int pos2 = pos; // pos1
671     GoBegin();
672     do {
673         ipush();
674         Next();
675     } while (pos<pos2);
676     ipop();
677     
678     return (!IsCR());
679 }
680
681
682 bool MathedXIter::goNextColumn()
683 {  
684     int rowp = row, colp=col;
685     while (Next() && col==colp);
686     
687     return (col!=colp+1 || rowp!=row);
688 }
689
690
691 bool MathedXIter::Up()
692 {
693     if (row==0) return false;
694     int xp = x, rowp = row, colp=col;
695     GoBegin();
696     while (row<rowp-1) Next();
697     while (x<xp && OK() && !IsCR()) {
698         ipush();
699         Next();
700     }
701     if (col>colp) // || (stck.col==colp && stck.x<=xp && x>xp))
702       ipop();
703     
704     return true;
705 }
706
707
708 bool MathedXIter::Down()
709 {
710         int xp = x, colp=col; // ,rowp = row
711     
712     bool res = (IsCR()) ? true: goNextCode(LM_TC_CR);
713     if (res) {
714         Next();
715         ipush();
716         while (x<xp && OK()) {
717             ipush();
718             Next();
719         }
720         if (col>colp || (stck.col==colp && stck.x<=xp && x>xp)) 
721           ipop();         
722         return true;
723     }
724     return false;
725 }
726
727
728 void MathedXIter::addRow()
729 {
730     if (!crow) {
731         lyxerr.debug(LString("MathErr: Attempt to insert new"
732                              " line in a subparagraph. ")
733                      + long(this), Error::MATHED);
734         return;
735     }    
736     // Create new item for the structure    
737     MathedRowSt *r = new MathedRowSt(ncols+1);
738     if (crow) {
739         r->next = crow->next;
740         crow->next = r;
741     } else {
742         crow = r;
743         r->next = 0;
744     }    
745     // Fill missed tabs in current row
746     while (col<ncols-1) 
747       Insert('T', LM_TC_TAB); 
748     //newline
749     Insert('K', LM_TC_CR);
750     
751     ipush();
752     if (!IsCR())
753       goNextCode(LM_TC_CR);
754     
755     // Fill missed tabs in new row
756     while (col<ncols-1) 
757       Insert('T', LM_TC_TAB);
758     ipop();
759 }
760
761
762 void MathedXIter::delRow()
763 {
764     if (!crow) {
765         lyxerr.debug("MathErr: Attempt to delete a line in a subparagraph.",
766                      Error::MATHED);
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       fprintf(stderr, "MathErr: No tabs allowed here");
844 }
845
846
847 void MathedXIter::subMetrics(int a, int d)
848 {
849     if (!crow) {
850 //      fprintf(stderr, "MathErr: Attempt to submetric a subparagraph.");
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 limits = 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             limits = 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                     ((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                       ((MathParInset*)pp)->GetXY(xx, des);
895                       if (des-pp->Height()<yy && !asc)
896                         asc = yy - (des-pp->Height());
897                       des -= yy;
898                   }
899                   des += ((limits) ? 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               limits = pp->GetLimits();
908         } else 
909         if (cx==LM_TC_TAB) {
910             limits = false;                   
911         }      
912         else {
913             lyxerr.debug(LString("Mathed Sel-Error: Unrecognized code[")
914                          + int(cx) + ']', Error::MATHED);
915             break;
916         }       
917         if (pos<pos2)  Next();
918         cxp = cx;
919    }
920     width = x - x1;
921 }
922
923
924 bool MathedXIter::setNumbered(bool numb)
925 {  
926     if (crow) {
927         crow->setNumbered(numb);
928         return true;
929     }
930     
931     return false;
932 }
933
934
935 bool MathedXIter::setLabel(char* label)
936 {  
937     if (label && crow) {
938         crow->setLabel(label);
939         return true;
940     }
941     
942     return false;
943 }
944
945
946 MathedRowSt *MathedXIter::adjustVerticalSt()
947 {
948     GoBegin();
949     if (!crow) {
950 //      fprintf(stderr, " CRW%d ", ncols);
951             crow = new MathedRowSt(ncols+1); // this leaks
952     }
953 //    fprintf(stderr, " CRW[%p] ", crow);
954     MathedRowSt *row = crow;
955     while (OK()) {
956         if (IsCR()) {
957             if (col>=ncols) ncols = col+1; 
958             MathedRowSt *r = new MathedRowSt(ncols+1); // this leaks
959 //          r->next = crow->next;
960             crow->next = r;
961             crow = r;
962 //          fprintf(stderr, " CX[%p]", crow);
963         }   
964         Next(); 
965     }
966     return row;
967 }
968