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