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