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