#include "frontends/Alert.h"
#include "frontends/FileDialog.h"
#include "frontends/FontMetrics.h"
-#include "frontends/Selection.h"
#include "graphics/Previews.h"
cursor_.resetAnchor();
cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset())));
cursor_.setSelection();
- theSelection().haveSelection(cursor_.selection());
+ // do not set selection to the new buffer because we
+ // only paste recent selection.
}
}
{
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.
cursor_.setSelection(cursor_, -length);
} else
cursor_.setSelection(cursor_, length);
- theSelection().haveSelection(cursor_.selection());
+ cap::saveSelection(cursor_);
}
}
typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack;
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
// FIXME: this is a workaround for bug 1919. Should be removed for 1.5,
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());
// again, do not track deletion
front.eraseChars(0, start, false);
- theCuts.push(make_pair(paragraphs, tc));
+ cutstack.push(make_pair(paragraphs, tc));
}
} // namespace anon
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,
}
-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)
{
// this doesn't make sense, if there is no selection
if (!cur.selection())
++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()) {
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 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();
}
}
+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)
{
// Use internal clipboard if it is the most recent one
if (theClipboard().isInternal()) {
- pasteSelection(cur, errorList, 0);
+ pasteClipboard(cur, errorList, 0);
return;
}
}
-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();
}
cur.setSelection(selbeg, -int(str.length()));
} else
cur.setSelection(selbeg, str.length());
+ saveSelection(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 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
/// 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.
#include "mathed/InsetMathScript.h"
#include "mathed/MathMacroTable.h"
-#include "frontends/Selection.h"
-
#include "support/limited_stack.h"
#include <boost/assert.hpp>
resetAnchor();
selection() = sel;
- theSelection().haveSelection(sel);
+ cap::saveSelection(*this);
return true;
}
using cap::dirtyTabularStack;
using cap::tabularStackDirty;
+using cap::saveSelection;
using graphics::PreviewLoader;
}
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,
//lyxerr << "# InsetTabular::MouseRelease\n" << bvcur << endl;
if (cmd.button() == mouse_button::button1) {
if (bvcur.selection())
- theSelection().haveSelection(true);
+ saveSelection(bvcur);// theSelection().haveSelection(true);
} else if (cmd.button() == mouse_button::button3)
InsetTabularMailer(*this).showDialog(&cur.bv());
break;
case LFUN_CELL_BACKWARD:
movePrevCell(cur);
cur.selection() = false;
+ saveSelection(cur);
break;
case LFUN_CELL_FORWARD:
moveNextCell(cur);
cur.selection() = false;
+ saveSelection(cur);
break;
case LFUN_CHAR_FORWARD_SELECT:
if (!cur.result().dispatched()) {
isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur);
if (cmd.action == LFUN_CHAR_FORWARD_SELECT)
- theSelection().haveSelection(cur.selection());
+ saveSelection(cur);
if (sl == cur.top())
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
else
if (!cur.result().dispatched()) {
isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur);
if (cmd.action == LFUN_CHAR_BACKWARD_SELECT)
- theSelection().haveSelection(cur.selection());
+ saveSelection(cur);
if (sl == cur.top())
cmd = FuncRequest(LFUN_FINISHED_LEFT);
else
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());
+ saveSelection(cur);
}
if (sl == cur.top()) {
// we trick it to go to the RIGHT after leaving the
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());
+ saveSelection(cur);
}
if (sl == cur.top()) {
cmd = FuncRequest(LFUN_FINISHED_UP);
case LFUN_PASTE:
if (tabularStackDirty() && theClipboard().isInternal()) {
recordUndoInset(cur, Undo::INSERT);
- pasteSelection(cur);
+ pasteClipboard(cur);
break;
}
cell(cur.idx())->dispatch(cur, cmd);
}
-bool InsetTabular::pasteSelection(LCursor & cur)
+bool InsetTabular::pasteClipboard(LCursor & cur)
{
if (!paste_tabular)
return false;
///
bool copySelection(LCursor & cur);
///
- bool pasteSelection(LCursor & cur);
+ bool pasteClipboard(LCursor & cur);
///
void cutSelection(LCursor & cur);
///
#include "undo.h"
#include "frontends/Alert.h"
-#include "frontends/Selection.h"
#include "support/convert.h"
#include "support/docstream.h"
// Now put cursor to end of selection:
bv->cursor().setCursor(cur);
bv->cursor().setSelection();
- theSelection().haveSelection(bv->cursor().selection());
return true;
}
using std::istringstream;
using std::vector;
-
class GridInsetMailer : public MailInset {
public:
GridInsetMailer(InsetMathGrid & inset) : inset_(inset) {}
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());
current = it;
top.pos_ += ar.size();
bv->update();
cur.selection() = true;
cur.pos() = cur.lastpos();
cur.idx() = cur.lastidx();
- theSelection().haveSelection(true);
+ cap::saveSelection(cur);
break;
case LFUN_PARAGRAPH_UP:
cur.updateFlags(Update::Decoration | Update::FitCursor);
} 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);
//lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl;
if (cmd.button() == mouse_button::button1) {
- if (cur.bv().cursor().selection())
- theSelection().haveSelection(true);
if (!cur.selection())
cur.noUpdate();
+ else {
+ LCursor & bvcur = cur.bv().cursor();
+ bvcur.selection() = true;
+ cap::saveSelection(bvcur);
+ }
return;
}
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
-#include "frontends/Selection.h"
#include "insets/insettext.h"
#include "insets/insetbibitem.h"
cur.resetAnchor();
setCursor(cur, to.pit(), to.pos());
cur.setSelection();
- theSelection().haveSelection(cur.selection());
+ cap::saveSelection(cur);
}
using cap::copySelection;
using cap::cutSelection;
+using cap::pasteFromStack;
using cap::pasteClipboard;
-using cap::pasteSelection;
using cap::replaceSelection;
+using cap::saveSelection;
using support::isStrUnsignedInt;
using support::token;
{
if (selecting || cur.mark())
cur.setSelection();
- theSelection().haveSelection(cur.selection());
+ saveSelection(cur);
cur.bv().switchKeyMap();
}
{
recordUndo(cur);
docstring sel = cur.selectionAsString(false);
- //lyxerr << "selection is: '" << sel << "'" << endl;
// It may happen that sel is empty but there is a selection
replaceSelection(cur);
cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
}
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_CHAR_BACKWARD:
cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_LEFT);
}
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_UP:
cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_UP);
}
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_DOWN:
cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_DOWN);
}
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_PARAGRAPH_UP:
case LFUN_PARAGRAPH_UP_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_UP_SELECT);
needsUpdate |= cursorUpParagraph(cur);
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_PARAGRAPH_DOWN:
case LFUN_PARAGRAPH_DOWN_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_DOWN_SELECT);
needsUpdate |= cursorDownParagraph(cur);
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_SCREEN_UP:
} else {
cursorPrevious(cur);
}
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_SCREEN_DOWN:
} else {
cursorNext(cur);
}
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_LINE_BEGIN:
case LFUN_LINE_END_SELECT:
needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_END_SELECT);
needsUpdate |= cursorEnd(cur);
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_WORD_FORWARD:
needsUpdate |= cursorLeftOneWord(cur);
else
needsUpdate |= cursorRightOneWord(cur);
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_WORD_BACKWARD:
needsUpdate |= cursorRightOneWord(cur);
else
needsUpdate |= cursorLeftOneWord(cur);
+ if (cur.selection())
+ saveSelection(cur);
break;
case LFUN_WORD_SELECT: {
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);
cursorEnd(cur);
cur.setSelection();
bv->cursor() = cur;
- theSelection().haveSelection(cur.selection());
+ saveSelection(cur);
}
break;
if (cmd.button() == mouse_button::button1) {
selectWord(cur, WHOLE_WORD_STRICT);
bv->cursor() = cur;
- theSelection().haveSelection(cur.selection());
}
break;
// 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;
}
// 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"));
}
if (cmd.button() == mouse_button::button2)
break;
- // finish selection
if (cmd.button() == mouse_button::button1) {
- if (cur.selection())
- theSelection().haveSelection(true);
+ // if there is new selection, update persistent
+ // 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;
cur.noUpdate();
}
// "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;
case LFUN_ESCAPE:
if (cur.selection()) {
cur.selection() = false;
+ saveSelection(cur);
} else {
cur.undispatched();
cmd = FuncRequest(LFUN_FINISHED_RIGHT);