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