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