The fact than one cannot change certain formula types to others has annoyed me several times. Here comes a patch that implements all missing mutations. Since I do not understand why the missing mutations are missing (e. g. why can a "multline" be converted to "alignat", but a "gather" cannot), it would be nice if somebody more familiar with this could enlighten me. Apart from that, it seems to work, and I think it can be applied.
Georg
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/ChangeLog lyx-1.4-cvs/src/mathed/ChangeLog --- lyx-1.4-clean/src/mathed/ChangeLog 2004-08-29 09:03:01.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/ChangeLog 2004-09-11 21:11:43.000000000 +0200 @@ -1,3 +1,10 @@ +2004-09-11 Georg Baum <[EMAIL PROTECTED]> + + * math_hullinset.[C,h] (splitTo2Cols): new + * math_hullinset.[C,h] (splitTo3Cols): new + * math_hullinset.[C,h] (changeCols): new + * math_hullinset.C (mutate): implement missing mutations + 2004-08-16 José Matos <[EMAIL PROTECTED]> * formulamacro.C (write): diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_hullinset.C lyx-1.4-cvs/src/mathed/math_hullinset.C --- lyx-1.4-clean/src/mathed/math_hullinset.C 2004-08-29 09:03:08.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/math_hullinset.C 2004-09-11 19:55:54.000000000 +0200 @@ -607,6 +616,65 @@ void MathHullInset::glueall() } +void MathHullInset::splitTo2Cols() +{ + BOOST_ASSERT(ncols() == 1); + MathGridInset::addCol(1); + for (row_type row = 0; row < nrows(); ++row) { + idx_type const i = 2 * row; + pos_type pos = firstRelOp(cell(i)); + cell(i + 1) = MathArray(cell(i).begin() + pos, cell(i).end()); + cell(i).erase(pos, cell(i).size()); + } +} + + +void MathHullInset::splitTo3Cols() +{ + BOOST_ASSERT(ncols() < 3); + if (ncols() < 2) + splitTo2Cols(); + MathGridInset::addCol(1); + for (row_type row = 0; row < nrows(); ++row) { + idx_type const i = 3 * row + 1; + if (cell(i).size()) { + cell(i + 1) = MathArray(cell(i).begin() + 1, cell(i).end()); + cell(i).erase(1, cell(i).size()); + } + } +} + + +void MathHullInset::changeCols(col_type cols) +{ + if (ncols() == cols) + return; + else if (ncols() < cols) { + // split columns + if (cols < 3) + splitTo2Cols(); + else { + splitTo3Cols(); + while (ncols() < cols) + MathGridInset::addCol(ncols() - 1); + } + return; + } + + // combine columns + for (row_type row = 0; row < nrows(); ++row) { + idx_type const i = row * ncols(); + for (col_type col = cols; col < ncols(); ++col) { + cell(i + cols - 1).append(cell(i + col)); + } + } + // delete columns + while (ncols() > cols) { + MathGridInset::delCol(ncols() - 1); + } +} + + string const & MathHullInset::getType() const { return type_; @@ -626,7 +694,12 @@ void MathHullInset::mutate(string const lyxerr << "mutating from '" << type_ << "' to '" << newtype << "'" << endl; // we try to move along the chain - // none <-> simple <-> equation <-> eqnarray + // none <-> simple <-> equation <-> eqnarray -> *align* -> multline, gather -+ + // ^ | + // +-------------------------------------+ + // we use eqnarray as intermediate type for mutations that are not + // directly supported because it handles labels and numbering for + // "down mutation". if (newtype == "dump") { dump(); @@ -645,6 +718,7 @@ void MathHullInset::mutate(string const else if (type_ == "simple") { if (newtype == "none") { setType("none"); + numbered(0, false); } else { setType("equation"); numbered(0, false); @@ -655,32 +729,17 @@ void MathHullInset::mutate(string const else if (type_ == "equation") { if (smaller(newtype, type_)) { setType("simple"); + numbered(0, false); mutate(newtype); } else if (newtype == "eqnarray") { - MathGridInset::addCol(1); - MathGridInset::addCol(1); - - // split it "nicely" on the firest relop - pos_type pos = firstRelOp(cell(0)); - cell(1) = MathArray(cell(0).begin() + pos, cell(0).end()); - cell(0).erase(pos, cell(0).size()); - - if (cell(1).size()) { - cell(2) = MathArray(cell(1).begin() + 1, cell(1).end()); - cell(1).erase(1, cell(1).size()); - } + // split it "nicely" on the first relop + splitTo3Cols(); setType("eqnarray"); - mutate(newtype); } else if (newtype == "multline" || newtype == "gather") { setType(newtype); - numbered(0, false); } else { - MathGridInset::addCol(1); // split it "nicely" - pos_type pos = firstRelOp(cell(0)); - cell(1) = cell(0); - cell(0).erase(pos, cell(0).size()); - cell(1).erase(0, pos); + splitTo2Cols(); setType("align"); mutate(newtype); } @@ -708,52 +767,67 @@ void MathHullInset::mutate(string const label_[0] = label; mutate(newtype); } else { // align & Co. - for (row_type row = 0; row < nrows(); ++row) { - idx_type c = 3 * row + 1; - cell(c).append(cell(c + 1)); - } - MathGridInset::delCol(2); + changeCols(2); setType("align"); mutate(newtype); } } - else if (type_ == "align") { - if (smaller(newtype, type_)) { - MathGridInset::addCol(1); + else if (type_ == "align" || type_ == "alignat" || + type_ == "xalignat" || type_ == "flalign") { + if (smaller(newtype, "align")) { + changeCols(3); setType("eqnarray"); mutate(newtype); + } else if (newtype == "gather" || newtype == "multline") { + changeCols(1); + setType(newtype); + } else if (newtype == "xxalignat") { + for (row_type row = 0; row < nrows(); ++row) + numbered(row, false); + setType(newtype); } else { setType(newtype); } } - else if (type_ == "multline") { - if (newtype == "gather" || newtype == "align" || - newtype == "xalignat" || newtype == "xxalignat" || newtype == "flalign") - setType(newtype); - else if (newtype == "eqnarray") { - MathGridInset::addCol(1); - MathGridInset::addCol(1); + else if (type_ == "xxalignat") { + for (row_type row = 0; row < nrows(); ++row) + numbered(row, false); + if (smaller(newtype, "align")) { + changeCols(3); setType("eqnarray"); + mutate(newtype); + } else if (newtype == "gather" || newtype == "multline") { + changeCols(1); + setType(newtype); } else { - lyxerr << "mutation from '" << type_ - << "' to '" << newtype << "' not implemented" << endl; + setType(newtype); } } - else if (type_ == "gather") { - if (newtype == "multline") { + else if (type_ == "multline" || type_ == "gather") { + if (newtype == "gather" || newtype == "multline") + setType(newtype); + else if (newtype == "align" || newtype == "flalign" || + newtype == "alignat" || newtype == "xalignat") { + splitTo2Cols(); + setType(newtype); + } else if (newtype == "xxalignat") { + splitTo2Cols(); + for (row_type row = 0; row < nrows(); ++row) + numbered(row, false); setType(newtype); } else { - lyxerr << "mutation from '" << type_ - << "' to '" << newtype << "' not implemented" << endl; + splitTo3Cols(); + setType("eqnarray"); + mutate(newtype); } } else { lyxerr << "mutation from '" << type_ - << "' to '" << newtype << "' not implemented" << endl; + << "' to '" << newtype << "' not implemented" << endl; } } diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_hullinset.h lyx-1.4-cvs/src/mathed/math_hullinset.h --- lyx-1.4-clean/src/mathed/math_hullinset.h 2004-04-13 19:38:16.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/math_hullinset.h 2004-09-11 19:28:00.000000000 +0200 @@ -145,6 +145,22 @@ private: void doExtern(LCursor & cur, FuncRequest & func); /// void glueall(); + /*! + * split every row at the first relation operator. + * The number of columns must be 1. One column is added. + * The first relation operator and everything after it goes to the + * second column. + */ + void splitTo2Cols(); + /*! + * split every row at the first relation operator. + * The number of columns must be < 3. One or two columns are added. + * The first relation operator goes to the second column. + * Everything after it goes to the third column. + */ + void splitTo3Cols(); + /// change number of columns, split or combine columns if necessary. + void changeCols(col_type); /// char const * standardFont() const; /// consistency check