Now that the clipboard works again on all platforms I give here a summary 
of the current status.

Am Freitag, 5. Januar 2007 17:05 schrieb Georg Baum:

> Let's start with our internal clipboard stack: This is advertised to the 
> user in the "paste recent" menu. If you know this it suddenly makes sense 
> that a middle mouse button press pushes the current selection to the 
> internal clipboard. So this is not a hack, but done on purpose. This is 
> only done for middle mouse button paste and not for C-v, since in the 
> latter case the stuff is already in the clipboard (at least if it comes 
> >from within LyX). Unfortunately this is only done in text, not in math 
nor 
> in tables. The attached patch x.diff implements the same mechanism for 
> tables and math and should go in IMO. Any objections?

This has been applied.

> The next question: The clipboard stack is not really a "paste recent" 
> stack: If you copy something in LyX without pasting it is nevertheless 
> added, and anything that is pasted but comes from outside (selection or 
> clipboard) is not added. That means that it is a bit inconsistent. To 
make 
> it consistent, we could decouple the stack from the clipboard and always 
> fill it on paste. The only disadvantage I see in doing so is that items 
> that you only copy do not appear anymore in the stack. Opinions?

Nothing has been changed here, since there were too many opinions.

> Then we need to decide how the selection should work. The current 
> implementation is almost what I want: No difference between "internal" 
> and "external" selection, only one application global selection exists: 
> Everything you select in LyX is advertised to the X server and can be 
> requested by other applications. If you select something in another 
> application LyX receives a SelectionClear event and clears the internal 
> selection. What is missing for this to be fully implemented are some 
calls 
> to theSelection().haveSelection() if the selection was modified by the 
> keyboard. No haveSelection call is missing AFAIK for selection changes by 
> the mouse.
> 
> Question: Do we want to advertise keyboard and mouse selections 
differently 
> to X? IMO we should not, and because we do our own selection handling and 
> don't use qApp->clipboard()->setText() for this there is no performance 
> penalty. Unless there are some very good reasons not to advertise 
> selection changes by keyboard to X I am going to add the missing 
> haveSelection calls.

This has been done, but only where we got a selection, not where we cleared 
it (for consistency reasons: This is the same as mouse selections are 
currently handled)

> Fake X selection for windows and Mac: The patch I originally sent is not 
> needed anymore if the patch x.diff in this message is applied, since then 
> the internal selection is always used if available. If we want to paste 
> the clipboard with the middle mouse button on systems that don't have a 
> selection then we should do it like the patch fake-selection.diff. This 
is 
> against the "simple mental model" of the selection, so I don't like it, 
> but if windows users agree that this is useful I won't object.

This is not in. AFAIK it is now as simple as the attached patch 
fake-selection2.diff.

> Persistent selection: Some people want that a selection is still 
available 
> for middle mouse button paste after it is not visible on screen anymore, 
> and several applications implement that. This is against the "simple 
> mental model": The equation "selection == highlighted text on screen" 
> would not be true anymore. It is not needed either: It makes sense for 
> applications that don't have a clipboard, but since we have one we can as 
> well use C-c and C-v for copy/paste.
> If a majority does not agree with me and somebody volunteers to implement 
> persistent selections I can outline how it can be done, but I won't 
> implement it myself. This is not very difficult to do, but would require 
> some code reorganizations.

The attached patch is the forward ported version of a patch I sent some 
time ago. It is not complete (see FIXMEs), and not tested at all. Bo, if 
you want to finish this you have to look for missing calls of 
cap::finishSelection (they are need whenever the current selections is 
modified). I believe that I found almost all places where that is needed, 
but I might have missed some.

> Related to persistent selections: Should a recieved SelectionClear event 
> clear the LyX selection or not? Again, some apps do this and others 
don't. 
> http://www.jwz.org/doc/x-cut-and-paste.html recommends to honor this 
> request, and this is currently done in LyX.

Nothing has been changed here.

I am not going to do further changes, so if anybody wants fake selection on 
windows, persistent selection or something else please take care of that 
yourself. IMHO both fake selection and persistent would be candidates for 
1.5, all other stuff (extend the external clipboard to all importable 
formats, making the internal clipboard a grid etc) is clearly for later.


Georg
Index: src/frontends/qt4/GuiSelection.C
===================================================================
--- src/frontends/qt4/GuiSelection.C	(Revision 16668)
+++ src/frontends/qt4/GuiSelection.C	(Arbeitskopie)
@@ -15,6 +15,8 @@
 #include "GuiSelection.h"
 #include "qt_helpers.h"
 
+#include "frontends/Clipboard.h"
+
 #include "debug.h"
 
 #include <QApplication>
@@ -58,6 +60,9 @@ void GuiSelection::haveSelection(bool ow
 
 docstring const GuiSelection::get() const
 {
+	if (!qApp->clipboard()->supportsSelection())
+		return theClipboard().getAsText();
+
 	QString const str = qApp->clipboard()->text(QClipboard::Selection);
 	lyxerr[Debug::ACTION] << "GuiSelection::get: " << fromqstr(str)
 	                      << endl;
Index: src/cursor.C
===================================================================
--- src/cursor.C	(Revision 16668)
+++ src/cursor.C	(Arbeitskopie)
@@ -41,8 +41,6 @@
 #include "mathed/InsetMathScript.h"
 #include "mathed/MathMacroTable.h"
 
-#include "frontends/Selection.h"
-
 #include "support/limited_stack.h"
 
 #include <boost/assert.hpp>
@@ -560,7 +558,7 @@ bool LCursor::selHandle(bool sel)
 
 	resetAnchor();
 	selection() = sel;
-	theSelection().haveSelection(sel);
+	cap::finishSelection(*this);
 	return true;
 }
 
Index: src/insets/insettabular.C
===================================================================
--- src/insets/insettabular.C	(Revision 16669)
+++ src/insets/insettabular.C	(Arbeitskopie)
@@ -455,6 +455,7 @@ void InsetTabular::edit(LCursor & cur, b
 	//lyxerr << "InsetTabular::edit: " << this << endl;
 	finishUndo();
 	cur.selection() = false;
+	cap::finishSelection(cur);
 	cur.push(*this);
 	if (left) {
 		if (isRightToLeft(cur))
@@ -495,18 +496,19 @@ void InsetTabular::doDispatch(LCursor & 
 			if (!bvcur.selection() && !cur.bv().mouseSetCursor(cur))
 				cur.noUpdate();
 			cur.selection() = false;
+			cap::finishSelection(cur);
 			setCursorFromCoordinates(cur, cmd.x, cmd.y);
 			cur.bv().mouseSetCursor(cur);
 			break;
 		}
 
 		if (cmd.button() == mouse_button::button2) {
-			if (bvcur.selection()) {
+			if (cap::selection()) {
 				// See comment in LyXText::dispatch why we
 				// do this
 				// FIXME This does not use paste_tabular,
 				// another reason why paste_tabular should go.
-				cap::copySelectionToStack(bvcur);
+				cap::copySelectionToStack();
 				cmd = FuncRequest(LFUN_PASTE, "0");
 			} else {
 				cmd = FuncRequest(LFUN_PRIMARY_SELECTION_PASTE,
@@ -535,21 +537,22 @@ void InsetTabular::doDispatch(LCursor & 
 
 	case LFUN_MOUSE_RELEASE:
 		//lyxerr << "# InsetTabular::MouseRelease\n" << bvcur << endl;
-		if (cmd.button() == mouse_button::button1) {
-			if (bvcur.selection())
-				theSelection().haveSelection(true);
-		} else if (cmd.button() == mouse_button::button3)
+		if (cmd.button() == mouse_button::button1)
+			cap::finishSelection(cur);
+		else if (cmd.button() == mouse_button::button3)
 			InsetTabularMailer(*this).showDialog(&cur.bv());
 		break;
 
 	case LFUN_CELL_BACKWARD:
 		movePrevCell(cur);
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		break;
 
 	case LFUN_CELL_FORWARD:
 		moveNextCell(cur);
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		break;
 
 	case LFUN_CHAR_FORWARD_SELECT:
@@ -558,7 +561,7 @@ void InsetTabular::doDispatch(LCursor & 
 		if (!cur.result().dispatched()) {
 			isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur);
 			if (cmd.action == LFUN_CHAR_FORWARD_SELECT)
-				theSelection().haveSelection(cur.selection());
+				cap::finishSelection(cur);
 			if (sl == cur.top())
 				cmd = FuncRequest(LFUN_FINISHED_RIGHT);
 			else
@@ -572,7 +575,7 @@ void InsetTabular::doDispatch(LCursor & 
 		if (!cur.result().dispatched()) {
 			isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur);
 			if (cmd.action == LFUN_CHAR_BACKWARD_SELECT)
-				theSelection().haveSelection(cur.selection());
+				cap::finishSelection(cur);
 			if (sl == cur.top())
 				cmd = FuncRequest(LFUN_FINISHED_LEFT);
 			else
@@ -595,7 +598,7 @@ void InsetTabular::doDispatch(LCursor & 
 					cur.bv().textMetrics(cell(cur.idx())->getText(0));
 				cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX());
 				if (cmd.action == LFUN_DOWN_SELECT)
-					theSelection().haveSelection(cur.selection());
+					cap::finishSelection(cur);
 			}
 		if (sl == cur.top()) {
 			// we trick it to go to the RIGHT after leaving the
@@ -622,7 +625,7 @@ void InsetTabular::doDispatch(LCursor & 
 					tm.parMetrics(cur.lastpit());
 				cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX());
 				if (cmd.action == LFUN_UP_SELECT)
-					theSelection().haveSelection(cur.selection());
+					cap::finishSelection(cur);
 			}
 		if (sl == cur.top()) {
 			cmd = FuncRequest(LFUN_FINISHED_UP);
@@ -746,7 +749,7 @@ void InsetTabular::doDispatch(LCursor & 
 	case LFUN_PASTE:
 		if (tabularStackDirty() && theClipboard().isInternal()) {
 			recordUndoInset(cur, Undo::INSERT);
-			pasteSelection(cur);
+			pasteClipboard(cur);
 			break;
 		}
 		cell(cur.idx())->dispatch(cur, cmd);
@@ -1203,6 +1206,7 @@ InsetBase * InsetTabular::editXY(LCursor
 {
 	//lyxerr << "InsetTabular::editXY: " << this << endl;
 	cur.selection() = false;
+	cap::finishSelection(cur);
 	cur.push(*this);
 	cur.idx() = getNearestCell(cur.bv(), x, y);
 	resetPos(cur);
@@ -1475,6 +1479,7 @@ void InsetTabular::tabularFeatures(LCurs
 		cur.pit() = 0;
 		cur.pos() = 0;
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		break;
 
 	case LyXTabular::DELETE_COLUMN:
@@ -1486,6 +1491,7 @@ void InsetTabular::tabularFeatures(LCurs
 		cur.pit() = 0;
 		cur.pos() = 0;
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		break;
 
 	case LyXTabular::COPY_ROW:
@@ -1606,6 +1612,7 @@ void InsetTabular::tabularFeatures(LCurs
 		cur.pit() = 0;
 		cur.pos() = 0;
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		break;
 	}
 
@@ -1827,7 +1834,7 @@ bool InsetTabular::copySelection(LCursor
 }
 
 
-bool InsetTabular::pasteSelection(LCursor & cur)
+bool InsetTabular::pasteClipboard(LCursor & cur)
 {
 	if (!paste_tabular)
 		return false;
@@ -1889,7 +1896,7 @@ void InsetTabular::cutSelection(LCursor 
 	if (cur.pos() > cur.lastpos())
 		cur.pos() = cur.lastpos();
 	cur.clearSelection();
-	theSelection().haveSelection(false);
+	cap::finishSelection(cur);
 }
 
 
Index: src/insets/insettabular.h
===================================================================
--- src/insets/insettabular.h	(Revision 16668)
+++ src/insets/insettabular.h	(Arbeitskopie)
@@ -179,7 +179,7 @@ private:
 	///
 	bool copySelection(LCursor & cur);
 	///
-	bool pasteSelection(LCursor & cur);
+	bool pasteClipboard(LCursor & cur);
 	///
 	void cutSelection(LCursor & cur);
 	///
Index: src/mathed/InsetMathGrid.C
===================================================================
--- src/mathed/InsetMathGrid.C	(Revision 16669)
+++ src/mathed/InsetMathGrid.C	(Arbeitskopie)
@@ -1078,6 +1078,7 @@ void InsetMathGrid::doDispatch(LCursor &
 	case LFUN_CELL_BACKWARD:
 		// See below.
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		if (!idxPrev(cur)) {
 			cmd = FuncRequest(LFUN_FINISHED_LEFT);
 			cur.undispatched();
@@ -1088,6 +1089,7 @@ void InsetMathGrid::doDispatch(LCursor &
 		// Can't handle selection by additional 'shift' as this is
 		// hard bound to LFUN_CELL_BACKWARD
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		if (!idxNext(cur)) {
 			cmd = FuncRequest(LFUN_FINISHED_RIGHT);
 			cur.undispatched();
Index: src/mathed/InsetMathHull.C
===================================================================
--- src/mathed/InsetMathHull.C	(Revision 16668)
+++ src/mathed/InsetMathHull.C	(Arbeitskopie)
@@ -1398,7 +1398,7 @@ bool InsetMathHull::searchForward(Buffer
 		MathArray const & a = top.asInsetMath()->cell(top.idx_);
 		if (a.matchpart(ar, top.pos_)) {
 			bv->cursor().setSelection(it, ar.size());
-			theSelection().haveSelection(bv->cursor().selection());
+			cap::finishSelection(bv->cursor());
 			current = it;
 			top.pos_ += ar.size();
 			bv->update();
Index: src/mathed/InsetMathNest.C
===================================================================
--- src/mathed/InsetMathNest.C	(Revision 16669)
+++ src/mathed/InsetMathNest.C	(Arbeitskopie)
@@ -596,7 +596,7 @@ void InsetMathNest::doDispatch(LCursor &
 		cur.selection() = true;
 		cur.pos() = cur.lastpos();
 		cur.idx() = cur.lastidx();
-		theSelection().haveSelection(true);
+		cap::finishSelection(cur);
 		break;
 
 	case LFUN_PARAGRAPH_UP:
@@ -1187,10 +1187,11 @@ void InsetMathNest::lfunMousePress(LCurs
 		//cur.noUpdate();
 	} else if (cmd.button() == mouse_button::button2) {
 		MathArray ar;
-		if (cur.selection()) {
+		if (cap::selection()) {
 			// See comment in LyXText::dispatch why we do this
-			cap::copySelectionToStack(bv.cursor());
-			asArray(bv.cursor().selectionAsString(false), ar);
+			cap::copySelectionToStack();
+			cmd = FuncRequest(LFUN_PASTE, "0");
+			doDispatch(cur, cmd);
 		} else
 			asArray(theSelection().get(), ar);
 
@@ -1221,8 +1222,7 @@ void InsetMathNest::lfunMouseRelease(LCu
 	//lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl;
 
 	if (cmd.button() == mouse_button::button1) {
-		if (cur.bv().cursor().selection())
-			theSelection().haveSelection(true);
+		cap::finishSelection(cur);
 		if (!cur.selection())
 			cur.noUpdate();
 		return;
@@ -1343,6 +1343,7 @@ bool InsetMathNest::interpretChar(LCurso
 	// just clear selection on pressing the space bar
 	if (cur.selection() && c == ' ') {
 		cur.selection() = false;
+		cap::finishSelection(cur);
 		return true;
 	}
 
Index: src/CutAndPaste.C
===================================================================
--- src/CutAndPaste.C	(Revision 16669)
+++ src/CutAndPaste.C	(Arbeitskopie)
@@ -72,6 +72,7 @@ typedef std::pair<pit_type, int> PitPosP
 typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack;
 
 CutStack theCuts(10);
+CutStack selectionBuffer(1);
 
 // store whether the tabular stack is newer than the normal copy stack
 // FIXME: this is a workaround for bug 1919. Should be removed for 1.5,
@@ -102,8 +103,8 @@ bool checkPastePossible(int index)
 
 
 pair<PitPosPair, pit_type>
-pasteSelectionHelper(LCursor & cur, ParagraphList const & parlist,
-		     textclass_type textclass, ErrorList & errorlist)
+pasteHelper(LCursor & cur, ParagraphList const & parlist,
+            textclass_type textclass, ErrorList & errorlist)
 {
 	Buffer const & buffer = cur.buffer();
 	pit_type pit = cur.pit();
@@ -342,7 +343,7 @@ void putClipboard(ParagraphList const & 
 
 void copySelectionHelper(Buffer const & buf, ParagraphList & pars,
 	pit_type startpit, pit_type endpit,
-	int start, int end, textclass_type tc)
+	int start, int end, textclass_type tc, CutStack & cutstack)
 {
 	BOOST_ASSERT(0 <= start && start <= pars[startpit].size());
 	BOOST_ASSERT(0 <= end && end <= pars[endpit].size());
@@ -376,7 +377,7 @@ void copySelectionHelper(Buffer const & 
 	// again, do not track deletion
 	front.eraseChars(0, start, false);
 
-	theCuts.push(make_pair(paragraphs, tc));
+	cutstack.push(make_pair(paragraphs, tc));
 }
 
 } // namespace anon
@@ -499,6 +500,8 @@ size_type numberOfSelections()
 
 void cutSelection(LCursor & cur, bool doclear, bool realcut)
 {
+	lyxerr << "cap::cutSelection: `"
+	       << to_utf8(cur.selectionAsString(true)) << "'." << endl;
 	// This doesn't make sense, if there is no selection
 	if (!cur.selection())
 		return;
@@ -523,7 +526,7 @@ void cutSelection(LCursor & cur, bool do
 				text->paragraphs(),
 				begpit, endpit,
 				cur.selBegin().pos(), endpos,
-				bp.textclass);
+				bp.textclass, theCuts);
 			// Stuff what we got on the clipboard.
 			// Even if there is no selection.
 			putClipboard(theCuts[0].first, theCuts[0].second,
@@ -579,17 +582,13 @@ void copySelection(LCursor & cur)
 }
 
 
-void copySelection(LCursor & cur, docstring const & plaintext)
-{
-	copySelectionToStack(cur);
-
-	// stuff the selection onto the X clipboard, from an explicit copy request
-	putClipboard(theCuts[0].first, theCuts[0].second, plaintext);
-}
-
+namespace {
 
-void copySelectionToStack(LCursor & cur)
+void copySelectionToStack(LCursor & cur, CutStack & cutstack)
 {
+	lyxerr << "cap::copySelectionToStack: `"
+	       << to_utf8(cur.selectionAsString(true)) << "'." << endl;
+
 	// this doesn't make sense, if there is no selection
 	if (!cur.selection())
 		return;
@@ -610,7 +609,7 @@ void copySelectionToStack(LCursor & cur)
 			++pos;
 
 		copySelectionHelper(cur.buffer(), pars, par, cur.selEnd().pit(),
-			pos, cur.selEnd().pos(), cur.buffer().params().textclass);
+			pos, cur.selEnd().pos(), cur.buffer().params().textclass, cutstack);
 	}
 
 	if (cur.inMathed()) {
@@ -621,10 +620,49 @@ void copySelectionToStack(LCursor & cur)
 		par.layout(bp.getLyXTextClass().defaultLayout());
 		par.insert(0, grabSelection(cur), LyXFont(), Change(Change::UNCHANGED));
 		pars.push_back(par);
-		theCuts.push(make_pair(pars, bp.textclass));
+		cutstack.push(make_pair(pars, bp.textclass));
 	}
-	// tell tabular that a recent copy happened
-	dirtyTabularStack(false);
+}
+
+}
+
+
+void copySelectionToStack()
+{
+	if (!selectionBuffer.empty())
+		theCuts.push(selectionBuffer[0]);
+}
+
+
+void copySelection(LCursor & cur, docstring const & plaintext)
+{
+	copySelectionToStack(cur, theCuts);
+
+	// stuff the selection onto the X clipboard, from an explicit copy request
+	putClipboard(theCuts[0].first, theCuts[0].second, plaintext);
+}
+
+
+void finishSelection(LCursor & cur)
+{
+	lyxerr << "cap::finishSelection: `"
+	       << to_utf8(cur.selectionAsString(true)) << "'." << endl;
+	if (cur.selection())
+		copySelectionToStack(cur, selectionBuffer);
+	// tell X whether we now have a valid selection
+	theSelection().haveSelection(cur.selection());
+}
+
+
+bool selection()
+{
+	return !selectionBuffer.empty();
+}
+
+
+void clearSelection()
+{
+	selectionBuffer.clear();
 }
 
 
@@ -647,8 +685,7 @@ void pasteParagraphList(LCursor & cur, P
 		PitPosPair ppp;
 
 		boost::tie(ppp, endpit) =
-			pasteSelectionHelper(cur, parlist,
-					     textclass, errorList);
+			pasteHelper(cur, parlist, textclass, errorList);
 		updateLabels(cur.buffer());
 		cur.clearSelection();
 		text->setCursor(cur.top(), ppp.first, ppp.second);
@@ -659,11 +696,25 @@ void pasteParagraphList(LCursor & cur, P
 }
 
 
+void pasteFromStack(LCursor & cur, ErrorList & errorList, size_t sel_index)
+{
+	// this does not make sense, if there is nothing to paste
+	if (!checkPastePossible(sel_index))
+		return;
+
+	recordUndo(cur);
+	pasteParagraphList(cur, theCuts[sel_index].first,
+			   theCuts[sel_index].second, errorList);
+	cur.setSelection();
+	finishSelection(cur);
+}
+
+
 void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs)
 {
 	// Use internal clipboard if it is the most recent one
 	if (theClipboard().isInternal()) {
-		pasteSelection(cur, errorList, 0);
+		pasteClipboard(cur, errorList, 0);
 		return;
 	}
 
@@ -695,16 +746,15 @@ void pasteClipboard(LCursor & cur, Error
 }
 
 
-void pasteSelection(LCursor & cur, ErrorList & errorList, size_t sel_index)
+void pasteSelection(LCursor & cur, ErrorList & errorList)
 {
-	// this does not make sense, if there is nothing to paste
-	if (!checkPastePossible(sel_index))
+	if (selectionBuffer.empty())
 		return;
-
 	recordUndo(cur);
-	pasteParagraphList(cur, theCuts[sel_index].first,
-			   theCuts[sel_index].second, errorList);
+	pasteParagraphList(cur, selectionBuffer[0].first,
+	                   selectionBuffer[0].second, errorList);
 	cur.setSelection();
+	finishSelection(cur);
 }
 
 
@@ -734,6 +784,7 @@ void replaceSelectionWithString(LCursor 
 		cur.setSelection(selbeg, -int(str.length()));
 	} else
 		cur.setSelection(selbeg, str.length());
+	finishSelection(cur);
 }
 
 
Index: src/CutAndPaste.h
===================================================================
--- src/CutAndPaste.h	(Revision 16669)
+++ src/CutAndPaste.h	(Arbeitskopie)
@@ -68,15 +68,24 @@ void copySelection(LCursor & cur);
  *        clipboard
  */
 void copySelection(LCursor & cur, docstring const & plaintext);
-/// Push the current selection to the cut buffer.
-void copySelectionToStack(LCursor & cur);
+/// Push the selection buffer to the cut buffer.
+void copySelectionToStack();
+/// Store the current selection in the internal selection buffer
+void finishSelection(LCursor & cur);
+/// Is a selection available in our selection buffer?
+bool selection();
+/// Clear our selection buffer
+void clearSelection();
+/// Paste the current selection at \p cur
+/// Does handle undo. Does only work in text, not mathed.
+void pasteSelection(LCursor & cur, ErrorList &);
 /// Replace the current selection with the clipboard contents (internal or
 /// external: which is newer)
 /// Does handle undo. Does only work in text, not mathed.
 void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs = true);
 /// Replace the current selection with cut buffer \c sel_index
 /// Does handle undo. Does only work in text, not mathed.
-void pasteSelection(LCursor & cur, ErrorList &, size_t sel_index = 0);
+void pasteFromStack(LCursor & cur, ErrorList & errorList, size_t sel_index);
 
 /// Paste the paragraph list \p parlist at the position given by \p cur.
 /// Does not handle undo. Does only work in text, not mathed.
Index: src/text3.C
===================================================================
--- src/text3.C	(Revision 16669)
+++ src/text3.C	(Arbeitskopie)
@@ -76,8 +76,8 @@ namespace lyx {
 
 using cap::copySelection;
 using cap::cutSelection;
+using cap::pasteFromStack;
 using cap::pasteClipboard;
-using cap::pasteSelection;
 using cap::replaceSelection;
 
 using support::isStrUnsignedInt;
@@ -122,7 +122,7 @@ namespace {
 	{
 		if (selecting || cur.mark())
 			cur.setSelection();
-		theSelection().haveSelection(cur.selection());
+		cap::finishSelection(cur);
 		cur.bv().switchKeyMap();
 	}
 
@@ -762,7 +762,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 			pasteClipboard(cur, bv->buffer()->errorList("Paste"));
 		else {
 			string const arg(to_utf8(cmd.argument()));
-			pasteSelection(cur, bv->buffer()->errorList("Paste"),
+			pasteFromStack(cur, bv->buffer()->errorList("Paste"),
 					isStrUnsignedInt(arg) ?
 						convert<unsigned int>(arg) :
 						0);
@@ -941,7 +941,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 			cursorEnd(cur);
 			cur.setSelection();
 			bv->cursor() = cur;
-			theSelection().haveSelection(cur.selection());
+			cap::finishSelection(cur);
 		}
 		break;
 
@@ -949,7 +949,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 		if (cmd.button() == mouse_button::button1) {
 			selectWord(cur, WHOLE_WORD_STRICT);
 			bv->cursor() = cur;
-			theSelection().haveSelection(cur.selection());
+			cap::finishSelection(cur);
 		}
 		break;
 
@@ -964,15 +964,11 @@ void LyXText::dispatch(LCursor & cur, Fu
 		// it could get cleared on the unlocking of the inset so
 		// we have to check this first
 		bool paste_internally = false;
-		if (cmd.button() == mouse_button::button2 && cur.selection()) {
-			// Copy the selection to the clipboard stack. This
-			// is done for two reasons:
-			// - We want it to appear in the "Edit->Paste recent"
-			//   menu.
-			// - We can then use the normal copy/paste machinery
-			//   instead of theSelection().get() to preserve
-			//   formatting of the pasted stuff.
-			cap::copySelectionToStack(cur.bv().cursor());
+		if (cmd.button() == mouse_button::button2 && cap::selection()) {
+			// Copy the selection buffer to the clipboard
+			// stack, because we want it to appear in the
+			// "Edit->Paste recent" menu.
+			cap::copySelectionToStack();
 			paste_internally = true;
 		}
 
@@ -983,9 +979,13 @@ void LyXText::dispatch(LCursor & cur, Fu
 		// if there is a local selection in the current buffer,
 		// insert this
 		if (cmd.button() == mouse_button::button2) {
-			if (paste_internally)
-				lyx::dispatch(FuncRequest(LFUN_PASTE, "0"));
-			else
+			if (paste_internally) {
+				cap::pasteSelection(cur, bv->buffer()->errorList("Paste"));
+				bv->buffer()->errors("Paste");
+				cur.clearSelection(); // bug 393
+				bv->switchKeyMap();
+				finishUndo();
+			} else
 				lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph"));
 		}
 
@@ -1042,10 +1042,12 @@ void LyXText::dispatch(LCursor & cur, Fu
 		if (cmd.button() == mouse_button::button2)
 			break;
 
-		// finish selection
 		if (cmd.button() == mouse_button::button1) {
-			if (cur.selection())
-				theSelection().haveSelection(true);
+			// finish selection
+			LCursor & bvcur = cur.bv().cursor();
+			bvcur.setCursor(cur);
+			bvcur.selection() = true;
+			cap::finishSelection(bvcur);
 			needsUpdate = false;
 			cur.noUpdate();
 		}
@@ -1064,13 +1066,9 @@ void LyXText::dispatch(LCursor & cur, Fu
 		// "auto_region_delete", which defaults to
 		// true (on).
 
-		if (lyxrc.auto_region_delete) {
+		if (lyxrc.auto_region_delete)
 			if (cur.selection())
 				cutSelection(cur, false, false);
-				// cutSelection clears the X selection.
-			else
-				theSelection().haveSelection(false);
-		}
 
 		cur.clearSelection();
 		LyXFont const old_font = real_current_font;
@@ -1472,6 +1470,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 	case LFUN_ESCAPE:
 		if (cur.selection()) {
 			cur.selection() = false;
+			cap::finishSelection(cur);
 		} else {
 			cur.undispatched();
 			cmd = FuncRequest(LFUN_FINISHED_RIGHT);
Index: src/lyxfind.C
===================================================================
--- src/lyxfind.C	(Revision 16668)
+++ src/lyxfind.C	(Arbeitskopie)
@@ -29,7 +29,6 @@
 #include "undo.h"
 
 #include "frontends/Alert.h"
-#include "frontends/Selection.h"
 
 #include "support/convert.h"
 #include "support/docstream.h"
@@ -357,7 +356,7 @@ bool findNextChange(BufferView * bv)
 	// Now put cursor to end of selection:
 	bv->cursor().setCursor(cur);
 	bv->cursor().setSelection();
-	theSelection().haveSelection(bv->cursor().selection());
+	cap::finishSelection(bv->cursor());
 	// if we used a lfun like in find/replace, dispatch would do
 	// that for us
 	bv->update();
Index: src/BufferView.C
===================================================================
--- src/BufferView.C	(Revision 16668)
+++ src/BufferView.C	(Arbeitskopie)
@@ -63,7 +63,6 @@
 #include "frontends/Alert.h"
 #include "frontends/FileDialog.h"
 #include "frontends/FontMetrics.h"
-#include "frontends/Selection.h"
 
 #include "graphics/Previews.h"
 
@@ -196,7 +195,7 @@ void BufferView::setBuffer(Buffer * b)
 			cursor_.resetAnchor();
 			cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset())));
 			cursor_.setSelection();
-			theSelection().haveSelection(cursor_.selection());
+			cap::finishSelection(cursor_);
 		}
 	}
 
@@ -1001,6 +1000,7 @@ docstring const BufferView::requestSelec
 
 	LCursor & cur = cursor_;
 
+	// FIXME should we not return the selection buffer in CutAndPaste.C?
 	if (!cur.selection()) {
 		xsel_cache_.set = false;
 		return docstring();
@@ -1023,6 +1023,10 @@ void BufferView::clearSelection()
 {
 	if (buffer_) {
 		cursor_.clearSelection();
+		// Clear the selection buffer. Otherwise a subsequent
+		// middle-mouse-button paste would use the selection buffer,
+		// not the more current external selection.
+		cap::clearSelection();
 		xsel_cache_.set = false;
 		// The buffer did not really change, but this causes the
 		// redraw we need because we cleared the selection above.
@@ -1309,7 +1313,7 @@ void BufferView::putSelectionAt(DocItera
 			cursor_.setSelection(cursor_, -length);
 		} else
 			cursor_.setSelection(cursor_, length);
-		theSelection().haveSelection(cursor_.selection());
+		cap::finishSelection(cursor_);
 	}
 }
 
Index: src/text.C
===================================================================
--- src/text.C	(Revision 16668)
+++ src/text.C	(Arbeitskopie)
@@ -53,7 +53,6 @@
 
 #include "frontends/FontMetrics.h"
 #include "frontends/Painter.h"
-#include "frontends/Selection.h"
 
 #include "insets/insettext.h"
 #include "insets/insetbibitem.h"
@@ -829,7 +828,7 @@ void LyXText::selectWord(LCursor & cur, 
 	cur.resetAnchor();
 	setCursor(cur, to.pit(), to.pos());
 	cur.setSelection();
-	theSelection().haveSelection(cur.selection());
+	cap::finishSelection(cur);
 }
 
 

Reply via email to