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