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