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

The cause of the bug is the following:

When you press backspace in an empty paragraph (which is equivalent to 
pressing delete in the lastpos of the paragraph above), LyXText::backspacePos0 
just moves the cursor to the left and lets deleteEmptyParagraphMechanism 
remove the empty paragraph. However, dEPM does not trigger if the paragraph 
isFreeSpacing() and/or allowEmpty(). Both is true for paragraphs in ERT 
insets.

There are some tricks to circumvent this for keepEmpty layouts in 
LyXText::backspacePos0 (the layout is reset to default), but they do not work 
and cannot be expanded for paragraphs in ERT, because isFreeSpacing() and 
allowEmpty() always return true if ownerCode == InsetBase::ERT_CODE (see 
paragraph.C).

So the best I could come up with is to delete the paragraph manually when we 
are in ERT. The attached patch against 1.4 does this and works well AFAICS. 
The code for paragraph deletion is basically stolen from dEPM and simplified 
as much as I think it could be inside ERT, where there are no Counters and 
nested insets to update.

Please review someone, I feel not too confident in the ParagraphList business.

Thanks,
Jürgen
Index: src/text.C
===================================================================
--- src/text.C	(Revision 15282)
+++ src/text.C	(Arbeitskopie)
@@ -1644,7 +1644,22 @@ bool LyXText::backspacePos0(LCursor & cu
 				BufferParams const & bparams = buf.params();
 				par.layout(bparams.getLyXTextClass().defaultLayout());
 			}
-                                
+			// Inside ERT insets, we have to delete the par ourselves,
+			// because allowEmpty() and isFreeSpacing() is always true
+			if (par.ownerCode() == InsetBase::ERT_CODE) {
+				LCursor old = cur;
+				cursorLeft(cur);
+				if (cur.pit() == old.pit())
+					return false;
+				// Delete old par.
+				recordUndo(old, Undo::ATOMIC,
+					max(old.pit() - 1, pit_type(0)),
+					min(old.pit() + 1, old.lastpit()));
+				ParagraphList & plist = old.text()->paragraphs();
+				plist.erase(boost::next(plist.begin(), old.pit()));
+				cur.resetAnchor();
+				return true;
+			}
 			cursorLeft(cur);
 			return true;
 		}

Reply via email to