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