Persistent-selection (and fix bug 3162)

* src/CutAndPaste.h/C: add selectionBuffer to save selected text
	* src/text3.C: proper handling of paste
	* src/lyxfind.C: save selection
	* src/BufferView.C: save selection
	* src/text.C: save selection
	* src/cursor.C: save selection
	* src/insets/insettabular.C: save selection
	* src/mathed/InsetMathGrid.C: save selection
	* src/mathed/InsetMathHull.C: save selection
	* src/mathed/InsetMathNest.C: save selection


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17022 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Bo Peng 2007-02-02 03:10:15 +00:00
parent f44bc0a0d1
commit 8b56166641
12 changed files with 167 additions and 80 deletions

View File

@ -63,7 +63,6 @@
#include "frontends/Alert.h" #include "frontends/Alert.h"
#include "frontends/FileDialog.h" #include "frontends/FileDialog.h"
#include "frontends/FontMetrics.h" #include "frontends/FontMetrics.h"
#include "frontends/Selection.h"
#include "graphics/Previews.h" #include "graphics/Previews.h"
@ -209,7 +208,8 @@ void BufferView::setBuffer(Buffer * b)
cursor_.resetAnchor(); cursor_.resetAnchor();
cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset()))); cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset())));
cursor_.setSelection(); cursor_.setSelection();
theSelection().haveSelection(cursor_.selection()); // do not set selection to the new buffer because we
// only paste recent selection.
} }
} }
@ -1054,6 +1054,10 @@ void BufferView::clearSelection()
{ {
if (buffer_) { if (buffer_) {
cursor_.clearSelection(); 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; xsel_cache_.set = false;
// The buffer did not really change, but this causes the // The buffer did not really change, but this causes the
// redraw we need because we cleared the selection above. // redraw we need because we cleared the selection above.
@ -1342,7 +1346,7 @@ void BufferView::putSelectionAt(DocIterator const & cur,
cursor_.setSelection(cursor_, -length); cursor_.setSelection(cursor_, -length);
} else } else
cursor_.setSelection(cursor_, length); cursor_.setSelection(cursor_, length);
theSelection().haveSelection(cursor_.selection()); cap::saveSelection(cursor_);
} }
} }

View File

@ -73,6 +73,8 @@ typedef std::pair<pit_type, int> PitPosPair;
typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack; typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack;
CutStack theCuts(10); CutStack theCuts(10);
// persistent selection, cleared until the next selection
CutStack selectionBuffer(1);
// store whether the tabular stack is newer than the normal copy stack // 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, // FIXME: this is a workaround for bug 1919. Should be removed for 1.5,
@ -343,7 +345,7 @@ void putClipboard(ParagraphList const & paragraphs, textclass_type textclass,
void copySelectionHelper(Buffer const & buf, ParagraphList & pars, void copySelectionHelper(Buffer const & buf, ParagraphList & pars,
pit_type startpit, pit_type endpit, 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 <= start && start <= pars[startpit].size());
BOOST_ASSERT(0 <= end && end <= pars[endpit].size()); BOOST_ASSERT(0 <= end && end <= pars[endpit].size());
@ -377,7 +379,7 @@ void copySelectionHelper(Buffer const & buf, ParagraphList & pars,
// again, do not track deletion // again, do not track deletion
front.eraseChars(0, start, false); front.eraseChars(0, start, false);
theCuts.push(make_pair(paragraphs, tc)); cutstack.push(make_pair(paragraphs, tc));
} }
} // namespace anon } // namespace anon
@ -524,7 +526,7 @@ void cutSelection(LCursor & cur, bool doclear, bool realcut)
text->paragraphs(), text->paragraphs(),
begpit, endpit, begpit, endpit,
cur.selBegin().pos(), endpos, cur.selBegin().pos(), endpos,
bp.textclass); bp.textclass, theCuts);
// Stuff what we got on the clipboard. // Stuff what we got on the clipboard.
// Even if there is no selection. // Even if there is no selection.
putClipboard(theCuts[0].first, theCuts[0].second, putClipboard(theCuts[0].first, theCuts[0].second,
@ -580,16 +582,9 @@ void copySelection(LCursor & cur)
} }
void copySelection(LCursor & cur, docstring const & plaintext) namespace {
{
copySelectionToStack(cur);
// stuff the selection onto the X clipboard, from an explicit copy request void copySelectionToStack(LCursor & cur, CutStack & cutstack)
putClipboard(theCuts[0].first, theCuts[0].second, plaintext);
}
void copySelectionToStack(LCursor & cur)
{ {
// this doesn't make sense, if there is no selection // this doesn't make sense, if there is no selection
if (!cur.selection()) if (!cur.selection())
@ -611,7 +606,7 @@ void copySelectionToStack(LCursor & cur)
++pos; ++pos;
copySelectionHelper(cur.buffer(), pars, par, cur.selEnd().pit(), 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()) { if (cur.inMathed()) {
@ -622,10 +617,50 @@ void copySelectionToStack(LCursor & cur)
par.layout(bp.getLyXTextClass().defaultLayout()); par.layout(bp.getLyXTextClass().defaultLayout());
par.insert(0, grabSelection(cur), LyXFont(), Change(Change::UNCHANGED)); par.insert(0, grabSelection(cur), LyXFont(), Change(Change::UNCHANGED));
pars.push_back(par); 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 saveSelection(LCursor & cur)
{
lyxerr[Debug::ACTION] << "cap::saveSelection: `"
<< 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();
} }
@ -660,11 +695,25 @@ void pasteParagraphList(LCursor & cur, ParagraphList const & parlist,
} }
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();
saveSelection(cur);
}
void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs) void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs)
{ {
// Use internal clipboard if it is the most recent one // Use internal clipboard if it is the most recent one
if (theClipboard().isInternal()) { if (theClipboard().isInternal()) {
pasteSelection(cur, errorList, 0); pasteClipboard(cur, errorList, 0);
return; return;
} }
@ -696,15 +745,13 @@ void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs)
} }
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 (selectionBuffer.empty())
if (!checkPastePossible(sel_index))
return; return;
recordUndo(cur); recordUndo(cur);
pasteParagraphList(cur, theCuts[sel_index].first, pasteParagraphList(cur, selectionBuffer[0].first,
theCuts[sel_index].second, errorList); selectionBuffer[0].second, errorList);
cur.setSelection(); cur.setSelection();
} }
@ -735,6 +782,7 @@ void replaceSelectionWithString(LCursor & cur, docstring const & str, bool backw
cur.setSelection(selbeg, -int(str.length())); cur.setSelection(selbeg, -int(str.length()));
} else } else
cur.setSelection(selbeg, str.length()); cur.setSelection(selbeg, str.length());
saveSelection(cur);
} }

View File

@ -68,15 +68,24 @@ void copySelection(LCursor & cur);
* clipboard * clipboard
*/ */
void copySelection(LCursor & cur, docstring const & plaintext); void copySelection(LCursor & cur, docstring const & plaintext);
/// Push the current selection to the cut buffer. /// Push the selection buffer to the cut buffer.
void copySelectionToStack(LCursor & cur); void copySelectionToStack();
/// Store the current selection in the internal selection buffer
void saveSelection(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 /// Replace the current selection with the clipboard contents (internal or
/// external: which is newer) /// external: which is newer)
/// Does handle undo. Does only work in text, not mathed. /// Does handle undo. Does only work in text, not mathed.
void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs = true); void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs = true);
/// Replace the current selection with cut buffer \c sel_index /// Replace the current selection with cut buffer \c sel_index
/// Does handle undo. Does only work in text, not mathed. /// 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. /// Paste the paragraph list \p parlist at the position given by \p cur.
/// Does not handle undo. Does only work in text, not mathed. /// Does not handle undo. Does only work in text, not mathed.

View File

@ -41,8 +41,6 @@
#include "mathed/InsetMathScript.h" #include "mathed/InsetMathScript.h"
#include "mathed/MathMacroTable.h" #include "mathed/MathMacroTable.h"
#include "frontends/Selection.h"
#include "support/limited_stack.h" #include "support/limited_stack.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
@ -560,7 +558,7 @@ bool LCursor::selHandle(bool sel)
resetAnchor(); resetAnchor();
selection() = sel; selection() = sel;
theSelection().haveSelection(sel); cap::saveSelection(*this);
return true; return true;
} }

View File

@ -50,6 +50,7 @@ namespace lyx {
using cap::dirtyTabularStack; using cap::dirtyTabularStack;
using cap::tabularStackDirty; using cap::tabularStackDirty;
using cap::saveSelection;
using graphics::PreviewLoader; using graphics::PreviewLoader;
@ -501,12 +502,12 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
} }
if (cmd.button() == mouse_button::button2) { if (cmd.button() == mouse_button::button2) {
if (bvcur.selection()) { if (cap::selection()) {
// See comment in LyXText::dispatch why we // See comment in LyXText::dispatch why we
// do this // do this
// FIXME This does not use paste_tabular, // FIXME This does not use paste_tabular,
// another reason why paste_tabular should go. // another reason why paste_tabular should go.
cap::copySelectionToStack(bvcur); cap::copySelectionToStack();
cmd = FuncRequest(LFUN_PASTE, "0"); cmd = FuncRequest(LFUN_PASTE, "0");
} else { } else {
cmd = FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, cmd = FuncRequest(LFUN_PRIMARY_SELECTION_PASTE,
@ -537,7 +538,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
//lyxerr << "# InsetTabular::MouseRelease\n" << bvcur << endl; //lyxerr << "# InsetTabular::MouseRelease\n" << bvcur << endl;
if (cmd.button() == mouse_button::button1) { if (cmd.button() == mouse_button::button1) {
if (bvcur.selection()) if (bvcur.selection())
theSelection().haveSelection(true); saveSelection(bvcur);// theSelection().haveSelection(true);
} else if (cmd.button() == mouse_button::button3) } else if (cmd.button() == mouse_button::button3)
InsetTabularMailer(*this).showDialog(&cur.bv()); InsetTabularMailer(*this).showDialog(&cur.bv());
break; break;
@ -545,11 +546,13 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_CELL_BACKWARD: case LFUN_CELL_BACKWARD:
movePrevCell(cur); movePrevCell(cur);
cur.selection() = false; cur.selection() = false;
saveSelection(cur);
break; break;
case LFUN_CELL_FORWARD: case LFUN_CELL_FORWARD:
moveNextCell(cur); moveNextCell(cur);
cur.selection() = false; cur.selection() = false;
saveSelection(cur);
break; break;
case LFUN_CHAR_FORWARD_SELECT: case LFUN_CHAR_FORWARD_SELECT:
@ -558,7 +561,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
if (!cur.result().dispatched()) { if (!cur.result().dispatched()) {
isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur); isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur);
if (cmd.action == LFUN_CHAR_FORWARD_SELECT) if (cmd.action == LFUN_CHAR_FORWARD_SELECT)
theSelection().haveSelection(cur.selection()); saveSelection(cur);
if (sl == cur.top()) if (sl == cur.top())
cmd = FuncRequest(LFUN_FINISHED_RIGHT); cmd = FuncRequest(LFUN_FINISHED_RIGHT);
else else
@ -572,7 +575,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
if (!cur.result().dispatched()) { if (!cur.result().dispatched()) {
isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur); isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur);
if (cmd.action == LFUN_CHAR_BACKWARD_SELECT) if (cmd.action == LFUN_CHAR_BACKWARD_SELECT)
theSelection().haveSelection(cur.selection()); saveSelection(cur);
if (sl == cur.top()) if (sl == cur.top())
cmd = FuncRequest(LFUN_FINISHED_LEFT); cmd = FuncRequest(LFUN_FINISHED_LEFT);
else else
@ -595,7 +598,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
cur.bv().textMetrics(cell(cur.idx())->getText(0)); cur.bv().textMetrics(cell(cur.idx())->getText(0));
cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX()); cur.pos() = tm.x2pos(cur.pit(), 0, cur.targetX());
if (cmd.action == LFUN_DOWN_SELECT) if (cmd.action == LFUN_DOWN_SELECT)
theSelection().haveSelection(cur.selection()); saveSelection(cur);
} }
if (sl == cur.top()) { if (sl == cur.top()) {
// we trick it to go to the RIGHT after leaving the // we trick it to go to the RIGHT after leaving the
@ -622,7 +625,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
tm.parMetrics(cur.lastpit()); tm.parMetrics(cur.lastpit());
cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX()); cur.pos() = tm.x2pos(cur.pit(), pm.rows().size()-1, cur.targetX());
if (cmd.action == LFUN_UP_SELECT) if (cmd.action == LFUN_UP_SELECT)
theSelection().haveSelection(cur.selection()); saveSelection(cur);
} }
if (sl == cur.top()) { if (sl == cur.top()) {
cmd = FuncRequest(LFUN_FINISHED_UP); cmd = FuncRequest(LFUN_FINISHED_UP);
@ -746,7 +749,7 @@ void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_PASTE: case LFUN_PASTE:
if (tabularStackDirty() && theClipboard().isInternal()) { if (tabularStackDirty() && theClipboard().isInternal()) {
recordUndoInset(cur, Undo::INSERT); recordUndoInset(cur, Undo::INSERT);
pasteSelection(cur); pasteClipboard(cur);
break; break;
} }
cell(cur.idx())->dispatch(cur, cmd); cell(cur.idx())->dispatch(cur, cmd);
@ -1823,7 +1826,7 @@ bool InsetTabular::copySelection(LCursor & cur)
} }
bool InsetTabular::pasteSelection(LCursor & cur) bool InsetTabular::pasteClipboard(LCursor & cur)
{ {
if (!paste_tabular) if (!paste_tabular)
return false; return false;

View File

@ -179,7 +179,7 @@ private:
/// ///
bool copySelection(LCursor & cur); bool copySelection(LCursor & cur);
/// ///
bool pasteSelection(LCursor & cur); bool pasteClipboard(LCursor & cur);
/// ///
void cutSelection(LCursor & cur); void cutSelection(LCursor & cur);
/// ///

View File

@ -29,7 +29,6 @@
#include "undo.h" #include "undo.h"
#include "frontends/Alert.h" #include "frontends/Alert.h"
#include "frontends/Selection.h"
#include "support/convert.h" #include "support/convert.h"
#include "support/docstream.h" #include "support/docstream.h"
@ -366,7 +365,6 @@ bool findNextChange(BufferView * bv)
// Now put cursor to end of selection: // Now put cursor to end of selection:
bv->cursor().setCursor(cur); bv->cursor().setCursor(cur);
bv->cursor().setSelection(); bv->cursor().setSelection();
theSelection().haveSelection(bv->cursor().selection());
return true; return true;
} }

View File

@ -50,7 +50,6 @@ using std::istream;
using std::istringstream; using std::istringstream;
using std::vector; using std::vector;
class GridInsetMailer : public MailInset { class GridInsetMailer : public MailInset {
public: public:
GridInsetMailer(InsetMathGrid & inset) : inset_(inset) {} GridInsetMailer(InsetMathGrid & inset) : inset_(inset) {}

View File

@ -1400,7 +1400,6 @@ bool InsetMathHull::searchForward(BufferView * bv, string const & str,
MathArray const & a = top.asInsetMath()->cell(top.idx_); MathArray const & a = top.asInsetMath()->cell(top.idx_);
if (a.matchpart(ar, top.pos_)) { if (a.matchpart(ar, top.pos_)) {
bv->cursor().setSelection(it, ar.size()); bv->cursor().setSelection(it, ar.size());
theSelection().haveSelection(bv->cursor().selection());
current = it; current = it;
top.pos_ += ar.size(); top.pos_ += ar.size();
bv->update(); bv->update();

View File

@ -580,7 +580,7 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
cur.selection() = true; cur.selection() = true;
cur.pos() = cur.lastpos(); cur.pos() = cur.lastpos();
cur.idx() = cur.lastidx(); cur.idx() = cur.lastidx();
theSelection().haveSelection(true); cap::saveSelection(cur);
break; break;
case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_UP:
@ -1151,10 +1151,11 @@ void InsetMathNest::lfunMousePress(LCursor & cur, FuncRequest & cmd)
cur.updateFlags(Update::Decoration | Update::FitCursor); cur.updateFlags(Update::Decoration | Update::FitCursor);
} else if (cmd.button() == mouse_button::button2) { } else if (cmd.button() == mouse_button::button2) {
MathArray ar; MathArray ar;
if (cur.selection()) { if (cap::selection()) {
// See comment in LyXText::dispatch why we do this // See comment in LyXText::dispatch why we do this
cap::copySelectionToStack(bv.cursor()); cap::copySelectionToStack();
asArray(bv.cursor().selectionAsString(false), ar); cmd = FuncRequest(LFUN_PASTE, "0");
doDispatch(cur, cmd);
} else } else
asArray(theSelection().get(), ar); asArray(theSelection().get(), ar);
@ -1185,10 +1186,13 @@ void InsetMathNest::lfunMouseRelease(LCursor & cur, FuncRequest & cmd)
//lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl; //lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl;
if (cmd.button() == mouse_button::button1) { if (cmd.button() == mouse_button::button1) {
if (cur.bv().cursor().selection())
theSelection().haveSelection(true);
if (!cur.selection()) if (!cur.selection())
cur.noUpdate(); cur.noUpdate();
else {
LCursor & bvcur = cur.bv().cursor();
bvcur.selection() = true;
cap::saveSelection(bvcur);
}
return; return;
} }

View File

@ -53,7 +53,6 @@
#include "frontends/FontMetrics.h" #include "frontends/FontMetrics.h"
#include "frontends/Painter.h" #include "frontends/Painter.h"
#include "frontends/Selection.h"
#include "insets/insettext.h" #include "insets/insettext.h"
#include "insets/insetbibitem.h" #include "insets/insetbibitem.h"
@ -829,7 +828,7 @@ void LyXText::selectWord(LCursor & cur, word_location loc)
cur.resetAnchor(); cur.resetAnchor();
setCursor(cur, to.pit(), to.pos()); setCursor(cur, to.pit(), to.pos());
cur.setSelection(); cur.setSelection();
theSelection().haveSelection(cur.selection()); cap::saveSelection(cur);
} }

View File

@ -76,9 +76,10 @@ namespace lyx {
using cap::copySelection; using cap::copySelection;
using cap::cutSelection; using cap::cutSelection;
using cap::pasteFromStack;
using cap::pasteClipboard; using cap::pasteClipboard;
using cap::pasteSelection;
using cap::replaceSelection; using cap::replaceSelection;
using cap::saveSelection;
using support::isStrUnsignedInt; using support::isStrUnsignedInt;
using support::token; using support::token;
@ -122,7 +123,7 @@ namespace {
{ {
if (selecting || cur.mark()) if (selecting || cur.mark())
cur.setSelection(); cur.setSelection();
theSelection().haveSelection(cur.selection()); saveSelection(cur);
cur.bv().switchKeyMap(); cur.bv().switchKeyMap();
} }
@ -138,7 +139,6 @@ namespace {
{ {
recordUndo(cur); recordUndo(cur);
docstring sel = cur.selectionAsString(false); docstring sel = cur.selectionAsString(false);
//lyxerr << "selection is: '" << sel << "'" << endl;
// It may happen that sel is empty but there is a selection // It may happen that sel is empty but there is a selection
replaceSelection(cur); replaceSelection(cur);
@ -434,6 +434,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
cur.undispatched(); cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_RIGHT); cmd = FuncRequest(LFUN_FINISHED_RIGHT);
} }
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_CHAR_BACKWARD: case LFUN_CHAR_BACKWARD:
@ -450,6 +452,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
cur.undispatched(); cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_LEFT); cmd = FuncRequest(LFUN_FINISHED_LEFT);
} }
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_UP: case LFUN_UP:
@ -464,6 +468,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
cur.undispatched(); cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_UP); cmd = FuncRequest(LFUN_FINISHED_UP);
} }
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_DOWN: case LFUN_DOWN:
@ -478,18 +484,24 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
cur.undispatched(); cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_DOWN); cmd = FuncRequest(LFUN_FINISHED_DOWN);
} }
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_UP:
case LFUN_PARAGRAPH_UP_SELECT: case LFUN_PARAGRAPH_UP_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_UP_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_UP_SELECT);
needsUpdate |= cursorUpParagraph(cur); needsUpdate |= cursorUpParagraph(cur);
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_PARAGRAPH_DOWN: case LFUN_PARAGRAPH_DOWN:
case LFUN_PARAGRAPH_DOWN_SELECT: case LFUN_PARAGRAPH_DOWN_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_DOWN_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_DOWN_SELECT);
needsUpdate |= cursorDownParagraph(cur); needsUpdate |= cursorDownParagraph(cur);
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_SCREEN_UP: case LFUN_SCREEN_UP:
@ -501,6 +513,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
} else { } else {
cursorPrevious(cur); cursorPrevious(cur);
} }
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_SCREEN_DOWN: case LFUN_SCREEN_DOWN:
@ -513,6 +527,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
} else { } else {
cursorNext(cur); cursorNext(cur);
} }
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_LINE_BEGIN: case LFUN_LINE_BEGIN:
@ -525,6 +541,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_LINE_END_SELECT: case LFUN_LINE_END_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_END_SELECT); needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_END_SELECT);
needsUpdate |= cursorEnd(cur); needsUpdate |= cursorEnd(cur);
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_WORD_FORWARD: case LFUN_WORD_FORWARD:
@ -534,6 +552,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
needsUpdate |= cursorLeftOneWord(cur); needsUpdate |= cursorLeftOneWord(cur);
else else
needsUpdate |= cursorRightOneWord(cur); needsUpdate |= cursorRightOneWord(cur);
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_WORD_BACKWARD: case LFUN_WORD_BACKWARD:
@ -543,6 +563,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
needsUpdate |= cursorRightOneWord(cur); needsUpdate |= cursorRightOneWord(cur);
else else
needsUpdate |= cursorLeftOneWord(cur); needsUpdate |= cursorLeftOneWord(cur);
if (cur.selection())
saveSelection(cur);
break; break;
case LFUN_WORD_SELECT: { case LFUN_WORD_SELECT: {
@ -781,7 +803,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
pasteClipboard(cur, bv->buffer()->errorList("Paste")); pasteClipboard(cur, bv->buffer()->errorList("Paste"));
else { else {
string const arg(to_utf8(cmd.argument())); string const arg(to_utf8(cmd.argument()));
pasteSelection(cur, bv->buffer()->errorList("Paste"), pasteFromStack(cur, bv->buffer()->errorList("Paste"),
isStrUnsignedInt(arg) ? isStrUnsignedInt(arg) ?
convert<unsigned int>(arg) : convert<unsigned int>(arg) :
0); 0);
@ -960,7 +982,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
cursorEnd(cur); cursorEnd(cur);
cur.setSelection(); cur.setSelection();
bv->cursor() = cur; bv->cursor() = cur;
theSelection().haveSelection(cur.selection()); saveSelection(cur);
} }
break; break;
@ -968,7 +990,6 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
if (cmd.button() == mouse_button::button1) { if (cmd.button() == mouse_button::button1) {
selectWord(cur, WHOLE_WORD_STRICT); selectWord(cur, WHOLE_WORD_STRICT);
bv->cursor() = cur; bv->cursor() = cur;
theSelection().haveSelection(cur.selection());
} }
break; break;
@ -983,15 +1004,11 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
// it could get cleared on the unlocking of the inset so // it could get cleared on the unlocking of the inset so
// we have to check this first // we have to check this first
bool paste_internally = false; bool paste_internally = false;
if (cmd.button() == mouse_button::button2 && cur.selection()) { if (cmd.button() == mouse_button::button2 && cap::selection()) {
// Copy the selection to the clipboard stack. This // Copy the selection buffer to the clipboard
// is done for two reasons: // stack, because we want it to appear in the
// - We want it to appear in the "Edit->Paste recent" // "Edit->Paste recent" menu.
// menu. cap::copySelectionToStack();
// - 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());
paste_internally = true; paste_internally = true;
} }
@ -1002,9 +1019,13 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
// if there is a local selection in the current buffer, // if there is a local selection in the current buffer,
// insert this // insert this
if (cmd.button() == mouse_button::button2) { if (cmd.button() == mouse_button::button2) {
if (paste_internally) if (paste_internally) {
lyx::dispatch(FuncRequest(LFUN_PASTE, "0")); cap::pasteSelection(cur, bv->buffer()->errorList("Paste"));
else bv->buffer()->errors("Paste");
cur.clearSelection(); // bug 393
bv->switchKeyMap();
finishUndo();
} else
lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph")); lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph"));
} }
@ -1061,10 +1082,18 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
if (cmd.button() == mouse_button::button2) if (cmd.button() == mouse_button::button2)
break; break;
// finish selection
if (cmd.button() == mouse_button::button1) { if (cmd.button() == mouse_button::button1) {
if (cur.selection()) // if there is new selection, update persistent
theSelection().haveSelection(true); // selection, otherwise, single click does not
// clear persistent selection buffer
if (cur.selection()) {
// finish selection
// if double click, cur is moved to the end of word by selectWord
// but bvcur is current mouse position
LCursor & bvcur = cur.bv().cursor();
bvcur.selection() = true;
saveSelection(bvcur);
}
needsUpdate = false; needsUpdate = false;
cur.noUpdate(); cur.noUpdate();
} }
@ -1083,13 +1112,9 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
// "auto_region_delete", which defaults to // "auto_region_delete", which defaults to
// true (on). // true (on).
if (lyxrc.auto_region_delete) { if (lyxrc.auto_region_delete)
if (cur.selection()) if (cur.selection())
cutSelection(cur, false, false); cutSelection(cur, false, false);
// cutSelection clears the X selection.
else
theSelection().haveSelection(false);
}
cur.clearSelection(); cur.clearSelection();
LyXFont const old_font = real_current_font; LyXFont const old_font = real_current_font;
@ -1508,6 +1533,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_ESCAPE: case LFUN_ESCAPE:
if (cur.selection()) { if (cur.selection()) {
cur.selection() = false; cur.selection() = false;
saveSelection(cur);
} else { } else {
cur.undispatched(); cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_RIGHT); cmd = FuncRequest(LFUN_FINISHED_RIGHT);