lyx_mirror/src/mathed/math_matrixinset.C

265 lines
5.4 KiB
C++
Raw Normal View History

#include <config.h>
#include "math_matrixinset.h"
#include "math_rowst.h"
#include "math_xiter.h"
#include "support/LOstream.h"
using std::ostream;
extern int number_of_newlines;
MathMatrixInset::MathMatrixInset(int m, int n, short st)
: MathParInset(st, "array", LM_OT_MATRIX), nc(m), nr(0), ws_(m),
v_align(0), h_align(nc, 'c')
{
row = 0;
flag = 15;
if (n > 0) {
row = new MathedRowSt(nc+1);
MathedXIter it(this);
for (int j = 1; j < n; ++j) it.addRow();
nr = n;
if (nr == 1 && nc > 1) {
for (int j = 0; j < nc - 1; ++j)
it.Insert('T', LM_TC_TAB);
}
} else if (n < 0) {
row = new MathedRowSt(nc + 1);
nr = 1;
}
}
MathMatrixInset::MathMatrixInset(MathMatrixInset * mt)
: MathParInset(mt->GetStyle(), mt->GetName(), mt->GetType()),
nc(mt->nc), nr(0), ws_(mt->nc), v_align(mt->v_align), h_align(mt->h_align)
{
MathedIter it;
it.SetData(mt->GetData());
array = it.Copy();
if (mt->row != 0) {
MathedRowSt * r, * ro= 0, * mrow = mt->row;
//mrow = mt->row; // This must be redundant...
while (mrow) {
r = new MathedRowSt(nc + 1);
r->setNumbered(mrow->isNumbered());
//if (mrow->label)
r->setLabel(mrow->getLabel());
if (!ro)
row = r;
else
ro->setNext(r);
mrow = mrow->getNext();
ro = r;
++nr;
}
} else
row = 0;
flag = mt->flag;
}
MathMatrixInset::~MathMatrixInset()
{
MathedRowSt * r = row;
while (r) {
MathedRowSt * q = r->getNext();
delete r;
r = q;
}
}
MathedInset * MathMatrixInset::Clone()
{
return new MathMatrixInset(this);
}
void MathMatrixInset::SetAlign(char vv, string const & hh)
{
v_align = vv;
h_align = hh.substr(0, nc); // usr just h_align = hh; perhaps
}
// Check the number of tabs and crs
void MathMatrixInset::SetData(MathedArray * a)
{
if (!a) return;
MathedIter it(a);
int nn = nc - 1;
nr = 1;
// count tabs per row
while (it.OK()) {
if (it.IsTab()) {
if (nn < 0) {
it.Delete();
continue;
} else {
// it.Next();
--nn;
}
}
if (it.IsCR()) {
while (nn > 0) {
it.Insert(' ', LM_TC_TAB);
--nn;
}
nn = nc - 1;
++nr;
}
it.Next();
}
it.Reset();
// Automatically inserts tabs around bops
// DISABLED because it's very easy to insert tabs
array = a;
}
void MathMatrixInset::draw(Painter & pain, int x, int baseline)
{
MathParInset::draw(pain, x, baseline);
}
void MathMatrixInset::Metrics()
{
int i, hl, h = 0;
MathedRowSt * cprow= 0;
if (!row) {
// lyxerr << " MIDA ";
MathedXIter it(this);
row = it.adjustVerticalSt();
}
// Clean the arrays
MathedRowSt * cxrow = row;
while (cxrow) {
for (i = 0; i <= nc; ++i) cxrow->setTab(i, 0);
cxrow = cxrow->getNext();
}
// Basic metrics
MathParInset::Metrics();
if (nc <= 1 && !row->getNext()) {
row->ascent(ascent);
row->descent(descent);
}
// Vertical positions of each row
cxrow = row;
while (cxrow) {
for (i = 0; i < nc; ++i) {
if (cxrow == row || ws_[i] < cxrow->getTab(i))
ws_[i] = cxrow->getTab(i);
if (cxrow->getNext() == 0 && ws_[i] == 0) ws_[i] = df_width;
}
cxrow->setBaseline((cxrow == row) ?
cxrow->ascent() :
cxrow->ascent() + cprow->descent()
+ MATH_ROWSEP + cprow->getBaseline());
h += cxrow->ascent() + cxrow->descent() + MATH_ROWSEP;
cprow = cxrow;
cxrow = cxrow->getNext();
}
hl = Descent();
h -= MATH_ROWSEP;
// Compute vertical align
switch (v_align) {
case 't': ascent = row->getBaseline(); break;
case 'b': ascent = h - hl; break;
default: ascent = (row->getNext()) ? h / 2: h - hl; break;
}
descent = h - ascent + 2;
// Increase ws_[i] for 'R' columns (except the first one)
for (i = 1; i < nc; ++i)
if (h_align[i] == 'R')
ws_[i] += 10*df_width;
// Increase ws_[i] for 'C' column
if (h_align[0] == 'C')
if (ws_[0] < 7*workWidth/8)
ws_[0] = 7*workWidth/8;
// Adjust local tabs
cxrow = row;
width = MATH_COLSEP;
while (cxrow) {
int rg = MATH_COLSEP, ww, lf = 0; //, * w = cxrow->w;
for (i = 0; i < nc; ++i) {
bool isvoid = false;
if (cxrow->getTab(i) <= 0) {
cxrow->setTab(i, df_width);
isvoid = true;
}
switch (h_align[i]) {
case 'l':
lf = 0;
break;
case 'c':
lf = (ws_[i] - cxrow->getTab(i))/2;
break;
case 'r':
case 'R':
lf = ws_[i] - cxrow->getTab(i);
break;
case 'C':
if (cxrow == row)
lf = 0;
else if (!cxrow->getNext())
lf = ws_[i] - cxrow->getTab(i);
else
lf = (ws_[i] - cxrow->getTab(i))/2;
break;
}
ww = (isvoid) ? lf : lf + cxrow->getTab(i);
cxrow->setTab(i, lf + rg);
rg = ws_[i] - ww + MATH_COLSEP;
if (cxrow == row) width += ws_[i] + MATH_COLSEP;
}
cxrow->setBaseline(cxrow->getBaseline() - ascent);
cxrow = cxrow->getNext();
}
}
void MathMatrixInset::Write(ostream & os, bool fragile)
{
if (GetType() == LM_OT_MATRIX){
if (fragile)
os << "\\protect";
os << "\\begin{"
<< name
<< '}';
if (v_align == 't' || v_align == 'b') {
os << '['
<< char(v_align)
<< ']';
}
os << '{'
<< h_align
<< "}\n";
++number_of_newlines;
}
MathParInset::Write(os, fragile);
if (GetType() == LM_OT_MATRIX){
os << "\n";
if (fragile)
os << "\\protect";
os << "\\end{"
<< name
<< '}';
++number_of_newlines;
}
}