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