Am Dienstag, 4. Oktober 2005 19:15 schrieb Jean-Marc Lasgouttes: > >>>>> "Georg" == Georg Baum <[EMAIL PROTECTED]> writes:
> Georg> AFAICS Andre' is right and MathMacroInset is the only > Georg> MathNestInset with 0 cells, so we could put the checks in > Georg> MathMacroInset. We would then avoid the checks when they are > Georg> not necessary. Would you prefer that? > > Yes, if that makes the code intent be clearer. In this case, we should > probably assert on bad values in MathNestInset. It looks like the attached, then. The asserts (if we add any) belong in MathNestInset::cell, MathGridInset::col and MathGridInset::row, because bad indices would harm there. I am not sure if we really need the asserts: MathMacroInset is really special. Apart from that I believe that the cell/column/row handling code is very robust in general. The asserts are now in a central place that gets called a lot. Shall I commit with or without the asserts? 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 2005-10-03 14:27:24.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/ChangeLog 2005-10-04 21:00:01.000000000 +0200 @@ -1,3 +1,13 @@ +2005-10-04 Georg Baum <[EMAIL PROTECTED]> + + * math_macro.C (editXY): new, fix crash (bug 2060) + * math_macro.C (cursorPos): new, fix potential crash + * math_macro.C (drawSelection): new, fix potential crash + * math_gridinset.C (col, row): assert on valid index + * math_nestinset.C (cell, drawSelection, editXY): ditto + * math_nestinset.C (doDispatch): fix crash when inserting math macros + with 0 arguments + 2005-09-30 Jean-Marc Lasgouttes <[EMAIL PROTECTED]> * math_nestinset.C (doDispatch): do not leave the inset after diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_gridinset.C lyx-1.4-cvs/src/mathed/math_gridinset.C --- lyx-1.4-clean/src/mathed/math_gridinset.C 2005-07-18 21:19:33.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/math_gridinset.C 2005-10-04 20:45:50.000000000 +0200 @@ -308,12 +347,14 @@ MathGridInset::row_type MathGridInset::n MathGridInset::col_type MathGridInset::col(idx_type idx) const { + BOOST_ASSERT(nargs() > idx); return idx % ncols(); } MathGridInset::row_type MathGridInset::row(idx_type idx) const { + BOOST_ASSERT(nargs() > idx); return idx / ncols(); } diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_macro.C lyx-1.4-cvs/src/mathed/math_macro.C --- lyx-1.4-clean/src/mathed/math_macro.C 2005-07-17 14:58:03.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/math_macro.C 2005-10-04 20:57:38.000000000 +0200 @@ -46,6 +46,15 @@ string MathMacro::name() const } +void MathMacro::cursorPos(CursorSlice const & sl, bool boundary, int & x, + int & y) const +{ + // We may have 0 arguments, but MathNestInset requires at least one. + if (nargs() > 0) + MathNestInset::cursorPos(sl, boundary, x, y); +} + + void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const { if (!MacroTable::globalMacros().has(name())) { @@ -102,10 +111,27 @@ void MathMacro::draw(PainterInfo & pi, i } +void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const +{ + // We may have 0 arguments, but MathNestInset requires at least one. + if (nargs() > 0) + MathNestInset::drawSelection(pi, x, y); +} + + void MathMacro::validate(LaTeXFeatures & features) const { if (name() == "binom" || name() == "mathcircumflex") features.require(name()); +} + + +InsetBase * MathMacro::editXY(LCursor & cur, int x, int y) +{ + // We may have 0 arguments, but MathNestInset requires at least one. + if (nargs() > 0) + return MathNestInset::editXY(cur, x, y); + return this; } diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_macro.h lyx-1.4-cvs/src/mathed/math_macro.h --- lyx-1.4-clean/src/mathed/math_macro.h 2004-11-24 17:46:19.000000000 +0100 +++ lyx-1.4-cvs/src/mathed/math_macro.h 2005-10-04 20:38:48.000000000 +0200 @@ -28,8 +28,14 @@ public: void draw(PainterInfo & pi, int x, int y) const; /// void drawExpanded(PainterInfo & pi, int x, int y) const; + /// draw selection background + void drawSelection(PainterInfo & pi, int x, int y) const; /// void metrics(MetricsInfo & mi, Dimension & dim) const; + /// get cursor position + void cursorPos(CursorSlice const & sl, bool boundary, int & x, int & y) const; + /// + InsetBase * editXY(LCursor & cur, int x, int y); /// std::string name() const; /// @@ -60,7 +66,7 @@ private: std::string name_; /// the unexpanded macro defintition mutable MathArray tmpl_; - /// the matcro substituted with our args + /// the macro substituted with our args mutable MathArray expanded_; }; diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_nestinset.C lyx-1.4-cvs/src/mathed/math_nestinset.C --- lyx-1.4-clean/src/mathed/math_nestinset.C 2005-10-03 14:27:29.000000000 +0200 +++ lyx-1.4-cvs/src/mathed/math_nestinset.C 2005-10-04 20:42:18.000000000 +0200 @@ -78,12 +78,14 @@ MathInset::idx_type MathNestInset::nargs MathArray & MathNestInset::cell(idx_type i) { + BOOST_ASSERT(i < cells_.size()); return cells_[i]; } MathArray const & MathNestInset::cell(idx_type i) const { + BOOST_ASSERT(i < cells_.size()); return cells_[i]; } @@ -219,6 +221,7 @@ void MathNestInset::draw(PainterInfo & p void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const { + BOOST_ASSERT(nargs() > 0); // FIXME: hack to get position cache warm draw(pi, x, y); @@ -859,7 +867,10 @@ void MathNestInset::doDispatch(LCursor & int cell(0); if (cmd.argument == "\\root") cell = 1; - if (ar.size() == 1 && (ar[0].nucleus()->asNestInset())) { + // math macros are nest insets and may have 0 cells. + // handleNest would crash in this case. + if (ar.size() == 1 && (ar[0].nucleus()->asNestInset()) && + ar[0].nucleus()->nargs() > cell) { cur.handleNest(ar[0], cell); } else cur.niceInsert(cmd.argument); @@ -1000,9 +1003,11 @@ void MathNestInset::edit(LCursor & cur, InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) { + idx_type const n = nargs(); + BOOST_ASSERT(n > 0); int idx_min = 0; int dist_min = 1000000; - for (idx_type i = 0, n = nargs(); i != n; ++i) { + for (idx_type i = 0; i != n; ++i) { int const d = cell(i).dist(x, y); if (d < dist_min) { dist_min = d;