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