]> git.lyx.org Git - lyx.git/blob - src/mathed/math_iter.C
fix the reformat bug, some small things
[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 = pos - 1;
188           for (; 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] >= ' '
357            && MathIsFont(array->bf[pos2-1])) 
358          --pos2;
359
360        int dx = pos2 - pos1;
361        a = new LyxArrayBase(dx+LyxArrayBase::ARRAY_MIN_SIZE);
362 //       lyxerr << "VA " << pos2 << " " << pos2 << " " << dx << endl;
363        my_memcpy(&a->bf[(fc) ? 1: 0], &array->bf[pos1], dx);
364        if (fc) {
365            a->bf[0] = fc;
366            ++dx;
367        }
368        a->last = dx;
369        a->bf[dx] = '\0';
370    }  else   
371       a = new LyxArrayBase(*array);
372    SetData(a);
373    while (OK()) {
374       if (IsInset()) {
375          MathedInset* inset = GetInset();
376          inset = inset->Clone();
377          my_memcpy(&array->bf[pos+1], &inset, sizeof(inset));
378       }
379       Next();
380    }
381 //   pos = posx;
382    array = t;
383    ipop(); 
384    return a;
385 }
386
387
388 void MathedIter::Clear()
389 {
390    if (!array) {
391            lyxerr << "Math error: Attempting to clean a void array." << endl;
392       return;
393    }   
394    Reset();  
395    while (OK()) {
396       if (IsInset()) {
397          MathedInset * inset = GetInset();
398           if (inset->GetType()!= LM_OT_MACRO_ARG)
399             delete inset;
400           Delete();
401       } else
402         Next();
403    }
404 }
405
406
407 // Check consistency of tabs and crs
408 void MathedIter::checkTabs()
409 {
410     ipush();
411     
412 //    MathedIter:Reset();
413     while (OK()) {
414         if ((IsTab() && col>= ncols-1) || (IsCR() && !(MthIF_CR&flags))) {
415             Delete();
416             continue;
417         }
418         if (IsCR() && col<ncols-2) {
419             Insert(' ', LM_TC_TAB);
420         }
421         MathedIter::Next();
422     }
423     if (col<ncols-2) {
424         Insert(' ', LM_TC_TAB);
425     }
426     ipop();
427 }         
428
429
430 //  Try to adjust tabs in the expected place, as used in eqnarrays
431 //  Rules:
432 //   - If there are a relation operator, put tabs around it
433 //   - If tehre are not a relation operator, put everything in the
434 //     3rd column.
435 void MathedIter::adjustTabs()
436 {
437
438 }         
439
440
441 void MathedXIter::Clean(int pos2)
442 {
443     if (!array) {
444             lyxerr << "Math error: Attempting to clean a void array." << endl;
445         return;
446     } 
447     
448     int pos1 = pos;
449     
450     if (pos2<pos1) {  
451         GoBegin();
452         while (pos<pos2 && OK()) { Next();
453         }
454         pos2 = pos1;
455         pos1 = pos;
456     }
457
458     ipush();
459     while (OK() && pos<pos2) {
460         if (IsInset()) {
461             MathedInset* inset = GetInset();
462             Next();
463             if (inset->GetType()!= LM_OT_MACRO_ARG)
464               delete inset;
465             continue;
466         } 
467         if (IsCR()) {
468             if (crow) {
469                 MathedRowSt *r = crow->next;
470                 if (r) {
471                     crow->next = r->next;
472                     delete r;
473                 }          
474             }
475         }
476         Next();
477     }    
478     ipop();
479     
480     if (pos2<= array->Last()) {
481         pos = pos1;
482         join(pos2);
483         checkTabs();
484     } 
485 }
486
487
488 void MathedXIter::Merge(LyxArrayBase *a0)
489 {
490     if (!a0) {
491             lyxerr[Debug::MATHED]
492                     << "Math error: Attempting to merge a void array." << endl;
493
494         return;
495     }
496     // All insets must be clonned
497     MathedIter it(a0);
498     LyxArrayBase *a = it.Copy();
499     
500     // make rom for the data 
501     split(a->Last());
502     array->MergeF(a, pos, a->Last());
503
504     int pos1= pos, pos2 = pos + a->Last(); // pos3= 0;
505
506     goPosAbs(pos1);
507     
508     // Complete rows
509     while (pos<pos2 && OK()) {
510         if (IsCR()) {
511             if (p && p->Permit(LMPF_ALLOW_CR)) {
512                 MathedRowSt *r = new MathedRowSt(ncols+1);
513                 if (crow) {
514                     r->next = crow->next;
515                     crow->next = r;
516                   } else {
517                       r->next = 0;
518                   }
519                 crow = r;
520             } else {
521                 Delete();
522                 --pos2;
523             }
524         }
525         Next();    
526     }
527     pos2 = getPos();
528     goPosAbs(pos1);
529     checkTabs();
530     goPosAbs(pos2);
531     
532     delete a;
533 }
534
535
536 //-----------  XIter
537
538
539 MathedXIter::MathedXIter(MathParInset* pp): p(pp) 
540
541     x = y = 0;
542     sx = sw = 0;   
543     limits = false;
544     s_type = 0;  
545     if (p) 
546       SetData(p);
547     else {
548         crow = 0;
549         size = 0;
550     }
551 }
552
553 void MathedXIter::SetData(MathParInset *pp)
554 {
555     p = pp;
556     x = y = 0;
557     array = p->GetData();
558     ncols = p->GetColumns();
559     crow = p->getRowSt();
560     if (p->Permit(LMPF_ALLOW_CR))
561       flags |= MthIF_CR;
562     if (p->Permit(LMPF_ALLOW_TAB))
563       flags |= MthIF_Tabs;
564     
565     if (crow) {
566         x = crow->getTab(0);
567         y = crow->getBaseline();
568     } 
569     if (!array) {
570             array = new LyxArrayBase; // this leaks
571         p->SetData(array);
572     }
573     size = p->GetStyle();
574     Reset();
575 }
576
577 byte* MathedXIter::GetString(int& ls)
578 {  
579    static byte s[255];
580    byte const *sxs =  MathedIter::GetString(ls);
581    if (ls>0) {
582        strncpy(reinterpret_cast<char*>(s), reinterpret_cast<const char*>(sxs), ls);
583        x += mathed_string_width(fcode, size, s, ls);
584        return &s[0];
585    }        
586     return 0;
587 }
588
589
590 bool MathedXIter::Next()
591 {  
592 //    lyxerr << "Ne[" << pos << "]";
593    if (!OK()) return false;
594    int w = 0;
595 //   lyxerr << "xt ";
596    if (IsInset()) {
597       MathedInset * px = GetInset();
598       w = px->Width();
599       if (px->GetType() == LM_OT_SCRIPT) {
600          if (w > sw) sw = w;
601          w = 0;
602       } else
603         sx = (px->GetLimits()) ? w : 0;
604    } else {  
605       byte c = GetChar();
606       if (c >= ' ') {
607 //        lyxerr << "WD[" << fcode << " " << size << " " << c << endl;
608           w = mathed_char_width(fcode, size, c);
609       } else
610       if (c == LM_TC_TAB && p) {
611 //       w = p->GetTab(col+1);
612           w = (crow) ? crow->getTab(col + 1) : 0;
613          //lyxerr << "WW[" << w << "]";
614       } else
615       if (c == LM_TC_CR && p) {
616           x = 0;
617           if (crow && crow->next) {
618               crow = crow->next;
619               y = crow->getBaseline();
620               w = crow->getTab(0);
621           }
622 //        lyxerr << "WW[" << col " " << row << "|" << w << "]";
623       } else 
624               lyxerr << "No hubo w[" << c << "]!";
625    }
626    if (MathedIter::Next()) {
627 //       lyxerr <<"LNX " << pos << endl;
628 //       if (sw>0 && GetChar()!= LM_TC_UP && GetChar()!= LM_TC_DOWN) {
629 //         w = (sx>sw) ? 0: sw-sx;
630       if ((sw > 0 || sx > 0) && GetChar() != LM_TC_UP && GetChar() != LM_TC_DOWN) {
631           if (sw > 0)
632             w = (sx > sw) ? 0 : sw - sx;
633           sx = sw = 0;
634       }
635       x += w;
636       return true;
637    } else
638      return false;
639 }
640
641
642 void MathedXIter::GoBegin()
643 {
644    Reset();
645    x = y = 0;   
646    sw = sx = 0;
647    if (p) {
648        crow = p->getRowSt();
649        if (crow) {
650            x = crow->getTab(0);
651            y = crow->getBaseline();
652        }
653    }
654 }
655
656 void MathedXIter::GoLast()
657 {
658    while (Next());
659 }
660
661
662 void MathedXIter::Adjust()
663 {
664    int posx = pos;
665    GoBegin();
666    while (posx>pos && OK()) Next();  
667 }
668
669
670 bool MathedXIter::Prev()
671 {  
672     if (pos == 0 || (pos == 1 && GetChar()>= ' '))
673       return false;
674     
675     int pos2 = pos; // pos1
676     GoBegin();
677     do {
678         ipush();
679         Next();
680     } while (pos<pos2);
681     ipop();
682     
683     return (!IsCR());
684 }
685
686
687 bool MathedXIter::goNextColumn()
688 {  
689     int rowp = row, colp= col;
690     while (Next() && col == colp);
691     
692     return (col!= colp+1 || rowp!= row);
693 }
694
695
696 bool MathedXIter::Up()
697 {
698     if (row == 0) return false;
699     int xp = x, rowp = row, colp= col;
700     GoBegin();
701     while (row<rowp-1) Next();
702     while (x<xp && OK() && !IsCR()) {
703         ipush();
704         Next();
705     }
706     if (col>colp) // || (stck.col == colp && stck.x<= xp && x>xp))
707       ipop();
708     
709     return true;
710 }
711
712
713 bool MathedXIter::Down()
714 {
715         int xp = x, colp= col; // , rowp = row
716     
717     bool res = (IsCR()) ? true: goNextCode(LM_TC_CR);
718     if (res) {
719         Next();
720         ipush();
721         while (x<xp && OK()) {
722             ipush();
723             Next();
724         }
725         if (col>colp || (stck.col == colp && stck.x<= xp && x>xp)) 
726           ipop();         
727         return true;
728     }
729     return false;
730 }
731
732
733 void MathedXIter::addRow()
734 {
735     if (!crow) {
736         lyxerr[Debug::MATHED] << "MathErr: Attempt to insert new"
737                 " line in a subparagraph. " << this << endl;
738
739         return;
740     }    
741     // Create new item for the structure    
742     MathedRowSt *r = new MathedRowSt(ncols+1);
743     if (crow) {
744         r->next = crow->next;
745         crow->next = r;
746     } else {
747         crow = r;
748         r->next = 0;
749     }    
750     // Fill missed tabs in current row
751     while (col<ncols-1) 
752       Insert('T', LM_TC_TAB); 
753     //newline
754     Insert('K', LM_TC_CR);
755     
756     ipush();
757     if (!IsCR())
758       goNextCode(LM_TC_CR);
759     
760     // Fill missed tabs in new row
761     while (col<ncols-1) 
762       Insert('T', LM_TC_TAB);
763     ipop();
764 }
765
766
767 void MathedXIter::delRow()
768 {
769     if (!crow) {
770             lyxerr[Debug::MATHED] << "MathErr: Attempt to delete a line in a subparagraph." << endl;
771         return;
772     }
773     bool line_empty = true;
774     ipush();
775 //    while (Next()) {
776     do {
777         if (IsCR()){
778             break;
779         } else if (!IsTab()) {
780             line_empty = false;
781         }
782     } while (Next());
783     int p1 = getPos();
784     ipop();
785     
786     if (line_empty) {
787         
788         MathedRowSt *r = crow->next;
789         if (r) {
790             crow->next = r->next;
791             delete r;
792         }
793         join(p1);
794         Delete();
795     } else
796       Clean(p1);
797     
798     checkTabs();    
799 }
800
801 void MathedXIter::ipush()
802
803     MathedIter::ipush();
804     stck.x = x;
805     stck.y = y;
806 }
807
808
809 void MathedXIter::ipop()
810
811     MathedIter::ipop();
812     x = stck.x;
813     y = stck.y;
814     if (p) {
815         crow = p->getRowSt();
816         if (crow)
817           for (int i = 0; i < row; ++i) 
818             crow = crow->next;
819     }
820 }
821
822
823 void MathedXIter::fitCoord(int /*xx*/, int yy)
824 {
825     int xo = 0, yo = 0;
826     
827     GoBegin();
828     if (p) 
829       p->GetXY(xo, yo);
830     // first fit vertically
831     while (crow && OK()) {
832         if (yy>= yo+y-crow->asc && yy<= yo+y+crow->desc) 
833           break;
834         goNextCode(LM_TC_CR);
835         Next();
836     }
837     // now horizontally
838 //    while (x<xx && Next());
839 }
840
841 void MathedXIter::setTab(int tx, int tab)
842 {
843     if (crow && tab<= ncols) {
844         crow->w[tab] = tx;
845     }
846     else 
847             lyxerr << "MathErr: No tabs allowed here" << endl;
848 }
849
850
851 void MathedXIter::subMetrics(int a, int d)
852 {
853     if (!crow) {
854 //      lyxerr << "MathErr: Attempt to submetric a subparagraph." << endl;
855         return;
856     }    
857     crow->asc = a;
858     crow->desc = d;
859 }
860
861
862 // This function is not recursive, as MathPar::Metrics is
863 void MathedXIter::IMetrics(int pos2, int& width, int& ascent, int& descent)
864 {  
865         byte cx, cxp= 0;// *s;
866         int x1;// ls;
867     int asc= 0, des= 0;
868     bool limit = false;
869   
870     descent = ascent = width = 0;
871     if (!array) return;
872     if (array->empty()) return;
873 //    if  (pos2 > array->last) return;
874     x1 = x; 
875     while (pos<pos2) {
876         cx = GetChar();
877         if (cx >= ' ') {
878             mathed_char_height(FCode(), size, cx, asc, des);
879             if (asc > ascent) ascent = asc;
880             if (des > descent) descent = des;
881             limit = false;
882         } else
883         if (MathIsInset(cx)) {
884             MathedInset *pp = GetInset();
885             if (cx == LM_TC_UP) {
886                 if (!asc && p) {
887                     int xx, yy;
888                     p->GetXY(xx, yy);
889                     static_cast<MathParInset*>(pp)->GetXY(xx, asc);
890                     asc = yy - asc;
891                 }
892                 asc += ((limits) ? pp->Height()+4: pp->Ascent());
893             } else
894               if (cx == LM_TC_DOWN) {
895                   if (!des && p) {
896                       int xx, yy;
897                       p->GetXY(xx, yy);
898                       static_cast<MathParInset*>(pp)->GetXY(xx, des);
899                       if (des-pp->Height()<yy && !asc)
900                         asc = yy - (des-pp->Height());
901                       des -= yy;
902                   }
903                   des += (limit ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
904               } else {
905                   asc = pp->Ascent();
906                   des = pp->Descent();
907               }
908             if (asc > ascent) ascent = asc;
909             if (des > descent) descent = des;
910             if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
911               limit = pp->GetLimits();
912         } else 
913         if (cx == LM_TC_TAB) {
914             limit = false;                   
915         }      
916         else {
917                 lyxerr[Debug::MATHED]
918                         << "Mathed Sel-Error: Unrecognized code["
919                         << cx << ']' << endl;
920             break;
921         }       
922         if (pos < pos2)  Next();
923         cxp = cx;
924    }
925     width = x - x1;
926 }
927
928
929 bool MathedXIter::setNumbered(bool numb)
930 {  
931     if (crow) {
932         crow->setNumbered(numb);
933         return true;
934     }
935     
936     return false;
937 }
938
939
940 bool MathedXIter::setLabel(char* label)
941 {  
942     if (label && crow) {
943         crow->setLabel(label);
944         return true;
945     }
946     
947     return false;
948 }
949
950
951 MathedRowSt *MathedXIter::adjustVerticalSt()
952 {
953     GoBegin();
954     if (!crow) {
955 //      lyxerr << " CRW" << ncols << " ";
956             crow = new MathedRowSt(ncols+1); // this leaks
957     }
958 //    lyxerr<< " CRW[" << crow << "] ";
959     MathedRowSt *mrow = crow;
960     while (OK()) {
961         if (IsCR()) {
962             if (col>= ncols) ncols = col+1; 
963             MathedRowSt *r = new MathedRowSt(ncols+1); // this leaks
964 //          r->next = crow->next;
965             crow->next = r;
966             crow = r;
967 //          lyxerr << " CX[" << crow << "]";
968         }   
969         Next(); 
970     }
971     return mrow;
972 }
973