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