]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xiter.C
cleanup indent
[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 const & a)
143 {
144 #if 0
145         array->insert(array->begin() + pos,
146                       a.begin(), a.end());
147 #else
148         // make room for the data 
149         split(a.last());
150         array->merge(a, pos);
151 #endif
152         int pos1 = pos;
153         int pos2 = pos + a.last();
154         
155         goPosAbs(pos1);
156         
157         // Complete rows
158         while (pos < pos2 && OK()) {
159                 if (IsCR()) {
160                         if (p_ && p_->Permit(LMPF_ALLOW_CR)) {
161                                 MathedRowSt * r = new MathedRowSt(ncols + 1);
162                                 if (crow_) {
163                                         r->setNext(crow_->getNext());
164                                         crow_->setNext(r);
165                                 } else {
166                                         r->setNext(0);
167                                 }
168                                 crow_ = r;
169                         } else {
170                                 Delete();
171                                 --pos2;
172                         }
173                 }
174                 Next();    
175         }
176         pos2 = getPos();
177         goPosAbs(pos1);
178         checkTabs();
179         goPosAbs(pos2);
180 }
181
182
183 void MathedXIter::SetData(MathParInset * pp)
184 {
185         p_ = pp;
186         x_ = y_ = 0;
187         array = &p_->GetData();
188         ncols = p_->GetColumns();
189         crow_ = p_->getRowSt();
190         if (p_->Permit(LMPF_ALLOW_CR))
191                 flags |= MthIF_CR;
192         if (p_->Permit(LMPF_ALLOW_TAB))
193                 flags |= MthIF_Tabs;
194         
195         if (crow_) {
196                 x_ = crow_->getTab(0);
197                 y_ = crow_->getBaseline();
198         } 
199         if (!array) {
200                 array = new MathedArray; // this leaks
201                 p_->setData(*array);
202         }
203         size_ = p_->GetStyle();
204         Reset();
205 }
206
207
208 string const MathedXIter::GetString() const
209 {
210         string const s = MathedIter::GetString();
211         x_ += mathed_string_width(fcode(), size_, s);
212         return s;
213 }
214
215
216 bool MathedXIter::Next()
217 {  
218 //    lyxerr << "Ne[" << pos << "]";
219         if (!OK()) return false;
220         int w = 0;
221 //   lyxerr << "xt ";
222         if (IsInset()) {
223                 MathedInset * px = GetInset();
224                 w = px->Width();
225                 if (px->GetType() == LM_OT_SCRIPT) {
226                         if (w > sw_) sw_ = w;
227                         w = 0;
228                 } else
229                         sx_ = (px->GetLimits()) ? w : 0;
230         } else {  
231                 byte c = GetChar();
232                 if (c >= ' ') {
233 //        lyxerr << "WD[" << fcode << " " << size << " " << c << endl;
234                         w = mathed_char_width(fcode(), size_, c);
235                 } else
236                         if (c == LM_TC_TAB && p_) {
237 //       w = p->GetTab(col + 1);
238                                 w = (crow_) ? crow_->getTab(col + 1) : 0;
239                                 //lyxerr << "WW[" << w << "]";
240                         } else
241                                 if (c == LM_TC_CR && p_) {
242                                         x_ = 0;
243                                         if (crow_ && crow_->getNext()) {
244                                                 crow_ = crow_->getNext();
245                                                 y_ = crow_->getBaseline();
246                                                 w = crow_->getTab(0);
247                                         }
248 //        lyxerr << "WW[" << col " " << row << "|" << w << "]";
249                                 } else 
250                                         lyxerr << "No hubo w[" << c << "]!";
251         }
252         if (MathedIter::Next()) {
253 //       lyxerr <<"LNX " << pos << endl;
254 //       if (sw>0 && GetChar()!= LM_TC_UP && GetChar()!= LM_TC_DOWN) {
255 //         w = (sx>sw) ? 0: sw-sx;
256                 if ((sw_ > 0 || sx_ > 0)
257                     && GetChar() != LM_TC_UP && GetChar() != LM_TC_DOWN) {
258                         if (sw_ > 0)
259                                 w = (sx_ > sw_) ? 0 : sw_ - sx_;
260                         sx_ = sw_ = 0;
261                 }
262                 x_ += w;
263                 return true;
264         } else
265                 return false;
266 }
267
268
269 void MathedXIter::GoBegin()
270 {
271         Reset();
272         x_ = y_ = 0;   
273         sw_ = sx_ = 0;
274         if (p_) {
275                 crow_ = p_->getRowSt();
276                 if (crow_) {
277                         x_ = crow_->getTab(0);
278                         y_ = crow_->getBaseline();
279                 }
280         }
281 }
282
283
284 void MathedXIter::GoLast()
285 {
286         while (Next());
287 }
288
289
290 void MathedXIter::Adjust()
291 {
292         int posx = pos;
293         GoBegin();
294         while (posx > pos && OK()) Next();  
295 }
296
297
298 bool MathedXIter::Prev()
299 {  
300         if (pos == 0 || (pos == 1 && GetChar() >= ' '))
301                 return false;
302         
303         int pos2 = pos; // pos1
304         GoBegin();
305         do {
306                 ipush();
307                 Next();
308         } while (pos<pos2);
309         ipop();
310         
311         return (!IsCR());
312 }
313
314
315 void MathedXIter::goNextColumn()
316 {  
317         //int rowp = row;
318         int colp = col;
319         while (Next() && col == colp)
320                 ;
321         
322         //return (col != colp + 1 || rowp != row);
323 }
324
325
326 bool MathedXIter::Up()
327 {
328         if (row == 0) return false;
329         int xp = x_;
330         int rowp = row;
331         int colp = col;
332         GoBegin();
333         while (row < rowp - 1) Next();
334         while (x_ < xp && OK() && !IsCR()) {
335                 ipush();
336                 Next();
337         }
338         if (col > colp) // || (stck.col == colp && stck.x<= xp && x>xp))
339                 ipop();
340         
341         return true;
342 }
343
344
345 bool MathedXIter::Down()
346 {
347         int xp = x_;
348         int colp= col;
349         // int rowp = row
350         
351         bool res = (IsCR()) ? true : goNextCode(LM_TC_CR);
352         if (res) {
353                 Next();
354                 ipush();
355                 while (x_ < xp && OK()) {
356                         ipush();
357                         Next();
358                 }
359                 if (col > colp || (stck.col == colp && stck.x <= xp && x_ > xp))
360                         ipop();
361                 return true;
362         }
363         return false;
364 }
365
366
367 void MathedXIter::addRow()
368 {
369         if (!crow_) {
370                 lyxerr[Debug::MATHED] << "MathErr: Attempt to insert new"
371                         " line in a subparagraph. " << this << endl;
372                 
373                 return;
374         }
375         // Create new item for the structure    
376         MathedRowSt * r = new MathedRowSt(ncols + 1);
377         if (crow_) {
378                 r->setNext(crow_->getNext());
379                 crow_->setNext(r);
380         } else {
381                 crow_ = r;
382                 r->setNext(0);
383         }    
384         // Fill missed tabs in current row
385         while (col < ncols - 1) 
386                 insert('T', LM_TC_TAB); 
387         //newline
388         insert('K', LM_TC_CR);
389         
390         ipush();
391         if (!IsCR())
392                 goNextCode(LM_TC_CR);
393         
394         // Fill missed tabs in new row
395         while (col < ncols - 1) 
396                 insert('T', LM_TC_TAB);
397         ipop();
398 }
399
400
401 void MathedXIter::delRow()
402 {
403         if (!crow_) {
404                 lyxerr[Debug::MATHED] << "MathErr: Attempt to delete a line in a subparagraph." << endl;
405                 return;
406         }
407         bool line_empty = true;
408         ipush();
409 //    while (Next()) {
410         do {
411                 if (IsCR()) {
412                         break;
413                 } else if (!IsTab()) {
414                         line_empty = false;
415                 }
416         } while (Next());
417         int const p1 = getPos();
418         ipop();
419         
420         if (line_empty) {
421                 
422                 MathedRowSt * r = crow_->getNext();
423                 if (r) {
424                         crow_->setNext(r->getNext());
425                         delete r;
426                 }
427                 join(p1);
428                 Delete();
429         } else
430                 Clean(p1);
431         
432         checkTabs();    
433 }
434
435
436 void MathedXIter::ipush()
437
438         MathedIter::ipush();
439         stck.x = x_;
440         stck.y = y_;
441 }
442
443
444 void MathedXIter::ipop()
445
446         MathedIter::ipop();
447         x_ = stck.x;
448         y_ = stck.y;
449         if (p_) {
450                 crow_ = p_->getRowSt();
451                 if (crow_)
452                         for (int i = 0; i < row; ++i)
453                                 crow_ = crow_->getNext();
454         }
455 }
456
457
458 void MathedXIter::fitCoord(int /*xx*/, int yy)
459 {
460         int xo = 0;
461         int yo = 0;
462         
463         GoBegin();
464         if (p_)
465                 p_->GetXY(xo, yo);
466         // first fit vertically
467         while (crow_ && OK()) {
468                 if (yy >= yo + y_ - crow_->ascent()
469                     && yy <= yo + y_ + crow_->descent()) 
470                         break;
471                 goNextCode(LM_TC_CR);
472                 Next();
473         }
474         // now horizontally
475 //    while (x<xx && Next());
476 }
477
478
479 void MathedXIter::setTab(int tx, int tab)
480 {
481         if (crow_ && tab <= ncols) {
482                 crow_->setTab(tab, tx);
483         } else
484                 lyxerr << "MathErr: No tabs allowed here" << endl;
485 }
486
487
488 void MathedXIter::subMetrics(int a, int d)
489 {
490         if (!crow_) {
491                 lyxerr[Debug::MATHED]
492                         << "MathErr: Attempt to submetric a subparagraph." << endl;
493                 return;
494         }
495         crow_->ascent(a);
496         crow_->descent(d);
497 }
498
499
500 // This function is not recursive, as MathPar::Metrics is
501 void MathedXIter::IMetrics(int pos2, int & width, int & ascent, int & descent)
502 {  
503         byte cx;
504         int x1; // ls;
505         int asc = 0;
506         int des = 0;
507         bool limit = false;
508         
509         descent = ascent = width = 0;
510         if (!array) return;
511         if (array->empty()) return;
512 //    if  (pos2 > array->last) return;
513         x1 = x_; 
514         while (pos < pos2) {
515                 cx = GetChar();
516                 if (cx >= ' ') {
517                         mathed_char_height(fcode(), size_, cx, asc, des);
518                         if (asc > ascent) ascent = asc;
519                         if (des > descent) descent = des;
520                         limit = false;
521                 } else
522                         if (MathIsInset(cx)) {
523                                 MathedInset * pp = GetInset();
524                                 if (cx == LM_TC_UP) {
525                                         if (!asc && p_) {
526                                                 int xx;
527                                                 int yy;
528                                                 p_->GetXY(xx, yy);
529                                                 static_cast<MathParInset*>(pp)->GetXY(xx, asc);
530                                                 asc = yy - asc;
531                                         }
532                                         asc += ((limits_) ? pp->Height() + 4 : pp->Ascent());
533                                 } else if (cx == LM_TC_DOWN) {
534                                         if (!des && p_) {
535                                                 int xx;
536                                                 int yy;
537                                                 p_->GetXY(xx, yy);
538                                                 static_cast<MathParInset*>(pp)->GetXY(xx, des);
539                                                 if (des - pp->Height() < yy && !asc)
540                                                         asc = yy - (des - pp->Height());
541                                                 des -= yy;
542                                         }
543                                         des += (limit ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
544                                 } else {
545                                         asc = pp->Ascent();
546                                         des = pp->Descent();
547                                 }
548                                 if (asc > ascent) ascent = asc;
549                                 if (des > descent) descent = des;
550                                 if (cx != LM_TC_UP && cx != LM_TC_DOWN)
551                                         limit = pp->GetLimits();
552                         } else if (cx == LM_TC_TAB) {
553                                 limit = false;                   
554                         } else {
555                                 lyxerr[Debug::MATHED]
556                                         << "Mathed Sel-Error: Unrecognized code["
557                                         << cx << ']' << endl;
558                                 break;
559                         }
560                 if (pos < pos2)  Next();
561         }
562         width = x_ - x1;
563 }
564
565
566 bool MathedXIter::setNumbered(bool numb)
567 {  
568         if (crow_) {
569                 crow_->setNumbered(numb);
570                 return true;
571         }
572         
573         return false;
574 }
575
576
577 bool MathedXIter::setLabel(string const & label)
578 {  
579         if (crow_) {
580                 crow_->setLabel(label);
581                 return true;
582         }
583         
584         return false;
585 }
586
587
588 MathedRowSt * MathedXIter::adjustVerticalSt()
589 {
590         GoBegin();
591         if (!crow_) {
592 //      lyxerr << " CRW" << ncols << " ";
593                 crow_ = new MathedRowSt(ncols + 1); // this leaks
594         }
595 //    lyxerr<< " CRW[" << crow_ << "] ";
596         MathedRowSt * mrow = crow_;
597         while (OK()) {
598                 if (IsCR()) {
599                         if (col >= ncols) ncols = col + 1; 
600                         MathedRowSt * r = new MathedRowSt(ncols + 1); // this leaks
601 //          r->next = crow_->next;
602                         crow_->setNext(r);
603                         crow_ = r;
604 //          lyxerr << " CX[" << crow_ << "]";
605                 }   
606                 Next(); 
607         }
608         return mrow;
609 }
610
611
612 string const & MathedXIter::getLabel() const
613 {
614         return crow_ ? crow_->getLabel() : error_label;
615 }
616
617