]> git.lyx.org Git - lyx.git/blob - src/mathed/math_xiter.C
some inline fix + mathed16.diff
[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
9
10 MathedXIter::MathedXIter()
11         : MathedIter(), sx(0), sw(0)
12 {
13         x = y = size = 0;
14         p = 0;
15         crow = 0;
16 }
17
18
19 MathParInset * MathedXIter::getPar() const
20 {
21         return p;
22 }
23
24
25 void MathedXIter::GetPos(int & xx, int & yy) const
26
27         if (p) 
28                 p->GetXY(xx, yy);
29         else {
30                 xx = 0;
31                 yy = 0;
32         }        
33         xx += x;
34         yy += y;
35 }
36
37
38 int MathedXIter::GetX() const
39
40         int xx;
41         int dummy_y;
42         GetPos(xx, dummy_y);
43         return xx; 
44 }
45
46
47 int MathedXIter::GetY() const
48
49         int dummy_x;
50         int yy;
51         GetPos(dummy_x, yy);
52         return yy; 
53 }
54
55
56 void MathedXIter::GetIncPos(int & xx, int & yy) const
57
58         xx = x;
59         yy = y; 
60 }
61
62
63 void MathedXIter::getAD(int & a, int & d) const
64
65         if (crow) {
66                 a = crow->ascent();
67                 d = crow->descent();
68         } else 
69                 if (p) {
70                         a = p->Ascent();
71                         d = p->Descent();
72                 } else {
73                         a = d = 0;
74                 }
75 }
76
77
78
79 void MathedXIter::Clean(int pos2)
80 {
81         if (!array) {
82                 lyxerr << "Math error: Attempting to clean a void array." << endl;
83                 return;
84         } 
85         
86         int pos1 = pos;
87         
88         if (pos2 < pos1) {
89                 GoBegin();
90                 while (pos < pos2 && OK()) {
91                         Next();
92                 }
93                 pos2 = pos1;
94                 pos1 = pos;
95         }
96         
97         ipush();
98         while (OK() && pos < pos2) {
99                 if (IsInset()) {
100                         MathedInset * inset = GetInset();
101                         Next();
102                         if (inset->GetType()!= LM_OT_MACRO_ARG)
103                                 delete inset;
104                         continue;
105                 } 
106                 if (IsCR()) {
107                         if (crow) {
108                                 MathedRowSt * r = crow->getNext();
109                                 if (r) {
110                                         crow->setNext(r->getNext());
111                                         delete r;
112                                 }          
113                         }
114                 }
115                 Next();
116         }    
117         ipop();
118         
119         if (pos2 <= array->last()) {
120                 pos = pos1;
121                 join(pos2);
122                 checkTabs();
123         } 
124 }
125
126
127 void MathedXIter::Merge(MathedArray * a0)
128 {
129         if (!a0) {
130                 lyxerr[Debug::MATHED]
131                         << "Math error: Attempting to merge a void array." << endl;
132                 
133                 return;
134         }
135         // All insets must be clonned
136         MathedIter it(a0);
137         MathedArray * a = it.Copy();
138         
139         // make room for the data 
140         split(a->last());
141         array->mergeF(a, pos, a->last());
142         
143         int pos1 = pos;
144         int pos2 = pos + a->last();
145         
146         goPosAbs(pos1);
147         
148         // Complete rows
149         while (pos < pos2 && OK()) {
150                 if (IsCR()) {
151                         if (p && p->Permit(LMPF_ALLOW_CR)) {
152                                 MathedRowSt * r = new MathedRowSt(ncols+1);
153                                 if (crow) {
154                                         r->setNext(crow->getNext());
155                                         crow->setNext(r);
156                                 } else {
157                                         r->setNext(0);
158                                 }
159                                 crow = r;
160                         } else {
161                                 Delete();
162                                 --pos2;
163                         }
164                 }
165                 Next();    
166         }
167         pos2 = getPos();
168         goPosAbs(pos1);
169         checkTabs();
170         goPosAbs(pos2);
171         
172         delete a;
173 }
174
175
176
177
178 MathedXIter::MathedXIter(MathParInset * pp)
179         : p(pp) 
180
181         x = y = 0;
182         sx = sw = 0;   
183         limits = false;
184         s_type = 0;  
185         if (p) 
186                 SetData(p);
187         else {
188                 crow = 0;
189                 size = 0;
190         }
191 }
192
193
194 void MathedXIter::SetData(MathParInset * pp)
195 {
196         p = pp;
197         x = y = 0;
198         array = p->GetData();
199         ncols = p->GetColumns();
200         crow = p->getRowSt();
201         if (p->Permit(LMPF_ALLOW_CR))
202                 flags |= MthIF_CR;
203         if (p->Permit(LMPF_ALLOW_TAB))
204                 flags |= MthIF_Tabs;
205         
206         if (crow) {
207                 x = crow->getTab(0);
208                 y = crow->getBaseline();
209         } 
210         if (!array) {
211                 array = new MathedArray; // this leaks
212                 p->SetData(array);
213         }
214         size = p->GetStyle();
215         Reset();
216 }
217
218
219 string const MathedXIter::GetString() const
220 {
221         string s = MathedIter::GetString();
222         x += mathed_string_width(fcode, size, s);
223         return s;
224 }
225
226
227 bool MathedXIter::Next()
228 {  
229 //    lyxerr << "Ne[" << pos << "]";
230         if (!OK()) return false;
231         int w = 0;
232 //   lyxerr << "xt ";
233         if (IsInset()) {
234                 MathedInset * px = GetInset();
235                 w = px->Width();
236                 if (px->GetType() == LM_OT_SCRIPT) {
237                         if (w > sw) sw = w;
238                         w = 0;
239                 } else
240                         sx = (px->GetLimits()) ? w : 0;
241         } else {  
242                 byte c = GetChar();
243                 if (c >= ' ') {
244 //        lyxerr << "WD[" << fcode << " " << size << " " << c << endl;
245                         w = mathed_char_width(fcode, size, c);
246                 } else
247                         if (c == LM_TC_TAB && p) {
248 //       w = p->GetTab(col + 1);
249                                 w = (crow) ? crow->getTab(col + 1) : 0;
250                                 //lyxerr << "WW[" << w << "]";
251                         } else
252                                 if (c == LM_TC_CR && p) {
253                                         x = 0;
254                                         if (crow && crow->getNext()) {
255                                                 crow = crow->getNext();
256                                                 y = crow->getBaseline();
257                                                 w = crow->getTab(0);
258                                         }
259 //        lyxerr << "WW[" << col " " << row << "|" << w << "]";
260                                 } else 
261                                         lyxerr << "No hubo w[" << c << "]!";
262         }
263         if (MathedIter::Next()) {
264 //       lyxerr <<"LNX " << pos << endl;
265 //       if (sw>0 && GetChar()!= LM_TC_UP && GetChar()!= LM_TC_DOWN) {
266 //         w = (sx>sw) ? 0: sw-sx;
267                 if ((sw > 0 || sx > 0)
268                     && GetChar() != LM_TC_UP && GetChar() != LM_TC_DOWN) {
269                         if (sw > 0)
270                                 w = (sx > sw) ? 0 : sw - sx;
271                         sx = sw = 0;
272                 }
273                 x += w;
274                 return true;
275         } else
276                 return false;
277 }
278
279
280 void MathedXIter::GoBegin()
281 {
282         Reset();
283         x = y = 0;   
284         sw = sx = 0;
285         if (p) {
286                 crow = p->getRowSt();
287                 if (crow) {
288                         x = crow->getTab(0);
289                         y = crow->getBaseline();
290                 }
291         }
292 }
293
294
295 void MathedXIter::GoLast()
296 {
297         while (Next());
298 }
299
300
301 void MathedXIter::Adjust()
302 {
303         int posx = pos;
304         GoBegin();
305         while (posx > pos && OK()) Next();  
306 }
307
308
309 bool MathedXIter::Prev()
310 {  
311         if (pos == 0 || (pos == 1 && GetChar() >= ' '))
312                 return false;
313         
314         int pos2 = pos; // pos1
315         GoBegin();
316         do {
317                 ipush();
318                 Next();
319         } while (pos<pos2);
320         ipop();
321         
322         return (!IsCR());
323 }
324
325
326 bool MathedXIter::goNextColumn()
327 {  
328         int rowp = row;
329         int colp = col;
330         while (Next() && col == colp);
331         
332         return (col != colp + 1 || rowp != row);
333 }
334
335
336 bool MathedXIter::Up()
337 {
338         if (row == 0) return false;
339         int xp = x;
340         int rowp = row;
341         int colp = col;
342         GoBegin();
343         while (row < rowp - 1) Next();
344         while (x < xp && OK() && !IsCR()) {
345                 ipush();
346                 Next();
347         }
348         if (col > colp) // || (stck.col == colp && stck.x<= xp && x>xp))
349                 ipop();
350         
351         return true;
352 }
353
354
355 bool MathedXIter::Down()
356 {
357         int xp = x;
358         int colp= col;
359         // int rowp = row
360         
361         bool res = (IsCR()) ? true : goNextCode(LM_TC_CR);
362         if (res) {
363                 Next();
364                 ipush();
365                 while (x < xp && OK()) {
366                         ipush();
367                         Next();
368                 }
369                 if (col > colp || (stck.col == colp && stck.x <= xp && x > xp))
370                         ipop();
371                 return true;
372         }
373         return false;
374 }
375
376
377
378 void MathedXIter::addRow()
379 {
380         if (!crow) {
381                 lyxerr[Debug::MATHED] << "MathErr: Attempt to insert new"
382                         " line in a subparagraph. " << this << endl;
383                 
384                 return;
385         }
386         // Create new item for the structure    
387         MathedRowSt * r = new MathedRowSt(ncols + 1);
388         if (crow) {
389                 r->setNext(crow->getNext());
390                 crow->setNext(r);
391         } else {
392                 crow = r;
393                 r->setNext(0);
394         }    
395         // Fill missed tabs in current row
396         while (col < ncols - 1) 
397                 Insert('T', LM_TC_TAB); 
398         //newline
399         Insert('K', LM_TC_CR);
400         
401         ipush();
402         if (!IsCR())
403                 goNextCode(LM_TC_CR);
404         
405         // Fill missed tabs in new row
406         while (col < ncols - 1) 
407                 Insert('T', LM_TC_TAB);
408         ipop();
409 }
410
411
412 void MathedXIter::delRow()
413 {
414         if (!crow) {
415                 lyxerr[Debug::MATHED] << "MathErr: Attempt to delete a line in a subparagraph." << endl;
416                 return;
417         }
418         bool line_empty = true;
419         ipush();
420 //    while (Next()) {
421         do {
422                 if (IsCR()) {
423                         break;
424                 } else if (!IsTab()) {
425                         line_empty = false;
426                 }
427         } while (Next());
428         int const p1 = getPos();
429         ipop();
430         
431         if (line_empty) {
432                 
433                 MathedRowSt * r = crow->getNext();
434                 if (r) {
435                         crow->setNext(r->getNext());
436                         delete r;
437                 }
438                 join(p1);
439                 Delete();
440         } else
441                 Clean(p1);
442         
443         checkTabs();    
444 }
445
446
447 void MathedXIter::ipush()
448
449         MathedIter::ipush();
450         stck.x = x;
451         stck.y = y;
452 }
453
454
455 void MathedXIter::ipop()
456
457         MathedIter::ipop();
458         x = stck.x;
459         y = stck.y;
460         if (p) {
461                 crow = p->getRowSt();
462                 if (crow)
463                         for (int i = 0; i < row; ++i)
464                                 crow = crow->getNext();
465         }
466 }
467
468
469 void MathedXIter::fitCoord(int /*xx*/, int yy)
470 {
471         int xo = 0;
472         int yo = 0;
473         
474         GoBegin();
475         if (p)
476                 p->GetXY(xo, yo);
477         // first fit vertically
478         while (crow && OK()) {
479                 if (yy >= yo + y - crow->ascent() && yy <= yo + y + crow->descent()) 
480                         break;
481                 goNextCode(LM_TC_CR);
482                 Next();
483         }
484         // now horizontally
485 //    while (x<xx && Next());
486 }
487
488
489 void MathedXIter::setTab(int tx, int tab)
490 {
491         if (crow && tab <= ncols) {
492                 crow->setTab(tab, tx);
493         } else
494                 lyxerr << "MathErr: No tabs allowed here" << endl;
495 }
496
497
498 void MathedXIter::subMetrics(int a, int d)
499 {
500         if (!crow) {
501                 lyxerr[Debug::MATHED]
502                         << "MathErr: Attempt to submetric a subparagraph." << endl;
503                 return;
504         }
505         crow->ascent(a);
506         crow->descent(d);
507 }
508
509
510 // This function is not recursive, as MathPar::Metrics is
511 void MathedXIter::IMetrics(int pos2, int & width, int & ascent, int & descent)
512 {  
513         byte cx;
514         int x1; // ls;
515         int asc = 0;
516         int des = 0;
517         bool limit = false;
518         
519         descent = ascent = width = 0;
520         if (!array) return;
521         if (array->empty()) return;
522 //    if  (pos2 > array->last) return;
523         x1 = x; 
524         while (pos < pos2) {
525                 cx = GetChar();
526                 if (cx >= ' ') {
527                         mathed_char_height(FCode(), size, cx, asc, des);
528                         if (asc > ascent) ascent = asc;
529                         if (des > descent) descent = des;
530                         limit = false;
531                 } else
532                         if (MathIsInset(cx)) {
533                                 MathedInset * pp = GetInset();
534                                 if (cx == LM_TC_UP) {
535                                         if (!asc && p) {
536                                                 int xx;
537                                                 int yy;
538                                                 p->GetXY(xx, yy);
539                                                 static_cast<MathParInset*>(pp)->GetXY(xx, asc);
540                                                 asc = yy - asc;
541                                         }
542                                         asc += ((limits) ? pp->Height() + 4 : pp->Ascent());
543                                 } else if (cx == LM_TC_DOWN) {
544                                         if (!des && p) {
545                                                 int xx;
546                                                 int yy;
547                                                 p->GetXY(xx, yy);
548                                                 static_cast<MathParInset*>(pp)->GetXY(xx, des);
549                                                 if (des - pp->Height() < yy && !asc)
550                                                         asc = yy - (des - pp->Height());
551                                                 des -= yy;
552                                         }
553                                         des += (limit ? pp->Height()+4: pp->Height()-pp->Ascent()/2);
554                                 } else {
555                                         asc = pp->Ascent();
556                                         des = pp->Descent();
557                                 }
558                                 if (asc > ascent) ascent = asc;
559                                 if (des > descent) descent = des;
560                                 if (cx != LM_TC_UP && cx != LM_TC_DOWN)
561                                         limit = pp->GetLimits();
562                         } else if (cx == LM_TC_TAB) {
563                                 limit = false;                   
564                         } else {
565                                 lyxerr[Debug::MATHED]
566                                         << "Mathed Sel-Error: Unrecognized code["
567                                         << cx << ']' << endl;
568                                 break;
569                         }
570                 if (pos < pos2)  Next();
571         }
572         width = x - x1;
573 }
574
575
576 bool MathedXIter::setNumbered(bool numb)
577 {  
578         if (crow) {
579                 crow->setNumbered(numb);
580                 return true;
581         }
582         
583         return false;
584 }
585
586
587 bool MathedXIter::setLabel(string const & label)
588 {  
589         if (crow) {
590                 crow->setLabel(label);
591                 return true;
592         }
593         
594         return false;
595 }
596
597
598 MathedRowSt * MathedXIter::adjustVerticalSt()
599 {
600         GoBegin();
601         if (!crow) {
602 //      lyxerr << " CRW" << ncols << " ";
603                 crow = new MathedRowSt(ncols + 1); // this leaks
604         }
605 //    lyxerr<< " CRW[" << crow << "] ";
606         MathedRowSt * mrow = crow;
607         while (OK()) {
608                 if (IsCR()) {
609                         if (col >= ncols) ncols = col + 1; 
610                         MathedRowSt * r = new MathedRowSt(ncols + 1); // this leaks
611 //          r->next = crow->next;
612                         crow->setNext(r);
613                         crow = r;
614 //          lyxerr << " CX[" << crow << "]";
615                 }   
616                 Next(); 
617         }
618         return mrow;
619 }
620
621
622 string const &  MathedXIter::getLabel() const
623 {
624         return crow ? crow->getLabel() : error_label;
625 }
626
627
628 string MathedXIter::error_label = "$mathed-error$";