]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xiter.C
fix "make dist" target
[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_()
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         lyx::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() && crow_)
127                         container().erase(crow_);
128                 Next();
129         }    
130         ipop();
131         
132         if (pos2 <= array->last()) {
133                 pos = pos1;
134                 join(pos2);
135                 checkTabs();
136         } 
137 }
138
139
140 void MathedXIter::Merge(MathedArray const & arr)
141 {
142 #ifdef WITH_WARNINGS
143 #warning quick and really dirty: make sure that we really own our inset
144 #endif
145         MathedArray a = arr;
146
147 #if 0
148         array->insert(array->begin() + pos,
149                       a.begin(), a.end());
150 #else
151         // make room for the data 
152         split(a.last());
153         array->merge(a, pos);
154 #endif
155         int pos1 = pos;
156         int pos2 = pos + a.last();
157         
158         goPosAbs(pos1);
159         
160         // Complete rows
161         while (pos < pos2 && OK()) {
162                 if (IsCR()) {
163                         if (p_ && p_->Permit(LMPF_ALLOW_CR)) {
164                                 container().insert(crow_);
165                                 ++crow_;
166                         } else {
167                                 Delete();
168                                 --pos2;
169                         }
170                 }
171                 Next();    
172         }
173         pos2 = getPos();
174         goPosAbs(pos1);
175         checkTabs();
176         goPosAbs(pos2);
177 }
178
179
180 void MathedXIter::SetData(MathParInset * pp)
181 {
182         //if (p_ && pp != p_) {
183         //      lyxerr << "MathedXIter::SetData: " << p_ << " " << pp << endl;
184         //}
185         p_ = pp;
186         x_ = y_ = 0;
187         array = &p_->GetData();
188         //lyxerr << "MathedXIter::SetData: " << p_ << " " << *array << endl;
189         ncols = p_->GetColumns();
190         crow_ = container().begin();
191         if (p_->Permit(LMPF_ALLOW_CR))
192                 flags |= MthIF_CR;
193         if (p_->Permit(LMPF_ALLOW_TAB))
194                 flags |= MthIF_Tabs;
195         
196         if (crow_) {
197                 x_ = crow_->getTab(0);
198                 y_ = crow_->getBaseline();
199         } 
200         if (!array) {
201                 array = new MathedArray; // this leaks
202                 p_->setData(*array);
203         }
204         size_ = p_->GetStyle();
205         Reset();
206 }
207
208
209 string const MathedXIter::GetString() const
210 {
211         string const s = MathedIter::GetString();
212         x_ += mathed_string_width(fcode(), size_, s);
213         return s;
214 }
215
216
217 bool MathedXIter::Next()
218 {  
219 //    lyxerr << "Ne[" << pos << "]";
220         if (!OK())
221                 return false;
222         int w = 0;
223 //   lyxerr << "xt ";
224         if (IsInset()) {
225                 MathedInset * px = GetInset();
226                 w = px->Width();
227                 if (px->GetType() == LM_OT_SCRIPT) {
228                         if (w > sw_)
229                                 sw_ = w;
230                         w = 0;
231                 } else
232                         sx_ = (px->GetLimits()) ? w : 0;
233         } else {  
234                 byte c = GetChar();
235                 if (c >= ' ') {
236 //        lyxerr << "WD[" << fcode << " " << size << " " << c << endl;
237                         w = mathed_char_width(fcode(), size_, c);
238                 } else
239                         if (c == LM_TC_TAB && p_) {
240 //       w = p->GetTab(col + 1);
241                                 w = (crow_) ? crow_->getTab(col + 1) : 0;
242                                 //lyxerr << "WW[" << w << "]";
243                         } else
244                                 if (c == LM_TC_CR && p_) {
245                                         x_ = 0;
246                                         if (crow_ && !crow_.is_last()) {
247                                                 ++crow_;
248                                                 y_ = crow_->getBaseline();
249                                                 w = crow_->getTab(0);
250                                         }
251 //        lyxerr << "WW[" << col " " << row << "|" << w << "]";
252                                 } else 
253                                         lyxerr << "No hubo w[" << c << "]!";
254         }
255         if (MathedIter::Next()) {
256 //       lyxerr <<"LNX " << pos << endl;
257 //       if (sw>0 && GetChar()!= LM_TC_UP && GetChar()!= LM_TC_DOWN) {
258 //         w = (sx>sw) ? 0: sw-sx;
259                 if ((sw_ > 0 || sx_ > 0)
260                     && GetChar() != LM_TC_UP && GetChar() != LM_TC_DOWN) {
261                         if (sw_ > 0)
262                                 w = (sx_ > sw_) ? 0 : sw_ - sx_;
263                         sx_ = sw_ = 0;
264                 }
265                 x_ += w;
266                 return true;
267         } else
268                 return false;
269 }
270
271
272 void MathedXIter::GoBegin()
273 {
274         Reset();
275         x_ = y_ = 0;   
276         sw_ = sx_ = 0;
277         if (p_) {
278                 crow_ = container().begin();
279                 if (crow_) {
280                         x_ = crow_->getTab(0);
281                         y_ = crow_->getBaseline();
282                 }
283         }
284 }
285
286
287 void MathedXIter::GoLast()
288 {
289         while (Next());
290 }
291
292
293 void MathedXIter::Adjust()
294 {
295         int posx = pos;
296         GoBegin();
297         while (posx > pos && OK())
298                 Next();  
299 }
300
301
302 bool MathedXIter::Prev()
303 {  
304         if (pos == 0 || (pos == 1 && GetChar() >= ' '))
305                 return false;
306         
307         int pos2 = pos; // pos1
308         GoBegin();
309         do {
310                 ipush();
311                 Next();
312         } while (pos < pos2);
313         ipop();
314         
315         return !IsCR();
316 }
317
318
319 void MathedXIter::goNextColumn()
320 {  
321         //int rowp = row;
322         int colp = col;
323         while (Next() && col == colp)
324                 ;
325         
326         //return (col != colp + 1 || rowp != row);
327 }
328
329
330 bool MathedXIter::Up()
331 {
332         if (row == 0) return false;
333         int xp = x_;
334         int rowp = row;
335         int colp = col;
336         GoBegin();
337         while (row < rowp - 1) Next();
338         while (x_ < xp && OK() && !IsCR()) {
339                 ipush();
340                 Next();
341         }
342         if (col > colp) // || (stck.col == colp && stck.x<= xp && x>xp))
343                 ipop();
344         
345         return true;
346 }
347
348
349 bool MathedXIter::Down()
350 {
351         int xp   = x_;
352         int colp = col;
353         // int rowp = row
354         
355         bool res = (IsCR()) ? true : goNextCode(LM_TC_CR);
356         if (res) {
357                 Next();
358                 ipush();
359                 while (x_ < xp && OK()) {
360                         ipush();
361                         Next();
362                 }
363                 if (col > colp || (stck.col == colp && stck.x <= xp && x_ > xp))
364                         ipop();
365                 return true;
366         }
367         return false;
368 }
369
370
371 void MathedXIter::addRow()
372 {
373         if (!crow_) {
374                 lyxerr[Debug::MATHED] << "MathErr: Attempt to insert new"
375                         " line in a subparagraph. " << this << endl;
376                 
377                 return;
378         }
379
380         // Create new item for the structure    
381         container().insert(crow_);
382         // Fill missed tabs in current row
383         while (col < ncols - 1) 
384                 insert('T', LM_TC_TAB); 
385         //newline
386         insert('K', LM_TC_CR);
387         
388         ipush();
389         if (!IsCR())
390                 goNextCode(LM_TC_CR);
391         
392         // Fill missed tabs in new row
393         while (col < ncols - 1) 
394                 insert('T', LM_TC_TAB);
395         ipop();
396 }
397
398
399 void MathedXIter::delRow()
400 {
401         if (!crow_) {
402                 lyxerr[Debug::MATHED] << "MathErr: Attempt to delete a line in a subparagraph." << endl;
403                 return;
404         }
405         bool line_empty = true;
406         ipush();
407 //    while (Next()) {
408         do {
409                 if (IsCR()) 
410                         break;
411
412                 if (!IsTab()) 
413                         line_empty = false;
414         } while (Next());
415
416         int const p1 = getPos();
417         ipop();
418         
419         if (line_empty) {
420                 container().erase(crow_);       
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)
505                 return;
506         if (array->empty())
507                 return;
508 //    if  (pos2 > array->last) return;
509         x1 = x_; 
510         while (pos < pos2) {
511                 cx = GetChar();
512                 if (cx >= ' ') {
513                         mathed_char_height(fcode(), size_, cx, asc, des);
514                         if (asc > ascent) ascent = asc;
515                         if (des > descent) descent = des;
516                         limit = false;
517                 } else
518                         if (MathIsInset(cx)) {
519                                 MathedInset * pp = GetInset();
520                                 if (cx == LM_TC_UP) {
521                                         if (!asc && p_) {
522                                                 int xx;
523                                                 int yy;
524                                                 p_->GetXY(xx, yy);
525                                                 static_cast<MathParInset*>(pp)->GetXY(xx, asc);
526                                                 asc = yy - asc;
527                                         }
528                                         asc += ((limits_) ? pp->Height() + 4 : pp->Ascent());
529                                 } else if (cx == LM_TC_DOWN) {
530                                         if (!des && p_) {
531                                                 int xx;
532                                                 int yy;
533                                                 p_->GetXY(xx, yy);
534                                                 static_cast<MathParInset*>(pp)->GetXY(xx, des);
535                                                 if (des - pp->Height() < yy && !asc)
536                                                         asc = yy - (des - pp->Height());
537                                                 des -= yy;
538                                         }
539                                         des += (limit ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
540                                 } else {
541                                         asc = pp->Ascent();
542                                         des = pp->Descent();
543                                 }
544                                 if (asc > ascent) ascent = asc;
545                                 if (des > descent) descent = des;
546                                 if (cx != LM_TC_UP && cx != LM_TC_DOWN)
547                                         limit = pp->GetLimits();
548                         } else if (cx == LM_TC_TAB) {
549                                 limit = false;                   
550                         } else {
551                                 lyxerr[Debug::MATHED]
552                                         << "Mathed Sel-Error: Unrecognized code["
553                                         << cx << ']' << endl;
554                                 break;
555                         }
556                 if (pos < pos2)
557                         Next();
558         }
559         width = x_ - x1;
560 }
561
562
563 bool MathedXIter::setNumbered(bool numb)
564 {  
565         if (crow_) {
566                 crow_->setNumbered(numb);
567                 return true;
568         }
569         
570         return false;
571 }
572
573
574 bool MathedXIter::setLabel(string const & label)
575 {  
576         if (crow_) {
577                 crow_->setLabel(label);
578                 return true;
579         }
580         
581         return false;
582 }
583
584
585
586 string const & MathedXIter::getLabel() const
587 {
588         return crow_ ? crow_->getLabel() : error_label;
589 }
590
591