selection patch

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8243 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Alfredo Braunstein 2003-12-12 15:19:35 +00:00
parent 82fbc52bbb
commit 7da68795a5
16 changed files with 166 additions and 143 deletions

View File

@ -68,6 +68,12 @@ BufferView::~BufferView()
}
void BufferView::unsetXSel()
{
pimpl_->xsel_cache_.set = false;
}
Buffer * BufferView::buffer() const
{
return pimpl_->buffer_;

View File

@ -182,6 +182,9 @@ public:
/// return target x position of cursor
int x_target() const;
/// clear the X selection
void unsetXSel();
/// access to cursor
LCursor & cursor();
/// access to cursor

View File

@ -114,6 +114,8 @@ BufferView::Pimpl::Pimpl(BufferView * bv, LyXView * owner,
: bv_(bv), owner_(owner), buffer_(0), cursor_timeout(400),
using_xterm_cursor(false), cursor_(bv)
{
xsel_cache_.set = false;
workarea_.reset(WorkAreaFactory::create(xpos, ypos, width, height));
screen_.reset(LyXScreenFactory::create(workarea()));
@ -390,10 +392,10 @@ void BufferView::Pimpl::resizeCurrentBuffer()
par = bv_->text()->cursor.par();
pos = bv_->text()->cursor.pos();
selstartpar = bv_->text()->selection.start.par();
selstartpos = bv_->text()->selection.start.pos();
selendpar = bv_->text()->selection.end.par();
selendpos = bv_->text()->selection.end.pos();
selstartpar = bv_->text()->selStart().par();
selstartpos = bv_->text()->selStart().pos();
selendpar = bv_->text()->selEnd().par();
selendpos = bv_->text()->selEnd().pos();
selection = bv_->text()->selection.set();
mark_set = bv_->text()->selection.mark();
bv_->text()->textwidth_ = bv_->workWidth();
@ -526,18 +528,20 @@ void BufferView::Pimpl::selectionRequested()
LyXText * text = bv_->getLyXText();
if (text->selection.set() &&
(!bv_->text()->xsel_cache.set() ||
text->selection.start != bv_->text()->xsel_cache.start ||
text->selection.end != bv_->text()->xsel_cache.end))
{
bv_->text()->xsel_cache = text->selection;
sel = text->selectionAsString(*bv_->buffer(), false);
} else if (!text->selection.set()) {
sel = string();
bv_->text()->xsel_cache.set(false);
if (!text->selection.set()) {
xsel_cache_.set = false;
return;
}
if (!sel.empty()) {
if (!xsel_cache_.set ||
text->cursor != xsel_cache_.cursor ||
text->selection.cursor != xsel_cache_.selection_cursor)
{
xsel_cache_.cursor = text->cursor;
xsel_cache_.selection_cursor = text->selection.cursor;
xsel_cache_.set = text->selection.set();
sel = text->selectionAsString(*bv_->buffer(), false);
if (!sel.empty())
workarea().putClipboard(sel);
}
}
@ -548,7 +552,7 @@ void BufferView::Pimpl::selectionLost()
if (available()) {
screen().hideCursor();
bv_->getLyXText()->clearSelection();
bv_->text()->xsel_cache.set(false);
xsel_cache_.set = false;
}
}
@ -631,8 +635,8 @@ Change const BufferView::Pimpl::getCurrentChange()
if (!text->selection.set())
return Change(Change::UNCHANGED);
return text->getPar(text->selection.start)
->lookupChangeFull(text->selection.start.pos());
return text->getPar(text->selStart())
->lookupChangeFull(text->selStart().pos());
}

View File

@ -193,7 +193,12 @@ private:
void MenuInsertLyXFile(std::string const & filen);
/// our workarea
WorkArea & workarea() const;
/// this is used to handle XSelection events in the right manner
struct {
LyXCursor cursor;
LyXCursor selection_cursor;
bool set;
} xsel_cache_;
///
LCursor cursor_;
};

View File

@ -1,4 +1,17 @@
2003-12-12 Alfredo Braunstein <abraunst@libero.it>
2003-12-12 Alfredo Braunstein <abraunst@lyx.org>
* textcursor.[Ch] (selStart,selEnd): add new methods
remove selection::start, end, use LyXCursor::operator<
* lyxcursor.[Ch] (operator<): add
* BufferView_pimpl.[Ch]: add new struct xsel_cache_
* BufferView.[Ch] (unsetXSel): add
* text2.C (clearSelection): use unsetXSel,adjust
* text.C: adjust
* text3.C: adjust
* rowpainter.C: adjust
* bufferview_funcs.C (put_selection_at): adjust
2003-12-12 Alfredo Braunstein <abraunst@lyx.org>
* BufferView_pimpl.C: small coord. correction

View File

@ -301,7 +301,7 @@ void put_selection_at(BufferView * bv, PosIterator const & cur,
text->setSelectionRange(length);
text->setSelection();
if (backwards)
text->cursor = text->selection.start;
std::swap(text->cursor, text->selection.cursor);
}
bv->fitCursor();

View File

@ -546,18 +546,7 @@ void InsetText::collapseParagraphs(BufferView * bv)
first->insertChar(first_par_size, ' ');
}
#warning probably broken
if (text_.selection.set()) {
if (text_.selection.start.par() == 1) {
text_.selection.start.par(1);
text_.selection.start.pos(text_.selection.start.pos() + first_par_size);
}
if (text_.selection.end.par() == 2) {
text_.selection.end.par(1);
text_.selection.end.pos(text_.selection.end.pos() + first_par_size);
}
}
text_.clearSelection();
mergeParagraph(bv->buffer()->params(), paragraphs(), first);
}
}

View File

@ -94,3 +94,9 @@ bool operator!=(LyXCursor const & a, LyXCursor const & b)
return !(a == b);
}
bool operator<(LyXCursor const & a, LyXCursor const & b)
{
return (a.par() < b.par() ||
(a.par() == b.par() && a.pos() < b.pos()));
}

View File

@ -81,5 +81,7 @@ private:
bool operator==(LyXCursor const & a, LyXCursor const & b);
///
bool operator!=(LyXCursor const & a, LyXCursor const & b);
///
bool operator<(LyXCursor const & a, LyXCursor const & b);
#endif // LYXCURSOR_H

View File

@ -225,7 +225,7 @@ int replace(BufferView * bv,
text->replaceSelectionWithString(replacestr);
text->setSelectionRange(replacestr.length());
text->cursor = fw ? text->selection.end : text->selection.start;
text->cursor = fw ? text->selEnd() : text->selStart();
bv->buffer()->markDirty();
find(bv, searchstr, cs, mw, fw);

View File

@ -391,14 +391,14 @@ void RowPainter::paintSelection()
bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params());
// the current selection
int const startx = text_.selection.start.x();
int const endx = text_.selection.end.x();
int const starty = text_.selection.start.y();
int const endy = text_.selection.end.y();
ParagraphList::iterator startpit = text_.getPar(text_.selection.start);
ParagraphList::iterator endpit = text_.getPar(text_.selection.end);
RowList::iterator startrow = startpit->getRow(text_.selection.start.pos());
RowList::iterator endrow = endpit->getRow(text_.selection.end.pos());
int const startx = text_.selStart().x();
int const endx = text_.selEnd().x();
int const starty = text_.selStart().y();
int const endy = text_.selEnd().y();
ParagraphList::iterator startpit = text_.getPar(text_.selStart());
ParagraphList::iterator endpit = text_.getPar(text_.selEnd());
RowList::iterator startrow = startpit->getRow(text_.selStart().pos());
RowList::iterator endrow = endpit->getRow(text_.selEnd().pos());
int const h = row_.height();
int const row_y = pit_->y + row_.y_offset();
@ -468,9 +468,9 @@ void RowPainter::paintSelection()
}
if (((startpit != pit_ && startrow != rit_)
|| text_.selection.start.pos() <= pos) &&
|| text_.selStart().pos() <= pos) &&
((endpit != pit_ && endrow != rit_)
|| pos < text_.selection.end.pos())) {
|| pos < text_.selEnd().pos())) {
// Here we do not use x_ as xo_ was added to x_.
pain_.fillRectangle(int(old_tmpx), yo_,
int(tmpx - old_tmpx + 1), h, LColor::selection);

View File

@ -1129,9 +1129,9 @@ void LyXText::acceptChange()
if (!selection.set() && cursorPar()->size())
return;
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
if (selStart().par() == selEnd().par()) {
LyXCursor const & startc = selStart();
LyXCursor const & endc = selEnd();
recordUndo(Undo::INSERT, this, startc.par());
getPar(startc)->acceptChange(startc.pos(), endc.pos());
finishUndo();
@ -1148,9 +1148,9 @@ void LyXText::rejectChange()
if (!selection.set() && cursorPar()->size())
return;
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
if (selStart().par() == selEnd().par()) {
LyXCursor const & startc = selStart();
LyXCursor const & endc = selEnd();
recordUndo(Undo::INSERT, this, startc.par());
getPar(startc)->rejectChange(startc.pos(), endc.pos());
finishUndo();
@ -1206,8 +1206,6 @@ void LyXText::deleteLineForward()
cursorRight(bv());
} else {
LyXCursor tmpcursor = cursor;
// We can't store the row over a regular setCursor
// so we set it to 0 and reset it afterwards.
selection.set(true); // to avoid deletion
cursorEnd();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
@ -1229,8 +1227,8 @@ void LyXText::changeCase(LyXText::TextCase action)
LyXCursor to;
if (selection.set()) {
from = selection.start;
to = selection.end;
from = selStart();
to = selEnd();
} else {
from = cursor;
getWord(from, to, lyx::PARTIAL_WORD);
@ -1514,10 +1512,10 @@ string LyXText::selectionAsString(Buffer const & buffer, bool label) const
return string();
// should be const ...
ParagraphList::iterator startpit = getPar(selection.start);
ParagraphList::iterator endpit = getPar(selection.end);
size_t const startpos = selection.start.pos();
size_t const endpos = selection.end.pos();
ParagraphList::iterator startpit = getPar(selStart());
ParagraphList::iterator endpit = getPar(selEnd());
size_t const startpos = selStart().pos();
size_t const endpos = selEnd().pos();
if (startpit == endpit)
return startpit->asString(buffer, startpos, endpos, label);

View File

@ -301,8 +301,6 @@ LyXText::setLayout(ParagraphList::iterator start,
// set layout over selection and make a total rebreak of those paragraphs
void LyXText::setLayout(string const & layout)
{
setSelection();
// special handling of new environment insets
BufferParams const & params = bv()->buffer()->params();
LyXLayout_ptr const & lyxlayout = params.getLyXTextClass()[layout];
@ -321,8 +319,8 @@ void LyXText::setLayout(string const & layout)
return;
}
ParagraphList::iterator start = getPar(selection.start.par());
ParagraphList::iterator end = boost::next(getPar(selection.end.par()));
ParagraphList::iterator start = getPar(selStart().par());
ParagraphList::iterator end = boost::next(getPar(selEnd().par()));
ParagraphList::iterator endpit = setLayout(start, end, layout);
redoParagraphs(start, endpit);
@ -342,8 +340,8 @@ void getSelectionSpan(LyXText & text,
beg = text.cursorPar();
end = boost::next(beg);
} else {
beg = text.getPar(text.selection.start);
end = boost::next(text.getPar(text.selection.end));
beg = text.getPar(text.selStart());
end = boost::next(text.getPar(text.selEnd()));
}
}
@ -438,14 +436,14 @@ void LyXText::setFont(LyXFont const & font, bool toggleall)
}
// ok we have a selection.
recUndo(selection.start.par(), selection.end.par());
recUndo(selStart().par(), selEnd().par());
freezeUndo();
ParagraphList::iterator beg = getPar(selection.start.par());
ParagraphList::iterator end = getPar(selection.end.par());
ParagraphList::iterator beg = getPar(selStart().par());
ParagraphList::iterator end = getPar(selEnd().par());
PosIterator pos(&paragraphs(), beg, selection.start.pos());
PosIterator posend(&paragraphs(), end, selection.end.pos());
PosIterator pos(&paragraphs(), beg, selStart().pos());
PosIterator posend(&paragraphs(), end, selEnd().pos());
BufferParams const & params = bv()->buffer()->params();
@ -481,7 +479,7 @@ void LyXText::clearSelection()
// reset this in the bv()!
if (bv() && bv()->text())
bv()->text()->xsel_cache.set(false);
bv()->unsetXSel();
}
@ -561,7 +559,7 @@ string LyXText::getStringToIndex()
string idxstring;
if (!selection.set())
bv()->owner()->message(_("Nothing to index!"));
else if (selection.start.par() != selection.end.par())
else if (selStart().par() != selEnd().par())
bv()->owner()->message(_("Cannot index more than one paragraph!"));
else
idxstring = selectionAsString(*bv()->buffer(), false);
@ -588,9 +586,8 @@ string LyXText::getStringToIndex()
void LyXText::setParagraph(Spacing const & spacing, LyXAlignment align,
string const & labelwidthstring, bool noindent)
{
setSelection();
// make sure that the depth behind the selection are restored, too
ParagraphList::iterator endpit = boost::next(getPar(selection.end));
ParagraphList::iterator endpit = boost::next(getPar(selEnd()));
ParagraphList::iterator pars_end = paragraphs().end();
while (endpit != pars_end && endpit->getDepth())
@ -599,10 +596,10 @@ void LyXText::setParagraph(Spacing const & spacing, LyXAlignment align,
if (endpit != pars_end)
++endpit;
recUndo(selection.start.par(), parOffset(endpit) - 1);
recUndo(selStart().par(), parOffset(endpit) - 1);
ParagraphList::reverse_iterator pit(getPar(selection.end.par()));
ParagraphList::reverse_iterator beg(getPar(selection.start.par()));
ParagraphList::reverse_iterator pit(getPar(selEnd().par()));
ParagraphList::reverse_iterator beg(getPar(selStart().par()));
for (++beg; pit != beg; ++pit) {
ParagraphParameters & params = pit->params();
@ -623,7 +620,7 @@ void LyXText::setParagraph(Spacing const & spacing, LyXAlignment align,
params.noindent(noindent);
}
redoParagraphs(getPar(selection.start), endpit);
redoParagraphs(getPar(selStart()), endpit);
redoCursor();
}
@ -955,12 +952,12 @@ void LyXText::cutSelection(bool doclear, bool realcut)
if (!selection.set())
return;
// OK, we have a selection. This is always between selection.start
// and selection.end
// OK, we have a selection. This is always between selStart()
// and selEnd()
// make sure that the depth behind the selection are restored, too
ParagraphList::iterator begpit = getPar(selection.start.par());
ParagraphList::iterator endpit = getPar(selection.end.par());
ParagraphList::iterator begpit = getPar(selStart().par());
ParagraphList::iterator endpit = getPar(selEnd().par());
ParagraphList::iterator undopit = boost::next(endpit);
ParagraphList::iterator pars_end = paragraphs().end();
@ -969,22 +966,22 @@ void LyXText::cutSelection(bool doclear, bool realcut)
//because of parindents etc.
if (undopit != pars_end)
++undopit;
recUndo(selection.start.par(), parOffset(undopit) - 1);
recUndo(selStart().par(), parOffset(undopit) - 1);
int endpos = selection.end.pos();
int endpos = selEnd().pos();
BufferParams const & bufparams = bv()->buffer()->params();
boost::tie(endpit, endpos) = realcut ?
CutAndPaste::cutSelection(bufparams,
paragraphs(),
begpit , endpit,
selection.start.pos(), endpos,
selStart().pos(), endpos,
bufparams.textclass,
doclear)
: CutAndPaste::eraseSelection(bufparams,
paragraphs(),
begpit, endpit,
selection.start.pos(), endpos,
selStart().pos(), endpos,
doclear);
// sometimes necessary
if (doclear)
@ -1013,19 +1010,20 @@ void LyXText::copySelection()
if (!selection.set())
return;
// ok we have a selection. This is always between selection.start
// ok we have a selection. This is always between selStart()
// and sel_end cursor
// copy behind a space if there is one
while (getPar(selection.start)->size() > selection.start.pos()
&& getPar(selection.start)->isLineSeparator(selection.start.pos())
&& (selection.start.par() != selection.end.par()
|| selection.start.pos() < selection.end.pos()))
selection.start.pos(selection.start.pos() + 1);
while (getPar(selStart())->size() > selStart().pos()
&& getPar(selStart())->isLineSeparator(selStart().pos())
&& (selStart().par() != selEnd().par()
|| selStart().pos() < selEnd().pos()))
selStart().pos(selStart().pos() + 1);
CutAndPaste::copySelection(getPar(selection.start.par()),
getPar(selection.end.par()),
selection.start.pos(), selection.end.pos(),
CutAndPaste::copySelection(getPar(selStart().par()),
getPar(selEnd().par()),
selStart().pos(),
selEnd().pos(),
bv()->buffer()->params().textclass);
}
@ -1082,22 +1080,17 @@ void LyXText::replaceSelectionWithString(string const & str)
recUndo(cursor.par());
freezeUndo();
if (!selection.set()) { // create a dummy selection
selection.end = cursor;
selection.start = cursor;
}
// Get font setting before we cut
pos_type pos = selection.end.pos();
LyXFont const font = getPar(selection.start)
pos_type pos = selEnd().pos();
LyXFont const font = getPar(selStart())
->getFontSettings(bv()->buffer()->params(),
selection.start.pos());
selStart().pos());
// Insert the new string
string::const_iterator cit = str.begin();
string::const_iterator end = str.end();
for (; cit != end; ++cit) {
getPar(selection.end)->insertChar(pos, (*cit), font);
getPar(selEnd())->insertChar(pos, (*cit), font);
++pos;
}
@ -1749,8 +1742,6 @@ bool LyXText::deleteEmptyParagraphMechanism(LyXCursor const & old_cursor)
// correct all cursors held by the LyXText
fixCursorAfterDelete(cursor, old_cursor);
fixCursorAfterDelete(selection.cursor, old_cursor);
fixCursorAfterDelete(selection.start, old_cursor);
fixCursorAfterDelete(selection.end, old_cursor);
return false;
}
}

View File

@ -999,6 +999,8 @@ DispatchResult LyXText::dispatch(FuncRequest const & cmd)
case LFUN_BEGINNINGBUFSEL:
if (in_inset_)
return DispatchResult(false);
if (!selection.set())
selection.cursor = cursor;
cursorTop();
finishChange(bv, true);
break;
@ -1006,6 +1008,8 @@ DispatchResult LyXText::dispatch(FuncRequest const & cmd)
case LFUN_ENDBUFSEL:
if (in_inset_)
return DispatchResult(false);
if (!selection.set())
selection.cursor = cursor;
cursorBottom();
finishChange(bv, true);
break;
@ -1076,10 +1080,10 @@ DispatchResult LyXText::dispatch(FuncRequest const & cmd)
bool change_layout = (current_layout != layout);
if (!change_layout && selection.set() &&
selection.start.par() != selection.end.par())
selStart().par() != selEnd().par())
{
ParagraphList::iterator spit = getPar(selection.start);
ParagraphList::iterator epit = boost::next(getPar(selection.end));
ParagraphList::iterator spit = getPar(selStart());
ParagraphList::iterator epit = boost::next(getPar(selEnd()));
while (spit != epit) {
if (spit->layout()->name() != current_layout) {
change_layout = true;

View File

@ -11,40 +11,44 @@
#include <config.h>
#include "textcursor.h"
#include "paragraph.h"
#include "ParagraphList_fwd.h"
#include "debug.h"
#include <string>
using std::string;
LyXCursor const & TextCursor::selStart() const
{
if (!selection.set())
return cursor;
return selection.cursor < cursor ? selection.cursor : cursor;
}
LyXCursor const & TextCursor::selEnd() const
{
if (!selection.set())
return cursor;
return selection.cursor < cursor ? cursor : selection.cursor;
}
LyXCursor & TextCursor::selStart()
{
TextCursor const & t = *this;
return const_cast<LyXCursor &>(t.selStart());
}
LyXCursor & TextCursor::selEnd()
{
TextCursor const & t = *this;
return const_cast<LyXCursor &>(t.selEnd());
}
void TextCursor::setSelection()
{
selection.set(true);
if (selection.cursor.par() == cursor.par())
if (selection.cursor.pos() < cursor.pos()) {
selection.end = cursor;
selection.start = selection.cursor;
} else {
selection.end = selection.cursor;
selection.start = cursor;
}
else if (selection.cursor.par() < cursor.par() ||
(selection.cursor.par() == cursor.par()
&& selection.cursor.pos() < cursor.pos())) {
selection.end = cursor;
selection.start = selection.cursor;
} else {
selection.end = selection.cursor;
selection.start = cursor;
}
// a selection with no contents is not a selection
if (selection.start.par() == selection.end.par() &&
selection.start.pos() == selection.end.pos())
if (cursor.par() == selection.cursor.par() &&
cursor.pos() == selection.cursor.pos())
{
selection.set(false);
}
@ -55,8 +59,6 @@ void TextCursor::clearSelection()
{
selection.set(false);
selection.mark(false);
selection.end = cursor;
selection.start = cursor;
selection.cursor = cursor;
}

View File

@ -50,10 +50,7 @@ struct Selection {
void mark(bool m) {
mark_ = m;
}
LyXCursor cursor; // temporary cursor to hold a cursor position
// until setSelection is called!
LyXCursor start; // start of a REAL selection
LyXCursor end; // end of a REAL selection
LyXCursor cursor; // the other end of the selection
private:
bool set_; // former selection
bool mark_; // former mark_set
@ -70,8 +67,11 @@ struct TextCursor {
LyXCursor cursor;
Selection selection;
// this is used to handle XSelection events in the right manner
Selection xsel_cache;
LyXCursor const & selStart() const;
LyXCursor const & selEnd() const;
LyXCursor & selStart();
LyXCursor & selEnd();
};
#endif