]> git.lyx.org Git - lyx.git/blob - src/mathed/math_matrixinset.C
mathed29.diff
[lyx.git] / src / mathed / math_matrixinset.C
1 #include <config.h>
2
3 #include "math_matrixinset.h"
4 #include "math_rowst.h"
5 #include "math_xiter.h"
6 #include "support/LOstream.h"
7
8 using std::ostream;
9
10 extern int number_of_newlines;
11
12 MathMatrixInset::MathMatrixInset(int m, int n, short st)
13         : MathParInset(st, "array", LM_OT_MATRIX), nc_(m), nr_(0), ws_(m),
14           v_align_(0), h_align_(nc_, 'c'), row_(0)
15 {
16         flag = 15;
17         if (n > 0) {
18                 row_ = new MathedRowSt(nc_ + 1);
19                 MathedXIter it(this);
20                 for (int j = 1; j < n; ++j) it.addRow();
21                 nr_ = n;
22                 if (nr_ == 1 && nc_ > 1) {
23                         for (int j = 0; j < nc_ - 1; ++j) 
24                                 it.insert('T', LM_TC_TAB);
25                 }
26         } else if (n < 0) {
27                 row_ = new MathedRowSt(nc_ + 1);
28                 nr_ = 1;
29         }
30 }
31
32
33 MathMatrixInset::MathMatrixInset(MathMatrixInset * mt)
34         : MathParInset(mt->GetStyle(), mt->GetName(), mt->GetType()),
35           nc_(mt->nc_), nr_(0), ws_(mt->nc_),
36           v_align_(mt->v_align_), h_align_(mt->h_align_)
37 {
38         MathedIter it(mt->GetData());
39         array = it.Copy();
40         if (mt->row_ != 0) {
41                 MathedRowSt * ro = 0;
42                 MathedRowSt * mrow = mt->row_;
43
44                 while (mrow) {
45                         MathedRowSt * r = new MathedRowSt(nc_ + 1);
46                         r->setNumbered(mrow->isNumbered());
47                         //if (mrow->label) 
48                         r->setLabel(mrow->getLabel());
49                         if (!ro) 
50                                 row_ = r;
51                         else
52                                 ro->setNext(r);
53                         mrow = mrow->getNext();
54                         ro = r;
55                         ++nr_;
56                 }
57         } else   
58                 row_ = 0;
59         flag = mt->flag;
60 }
61
62
63 MathMatrixInset::~MathMatrixInset()
64 {
65         MathedRowSt * r = row_;
66         while (r) {
67                 MathedRowSt * q = r->getNext();
68                 delete r;
69                 r = q;
70         }
71 }
72
73
74 MathedInset * MathMatrixInset::Clone()
75 {
76         return new MathMatrixInset(this);
77 }
78
79
80 void MathMatrixInset::SetAlign(char vv, string const & hh)
81 {
82         v_align_ = vv;
83         h_align_ = hh.substr(0, nc_); // usr just h_align = hh; perhaps
84 }
85
86
87 // Check the number of tabs and crs
88 void MathMatrixInset::setData(MathedArray * a)
89 {
90         if (!a) return;
91         MathedIter it(a);
92         int nn = nc_ - 1;
93         nr_ = 1;
94         // count tabs per row
95         while (it.OK()) {
96                 if (it.IsTab()) {
97                         if (nn < 0) { 
98                                 it.Delete();
99                                 continue;
100                         } else {
101                                 // it.Next();
102                                 --nn;
103                         }
104                 }
105                 if (it.IsCR()) {
106                         while (nn > 0) {
107                                 it.insert(' ', LM_TC_TAB);
108                                 --nn;
109                         }
110                         nn = nc_ - 1;
111                         ++nr_;
112                 }
113                 it.Next();
114         }
115         it.Reset();
116         
117         // Automatically inserts tabs around bops
118         // DISABLED because it's very easy to insert tabs 
119         array = a;
120 }
121
122
123 void MathMatrixInset::draw(Painter & pain, int x, int baseline)
124 {
125         MathParInset::draw(pain, x, baseline);
126 }
127
128
129
130 void MathMatrixInset::Metrics()
131 {
132         if (!row_) {
133                 // lyxerr << " MIDA ";
134                 MathedXIter it(this);
135                 row_ = it.adjustVerticalSt();
136         } 
137         
138         // Clean the arrays      
139         MathedRowSt * cxrow = row_;
140         while (cxrow) {   
141                 for (int i = 0; i <= nc_; ++i)
142                         cxrow->setTab(i, 0);
143                 cxrow = cxrow->getNext();
144         }
145         
146         // Basic metrics
147         MathParInset::Metrics();
148         
149         if (nc_ <= 1 && !row_->getNext()) {
150                 row_->ascent(ascent);
151                 row_->descent(descent);
152         }
153         
154         // Vertical positions of each row
155         cxrow = row_;     
156         MathedRowSt * cprow = 0;
157         int h = 0;
158         while (cxrow) {
159                 for (int i = 0; i < nc_; ++i) {
160                         if (cxrow == row_ || ws_[i] < cxrow->getTab(i))
161                                 ws_[i] = cxrow->getTab(i);
162                         if (cxrow->getNext() == 0 && ws_[i] == 0)
163                                 ws_[i] = df_width;
164                 }
165                 
166                 cxrow->setBaseline((cxrow == row_) ?
167                                    cxrow->ascent() :
168                                    cxrow->ascent() + cprow->descent()
169                                    + MATH_ROWSEP + cprow->getBaseline());
170                 h += cxrow->ascent() + cxrow->descent() + MATH_ROWSEP;  
171                 cprow = cxrow;
172                 cxrow = cxrow->getNext();
173         }
174         
175         int hl = Descent();
176         h -= MATH_ROWSEP;
177         
178         //  Compute vertical align
179         switch (v_align_) {
180         case 't':
181                 ascent = row_->getBaseline();
182                 break;
183         case 'b':
184                 ascent = h - hl;
185                 break;
186         default:
187                 ascent = (row_->getNext()) ? h / 2 : h - hl;
188                 break;
189         }
190         descent = h - ascent + 2;
191         
192         // Increase ws_[i] for 'R' columns (except the first one)
193         for (int i = 1; i < nc_; ++i)
194                 if (h_align_[i] == 'R')
195                         ws_[i] += 10 * df_width;
196         // Increase ws_[i] for 'C' column
197         if (h_align_[0] == 'C')
198                 if (ws_[0] < 7 * workWidth / 8)
199                         ws_[0] = 7 * workWidth / 8;
200         
201         // Adjust local tabs
202         cxrow = row_;
203         width = MATH_COLSEP;
204         while (cxrow) {   
205                 int rg = MATH_COLSEP;
206                 int lf = 0;
207                 for (int i = 0; i < nc_; ++i) {
208                         bool isvoid = false;
209                         if (cxrow->getTab(i) <= 0) {
210                                 cxrow->setTab(i, df_width);
211                                 isvoid = true;
212                         }
213                         switch (h_align_[i]) {
214                         case 'l':
215                                 lf = 0;
216                                 break;
217                         case 'c':
218                                 lf = (ws_[i] - cxrow->getTab(i))/2; 
219                                 break;
220                         case 'r':
221                         case 'R':
222                                 lf = ws_[i] - cxrow->getTab(i);
223                                 break;
224                         case 'C':
225                                 if (cxrow == row_)
226                                         lf = 0;
227                                 else if (!cxrow->getNext())
228                                         lf = ws_[i] - cxrow->getTab(i);
229                                 else
230                                         lf = (ws_[i] - cxrow->getTab(i))/2; 
231                                 break;
232                         }
233                         int ww = (isvoid) ? lf : lf + cxrow->getTab(i);
234                         cxrow->setTab(i, lf + rg);
235                         rg = ws_[i] - ww + MATH_COLSEP;
236                         if (cxrow == row_)
237                                 width += ws_[i] + MATH_COLSEP;
238                 }
239                 cxrow->setBaseline(cxrow->getBaseline() - ascent);
240                 cxrow = cxrow->getNext();
241         }
242 }
243
244
245 void MathMatrixInset::Write(ostream & os, bool fragile)
246 {
247         if (GetType() == LM_OT_MATRIX) {
248                 if (fragile)
249                         os << "\\protect";
250                 os << "\\begin{"
251                    << name
252                    << '}';
253                 if (v_align_ == 't' || v_align_ == 'b') {
254                         os << '['
255                            << char(v_align_)
256                            << ']';
257                 }
258                 os << '{'
259                    << h_align_
260                    << "}\n";
261                 ++number_of_newlines;
262         }
263         MathParInset::Write(os, fragile);
264         if (GetType() == LM_OT_MATRIX){
265                 os << "\n";
266                 if (fragile)
267                         os << "\\protect";
268                 os << "\\end{"
269                    << name
270                    << '}';
271                 ++number_of_newlines;
272         }
273 }