X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsettext.C;h=3ceb4f48812088d2d5af000f6cfb8fbe54e070fe;hb=5e3b849ce7e31902e6a3b757e8a28722ea2134b6;hp=09a29c4a85feb6c552b946bb2608c534f05e81c8;hpb=9f3dd22dd39c419522914846b21dd2b45720ad0a;p=lyx.git diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 09a29c4a85..3ceb4f4881 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -1,6 +1,6 @@ /* This file is part of * ====================================================== - * + * * LyX, The Document Processor * * Copyright 1998-2001 The LyX Team. @@ -10,12 +10,6 @@ #include -#include -#include - -#include -//#include - #ifdef __GNUG__ #pragma implementation #endif @@ -29,54 +23,67 @@ #include "buffer.h" #include "LyXView.h" #include "BufferView.h" -#include "layout.h" +#include "lyxtextclasslist.h" #include "LaTeXFeatures.h" #include "Painter.h" -#include "lyx_gui_misc.h" #include "lyxtext.h" #include "lyxcursor.h" #include "CutAndPaste.h" #include "font.h" #include "LColor.h" -#include "support/textutils.h" -#include "support/LAssert.h" -#include "support/lstrings.h" #include "lyxrow.h" #include "lyxrc.h" #include "intl.h" #include "trans_mgr.h" #include "lyxscreen.h" -#include "WorkArea.h" #include "gettext.h" #include "lyxfunc.h" #include "ParagraphParameters.h" #include "undo_funcs.h" #include "lyxfind.h" +#include "frontends/Alert.h" +#include "frontends/Dialogs.h" + +#include "support/textutils.h" +#include "support/LAssert.h" +#include "support/lstrings.h" +#include "support/lyxalgo.h" // lyx::count + +#include +#include +#include +//#include + using std::ostream; using std::ifstream; using std::endl; using std::min; using std::max; using std::make_pair; +using std::vector; +using std::pair; + +using lyx::pos_type; +using lyx::textclass_type; 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) +// These functions should probably go into bufferview_funcs somehow (Jug) void InsetText::saveLyXTextState(LyXText * t) const { // check if my paragraphs are still valid Paragraph * p = par; - while(p) { + while (p) { if (p == t->cursor.par()) break; p = p->next(); } - + if (p && t->cursor.pos() <= p->size()) { sstate.lpar = t->cursor.par(); sstate.pos = t->cursor.pos(); @@ -104,10 +111,10 @@ void InsetText::restoreLyXTextState(BufferView * bv, LyXText * t) const t->selection.mark(sstate.mark_set); if (sstate.selection) { t->setCursor(bv, sstate.selstartpar, sstate.selstartpos, - true, sstate.selstartboundary); + true, sstate.selstartboundary); t->selection.cursor = t->cursor; t->setCursor(bv, sstate.selendpar, sstate.selendpos, - true, sstate.selendboundary); + true, sstate.selendboundary); t->setSelection(bv); t->setCursor(bv, sstate.lpar, sstate.pos); } else { @@ -128,11 +135,13 @@ InsetText::InnerCache::InnerCache(boost::shared_ptr t) } -InsetText::InsetText() +InsetText::InsetText(BufferParams const & bp) : UpdatableInset(), lt(0), in_update(false), do_resize(0), do_reinit(false) { par = new Paragraph; + par->layout(textclasslist[bp.textclass].defaultLayoutName()); + init(); } @@ -156,7 +165,7 @@ InsetText & InsetText::operator=(InsetText const & it) void InsetText::init(InsetText const * ins, bool same_id) { if (ins) { - setParagraphData(ins->par); + setParagraphData(ins->par, same_id); autoBreakRows = ins->autoBreakRows; drawFrame_ = ins->drawFrame_; frame_color = ins->frame_color; @@ -164,7 +173,7 @@ void InsetText::init(InsetText const * ins, bool same_id) id_ = ins->id_; } else { Paragraph * p = par; - while(p) { + while (p) { p->setInsetOwner(this); p = p->next(); } @@ -174,13 +183,11 @@ void InsetText::init(InsetText const * ins, bool same_id) autoBreakRows = false; } top_y = 0; - last_width = 0; - last_height = 0; insetAscent = 0; insetDescent = 0; insetWidth = 0; old_max_width = 0; - no_selection = false; + no_selection = true; need_update = FULL; drawTextXOffset = 0; drawTextYOffset = 0; @@ -191,6 +198,7 @@ void InsetText::init(InsetText const * ins, bool same_id) frame_is_visible = false; cached_bview = 0; sstate.lpar = 0; + in_insetAllowed = false; } @@ -199,7 +207,7 @@ InsetText::~InsetText() cached_bview = 0; // NOTE - + while (par) { Paragraph * tmp = par->next(); delete par; @@ -210,19 +218,26 @@ InsetText::~InsetText() void InsetText::clear() { + // This is a gross hack... + string old_layout = par->layout(); + while (par) { Paragraph * tmp = par->next(); delete par; par = tmp; } par = new Paragraph; + par->setInsetOwner(this); + par->layout(old_layout); + + reinitLyXText(); need_update = INIT; } Inset * InsetText::clone(Buffer const &, bool same_id) const { - return new InsetText(*this, same_id); + return new InsetText(*this, same_id); } @@ -244,11 +259,11 @@ void InsetText::read(Buffer const * buf, LyXLex & lex) string token; int pos = 0; Paragraph * return_par = 0; - Paragraph::depth_type depth = 0; + Paragraph::depth_type depth = 0; LyXFont font(LyXFont::ALL_INHERIT); clear(); - + while (lex.isOK()) { lex.nextToken(); token = lex.getString(); @@ -256,11 +271,11 @@ void InsetText::read(Buffer const * buf, LyXLex & lex) continue; if (token == "\\end_inset") { #ifndef NO_COMPABILITY - const_cast(buf)->insertErtContents(par, pos, font, false); + const_cast(buf)->insertErtContents(par, pos, false); #endif break; } - + if (const_cast(buf)-> parseSingleLyXformat2Token(lex, par, return_par, token, pos, depth, font)) { @@ -272,11 +287,11 @@ void InsetText::read(Buffer const * buf, LyXLex & lex) if (!return_par) return_par = par; par = return_par; - while(return_par) { + while (return_par) { return_par->setInsetOwner(this); return_par = return_par->next(); } - + if (token != "\\end_inset") { lex.printError("Missing \\end_inset at this point. " "Read: `$$Token'"); @@ -287,26 +302,17 @@ void InsetText::read(Buffer const * buf, LyXLex & lex) int InsetText::ascent(BufferView * bv, LyXFont const &) const { - int y_temp = 0; - Row * row = getLyXText(bv)->getRowNearY(y_temp); - insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET; + insetAscent = getLyXText(bv)->firstRow()->ascent_of_text() + + TEXT_TO_INSET_OFFSET; return insetAscent; } int InsetText::descent(BufferView * bv, LyXFont const &) const { - bool clear = false; - if (!lt) { - lt = getLyXText(bv); - clear = true; - } - int y_temp = 0; - Row * row = lt->getRowNearY(y_temp); - insetDescent = lt->height - row->ascent_of_text() + - TEXT_TO_INSET_OFFSET; - if (clear) - lt = 0; + LyXText * llt = getLyXText(bv); + insetDescent = llt->height - llt->firstRow()->ascent_of_text() + + TEXT_TO_INSET_OFFSET; return insetDescent; } @@ -330,7 +336,7 @@ int InsetText::textWidth(BufferView * bv, bool fordraw) const } if (fordraw) { return max(w - (2 * TEXT_TO_INSET_OFFSET), - (int)getLyXText(bv)->width); + (int)getLyXText(bv)->width); } else if (w < 0) { return -1; } @@ -339,42 +345,42 @@ int InsetText::textWidth(BufferView * bv, bool fordraw) const void InsetText::draw(BufferView * bv, LyXFont const & f, - int baseline, float & x, bool cleared) const + int baseline, float & x, bool cleared) const { if (nodraw()) return; Painter & pain = bv->painter(); - + // this is the first thing we have to ask because if the x pos // changed we have to do a complete rebreak of the text as we // may have few space to draw in. Well we should check on this too int old_x = top_x; if (top_x != int(x)) { top_x = int(x); + topx_set = true; int nw = getMaxWidth(bv, this); if (nw > 0 && old_max_width != nw) { need_update = INIT; old_max_width = nw; bv->text->status(bv, LyXText::CHANGED_IN_DRAW); - topx_set = true; return; - } else { - top_x = old_x; } } + // call these methods so that insetWidth, insetAscent and + // insetDescent have the right values. + width(bv, f); + ascent(bv, f); + descent(bv, f); + // repaint the background if needed if (cleared && backgroundColor() != LColor::background) { - top_x = int(x); - clearInset(pain, baseline, cleared); - top_x = old_x; + clearInset(bv, baseline, cleared); } // no draw is necessary !!! if ((drawFrame_ == LOCKED) && !locked && !par->size()) { - top_x = int(x); - topx_set = true; top_baseline = baseline; x += width(bv, f); if (need_update & CLEAR_FRAME) @@ -388,14 +394,15 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, x += static_cast(scroll()); // if top_x differs we did it already - if (!cleared && (top_x == int(x)) && - ((need_update&(INIT|FULL)) || (top_baseline!=baseline) || - (last_drawn_width!=insetWidth))) { - clearInset(pain, baseline, cleared); + if (!cleared && (old_x == int(x)) + && ((need_update&(INIT|FULL)) || (top_baseline != baseline) + ||(last_drawn_width != insetWidth))) + { + // Condition necessary to eliminate bug 59 attachment 37 + if (baseline > 0) + clearInset(bv, baseline, cleared); } - top_x = int(x); - topx_set = true; if (cleared) frame_is_visible = false; @@ -406,13 +413,11 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, } top_baseline = baseline; - top_y = baseline - ascent(bv, f); - last_width = width(bv, f); - last_height = ascent(bv, f) + descent(bv, f); + top_y = baseline - insetAscent; - if (cleared || (last_drawn_width != insetWidth)) { - if (!cleared) - clearInset(pain, baseline, cleared); + if (last_drawn_width != insetWidth) { + if (!cleared) + clearInset(bv, baseline, cleared); need_update |= FULL; last_drawn_width = insetWidth; } @@ -423,10 +428,9 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, inset_y = cy(bv) + drawTextYOffset; } if (!cleared && (need_update == CURSOR) - && !getLyXText(bv)->selection.set()) - { + && !getLyXText(bv)->selection.set()) { drawFrame(pain, cleared); - x += last_width; // was width(bv, f); + x += insetWidth; need_update = NONE; return; } @@ -437,12 +441,11 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, } x += TEXT_TO_INSET_OFFSET; - int y = 0; - Row * row = lt->getRowNearY(y); + Row * row = lt->firstRow(); int y_offset = baseline - row->ascent_of_text(); int ph = pain.paperHeight(); int first = 0; - y = y_offset; + int y = y_offset; while ((row != 0) && ((y+row->height()) <= 0)) { y += row->height(); first += row->height(); @@ -450,13 +453,13 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, } if (y_offset < 0) y_offset = y; - lt->first = first; + lt->first_y = first; if (cleared || (need_update&(INIT|FULL))) { int yf = y_offset; y = 0; while ((row != 0) && (yf < ph)) { lt->getVisibleRow(bv, y+y_offset, int(x), row, - y+first, cleared); + y+first, cleared); y += row->height(); yf += row->height(); row = row->next(); @@ -470,9 +473,9 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, bv->screen()->update(lt, bv, y_offset, int(x)); } else { locked = false; - if (need_update & SELECTION) + if (need_update & SELECTION) { bv->screen()->toggleToggle(lt, bv, y_offset, int(x)); - else if (need_update & CURSOR) { + } else if (need_update & CURSOR) { bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x)); lt->clearSelection(); lt->selection.cursor = lt->cursor; @@ -483,16 +486,22 @@ void InsetText::draw(BufferView * bv, LyXFont const & f, lt->refresh_y = 0; lt->status(bv, LyXText::UNCHANGED); - if ((need_update != CURSOR_PAR) && - ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) + if ((drawFrame_ == ALWAYS) || + ((cleared || (need_update != CURSOR_PAR)) && + (drawFrame_ == LOCKED) && locked)) + { drawFrame(pain, cleared); - else if (need_update & CLEAR_FRAME) + } else if (need_update & CLEAR_FRAME) { clearFrame(pain, cleared); - x += last_width /* was width(bv, f) */ - TEXT_TO_INSET_OFFSET; + } + + x += insetWidth - TEXT_TO_INSET_OFFSET; + if (bv->text->status() == LyXText::CHANGED_IN_DRAW) { need_update |= FULL; - } else if (need_update != INIT) + } else if (need_update != INIT) { need_update = NONE; + } if (clear) lt = 0; } @@ -504,10 +513,10 @@ void InsetText::drawFrame(Painter & pain, bool cleared) const if (!frame_is_visible || cleared) { frame_x = top_x + ttoD2; frame_y = top_baseline - insetAscent + ttoD2; - frame_w = last_width - TEXT_TO_INSET_OFFSET; + frame_w = insetWidth - TEXT_TO_INSET_OFFSET; frame_h = insetAscent + insetDescent - TEXT_TO_INSET_OFFSET; pain.rectangle(frame_x, frame_y, frame_w, frame_h, - frame_color); + frame_color); frame_is_visible = true; } } @@ -518,7 +527,7 @@ void InsetText::clearFrame(Painter & pain, bool cleared) const if (frame_is_visible) { if (!cleared) { pain.rectangle(frame_x, frame_y, frame_w, frame_h, - backgroundColor()); + backgroundColor()); } frame_is_visible = false; } @@ -537,12 +546,17 @@ void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit) in_update = true; if (reinit || need_update == INIT) { need_update = FULL; + // we should put this call where we set need_update to INIT! reinitLyXText(); if (owner()) owner()->update(bv, font, true); in_update = false; return; } + + if (!autoBreakRows && par->next()) + collapseParagraphs(bv->buffer()->params); + if (the_locking_inset) { inset_x = cx(bv) - top_x + drawTextXOffset; inset_y = cy(bv) + drawTextYOffset; @@ -554,18 +568,6 @@ void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit) lt = getLyXText(bv); clear = true; } -#if 0 - int oldw = insetWidth; - insetWidth = lt->width + (2 * TEXT_TO_INSET_OFFSET); - if (oldw != insetWidth) { - resizeLyXText(bv); - need_update |= FULL; - if (clear) - lt = 0; - in_update = false; - return; - } -#endif if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) && the_locking_inset) { @@ -581,36 +583,34 @@ void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit) void InsetText::setUpdateStatus(BufferView * bv, int what) const { - bool clear = false; - if (!lt) { - lt = getLyXText(bv); - clear = true; - } + // this does nothing dangerous so use only a localized buffer + LyXText * llt = getLyXText(bv); + need_update |= what; // we have to redraw us full if our LyXText NEEDS_MORE_REFRES or // if we don't break row so that we only have one row to update! - if ((lt->status() == LyXText::NEED_MORE_REFRESH) || + if ((llt->status() == LyXText::NEED_MORE_REFRESH) || (!autoBreakRows && - (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH))) + (llt->status() == LyXText::NEED_VERY_LITTLE_REFRESH))) { need_update |= FULL; - } else if (lt->status() == LyXText::NEED_VERY_LITTLE_REFRESH) { + } else if (llt->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 & CURSOR && !(need_update & SELECTION)) { - if (lt->selection.set()) + if (llt->selection.set()) need_update = FULL; - lt->clearSelection(); + llt->clearSelection(); } - if (clear) - lt = 0; } void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const { + if (!autoBreakRows && par->next()) + collapseParagraphs(bv->buffer()->params); bool clear = false; if (!lt) { lt = getLyXText(bv); @@ -618,20 +618,27 @@ void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const } lt->fullRebreak(bv); setUpdateStatus(bv, what); - if (((need_update != CURSOR) && (need_update != NONE)) || - (lt->status() != LyXText::UNCHANGED) || lt->selection.set()) - { + bool flag = mark_dirty || + (((need_update != CURSOR) && (need_update != NONE)) || + (lt->status() != LyXText::UNCHANGED) || lt->selection.set()); + if (!lt->selection.set()) + lt->selection.cursor = lt->cursor; + if (clear) + lt = 0; + if (locked && (need_update & CURSOR) && bv->fitCursor()) + need_update |= FULL; + if (flag) bv->updateInset(const_cast(this), mark_dirty); - } + if (need_update == CURSOR) need_update = NONE; bv->owner()->showState(); + bv->owner()->updateMenubar(); + bv->owner()->updateToolbar(); if (old_par != cpar(bv)) { - bv->owner()->setLayout(cpar(bv)->getLayout()); + bv->owner()->setLayout(cpar(bv)->layout()); old_par = cpar(bv); } - if (clear) - lt = 0; } @@ -644,7 +651,7 @@ string const InsetText::editMessage() const void InsetText::edit(BufferView * bv, int x, int y, unsigned int button) { UpdatableInset::edit(bv, x, y, button); - + if (!bv->lockInset(this)) { lyxerr[Debug::INSETS] << "Cannot lock inset" << endl; return; @@ -661,32 +668,38 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button) lt = getLyXText(bv); clear = true; } - if (!checkAndActivateInset(bv, x, tmp_y, button)) lt->setCursorFromCoordinates(bv, x - drawTextXOffset, - y + insetAscent); + y + insetAscent); lt->clearSelection(); finishUndo(); - showInsetCursor(bv); - updateLocal(bv, CURSOR, false); - // 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) != lt->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; + + int code = CURSOR; + if (drawFrame_ == LOCKED) + code = CURSOR|DRAW_FRAME; + updateLocal(bv, code, false); + showInsetCursor(bv); + + // Tell the paragraph dialog that we've entered an insettext. + bv->owner()->getDialogs()->updateParagraph(); } void InsetText::edit(BufferView * bv, bool front) { UpdatableInset::edit(bv, front); - + if (!bv->lockInset(this)) { lyxerr[Debug::INSETS] << "Cannot lock inset" << endl; return; @@ -706,16 +719,13 @@ void InsetText::edit(BufferView * bv, bool front) lt->setCursor(bv, par, 0); else { Paragraph * p = par; - while(p->next()) + while (p->next()) p = p->next(); // int const pos = (p->size() ? p->size()-1 : p->size()); lt->setCursor(bv, p, p->size()); } lt->clearSelection(); finishUndo(); - showInsetCursor(bv); - updateLocal(bv, CURSOR, false); - // 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() && @@ -726,6 +736,11 @@ void InsetText::edit(BufferView * bv, bool front) } if (clear) lt = 0; + int code = CURSOR; + if (drawFrame_ == LOCKED) + code = CURSOR|DRAW_FRAME; + updateLocal(bv, code, false); + showInsetCursor(bv); } @@ -736,12 +751,12 @@ void InsetText::insetUnlock(BufferView * bv) the_locking_inset = 0; } hideInsetCursor(bv); - no_selection = false; + no_selection = true; locked = false; int code; if (drawFrame_ == LOCKED) code = CURSOR|CLEAR_FRAME; - else + else code = CURSOR; bool clear = false; if (!lt) { @@ -753,14 +768,29 @@ void InsetText::insetUnlock(BufferView * bv) code = FULL; } else if (owner()) { bv->owner()->setLayout(owner()->getLyXText(bv) - ->cursor.par()->getLayout()); + ->cursor.par()->layout()); } else - bv->owner()->setLayout(bv->text->cursor.par()->getLayout()); + bv->owner()->setLayout(bv->text->cursor.par()->layout()); // hack for deleteEmptyParMech - lt->setCursor(bv, par, 0); - updateLocal(bv, code, false); + if (par->size()) { + lt->setCursor(bv, par, 0); + } else if (par->next()) { + lt->setCursor(bv, par->next(), 0); + } if (clear) lt = 0; + updateLocal(bv, code, false); +} + +void InsetText::lockInset(BufferView * bv, UpdatableInset * inset) +{ + the_locking_inset = inset; + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + inset_pos = cpos(bv); + inset_par = cpar(bv); + inset_boundary = cboundary(bv); + updateLocal(bv, CURSOR, false); } @@ -770,15 +800,33 @@ bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset) << inset << "): "; if (!inset) return false; + if (!the_locking_inset) { + Paragraph * p = par; + int const id = inset->id(); + while(p) { + Paragraph::inset_iterator it = + p->inset_iterator_begin(); + Paragraph::inset_iterator const end = + p->inset_iterator_end(); + for (; it != end; ++it) { + if ((*it) == inset) { + getLyXText(bv)->setCursorIntern(bv, p, it.getPos()); + lockInset(bv, inset); + return true; + } + if ((*it)->getInsetFromID(id)) { + getLyXText(bv)->setCursorIntern(bv, p, it.getPos()); + (*it)->edit(bv); + return the_locking_inset->lockInsetInInset(bv, inset); + } + } + p = p->next(); + } + return false; + } if (inset == cpar(bv)->getInset(cpos(bv))) { lyxerr[Debug::INSETS] << "OK" << endl; - the_locking_inset = inset; - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - inset_pos = cpos(bv); - inset_par = cpar(bv); - inset_boundary = cboundary(bv); - updateLocal(bv, CURSOR, false); + lockInset(bv, inset); return true; } else if (the_locking_inset && (the_locking_inset == inset)) { if (cpar(bv) == inset_par && cpos(bv) == inset_pos) { @@ -821,20 +869,51 @@ bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset, bool InsetText::updateInsetInInset(BufferView * bv, Inset * inset) { - if (!the_locking_inset) - return false; - if (the_locking_inset != inset) { - getLyXText(bv)->updateInset(bv, the_locking_inset); - setUpdateStatus(bv, CURSOR_PAR); - return the_locking_inset->updateInsetInInset(bv, inset); + if (!autoBreakRows && par->next()) + collapseParagraphs(bv->buffer()->params); + if (inset == this) + return true; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; } - if (getLyXText(bv)->updateInset(bv, inset)) - updateLocal(bv, CURSOR_PAR, false); - if (cpar(bv) == inset_par && cpos(bv) == inset_pos) { - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; + if (inset->owner() != this) { + int ustat = CURSOR_PAR; + bool found = false; + UpdatableInset * tl_inset = the_locking_inset; + if (tl_inset) + found = tl_inset->updateInsetInInset(bv, inset); + if (!found) { + tl_inset = static_cast(inset); + while(tl_inset->owner() && tl_inset->owner() != this) + tl_inset = static_cast(tl_inset->owner()); + if (!tl_inset->owner()) + return false; + found = tl_inset->updateInsetInInset(bv, inset); + ustat = FULL; + } + if (found) + lt->updateInset(bv, tl_inset); + if (clear) + lt = 0; + if (found) + setUpdateStatus(bv, ustat); + return found; } - return true; + bool found = lt->updateInset(bv, inset); + if (clear) + lt = 0; + if (found) { + setUpdateStatus(bv, CURSOR_PAR); + if (the_locking_inset && + cpar(bv) == inset_par && cpos(bv) == inset_pos) + { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + } + } + return found; } @@ -842,35 +921,44 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button) { no_selection = true; + // use this to check mouse motion for selection! + mouse_x = x; + mouse_y = y; + int tmp_x = x - drawTextXOffset; - int tmp_y = y + insetAscent - getLyXText(bv)->first; - Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y, button); + int tmp_y = y + insetAscent - getLyXText(bv)->first_y; + Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y); hideInsetCursor(bv); if (the_locking_inset) { if (the_locking_inset == inset) { - the_locking_inset->insetButtonPress(bv,x-inset_x,y-inset_y,button); - no_selection = false; + the_locking_inset->insetButtonPress(bv, + x - inset_x, + y - inset_y, + button); return; } else if (inset) { // otherwise unlock the_locking_inset and lock the new inset the_locking_inset->insetUnlock(bv); inset_x = cx(bv) - top_x + drawTextXOffset; inset_y = cy(bv) + drawTextYOffset; - the_locking_inset = static_cast(inset); - inset->insetButtonPress(bv, x - inset_x, y - inset_y, button); - inset->edit(bv, x - inset_x, y - inset_y, button); + the_locking_inset = 0; + inset->insetButtonPress(bv, x - inset_x, + y - inset_y, button); +// inset->edit(bv, x - inset_x, y - inset_y, button); if (the_locking_inset) updateLocal(bv, CURSOR, false); - no_selection = false; return; } // otherwise only unlock the_locking_inset the_locking_inset->insetUnlock(bv); the_locking_inset = 0; } + if (!inset) + no_selection = false; + if (bv->theLockingInset()) { - if (inset && inset->editable() == Inset::HIGHLY_EDITABLE) { + if (isHighlyEditableInset(inset)) { UpdatableInset * uinset = static_cast(inset); inset_x = cx(bv) - top_x + drawTextXOffset; inset_y = cy(bv) + drawTextYOffset; @@ -883,7 +971,6 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button) uinset->edit(bv, x - inset_x, y - inset_y, 0); if (the_locking_inset) updateLocal(bv, CURSOR, false); - no_selection = false; return; } } @@ -898,14 +985,29 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button) lt = getLyXText(bv); clear = true; } - lt->setCursorFromCoordinates(bv, x-drawTextXOffset, y + insetAscent); + int old_first_y = lt->first_y; + + lt->setCursorFromCoordinates(bv, x - drawTextXOffset, + y + insetAscent); + // set the selection cursor! + lt->selection.cursor = lt->cursor; + lt->cursor.x_fix(lt->cursor.x()); + if (lt->selection.set()) { lt->clearSelection(); + if (clear) + lt = 0; updateLocal(bv, FULL, false); } else { lt->clearSelection(); + if (clear) + lt = 0; + updateLocal(bv, CURSOR, false); } - bv->owner()->setLayout(cpar(bv)->getLayout()); + bv->owner()->setLayout(cpar(bv)->layout()); + // we moved the view we cannot do mouse selection in this case! + if (getLyXText(bv)->first_y != old_first_y) + no_selection = true; old_par = cpar(bv); // Insert primary selection with middle mouse // if there is a local selection in the current buffer, @@ -917,61 +1019,75 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button) localDispatch(bv, LFUN_PASTESELECTION, "paragraph"); } - if (clear) - lt = 0; + } else { + getLyXText(bv)->clearSelection(); } showInsetCursor(bv); - no_selection = false; } -void InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button) +bool InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button) { - UpdatableInset * inset = 0; - + no_selection = true; if (the_locking_inset) { - the_locking_inset->insetButtonRelease(bv, - x - inset_x, y - inset_y, - button); - } else { - if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) { - inset = static_cast(cpar(bv)->getInset(cpos(bv))); - if (inset->editable() == Inset::HIGHLY_EDITABLE) { - inset->insetButtonRelease(bv, - x - inset_x, - y - inset_y, button); - } else { - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - inset->insetButtonRelease(bv, - x - inset_x, - y - inset_y, button); - inset->edit(bv, - x - inset_x, y - inset_y, button); - } - updateLocal(bv, CURSOR_PAR, false); + return the_locking_inset->insetButtonRelease(bv, + x - inset_x, y - inset_y, + button); + } + int tmp_x = x - drawTextXOffset; + int tmp_y = y + insetAscent - getLyXText(bv)->first_y; + Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y); + bool ret = false; + if (inset) { + if (isHighlyEditableInset(inset)) { + ret = inset->insetButtonRelease(bv, x - inset_x, + y - inset_y, button); + } else { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + ret = inset->insetButtonRelease(bv, x - inset_x, + y - inset_y, button); + inset->edit(bv, x - inset_x, + y - inset_y, button); } + updateLocal(bv, CURSOR_PAR, false); } - no_selection = false; + return ret; } void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state) { - if (no_selection) - return; if (the_locking_inset) { the_locking_inset->insetMotionNotify(bv, x - inset_x, y - inset_y,state); return; } - LyXText * t = getLyXText(bv); + + if (no_selection || ((mouse_x == x) && (mouse_y == y))) + return; + + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } hideInsetCursor(bv); - t->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent); - t->setSelection(bv); - if (t->toggle_cursor.par() != t->toggle_end_cursor.par() || - t->toggle_cursor.pos() != t->toggle_end_cursor.pos()) + LyXCursor cur = lt->cursor; + lt->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent); + if (cur == lt->cursor) { + if (clear) + lt = 0; + return; + } + lt->setSelection(bv); + bool flag = (lt->toggle_cursor.par() != lt->toggle_end_cursor.par() || + lt->toggle_cursor.pos() != lt->toggle_end_cursor.pos()); + if (clear) + lt = 0; + if (flag) { updateLocal(bv, SELECTION, false); + } showInsetCursor(bv); } @@ -987,7 +1103,7 @@ void InsetText::insetKeyPress(XKeyEvent * xke) UpdatableInset::RESULT InsetText::localDispatch(BufferView * bv, - kb_action action, string const & arg) + kb_action action, string const & arg) { bool was_empty = par->size() == 0 && !par->next(); no_selection = false; @@ -1008,30 +1124,34 @@ InsetText::localDispatch(BufferView * bv, else if (result == DISPATCHED) { updateLocal(bv, CURSOR_PAR, false); return result; - } else if (result == FINISHED) { - bool dispatched = false; - switch (action) { - case LFUN_UNKNOWN_ACTION: - case LFUN_BREAKPARAGRAPH: - case LFUN_BREAKLINE: + } else if (result >= FINISHED) { + switch (result) { + case FINISHED_RIGHT: moveRightIntern(bv, false, false); + result = DISPATCHED; break; - case LFUN_RIGHT: - if (!getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) - moveRightIntern(bv, false, false); - dispatched = true; + case FINISHED_UP: + if ((result = moveUp(bv)) >= FINISHED) { + updateLocal(bv, CURSOR, false); + bv->unlockInset(this); + } break; - case LFUN_LEFT: - if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) - moveRightIntern(bv, false, false); - dispatched = true; + case FINISHED_DOWN: + if ((result = moveDown(bv)) >= FINISHED) { + updateLocal(bv, CURSOR, false); + bv->unlockInset(this); + } break; default: + result = DISPATCHED; break; } the_locking_inset = 0; - if (dispatched) - return DISPATCHED; +#ifdef WITH_WARNINGS +#warning I changed this to always return Dispatched maybe it is wrong (20011001 Jug) +#endif + updateLocal(bv, CURSOR, false); + return result; } } hideInsetCursor(bv); @@ -1040,6 +1160,8 @@ InsetText::localDispatch(BufferView * bv, lt = getLyXText(bv); clear = true; } + int updwhat = 0; + int updflag = false; switch (action) { // Normal chars case LFUN_SELFINSERT: @@ -1055,7 +1177,7 @@ InsetText::localDispatch(BufferView * bv, * true (on). */ setUndo(bv, Undo::INSERT, - lt->cursor.par(), lt->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); bv->setState(); if (lyxrc.auto_region_delete) { if (lt->selection.set()) { @@ -1068,7 +1190,8 @@ InsetText::localDispatch(BufferView * bv, } } lt->selection.cursor = lt->cursor; - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; result = DISPATCHED_NOUPDATE; break; // --- Cursor Movements ----------------------------------- @@ -1076,95 +1199,98 @@ InsetText::localDispatch(BufferView * bv, finishUndo(); moveRight(bv, false, true); lt->setSelection(bv); - updateLocal(bv, SELECTION, false); + updwhat = SELECTION; break; case LFUN_RIGHT: result = moveRight(bv); finishUndo(); - updateLocal(bv, CURSOR, false); + updwhat = CURSOR; break; case LFUN_LEFTSEL: finishUndo(); moveLeft(bv, false, true); lt->setSelection(bv); - updateLocal(bv, SELECTION, false); + updwhat = SELECTION; break; case LFUN_LEFT: finishUndo(); result = moveLeft(bv); - updateLocal(bv, CURSOR, false); + updwhat = CURSOR; break; case LFUN_DOWNSEL: finishUndo(); moveDown(bv); lt->setSelection(bv); - updateLocal(bv, SELECTION, false); + updwhat = SELECTION; break; case LFUN_DOWN: finishUndo(); result = moveDown(bv); - updateLocal(bv, CURSOR, false); + updwhat = CURSOR; break; case LFUN_UPSEL: finishUndo(); moveUp(bv); lt->setSelection(bv); - updateLocal(bv, SELECTION, false); + updwhat = SELECTION; break; case LFUN_UP: finishUndo(); result = moveUp(bv); - updateLocal(bv, CURSOR, false); + updwhat = CURSOR; break; case LFUN_HOME: finishUndo(); lt->cursorHome(bv); - updateLocal(bv, CURSOR, false); + updwhat = CURSOR; break; case LFUN_END: lt->cursorEnd(bv); - updateLocal(bv, CURSOR, false); + updwhat = CURSOR; break; case LFUN_BACKSPACE: { setUndo(bv, Undo::DELETE, - lt->cursor.par(), lt->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); if (lt->selection.set()) lt->cutSelection(bv); else lt->backspace(bv); - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; } break; - + case LFUN_DELETE: { setUndo(bv, Undo::DELETE, - lt->cursor.par(), lt->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); if (lt->selection.set()) { lt->cutSelection(bv); } else { lt->Delete(bv); } - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; } break; - + case LFUN_CUT: { setUndo(bv, Undo::DELETE, - lt->cursor.par(), lt->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); lt->cutSelection(bv); - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; } break; case LFUN_COPY: finishUndo(); lt->copySelection(bv); - updateLocal(bv, CURSOR_PAR, false); + updwhat = CURSOR_PAR; break; case LFUN_PASTESELECTION: { string const clip(bv->getClipboard()); - + if (clip.empty()) break; if (arg == "paragraph") { @@ -1172,23 +1298,25 @@ InsetText::localDispatch(BufferView * bv, } else { lt->insertStringAsLines(bv, clip); } - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; break; } case LFUN_PASTE: { if (!autoBreakRows) { if (CutAndPaste::nrOfParagraphs() > 1) { - WriteAlert(_("Impossible operation"), + Alert::alert(_("Impossible operation"), _("Cannot include more than one paragraph!"), _("Sorry.")); break; } } setUndo(bv, Undo::INSERT, - lt->cursor.par(), lt->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); lt->pasteSelection(bv); - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; } break; @@ -1198,7 +1326,8 @@ InsetText::localDispatch(BufferView * bv, break; } lt->breakParagraph(bv, 0); - updateLocal(bv, FULL, true); + updwhat = CURSOR | FULL; + updflag = true; break; case LFUN_BREAKPARAGRAPHKEEPLAYOUT: if (!autoBreakRows) { @@ -1206,7 +1335,8 @@ InsetText::localDispatch(BufferView * bv, break; } lt->breakParagraph(bv, 1); - updateLocal(bv, FULL, true); + updwhat = CURSOR | FULL; + updflag = true; break; case LFUN_BREAKLINE: { @@ -1215,48 +1345,50 @@ InsetText::localDispatch(BufferView * bv, break; } setUndo(bv, Undo::INSERT, - lt->cursor.par(), lt->cursor.par()->next()); + lt->cursor.par(), lt->cursor.par()->next()); lt->insertChar(bv, Paragraph::META_NEWLINE); - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR | CURSOR_PAR; + updflag = true; } break; case LFUN_LAYOUT: // do not set layouts on non breakable textinsets if (autoBreakRows) { - LyXTextClass::size_type cur_layout = cpar(bv)->layout; - + string cur_layout = cpar(bv)->layout(); + // Derive layout number from given argument (string) - // and current buffer's textclass (number). */ - LyXTextClassList::ClassList::size_type tclass = - bv->buffer()->params.textclass; - std::pair layout = - textclasslist.NumberOfLayout(tclass, arg); + // and current buffer's textclass (number). */ + textclass_type tclass = bv->buffer()->params.textclass; + string layout = arg; + bool hasLayout = textclasslist[tclass].hasLayout(layout); // If the entry is obsolete, use the new one instead. - if (layout.first) { - string obs = textclasslist.Style(tclass,layout.second). + if (hasLayout) { + string const & obs = + textclasslist[tclass][layout]. obsoleted_by(); - if (!obs.empty()) - layout = textclasslist.NumberOfLayout(tclass, obs); + if (!obs.empty()) + layout = obs; } // see if we found the layout number: - if (!layout.first) { + if (!hasLayout) { string const msg = string(N_("Layout ")) + arg + N_(" not known"); bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg); break; } - if (cur_layout != layout.second) { - cur_layout = layout.second; - lt->setLayout(bv, layout.second); - bv->owner()->setLayout(cpar(bv)->getLayout()); - updateLocal(bv, CURSOR_PAR, true); + if (cur_layout != layout) { + cur_layout = layout; + lt->setLayout(bv, layout); + bv->owner()->setLayout(cpar(bv)->layout()); + updwhat = CURSOR_PAR; + updflag = true; } } else { // reset the layout box - bv->owner()->setLayout(cpar(bv)->getLayout()); + bv->owner()->setLayout(cpar(bv)->layout()); } break; case LFUN_PARAGRAPH_SPACING: @@ -1270,7 +1402,7 @@ InsetText::localDispatch(BufferView * bv, if (cur_spacing == Spacing::Other) { cur_value = par->params().spacing().getValue(); } - + istringstream istr(arg.c_str()); string tmp; istr >> tmp; @@ -1300,17 +1432,22 @@ InsetText::localDispatch(BufferView * bv, } if (cur_spacing != new_spacing || cur_value != new_value) { par->params().spacing(Spacing(new_spacing, new_value)); - updateLocal(bv, CURSOR_PAR, true); + updwhat = CURSOR_PAR; + updflag = true; } } break; - + default: if (!bv->Dispatch(action, arg)) result = UNDISPATCHED; break; } + if (clear) + lt = 0; + if (updwhat > 0) + updateLocal(bv, updwhat, updflag); /// If the action has deleted all text in the inset, we need to change the // language to the language of the surronding text. if (!was_empty && par->size() == 0 && !par->next()) { @@ -1319,12 +1456,11 @@ InsetText::localDispatch(BufferView * bv, setFont(bv, font, false); } - if (result != FINISHED) { - showInsetCursor(bv); - } else + if (result >= FINISHED) bv->unlockInset(this); - if (clear) - lt = 0; + + if (result == DISPATCHED_NOUPDATE && (need_update & FULL)) + result = DISPATCHED; return result; } @@ -1341,10 +1477,10 @@ int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const { Paragraph * p = par; unsigned int lines = 0; - + while (p) { - string const tmp = buf->asciiParagraph(p, linelen); - lines += countChar(tmp, '\n'); + string const tmp = buf->asciiParagraph(p, linelen, p->previous()==0); + lines += lyx::count(tmp.begin(), tmp.end(), '\n'); os << tmp; p = p->next(); } @@ -1352,18 +1488,188 @@ int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const } -int InsetText::docBook(Buffer const * buf, ostream & os) const +int InsetText::docbook(Buffer const * buf, ostream & os) const { Paragraph * p = par; unsigned int lines = 0; - int desc = 0; - - string tmp; + + vector environment_stack(10); + vector environment_inner(10); + + int const command_depth = 0; + string item_name; + + Paragraph::depth_type depth = 0; // paragraph depth + while (p) { - buf->simpleDocBookOnePar(os, tmp, p, desc, 0); + string sgmlparam; + int desc_on = 0; // description mode + + LyXLayout const & style = + textclasslist[buf->params.textclass][p->layout()]; + + // environment tag closing + for (; depth > p->params().depth(); --depth) { + if (environment_inner[depth] != "!-- --") { + item_name = "listitem"; + buf->sgmlCloseTag(os, command_depth + depth, + item_name); + if (environment_inner[depth] == "varlistentry") + buf->sgmlCloseTag(os, depth+command_depth, + environment_inner[depth]); + } + buf->sgmlCloseTag(os, depth + command_depth, + environment_stack[depth]); + environment_stack[depth].erase(); + environment_inner[depth].erase(); + } + + if (depth == p->params().depth() + && environment_stack[depth] != style.latexname() + && !environment_stack[depth].empty()) { + if (environment_inner[depth] != "!-- --") { + item_name= "listitem"; + buf->sgmlCloseTag(os, command_depth+depth, + item_name); + if (environment_inner[depth] == "varlistentry") + buf->sgmlCloseTag(os, + depth + command_depth, + environment_inner[depth]); + } + + buf->sgmlCloseTag(os, depth + command_depth, + environment_stack[depth]); + + environment_stack[depth].erase(); + environment_inner[depth].erase(); + } + + // Write opening SGML tags. + switch (style.latextype) { + case LATEX_PARAGRAPH: + buf->sgmlOpenTag(os, depth + command_depth, + style.latexname()); + break; + + case LATEX_COMMAND: + buf->sgmlError(p, 0, + _("Error : LatexType Command not allowed here.\n")); + return -1; + break; + + case LATEX_ENVIRONMENT: + case LATEX_ITEM_ENVIRONMENT: + if (depth < p->params().depth()) { + depth = p->params().depth(); + environment_stack[depth].erase(); + } + + if (environment_stack[depth] != style.latexname()) { + if (environment_stack.size() == depth + 1) { + environment_stack.push_back("!-- --"); + environment_inner.push_back("!-- --"); + } + environment_stack[depth] = style.latexname(); + environment_inner[depth] = "!-- --"; + buf->sgmlOpenTag(os, depth + command_depth, + environment_stack[depth]); + } else { + if (environment_inner[depth] != "!-- --") { + item_name= "listitem"; + buf->sgmlCloseTag(os, + command_depth + depth, + item_name); + if (environment_inner[depth] == "varlistentry") + buf->sgmlCloseTag(os, + depth + command_depth, + environment_inner[depth]); + } + } + + if (style.latextype == LATEX_ENVIRONMENT) { + if (!style.latexparam().empty()) { + if (style.latexparam() == "CDATA") + os << "sgmlOpenTag(os, depth + command_depth, + style.latexparam()); + } + break; + } + + desc_on = (style.labeltype == LABEL_MANUAL); + + if (desc_on) + environment_inner[depth]= "varlistentry"; + else + environment_inner[depth]= "listitem"; + + buf->sgmlOpenTag(os, depth + 1 + command_depth, + environment_inner[depth]); + + if (desc_on) { + item_name= "term"; + buf->sgmlOpenTag(os, depth + 1 + command_depth, + item_name); + } else { + item_name= "para"; + buf->sgmlOpenTag(os, depth + 1 + command_depth, + item_name); + } + break; + default: + buf->sgmlOpenTag(os, depth + command_depth, + style.latexname()); + break; + } + + buf->simpleDocBookOnePar(os, p, desc_on, + depth + 1 + command_depth); p = p->next(); + + string end_tag; + // write closing SGML tags + switch (style.latextype) { + case LATEX_ENVIRONMENT: + if (!style.latexparam().empty()) { + if (style.latexparam() == "CDATA") + os << "]]>"; + else + buf->sgmlCloseTag(os, depth + command_depth, + style.latexparam()); + } + break; + case LATEX_ITEM_ENVIRONMENT: + if (desc_on == 1) break; + end_tag= "para"; + buf->sgmlCloseTag(os, depth + 1 + command_depth, end_tag); + break; + case LATEX_PARAGRAPH: + buf->sgmlCloseTag(os, depth + command_depth, style.latexname()); + break; + default: + buf->sgmlCloseTag(os, depth + command_depth, style.latexname()); + break; + } } - + + // Close open tags + for (int d = depth; d >= 0; --d) { + if (!environment_stack[depth].empty()) { + if (environment_inner[depth] != "!-- --") { + item_name = "listitem"; + buf->sgmlCloseTag(os, command_depth + depth, + item_name); + if (environment_inner[depth] == "varlistentry") + buf->sgmlCloseTag(os, depth + command_depth, + environment_inner[depth]); + } + + buf->sgmlCloseTag(os, depth + command_depth, + environment_stack[depth]); + } + } + return lines; } @@ -1380,8 +1686,7 @@ void InsetText::validate(LaTeXFeatures & features) const int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const { - if (textclasslist.Style(buf->params.textclass, - p->getLayout()).labeltype != LABEL_MANUAL) + if (textclasslist[buf->params.textclass][p->layout()].labeltype != LABEL_MANUAL) return 0; else return p->beginningOfMainBody(); @@ -1420,7 +1725,7 @@ void InsetText::toggleInsetCursor(BufferView * bv) int const asc = lyxfont::maxAscent(font); int const desc = lyxfont::maxDescent(font); - + if (isCursorVisible()) bv->hideLockedInsetCursor(); else @@ -1438,7 +1743,7 @@ void InsetText::showInsetCursor(BufferView * bv, bool show) if (!isCursorVisible()) { LyXFont const font = getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)); - + int const asc = lyxfont::maxAscent(font); int const desc = lyxfont::maxDescent(font); @@ -1469,11 +1774,12 @@ void InsetText::fitInsetCursor(BufferView * bv) const } LyXFont const font = getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)); - + int const asc = lyxfont::maxAscent(font); int const desc = lyxfont::maxDescent(font); - bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc); + if (bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc)) + need_update |= FULL; } @@ -1498,11 +1804,11 @@ InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting) UpdatableInset::RESULT -InsetText::moveRightIntern(BufferView * bv, bool behind, +InsetText::moveRightIntern(BufferView * bv, bool behind, bool activate_inset, bool selecting) { if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size())) - return FINISHED; + return FINISHED_RIGHT; if (activate_inset && checkAndActivateInset(bv, behind)) return DISPATCHED; getLyXText(bv)->cursorRight(bv); @@ -1531,7 +1837,7 @@ UpdatableInset::RESULT InsetText::moveUp(BufferView * bv) { if (!crow(bv)->previous()) - return FINISHED; + return FINISHED_UP; getLyXText(bv)->cursorUp(bv); return DISPATCHED_NOUPDATE; } @@ -1541,7 +1847,7 @@ UpdatableInset::RESULT InsetText::moveDown(BufferView * bv) { if (!crow(bv)->next()) - return FINISHED; + return FINISHED_DOWN; getLyXText(bv)->cursorDown(bv); return DISPATCHED_NOUPDATE; } @@ -1554,34 +1860,41 @@ bool InsetText::insertInset(BufferView * bv, Inset * inset) return the_locking_inset->insertInset(bv, inset); return false; } - inset->setOwner(this); - hideInsetCursor(bv); - bool clear = false; if (!lt) { lt = getLyXText(bv); clear = true; } + setUndo(bv, Undo::FINISH, lt->cursor.par(), lt->cursor.par()->next()); + freezeUndo(); + inset->setOwner(this); + hideInsetCursor(bv); lt->insertInset(bv, inset); -#if 0 - if ((cpar(bv)->getChar(cpos(bv)) != Paragraph::META_INSET) || - (cpar(bv)->getInset(cpos(bv)) != inset)) - lt->cursorLeft(bv); -#endif bv->fitCursor(); - updateLocal(bv, CURSOR_PAR|CURSOR, true); - showInsetCursor(bv); if (clear) lt = 0; + updateLocal(bv, CURSOR_PAR|CURSOR, true); + unFreezeUndo(); return true; } bool InsetText::insetAllowed(Inset::Code code) const { + // in_insetAllowed is a really gross hack, + // to allow us to call the owner's insetAllowed + // without stack overflow, which can happen + // when the owner uses InsetCollapsable::insetAllowed() + bool ret = true; + if (in_insetAllowed) + return ret; + in_insetAllowed = true; if (the_locking_inset) - return the_locking_inset->insetAllowed(code); - return true; + ret = the_locking_inset->insetAllowed(code); + else if (owner()) + ret = owner()->insetAllowed(code); + in_insetAllowed = false; + return ret; } @@ -1610,16 +1923,16 @@ bool InsetText::showInsetDialog(BufferView * bv) const } -std::vector const InsetText::getLabelList() const +vector const InsetText::getLabelList() const { - std::vector label_list; + vector label_list; Paragraph * tpar = par; while (tpar) { Paragraph::inset_iterator beg = tpar->inset_iterator_begin(); Paragraph::inset_iterator end = tpar->inset_iterator_end(); for (; beg != end; ++beg) { - std::vector const l = (*beg)->getLabelList(); + vector const l = (*beg)->getLabelList(); label_list.insert(label_list.end(), l.begin(), l.end()); } tpar = tpar->next(); @@ -1629,7 +1942,7 @@ std::vector const InsetText::getLabelList() const void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall, - bool selectall) + bool selectall) { if (the_locking_inset) { the_locking_inset->setFont(bv, font, toggleall, selectall); @@ -1653,23 +1966,24 @@ void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall, if (selectall) lt->clearSelection(); bv->fitCursor(); - if (selectall || lt->selection.set()) + bool flag = (selectall || lt->selection.set()); + if (clear) + lt = 0; + if (flag) updateLocal(bv, FULL, true); else updateLocal(bv, CURSOR_PAR, true); - if (clear) - lt = 0; } bool InsetText::checkAndActivateInset(BufferView * bv, bool behind) { - if (cpar(bv)->getChar(cpos(bv)) == Paragraph::META_INSET) { + if (cpar(bv)->isInset(cpos(bv))) { unsigned int x; unsigned int y; Inset * inset = static_cast(cpar(bv)->getInset(cpos(bv))); - if (!inset || inset->editable() != Inset::HIGHLY_EDITABLE) + if (!isHighlyEditableInset(inset)) return false; LyXFont const font = getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)); @@ -1698,7 +2012,7 @@ bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y, x -= drawTextXOffset; int dummyx = x; int dummyy = y + insetAscent; - Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy, button); + Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy); if (inset) { if (x < 0) @@ -1736,7 +2050,7 @@ int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const } -void InsetText::setParagraphData(Paragraph * p) +void InsetText::setParagraphData(Paragraph * p, bool same_id) { // we have to unlock any locked inset otherwise we're in troubles the_locking_inset = 0; @@ -1746,26 +2060,27 @@ void InsetText::setParagraphData(Paragraph * p) par = tmp; } - par = new Paragraph(*p); + par = new Paragraph(*p, same_id); par->setInsetOwner(this); Paragraph * np = par; while (p->next()) { p = p->next(); - np->next(new Paragraph(*p)); + np->next(new Paragraph(*p, same_id)); np->next()->previous(np); np = np->next(); np->setInsetOwner(this); } + reinitLyXText(); need_update = INIT; } -void InsetText::setText(string const & data) +void InsetText::setText(string const & data, LyXFont const & font) { clear(); - LyXFont font(LyXFont::ALL_SANE); for (unsigned int i=0; i < data.length(); ++i) par->insertChar(i, data[i], font); + reinitLyXText(); } @@ -1802,21 +2117,15 @@ void InsetText::setFrameColor(BufferView * bv, LColor::color col) int InsetText::cx(BufferView * bv) const { - bool clear = false; - if (!lt) { - lt = getLyXText(bv); - clear = true; - } - int x = lt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET; + // we do nothing dangerous so we use a local cache + LyXText * llt = getLyXText(bv); + int x = llt->cursor.x() + top_x + TEXT_TO_INSET_OFFSET; if (the_locking_inset) { - LyXFont font = lt->getFont(bv->buffer(), - lt->cursor.par(), - lt->cursor.pos()); + LyXFont font = llt->getFont(bv->buffer(), llt->cursor.par(), + llt->cursor.pos()); if (font.isVisibleRightToLeft()) x -= the_locking_inset->width(bv, font); } - if (clear) - lt = 0; return x; } @@ -1828,7 +2137,7 @@ int InsetText::cy(BufferView * bv) const } -Paragraph::size_type InsetText::cpos(BufferView * bv) const +pos_type InsetText::cpos(BufferView * bv) const { return getLyXText(bv)->cursor.pos(); } @@ -1853,44 +2162,63 @@ Row * InsetText::crow(BufferView * bv) const LyXText * InsetText::getLyXText(BufferView const * lbv, - bool const recursive) const + bool const recursive) const { - if (!recursive && (cached_bview == lbv)) - return cached_text.get(); - + if (cached_bview == lbv) { + if (recursive && the_locking_inset) + return the_locking_inset->getLyXText(lbv, true); + LyXText * lt = cached_text.get(); + lyx::Assert(lt && lt->firstRow()->par() == par); + return lt; + } // Super UGLY! (Lgb) BufferView * bv = const_cast(lbv); - + cached_bview = bv; Cache::iterator it = cache.find(bv); if (it != cache.end()) { - if (do_reinit) + if (do_reinit) { reinitLyXText(); - else if (do_resize) + } else if (do_resize) { resizeLyXText(do_resize); - if (lt || !it->second.remove) { - lyx::Assert(it->second.text.get()); - cached_text = it->second.text; - if (recursive && the_locking_inset) { - return the_locking_inset->getLyXText(bv, true); - } - return cached_text.get(); - } else if (it->second.remove) { - if (locked) { - saveLyXTextState(it->second.text.get()); - } else { - sstate.lpar = 0; + } else { + if (lt || !it->second.remove) { + lyx::Assert(it->second.text.get()); + cached_text = it->second.text; + if (recursive && the_locking_inset) { + return the_locking_inset->getLyXText(bv, true); + } + return cached_text.get(); + } else if (it->second.remove) { + if (locked) { + saveLyXTextState(it->second.text.get()); + } else { + sstate.lpar = 0; + } } + // + // when we have to reinit the existing LyXText! + // + it->second.text->init(bv); + restoreLyXTextState(bv, it->second.text.get()); + it->second.remove = false; + } + cached_text = it->second.text; + if (the_locking_inset && recursive) { + return the_locking_inset->getLyXText(bv); } + return cached_text.get(); } - + /// + // we are here only if we don't have a BufferView * in the cache!!! + /// 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 && recursive) { return the_locking_inset->getLyXText(bv); } @@ -1903,7 +2231,7 @@ void InsetText::deleteLyXText(BufferView * bv, bool recursive) const cached_bview = 0; Cache::iterator it = cache.find(bv); - + if (it == cache.end()) { return; } @@ -1929,10 +2257,16 @@ void InsetText::resizeLyXText(BufferView * bv, bool force) const do_resize = bv; return; } - do_resize = false; + do_resize = 0; // lyxerr << "InsetText::resizeLyXText\n"; - if (!par->next() && !par->size()) // no data, resize not neccessary! + if (!par->next() && !par->size()) { // no data, resize not neccessary! + // we have to do this as a fixed width may have changed! + LyXText * t = getLyXText(bv); + saveLyXTextState(t); + t->init(bv, true); + restoreLyXTextState(bv, t); return; + } // one endless line, resize normally not necessary if (!force && getMaxWidth(bv, this) < 0) return; @@ -1956,11 +2290,11 @@ void InsetText::resizeLyXText(BufferView * bv, bool force) const } if (bv->screen()) { - t->first = bv->screen()->topCursorVisible(t); + t->first_y = bv->screen()->topCursorVisible(t); } if (!owner()) { updateLocal(bv, FULL, false); - // this will scroll the screen such that the cursor becomes visible + // this will scroll the screen such that the cursor becomes visible bv->updateScrollbar(); } else { need_update |= FULL; @@ -1977,7 +2311,7 @@ void InsetText::reinitLyXText() const return; } do_reinit = false; - do_resize = false; + do_resize = 0; // lyxerr << "InsetText::reinitLyXText\n"; for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) { lyx::Assert(it->second.text.get()); @@ -1996,11 +2330,11 @@ void InsetText::reinitLyXText() const inset_y = cy(bv) + drawTextYOffset; } if (bv->screen()) { - t->first = bv->screen()->topCursorVisible(t); + t->first_y = bv->screen()->topCursorVisible(t); } if (!owner()) { updateLocal(bv, FULL, false); - // this will scroll the screen such that the cursor becomes visible + // this will scroll the screen such that the cursor becomes visible bv->updateScrollbar(); } else { need_update = FULL; @@ -2011,12 +2345,18 @@ void InsetText::reinitLyXText() const void InsetText::removeNewlines() { + bool changed = false; + for (Paragraph * p = par; p; p = p->next()) { for (int i = 0; i < p->size(); ++i) { - if (p->getChar(i) == Paragraph::META_NEWLINE) + if (p->getChar(i) == Paragraph::META_NEWLINE) { + changed = true; p->erase(i); + } } } + if (changed) + reinitLyXText(); } @@ -2060,12 +2400,13 @@ void InsetText::clearSelection(BufferView * bv) } -void InsetText::clearInset(Painter & pain, int baseline, bool & cleared) const +void InsetText::clearInset(BufferView * bv, int baseline, bool & cleared) const { + Painter & pain = bv->painter(); int w = insetWidth; int h = insetAscent + insetDescent; int ty = baseline - insetAscent; - + if (ty < 0) { h += ty; ty = 0; @@ -2096,8 +2437,6 @@ Paragraph * InsetText::getParFromID(int id) const #else Paragraph * tmp = par; while (tmp) { - int tmp_id = tmp->id(); - lyxerr << "Looking at paragraph: " << tmp_id << endl; if (tmp->id() == id) { return tmp; } @@ -2122,6 +2461,12 @@ Paragraph * InsetText::firstParagraph() const } +Paragraph * InsetText::getFirstParagraph(int i) const +{ + return (i == 0) ? par : 0; +} + + LyXCursor const & InsetText::cursor(BufferView * bv) const { if (the_locking_inset) @@ -2138,14 +2483,19 @@ Paragraph * InsetText::paragraph() const void InsetText::paragraph(Paragraph * p) { + // GENERAL COMMENT: We don't have to free the old paragraphs as the + // caller of this function has to take care of it. This IS important + // as we could have to insert a paragraph before this one and just + // link the actual to a new ones next and set it with this function + // and are done! par = p; -#if 0 - // we now have to update/redraw all instances - for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit) { - delete cit->second; - cit->second = 0; + // set ourself as owner for all the paragraphs inserted! + Paragraph * np = par; + while (np) { + np->setInsetOwner(this); + np = np->next(); } -#endif + reinitLyXText(); // redraw myself when asked for need_update = INIT; } @@ -2158,7 +2508,7 @@ Inset * InsetText::getInsetFromID(int id_arg) const Paragraph * lp = par; - while(lp) { + while (lp) { for (Paragraph::inset_iterator it = lp->inset_iterator_begin(), en = lp->inset_iterator_end(); it != en; ++it) @@ -2175,7 +2525,7 @@ Inset * InsetText::getInsetFromID(int id_arg) const } -string const InsetText::selectNextWord(BufferView * bv, float & value) const +string const InsetText::selectNextWordToSpellcheck(BufferView * bv, float & value) const { bool clear = false; string str; @@ -2185,18 +2535,17 @@ string const InsetText::selectNextWord(BufferView * bv, float & value) const clear = true; } if (the_locking_inset) { - str = the_locking_inset->selectNextWord(bv, value); + str = the_locking_inset->selectNextWordToSpellcheck(bv, value); if (!str.empty()) { value += cy(bv); if (clear) lt = 0; return str; } -#warning Dekel please have a look on this one RTL? (Jug) - // we have to go on checking so move cusor to the right + // we have to go on checking so move cusor to the next char lt->cursor.pos(lt->cursor.pos() + 1); } - str = lt->selectNextWord(bv, value); + str = lt->selectNextWordToSpellcheck(bv, value); if (str.empty()) bv->unlockInset(const_cast(this)); else @@ -2231,17 +2580,16 @@ void InsetText::toggleSelection(BufferView * bv, bool kill_selection) int x = top_x + TEXT_TO_INSET_OFFSET; - int y = 0; - Row * row = lt->getRowNearY(y); + Row * row = lt->firstRow(); int y_offset = top_baseline - row->ascent_of_text(); - y = y_offset; + int y = y_offset; while ((row != 0) && ((y+row->height()) <= 0)) { y += row->height(); row = row->next(); } if (y_offset < 0) y_offset = y; - + if (need_update & SELECTION) need_update = NONE; bv->screen()->toggleSelection(lt, bv, kill_selection, y_offset, x); @@ -2251,7 +2599,7 @@ void InsetText::toggleSelection(BufferView * bv, bool kill_selection) bool InsetText::searchForward(BufferView * bv, string const & str, - bool const & cs, bool const & mw) + bool cs, bool mw) { if (the_locking_inset) { if (the_locking_inset->searchForward(bv, str, cs, mw)) @@ -2262,7 +2610,7 @@ bool InsetText::searchForward(BufferView * bv, string const & str, clear = true; } Paragraph * lpar = lt->cursor.par(); - Paragraph::size_type pos = lt->cursor.pos(); + pos_type pos = lt->cursor.pos(); if (pos < lpar->size() - 1) ++pos; else { @@ -2289,7 +2637,7 @@ bool InsetText::searchForward(BufferView * bv, string const & str, } bool InsetText::searchBackward(BufferView * bv, string const & str, - bool const & cs, bool const & mw) + bool cs, bool mw) { if (the_locking_inset) if (the_locking_inset->searchBackward(bv, str, cs, mw)) @@ -2301,3 +2649,67 @@ bool InsetText::searchBackward(BufferView * bv, string const & str, bv->unlockInset(const_cast(this)); return false; } + + +bool InsetText::checkInsertChar(LyXFont & font) +{ + if (owner()) + return owner()->checkInsertChar(font); + return true; +} + + +void InsetText::collapseParagraphs(BufferParams const & bparams) const +{ + while(par->next()) { + if (par->size() && par->next()->size() && + !par->isSeparator(par->size()-1)) + { + par->insertChar(par->size(), ' '); + } + par->pasteParagraph(bparams); + } + reinitLyXText(); +} + + +void InsetText::getDrawFont(LyXFont & font) const +{ + if (!owner()) + return; + owner()->getDrawFont(font); +} + + +void InsetText::appendParagraphs(BufferParams const & bparams, + Paragraph * newpar) +{ + Paragraph * buf; + Paragraph * tmpbuf = newpar; + Paragraph * lastbuffer = buf = new Paragraph(*tmpbuf, false); + + while (tmpbuf->next()) { + tmpbuf = tmpbuf->next(); + lastbuffer->next(new Paragraph(*tmpbuf, false)); + lastbuffer->next()->previous(lastbuffer); + lastbuffer = lastbuffer->next(); + } + lastbuffer = par; + while (lastbuffer->next()) + lastbuffer = lastbuffer->next(); + if (newpar->size() && lastbuffer->size() && + !lastbuffer->isSeparator(lastbuffer->size()-1)) + { + lastbuffer->insertChar(lastbuffer->size(), ' '); + } + + // make the buf exactly the same layout than our last paragraph + buf->makeSameLayout(lastbuffer); + + // paste it! + lastbuffer->next(buf); + buf->previous(lastbuffer); + lastbuffer->pasteParagraph(bparams); + + reinitLyXText(); +}