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