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