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