http://bugzilla.lyx.org/show_bug.cgi?id=4566

Attached is a backport of Stefan's fixes for this bug. It works for me, and 
Uwe tested it as well, but since it entails a range of changes, please have a 
look before I commit.

Jürgen
Index: src/mathed/InsetMathNest.cpp
===================================================================
--- src/mathed/InsetMathNest.cpp	(Revision 24068)
+++ src/mathed/InsetMathNest.cpp	(Arbeitskopie)
@@ -413,66 +413,78 @@
 	// this whole function is a hack and won't work for incremental font
 	// changes...
 
-	if (cur.inset().asInsetMath()->name() == font) {
-		recordUndoInset(cur, Undo::ATOMIC);
+	recordUndoSelection(cur);
+
+	if (cur.inset().asInsetMath()->name() == font)
 		cur.handleFont(to_utf8(font));
-	} else {
-		CursorSlice i1 = cur.selBegin();
-		CursorSlice i2 = cur.selEnd();
-		if (!i1.inset().asInsetMath())
-			return;
-		if (i1.idx() == i2.idx()) {
-			// the easy case where only one cell is selected
-			recordUndo(cur, Undo::ATOMIC);
-			cur.handleNest(createInsetMath(font));
+	else
+		handleNest(cur, createInsetMath(font), arg);
+}
+
+
+void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest)
+{
+	handleNest(cur, nest, docstring());
+}
+
+
+void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest,
+	docstring const & arg)
+{
+	CursorSlice i1 = cur.selBegin();
+	CursorSlice i2 = cur.selEnd();
+	if (!i1.inset().asInsetMath())
+		return;
+	if (i1.idx() == i2.idx()) {
+		// the easy case where only one cell is selected
+		cur.handleNest(nest);
+		cur.insert(arg);
+		return;
+	}
+
+	// multiple selected cells in a simple non-grid inset
+	if (i1.asInsetMath()->nrows() == 0 || i1.asInsetMath()->ncols() == 0) {
+		for (idx_type i = i1.idx(); i <= i2.idx(); ++i) {
+			// select cell
+			cur.idx() = i;
+			cur.pos() = 0;
+			cur.resetAnchor();
+			cur.pos() = cur.lastpos();
+			cur.setSelection();
+			
+			// change font of cell
+			cur.handleNest(nest);
 			cur.insert(arg);
-			return;
+			
+			// cur is in the font inset now. If the loop continues,
+			// we need to get outside again for the next cell
+			if (i + 1 <= i2.idx())
+				cur.pop_back();
 		}
-		// multiple selected cells in a simple non-grid inset
-		if (i1.asInsetMath()->nrows() == 0 || i1.asInsetMath()->ncols() == 0) {
-			recordUndoInset(cur);
-			for (idx_type i = i1.idx(); i <= i2.idx(); ++i) {
-				// select cell
-				cur.idx() = i;
-				cur.pos() = 0;
-				cur.resetAnchor();
-				cur.pos() = cur.lastpos();
-				cur.setSelection();
-				
-				// change font of cell
-				cur.handleNest(createInsetMath(font));
-				cur.insert(arg);
-				
-				// cur is in the font inset now. If the loop continues,
-				// we need to get outside again for the next cell
-				if (i + 1 <= i2.idx())
-					cur.pop_back();
-			}
-			return;
-		}
-		// the complicated case with multiple selected cells in a grid
-		recordUndoInset(cur);
-		Inset::row_type r1, r2;
-		Inset::col_type c1, c2;
-		cap::region(i1, i2, r1, r2, c1, c2);
-		for (Inset::row_type row = r1; row <= r2; ++row) {
-			for (Inset::col_type col = c1; col <= c2; ++col) {
-				// select cell
-				cur.idx() = i1.asInsetMath()->index(row, col);
-				cur.pos() = 0;
-				cur.resetAnchor();
-				cur.pos() = cur.lastpos();
-				cur.setSelection();
+		return;
+	}
 
-				// change font of cell
-				cur.handleNest(createInsetMath(font));
-				cur.insert(arg);
+	// the complicated case with multiple selected cells in a grid
+	Inset::row_type r1, r2;
+	Inset::col_type c1, c2;
+	cap::region(i1, i2, r1, r2, c1, c2);
+	for (Inset::row_type row = r1; row <= r2; ++row) {
+		for (Inset::col_type col = c1; col <= c2; ++col) {
+			// select cell
+			cur.idx() = i1.asInsetMath()->index(row, col);
+			cur.pos() = 0;
+			cur.resetAnchor();
+			cur.pos() = cur.lastpos();
+			cur.setSelection();
 
-				// cur is in the font inset now. If the loop continues,
-				// we need to get outside again for the next cell
-				if (col + 1 <= c2 || row + 1 <= r2)
-					cur.pop_back();
-			}
+			// change font of cell
+			cur.handleNest(nest);
+			cur.insert(arg);
+
+			// cur is in the font inset now. If the loop continues,
+			// we need to get outside again for the next cell
+			if (col + 1 <= c2 || row + 1 <= r2)
+				cur.pop_back();
 		}
 	}
 }
@@ -480,14 +492,12 @@
 
 void InsetMathNest::handleFont2(Cursor & cur, docstring const & arg)
 {
-	recordUndo(cur, Undo::ATOMIC);
+	recordUndoSelection(cur);
 	Font font;
 	bool b;
 	bv_funcs::string2font(to_utf8(arg), font, b);
-	if (font.color() != Color::inherit && font.color() != Color::ignore) {
-		MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
-		cur.handleNest(at, 0);
-	}
+	if (font.color() != Color::inherit && font.color() != Color::ignore)
+		handleNest(cur, MathAtom(new InsetMathColor(true, font.color())));
 }
 
 
@@ -1029,11 +1039,17 @@
 // handling such that "self-insert" works on "arbitrary stuff" too, and
 // math-insert only handles special math things like "matrix".
 	case LFUN_MATH_INSERT: {
-		recordUndo(cur, Undo::ATOMIC);
-		if (cmd.argument() == "^" || cmd.argument() == "_") {
+		recordUndoSelection(cur);
+		if (cmd.argument() == "^" || cmd.argument() == "_")
 			interpretChar(cur, cmd.argument()[0]);
-		} else
-			cur.niceInsert(cmd.argument());
+		else {
+			MathData ar;
+			asArray(cmd.argument(), ar);
+			if (ar.size() == 1 && ar[0]->asNestInset())
+				handleNest(cur, ar[0]);
+			else
+				cur.niceInsert(cmd.argument());
+		}
 		break;
 		}
 
Index: src/mathed/InsetMathNest.h
===================================================================
--- src/mathed/InsetMathNest.h	(Revision 24068)
+++ src/mathed/InsetMathNest.h	(Arbeitskopie)
@@ -128,6 +128,11 @@
 		docstring const & arg, char const * const font);
 	///
 	void handleFont2(Cursor & cur, docstring const & arg);
+	/// Grab and erase selection and insert the InsetMathNest atom in every
+	/// previously selected cell, insert the grabbed former data and \c arg
+	/// in the first cell of the inserted atom.
+	void handleNest(Cursor & cur, MathAtom const & nest);
+	void handleNest(Cursor & cur, MathAtom const & nest, docstring const & arg);
 
 	/// interpret \p c and insert the result at the current position of
 	/// of \p cur. Return whether the cursor should stay in the formula.
Index: src/CutAndPaste.h
===================================================================
--- src/CutAndPaste.h	(Revision 24068)
+++ src/CutAndPaste.h	(Arbeitskopie)
@@ -106,6 +106,8 @@
 void region(CursorSlice const & i1, CursorSlice const & i2,
 	Inset::row_type & r1, Inset::row_type & r2,
 	Inset::col_type & c1, Inset::col_type & c2);
+/// Returns true if multiple cells are selected in mathed.
+bool multipleCellsSelected(Cursor const & cur);
 /// Get the current selection as a string. Does not change the selection.
 /// Does only work if the whole selection is in mathed.
 docstring grabSelection(Cursor const & cur);
Index: src/CutAndPaste.cpp
===================================================================
--- src/CutAndPaste.cpp	(Revision 24068)
+++ src/CutAndPaste.cpp	(Arbeitskopie)
@@ -404,6 +404,23 @@
 }
 
 
+bool multipleCellsSelected(Cursor const & cur)
+{
+	if (!cur.selection() || !cur.inMathed())
+		return false;
+	
+	CursorSlice i1 = cur.selBegin();
+	CursorSlice i2 = cur.selEnd();
+	if (!i1.inset().asInsetMath())
+		return false;
+	
+	if (i1.idx() == i2.idx())
+		return false;
+	
+	return true;
+}
+
+
 void switchBetweenClasses(textclass_type c1, textclass_type c2,
 	InsetText & in, ErrorList & errorlist)
 {
Index: src/Undo.cpp
===================================================================
--- src/Undo.cpp	(Revision 24068)
+++ src/Undo.cpp	(Arbeitskopie)
@@ -19,6 +19,7 @@
 #include "Buffer.h"
 #include "buffer_funcs.h"
 #include "Cursor.h"
+#include "CutAndPaste.h"
 #include "debug.h"
 #include "BufferView.h"
 #include "Text.h"
@@ -282,7 +283,14 @@
 
 void recordUndoSelection(Cursor & cur, Undo::undo_kind kind)
 {
-	recordUndo(kind, cur, cur.selBegin().pit(), cur.selEnd().pit());
+	if (cur.inMathed()) {
+		if (cap::multipleCellsSelected(cur))
+			recordUndoInset(cur, kind);
+		else
+			recordUndo(cur, kind);
+	} else
+		recordUndo(kind, cur, cur.selBegin().pit(),
+			cur.selEnd().pit());
 }
 
 

Reply via email to