This fixes a real bug in InsetText where it was possible to delete the

cached LyXText while we where working inside it (accessing of freed
memory!), small changes in the insetInsertAllowed functions to have
a better check where is what allowed.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@2225 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Vigna 2001-07-12 12:26:06 +00:00
parent 72f625da0e
commit 8dc8a36370
10 changed files with 323 additions and 215 deletions

View File

@ -9,6 +9,7 @@ src/converter.C
src/CutAndPaste.C src/CutAndPaste.C
src/debug.C src/debug.C
src/exporter.C src/exporter.C
src/ext_l10n.h
src/figure_form.C src/figure_form.C
src/figureForm.C src/figureForm.C
src/FontLoader.C src/FontLoader.C

View File

@ -1,3 +1,25 @@
2001-07-12 Juergen Vigna <jug@sad.it>
* insetfloat.C (insertInsetAllowed): make a bit more checks.
* insettext.C (getLyXText): use 'lt' to assure we're not erasing the
LyXText which is marked for removal while we're using it!
* insettext.h: added private LyXText * lt to use it to assure we are
not deleting our LyXText while we're using it!
2001-07-11 Juergen Vigna <jug@sad.it>
* insettext.C (insertInset): check if we are before the inset after
inserting it! This check IS needed. Remove the Undo-Call as it is
called in LyXText::insertInset!
* insettext.h: added struct InnerCache.
* insettext.C (deleteLyXText): insert a new InnerCache mechanism so
that we ONLY delete the LyXText in the getLyXText() routine. So we
are sure we don't delete LyXText while someone is working with it!
2001-07-12 Lars Gullik Bjønnes <larsbj@birdstep.com> 2001-07-12 Lars Gullik Bjønnes <larsbj@birdstep.com>
* insetexternal.C: (*it). -> it-> * insetexternal.C: (*it). -> it->

View File

@ -369,7 +369,9 @@ public:
/// ///
virtual bool insertInsetAllowed(Inset *) const { return false; } virtual bool insertInsetAllowed(Inset *) const { return false; }
/// ///
virtual UpdatableInset * getLockingInset() { return this; } virtual UpdatableInset * getLockingInset() const {
return const_cast<UpdatableInset *>(this);
}
/// ///
virtual UpdatableInset * getFirstLockingInsetOfType(Inset::Code c) virtual UpdatableInset * getFirstLockingInsetOfType(Inset::Code c)
{ return (c == lyxCode()) ? this : 0; } { return (c == lyxCode()) ? this : 0; }

View File

@ -425,11 +425,11 @@ void InsetCollapsable::toggleInsetCursor(BufferView * bv)
} }
UpdatableInset * InsetCollapsable::getLockingInset() UpdatableInset * InsetCollapsable::getLockingInset() const
{ {
UpdatableInset * in = inset.getLockingInset(); UpdatableInset * in = inset.getLockingInset();
if (&inset == in) if (&inset == in)
return this; return const_cast<InsetCollapsable *>(this);
return in; return in;
} }

View File

@ -111,7 +111,7 @@ public:
/// ///
void toggleInsetCursor(BufferView *); void toggleInsetCursor(BufferView *);
/// ///
UpdatableInset * getLockingInset(); UpdatableInset * getLockingInset() const;
/// ///
UpdatableInset * getFirstLockingInsetOfType(Inset::Code); UpdatableInset * getFirstLockingInsetOfType(Inset::Code);
/// ///

View File

@ -236,8 +236,13 @@ int InsetFloat::docBook(Buffer const * buf, ostream & os) const
bool InsetFloat::insertInsetAllowed(Inset * in) const bool InsetFloat::insertInsetAllowed(Inset * in) const
{ {
if (in->lyxCode() == Inset::FLOAT_CODE)
return false;
if (inset.getLockingInset() != this)
return inset.insertInsetAllowed(in);
if ((in->lyxCode() == Inset::FOOT_CODE) || if ((in->lyxCode() == Inset::FOOT_CODE) ||
(in->lyxCode() == Inset::MARGIN_CODE)) { (in->lyxCode() == Inset::MARGIN_CODE))
{
return false; return false;
} }
return true; return true;

View File

@ -632,9 +632,10 @@ unsigned int InsetTabular::insetInInsetY()
} }
UpdatableInset * InsetTabular::getLockingInset() UpdatableInset * InsetTabular::getLockingInset() const
{ {
return the_locking_inset ? the_locking_inset->getLockingInset() : this; return the_locking_inset ? the_locking_inset->getLockingInset() :
const_cast<InsetTabular *>(this);
} }

View File

@ -117,7 +117,7 @@ public:
/// ///
unsigned int insetInInsetY(); unsigned int insetInInsetY();
/// ///
UpdatableInset * getLockingInset(); UpdatableInset * getLockingInset() const;
/// ///
UpdatableInset * getFirstLockingInsetOfType(Inset::Code); UpdatableInset * getFirstLockingInsetOfType(Inset::Code);
/// ///

View File

@ -14,6 +14,7 @@
#include <algorithm> #include <algorithm>
#include <cstdlib> #include <cstdlib>
//#include <signal.h>
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation #pragma implementation
@ -61,6 +62,55 @@ extern unsigned char getCurrentTextClass(Buffer *);
extern bool math_insert_greek(BufferView *, char); extern bool math_insert_greek(BufferView *, char);
extern int greek_kb_flag; extern int greek_kb_flag;
#warning this functions should probably go into bufferview_funcs somehow (Jug)
void InsetText::saveLyXTextState(LyXText * t) const
{
sstate.lpar = t->cursor.par();
sstate.pos = t->cursor.pos();
sstate.boundary = t->cursor.boundary();
sstate.selstartpar = t->selection.start.par();
sstate.selstartpos = t->selection.start.pos();
sstate.selstartboundary = t->selection.start.boundary();
sstate.selendpar = t->selection.end.par();
sstate.selendpos = t->selection.end.pos();
sstate.selendboundary = t->selection.end.boundary();
sstate.selection = t->selection.set();
sstate.mark_set = t->selection.mark();
}
void InsetText::restoreLyXTextState(BufferView * bv, LyXText * t) const
{
if (sstate.lpar) {
t->selection.set(true);
/* at this point just to avoid the Delete-Empty-Paragraph
* Mechanism when setting the cursor */
t->selection.mark(sstate.mark_set);
if (sstate.selection) {
t->setCursor(bv, sstate.selstartpar, sstate.selstartpos,
true, sstate.selstartboundary);
t->selection.cursor = t->cursor;
t->setCursor(bv, sstate.selendpar, sstate.selendpos,
true, sstate.selendboundary);
t->setSelection(bv);
t->setCursor(bv, sstate.lpar, sstate.pos);
} else {
t->setCursor(bv, sstate.lpar, sstate.pos, true, sstate.boundary);
t->selection.cursor = t->cursor;
t->selection.set(false);
}
}
}
InsetText::InnerCache::InnerCache(boost::shared_ptr<LyXText> t)
{
text = t;
remove = false;
}
InsetText::InsetText() InsetText::InsetText()
{ {
par = new Paragraph; par = new Paragraph;
@ -116,6 +166,8 @@ void InsetText::init(InsetText const * ins, bool same_id)
last_drawn_width = -1; last_drawn_width = -1;
frame_is_visible = false; frame_is_visible = false;
cached_bview = 0; cached_bview = 0;
sstate.lpar = 0;
lt = 0;
} }
@ -221,11 +273,17 @@ int InsetText::ascent(BufferView * bv, LyXFont const &) const
int InsetText::descent(BufferView * bv, LyXFont const &) const int InsetText::descent(BufferView * bv, LyXFont const &) const
{ {
LyXText * t = getLyXText(bv); bool clear = false;
if (!lt) {
lt = getLyXText(bv);
clear = true;
}
int y_temp = 0; int y_temp = 0;
Row * row = t->getRowNearY(y_temp); Row * row = lt->getRowNearY(y_temp);
insetDescent = t->height - row->ascent_of_text() + insetDescent = lt->height - row->ascent_of_text() +
TEXT_TO_INSET_OFFSET; TEXT_TO_INSET_OFFSET;
if (clear)
lt = 0;
return insetDescent; return insetDescent;
} }
@ -301,11 +359,7 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
bv->text->status(bv, LyXText::CHANGED_IN_DRAW); bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
} }
top_x = int(x); top_x = int(x);
#if 1
clearInset(pain, baseline, cleared); clearInset(pain, baseline, cleared);
#else
return;
#endif
} }
// lyxerr << "InsetText::draw[" << this << "](" << need_update << ":" << int(x) << ":" << top_x << ")\n"; // lyxerr << "InsetText::draw[" << this << "](" << need_update << ":" << int(x) << ":" << top_x << ")\n";
@ -332,10 +386,15 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
need_update = NONE; need_update = NONE;
return; return;
} }
bool clear = false;
if (!lt) {
lt = getLyXText(bv);
clear = true;
}
x += TEXT_TO_INSET_OFFSET; x += TEXT_TO_INSET_OFFSET;
int y = 0; int y = 0;
Row * row = getLyXText(bv)->getRowNearY(y); Row * row = lt->getRowNearY(y);
int y_offset = baseline - row->ascent_of_text(); int y_offset = baseline - row->ascent_of_text();
int ph = pain.paperHeight(); int ph = pain.paperHeight();
int first = 0; int first = 0;
@ -347,12 +406,12 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
} }
if (y_offset < 0) if (y_offset < 0)
y_offset = y; y_offset = y;
getLyXText(bv)->first = first; lt->first = first;
if (cleared) { if (cleared) {
int yf = y_offset; int yf = y_offset;
y = 0; y = 0;
while ((row != 0) && (yf < ph)) { while ((row != 0) && (yf < ph)) {
getLyXText(bv)->getVisibleRow(bv, y+y_offset, int(x), row, lt->getVisibleRow(bv, y+y_offset, int(x), row,
y+first, cleared); y+first, cleared);
y += row->height(); y += row->height();
yf += row->height(); yf += row->height();
@ -360,26 +419,26 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
} }
} else if (!locked) { } else if (!locked) {
if (need_update & CURSOR) { if (need_update & CURSOR) {
bv->screen()->toggleSelection(getLyXText(bv), bv, true, y_offset,int(x)); bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
getLyXText(bv)->clearSelection(bv); lt->clearSelection(bv);
getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; lt->selection.cursor = lt->cursor;
} }
bv->screen()->update(getLyXText(bv), bv, y_offset, int(x)); bv->screen()->update(lt, bv, y_offset, int(x));
} else { } else {
locked = false; locked = false;
if (need_update & SELECTION) if (need_update & SELECTION)
bv->screen()->toggleToggle(getLyXText(bv), bv, y_offset, int(x)); bv->screen()->toggleToggle(lt, bv, y_offset, int(x));
else if (need_update & CURSOR) { else if (need_update & CURSOR) {
bv->screen()->toggleSelection(getLyXText(bv), bv, true, y_offset,int(x)); bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x));
getLyXText(bv)->clearSelection(bv); lt->clearSelection(bv);
getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; lt->selection.cursor = lt->cursor;
} }
bv->screen()->update(getLyXText(bv), bv, y_offset, int(x)); bv->screen()->update(lt, bv, y_offset, int(x));
locked = true; locked = true;
} }
getLyXText(bv)->refresh_y = 0; lt->refresh_y = 0;
getLyXText(bv)->status(bv, LyXText::UNCHANGED); lt->status(bv, LyXText::UNCHANGED);
if ((need_update != CURSOR_PAR) && if ((need_update != CURSOR_PAR) &&
((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked)))
drawFrame(pain, cleared); drawFrame(pain, cleared);
@ -390,6 +449,8 @@ void InsetText::draw(BufferView * bv, LyXFont const & f,
need_update |= INIT; need_update |= INIT;
} else if (need_update != INIT) } else if (need_update != INIT)
need_update = NONE; need_update = NONE;
if (clear)
lt = 0;
} }
@ -419,14 +480,6 @@ void InsetText::clearFrame(Painter & pain, bool cleared) const
void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit) void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
{ {
LyXText * t = getLyXText(bv);
#if 0
int ww = t->width;
t->BreakParagraph(bv);
if (ww != t->width)
reinit = true;
#endif
if (reinit) { if (reinit) {
need_update |= INIT; need_update |= INIT;
resizeLyXText(bv); resizeLyXText(bv);
@ -439,59 +492,63 @@ void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit)
inset_y = cy(bv) + drawTextYOffset; inset_y = cy(bv) + drawTextYOffset;
the_locking_inset->update(bv, font, reinit); the_locking_inset->update(bv, font, reinit);
} }
#if 0
if (need_update == INIT) { bool clear = false;
resizeLyXText(bv); if (!lt) {
need_update |= FULL; lt = getLyXText(bv);
clear = true;
} }
#endif
int oldw = insetWidth; int oldw = insetWidth;
insetWidth = t->width + (2 * TEXT_TO_INSET_OFFSET); insetWidth = lt->width + (2 * TEXT_TO_INSET_OFFSET);
if (oldw != insetWidth) { if (oldw != insetWidth) {
resizeLyXText(bv); resizeLyXText(bv);
need_update |= FULL; need_update |= FULL;
// update(bv, font, reinit);
return; return;
} }
if ((need_update & CURSOR_PAR) && (t->status() == LyXText::UNCHANGED) && if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) &&
the_locking_inset) the_locking_inset)
{ {
t->updateInset(bv, the_locking_inset); lt->updateInset(bv, the_locking_inset);
} }
if (lt->status() == LyXText::NEED_MORE_REFRESH)
if (t->status() == LyXText::NEED_MORE_REFRESH)
need_update |= FULL; need_update |= FULL;
#if 0 if (clear)
int y_temp = 0; lt = 0;
Row * row = t->GetRowNearY(y_temp);
insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
insetDescent = t->height - row->ascent_of_text() + TEXT_TO_INSET_OFFSET;
#endif
} }
void InsetText::setUpdateStatus(BufferView * bv, int what) const void InsetText::setUpdateStatus(BufferView * bv, int what) const
{ {
LyXText * t = getLyXText(bv); bool clear = false;
if (!lt) {
lt = getLyXText(bv);
clear = true;
}
need_update |= what; need_update |= what;
if (t->status() == LyXText::NEED_MORE_REFRESH) if (lt->status() == LyXText::NEED_MORE_REFRESH)
need_update |= FULL; need_update |= FULL;
else if (t->status() == LyXText::NEED_VERY_LITTLE_REFRESH) else if (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH)
need_update |= CURSOR_PAR; need_update |= CURSOR_PAR;
// this to not draw a selection when we redraw all of it! // this to not draw a selection when we redraw all of it!
if ((need_update & (INIT|FULL)) && (need_update & CURSOR)) if ((need_update & (INIT|FULL)) && (need_update & CURSOR))
t->clearSelection(bv); lt->clearSelection(bv);
if (clear)
lt = 0;
} }
void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty)
{ {
LyXText * t = getLyXText(bv); bool clear = false;
t->fullRebreak(bv); if (!lt) {
lt = getLyXText(bv);
clear = true;
}
lt->fullRebreak(bv);
setUpdateStatus(bv, what); setUpdateStatus(bv, what);
if ((need_update != CURSOR) || (t->status() != LyXText::UNCHANGED) || if ((need_update != CURSOR) || (lt->status() != LyXText::UNCHANGED) ||
t->selection.set()) lt->selection.set())
{ {
bv->updateInset(this, mark_dirty); bv->updateInset(this, mark_dirty);
} }
@ -500,6 +557,8 @@ void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty)
bv->owner()->setLayout(cpar(bv)->getLayout()); bv->owner()->setLayout(cpar(bv)->getLayout());
old_par = cpar(bv); old_par = cpar(bv);
} }
if (clear)
lt = 0;
} }
@ -525,12 +584,16 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
inset_par = 0; inset_par = 0;
old_par = 0; old_par = 0;
int tmp_y = (y < 0) ? 0 : y; int tmp_y = (y < 0) ? 0 : y;
LyXText * t = getLyXText(bv); bool clear = false;
if (!lt) {
lt = getLyXText(bv);
clear = true;
}
if (!checkAndActivateInset(bv, x, tmp_y, button)) if (!checkAndActivateInset(bv, x, tmp_y, button))
t->setCursorFromCoordinates(bv, x - drawTextXOffset, lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
y + insetAscent); y + insetAscent);
t->selection.cursor = t->cursor; lt->selection.cursor = lt->cursor;
finishUndo(); finishUndo();
showInsetCursor(bv); showInsetCursor(bv);
updateLocal(bv, CURSOR, false); updateLocal(bv, CURSOR, false);
@ -538,11 +601,13 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
// If the inset is empty set the language of the current font to the // If the inset is empty set the language of the current font to the
// language to the surronding text (if different). // language to the surronding text (if different).
if (par->size() == 0 && !par->next() && if (par->size() == 0 && !par->next() &&
bv->getParentLanguage(this) != t->current_font.language()) { bv->getParentLanguage(this) != lt->current_font.language()) {
LyXFont font(LyXFont::ALL_IGNORE); LyXFont font(LyXFont::ALL_IGNORE);
font.setLanguage(bv->getParentLanguage(this)); font.setLanguage(bv->getParentLanguage(this));
setFont(bv, font, false); setFont(bv, font, false);
} }
if (clear)
lt = 0;
} }
@ -556,9 +621,13 @@ void InsetText::insetUnlock(BufferView * bv)
no_selection = false; no_selection = false;
locked = false; locked = false;
int code = CURSOR|CLEAR_FRAME; int code = CURSOR|CLEAR_FRAME;
LyXText * t = getLyXText(bv); bool clear = false;
if (t->selection.set()) { if (!lt) {
t->clearSelection(bv); lt = getLyXText(bv);
clear = true;
}
if (lt->selection.set()) {
lt->clearSelection(bv);
code = FULL; code = FULL;
} else if (owner()) { } else if (owner()) {
bv->owner()->setLayout(owner()->getLyXText(bv) bv->owner()->setLayout(owner()->getLyXText(bv)
@ -566,6 +635,8 @@ void InsetText::insetUnlock(BufferView * bv)
} else } else
bv->owner()->setLayout(bv->text->cursor.par()->getLayout()); bv->owner()->setLayout(bv->text->cursor.par()->getLayout());
updateLocal(bv, code, false); updateLocal(bv, code, false);
if (clear)
lt = 0;
} }
@ -583,13 +654,7 @@ bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
inset_pos = cpos(bv); inset_pos = cpos(bv);
inset_par = cpar(bv); inset_par = cpar(bv);
inset_boundary = cboundary(bv); inset_boundary = cboundary(bv);
#if 0
getLyXText(bv)->clearSelection(bv);
getLyXText(bv)->sel_cursor = getLyXText(bv)->cursor;
getLyXText(bv)->UpdateInset(bv, the_locking_inset);
#else
updateLocal(bv, CURSOR, false); updateLocal(bv, CURSOR, false);
#endif
return true; return true;
} else if (the_locking_inset && (the_locking_inset == inset)) { } else if (the_locking_inset && (the_locking_inset == inset)) {
if (cpar(bv) == inset_par && cpos(bv) == inset_pos) { if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
@ -706,7 +771,7 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
paste_internally = true; paste_internally = true;
} }
getLyXText(bv)->setCursorFromCoordinates(bv, x-drawTextXOffset, getLyXText(bv)->setCursorFromCoordinates(bv, x-drawTextXOffset,
y + insetAscent); y + insetAscent);
getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor;
updateLocal(bv, CURSOR, false); updateLocal(bv, CURSOR, false);
bv->owner()->setLayout(cpar(bv)->getLayout()); bv->owner()->setLayout(cpar(bv)->getLayout());
@ -836,6 +901,11 @@ InsetText::localDispatch(BufferView * bv,
} }
} }
hideInsetCursor(bv); hideInsetCursor(bv);
bool clear = false;
if (!lt) {
lt = getLyXText(bv);
clear = true;
}
switch (action) { switch (action) {
// Normal chars // Normal chars
case LFUN_SELFINSERT: case LFUN_SELFINSERT:
@ -850,29 +920,28 @@ InsetText::localDispatch(BufferView * bv,
* "auto_region_delete", which defaults to * "auto_region_delete", which defaults to
* true (on). */ * true (on). */
LyXText * t = getLyXText(bv);
setUndo(bv, Undo::INSERT, setUndo(bv, Undo::INSERT,
t->cursor.par(), t->cursor.par()->next()); lt->cursor.par(), lt->cursor.par()->next());
bv->setState(); bv->setState();
if (lyxrc.auto_region_delete) { if (lyxrc.auto_region_delete) {
if (t->selection.set()) { if (lt->selection.set()) {
t->cutSelection(bv, false); lt->cutSelection(bv, false);
} }
} }
t->clearSelection(bv); lt->clearSelection(bv);
for (string::size_type i = 0; i < arg.length(); ++i) { for (string::size_type i = 0; i < arg.length(); ++i) {
if (greek_kb_flag) { if (greek_kb_flag) {
if (!math_insert_greek(bv, arg[i])) { if (!math_insert_greek(bv, arg[i])) {
bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], getLyXText(bv)); bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
} else if (!the_locking_inset) { } else if (!the_locking_inset) {
(void)moveRight(bv, false); (void)moveRight(bv, false);
} }
} else { } else {
bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], getLyXText(bv)); bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt);
} }
} }
} }
getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; lt->selection.cursor = lt->cursor;
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
result = DISPATCHED_NOUPDATE; result = DISPATCHED_NOUPDATE;
break; break;
@ -880,7 +949,7 @@ InsetText::localDispatch(BufferView * bv,
case LFUN_RIGHTSEL: case LFUN_RIGHTSEL:
finishUndo(); finishUndo();
moveRight(bv, false, true); moveRight(bv, false, true);
getLyXText(bv)->setSelection(bv); lt->setSelection(bv);
updateLocal(bv, SELECTION, false); updateLocal(bv, SELECTION, false);
break; break;
case LFUN_RIGHT: case LFUN_RIGHT:
@ -891,7 +960,7 @@ InsetText::localDispatch(BufferView * bv,
case LFUN_LEFTSEL: case LFUN_LEFTSEL:
finishUndo(); finishUndo();
moveLeft(bv, false, true); moveLeft(bv, false, true);
getLyXText(bv)->setSelection(bv); lt->setSelection(bv);
updateLocal(bv, SELECTION, false); updateLocal(bv, SELECTION, false);
break; break;
case LFUN_LEFT: case LFUN_LEFT:
@ -902,7 +971,7 @@ InsetText::localDispatch(BufferView * bv,
case LFUN_DOWNSEL: case LFUN_DOWNSEL:
finishUndo(); finishUndo();
moveDown(bv); moveDown(bv);
getLyXText(bv)->setSelection(bv); lt->setSelection(bv);
updateLocal(bv, SELECTION, false); updateLocal(bv, SELECTION, false);
break; break;
case LFUN_DOWN: case LFUN_DOWN:
@ -913,7 +982,7 @@ InsetText::localDispatch(BufferView * bv,
case LFUN_UPSEL: case LFUN_UPSEL:
finishUndo(); finishUndo();
moveUp(bv); moveUp(bv);
getLyXText(bv)->setSelection(bv); lt->setSelection(bv);
updateLocal(bv, SELECTION, false); updateLocal(bv, SELECTION, false);
break; break;
case LFUN_UP: case LFUN_UP:
@ -923,50 +992,47 @@ InsetText::localDispatch(BufferView * bv,
break; break;
case LFUN_HOME: case LFUN_HOME:
finishUndo(); finishUndo();
getLyXText(bv)->cursorHome(bv); lt->cursorHome(bv);
updateLocal(bv, CURSOR, false); updateLocal(bv, CURSOR, false);
break; break;
case LFUN_END: case LFUN_END:
getLyXText(bv)->cursorEnd(bv); lt->cursorEnd(bv);
updateLocal(bv, CURSOR, false); updateLocal(bv, CURSOR, false);
break; break;
case LFUN_BACKSPACE: { case LFUN_BACKSPACE: {
LyXText * t = getLyXText(bv);
setUndo(bv, Undo::DELETE, setUndo(bv, Undo::DELETE,
t->cursor.par(), t->cursor.par()->next()); lt->cursor.par(), lt->cursor.par()->next());
if (t->selection.set()) if (lt->selection.set())
t->cutSelection(bv); lt->cutSelection(bv);
else else
t->backspace(bv); lt->backspace(bv);
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
} }
break; break;
case LFUN_DELETE: { case LFUN_DELETE: {
LyXText * t = getLyXText(bv);
setUndo(bv, Undo::DELETE, setUndo(bv, Undo::DELETE,
t->cursor.par(), t->cursor.par()->next()); lt->cursor.par(), lt->cursor.par()->next());
if (t->selection.set()) { if (lt->selection.set()) {
t->cutSelection(bv); lt->cutSelection(bv);
} else { } else {
t->Delete(bv); lt->Delete(bv);
} }
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
} }
break; break;
case LFUN_CUT: { case LFUN_CUT: {
LyXText * t = getLyXText(bv);
setUndo(bv, Undo::DELETE, setUndo(bv, Undo::DELETE,
t->cursor.par(), t->cursor.par()->next()); lt->cursor.par(), lt->cursor.par()->next());
t->cutSelection(bv); lt->cutSelection(bv);
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
} }
break; break;
case LFUN_COPY: case LFUN_COPY:
finishUndo(); finishUndo();
getLyXText(bv)->copySelection(bv); lt->copySelection(bv);
updateLocal(bv, CURSOR_PAR, false); updateLocal(bv, CURSOR_PAR, false);
break; break;
case LFUN_PASTESELECTION: case LFUN_PASTESELECTION:
@ -976,9 +1042,9 @@ InsetText::localDispatch(BufferView * bv,
if (clip.empty()) if (clip.empty())
break; break;
if (arg == "paragraph") { if (arg == "paragraph") {
getLyXText(bv)->insertStringAsParagraphs(bv, clip); lt->insertStringAsParagraphs(bv, clip);
} else { } else {
getLyXText(bv)->insertStringAsLines(bv, clip); lt->insertStringAsLines(bv, clip);
} }
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
break; break;
@ -993,34 +1059,38 @@ InsetText::localDispatch(BufferView * bv,
break; break;
} }
} }
LyXText * t = getLyXText(bv);
setUndo(bv, Undo::INSERT, setUndo(bv, Undo::INSERT,
t->cursor.par(), t->cursor.par()->next()); lt->cursor.par(), lt->cursor.par()->next());
t->pasteSelection(bv); lt->pasteSelection(bv);
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
} }
break; break;
case LFUN_BREAKPARAGRAPH: case LFUN_BREAKPARAGRAPH:
if (!autoBreakRows) if (!autoBreakRows) {
return DISPATCHED; result = DISPATCHED;
getLyXText(bv)->breakParagraph(bv, 0); break;
}
lt->breakParagraph(bv, 0);
updateLocal(bv, FULL, true); updateLocal(bv, FULL, true);
break; break;
case LFUN_BREAKPARAGRAPHKEEPLAYOUT: case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
if (!autoBreakRows) if (!autoBreakRows) {
return DISPATCHED; result = DISPATCHED;
getLyXText(bv)->breakParagraph(bv, 1); break;
}
lt->breakParagraph(bv, 1);
updateLocal(bv, FULL, true); updateLocal(bv, FULL, true);
break; break;
case LFUN_BREAKLINE: { case LFUN_BREAKLINE: {
if (!autoBreakRows) if (!autoBreakRows) {
return DISPATCHED; result = DISPATCHED;
LyXText * t = getLyXText(bv); break;
}
setUndo(bv, Undo::INSERT, setUndo(bv, Undo::INSERT,
t->cursor.par(), t->cursor.par()->next()); lt->cursor.par(), lt->cursor.par()->next());
t->insertChar(bv, Paragraph::META_NEWLINE); lt->insertChar(bv, Paragraph::META_NEWLINE);
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
} }
break; break;
@ -1054,7 +1124,7 @@ InsetText::localDispatch(BufferView * bv,
if (cur_layout != layout.second) { if (cur_layout != layout.second) {
cur_layout = layout.second; cur_layout = layout.second;
getLyXText(bv)->setLayout(bv, layout.second); lt->setLayout(bv, layout.second);
bv->owner()->setLayout(cpar(bv)->getLayout()); bv->owner()->setLayout(cpar(bv)->getLayout());
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
} }
@ -1068,7 +1138,7 @@ InsetText::localDispatch(BufferView * bv,
// it also seems to me that the paragraphs inside the insettext // it also seems to me that the paragraphs inside the insettext
// inherit bufferparams/paragraphparams in a strange way. (Lgb) // inherit bufferparams/paragraphparams in a strange way. (Lgb)
{ {
Paragraph * par = getLyXText(bv)->cursor.par(); Paragraph * par = lt->cursor.par();
Spacing::Space cur_spacing = par->params().spacing().getSpace(); Spacing::Space cur_spacing = par->params().spacing().getSpace();
float cur_value = 1.0; float cur_value = 1.0;
if (cur_spacing == Spacing::Other) { if (cur_spacing == Spacing::Other) {
@ -1104,9 +1174,7 @@ InsetText::localDispatch(BufferView * bv,
} }
if (cur_spacing != new_spacing || cur_value != new_value) { if (cur_spacing != new_spacing || cur_value != new_value) {
par->params().spacing(Spacing(new_spacing, new_value)); par->params().spacing(Spacing(new_spacing, new_value));
//getLyXText(bv)->RedoParagraph(owner->view());
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
//bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
} }
} }
break; break;
@ -1118,7 +1186,7 @@ InsetText::localDispatch(BufferView * bv,
} }
/// If the action has deleted all text in the inset, we need to change the /// If the action has deleted all text in the inset, we need to change the
// language to the language to the surronding text. // language to the language of the surronding text.
if (par->size() == 0 && !par->next()) { if (par->size() == 0 && !par->next()) {
LyXFont font(LyXFont::ALL_IGNORE); LyXFont font(LyXFont::ALL_IGNORE);
font.setLanguage(bv->getParentLanguage(this)); font.setLanguage(bv->getParentLanguage(this));
@ -1129,6 +1197,8 @@ InsetText::localDispatch(BufferView * bv,
showInsetCursor(bv); showInsetCursor(bv);
} else } else
bv->unlockInset(this); bv->unlockInset(this);
if (clear)
lt = 0;
return result; return result;
} }
@ -1338,28 +1408,39 @@ bool InsetText::insertInset(BufferView * bv, Inset * inset)
return the_locking_inset->insertInset(bv, inset); return the_locking_inset->insertInset(bv, inset);
return false; return false;
} }
LyXText * t = getLyXText(bv);
setUndo(bv, Undo::INSERT,
t->cursor.par(), t->cursor.par()->next());
inset->setOwner(this); inset->setOwner(this);
hideInsetCursor(bv); hideInsetCursor(bv);
t = getLyXText(bv);
t->insertInset(bv, inset); bool clear = false;
#if 0 if (!lt) {
if ((cpar(bv)->GetChar(cpos(bv)) != Paragraph::META_INSET) || lt = getLyXText(bv);
(cpar(bv)->GetInset(cpos(bv)) != inset)) clear = true;
t->CursorLeft(bv); }
#endif lt->insertInset(bv, inset);
bv->fitCursor(t); if ((cpar(bv)->getChar(cpos(bv)) != Paragraph::META_INSET) ||
(cpar(bv)->getInset(cpos(bv)) != inset))
lt->cursorLeft(bv);
bv->fitCursor(lt);
updateLocal(bv, CURSOR_PAR|CURSOR, true); updateLocal(bv, CURSOR_PAR|CURSOR, true);
showInsetCursor(bv); showInsetCursor(bv);
if (clear)
lt = 0;
return true; return true;
} }
UpdatableInset * InsetText::getLockingInset() bool InsetText::insertInsetAllowed(Inset * in) const
{ {
return the_locking_inset ? the_locking_inset->getLockingInset() : this; if (the_locking_inset)
return the_locking_inset->insertInsetAllowed(in);
return true;
}
UpdatableInset * InsetText::getLockingInset() const
{
return the_locking_inset ? the_locking_inset->getLockingInset() :
const_cast<InsetText *>(this);
} }
@ -1406,25 +1487,30 @@ void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall,
the_locking_inset->setFont(bv, font, toggleall, selectall); the_locking_inset->setFont(bv, font, toggleall, selectall);
return; return;
} }
LyXText * t = getLyXText(bv); bool clear = false;
if (t->selection.set()) { if (!lt) {
setUndo(bv, Undo::EDIT, lt = getLyXText(bv);
t->cursor.par(), t->cursor.par()->next()); clear = true;
}
if (lt->selection.set()) {
setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next());
} }
if (selectall) if (selectall)
selectAll(bv); selectAll(bv);
#if 1 #if 1
t->toggleFree(bv, font, toggleall); lt->toggleFree(bv, font, toggleall);
#else #else
t->setFont(bv, font, toggleall); lt->setFont(bv, font, toggleall);
#endif #endif
if (selectall) if (selectall)
t->clearSelection(bv); lt->clearSelection(bv);
bv->fitCursor(t); bv->fitCursor(lt);
if (selectall || t->selection.set()) if (selectall || lt->selection.set())
updateLocal(bv, FULL, true); updateLocal(bv, FULL, true);
else else
updateLocal(bv, CURSOR_PAR, true); updateLocal(bv, CURSOR_PAR, true);
if (clear)
lt = 0;
} }
@ -1569,15 +1655,21 @@ void InsetText::setFrameColor(BufferView * bv, LColor::color col)
int InsetText::cx(BufferView * bv) const int InsetText::cx(BufferView * bv) const
{ {
LyXText * text = getLyXText(bv); bool clear = false;
int x = text->cursor.x() + top_x + TEXT_TO_INSET_OFFSET; if (!lt) {
lt = getLyXText(bv);
clear = true;
}
int x = lt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET;
if (the_locking_inset) { if (the_locking_inset) {
LyXFont font = text->getFont(bv->buffer(), LyXFont font = lt->getFont(bv->buffer(),
text->cursor.par(), lt->cursor.par(),
text->cursor.pos()); lt->cursor.pos());
if (font.isVisibleRightToLeft()) if (font.isVisibleRightToLeft())
x -= the_locking_inset->width(bv, font); x -= the_locking_inset->width(bv, font);
} }
if (clear)
lt = 0;
return x; return x;
} }
@ -1625,26 +1717,32 @@ LyXText * InsetText::getLyXText(BufferView const * lbv,
cached_bview = bv; cached_bview = bv;
Cache::iterator it = cache.find(bv); Cache::iterator it = cache.find(bv);
if (it != cache.end()) { if (it != cache.end() && (lt || !it->second.remove)) {
lyx::Assert(it->second.get()); lyx::Assert(it->second.text.get());
cached_text = it->second; cached_text = it->second.text;
if (recursive && the_locking_inset) { if (recursive && the_locking_inset) {
return the_locking_inset->getLyXText(bv); return the_locking_inset->getLyXText(bv);
} }
return cached_text.get(); return cached_text.get();
} else if (it->second.remove) {
if (locked) {
saveLyXTextState(it->second.text.get());
} else {
sstate.lpar = 0;
}
cache.erase(bv);
// raise(SIGSTOP);
} }
cached_text.reset(new LyXText(const_cast<InsetText *>(this))); cached_text.reset(new LyXText(const_cast<InsetText *>(this)));
cached_text->init(bv); cached_text->init(bv);
restoreLyXTextState(bv, cached_text.get());
cache.insert(make_pair(bv, cached_text)); cache.insert(make_pair(bv, cached_text));
if (the_locking_inset) { if (the_locking_inset && recursive) {
cached_text->setCursor(bv, inset_par, inset_pos, return the_locking_inset->getLyXText(bv);
true, inset_boundary);
if (recursive) {
return the_locking_inset->getLyXText(bv);
}
} }
return cached_text.get(); return cached_text.get();
} }
@ -1660,9 +1758,9 @@ void InsetText::deleteLyXText(BufferView * bv, bool recursive) const
return; return;
} }
lyx::Assert(it->second.get()); lyx::Assert(it->second.text.get());
cache.erase(bv); it->second.remove = true;
if (recursive) { if (recursive) {
/// then remove all LyXText in text-insets /// then remove all LyXText in text-insets
Paragraph * p = par; Paragraph * p = par;
@ -1685,57 +1783,10 @@ void InsetText::resizeLyXText(BufferView * bv, bool force) const
if (it == cache.end()) { if (it == cache.end()) {
return; return;
} }
lyx::Assert(it->second.get()); lyx::Assert(it->second.text.get());
Paragraph * lpar = 0;
Paragraph * selstartpar = 0;
Paragraph * selendpar = 0;
Paragraph::size_type pos = 0;
Paragraph::size_type selstartpos = 0;
Paragraph::size_type selendpos = 0;
bool boundary = false;
bool selstartboundary = false;
bool selendboundary = false;
bool selection = false;
bool mark_set = false;
// bv->owner()->prohibitInput();
if (locked) {
LyXText * t = getLyXText(bv);
lpar = t->cursor.par();
pos = t->cursor.pos();
boundary = t->cursor.boundary();
selstartpar = t->selection.start.par();
selstartpos = t->selection.start.pos();
selstartboundary = t->selection.start.boundary();
selendpar = t->selection.end.par();
selendpos = t->selection.end.pos();
selendboundary = t->selection.end.boundary();
selection = t->selection.set();
mark_set = t->selection.mark();
}
deleteLyXText(bv, (the_locking_inset == 0) || force); deleteLyXText(bv, (the_locking_inset == 0) || force);
if (lpar) {
LyXText * t = getLyXText(bv);
t->selection.set(true);
/* at this point just to avoid the Delete-Empty-Paragraph
* Mechanism when setting the cursor */
t->selection.mark(mark_set);
if (selection) {
t->setCursor(bv, selstartpar, selstartpos, true, selstartboundary);
t->selection.cursor = t->cursor;
t->setCursor(bv, selendpar, selendpos, true, selendboundary);
t->setSelection(bv);
t->setCursor(bv, lpar, pos);
} else {
t->setCursor(bv, lpar, pos, true, boundary);
t->selection.cursor = t->cursor;
t->selection.set(false);
}
}
if (bv->screen()) { if (bv->screen()) {
LyXText * t = getLyXText(bv); LyXText * t = getLyXText(bv);
t->first = bv->screen()->topCursorVisible(t); t->first = bv->screen()->topCursorVisible(t);
@ -1743,7 +1794,6 @@ void InsetText::resizeLyXText(BufferView * bv, bool force) const
// this will scroll the screen such that the cursor becomes visible // this will scroll the screen such that the cursor becomes visible
bv->updateScrollbar(); bv->updateScrollbar();
// bv->owner()->allowInput();
if (the_locking_inset) { if (the_locking_inset) {
/// then resize all LyXText in text-insets /// then resize all LyXText in text-insets
inset_x = cx(bv) - top_x + drawTextXOffset; inset_x = cx(bv) - top_x + drawTextXOffset;

View File

@ -152,9 +152,9 @@ public:
/// ///
bool insertInset(BufferView *, Inset *); bool insertInset(BufferView *, Inset *);
/// ///
bool insertInsetAllowed(Inset *) const { return true; } bool insertInsetAllowed(Inset *) const;
/// ///
UpdatableInset * getLockingInset(); UpdatableInset * getLockingInset() const;
/// ///
UpdatableInset * getFirstLockingInsetOfType(Inset::Code); UpdatableInset * getFirstLockingInsetOfType(Inset::Code);
/// ///
@ -234,8 +234,14 @@ protected:
LColor::color frame_color; LColor::color frame_color;
private: private:
struct InnerCache {
InnerCache(boost::shared_ptr<LyXText>);
boost::shared_ptr<LyXText> text;
bool remove;
};
/// ///
typedef std::map<BufferView *, boost::shared_ptr<LyXText> > Cache; typedef std::map<BufferView *, struct InnerCache > Cache;
/// ///
typedef Cache::value_type value_type; typedef Cache::value_type value_type;
/// ///
@ -294,6 +300,9 @@ private:
void clearFrame(Painter &, bool cleared) const; void clearFrame(Painter &, bool cleared) const;
/// ///
void clearInset(Painter &, int baseline, bool & cleared) const; void clearInset(Painter &, int baseline, bool & cleared) const;
///
void saveLyXTextState(LyXText *) const;
void restoreLyXTextState(BufferView *, LyXText *) const;
/* Private structures and variables */ /* Private structures and variables */
/// ///
@ -342,5 +351,23 @@ private:
mutable BufferView * cached_bview; mutable BufferView * cached_bview;
/// ///
mutable boost::shared_ptr<LyXText> cached_text; mutable boost::shared_ptr<LyXText> cached_text;
///
mutable struct save_state {
Paragraph * lpar;
Paragraph * selstartpar;
Paragraph * selendpar;
Paragraph::size_type pos;
Paragraph::size_type selstartpos;
Paragraph::size_type selendpos;
bool boundary;
bool selstartboundary;
bool selendboundary;
bool selection;
bool mark_set;
} sstate;
///
// this is needed globally so we know that we're using it actually and
// so the LyXText-Cache is not erased until used!
mutable LyXText * lt;
}; };
#endif #endif