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

This patch addresses this bug in form of some rather ugly additional checks: 
if a bibitem is deleted, the paragraph will be merged with the preceeding 
par, if that's a bibitem par as well, else it will be reset to default.

Furthermore, it is checked that bibitem do not occur outside pos 0.

The ideal solution, instead of all these checks, would be to set the bibitem 
in the margin (like the itemize item) and thus disallow the cursor being 
placed in front of it. However, I think this is post-1.5.0 stuff, and my 
solution would do for now.

However, please cast your eye on the paragraph merging code in 
handleBibitem(). I wouldn't be surprised if this could be optimized.

Thanks,
Jürgen
Index: src/text.cpp
===================================================================
--- src/text.cpp	(Revision 18054)
+++ src/text.cpp	(Arbeitskopie)
@@ -1170,6 +1170,39 @@
 }
 
 
+bool LyXText::handleBibitems(Cursor & cur)
+{
+	if (cur.paragraph().layout()->labeltype != LABEL_BIBLIO)
+		return false;
+	// if a bibitem is deleted, merge with previous paragraph
+	// if this is a bibliography item as well
+	if (cur.pos() == 0) {
+		BufferParams const & bufparams = cur.buffer().params();
+		Paragraph const & par = cur.paragraph();
+		Cursor prevcur = cur;
+		if (cur.pit() > 0) {
+			--prevcur.pit();
+			prevcur.pos() = prevcur.lastpos();
+		}
+		Paragraph const & prevpar = prevcur.paragraph();
+		if (cur.pit() > 0 && par.layout() == prevpar.layout()) {
+			recordUndo(cur, Undo::ATOMIC, prevcur.pit());
+			mergeParagraph(bufparams, cur.text()->paragraphs(),
+				       prevcur.pit());
+			updateLabels(cur.buffer());
+			setCursorIntern(cur, prevcur.pit(), prevcur.pos());
+			cur.updateFlags(Update::Force);
+			return true;
+		// if not, reset the paragraph to default
+		} else
+			cur.paragraph().layout(
+				bufparams.getLyXTextClass().defaultLayout());
+		return true;
+	}
+	return false;
+}
+
+
 bool LyXText::erase(Cursor & cur)
 {
 	BOOST_ASSERT(this == cur.text());
@@ -1200,6 +1233,8 @@
 		}
 	}
 
+	needsUpdate |= handleBibitems(cur);
+
 	if (needsUpdate) {
 		// Make sure the cursor is correct. Is this really needed?
 		// No, not really... at least not here!
@@ -1298,6 +1333,8 @@
 	if (cur.pos() == cur.lastpos())
 		setCurrentFont(cur);
 
+	needsUpdate |= handleBibitems(cur);
+
 	// A singlePar update is not enough in this case.
 //		cur.updateFlags(Update::Force);
 	setCursor(cur.top(), cur.pit(), cur.pos());
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp	(Revision 18054)
+++ src/Paragraph.cpp	(Arbeitskopie)
@@ -2592,12 +2592,34 @@
 		&& getChar(0) == Paragraph::META_INSET
 		&& insetlist.begin()->inset->lyxCode() == InsetBase::BIBITEM_CODE;
 
+	docstring oldkey;
+	docstring oldlabel;
+
+	// remove bibitems in pos != 0
+	// restore them later in pos 0 if necessary
+	// (e.g. if a user inserts contents _before_ the item)
+	InsetList::const_iterator it = insetlist.begin();
+	InsetList::const_iterator end = insetlist.end();
+	for (; it != end; ++it)
+		if (it->inset->lyxCode() == InsetBase::BIBITEM_CODE
+		    && it->pos > 0) {
+			InsetBibitem * olditem = static_cast<InsetBibitem *>(it->inset);
+			oldkey = olditem->getParam("key");
+			oldlabel = olditem->getParam("label");
+			eraseChar(it->pos, track_changes);
+	}
+
 	if (hasbibitem)
 		return false;
 
 	InsetBibitem * inset(new InsetBibitem(InsetCommandParams("bibitem")));
+	// restore values of previously deleted item in this par.
+	if (!oldkey.empty())
+		inset->setParam("key", oldkey);
+	if (!oldlabel.empty())
+		inset->setParam("label", oldlabel);
 	insertInset(0, static_cast<InsetBase *>(inset),
-		Change(track_changes ? Change::INSERTED : Change::UNCHANGED));
+		    Change(track_changes ? Change::INSERTED : Change::UNCHANGED));
 
 	return true;
 }
Index: src/text3.cpp
===================================================================
--- src/text3.cpp	(Revision 18054)
+++ src/text3.cpp	(Arbeitskopie)
@@ -1653,7 +1653,8 @@
 		return true;
 
 	case LFUN_BIBITEM_INSERT:
-		enable = (cur.paragraph().layout()->labeltype == LABEL_BIBLIO);
+		enable = (cur.paragraph().layout()->labeltype == LABEL_BIBLIO
+			  && cur.pos() == 0);
 		break;
 
 	case LFUN_DIALOG_SHOW_NEW_INSET:
Index: src/LyXText.h
===================================================================
--- src/LyXText.h	(Revision 18054)
+++ src/LyXText.h	(Arbeitskopie)
@@ -387,6 +387,8 @@
 	// At cursor position 0, try to merge the paragraph with the one before it.
 	// Ignore change tracking, i.e., physically remove the end-of-par character
 	bool backspacePos0(Cursor & cur);
+	/// handle the case where bibitems were deleted
+	bool handleBibitems(Cursor & cur);
 
 	///
 	void deleteWordForward(Cursor & cur);

Reply via email to