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