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;