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