]> git.lyx.org Git - lyx.git/blob - src/mathed/math_parinset.C
remove cruft
[lyx.git] / src / mathed / math_parinset.C
1 #include <config.h>
2
3 #include "math_parinset.h"
4 #include "math_iter.h"
5 #include "array.h"
6 #include "math_xiter.h"
7 #include "LColor.h"
8 #include "mathed/support.h"
9 #include "Painter.h"
10 #include "math_parser.h"
11 #include "math_rowst.h"
12 #include "math_parinset.h"
13 #include "debug.h"
14
15 using std::endl;
16
17 extern int number_of_newlines;
18
19
20 MathedRowSt * MathParInset::getRowSt() const
21 {
22         return 0;
23 }
24
25
26 MathParInset::MathParInset(short st, string const & nm, short ot)
27         : MathedInset(nm, ot, st)
28 {
29         array = 0;
30         ascent = 8;
31         width = 4;
32         descent = 0;
33         flag = 1;
34         if (objtype == LM_OT_SCRIPT)
35                 flag |= LMPF_SCRIPT;
36 }
37
38
39 MathParInset::MathParInset(MathParInset * p)
40         : MathedInset(p)
41 {
42         flag = p->flag;
43         p->setArgumentIdx(0);
44         MathedIter it(p->GetData());
45         SetData(it.Copy());
46 }
47
48
49 MathParInset::~MathParInset()
50 {
51         if (array) {
52                 MathedIter it(array);
53                 it.Clear();
54                 delete array;
55         }
56 }
57
58
59 MathedInset * MathParInset::Clone()
60 {
61         return new MathParInset(this);
62 }
63
64
65 void MathParInset::SetData(MathedArray * a)
66 {
67         array = a;
68         
69         // A standard paragraph shouldn't have any tabs nor CRs.
70         if (array) {
71                 MathedIter it(array);
72                 while (it.OK()) {
73                         char c = it.GetChar();
74                         if (c == LM_TC_TAB || c == LM_TC_CR) 
75                                 it.Delete();
76                         else
77                                 it.Next();
78                 }
79         }
80 }
81
82
83 void 
84 MathParInset::draw(Painter & pain, int x, int y)
85 {
86         byte cxp = 0;
87         int xp = 0;
88         int asc = df_asc, des = 0;
89         bool limits = false;
90         
91         xo = x;  yo = y; 
92         if (!array || array->empty()) {
93                 if (array) {
94                         MathedXIter data(this);
95                         data.GetPos(x, y);
96                 }
97                 pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
98                 return;
99         }  
100         MathedXIter data(this);
101         data.GoBegin();
102         while (data.OK()) {
103                 data.GetPos(x, y);
104                 byte cx = data.GetChar();
105                 if (cx >= ' ') {
106                         string s = data.GetString();
107                         drawStr(pain, data.FCode(), size, x, y, s);
108                         mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
109                         limits = false;
110                 }
111                 else {
112                         if (cx == 0)
113                                 break;
114                         if (MathIsInset(cx)) {
115                                 int yy = y;
116                                 MathedInset * p = data.GetInset();
117                                 if (cx == LM_TC_UP) {
118                                         if (limits) {
119                                                 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;  
120                                                 yy -= (asc + p->Descent()+4);
121                                         }       
122                                         else
123                                                 yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
124                                 }
125                                 else if (cx == LM_TC_DOWN) {
126                                         if (limits) {
127                                                 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
128                                                 yy += des + p->Ascent() + 2;
129                                         } else
130                                                 yy += des + p->Ascent()/2;
131                                 }
132                                 else {
133                                         asc = p->Ascent();
134                                         des = p->Descent();
135                                 }
136                                 p->draw(pain, x, yy);
137                                 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
138                                         limits = p->GetLimits();
139                                         if (limits)
140                                                 xp = p->Width();
141                                 }
142                                 data.Next();
143                         }
144                         else if (cx == LM_TC_TAB) {
145                                 if (cxp == cx || cxp == LM_TC_CR || data.IsFirst()) {
146                                         pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
147                                 }
148                                 data.Next();
149                                 limits = false;
150                         }
151                         else if (cx == LM_TC_CR) {
152                                 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) {
153                                         pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
154                                 }
155                                 data.Next();
156                                 limits = false;
157                         }
158                         else {   
159                                 lyxerr << "GMathed Error: Unrecognized code[" << cx << "]" << endl;
160                                 break;
161                         }
162                 }
163                 cxp = cx;
164         }
165         if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { 
166                 data.GetPos(x, y);
167                 pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
168         }
169 }
170
171
172 void 
173 MathParInset::Metrics()
174 {
175         byte cx;
176         byte cxp = 0;
177         int ls;
178         int asc = df_asc;
179         int des = 0;
180         int tb = 0;
181         int tab = 0;
182         
183         bool limits = false;
184         
185         ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des); 
186         width = df_width;
187         descent = 0;
188         if (!array) return;
189         if (array->empty()) return;
190         
191         ascent = 0;
192         MathedXIter data(this);
193         data.GoBegin();
194         while (data.OK()) {
195                 cx = data.GetChar();      
196                 if (cx >= ' ') {
197                         string s = data.GetString();
198                         mathed_string_height(data.FCode(), size, s, asc, des);
199                         if (asc > ascent) ascent = asc;
200                         if (des > descent) descent = des;
201                         limits = false;
202                         mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
203                 } else
204                         if (MathIsInset(cx)) {
205                                 MathedInset * p = data.GetInset();
206                                 p->SetStyle(size);   
207                                 p->Metrics();
208                                 if (cx == LM_TC_UP) {
209                                         asc += (limits) ? p->Height() + 4: p->Ascent() + 
210                                                 ((p->Descent()>asc) ? p->Descent() - asc + 4: 0);
211                                 } else
212                                         if (cx == LM_TC_DOWN) {
213                                                 des += ((limits) ? p->Height() + 4: p->Height() - p->Ascent() / 2);
214                                         } else {
215                                                 asc = p->Ascent();
216                                                 des = p->Descent();
217                                         }
218                                 if (asc > ascent) ascent = asc;
219                                 if (des > descent) descent = des;
220                                 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
221                                         limits = p->GetLimits();
222                                 data.Next();
223                         } else 
224                                 if (cx == LM_TC_TAB) {
225                                         int x, y;
226                                         data.GetIncPos(x, y);
227                                         if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
228                                                 if (ascent<df_asc) ascent = df_asc;
229                                                 tb = x;
230                                         }
231                                         data.setTab(x-tb, tab);
232                                         tb = x;
233                                         ++tab;
234                                         limits = false;                   
235                                         data.Next();
236                                 } else
237                                         if (cx == LM_TC_CR) {
238                                                 if (tb > 0) {
239                                                         int x, y;
240                                                         data.GetIncPos(x, y);
241                                                         if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
242                                                                 if (ascent<df_asc) ascent = df_asc;
243                                                                 tb = x;
244                                                         } 
245                                                         data.setTab(x - tb, tab);
246                                                 } else //if (GetColumns() == 1) 
247                                                         {
248                                                                 int x, y;
249                                                                 data.GetIncPos(x, y);
250                                                                 data.setTab(x, tab);
251                                                                 if (ascent<df_asc) ascent = df_asc;
252                                                         } 
253                                                 tb = tab = 0;
254                                                 data.subMetrics(ascent, descent);
255                                                 ascent = df_asc;   
256                                                 descent = 0;
257                                                 data.Next();
258                                         } else {
259                                                 lyxerr << "Mathed Error: Unrecognized code[" << cx
260                                                        << "]" << endl;
261                                                 break;
262                                         }       
263                 cxp = cx;
264         }
265         data.GetIncPos(width, ls);
266         
267         // No matter how simple is a matrix, it is NOT a subparagraph
268         if (isMatrix()) {
269                 if (cxp == LM_TC_TAB) {
270                         if (ascent<df_asc) ascent = df_asc;
271                         data.setTab(0, tab);
272                 } else {
273                         data.setTab(width - tb, tab);
274                 }
275         }
276         
277         data.subMetrics(ascent, descent);
278 }
279
280
281
282 void MathParInset::Write(ostream & os, bool fragile)
283 {
284         if (!array) return;
285         int brace = 0;
286         latexkeys * l;
287         MathedIter data(array);
288         // hack
289         MathedRowSt const * crow = getRowSt();   
290         data.Reset();
291         
292         if (!Permit(LMPF_FIXED_SIZE)) { 
293                 l = lm_get_key_by_id(size, LM_TK_STY);
294                 if (l) {
295                         os << '\\' << l->name << ' ';
296                 }
297         }
298         while (data.OK()) {
299                 byte cx = data.GetChar();
300                 if (cx >= ' ') {
301                         string str = data.GetString();
302                         
303                         if (data.FCode() >= LM_TC_RM && data.FCode() <= LM_TC_TEXTRM) {
304                                 os << '\\' << math_font_name[data.FCode()-LM_TC_RM] << '{';
305                         }
306                         for (string::const_iterator s = str.begin();
307                              s != str.end(); ++s) {
308                                 byte c = *s;
309                                 if (MathIsSymbol(data.FCode())) {
310                                         l = lm_get_key_by_id(c, (data.FCode() == LM_TC_BSYM) ?
311                                                              LM_TK_BIGSYM : LM_TK_SYM);
312                                         if (l) {
313                                                 os << '\\' << l->name << ' ';
314                                         } else {
315 #warning this does not compile on gcc 2.97
316                                                 //lyxerr << "Illegal symbol code[" << c
317                                                 //   << " " << str.end() - s << " " << data.FCode() << "]";
318                                         }
319                                 } else {
320                                         // Is there a standard logical XOR?
321                                         if ((data.FCode() == LM_TC_TEX && c != '{' && c != '}') ||
322                                             (data.FCode() == LM_TC_SPECIAL))
323                                                 os << '\\';
324                                         else {
325                                                 if (c == '{') ++brace;
326                                                 if (c == '}') --brace;
327                                         }
328                                         if (c == '}' && data.FCode() == LM_TC_TEX && brace < 0) 
329                                                 lyxerr <<"Math warning: Unexpected closing brace."
330                                                        << endl;
331                                         else           
332                                                 os << char(c);
333                                 }
334                         }
335                         if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
336                                 os << '}';
337                 } else     
338                         if (MathIsInset(cx)) {
339                                 MathedInset * p = data.GetInset();
340                                 if (cx == LM_TC_UP)
341                                         os << "^{";
342                                 if (cx == LM_TC_DOWN)
343                                         os << "_{";
344                                 p->Write(os, fragile);
345                                 if (cx == LM_TC_UP || cx == LM_TC_DOWN)
346                                         os << '}';
347                                 data.Next();
348                         } else
349                                 switch (cx) {
350                                 case LM_TC_TAB:
351                                 {
352                                         os << " & ";
353                                         data.Next();
354                                         break;
355                                 }
356                                 case LM_TC_CR:
357                                 {
358                                         if (crow) {
359                                                 if (!crow->isNumbered()) {  
360                                                         os << "\\nonumber ";
361                                                 }
362                                                 if (!crow->getLabel().empty()) {
363                                                         os << "\\label{"
364                                                            << crow->getLabel()
365                                                            << "} ";
366                                                 }
367                                                 crow = crow->getNext();
368                                         }
369                                         if (fragile)
370                                                 os << "\\protect";
371                                         os << "\\\\\n";
372                                         ++number_of_newlines;
373                                         data.Next();
374                                         break;
375                                 }
376                                 default:
377                                         lyxerr << "WMath Error: unrecognized code[" << cx << "]";
378                                         return;
379                                 }     
380         }
381         
382         if (crow) {
383                 if (!crow->isNumbered()) {
384                         os << "\\nonumber ";
385                 }
386                 if (!crow->getLabel().empty()) {
387                         os << "\\label{"
388                            << crow->getLabel()
389                            << "} ";
390                 }
391         }
392
393         if (brace > 0)
394                 os << string(brace, '}');
395 }
396
397
398 bool MathParInset::Inside(int x, int y) 
399 {
400   return (x >= xo && x <= xo + width
401           && y <= yo + descent && y >= yo - ascent);
402 }
403
404
405 void MathParInset::GetXY(int & x, int & y) const
406 {
407    x = xo;
408    y = yo;
409 }
410
411
412 void MathParInset::UserSetSize(short sz)
413 {
414    if (sz >= 0) {
415        size = sz;      
416        flag = flag & ~LMPF_FIXED_SIZE;
417    }
418 }
419
420
421 void MathParInset::SetStyle(short sz) 
422 {
423     if (Permit(LMPF_FIXED_SIZE)) {
424         if (Permit(LMPF_SCRIPT)) 
425           sz = (sz < LM_ST_SCRIPT) ? LM_ST_SCRIPT: LM_ST_SCRIPTSCRIPT;
426         if (Permit(LMPF_SMALLER) && sz < LM_ST_SCRIPTSCRIPT) {
427             ++sz;
428         } 
429         MathedInset::SetStyle(sz);
430     }
431 }
432
433
434 void  MathParInset::setFlag(MathedParFlag f)
435 {
436         flag |= f;
437 }
438
439
440 bool MathParInset::Permit(short f) const
441 {
442         return bool(f & flag);
443 }
444
445
446 MathedArray * MathParInset::GetData()
447 {
448         return array;
449 }
450
451
452 void MathParInset::setXY(int x, int y)
453 {
454         xo = x;
455         yo = y;
456 }