]> git.lyx.org Git - features.git/blob - src/mathed/math_xiter.C
mathed49.diff
[features.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_()
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), crow_()
24
25         if (p_) 
26                 SetData(p_);
27         else {
28                 size_ = 0;
29         }
30 }
31
32
33
34 MathParInset * MathedXIter::getPar() const
35 {
36         return p_;
37 }
38
39 MathedRowContainer & MathedXIter::container()
40 {
41         Assert(p_);
42         return p_->getRowSt();
43 }
44
45
46 void MathedXIter::GetPos(int & xx, int & yy) const
47
48         if (p_) 
49                 p_->GetXY(xx, yy);
50         else {
51                 xx = 0;
52                 yy = 0;
53         }        
54         xx += x_;
55         yy += y_;
56 }
57
58
59 int MathedXIter::GetX() const
60
61         int xx;
62         int dummy_y;
63         GetPos(xx, dummy_y);
64         return xx; 
65 }
66
67
68 int MathedXIter::GetY() const
69
70         int dummy_x;
71         int yy;
72         GetPos(dummy_x, yy);
73         return yy; 
74 }
75
76
77 void MathedXIter::GetIncPos(int & xx, int & yy) const
78
79         xx = x_;
80         yy = y_; 
81 }
82
83
84 void MathedXIter::getAD(int & a, int & d) const
85
86         if (crow_) {
87                 a = crow_->ascent();
88                 d = crow_->descent();
89         } else 
90                 if (p_) {
91                         a = p_->Ascent();
92                         d = p_->Descent();
93                 } else {
94                         a = d = 0;
95                 }
96 }
97
98
99 void MathedXIter::Clean(int pos2)
100 {
101         if (!array) {
102                 lyxerr << "Math error: Attempting to clean a void array." << endl;
103                 return;
104         } 
105         
106         int pos1 = pos;
107         
108         if (pos2 < pos1) {
109                 GoBegin();
110                 while (pos < pos2 && OK()) {
111                         Next();
112                 }
113                 pos2 = pos1;
114                 pos1 = pos;
115         }
116         
117         ipush();
118         while (OK() && pos < pos2) {
119                 if (IsInset()) {
120                         MathedInset * inset = GetInset();
121                         Next();
122                         if (inset->GetType()!= LM_OT_MACRO_ARG)
123                                 delete inset;
124                         continue;
125                 } 
126                 if (IsCR()) {
127                         if (crow_) {
128                                 MathedRowContainer::iterator r = crow_;
129                                 ++r;
130                                 if (r) {
131                                         crow_.st_->next_ = r.st_->next_;
132                                         delete r.st_;
133                                 }          
134                         }
135                 }
136                 Next();
137         }    
138         ipop();
139         
140         if (pos2 <= array->last()) {
141                 pos = pos1;
142                 join(pos2);
143                 checkTabs();
144         } 
145 }
146
147
148 void MathedXIter::Merge(MathedArray const & a)
149 {
150 #if 0
151         array->insert(array->begin() + pos,
152                       a.begin(), a.end());
153 #else
154         // make room for the data 
155         split(a.last());
156         array->merge(a, pos);
157 #endif
158         int pos1 = pos;
159         int pos2 = pos + a.last();
160         
161         goPosAbs(pos1);
162         
163         // Complete rows
164         while (pos < pos2 && OK()) {
165                 if (IsCR()) {
166                         if (p_ && p_->Permit(LMPF_ALLOW_CR)) {
167                                 container().insert_after(crow_, MathedRowSt(ncols + 1));
168                                 ++crow_;
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_ = container().begin();
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_.st_->next_) {
244                                                 ++crow_;
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_ = container().begin();
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
376         // Create new item for the structure    
377         container().insert_after(crow_, MathedRowSt(ncols + 1));
378         // Fill missed tabs in current row
379         while (col < ncols - 1) 
380                 insert('T', LM_TC_TAB); 
381         //newline
382         insert('K', LM_TC_CR);
383         
384         ipush();
385         if (!IsCR())
386                 goNextCode(LM_TC_CR);
387         
388         // Fill missed tabs in new row
389         while (col < ncols - 1) 
390                 insert('T', LM_TC_TAB);
391         ipop();
392 }
393
394
395 void MathedXIter::delRow()
396 {
397         if (!crow_) {
398                 lyxerr[Debug::MATHED] << "MathErr: Attempt to delete a line in a subparagraph." << endl;
399                 return;
400         }
401         bool line_empty = true;
402         ipush();
403 //    while (Next()) {
404         do {
405                 if (IsCR()) {
406                         break;
407                 } else if (!IsTab()) {
408                         line_empty = false;
409                 }
410         } while (Next());
411         int const p1 = getPos();
412         ipop();
413         
414         if (line_empty) {
415                 
416                 MathedRowContainer::iterator r( crow_.st_->next_ );
417                 if (r) {
418                         crow_.st_->next_ = r.st_->next_;
419                         delete r.st_;
420                 }
421                 join(p1);
422                 Delete();
423         } else
424                 Clean(p1);
425         
426         checkTabs();    
427 }
428
429
430 void MathedXIter::ipush()
431
432         MathedIter::ipush();
433         stck.x = x_;
434         stck.y = y_;
435 }
436
437
438 void MathedXIter::ipop()
439
440         MathedIter::ipop();
441         x_ = stck.x;
442         y_ = stck.y;
443         if (p_) {
444                 crow_ = container().begin();
445                 if (crow_)
446                         for (int i = 0; i < row; ++i)
447                                 ++crow_;
448         }
449 }
450
451
452 void MathedXIter::fitCoord(int /*xx*/, int yy)
453 {
454         int xo = 0;
455         int yo = 0;
456         
457         GoBegin();
458         if (p_)
459                 p_->GetXY(xo, yo);
460         // first fit vertically
461         while (crow_ && OK()) {
462                 if (yy >= yo + y_ - crow_->ascent()
463                     && yy <= yo + y_ + crow_->descent()) 
464                         break;
465                 goNextCode(LM_TC_CR);
466                 Next();
467         }
468         // now horizontally
469 //    while (x<xx && Next());
470 }
471
472
473 void MathedXIter::setTab(int tx, int tab)
474 {
475         if (crow_ && tab <= ncols) {
476                 crow_->setTab(tab, tx);
477         } else
478                 lyxerr << "MathErr: No tabs allowed here" << endl;
479 }
480
481
482 void MathedXIter::subMetrics(int a, int d)
483 {
484         if (!crow_) {
485                 lyxerr[Debug::MATHED]
486                         << "MathErr: Attempt to submetric a subparagraph." << endl;
487                 return;
488         }
489         crow_->ascent(a);
490         crow_->descent(d);
491 }
492
493
494 // This function is not recursive, as MathPar::Metrics is
495 void MathedXIter::IMetrics(int pos2, int & width, int & ascent, int & descent)
496 {  
497         byte cx;
498         int x1; // ls;
499         int asc = 0;
500         int des = 0;
501         bool limit = false;
502         
503         descent = ascent = width = 0;
504         if (!array) return;
505         if (array->empty()) return;
506 //    if  (pos2 > array->last) return;
507         x1 = x_; 
508         while (pos < pos2) {
509                 cx = GetChar();
510                 if (cx >= ' ') {
511                         mathed_char_height(fcode(), size_, cx, asc, des);
512                         if (asc > ascent) ascent = asc;
513                         if (des > descent) descent = des;
514                         limit = false;
515                 } else
516                         if (MathIsInset(cx)) {
517                                 MathedInset * pp = GetInset();
518                                 if (cx == LM_TC_UP) {
519                                         if (!asc && p_) {
520                                                 int xx;
521                                                 int yy;
522                                                 p_->GetXY(xx, yy);
523                                                 static_cast<MathParInset*>(pp)->GetXY(xx, asc);
524                                                 asc = yy - asc;
525                                         }
526                                         asc += ((limits_) ? pp->Height() + 4 : pp->Ascent());
527                                 } else if (cx == LM_TC_DOWN) {
528                                         if (!des && p_) {
529                                                 int xx;
530                                                 int yy;
531                                                 p_->GetXY(xx, yy);
532                                                 static_cast<MathParInset*>(pp)->GetXY(xx, des);
533                                                 if (des - pp->Height() < yy && !asc)
534                                                         asc = yy - (des - pp->Height());
535                                                 des -= yy;
536                                         }
537                                         des += (limit ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
538                                 } else {
539                                         asc = pp->Ascent();
540                                         des = pp->Descent();
541                                 }
542                                 if (asc > ascent) ascent = asc;
543                                 if (des > descent) descent = des;
544                                 if (cx != LM_TC_UP && cx != LM_TC_DOWN)
545                                         limit = pp->GetLimits();
546                         } else if (cx == LM_TC_TAB) {
547                                 limit = false;                   
548                         } else {
549                                 lyxerr[Debug::MATHED]
550                                         << "Mathed Sel-Error: Unrecognized code["
551                                         << cx << ']' << endl;
552                                 break;
553                         }
554                 if (pos < pos2)  Next();
555         }
556         width = x_ - x1;
557 }
558
559
560 bool MathedXIter::setNumbered(bool numb)
561 {  
562         if (crow_) {
563                 crow_->setNumbered(numb);
564                 return true;
565         }
566         
567         return false;
568 }
569
570
571 bool MathedXIter::setLabel(string const & label)
572 {  
573         if (crow_) {
574                 crow_->setLabel(label);
575                 return true;
576         }
577         
578         return false;
579 }
580
581
582 MathedRowSt * MathedXIter::adjustVerticalSt()
583 {
584         GoBegin();
585         if (!crow_) {
586                 crow_.st_ = new MathedRowSt(ncols + 1); // this leaks
587         }
588         MathedRowSt * mrow = crow_.st_;
589         while (OK()) {
590                 if (IsCR()) {
591                         if (col >= ncols)
592                                 ncols = col + 1; 
593                         MathedRowSt * r = new MathedRowSt(ncols + 1); // this leaks
594                         crow_.st_->next_ = r;
595                         crow_.st_ = r;
596                 }   
597                 Next(); 
598         }
599         return mrow;
600 }
601
602
603 string const & MathedXIter::getLabel() const
604 {
605         return crow_ ? crow_->getLabel() : error_label;
606 }
607
608