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