]> git.lyx.org Git - features.git/blob - src/mathed/math_matrixinset.C
mathed49.diff
[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 "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')
19 {
20         flag = 15;
21         if (n > 0) {
22                 row_.data_ = new MathedRowSt(nc_ + 1);
23                 MathedXIter it(this);
24                 for (int j = 1; j < n; ++j)
25                         it.addRow();
26                 nr_ = n;
27                 if (nr_ == 1 && nc_ > 1) {
28                         for (int j = 0; j < nc_ - 1; ++j) 
29                                 it.insert('T', LM_TC_TAB);
30                 }
31         } else if (n < 0) {
32                 row_.data_ = new MathedRowSt(nc_ + 1);
33                 nr_ = 1;
34         }
35 }
36
37
38 MathMatrixInset::MathMatrixInset(MathMatrixInset const & mt)
39         : MathParInset(mt.GetStyle(), mt.GetName(), mt.GetType()),
40           nc_(mt.nc_), nr_(0), ws_(mt.nc_),
41           v_align_(mt.v_align_), h_align_(mt.h_align_)
42 {
43         array = mt.GetData();
44         if (!mt.row_.empty()) {
45                 MathedRowSt * ro = 0;
46                 MathedRowSt * mrow = mt.row_.data_;
47
48                 while (mrow) {
49                         MathedRowSt * r = new MathedRowSt(nc_ + 1);
50                         r->setNumbered(mrow->isNumbered());
51                         //if (mrow->label) 
52                         r->setLabel(mrow->getLabel());
53                         if (!ro) 
54                                 row_.data_ = r;
55                         else
56                                 ro->next_ = r;
57                         mrow = mrow->next_;
58                         ro = r;
59                         ++nr_;
60                 }
61         } else   
62                 row_.data_ = 0;
63         flag = mt.flag;
64 }
65
66
67 MathMatrixInset::~MathMatrixInset()
68 {
69         MathedRowSt * r = row_.data_;
70         while (r) {
71                 MathedRowSt * q = r->next_;
72                 delete r;
73                 r = q;
74         }
75 }
76
77
78
79 MathedInset * MathMatrixInset::Clone()
80 {
81         return new MathMatrixInset(*this);
82 }
83
84
85 void MathMatrixInset::SetAlign(char vv, string const & hh)
86 {
87         v_align_ = vv;
88         h_align_ = hh.substr(0, nc_); // usr just h_align = hh; perhaps
89 }
90
91
92 // Check the number of tabs and crs
93 void MathMatrixInset::setData(MathedArray const & a)
94 {
95         array = a;
96
97         MathedIter it(&array);
98         int nn = nc_ - 1;
99         nr_ = 1;
100         // count tabs per row
101         while (it.OK()) {
102                 if (it.IsTab()) {
103                         if (nn < 0) { 
104                                 it.Delete();
105                                 continue;
106                         } else {
107                                 // it.Next();
108                                 --nn;
109                         }
110                 }
111                 if (it.IsCR()) {
112                         while (nn > 0) {
113                                 it.insert(' ', LM_TC_TAB);
114                                 --nn;
115                         }
116                         nn = nc_ - 1;
117                         ++nr_;
118                 }
119                 it.Next();
120         }
121         it.Reset();
122         
123         // Automatically inserts tabs around bops
124         // DISABLED because it's very easy to insert tabs 
125 }
126
127
128 void MathMatrixInset::draw(Painter & pain, int x, int baseline)
129 {
130         MathParInset::draw(pain, x, baseline);
131 }
132
133
134
135 void MathMatrixInset::Metrics()
136 {
137         if (row_.empty()) {
138                 // lyxerr << " MIDA ";
139                 MathedXIter it(this);
140                 row_.data_ = it.adjustVerticalSt();
141         } 
142         
143         // Clean the arrays      
144         for (MathedRowContainer::iterator it = row_.begin(); it; ++it)
145                 for (int i = 0; i <= nc_; ++i)
146                         it->setTab(i, 0);
147         
148         // Basic metrics
149         MathParInset::Metrics();
150
151         MathedRowContainer::iterator cxrow = row_.begin();
152         if (nc_ <= 1 && cxrow.is_last()) {
153                 cxrow->ascent(ascent);
154                 cxrow->descent(descent);
155         }
156         
157         // Vertical positions of each row
158         MathedRowContainer::iterator cprow = cxrow;
159         int h = 0;
160         for ( ; cxrow; ++cxrow) {
161                 for (int i = 0; i < nc_; ++i) {
162                         if (cxrow == row_.begin() || ws_[i] < cxrow->getTab(i))
163                                 ws_[i] = cxrow->getTab(i);
164                         if (cxrow.is_last() && ws_[i] == 0)
165                                 ws_[i] = df_width;
166                 }
167                 
168                 cxrow->setBaseline((cxrow == row_.begin()) ?
169                                    cxrow->ascent() :
170                                    cxrow->ascent() + cprow->descent()
171                                    + MATH_ROWSEP + cprow->getBaseline());
172                 h += cxrow->ascent() + cxrow->descent() + MATH_ROWSEP;  
173                 cprow = cxrow;
174         }
175         
176         int const hl = Descent();
177         h -= MATH_ROWSEP;
178         
179         //  Compute vertical align
180         switch (v_align_) {
181         case 't':
182                 ascent = row_.begin()->getBaseline();
183                 break;
184         case 'b':
185                 ascent = h - hl;
186                 break;
187         default:
188                 ascent = (row_.begin().is_last()) ? h / 2 : h - hl;
189                 break;
190         }
191         descent = h - ascent + 2;
192         
193         // Increase ws_[i] for 'R' columns (except the first one)
194         for (int i = 1; i < nc_; ++i)
195                 if (h_align_[i] == 'R')
196                         ws_[i] += 10 * df_width;
197         // Increase ws_[i] for 'C' column
198         if (h_align_[0] == 'C')
199                 if (ws_[0] < 7 * workWidth / 8)
200                         ws_[0] = 7 * workWidth / 8;
201         
202         // Adjust local tabs
203         width = MATH_COLSEP;
204         for (cxrow = row_.begin(); cxrow; ++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_.begin())
226                                         lf = 0;
227                                 else if (cxrow.is_last())
228                                         lf = ws_[i] - cxrow->getTab(i);
229                                 else
230                                         lf = (ws_[i] - cxrow->getTab(i))/2; 
231                                 break;
232                         }
233                         int const ww = (isvoid) ? lf : lf + cxrow->getTab(i);
234                         cxrow->setTab(i, lf + rg);
235                         rg = ws_[i] - ww + MATH_COLSEP;
236                         if (cxrow == row_.begin())
237                                 width += ws_[i] + MATH_COLSEP;
238                 }
239                 cxrow->setBaseline(cxrow->getBaseline() - ascent);
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 }