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