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