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