]> git.lyx.org Git - lyx.git/blob - src/mathed/math_matrixinset.C
gcc 3.0 fixes
[lyx.git] / src / mathed / math_matrixinset.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include <vector>
8 #include <functional>
9
10 #include "math_matrixinset.h"
11 #include "debug.h"
12 #include "support/LOstream.h"
13 #include "Painter.h"
14 #include "LaTeXFeatures.h"
15
16
17 LyXFont WhichFont(short type, int size);
18
19 namespace {
20
21 string const getAlign(short int type, int cols)
22 {
23         string align;
24         switch (type) {
25                 case LM_OT_ALIGN:
26                         for (int i = 0; i < cols; ++i)
27                                 align += "Rl";
28                         break;
29
30                 case LM_OT_ALIGNAT:
31                         for (int i = 0; i < cols; ++i)
32                                 align += "rl";
33                         break;
34
35                 case LM_OT_MULTLINE:
36                         align = "C";
37                         break;
38
39                 default:
40                         align = "rcl";
41                         break;
42         }
43         return align;
44 }
45
46
47 string const star(bool n)
48 {
49         return n ? "" : "*";
50 }
51
52
53 int getCols(short int type)
54 {
55         int col;
56         switch (type) {
57                 case LM_OT_EQNARRAY:
58                         col = 3;
59                         break;
60
61                 case LM_OT_ALIGN:
62                 case LM_OT_ALIGNAT:
63                         col = 2;
64                         break;
65
66                 default:
67                         col = 1;
68         }
69         return col;
70 }
71
72 }
73
74 MathMatrixInset::MathMatrixInset(MathInsetTypes t)
75         : MathGridInset(getCols(t), 1, "formula", t), nonum_(1), label_(1)
76 {}
77
78
79 MathMatrixInset::MathMatrixInset()
80         : MathGridInset(1, 1, "formula", LM_OT_SIMPLE), nonum_(1), label_(1)
81 {}
82
83 MathInset * MathMatrixInset::Clone() const
84 {
85         return new MathMatrixInset(*this);
86 }
87
88
89 void MathMatrixInset::Metrics(MathStyles st)
90 {
91         size_ = st;
92         //LyXFont wfont = WhichFont(LM_TC_BF, size());
93         //wfont.setLatex(LyXFont::OFF);
94
95         // let the cells adjust themselves
96         MathGridInset::Metrics(st);
97
98         if (display()) {
99                 ascent_  += 12;
100                 descent_ += 12;
101         }       
102
103         if (numberedType()) {
104                 int l = 0;
105                 for (int row = 0; row < nrows(); ++row)
106                         l = std::max(l, mathed_string_width(LM_TC_TEXTRM, size(), nicelabel(row)));
107
108                 if (l)
109                         width_ += 30 + l;
110         }
111 }
112
113
114 void MathMatrixInset::draw(Painter & pain, int x, int y)
115 {
116         xo(x);
117         yo(y);
118
119         MathGridInset::draw(pain, x, y);
120
121         if (numberedType()) {
122                 LyXFont wfont = WhichFont(LM_TC_BF, size());
123 #ifndef NO_LATEX
124                 wfont.setLatex(LyXFont::OFF);
125 #endif
126                 int xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
127                 for (int row = 0; row < nrows(); ++row) 
128                         pain.text(xx, y + rowinfo_[row].offset_, nicelabel(row), wfont);
129         }
130 }
131
132
133 void MathMatrixInset::Write(std::ostream & os, bool fragile) const
134 {
135   header_write(os);
136
137         bool n = numberedType();
138
139         for (int row = 0; row < nrows(); ++row) {
140                 if (row)
141                         os << " \\\\\n";
142                 for (int col = 0; col < ncols(); ++col) {
143                         if (col)
144                                 os << " & ";
145                         cell(index(row, col)).Write(os, fragile);
146                 }
147                 if (n) {
148                         if (!label_[row].empty())
149                                 os << "\\label{" << label_[row] << "}";
150                         if (nonum_[row])
151                                 os << "\\nonumber ";
152                 }
153         }
154
155   footer_write(os);
156 }
157
158
159 string MathMatrixInset::label(int row) const
160 {
161         return label_[row];
162 }
163
164 void MathMatrixInset::label(int row, string const & label)
165 {
166         label_[row] = label; 
167 }
168
169
170 void MathMatrixInset::numbered(int row, bool num)
171 {
172         nonum_[row] = !num; 
173 }
174
175
176 bool MathMatrixInset::numbered(int row) const
177 {
178         return !nonum_[row];
179 }
180
181
182 bool MathMatrixInset::ams() const
183 {
184         return true;
185 }
186
187
188 bool MathMatrixInset::display() const
189 {
190         return GetType() != LM_OT_SIMPLE;
191 }
192
193
194 std::vector<string> const MathMatrixInset::getLabelList() const
195 {
196         std::vector<string> res;
197         for (int row = 0; row < nrows(); ++row)
198                 if (!label_[row].empty() && nonum_[row] != 1)
199                         res.push_back(label_[row]);
200         return res;
201 }
202
203
204 bool MathMatrixInset::numberedType() const
205 {
206         if (GetType() == LM_OT_SIMPLE)
207                 return false;
208         for (int row = 0; row < nrows(); ++row)
209                 if (!nonum_[row])
210                         return true;
211         return false;
212 }
213
214
215 void MathMatrixInset::Validate(LaTeXFeatures & features)
216 {
217         features.amsstyle = ams();
218
219         // Validation is necessary only if not using AMS math.
220         // To be safe, we will always run mathedValidate.
221         //if (features.amsstyle)
222         //  return;
223
224         //Validate1(features);
225
226         features.boldsymbol = true;
227         features.binom      = true;
228 }
229
230 /*
231 void MathMatrixInset::Validate1(LaTeXFeatures & features)
232 {
233         MathIter it(cell());
234
235         while (it.OK() && !(features.binom && features.boldsymbol)) {
236                 MathInset * p = it.GetInset();
237                 if (p) {
238                         p = it.GetActiveInset();
239                         if (p) {
240                                 if (!features.binom && p->GetType() == LM_OT_MACRO &&
241                                     p->name() == "binom") {
242                                         features.binom = true;
243                                 } else {
244                                         for (int i = 0; i <= p->getMaxArgumentIdx(); ++i) {
245                                                 p->setArgumentIdx(i);
246                                                 Validate1(features, p);
247                                         }
248                                 }
249                         } else {
250                                 if (!features.boldsymbol && p->name() == "boldsymbol") 
251                                         features.boldsymbol = true;
252                         }
253                 }
254                 it.Next();
255         }
256 }
257 */
258
259
260 void MathMatrixInset::header_write(std::ostream & os) const
261 {
262         bool n = numberedType();
263
264         switch (GetType()) {
265                 case LM_OT_SIMPLE:
266                         os << "\\("; 
267                         break;
268
269                 case LM_OT_EQUATION:
270                         if (n)
271                                 os << "\\begin{equation" << star(n) << "}\n"; 
272                         else
273                                 os << "\\[\n"; 
274                         break;
275
276                 case LM_OT_EQNARRAY:
277                         os << "\\begin{eqnarray" << star(n) << "}\n";
278                         break;
279
280                 case LM_OT_ALIGN:
281                         os << "\\begin{align" << star(n) << "}";
282                         break;
283
284                 case LM_OT_ALIGNAT:
285                         os << "\\begin{alignat" << star(n) << "}"
286                            << "{" << ncols()/2 << "}\n";
287                         break;
288         }
289 }
290
291
292 void MathMatrixInset::footer_write(std::ostream & os) const
293 {
294         bool n = numberedType();
295
296         switch (GetType()) {
297                 case LM_OT_SIMPLE:
298                         os << "\\)";
299                         break;
300
301                 case LM_OT_EQUATION:
302                         if (n)
303                                 os << "\\end{equation" << star(n) << "}\n"; 
304                         else
305                                 os << "\\]\n"; 
306                         break;
307
308                 case LM_OT_EQNARRAY:
309                         os << "\\end{eqnarray" << star(n) << "}\n";
310                         break;
311
312                 case LM_OT_ALIGN:
313                         os << "\\end{align" << star(n) << "}\n";
314                         break;
315
316                 case LM_OT_ALIGNAT:
317                         os << "\\end{alignat" << star(n) << "}\n";
318                         break;
319         }
320 }
321
322
323 void MathMatrixInset::addRow(int row) 
324 {
325         nonum_.insert(nonum_.begin() + row + 1, !numberedType());
326         label_.insert(label_.begin() + row + 1, string());
327         MathGridInset::addRow(row);
328 }
329
330 void MathMatrixInset::appendRow()
331 {
332         nonum_.push_back(!numberedType());
333         label_.push_back(string());
334         MathGridInset::appendRow();
335 }
336
337
338 void MathMatrixInset::delRow(int row) 
339 {
340         MathGridInset::delRow(row);
341         nonum_.erase(nonum_.begin() + row);
342         label_.erase(label_.begin() + row);
343 }
344
345 void MathMatrixInset::addCol(int col)
346 {
347         switch (GetType()) {
348                 case LM_OT_EQUATION:
349                         mutate(LM_OT_EQNARRAY);
350                         break;
351
352                 case LM_OT_EQNARRAY:
353                         mutate(LM_OT_ALIGN);
354                         addCol(col);
355                         break;
356
357                 case LM_OT_ALIGN:
358                 case LM_OT_ALIGNAT:
359                         MathGridInset::addCol(col);
360                         halign(col, 'l');
361                         MathGridInset::addCol(col);
362                         halign(col, 'r');
363                         break;
364
365                 default:
366                         break;
367         }
368 }
369
370 void MathMatrixInset::delCol(int col)
371 {
372         switch (GetType()) {
373                 case LM_OT_ALIGN:
374                         MathGridInset::delCol(col);
375                         break;
376
377                 default:
378                         break;
379         }
380 }
381
382 void MathMatrixInset::breakLine() 
383 {
384         if (GetType() == LM_OT_SIMPLE || GetType() == LM_OT_EQUATION) 
385                 mutate(LM_OT_EQNARRAY);
386         addRow(nrows() - 1);
387 }
388
389
390 void MathMatrixInset::splitCell(int idx)
391 {
392         if (idx == nargs() - 1) {
393                 lyxerr << "can't split last cell\n";
394                 return;
395         }
396
397         lyxerr << "unimplemented\n";
398 }
399
400
401 string MathMatrixInset::nicelabel(int row) const
402 {
403         if (nonum_[row])
404                 return string();
405         if (label_[row].empty())
406                 return string("(#)");
407         return "(" + label_[row] + ")";
408 }
409
410
411 namespace {
412         short typecode(string const & s)
413         {
414                 if (s == "equation")
415                         return LM_OT_EQUATION;
416                 if (s == "display")
417                         return LM_OT_EQUATION;
418                 if (s == "eqnarray")
419                         return LM_OT_EQNARRAY;
420                 if (s == "align")
421                         return LM_OT_ALIGN;
422                 if (s == "xalign")
423                         return LM_OT_XALIGN;
424                 if (s == "xxalign")
425                         return LM_OT_XXALIGN;
426                 if (s == "multline")
427                         return LM_OT_MULTLINE;
428                 return LM_OT_SIMPLE;
429         }       
430 }
431
432 void MathMatrixInset::mutate(string const & newtype)
433 {
434         if (newtype == "dump") {
435                 dump();
436                 return;
437         }
438         //lyxerr << "mutating from '" << GetType() << "' to '" << newtype << "'\n";
439         mutate(typecode(newtype));
440 }
441
442 void MathMatrixInset::glueall()
443 {
444         MathArray ar;
445         for (int i = 0; i < nargs(); ++i)
446                 ar.push_back(cell(i));
447         *this = MathMatrixInset(LM_OT_SIMPLE);
448         cell(0) = ar;
449 }
450
451 void MathMatrixInset::mutate(short newtype)
452 {
453         //lyxerr << "mutating from '" << GetType() << "' to '" << newtype << "'\n";
454
455         if (newtype == GetType())
456                 return;
457
458         switch (GetType()) {
459                 case LM_OT_SIMPLE:
460                         SetType(LM_OT_EQUATION);
461                         numbered(false);
462                         mutate(newtype);
463                         break;
464
465                 case LM_OT_EQUATION:
466                         switch (newtype) {
467                                 case LM_OT_SIMPLE:
468                                         SetType(LM_OT_SIMPLE);
469                                         break;
470
471                                 case LM_OT_ALIGN:
472                                         MathGridInset::addCol(1);
473                                         halign("rl");
474                                         SetType(LM_OT_ALIGN);
475                                         break;
476
477                                 default:
478                                         MathGridInset::addCol(1);
479                                         MathGridInset::addCol(1);
480                                         halign("rcl");
481                                         SetType(LM_OT_EQNARRAY);
482                                         mutate(newtype);
483                                         break;
484                                 }
485                         break;
486
487                 case LM_OT_EQNARRAY:
488                         switch (newtype) {
489                                 case LM_OT_SIMPLE:
490                                         glueall();
491                                         break;
492
493                                 case LM_OT_EQUATION:
494                                         if (nrows() == 1) {
495                                                 MathGridInset::delCol(2);
496                                                 MathGridInset::delCol(1);
497                                                 SetType(LM_OT_EQUATION);
498                                                 mutate(newtype);
499                                         } else 
500                                                 lyxerr << "need to delete rows first\n";
501                                         break;
502
503                                 case LM_OT_ALIGN:
504                                 default:
505                                         for (int row = 0; row < nrows(); ++row) {
506                                                 int c = 3 * row + 1;
507                                                 cell(c).push_back(cell(c + 1));
508                                         }
509                                         MathGridInset::delCol(2);
510                                         SetType(LM_OT_ALIGN);
511                                         halign("rl");
512                                         mutate(newtype);
513                                         break;
514                         }
515                         break;
516
517                 case LM_OT_ALIGN:
518                         switch (newtype) {
519                                 case LM_OT_SIMPLE:
520                                 case LM_OT_EQUATION:
521                                 case LM_OT_EQNARRAY:
522                                         MathGridInset::addCol(1);
523                                         SetType(LM_OT_EQNARRAY);
524                                         halign("lrl");
525                                         mutate(newtype);
526                                         break;
527                                 
528                                 default:
529                                         lyxerr << "mutation from '" << GetType()
530                                                 << "' to '" << newtype << "' not implemented\n";
531                                         break;
532                         }
533                         break;
534
535                 default:
536                         lyxerr << "mutation from '" << GetType()
537                                 << "' to '" << newtype << "' not implemented\n";
538         }
539 }