]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xiter.C
mathed34.diff
[lyx.git] / src / mathed / math_xiter.C
1 #include <config.h>
2
3 #include "math_xiter.h"
4 #include "math_parinset.h"
5 #include "math_rowst.h"
6 #include "array.h"
7 #include "mathed/support.h"
8 #include "debug.h"
9
10 using std::endl;
11
12 string MathedXIter::error_label = "$mathed-error$";
13
14 MathedXIter::MathedXIter()
15         : MathedIter(), size_(0), x_(0), y_(0), p_(0), sx_(0), sw_(0),
16           crow_(0)
17 {
18         // should limits_ be initialized?
19 }
20
21
22 MathedXIter::MathedXIter(MathParInset * pp)
23         : x_(0), y_(0), p_(pp), sx_(0), sw_(0), limits_(false)
24
25         if (p_) 
26                 SetData(p_);
27         else {
28                 crow_ = 0;
29                 size_ = 0;
30         }
31 }
32
33
34
35 MathParInset * MathedXIter::getPar() const
36 {
37         return p_;
38 }
39
40
41 void MathedXIter::GetPos(int & xx, int & yy) const
42
43         if (p_) 
44                 p_->GetXY(xx, yy);
45         else {
46                 xx = 0;
47                 yy = 0;
48         }        
49         xx += x_;
50         yy += y_;
51 }
52
53
54 int MathedXIter::GetX() const
55
56         int xx;
57         int dummy_y;
58         GetPos(xx, dummy_y);
59         return xx; 
60 }
61
62
63 int MathedXIter::GetY() const
64
65         int dummy_x;
66         int yy;
67         GetPos(dummy_x, yy);
68         return yy; 
69 }
70
71
72 void MathedXIter::GetIncPos(int & xx, int & yy) const
73
74         xx = x_;
75         yy = y_; 
76 }
77
78
79 void MathedXIter::getAD(int & a, int & d) const
80
81         if (crow_) {
82                 a = crow_->ascent();
83                 d = crow_->descent();
84         } else 
85                 if (p_) {
86                         a = p_->Ascent();
87                         d = p_->Descent();
88                 } else {
89                         a = d = 0;
90                 }
91 }
92
93
94 void MathedXIter::Clean(int pos2)
95 {
96         if (!array) {
97                 lyxerr << "Math error: Attempting to clean a void array." << endl;
98                 return;
99         } 
100         
101         int pos1 = pos;
102         
103         if (pos2 < pos1) {
104                 GoBegin();
105                 while (pos < pos2 && OK()) {
106                         Next();
107                 }
108                 pos2 = pos1;
109                 pos1 = pos;
110         }
111         
112         ipush();
113         while (OK() && pos < pos2) {
114                 if (IsInset()) {
115                         MathedInset * inset = GetInset();
116                         Next();
117                         if (inset->GetType()!= LM_OT_MACRO_ARG)
118                                 delete inset;
119                         continue;
120                 } 
121                 if (IsCR()) {
122                         if (crow_) {
123                                 MathedRowSt * r = crow_->getNext();
124                                 if (r) {
125                                         crow_->setNext(r->getNext());
126                                         delete r;
127                                 }          
128                         }
129                 }
130                 Next();
131         }    
132         ipop();
133         
134         if (pos2 <= array->last()) {
135                 pos = pos1;
136                 join(pos2);
137                 checkTabs();
138         } 
139 }
140
141
142 void MathedXIter::Merge(MathedArray * a0)
143 {
144         if (!a0) {
145                 lyxerr[Debug::MATHED]
146                         << "Math error: Attempting to merge a void array." << endl;
147                 
148                 return;
149         }
150         // All insets must be clonned
151         MathedArray * a = new MathedArray(*a0);
152
153 #if 0
154         array->insert(array->begin() + pos,
155                       a->begin(), a->end());
156 #else
157         // make room for the data 
158         split(a->last());
159         array->mergeF(a, pos, a->last());
160 #endif
161         int pos1 = pos;
162         int pos2 = pos + a->last();
163         
164         goPosAbs(pos1);
165         
166         // Complete rows
167         while (pos < pos2 && OK()) {
168                 if (IsCR()) {
169                         if (p_ && p_->Permit(LMPF_ALLOW_CR)) {
170                                 MathedRowSt * r = new MathedRowSt(ncols + 1);
171                                 if (crow_) {
172                                         r->setNext(crow_->getNext());
173                                         crow_->setNext(r);
174                                 } else {
175                                         r->setNext(0);
176                                 }
177                                 crow_ = r;
178                         } else {
179                                 Delete();
180                                 --pos2;
181                         }
182                 }
183                 Next();    
184         }
185         pos2 = getPos();
186         goPosAbs(pos1);
187         checkTabs();
188         goPosAbs(pos2);
189         
190         delete a;
191 }
192
193
194 void MathedXIter::SetData(MathParInset * pp)
195 {
196         p_ = pp;
197         x_ = y_ = 0;
198         array = &p_->GetData();
199         ncols = p_->GetColumns();
200         crow_ = p_->getRowSt();
201         if (p_->Permit(LMPF_ALLOW_CR))
202                 flags |= MthIF_CR;
203         if (p_->Permit(LMPF_ALLOW_TAB))
204                 flags |= MthIF_Tabs;
205         
206         if (crow_) {
207                 x_ = crow_->getTab(0);
208                 y_ = crow_->getBaseline();
209         } 
210         if (!array) {
211                 array = new MathedArray; // this leaks
212                 p_->setData(*array);
213         }
214         size_ = p_->GetStyle();
215         Reset();
216 }
217
218
219 string const MathedXIter::GetString() const
220 {
221         string const s = MathedIter::GetString();
222         x_ += mathed_string_width(fcode(), size_, s);
223         return s;
224 }
225
226
227 bool MathedXIter::Next()
228 {  
229 //    lyxerr << "Ne[" << pos << "]";
230         if (!OK()) return false;
231         int w = 0;
232 //   lyxerr << "xt ";
233         if (IsInset()) {
234                 MathedInset * px = GetInset();
235                 w = px->Width();
236                 if (px->GetType() == LM_OT_SCRIPT) {
237                         if (w > sw_) sw_ = w;
238                         w = 0;
239                 } else
240                         sx_ = (px->GetLimits()) ? w : 0;
241         } else {  
242                 byte c = GetChar();
243                 if (c >= ' ') {
244 //        lyxerr << "WD[" << fcode << " " << size << " " << c << endl;
245                         w = mathed_char_width(fcode(), size_, c);
246                 } else
247                         if (c == LM_TC_TAB && p_) {
248 //       w = p->GetTab(col + 1);
249                                 w = (crow_) ? crow_->getTab(col + 1) : 0;
250                                 //lyxerr << "WW[" << w << "]";
251                         } else
252                                 if (c == LM_TC_CR && p_) {
253                                         x_ = 0;
254                                         if (crow_ && crow_->getNext()) {
255                                                 crow_ = crow_->getNext();
256                                                 y_ = crow_->getBaseline();
257                                                 w = crow_->getTab(0);
258                                         }
259 //        lyxerr << "WW[" << col " " << row << "|" << w << "]";
260                                 } else 
261                                         lyxerr << "No hubo w[" << c << "]!";
262         }
263         if (MathedIter::Next()) {
264 //       lyxerr <<"LNX " << pos << endl;
265 //       if (sw>0 && GetChar()!= LM_TC_UP && GetChar()!= LM_TC_DOWN) {
266 //         w = (sx>sw) ? 0: sw-sx;
267                 if ((sw_ > 0 || sx_ > 0)
268                     && GetChar() != LM_TC_UP && GetChar() != LM_TC_DOWN) {
269                         if (sw_ > 0)
270                                 w = (sx_ > sw_) ? 0 : sw_ - sx_;
271                         sx_ = sw_ = 0;
272                 }
273                 x_ += w;
274                 return true;
275         } else
276                 return false;
277 }
278
279
280 void MathedXIter::GoBegin()
281 {
282         Reset();
283         x_ = y_ = 0;   
284         sw_ = sx_ = 0;
285         if (p_) {
286                 crow_ = p_->getRowSt();
287                 if (crow_) {
288                         x_ = crow_->getTab(0);
289                         y_ = crow_->getBaseline();
290                 }
291         }
292 }
293
294
295 void MathedXIter::GoLast()
296 {
297         while (Next());
298 }
299
300
301 void MathedXIter::Adjust()
302 {
303         int posx = pos;
304         GoBegin();
305         while (posx > pos && OK()) Next();  
306 }
307
308
309 bool MathedXIter::Prev()
310 {  
311         if (pos == 0 || (pos == 1 && GetChar() >= ' '))
312                 return false;
313         
314         int pos2 = pos; // pos1
315         GoBegin();
316         do {
317                 ipush();
318                 Next();
319         } while (pos<pos2);
320         ipop();
321         
322         return (!IsCR());
323 }
324
325
326 void MathedXIter::goNextColumn()
327 {  
328         //int rowp = row;
329         int colp = col;
330         while (Next() && col == colp)
331                 ;
332         
333         //return (col != colp + 1 || rowp != row);
334 }
335
336
337 bool MathedXIter::Up()
338 {
339         if (row == 0) return false;
340         int xp = x_;
341         int rowp = row;
342         int colp = col;
343         GoBegin();
344         while (row < rowp - 1) Next();
345         while (x_ < xp && OK() && !IsCR()) {
346                 ipush();
347                 Next();
348         }
349         if (col > colp) // || (stck.col == colp && stck.x<= xp && x>xp))
350                 ipop();
351         
352         return true;
353 }
354
355
356 bool MathedXIter::Down()
357 {
358         int xp = x_;
359         int colp= col;
360         // int rowp = row
361         
362         bool res = (IsCR()) ? true : goNextCode(LM_TC_CR);
363         if (res) {
364                 Next();
365                 ipush();
366                 while (x_ < xp && OK()) {
367                         ipush();
368                         Next();
369                 }
370                 if (col > colp || (stck.col == colp && stck.x <= xp && x_ > xp))
371                         ipop();
372                 return true;
373         }
374         return false;
375 }
376
377
378 void MathedXIter::addRow()
379 {
380         if (!crow_) {
381                 lyxerr[Debug::MATHED] << "MathErr: Attempt to insert new"
382                         " line in a subparagraph. " << this << endl;
383                 
384                 return;
385         }
386         // Create new item for the structure    
387         MathedRowSt * r = new MathedRowSt(ncols + 1);
388         if (crow_) {
389                 r->setNext(crow_->getNext());
390                 crow_->setNext(r);
391         } else {
392                 crow_ = r;
393                 r->setNext(0);
394         }    
395         // Fill missed tabs in current row
396         while (col < ncols - 1) 
397                 insert('T', LM_TC_TAB); 
398         //newline
399         insert('K', LM_TC_CR);
400         
401         ipush();
402         if (!IsCR())
403                 goNextCode(LM_TC_CR);
404         
405         // Fill missed tabs in new row
406         while (col < ncols - 1) 
407                 insert('T', LM_TC_TAB);
408         ipop();
409 }
410
411
412 void MathedXIter::delRow()
413 {
414         if (!crow_) {
415                 lyxerr[Debug::MATHED] << "MathErr: Attempt to delete a line in a subparagraph." << endl;
416                 return;
417         }
418         bool line_empty = true;
419         ipush();
420 //    while (Next()) {
421         do {
422                 if (IsCR()) {
423                         break;
424                 } else if (!IsTab()) {
425                         line_empty = false;
426                 }
427         } while (Next());
428         int const p1 = getPos();
429         ipop();
430         
431         if (line_empty) {
432                 
433                 MathedRowSt * r = crow_->getNext();
434                 if (r) {
435                         crow_->setNext(r->getNext());
436                         delete r;
437                 }
438                 join(p1);
439                 Delete();
440         } else
441                 Clean(p1);
442         
443         checkTabs();    
444 }
445
446
447 void MathedXIter::ipush()
448
449         MathedIter::ipush();
450         stck.x = x_;
451         stck.y = y_;
452 }
453
454
455 void MathedXIter::ipop()
456
457         MathedIter::ipop();
458         x_ = stck.x;
459         y_ = stck.y;
460         if (p_) {
461                 crow_ = p_->getRowSt();
462                 if (crow_)
463                         for (int i = 0; i < row; ++i)
464                                 crow_ = crow_->getNext();
465         }
466 }
467
468
469 void MathedXIter::fitCoord(int /*xx*/, int yy)
470 {
471         int xo = 0;
472         int yo = 0;
473         
474         GoBegin();
475         if (p_)
476                 p_->GetXY(xo, yo);
477         // first fit vertically
478         while (crow_ && OK()) {
479                 if (yy >= yo + y_ - crow_->ascent()
480                     && yy <= yo + y_ + crow_->descent()) 
481                         break;
482                 goNextCode(LM_TC_CR);
483                 Next();
484         }
485         // now horizontally
486 //    while (x<xx && Next());
487 }
488
489
490 void MathedXIter::setTab(int tx, int tab)
491 {
492         if (crow_ && tab <= ncols) {
493                 crow_->setTab(tab, tx);
494         } else
495                 lyxerr << "MathErr: No tabs allowed here" << endl;
496 }
497
498
499 void MathedXIter::subMetrics(int a, int d)
500 {
501         if (!crow_) {
502                 lyxerr[Debug::MATHED]
503                         << "MathErr: Attempt to submetric a subparagraph." << endl;
504                 return;
505         }
506         crow_->ascent(a);
507         crow_->descent(d);
508 }
509
510
511 // This function is not recursive, as MathPar::Metrics is
512 void MathedXIter::IMetrics(int pos2, int & width, int & ascent, int & descent)
513 {  
514         byte cx;
515         int x1; // ls;
516         int asc = 0;
517         int des = 0;
518         bool limit = false;
519         
520         descent = ascent = width = 0;
521         if (!array) return;
522         if (array->empty()) return;
523 //    if  (pos2 > array->last) return;
524         x1 = x_; 
525         while (pos < pos2) {
526                 cx = GetChar();
527                 if (cx >= ' ') {
528                         mathed_char_height(fcode(), size_, cx, asc, des);
529                         if (asc > ascent) ascent = asc;
530                         if (des > descent) descent = des;
531                         limit = false;
532                 } else
533                         if (MathIsInset(cx)) {
534                                 MathedInset * pp = GetInset();
535                                 if (cx == LM_TC_UP) {
536                                         if (!asc && p_) {
537                                                 int xx;
538                                                 int yy;
539                                                 p_->GetXY(xx, yy);
540                                                 static_cast<MathParInset*>(pp)->GetXY(xx, asc);
541                                                 asc = yy - asc;
542                                         }
543                                         asc += ((limits_) ? pp->Height() + 4 : pp->Ascent());
544                                 } else if (cx == LM_TC_DOWN) {
545                                         if (!des && p_) {
546                                                 int xx;
547                                                 int yy;
548                                                 p_->GetXY(xx, yy);
549                                                 static_cast<MathParInset*>(pp)->GetXY(xx, des);
550                                                 if (des - pp->Height() < yy && !asc)
551                                                         asc = yy - (des - pp->Height());
552                                                 des -= yy;
553                                         }
554                                         des += (limit ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
555                                 } else {
556                                         asc = pp->Ascent();
557                                         des = pp->Descent();
558                                 }
559                                 if (asc > ascent) ascent = asc;
560                                 if (des > descent) descent = des;
561                                 if (cx != LM_TC_UP && cx != LM_TC_DOWN)
562                                         limit = pp->GetLimits();
563                         } else if (cx == LM_TC_TAB) {
564                                 limit = false;                   
565                         } else {
566                                 lyxerr[Debug::MATHED]
567                                         << "Mathed Sel-Error: Unrecognized code["
568                                         << cx << ']' << endl;
569                                 break;
570                         }
571                 if (pos < pos2)  Next();
572         }
573         width = x_ - x1;
574 }
575
576
577 bool MathedXIter::setNumbered(bool numb)
578 {  
579         if (crow_) {
580                 crow_->setNumbered(numb);
581                 return true;
582         }
583         
584         return false;
585 }
586
587
588 bool MathedXIter::setLabel(string const & label)
589 {  
590         if (crow_) {
591                 crow_->setLabel(label);
592                 return true;
593         }
594         
595         return false;
596 }
597
598
599 MathedRowSt * MathedXIter::adjustVerticalSt()
600 {
601         GoBegin();
602         if (!crow_) {
603 //      lyxerr << " CRW" << ncols << " ";
604                 crow_ = new MathedRowSt(ncols + 1); // this leaks
605         }
606 //    lyxerr<< " CRW[" << crow_ << "] ";
607         MathedRowSt * mrow = crow_;
608         while (OK()) {
609                 if (IsCR()) {
610                         if (col >= ncols) ncols = col + 1; 
611                         MathedRowSt * r = new MathedRowSt(ncols + 1); // this leaks
612 //          r->next = crow_->next;
613                         crow_->setNext(r);
614                         crow_ = r;
615 //          lyxerr << " CX[" << crow_ << "]";
616                 }   
617                 Next(); 
618         }
619         return mrow;
620 }
621
622
623 string const & MathedXIter::getLabel() const
624 {
625         return crow_ ? crow_->getLabel() : error_label;
626 }
627
628