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