From: Jürgen Vigna Date: Thu, 12 Jul 2001 12:26:06 +0000 (+0000) Subject: This fixes a real bug in InsetText where it was possible to delete the X-Git-Tag: 1.6.10~21097 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=8dc8a363709d38a087532d6fe8b1c6f9d11aca4e;p=features.git 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 --- diff --git a/po/POTFILES.in b/po/POTFILES.in index 336d2f748e..300a18a53d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,7 @@ src/converter.C src/CutAndPaste.C src/debug.C src/exporter.C +src/ext_l10n.h src/figure_form.C src/figureForm.C src/FontLoader.C diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index dff8f7dede..d4809a166a 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,25 @@ +2001-07-12 Juergen Vigna + + * 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 + + * 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 * insetexternal.C: (*it). -> it-> diff --git a/src/insets/inset.h b/src/insets/inset.h index b9eb820b9c..2b089cf867 100644 --- a/src/insets/inset.h +++ b/src/insets/inset.h @@ -369,7 +369,9 @@ public: /// virtual bool insertInsetAllowed(Inset *) const { return false; } /// - virtual UpdatableInset * getLockingInset() { return this; } + virtual UpdatableInset * getLockingInset() const { + return const_cast(this); + } /// virtual UpdatableInset * getFirstLockingInsetOfType(Inset::Code c) { return (c == lyxCode()) ? this : 0; } diff --git a/src/insets/insetcollapsable.C b/src/insets/insetcollapsable.C index 43d93e6918..278af604c8 100644 --- a/src/insets/insetcollapsable.C +++ b/src/insets/insetcollapsable.C @@ -425,11 +425,11 @@ void InsetCollapsable::toggleInsetCursor(BufferView * bv) } -UpdatableInset * InsetCollapsable::getLockingInset() +UpdatableInset * InsetCollapsable::getLockingInset() const { UpdatableInset * in = inset.getLockingInset(); if (&inset == in) - return this; + return const_cast(this); return in; } diff --git a/src/insets/insetcollapsable.h b/src/insets/insetcollapsable.h index 486a991bd6..c58e20dd04 100644 --- a/src/insets/insetcollapsable.h +++ b/src/insets/insetcollapsable.h @@ -111,7 +111,7 @@ public: /// void toggleInsetCursor(BufferView *); /// - UpdatableInset * getLockingInset(); + UpdatableInset * getLockingInset() const; /// UpdatableInset * getFirstLockingInsetOfType(Inset::Code); /// diff --git a/src/insets/insetfloat.C b/src/insets/insetfloat.C index 5942f6b90d..a45e63a882 100644 --- a/src/insets/insetfloat.C +++ b/src/insets/insetfloat.C @@ -236,8 +236,13 @@ int InsetFloat::docBook(Buffer const * buf, ostream & os) 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) || - (in->lyxCode() == Inset::MARGIN_CODE)) { + (in->lyxCode() == Inset::MARGIN_CODE)) + { return false; } return true; diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index 2fda1bfe29..64bdd4d84d 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -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(this); } diff --git a/src/insets/insettabular.h b/src/insets/insettabular.h index daacf2d4d9..5d5af999f4 100644 --- a/src/insets/insettabular.h +++ b/src/insets/insettabular.h @@ -117,7 +117,7 @@ public: /// unsigned int insetInInsetY(); /// - UpdatableInset * getLockingInset(); + UpdatableInset * getLockingInset() const; /// UpdatableInset * getFirstLockingInsetOfType(Inset::Code); /// diff --git a/src/insets/insettext.C b/src/insets/insettext.C index dee8bec63f..d4057cec57 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -14,6 +14,7 @@ #include #include +//#include #ifdef __GNUG__ #pragma implementation @@ -61,6 +62,55 @@ extern unsigned char getCurrentTextClass(Buffer *); extern bool math_insert_greek(BufferView *, char); 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 t) +{ + text = t; + remove = false; +} + + InsetText::InsetText() { par = new Paragraph; @@ -116,6 +166,8 @@ void InsetText::init(InsetText const * ins, bool same_id) last_drawn_width = -1; frame_is_visible = false; 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 { - LyXText * t = getLyXText(bv); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } int y_temp = 0; - Row * row = t->getRowNearY(y_temp); - insetDescent = t->height - row->ascent_of_text() + + Row * row = lt->getRowNearY(y_temp); + insetDescent = lt->height - row->ascent_of_text() + TEXT_TO_INSET_OFFSET; + if (clear) + lt = 0; return insetDescent; } @@ -301,11 +359,7 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, bv->text->status(bv, LyXText::CHANGED_IN_DRAW); } top_x = int(x); -#if 1 clearInset(pain, baseline, cleared); -#else - return; -#endif } // 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; return; } + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } x += TEXT_TO_INSET_OFFSET; int y = 0; - Row * row = getLyXText(bv)->getRowNearY(y); + Row * row = lt->getRowNearY(y); int y_offset = baseline - row->ascent_of_text(); int ph = pain.paperHeight(); int first = 0; @@ -347,12 +406,12 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, } if (y_offset < 0) y_offset = y; - getLyXText(bv)->first = first; + lt->first = first; if (cleared) { int yf = y_offset; y = 0; 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 += row->height(); yf += row->height(); @@ -360,26 +419,26 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, } } else if (!locked) { if (need_update & CURSOR) { - bv->screen()->toggleSelection(getLyXText(bv), bv, true, y_offset,int(x)); - getLyXText(bv)->clearSelection(bv); - getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; + bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x)); + lt->clearSelection(bv); + 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 { locked = false; 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) { - bv->screen()->toggleSelection(getLyXText(bv), bv, true, y_offset,int(x)); - getLyXText(bv)->clearSelection(bv); - getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; + bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x)); + lt->clearSelection(bv); + 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; } - getLyXText(bv)->refresh_y = 0; - getLyXText(bv)->status(bv, LyXText::UNCHANGED); + lt->refresh_y = 0; + lt->status(bv, LyXText::UNCHANGED); if ((need_update != CURSOR_PAR) && ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) drawFrame(pain, cleared); @@ -390,6 +449,8 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, need_update |= INIT; } else if (need_update != INIT) 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) { - LyXText * t = getLyXText(bv); - -#if 0 - int ww = t->width; - t->BreakParagraph(bv); - if (ww != t->width) - reinit = true; -#endif if (reinit) { need_update |= INIT; resizeLyXText(bv); @@ -439,59 +492,63 @@ void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit) inset_y = cy(bv) + drawTextYOffset; the_locking_inset->update(bv, font, reinit); } -#if 0 - if (need_update == INIT) { - resizeLyXText(bv); - need_update |= FULL; + + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; } -#endif int oldw = insetWidth; - insetWidth = t->width + (2 * TEXT_TO_INSET_OFFSET); + insetWidth = lt->width + (2 * TEXT_TO_INSET_OFFSET); if (oldw != insetWidth) { resizeLyXText(bv); need_update |= FULL; -// update(bv, font, reinit); return; } - if ((need_update & CURSOR_PAR) && (t->status() == LyXText::UNCHANGED) && + if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) && the_locking_inset) { - t->updateInset(bv, the_locking_inset); + lt->updateInset(bv, the_locking_inset); } - - if (t->status() == LyXText::NEED_MORE_REFRESH) + if (lt->status() == LyXText::NEED_MORE_REFRESH) need_update |= FULL; -#if 0 - int y_temp = 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 + if (clear) + lt = 0; } 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; - if (t->status() == LyXText::NEED_MORE_REFRESH) + if (lt->status() == LyXText::NEED_MORE_REFRESH) 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; // this to not draw a selection when we redraw all of it! 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) { - LyXText * t = getLyXText(bv); - t->fullRebreak(bv); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + lt->fullRebreak(bv); setUpdateStatus(bv, what); - if ((need_update != CURSOR) || (t->status() != LyXText::UNCHANGED) || - t->selection.set()) + if ((need_update != CURSOR) || (lt->status() != LyXText::UNCHANGED) || + lt->selection.set()) { 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()); 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; old_par = 0; 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)) - t->setCursorFromCoordinates(bv, x - drawTextXOffset, + lt->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent); - t->selection.cursor = t->cursor; + lt->selection.cursor = lt->cursor; finishUndo(); showInsetCursor(bv); 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 // language to the surronding text (if different). 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); font.setLanguage(bv->getParentLanguage(this)); setFont(bv, font, false); } + if (clear) + lt = 0; } @@ -556,9 +621,13 @@ void InsetText::insetUnlock(BufferView * bv) no_selection = false; locked = false; int code = CURSOR|CLEAR_FRAME; - LyXText * t = getLyXText(bv); - if (t->selection.set()) { - t->clearSelection(bv); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if (lt->selection.set()) { + lt->clearSelection(bv); code = FULL; } else if (owner()) { bv->owner()->setLayout(owner()->getLyXText(bv) @@ -566,6 +635,8 @@ void InsetText::insetUnlock(BufferView * bv) } else bv->owner()->setLayout(bv->text->cursor.par()->getLayout()); updateLocal(bv, code, false); + if (clear) + lt = 0; } @@ -583,13 +654,7 @@ bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset) inset_pos = cpos(bv); inset_par = cpar(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); -#endif return true; } else if (the_locking_inset && (the_locking_inset == inset)) { 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; } getLyXText(bv)->setCursorFromCoordinates(bv, x-drawTextXOffset, - y + insetAscent); + y + insetAscent); getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; updateLocal(bv, CURSOR, false); bv->owner()->setLayout(cpar(bv)->getLayout()); @@ -836,6 +901,11 @@ InsetText::localDispatch(BufferView * bv, } } hideInsetCursor(bv); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } switch (action) { // Normal chars case LFUN_SELFINSERT: @@ -850,29 +920,28 @@ InsetText::localDispatch(BufferView * bv, * "auto_region_delete", which defaults to * true (on). */ - LyXText * t = getLyXText(bv); setUndo(bv, Undo::INSERT, - t->cursor.par(), t->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); bv->setState(); if (lyxrc.auto_region_delete) { - if (t->selection.set()) { - t->cutSelection(bv, false); + if (lt->selection.set()) { + lt->cutSelection(bv, false); } } - t->clearSelection(bv); + lt->clearSelection(bv); for (string::size_type i = 0; i < arg.length(); ++i) { if (greek_kb_flag) { 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) { (void)moveRight(bv, false); } } 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); result = DISPATCHED_NOUPDATE; break; @@ -880,7 +949,7 @@ InsetText::localDispatch(BufferView * bv, case LFUN_RIGHTSEL: finishUndo(); moveRight(bv, false, true); - getLyXText(bv)->setSelection(bv); + lt->setSelection(bv); updateLocal(bv, SELECTION, false); break; case LFUN_RIGHT: @@ -891,7 +960,7 @@ InsetText::localDispatch(BufferView * bv, case LFUN_LEFTSEL: finishUndo(); moveLeft(bv, false, true); - getLyXText(bv)->setSelection(bv); + lt->setSelection(bv); updateLocal(bv, SELECTION, false); break; case LFUN_LEFT: @@ -902,7 +971,7 @@ InsetText::localDispatch(BufferView * bv, case LFUN_DOWNSEL: finishUndo(); moveDown(bv); - getLyXText(bv)->setSelection(bv); + lt->setSelection(bv); updateLocal(bv, SELECTION, false); break; case LFUN_DOWN: @@ -913,7 +982,7 @@ InsetText::localDispatch(BufferView * bv, case LFUN_UPSEL: finishUndo(); moveUp(bv); - getLyXText(bv)->setSelection(bv); + lt->setSelection(bv); updateLocal(bv, SELECTION, false); break; case LFUN_UP: @@ -923,50 +992,47 @@ InsetText::localDispatch(BufferView * bv, break; case LFUN_HOME: finishUndo(); - getLyXText(bv)->cursorHome(bv); + lt->cursorHome(bv); updateLocal(bv, CURSOR, false); break; case LFUN_END: - getLyXText(bv)->cursorEnd(bv); + lt->cursorEnd(bv); updateLocal(bv, CURSOR, false); break; case LFUN_BACKSPACE: { - LyXText * t = getLyXText(bv); setUndo(bv, Undo::DELETE, - t->cursor.par(), t->cursor.par()->next()); - if (t->selection.set()) - t->cutSelection(bv); + lt->cursor.par(), lt->cursor.par()->next()); + if (lt->selection.set()) + lt->cutSelection(bv); else - t->backspace(bv); + lt->backspace(bv); updateLocal(bv, CURSOR_PAR, true); } break; case LFUN_DELETE: { - LyXText * t = getLyXText(bv); setUndo(bv, Undo::DELETE, - t->cursor.par(), t->cursor.par()->next()); - if (t->selection.set()) { - t->cutSelection(bv); + lt->cursor.par(), lt->cursor.par()->next()); + if (lt->selection.set()) { + lt->cutSelection(bv); } else { - t->Delete(bv); + lt->Delete(bv); } updateLocal(bv, CURSOR_PAR, true); } break; case LFUN_CUT: { - LyXText * t = getLyXText(bv); setUndo(bv, Undo::DELETE, - t->cursor.par(), t->cursor.par()->next()); - t->cutSelection(bv); + lt->cursor.par(), lt->cursor.par()->next()); + lt->cutSelection(bv); updateLocal(bv, CURSOR_PAR, true); } break; case LFUN_COPY: finishUndo(); - getLyXText(bv)->copySelection(bv); + lt->copySelection(bv); updateLocal(bv, CURSOR_PAR, false); break; case LFUN_PASTESELECTION: @@ -976,9 +1042,9 @@ InsetText::localDispatch(BufferView * bv, if (clip.empty()) break; if (arg == "paragraph") { - getLyXText(bv)->insertStringAsParagraphs(bv, clip); + lt->insertStringAsParagraphs(bv, clip); } else { - getLyXText(bv)->insertStringAsLines(bv, clip); + lt->insertStringAsLines(bv, clip); } updateLocal(bv, CURSOR_PAR, true); break; @@ -993,34 +1059,38 @@ InsetText::localDispatch(BufferView * bv, break; } } - LyXText * t = getLyXText(bv); setUndo(bv, Undo::INSERT, - t->cursor.par(), t->cursor.par()->next()); - t->pasteSelection(bv); + lt->cursor.par(), lt->cursor.par()->next()); + lt->pasteSelection(bv); updateLocal(bv, CURSOR_PAR, true); } break; case LFUN_BREAKPARAGRAPH: - if (!autoBreakRows) - return DISPATCHED; - getLyXText(bv)->breakParagraph(bv, 0); + if (!autoBreakRows) { + result = DISPATCHED; + break; + } + lt->breakParagraph(bv, 0); updateLocal(bv, FULL, true); break; case LFUN_BREAKPARAGRAPHKEEPLAYOUT: - if (!autoBreakRows) - return DISPATCHED; - getLyXText(bv)->breakParagraph(bv, 1); + if (!autoBreakRows) { + result = DISPATCHED; + break; + } + lt->breakParagraph(bv, 1); updateLocal(bv, FULL, true); break; case LFUN_BREAKLINE: { - if (!autoBreakRows) - return DISPATCHED; - LyXText * t = getLyXText(bv); + if (!autoBreakRows) { + result = DISPATCHED; + break; + } setUndo(bv, Undo::INSERT, - t->cursor.par(), t->cursor.par()->next()); - t->insertChar(bv, Paragraph::META_NEWLINE); + lt->cursor.par(), lt->cursor.par()->next()); + lt->insertChar(bv, Paragraph::META_NEWLINE); updateLocal(bv, CURSOR_PAR, true); } break; @@ -1054,7 +1124,7 @@ InsetText::localDispatch(BufferView * bv, if (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()); updateLocal(bv, CURSOR_PAR, true); } @@ -1068,7 +1138,7 @@ InsetText::localDispatch(BufferView * bv, // it also seems to me that the paragraphs inside the insettext // 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(); float cur_value = 1.0; if (cur_spacing == Spacing::Other) { @@ -1104,9 +1174,7 @@ InsetText::localDispatch(BufferView * bv, } if (cur_spacing != new_spacing || cur_value != new_value) { par->params().spacing(Spacing(new_spacing, new_value)); - //getLyXText(bv)->RedoParagraph(owner->view()); updateLocal(bv, CURSOR_PAR, true); - //bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); } } break; @@ -1118,7 +1186,7 @@ InsetText::localDispatch(BufferView * bv, } /// 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()) { LyXFont font(LyXFont::ALL_IGNORE); font.setLanguage(bv->getParentLanguage(this)); @@ -1129,6 +1197,8 @@ InsetText::localDispatch(BufferView * bv, showInsetCursor(bv); } else bv->unlockInset(this); + if (clear) + lt = 0; return result; } @@ -1338,28 +1408,39 @@ bool InsetText::insertInset(BufferView * bv, Inset * inset) return the_locking_inset->insertInset(bv, inset); return false; } - LyXText * t = getLyXText(bv); - setUndo(bv, Undo::INSERT, - t->cursor.par(), t->cursor.par()->next()); inset->setOwner(this); hideInsetCursor(bv); - t = getLyXText(bv); - t->insertInset(bv, inset); -#if 0 - if ((cpar(bv)->GetChar(cpos(bv)) != Paragraph::META_INSET) || - (cpar(bv)->GetInset(cpos(bv)) != inset)) - t->CursorLeft(bv); -#endif - bv->fitCursor(t); + + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + lt->insertInset(bv, inset); + 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); showInsetCursor(bv); + if (clear) + lt = 0; + return true; +} + + +bool InsetText::insertInsetAllowed(Inset * in) const +{ + if (the_locking_inset) + return the_locking_inset->insertInsetAllowed(in); return true; } -UpdatableInset * InsetText::getLockingInset() +UpdatableInset * InsetText::getLockingInset() const { - return the_locking_inset ? the_locking_inset->getLockingInset() : this; + return the_locking_inset ? the_locking_inset->getLockingInset() : + const_cast(this); } @@ -1406,25 +1487,30 @@ void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall, the_locking_inset->setFont(bv, font, toggleall, selectall); return; } - LyXText * t = getLyXText(bv); - if (t->selection.set()) { - setUndo(bv, Undo::EDIT, - t->cursor.par(), t->cursor.par()->next()); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if (lt->selection.set()) { + setUndo(bv, Undo::EDIT, lt->cursor.par(), lt->cursor.par()->next()); } if (selectall) selectAll(bv); #if 1 - t->toggleFree(bv, font, toggleall); + lt->toggleFree(bv, font, toggleall); #else - t->setFont(bv, font, toggleall); + lt->setFont(bv, font, toggleall); #endif if (selectall) - t->clearSelection(bv); - bv->fitCursor(t); - if (selectall || t->selection.set()) + lt->clearSelection(bv); + bv->fitCursor(lt); + if (selectall || lt->selection.set()) updateLocal(bv, FULL, true); else 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 { - LyXText * text = getLyXText(bv); - int x = text->cursor.x() + top_x + TEXT_TO_INSET_OFFSET; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + int x = lt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET; if (the_locking_inset) { - LyXFont font = text->getFont(bv->buffer(), - text->cursor.par(), - text->cursor.pos()); + LyXFont font = lt->getFont(bv->buffer(), + lt->cursor.par(), + lt->cursor.pos()); if (font.isVisibleRightToLeft()) x -= the_locking_inset->width(bv, font); } + if (clear) + lt = 0; return x; } @@ -1625,26 +1717,32 @@ LyXText * InsetText::getLyXText(BufferView const * lbv, cached_bview = bv; Cache::iterator it = cache.find(bv); - if (it != cache.end()) { - lyx::Assert(it->second.get()); + if (it != cache.end() && (lt || !it->second.remove)) { + lyx::Assert(it->second.text.get()); - cached_text = it->second; + cached_text = it->second.text; if (recursive && the_locking_inset) { return the_locking_inset->getLyXText(bv); } 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(this))); cached_text->init(bv); + restoreLyXTextState(bv, cached_text.get()); cache.insert(make_pair(bv, cached_text)); - if (the_locking_inset) { - cached_text->setCursor(bv, inset_par, inset_pos, - true, inset_boundary); - if (recursive) { - return the_locking_inset->getLyXText(bv); - } + if (the_locking_inset && recursive) { + return the_locking_inset->getLyXText(bv); } return cached_text.get(); } @@ -1660,9 +1758,9 @@ void InsetText::deleteLyXText(BufferView * bv, bool recursive) const return; } - lyx::Assert(it->second.get()); + lyx::Assert(it->second.text.get()); - cache.erase(bv); + it->second.remove = true; if (recursive) { /// then remove all LyXText in text-insets Paragraph * p = par; @@ -1685,57 +1783,10 @@ void InsetText::resizeLyXText(BufferView * bv, bool force) const if (it == cache.end()) { return; } - lyx::Assert(it->second.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(); - } + lyx::Assert(it->second.text.get()); + 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()) { LyXText * t = getLyXText(bv); 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 bv->updateScrollbar(); -// bv->owner()->allowInput(); if (the_locking_inset) { /// then resize all LyXText in text-insets inset_x = cx(bv) - top_x + drawTextXOffset; diff --git a/src/insets/insettext.h b/src/insets/insettext.h index e2dd26bdf7..fb20a03a88 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -152,9 +152,9 @@ public: /// bool insertInset(BufferView *, Inset *); /// - bool insertInsetAllowed(Inset *) const { return true; } + bool insertInsetAllowed(Inset *) const; /// - UpdatableInset * getLockingInset(); + UpdatableInset * getLockingInset() const; /// UpdatableInset * getFirstLockingInsetOfType(Inset::Code); /// @@ -234,8 +234,14 @@ protected: LColor::color frame_color; private: + struct InnerCache { + InnerCache(boost::shared_ptr); + + boost::shared_ptr text; + bool remove; + }; /// - typedef std::map > Cache; + typedef std::map Cache; /// typedef Cache::value_type value_type; /// @@ -294,6 +300,9 @@ private: void clearFrame(Painter &, bool cleared) const; /// void clearInset(Painter &, int baseline, bool & cleared) const; + /// + void saveLyXTextState(LyXText *) const; + void restoreLyXTextState(BufferView *, LyXText *) const; /* Private structures and variables */ /// @@ -342,5 +351,23 @@ private: mutable BufferView * cached_bview; /// mutable boost::shared_ptr 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