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