Am Mittwoch, 3. Januar 2007 15:56 schrieb Abdelrazak Younes:
> Georg Baum wrote:
> > Almost all of the remaining stuff looks wrong, too. Can't you simply 
fill 
> > the selection at the right time without touching LFUN_COPY?
> 
> Of course I can. But then it will not be possible to keep the LyX 
> formatting.

Sure it will. There are 1000 other solutions than changing LFUN_COPY to 
keep LyX formatting, for example the existing one. If you don't like that 
the internal clipboard is currently filled with the selection, then you 
can do something like the attached. It does not work yet because the 
selection is empty on LFUN_MOUSE_RELEASE, but I am pretty sure that this 
can be fixed and the principal approach works.

> It is still the same misunderstanding: you want to limit the X Selection 
> to a single unformatted string and I want rich contents.

As far as frontend::Selection is concerned: Yes, that should be a single 
unformatted string. frontend::Selection should only be an interface to the 
system selection (either the real one or a faked one), not more and not 
less. The same holds for frontend::Clipboard. The only difference is that 
frontend::Clipboard will hopefully be able to store and retrieve LyX 
contents in the future. That is OK, since it can be supported by the 
system clipboard as well.

> Noted that as  
> it is now, middle-mouse pasting will always keep the formatting because 
> of the 'paste_internally' boolean. If you want to be coherent with 
> yourself, we should get rid of that feature also and only use the X 
> selection.

One could indeed argue like that, but that is not what I am doing. What I 
want is:

- A clear interface to the system selection. That is the 
frontend::Selection class you introduced.
- A clear interface to the system clipboard. That is the 
frontend::Clipboard class you introduced.
- A well defined set of lfuns that do not mix different concepts.

As long as these requirements are fulfilled I don't care very much whether 
the middle mouse button preserves formatting if it pastes something from 
within LyX or not. I do care about the format of the external selection: 
That should always be plain text, definitely not LyX syntax.


Georg
Index: src/insets/insettabular.C
===================================================================
--- src/insets/insettabular.C	(Revision 16479)
+++ src/insets/insettabular.C	(Arbeitskopie)
@@ -735,7 +735,7 @@ void InsetTabular::doDispatch(LCursor & 
 	case LFUN_PASTE:
 		if (hasPasteBuffer() && tabularStackDirty()) {
 			recordUndoInset(cur, Undo::INSERT);
-			pasteSelection(cur);
+			pasteClipboard(cur);
 			break;
 		}
 		cell(cur.idx())->dispatch(cur, cmd);
@@ -1812,7 +1812,7 @@ bool InsetTabular::copySelection(LCursor
 }
 
 
-bool InsetTabular::pasteSelection(LCursor & cur)
+bool InsetTabular::pasteClipboard(LCursor & cur)
 {
 	if (!paste_tabular)
 		return false;
Index: src/insets/insettabular.h
===================================================================
--- src/insets/insettabular.h	(Revision 16479)
+++ src/insets/insettabular.h	(Arbeitskopie)
@@ -181,7 +181,7 @@ private:
 	///
 	bool copySelection(LCursor & cur);
 	///
-	bool pasteSelection(LCursor & cur);
+	bool pasteClipboard(LCursor & cur);
 	///
 	void cutSelection(LCursor & cur);
 	///
Index: src/CutAndPaste.C
===================================================================
--- src/CutAndPaste.C	(Revision 16479)
+++ src/CutAndPaste.C	(Arbeitskopie)
@@ -46,6 +46,7 @@
 #include "support/lstrings.h"
 
 #include "frontends/Clipboard.h"
+#include "frontends/Selection.h"
 
 #include <boost/tuple/tuple.hpp>
 
@@ -70,6 +71,7 @@ typedef std::pair<pit_type, int> PitPosP
 typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack;
 
 CutStack theCuts(10);
+CutStack selection(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,
@@ -100,8 +102,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();
@@ -325,7 +327,7 @@ PitPosPair eraseSelectionHelper(BufferPa
 
 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());
@@ -359,7 +361,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
@@ -492,16 +494,6 @@ void cutSelection(LCursor & cur, bool do
 	if (cur.inTexted()) {
 		LyXText * text = cur.text();
 		BOOST_ASSERT(text);
-		// Stuff what we got on the clipboard. Even if there is no selection.
-
-		// There is a problem with having the stuffing here in that the
-		// larger the selection the slower LyX will get. This can be
-		// solved by running the line below only when the selection has
-		// finished. The solution used currently just works, to make it
-		// faster we need to be more clever and probably also have more
-		// calls to theSelection().put. (Lgb)
-//		theSelection().put(cur.selectionAsString(true));
-
 
 		// make sure that the depth behind the selection are restored, too
 		recordUndoSelection(cur);
@@ -516,7 +508,7 @@ void cutSelection(LCursor & cur, bool do
 				text->paragraphs(),
 				begpit, endpit,
 				cur.selBegin().pos(), endpos,
-				bp.textclass);
+				bp.textclass, theCuts);
 		}
 
 		boost::tie(endpit, endpos) =
@@ -561,11 +553,10 @@ void cutSelection(LCursor & cur, bool do
 }
 
 
-void copySelection(LCursor & cur)
-{
-	// stuff the selection onto the X clipboard, from an explicit copy request
-	theClipboard().put(cur.selectionAsString(true));
+namespace {
 
+void copySelection(LCursor & cur, CutStack & cutstack)
+{
 	// this doesn't make sense, if there is no selection
 	if (!cur.selection())
 		return;
@@ -586,7 +577,7 @@ void copySelection(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()) {
@@ -597,8 +588,28 @@ void copySelection(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));
 	}
+}
+
+}
+
+
+void finishSelection(LCursor & cur)
+{
+	// push the selection to the X selection
+	theSelection().put(cur.selectionAsString(true));
+
+	copySelection(cur, selection);
+}
+
+
+void copySelection(LCursor & cur)
+{
+	// stuff the selection onto the X clipboard, from an explicit copy request
+	theClipboard().put(cur.selectionAsString(true));
+
+	copySelection(cur, theCuts);
 	// tell tabular that a recent copy happened
 	dirtyTabularStack(false);
 }
@@ -623,8 +634,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);
@@ -635,7 +645,15 @@ void pasteParagraphList(LCursor & cur, P
 }
 
 
-void pasteSelection(LCursor & cur, ErrorList & errorList, size_t sel_index)
+void pasteSelection(LCursor & cur, ErrorList & errorList)
+{
+	recordUndo(cur);
+	pasteParagraphList(cur, selection[0].first, selection[0].second, errorList);
+	cur.setSelection();
+}
+
+
+void pasteClipboard(LCursor & cur, ErrorList & errorList, size_t sel_index)
 {
 	// this does not make sense, if there is nothing to paste
 	if (!checkPastePossible(sel_index))
Index: src/CutAndPaste.h
===================================================================
--- src/CutAndPaste.h	(Revision 16479)
+++ src/CutAndPaste.h	(Arbeitskopie)
@@ -51,10 +51,15 @@ void replaceSelection(LCursor & cur);
 
 ///
 void cutSelection(LCursor & cur, bool doclear = true, bool realcut = true);
-///
+/// Copy the current selection to the local and the system clipboard
 void copySelection(LCursor & cur);
-///
-void pasteSelection(LCursor & cur, ErrorList &, size_t sel_index = 0);
+/// Store the current selection in the internal selection buffer and push
+/// it to the X server
+void finishSelection(LCursor & cur);
+/// Paste the current selection at \p cur
+void pasteSelection(LCursor & cur, ErrorList &);
+/// Paste the clipboard with index \p sel_index at \p cur
+void pasteClipboard(LCursor & cur, ErrorList &, size_t sel_index = 0);
 
 /// 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/frontends/qt4/GuiSelection.C
===================================================================
--- src/frontends/qt4/GuiSelection.C	(Revision 16479)
+++ src/frontends/qt4/GuiSelection.C	(Arbeitskopie)
@@ -30,18 +30,6 @@ using std::endl;
 namespace lyx {
 namespace frontend {
 
-void GuiSelection::haveSelection(bool own)
-{
-	if (!qApp->clipboard()->supportsSelection())
-		return;
-
-	if (own)
-		qApp->clipboard()->setText(QString(), QClipboard::Selection);
-	// We don't need to do anything if own = false, as this case is
-	// handled by QT.
-}
-
-
 docstring const GuiSelection::get() const
 {
 	QString const str = qApp->clipboard()->text(QClipboard::Selection);
Index: src/frontends/qt4/GuiSelection.h
===================================================================
--- src/frontends/qt4/GuiSelection.h	(Revision 16479)
+++ src/frontends/qt4/GuiSelection.h	(Arbeitskopie)
@@ -30,7 +30,6 @@ public:
 	/** Selection overloaded methods
 	 */
 	//@{
-	void haveSelection(bool own);
 	docstring const get() const;
 	void put(docstring const & str);
 	bool isInternal() const;
Index: src/frontends/Selection.h
===================================================================
--- src/frontends/Selection.h	(Revision 16479)
+++ src/frontends/Selection.h	(Arbeitskopie)
@@ -27,8 +27,6 @@ class Selection
 public:
 	virtual ~Selection() {}
 
-	/// Tell the window system whether we have a selection.
-	virtual void haveSelection(bool) = 0;
 	/**
 	 * Get the X selection contents.
 	 * This is a noop on systems that don't have a selection.
Index: src/text3.C
===================================================================
--- src/text3.C	(Revision 16479)
+++ src/text3.C	(Arbeitskopie)
@@ -76,7 +76,7 @@ namespace lyx {
 
 using cap::copySelection;
 using cap::cutSelection;
-using cap::pasteSelection;
+using cap::pasteClipboard;
 using cap::replaceSelection;
 
 using support::isStrUnsignedInt;
@@ -119,10 +119,10 @@ namespace {
 
 	void moveCursor(LCursor & cur, bool selecting)
 	{
-		if (selecting || cur.mark())
+		if (selecting || cur.mark()) {
 			cur.setSelection();
-		if (!cur.selection())
-			theSelection().haveSelection(false);
+			cap::finishSelection(cur);
+		}
 		cur.bv().switchKeyMap();
 	}
 
@@ -757,10 +757,10 @@ void LyXText::dispatch(LCursor & cur, Fu
 		cur.message(_("Paste"));
 		cap::replaceSelection(cur);
 		if (isStrUnsignedInt(to_utf8(cmd.argument())))
-			pasteSelection(cur, bv->buffer()->errorList("Paste"),
+			pasteClipboard(cur, bv->buffer()->errorList("Paste"),
 			convert<unsigned int>(to_utf8(cmd.argument())));
 		else
-			pasteSelection(cur, bv->buffer()->errorList("Paste"),
+			pasteClipboard(cur, bv->buffer()->errorList("Paste"),
 			0);
 		bv->buffer()->errors("Paste");
 		cur.clearSelection(); // bug 393
@@ -932,7 +932,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 			cursorEnd(cur);
 			cur.setSelection();
 			bv->cursor() = cur;
-			theSelection().haveSelection(cur.selection());
+			cap::finishSelection(cur);
 		}
 		break;
 
@@ -940,7 +940,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;
 
@@ -954,11 +954,7 @@ void LyXText::dispatch(LCursor & cur, Fu
 		// We do this here as if the selection was inside an inset
 		// 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()) {
-			lyx::dispatch(FuncRequest(LFUN_COPY));
-			paste_internally = true;
-		}
+		bool const paste_internally = cmd.button() == mouse_button::button2 && cur.selection();
 
 		// we have to update after dePM triggered
 		bool update = bv->mouseSetCursor(cur);
@@ -967,9 +963,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));
-			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"));
 		}
 
@@ -1028,8 +1028,10 @@ void LyXText::dispatch(LCursor & cur, Fu
 
 		// finish selection
 		if (cmd.button() == mouse_button::button1) {
-			if (cur.selection())
-				theSelection().haveSelection(cur.selection());
+			lyxerr << "cursor: " << cur << endl;
+			cur.setSelection();
+			lyxerr << "finish selection: `" << to_utf8(cur.selectionAsString(true)) << "'." << endl;
+			cap::finishSelection(cur);
 			needsUpdate = false;
 			cur.noUpdate();
 		}
@@ -1048,11 +1050,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);
-			theSelection().haveSelection(false);
-		}
 
 		cur.clearSelection();
 		LyXFont const old_font = real_current_font;

Reply via email to