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