X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsettext.C;h=ff1d9119197dcde2581f74a1a91a1dd3f8d9f049;hb=dbd7a961fc46bb10c85bdd8c7fb6626477ae63d8;hp=8dadb19924160b42eabb865d6f2a91cb1cc5caaf;hpb=53b30ba060d23b7cc5f290d96e8eed64dad34d89;p=lyx.git diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 8dadb19924..f22c7cf84e 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -1,27 +1,21 @@ -// -*- C++ -*- /* This file is part of * ====================================================== * * LyX, The Document Processor * - * Copyright 1998-2000 The LyX Team. + * Copyright 1998-2001 The LyX Team. * * ====================================================== */ #include -#include -#include - -#include - #ifdef __GNUG__ #pragma implementation #endif #include "insettext.h" -#include "lyxparagraph.h" +#include "paragraph.h" #include "lyxlex.h" #include "debug.h" #include "lyxfont.h" @@ -29,1500 +23,2068 @@ #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 "minibuffer.h" #include "LColor.h" -#include "support/textutils.h" -#include "support/LAssert.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 "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; + +// 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) { + 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(); + 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(); + sstate.refresh = t->refresh_row != 0; + } else { + sstate.lpar = 0; + } +} + +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); + } + if (sstate.refresh) { + } + } +} + + +InsetText::InnerCache::InnerCache(boost::shared_ptr t) +{ + text = t; + remove = false; +} + + InsetText::InsetText() + : UpdatableInset(), lt(0), in_update(false), do_resize(0), + do_reinit(false) { - par = new LyXParagraph(); - init(); + par = new Paragraph; + init(); } -InsetText::InsetText(InsetText const & ins) - : UpdatableInset() +InsetText::InsetText(InsetText const & in, bool same_id) + : UpdatableInset(in, same_id), lt(0), in_update(false), do_resize(0), + do_reinit(false) { - par = 0; - init(&ins); - autoBreakRows = ins.autoBreakRows; + par = 0; + init(&in, same_id); } InsetText & InsetText::operator=(InsetText const & it) { - init(&it); - autoBreakRows = it.autoBreakRows; - return * this; -} - - -void InsetText::init(InsetText const * ins) -{ - top_y = 0; - last_width = 0; - last_height = 0; - insetAscent = 0; - insetDescent = 0; - insetWidth = 0; - the_locking_inset = 0; - cursor_visible = false; - interline_space = 1; - no_selection = false; - need_update = INIT; - drawTextXOffset = 0; - drawTextYOffset = 0; - autoBreakRows = false; - drawFrame = NEVER; - xpos = 0.0; - if (ins) { - SetParagraphData(ins->par); - autoBreakRows = ins->autoBreakRows; - drawFrame = ins->drawFrame; - } - par->SetInsetOwner(this); - frame_color = LColor::insetframe; - locked = false; - old_par = 0; + init(&it); + return * this; +} + + +void InsetText::init(InsetText const * ins, bool same_id) +{ + if (ins) { + setParagraphData(ins->par, same_id); + autoBreakRows = ins->autoBreakRows; + drawFrame_ = ins->drawFrame_; + frame_color = ins->frame_color; + if (same_id) + id_ = ins->id_; + } else { + Paragraph * p = par; + while (p) { + p->setInsetOwner(this); + p = p->next(); + } + the_locking_inset = 0; + drawFrame_ = NEVER; + frame_color = LColor::insetframe; + autoBreakRows = false; + } + top_y = 0; + insetAscent = 0; + insetDescent = 0; + insetWidth = 0; + old_max_width = 0; + no_selection = false; + need_update = FULL; + drawTextXOffset = 0; + drawTextYOffset = 0; + xpos = 0.0; + locked = false; + old_par = 0; + last_drawn_width = -1; + frame_is_visible = false; + cached_bview = 0; + sstate.lpar = 0; + in_insetAllowed = false; } InsetText::~InsetText() { - // delete all instances of LyXText before deleting the paragraps used - // by it. - for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit){ - delete (*cit).second; - (*cit).second = 0; - } - LyXParagraph * p = par->next; - delete par; - while(p) { - par = p; - p = p->next; - delete par; - } + cached_bview = 0; + + // NOTE + + while (par) { + Paragraph * tmp = par->next(); + delete par; + par = tmp; + } } void InsetText::clear() { - // delete all instances of LyXText before deleting the paragraps used - // by it. - for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit){ - delete (*cit).second; - (*cit).second = 0; - } - LyXParagraph * p = par->next; - delete par; - while(p) { - par = p; - p = p->next; - delete par; - } - par = new LyXParagraph(); + while (par) { + Paragraph * tmp = par->next(); + delete par; + par = tmp; + } + par = new Paragraph; + reinitLyXText(); + need_update = INIT; } -Inset * InsetText::Clone(Buffer const &) const +Inset * InsetText::clone(Buffer const &, bool same_id) const { - InsetText * t = new InsetText(*this); - return t; + return new InsetText(*this, same_id); } -void InsetText::Write(Buffer const * buf, ostream & os) const +void InsetText::write(Buffer const * buf, ostream & os) const { - os << "Text\n"; - WriteParagraphData(buf, os); + os << "Text\n"; + writeParagraphData(buf, os); } -void InsetText::WriteParagraphData(Buffer const * buf, ostream & os) const +void InsetText::writeParagraphData(Buffer const * buf, ostream & os) const { - par->writeFile(buf, os, buf->params, 0, 0); + par->writeFile(buf, os, buf->params, 0); } -void InsetText::Read(Buffer const * buf, LyXLex & lex) +void InsetText::read(Buffer const * buf, LyXLex & lex) { - string token; - int pos = 0; - LyXParagraph * return_par = 0; - char depth = 0; // signed or unsigned? -#ifndef NEW_INSETS - LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE; - LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE; -#endif - LyXFont font(LyXFont::ALL_INHERIT); - - // delete all instances of LyXText before deleting the paragraps used - // by it. - for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit){ - delete (*cit).second; - (*cit).second = 0; - } - - LyXParagraph * p = par->next; - delete par; - while(p) { - par = p; - p = p->next; - delete par; - } - par = new LyXParagraph; - while (lex.IsOK()) { - lex.nextToken(); - token = lex.GetString(); - if (token.empty()) - continue; - if (token == "\\end_inset") - break; - if (const_cast(buf)-> - parseSingleLyXformat2Token(lex, par, return_par,token, pos, depth, - font -#ifndef NEW_INSETS - , footnoteflag, footnotekind + string token; + int pos = 0; + Paragraph * return_par = 0; + Paragraph::depth_type depth = 0; + LyXFont font(LyXFont::ALL_INHERIT); + + clear(); + + while (lex.isOK()) { + lex.nextToken(); + token = lex.getString(); + if (token.empty()) + continue; + if (token == "\\end_inset") { +#ifndef NO_COMPABILITY + const_cast(buf)->insertErtContents(par, pos, false); #endif - )) - { - // the_end read this should NEVER happen - lex.printError("\\the_end read in inset! Error in document!"); - return; - } - } - if (!return_par) - return_par = par; - par = 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'"); - } - need_update = INIT; + break; + } + + if (const_cast(buf)-> + parseSingleLyXformat2Token(lex, par, return_par, + token, pos, depth, font)) { + // the_end read this should NEVER happen + lex.printError("\\the_end read in inset! Error in document!"); + return; + } + } + if (!return_par) + return_par = par; + par = 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'"); + } + need_update = FULL; } int InsetText::ascent(BufferView * bv, LyXFont const &) const { - int y_temp = 0; - Row * row = TEXT(bv)->GetRowNearY(y_temp); - insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET; - return insetAscent; + insetAscent = getLyXText(bv)->firstRow()->ascent_of_text() + + TEXT_TO_INSET_OFFSET; + return insetAscent; } int InsetText::descent(BufferView * bv, LyXFont const &) const { - int y_temp = 0; - Row * row = TEXT(bv)->GetRowNearY(y_temp); - insetDescent = TEXT(bv)->height - row->ascent_of_text() + - TEXT_TO_INSET_OFFSET; - return insetDescent; + LyXText * llt = getLyXText(bv); + insetDescent = llt->height - llt->firstRow()->ascent_of_text() + + TEXT_TO_INSET_OFFSET; + return insetDescent; } int InsetText::width(BufferView * bv, LyXFont const &) const { - insetWidth = max(textWidth(bv->painter()), - (int)TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET)); - return insetWidth; + insetWidth = max(textWidth(bv), (int)getLyXText(bv)->width) + + (2 * TEXT_TO_INSET_OFFSET); + insetWidth = max(insetWidth, 10); + return insetWidth; } -int InsetText::textWidth(Painter & pain) const +int InsetText::textWidth(BufferView * bv, bool fordraw) const { - int w = getMaxWidth(pain, this); - return w; + int w; + if (!autoBreakRows) { + w = -1; + } else { + w = getMaxWidth(bv, this); + } + if (fordraw) { + return max(w - (2 * TEXT_TO_INSET_OFFSET), + (int)getLyXText(bv)->width); + } else if (w < 0) { + return -1; + } + return w - (2 * TEXT_TO_INSET_OFFSET); } void InsetText::draw(BufferView * bv, LyXFont const & f, - int baseline, float & x, bool cleared) const + int baseline, float & x, bool cleared) const { - Painter & pain = bv->painter(); + if (nodraw()) + return; - // no draw is necessary !!! - if ((drawFrame == LOCKED) && !locked && !par->size()) { - if (!cleared && (need_update == CLEAR_FRAME)) { - pain.rectangle(top_x + 1, baseline - insetAscent + 1, - width(bv, f) - 1, - insetAscent + insetDescent - 1, - LColor::background); - } - top_x = int(x); - top_baseline = baseline; - x += width(bv, f); - need_update = NONE; - return; - } - - xpos = x; - UpdatableInset::draw(bv, f, baseline, x, cleared); - - // if top_x differs we have a rule down and we don't have to clear anything - if (!cleared && (top_x == int(x)) && - ((need_update==FULL) || (top_baseline!=baseline))) - { - int w = insetWidth; - int h = insetAscent + insetDescent; - int ty = baseline - insetAscent; + Painter & pain = bv->painter(); - if (ty < 0) { - h += ty; - ty = 0; + // 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); + return; + } } - if ((ty + h) > pain.paperHeight()) - h = pain.paperHeight(); - if ((top_x + drawTextXOffset + w) > pain.paperWidth()) - w = pain.paperWidth(); - pain.fillRectangle(top_x+drawTextXOffset, ty, w, h); - cleared = true; - need_update = FULL; - } - if (!cleared && (need_update == NONE)) - return; - if (top_x != int(x)) { -// printf("InsetText::draw1 -> INIT(%d)\n",insetWidth); - need_update = INIT; - top_x = int(x); - bv->text->status = LyXText::CHANGED_IN_DRAW; - return; - } + // call these methods so that insetWidth, insetAscent and + // insetDescent have the right values. + width(bv, f); + ascent(bv, f); + descent(bv, f); - top_baseline = baseline; - top_y = baseline - ascent(bv, f); - last_width = width(bv, f); - last_height = ascent(bv, f) + descent(bv, f); + // repaint the background if needed + if (cleared && backgroundColor() != LColor::background) { + clearInset(bv, baseline, cleared); + } - if (the_locking_inset && (cpar(bv) == inset_par) && (cpos(bv) == inset_pos)) { - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - } - if (!cleared && (need_update == CURSOR) && !TEXT(bv)->selection) { - x += width(bv, f); - need_update = NONE; - return; - } - x += TEXT_TO_INSET_OFFSET; - { - int y = 0; - Row * row = TEXT(bv)->GetRowNearY(y); + // no draw is necessary !!! + if ((drawFrame_ == LOCKED) && !locked && !par->size()) { + top_baseline = baseline; + x += width(bv, f); + if (need_update & CLEAR_FRAME) + clearFrame(pain, cleared); + need_update = NONE; + return; + } + + xpos = x; + if (!owner()) + x += static_cast(scroll()); + + // if top_x differs we did it already + 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); + } + + if (cleared) + frame_is_visible = false; + + if (!cleared && (need_update == NONE)) { + if (locked) + drawFrame(pain, cleared); + return; + } + + top_baseline = baseline; + top_y = baseline - insetAscent; + + if (last_drawn_width != insetWidth) { + if (!cleared) + clearInset(bv, baseline, cleared); + need_update |= FULL; + last_drawn_width = insetWidth; + } + + if (the_locking_inset && (cpar(bv) == inset_par) + && (cpos(bv) == inset_pos)) { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + } + if (!cleared && (need_update == CURSOR) + && !getLyXText(bv)->selection.set()) { + drawFrame(pain, cleared); + x += insetWidth; + need_update = NONE; + return; + } + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + x += TEXT_TO_INSET_OFFSET; + + 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(); - row = row->next(); - } - if (y_offset < 0) - y_offset = y; - TEXT(bv)->first = first; - if (cleared || !locked || (need_update==FULL) || (need_update==INIT)) { - int yf = y_offset; - y = 0; - while ((row != 0) && (yf < ph)) { - TEXT(bv)->GetVisibleRow(bv, y+y_offset, int(x), row, - y+first, cleared); y += row->height(); - yf += row->height(); + first += row->height(); row = row->next(); - } - } else if (need_update == SELECTION) { - bv->screen()->ToggleToggle(TEXT(bv), bv, y_offset, int(x)); + } + if (y_offset < 0) + y_offset = y; + lt->first = 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 += row->height(); + yf += row->height(); + row = row->next(); + } + } else if (!locked) { + if (need_update & CURSOR) { + bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x)); + lt->clearSelection(); + lt->selection.cursor = lt->cursor; + } + bv->screen()->update(lt, bv, y_offset, int(x)); } else { - locked = false; - if (need_update == CURSOR) { - bv->screen()->ToggleSelection(TEXT(bv), bv, true, y_offset,int(x)); - TEXT(bv)->ClearSelection(); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - } - bv->screen()->Update(TEXT(bv), bv, y_offset, int(x)); - locked = true; - } - } - TEXT(bv)->refresh_y = 0; - TEXT(bv)->status = LyXText::UNCHANGED; - if ((need_update != CURSOR_PAR) && - ((drawFrame == ALWAYS) || ((drawFrame == LOCKED) && locked))) - { - pain.rectangle(top_x + 1, baseline - insetAscent + 1, - width(bv, f) - 1, insetAscent + insetDescent - 1, - frame_color); - } else if (need_update == CLEAR_FRAME) { - pain.rectangle(top_x + 1, baseline - insetAscent + 1, - width(bv, f) - 1, insetAscent + insetDescent - 1, - LColor::background); - } - x += width(bv, f) - TEXT_TO_INSET_OFFSET; - if (bv->text->status==LyXText::CHANGED_IN_DRAW) - { - need_update = INIT; -// printf("InsetText::draw2 -> INIT(%d)\n",insetWidth); - } - else if (need_update != INIT) - need_update = NONE; + locked = false; + if (need_update & SELECTION) { + bv->screen()->toggleToggle(lt, bv, y_offset, int(x)); + } else if (need_update & CURSOR) { + bv->screen()->toggleSelection(lt, bv, true, y_offset,int(x)); + lt->clearSelection(); + lt->selection.cursor = lt->cursor; + } + bv->screen()->update(lt, bv, y_offset, int(x)); + locked = true; + } + + lt->refresh_y = 0; + lt->status(bv, LyXText::UNCHANGED); + if ((need_update != CURSOR_PAR) && + ((drawFrame_ == ALWAYS) || ((drawFrame_ == LOCKED) && locked))) { + drawFrame(pain, cleared); + } else if (need_update & CLEAR_FRAME) { + clearFrame(pain, cleared); + } + + x += insetWidth - TEXT_TO_INSET_OFFSET; + + if (bv->text->status() == LyXText::CHANGED_IN_DRAW) { + need_update |= FULL; + } else if (need_update != INIT) { + need_update = NONE; + } + if (clear) + lt = 0; +} + + +void InsetText::drawFrame(Painter & pain, bool cleared) const +{ + static int const ttoD2 = TEXT_TO_INSET_OFFSET / 2; + if (!frame_is_visible || cleared) { + frame_x = top_x + ttoD2; + frame_y = top_baseline - insetAscent + ttoD2; + 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_is_visible = true; + } +} + + +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()); + } + frame_is_visible = false; + } } void InsetText::update(BufferView * bv, LyXFont const & font, bool reinit) { - if (reinit) { // && (need_update != CURSOR)) { - need_update = INIT; - resizeLyXText(bv); - if (owner()) - owner()->update(bv, font, true); - return; - } - if (the_locking_inset) { - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - the_locking_inset->update(bv, font, reinit); - } - if (need_update == INIT) { - resizeLyXText(bv); - need_update = FULL; - } - int oldw = insetWidth; -#if 1 - insetWidth = TEXT(bv)->width + (2 * TEXT_TO_INSET_OFFSET); - // max(textWidth(bv->painter()), - // static_cast(TEXT(bv)->width) + drawTextXOffset) + - // (2 * TEXT_TO_INSET_OFFSET); -#else - insetWidth = textWidth(bv->painter()); - if (insetWidth < 0) - insetWidth = static_cast(TEXT(bv)->width); -#endif - if (oldw != insetWidth) { -// printf("TW(%p): %d-%d-%d-%d\n",this,insetWidth, oldw, -// textWidth(bv->painter()),static_cast(TEXT(bv)->width)); - resizeLyXText(bv); - need_update = FULL; - update(bv, font, reinit); - return; - } - if ((need_update==CURSOR_PAR) && (TEXT(bv)->status==LyXText::UNCHANGED) && - the_locking_inset) - { - TEXT(bv)->UpdateInset(bv, the_locking_inset); - } - - if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH) - need_update = FULL; + if (in_update) { + if (reinit && owner()) { + reinitLyXText(); + owner()->update(bv, font, true); + } + return; + } + 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 (the_locking_inset) { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + the_locking_inset->update(bv, font, reinit); + } - int y_temp = 0; - Row * row = TEXT(bv)->GetRowNearY(y_temp); - insetAscent = row->ascent_of_text() + TEXT_TO_INSET_OFFSET; - insetDescent = TEXT(bv)->height - row->ascent_of_text() + - TEXT_TO_INSET_OFFSET; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if ((need_update & CURSOR_PAR) && (lt->status() == LyXText::UNCHANGED) && + the_locking_inset) + { + lt->updateInset(bv, the_locking_inset); + } + if (lt->status() == LyXText::NEED_MORE_REFRESH) + need_update |= FULL; + if (clear) + lt = 0; + in_update = false; } -void InsetText::UpdateLocal(BufferView * bv, UpdateCodes what, bool mark_dirty) +void InsetText::setUpdateStatus(BufferView * bv, int what) const { -// if (what == INIT) -// printf("InsetText::UpdateLocal -> INIT(%d)\n",insetWidth); - TEXT(bv)->FullRebreak(bv); - if (need_update != INIT) { - if (TEXT(bv)->status == LyXText::NEED_MORE_REFRESH) - need_update = FULL; - else if (!the_locking_inset || (what != CURSOR)) - need_update = what; - } - if ((need_update != CURSOR) || (TEXT(bv)->status != LyXText::UNCHANGED) || - TEXT(bv)->selection) - bv->updateInset(this, mark_dirty); - bv->owner()->showState(); - if (old_par != cpar(bv)) { - bv->owner()->setLayout(cpar(bv)->GetLayout()); - old_par = cpar(bv); - } + // 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 ((llt->status() == LyXText::NEED_MORE_REFRESH) || + (!autoBreakRows && + (llt->status() == LyXText::NEED_VERY_LITTLE_REFRESH))) + { + need_update |= FULL; + } 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 (llt->selection.set()) + need_update = FULL; + llt->clearSelection(); + } } -string const InsetText::EditMessage() const +void InsetText::updateLocal(BufferView * bv, int what, bool mark_dirty) const { - return _("Opened Text Inset"); + if (!autoBreakRows && par->next()) + collapseParagraphs(bv->buffer()->params); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + lt->fullRebreak(bv); + setUpdateStatus(bv, what); + bool flag = (((need_update != CURSOR) && (need_update != NONE)) || + (lt->status() != LyXText::UNCHANGED) || lt->selection.set()); + if (clear) + lt = 0; + if (flag) + bv->updateInset(const_cast(this), mark_dirty); + else + bv->fitCursor(); + + 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)->layout()); + old_par = cpar(bv); + } } -void InsetText::Edit(BufferView * bv, int x, int y, unsigned int button) +string const InsetText::editMessage() const { -// par->SetInsetOwner(this); - UpdatableInset::Edit(bv, x, y, button); + return _("Opened Text Inset"); +} - if (!bv->lockInset(this)) { - lyxerr[Debug::INSETS] << "Cannot lock inset" << endl; - return; - } - locked = true; - the_locking_inset = 0; - inset_pos = inset_x = inset_y = 0; - inset_boundary = false; - inset_par = 0; - old_par = 0; - if (!checkAndActivateInset(bv, x, y, button)) - TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset, - y+insetAscent); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - bv->text->FinishUndo(); - ShowInsetCursor(bv); - UpdateLocal(bv, FULL, false); - // If the inset is empty set the language of the current font to the - // language to the surronding text. - if (par->Last() == 0 && !par->next) { - LyXFont font(LyXFont::ALL_IGNORE); - font.setLanguage(bv->getParentLanguage(this)); - SetFont(bv, font, false); - } +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; + } + locked = true; + the_locking_inset = 0; + inset_pos = inset_x = inset_y = 0; + inset_boundary = false; + inset_par = 0; + old_par = 0; + int tmp_y = (y < 0) ? 0 : y; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if (!checkAndActivateInset(bv, x, tmp_y, button)) + lt->setCursorFromCoordinates(bv, x - drawTextXOffset, + y + insetAscent); + lt->clearSelection(); + finishUndo(); + // 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()) + { + LyXFont font(LyXFont::ALL_IGNORE); + font.setLanguage(bv->getParentLanguage(this)); + setFont(bv, font, false); + } + showInsetCursor(bv); + if (clear) + lt = 0; + + int code = CURSOR; + if (drawFrame_ == LOCKED) + code = CURSOR|DRAW_FRAME; + updateLocal(bv, code, false); } -void InsetText::InsetUnlock(BufferView * bv) +void InsetText::edit(BufferView * bv, bool front) { - if (the_locking_inset) { - the_locking_inset->InsetUnlock(bv); + UpdatableInset::edit(bv, front); + + if (!bv->lockInset(this)) { + lyxerr[Debug::INSETS] << "Cannot lock inset" << endl; + return; + } + locked = true; the_locking_inset = 0; - } - HideInsetCursor(bv); - no_selection = false; - locked = false; - TEXT(bv)->selection = 0; - UpdateLocal(bv, CLEAR_FRAME, false); - if (owner()) - bv->owner()->setLayout(owner()->getLyXText(bv) - ->cursor.par()->GetLayout()); - else - bv->owner()->setLayout(bv->text->cursor.par()->GetLayout()); + inset_pos = inset_x = inset_y = 0; + inset_boundary = false; + inset_par = 0; + old_par = 0; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if (front) + lt->setCursor(bv, par, 0); + else { + Paragraph * p = par; + 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(); + // 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()) { + LyXFont font(LyXFont::ALL_IGNORE); + font.setLanguage(bv->getParentLanguage(this)); + setFont(bv, font, false); + } + showInsetCursor(bv); + if (clear) + lt = 0; + int code = CURSOR; + if (drawFrame_ == LOCKED) + code = CURSOR|DRAW_FRAME; + updateLocal(bv, code, false); } -bool InsetText::LockInsetInInset(BufferView * bv, UpdatableInset * inset) +void InsetText::insetUnlock(BufferView * bv) +{ + if (the_locking_inset) { + the_locking_inset->insetUnlock(bv); + the_locking_inset = 0; + } + hideInsetCursor(bv); + no_selection = false; + locked = false; + int code; + if (drawFrame_ == LOCKED) + code = CURSOR|CLEAR_FRAME; + else + code = CURSOR; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if (lt->selection.set()) { + lt->clearSelection(); + code = FULL; + } else if (owner()) { + bv->owner()->setLayout(owner()->getLyXText(bv) + ->cursor.par()->layout()); + } else + bv->owner()->setLayout(bv->text->cursor.par()->layout()); + // hack for deleteEmptyParMech + 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) { - lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" << inset << "): "; - if (!inset) - 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); - TEXT(bv)->UpdateInset(bv, the_locking_inset); - return true; - } else if (the_locking_inset && (the_locking_inset == inset)) { - if (cpar(bv) == inset_par && cpos(bv) == inset_pos) { - lyxerr[Debug::INSETS] << "OK" << endl; - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - } else { - lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl; - } - } else if (the_locking_inset) { - lyxerr[Debug::INSETS] << "MAYBE" << endl; - return the_locking_inset->LockInsetInInset(bv, inset); - } - lyxerr[Debug::INSETS] << "NOT OK" << endl; - return false; -} - - -bool InsetText::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset, - bool lr) -{ - if (!the_locking_inset) - return false; - if (the_locking_inset == inset) { - the_locking_inset->InsetUnlock(bv); - TEXT(bv)->UpdateInset(bv, inset); - the_locking_inset = 0; - if (lr) - moveRight(bv, false); - old_par = 0; // force layout setting - UpdateLocal(bv, CURSOR_PAR, false); - return true; - } - return the_locking_inset->UnlockInsetInInset(bv, inset, lr); -} - - -bool InsetText::UpdateInsetInInset(BufferView * bv, Inset * inset) -{ - if (!the_locking_inset) - return false; - if (the_locking_inset != inset) { - TEXT(bv)->UpdateInset(bv, the_locking_inset); - need_update = CURSOR_PAR; - return the_locking_inset->UpdateInsetInInset(bv, inset); - } -// UpdateLocal(bv, FULL, false); - if (TEXT(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; - } - return true; + updateLocal(bv, CURSOR, false); +} + + +bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset) +{ + lyxerr[Debug::INSETS] << "InsetText::LockInsetInInset(" + << 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; + lockInset(bv, inset); + return true; + } else if (the_locking_inset && (the_locking_inset == inset)) { + if (cpar(bv) == inset_par && cpos(bv) == inset_pos) { + lyxerr[Debug::INSETS] << "OK" << endl; + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + } else { + lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl; + } + } else if (the_locking_inset) { + lyxerr[Debug::INSETS] << "MAYBE" << endl; + return the_locking_inset->lockInsetInInset(bv, inset); + } + lyxerr[Debug::INSETS] << "NOT OK" << endl; + return false; } -void InsetText::InsetButtonPress(BufferView * bv, int x, int y, int button) +bool InsetText::unlockInsetInInset(BufferView * bv, UpdatableInset * inset, + bool lr) { - no_selection = false; + if (!the_locking_inset) + return false; + if (the_locking_inset == inset) { + the_locking_inset->insetUnlock(bv); + getLyXText(bv)->updateInset(bv, inset); + the_locking_inset = 0; + if (lr) + moveRight(bv, false); + old_par = 0; // force layout setting + if (scroll()) + scroll(bv, 0.0F); + else + updateLocal(bv, CURSOR, false); + return true; + } + return the_locking_inset->unlockInsetInInset(bv, inset, lr); +} - int tmp_x = x - drawTextXOffset; - int tmp_y = y + insetAscent - TEXT(bv)->first; - Inset * inset = bv->checkInsetHit(TEXT(bv), tmp_x, tmp_y, button); - HideInsetCursor(bv); - if (the_locking_inset) { - if (the_locking_inset == inset) { - 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); - if (the_locking_inset) { - UpdateLocal(bv, CURSOR_PAR, false); - } - return; - } - // otherwise only unlock the_locking_inset - the_locking_inset->InsetUnlock(bv); - the_locking_inset = 0; - } - if (bv->theLockingInset()) { - if (inset && inset->Editable() == Inset::HIGHLY_EDITABLE) { - UpdatableInset * uinset = static_cast(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); - the_locking_inset = uinset; - uinset->InsetButtonPress(bv, x - inset_x, y - inset_y, button); - uinset->Edit(bv, x - inset_x, y - inset_y, 0); -// TEXT(bv)->ClearSelection(); - if (the_locking_inset) { - UpdateLocal(bv, CURSOR_PAR, false); - } - return; - } - } - if (!inset) { - bool paste_internally = false; - if ((button == 2) && TEXT(bv)->selection) { - LocalDispatch(bv, LFUN_COPY, ""); - paste_internally = true; - } - TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset, - y + insetAscent); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - UpdateLocal(bv, CURSOR, false); - bv->owner()->setLayout(cpar(bv)->GetLayout()); - old_par = cpar(bv); - // Insert primary selection with middle mouse - // if there is a local selection in the current buffer, - // insert this - if (button == 2) { - if (paste_internally) - LocalDispatch(bv, LFUN_PASTE, ""); - else - LocalDispatch(bv, LFUN_PASTESELECTION, "paragraph"); - } - } - ShowInsetCursor(bv); -} - - -void InsetText::InsetButtonRelease(BufferView * bv, int x, int y, int button) -{ - UpdatableInset * inset = 0; - - if (the_locking_inset) { - the_locking_inset->InsetButtonRelease(bv, - x - inset_x, y - inset_y, - button); - } else { - if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::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); +bool InsetText::updateInsetInInset(BufferView * bv, Inset * 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 (!the_locking_inset) { + bool found = lt->updateInset(bv, inset); + if (clear) + lt = 0; + if (found) + setUpdateStatus(bv, NONE); + return found; + } + if (the_locking_inset != inset) { + bool found = the_locking_inset->updateInsetInInset(bv, inset); + if (clear) + lt = 0; + if (found) + setUpdateStatus(bv, CURSOR_PAR); + return found; + } + bool found = lt->updateInset(bv, inset); + if (clear) + lt = 0; + if (found) { + setUpdateStatus(bv, CURSOR_PAR); + if (cpar(bv) == inset_par && cpos(bv) == inset_pos) { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + } + } + return found; +} + + +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); + + 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; + 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 = 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 (bv->theLockingInset()) { + if (isHighlyEditableInset(inset)) { + UpdatableInset * uinset = static_cast(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); + the_locking_inset = uinset; + uinset->insetButtonPress(bv, x - inset_x, y - inset_y, + button); + uinset->edit(bv, x - inset_x, y - inset_y, 0); + if (the_locking_inset) + updateLocal(bv, CURSOR, false); + no_selection = false; + return; + } + } + if (!inset) { // && (button == 2)) { + bool paste_internally = false; + if ((button == 2) && getLyXText(bv)->selection.set()) { + localDispatch(bv, LFUN_COPY, ""); + paste_internally = true; + } + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + + 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)->layout()); + old_par = cpar(bv); + // Insert primary selection with middle mouse + // if there is a local selection in the current buffer, + // insert this + if (button == 2) { + if (paste_internally) + localDispatch(bv, LFUN_PASTE, ""); + else + localDispatch(bv, LFUN_PASTESELECTION, + "paragraph"); + } + } else { + getLyXText(bv)->clearSelection(); + } + showInsetCursor(bv); + no_selection = false; +} + + +bool InsetText::insetButtonRelease(BufferView * bv, int x, int y, int button) +{ + if (the_locking_inset) { + return the_locking_inset->insetButtonRelease(bv, + x - inset_x, y - inset_y, + button); } - } - no_selection = false; + int tmp_x = x - drawTextXOffset; + int tmp_y = y + insetAscent - getLyXText(bv)->first; + 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); + } + return ret; } -void InsetText::InsetMotionNotify(BufferView * bv, int x, int y, int state) +void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state) { - if (the_locking_inset) { - the_locking_inset->InsetMotionNotify(bv, x - inset_x, - y - inset_y,state); - return; - } - if (!no_selection) { - HideInsetCursor(bv); - TEXT(bv)->SetCursorFromCoordinates(bv, x-drawTextXOffset, - y+insetAscent); - TEXT(bv)->SetSelection(); - if (TEXT(bv)->toggle_cursor.par()!=TEXT(bv)->toggle_end_cursor.par() || - TEXT(bv)->toggle_cursor.pos()!=TEXT(bv)->toggle_end_cursor.pos()) - UpdateLocal(bv, SELECTION, false); - ShowInsetCursor(bv); - } - no_selection = false; + if (no_selection || ((mouse_x == x) && (mouse_y == y))) + return; + if (the_locking_inset) { + the_locking_inset->insetMotionNotify(bv, x - inset_x, + y - inset_y,state); + return; + } + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + hideInsetCursor(bv); + 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); } -void InsetText::InsetKeyPress(XKeyEvent * xke) +void InsetText::insetKeyPress(XKeyEvent * xke) { - if (the_locking_inset) { - the_locking_inset->InsetKeyPress(xke); - return; - } + if (the_locking_inset) { + the_locking_inset->insetKeyPress(xke); + return; + } } UpdatableInset::RESULT -InsetText::LocalDispatch(BufferView * bv, - int action, string const & arg) -{ - no_selection = false; - UpdatableInset::RESULT - result= UpdatableInset::LocalDispatch(bv, action, arg); - if (result != UNDISPATCHED) { - return DISPATCHED; - } - - result=DISPATCHED; - if ((action < 0) && arg.empty()) - return FINISHED; - - if (the_locking_inset) { - result = the_locking_inset->LocalDispatch(bv, action, arg); - if (result == DISPATCHED_NOUPDATE) - return result; - 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: - moveRightIntern(bv, false, false); - break; - case LFUN_RIGHT: - if (!TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) - moveRightIntern(bv, false, false); - dispatched = true; - break; - case LFUN_LEFT: - if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) - moveRightIntern(bv, false, false); - dispatched = true; - break; - } - the_locking_inset = 0; - if (dispatched) +InsetText::localDispatch(BufferView * bv, + kb_action action, string const & arg) +{ + bool was_empty = par->size() == 0 && !par->next(); + no_selection = false; + UpdatableInset::RESULT + result= UpdatableInset::localDispatch(bv, action, arg); + if (result != UNDISPATCHED) { return DISPATCHED; } - } - HideInsetCursor(bv); - switch (action) { + + result = DISPATCHED; + if ((action < 0) && arg.empty()) + return FINISHED; + + if (the_locking_inset) { + result = the_locking_inset->localDispatch(bv, action, arg); + if (result == DISPATCHED_NOUPDATE) + return result; + else if (result == DISPATCHED) { + updateLocal(bv, CURSOR_PAR, false); + return result; + } else if (result >= FINISHED) { + switch (result) { + case FINISHED_RIGHT: + moveRightIntern(bv, false, false); + result = DISPATCHED; + break; + case FINISHED_UP: + if ((result = moveUp(bv)) >= FINISHED) { + updateLocal(bv, CURSOR, false); + bv->unlockInset(this); + } + break; + case FINISHED_DOWN: + if ((result = moveDown(bv)) >= FINISHED) { + updateLocal(bv, CURSOR, false); + bv->unlockInset(this); + } + break; + default: + result = DISPATCHED; + break; + } + the_locking_inset = 0; +#ifdef WITH_WARNINGS +#warning I changed this to always return Dispatched maybe it is wrong (20011001 Jug) +#endif + return result; + } + } + hideInsetCursor(bv); + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + int updwhat = 0; + int updflag = false; + switch (action) { // Normal chars - case LFUN_UNKNOWN_ACTION: - if (bv->buffer()->isReadonly()) { + case LFUN_SELFINSERT: + if (bv->buffer()->isReadonly()) { // setErrorMessage(N_("Document is read only")); - break; - } - if (!arg.empty()) { - /* Automatically delete the currently selected - * text and replace it with what is being - * typed in now. Depends on lyxrc settings - * "auto_region_delete", which defaults to - * true (on). */ - - bv->text->SetUndo(bv->buffer(), Undo::INSERT, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - bv->setState(); - if (lyxrc.auto_region_delete) { - if (TEXT(bv)->selection){ - TEXT(bv)->CutSelection(bv, false); + break; } - } - TEXT(bv)->ClearSelection(); - for (string::size_type i = 0; i < arg.length(); ++i) { - if (greek_kb_flag) { - if (!math_insert_greek(bv, arg[i])) { -#if 0 - bv->owner()->getIntl()->getTrans()->TranslateAndInsert(arg[i], TEXT(bv)); -#else - bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], TEXT(bv)); -#endif - } else if (!the_locking_inset) { - (void)moveRight(bv, false); - } - } else { -#if 0 - bv->owner()->getIntl()->getTrans()->TranslateAndInsert(arg[i], TEXT(bv)); -#else - bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], TEXT(bv)); -#endif + if (!arg.empty()) { + /* Automatically delete the currently selected + * text and replace it with what is being + * typed in now. Depends on lyxrc settings + * "auto_region_delete", which defaults to + * true (on). */ + + setUndo(bv, Undo::INSERT, + lt->cursor.par(), lt->cursor.par()->next()); + bv->setState(); + if (lyxrc.auto_region_delete) { + if (lt->selection.set()) { + lt->cutSelection(bv, false); + } + } + lt->clearSelection(); + for (string::size_type i = 0; i < arg.length(); ++i) { + bv->owner()->getIntl()->getTrans().TranslateAndInsert(arg[i], lt); + } } - } - } - UpdateLocal(bv, CURSOR_PAR, true); - result=DISPATCHED_NOUPDATE; - break; - // --- Cursor Movements --------------------------------------------- - case LFUN_RIGHTSEL: - bv->text->FinishUndo(); - moveRight(bv, false, true); - TEXT(bv)->SetSelection(); - UpdateLocal(bv, SELECTION, false); - break; - case LFUN_RIGHT: - result = moveRight(bv); - bv->text->FinishUndo(); - TEXT(bv)->ClearSelection(); - UpdateLocal(bv, CURSOR, false); - break; - case LFUN_LEFTSEL: - bv->text->FinishUndo(); - moveLeft(bv, false, true); - TEXT(bv)->SetSelection(); - UpdateLocal(bv, SELECTION, false); - break; - case LFUN_LEFT: - bv->text->FinishUndo(); - result = moveLeft(bv); - TEXT(bv)->ClearSelection(); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - UpdateLocal(bv, CURSOR, false); - break; - case LFUN_DOWNSEL: - bv->text->FinishUndo(); - moveDown(bv); - TEXT(bv)->SetSelection(); - UpdateLocal(bv, SELECTION, false); - break; - case LFUN_DOWN: - bv->text->FinishUndo(); - result = moveDown(bv); - TEXT(bv)->ClearSelection(); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - UpdateLocal(bv, CURSOR, false); - break; - case LFUN_UPSEL: - bv->text->FinishUndo(); - moveUp(bv); - TEXT(bv)->SetSelection(); - UpdateLocal(bv, SELECTION, false); - break; - case LFUN_UP: - bv->text->FinishUndo(); - result = moveUp(bv); - TEXT(bv)->ClearSelection(); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - UpdateLocal(bv, CURSOR, false); - break; - case LFUN_HOME: - bv->text->FinishUndo(); - TEXT(bv)->CursorHome(bv); - TEXT(bv)->ClearSelection(); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - UpdateLocal(bv, CURSOR, false); - break; - case LFUN_END: - TEXT(bv)->CursorEnd(bv); - TEXT(bv)->ClearSelection(); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - UpdateLocal(bv, CURSOR, false); - break; - case LFUN_BACKSPACE: - bv->text->SetUndo(bv->buffer(), Undo::DELETE, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - if (TEXT(bv)->selection) - TEXT(bv)->CutSelection(bv); - else - TEXT(bv)->Backspace(bv); - UpdateLocal(bv, CURSOR_PAR, true); - break; - case LFUN_DELETE: - bv->text->SetUndo(bv->buffer(), Undo::DELETE, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - if (TEXT(bv)->selection) - TEXT(bv)->CutSelection(bv); - else - TEXT(bv)->Delete(bv); - UpdateLocal(bv, CURSOR_PAR, true); - break; - case LFUN_CUT: - bv->text->SetUndo(bv->buffer(), Undo::DELETE, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - TEXT(bv)->CutSelection(bv); - UpdateLocal(bv, CURSOR_PAR, true); + lt->selection.cursor = lt->cursor; + updwhat = CURSOR_PAR; + updflag = true; + result = DISPATCHED_NOUPDATE; + break; + // --- Cursor Movements ----------------------------------- + case LFUN_RIGHTSEL: + finishUndo(); + moveRight(bv, false, true); + lt->setSelection(bv); + updwhat = SELECTION; + break; + case LFUN_RIGHT: + result = moveRight(bv); + finishUndo(); + updwhat = CURSOR; + break; + case LFUN_LEFTSEL: + finishUndo(); + moveLeft(bv, false, true); + lt->setSelection(bv); + updwhat = SELECTION; + break; + case LFUN_LEFT: + finishUndo(); + result = moveLeft(bv); + updwhat = CURSOR; + break; + case LFUN_DOWNSEL: + finishUndo(); + moveDown(bv); + lt->setSelection(bv); + updwhat = SELECTION; + break; + case LFUN_DOWN: + finishUndo(); + result = moveDown(bv); + updwhat = CURSOR; + break; + case LFUN_UPSEL: + finishUndo(); + moveUp(bv); + lt->setSelection(bv); + updwhat = SELECTION; + break; + case LFUN_UP: + finishUndo(); + result = moveUp(bv); + updwhat = CURSOR; + break; + case LFUN_HOME: + finishUndo(); + lt->cursorHome(bv); + updwhat = CURSOR; + break; + case LFUN_END: + lt->cursorEnd(bv); + updwhat = CURSOR; + break; + case LFUN_BACKSPACE: { + setUndo(bv, Undo::DELETE, + lt->cursor.par(), lt->cursor.par()->next()); + if (lt->selection.set()) + lt->cutSelection(bv); + else + lt->backspace(bv); + updwhat = CURSOR_PAR; + updflag = true; + } break; - case LFUN_COPY: - bv->text->FinishUndo(); - TEXT(bv)->CopySelection(bv); - UpdateLocal(bv, CURSOR_PAR, false); + + case LFUN_DELETE: { + setUndo(bv, Undo::DELETE, + lt->cursor.par(), lt->cursor.par()->next()); + if (lt->selection.set()) { + lt->cutSelection(bv); + } else { + lt->Delete(bv); + } + updwhat = CURSOR_PAR; + updflag = true; + } break; - case LFUN_PASTESELECTION: - { - string clip(bv->workarea()->getClipboard()); - if (clip.empty()) - break; - if (arg == "paragraph") { - TEXT(bv)->InsertStringB(bv, clip); - } else { - TEXT(bv)->InsertStringA(bv, clip); + case LFUN_CUT: { + setUndo(bv, Undo::DELETE, + lt->cursor.par(), lt->cursor.par()->next()); + lt->cutSelection(bv); + updwhat = CURSOR_PAR; + updflag = true; } - UpdateLocal(bv, CURSOR_PAR, true); break; - } - case LFUN_PASTE: - if (!autoBreakRows) { - CutAndPaste cap; - if (cap.nrOfParagraphs() > 1) { - WriteAlert(_("Impossible operation"), - _("Cannot include more than one paragraph!"), - _("Sorry.")); + case LFUN_COPY: + finishUndo(); + lt->copySelection(bv); + updwhat = CURSOR_PAR; + break; + case LFUN_PASTESELECTION: + { + string const clip(bv->getClipboard()); + + if (clip.empty()) + break; + if (arg == "paragraph") { + lt->insertStringAsParagraphs(bv, clip); + } else { + lt->insertStringAsLines(bv, clip); + } + updwhat = CURSOR_PAR; + updflag = true; break; - } } - bv->text->SetUndo(bv->buffer(), Undo::INSERT, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - TEXT(bv)->PasteSelection(bv); - UpdateLocal(bv, CURSOR_PAR, true); - break; - case LFUN_BREAKPARAGRAPH: - if (!autoBreakRows) - return DISPATCHED; - TEXT(bv)->BreakParagraph(bv, 0); - UpdateLocal(bv, FULL, true); - break; - case LFUN_BREAKPARAGRAPHKEEPLAYOUT: - if (!autoBreakRows) - return DISPATCHED; - TEXT(bv)->BreakParagraph(bv, 1); - UpdateLocal(bv, FULL, true); + case LFUN_PASTE: { + if (!autoBreakRows) { + + if (CutAndPaste::nrOfParagraphs() > 1) { + Alert::alert(_("Impossible operation"), + _("Cannot include more than one paragraph!"), + _("Sorry.")); + break; + } + } + setUndo(bv, Undo::INSERT, + lt->cursor.par(), lt->cursor.par()->next()); + lt->pasteSelection(bv); + updwhat = CURSOR_PAR; + updflag = true; + } break; - case LFUN_BREAKLINE: - if (!autoBreakRows) - return DISPATCHED; - bv->text->SetUndo(bv->buffer(), Undo::INSERT, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - TEXT(bv)->InsertChar(bv, LyXParagraph::META_NEWLINE); - UpdateLocal(bv, CURSOR_PAR, true); + + case LFUN_BREAKPARAGRAPH: + if (!autoBreakRows) { + result = DISPATCHED; + break; + } + lt->breakParagraph(bv, 0); + updwhat = FULL; + updflag = true; + break; + case LFUN_BREAKPARAGRAPHKEEPLAYOUT: + if (!autoBreakRows) { + result = DISPATCHED; + break; + } + lt->breakParagraph(bv, 1); + updwhat = FULL; + updflag = true; + break; + + case LFUN_BREAKLINE: { + if (!autoBreakRows) { + result = DISPATCHED; + break; + } + setUndo(bv, Undo::INSERT, + lt->cursor.par(), lt->cursor.par()->next()); + lt->insertChar(bv, Paragraph::META_NEWLINE); + updwhat = 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; - - // 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); - - // If the entry is obsolete, use the new one instead. - if (layout.first) { - string obs = textclasslist.Style(tclass,layout.second). - obsoleted_by(); - if (!obs.empty()) - layout = textclasslist.NumberOfLayout(tclass, obs); - } - - // see if we found the layout number: - if (!layout.first) { - string msg = string(N_("Layout ")) + arg + N_(" not known"); - - bv->owner()->getMiniBuffer()->Set(msg); + + case LFUN_LAYOUT: + // do not set layouts on non breakable textinsets + if (autoBreakRows) { + string cur_layout = cpar(bv)->layout(); + + // Derive layout number from given argument (string) + // and current buffer's textclass (number). */ + textclass_type tclass = bv->buffer()->params.textclass; + string layout = lowercase(arg); + bool hasLayout = textclasslist[tclass].hasLayout(layout); + + // If the entry is obsolete, use the new one instead. + if (hasLayout) { + string const & obs = + textclasslist[tclass][layout]. + obsoleted_by(); + if (!obs.empty()) + layout = lowercase(obs); + } + + // see if we found the layout number: + if (!hasLayout) { + string const msg = string(N_("Layout ")) + arg + N_(" not known"); + bv->owner()->getLyXFunc()->dispatch(LFUN_MESSAGE, msg); + break; + } + + 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)->layout()); + } break; - } - - if (cur_layout != layout.second) { - cur_layout = layout.second; - TEXT(bv)->SetLayout(bv, layout.second); - bv->owner()->setLayout(cpar(bv)->GetLayout()); - UpdateLocal(bv, CURSOR_PAR, true); - } - } else { - // reset the layout box - bv->owner()->setLayout(cpar(bv)->GetLayout()); + case LFUN_PARAGRAPH_SPACING: + // This one is absolutely not working. When fiddling with this + // it also seems to me that the paragraphs inside the insettext + // inherit bufferparams/paragraphparams in a strange way. (Lgb) + { + Paragraph * par = lt->cursor.par(); + Spacing::Space cur_spacing = par->params().spacing().getSpace(); + float cur_value = 1.0; + if (cur_spacing == Spacing::Other) { + cur_value = par->params().spacing().getValue(); + } + + istringstream istr(arg.c_str()); + string tmp; + istr >> tmp; + Spacing::Space new_spacing = cur_spacing; + float new_value = cur_value; + if (tmp.empty()) { + lyxerr << "Missing argument to `paragraph-spacing'" + << endl; + } else if (tmp == "single") { + new_spacing = Spacing::Single; + } else if (tmp == "onehalf") { + new_spacing = Spacing::Onehalf; + } else if (tmp == "double") { + new_spacing = Spacing::Double; + } else if (tmp == "other") { + new_spacing = Spacing::Other; + float tmpval = 0.0; + istr >> tmpval; + lyxerr << "new_value = " << tmpval << endl; + if (tmpval != 0.0) + new_value = tmpval; + } else if (tmp == "default") { + new_spacing = Spacing::Default; + } else { + lyxerr << _("Unknown spacing argument: ") + << arg << endl; + } + if (cur_spacing != new_spacing || cur_value != new_value) { + par->params().spacing(Spacing(new_spacing, new_value)); + updwhat = CURSOR_PAR; + updflag = true; + } } break; - case LFUN_PARAGRAPH_SPACING: - // This one is absolutely not working. When fiddling with this - // it also seems to me that the paragraphs inside the insettext - // inherit bufferparams/paragraphparams in a strange way. (Lgb) - { - LyXParagraph * par = TEXT(bv)->cursor.par(); - Spacing::Space cur_spacing = par->spacing.getSpace(); - float cur_value = 1.0; - if (cur_spacing == Spacing::Other) { - cur_value = par->spacing.getValue(); - } - - std::istringstream istr(arg.c_str()); - string tmp; - istr >> tmp; - Spacing::Space new_spacing = cur_spacing; - float new_value = cur_value; - if (tmp.empty()) { - lyxerr << "Missing argument to `paragraph-spacing'" - << endl; - } else if (tmp == "single") { - new_spacing = Spacing::Single; - } else if (tmp == "onehalf") { - new_spacing = Spacing::Onehalf; - } else if (tmp == "double") { - new_spacing = Spacing::Double; - } else if (tmp == "other") { - new_spacing = Spacing::Other; - float tmpval = 0.0; - istr >> tmpval; - lyxerr << "new_value = " << tmpval << endl; - if (tmpval != 0.0) - new_value = tmpval; - } else if (tmp == "default") { - new_spacing = Spacing::Default; - } else { - lyxerr << _("Unknown spacing argument: ") - << arg << endl; - } - if (cur_spacing != new_spacing || cur_value != new_value) { - par->spacing.set(new_spacing, new_value); - //TEXT(bv)->RedoParagraph(owner->view()); - UpdateLocal(bv, CURSOR_PAR, true); - //bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); - } - } - break; - default: - result = UNDISPATCHED; - break; - } - if (result != FINISHED) { - ShowInsetCursor(bv); - } else - bv->unlockInset(this); - return result; + 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()) { + LyXFont font(LyXFont::ALL_IGNORE); + font.setLanguage(bv->getParentLanguage(this)); + setFont(bv, font, false); + } + + if (result < FINISHED) { + showInsetCursor(bv); + } else + bv->unlockInset(this); + return result; } -int InsetText::Latex(Buffer const * buf, ostream & os, bool, bool) const +int InsetText::latex(Buffer const * buf, ostream & os, bool, bool) const { - TexRow texrow; - buf->latexParagraphs(os, par, 0, texrow); - return texrow.rows(); + TexRow texrow; + buf->latexParagraphs(os, par, 0, texrow); + return texrow.rows(); } -int InsetText::Ascii(Buffer const * buf, ostream & os, int linelen) const +int InsetText::ascii(Buffer const * buf, ostream & os, int linelen) const { - LyXParagraph * p = par; - unsigned int lines = 0; - - string tmp; - while (p) { - tmp = buf->asciiParagraph(p, linelen); - lines += countChar(tmp, '\n'); - os << tmp; - p = p->next; - } - return lines; + Paragraph * p = par; + unsigned int lines = 0; + + while (p) { + string const tmp = buf->asciiParagraph(p, linelen, p->previous()==0); + lines += lyx::count(tmp.begin(), tmp.end(), '\n'); + os << tmp; + p = p->next(); + } + return lines; } -int InsetText::DocBook(Buffer const * buf, ostream & os) const +int InsetText::docbook(Buffer const * buf, ostream & os) const { - LyXParagraph * p = par; - unsigned int lines = 0; - int desc=0; - - string tmp; - while (p) { - buf->SimpleDocBookOnePar(os,tmp,p,desc,0); - p = p->next; - } - - return lines; + Paragraph * p = par; + unsigned int lines = 0; + + 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) { + 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; } -void InsetText::Validate(LaTeXFeatures & features) const +void InsetText::validate(LaTeXFeatures & features) const { - LyXParagraph * p = par; - while(p) { - p->validate(features); - p = p->next; - } + Paragraph * p = par; + while (p) { + p->validate(features); + p = p->next(); + } } -int InsetText::BeginningOfMainBody(Buffer const * buf, LyXParagraph * p) const +int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const { - if (textclasslist.Style(buf->params.textclass, - p->GetLayout()).labeltype != LABEL_MANUAL) - return 0; - else - return p->BeginningOfMainBody(); + if (textclasslist[buf->params.textclass][p->layout()].labeltype != LABEL_MANUAL) + return 0; + else + return p->beginningOfMainBody(); } -void InsetText::GetCursorPos(BufferView * bv, +void InsetText::getCursorPos(BufferView * bv, int & x, int & y) const { - x = cx(bv); - y = cy(bv); + if (the_locking_inset) { + the_locking_inset->getCursorPos(bv, x, y); + return; + } + x = cx(bv); + y = cy(bv); } -unsigned int InsetText::InsetInInsetY() +unsigned int InsetText::insetInInsetY() { - if (!the_locking_inset) - return 0; + if (!the_locking_inset) + return 0; - return (inset_y + the_locking_inset->InsetInInsetY()); + return (inset_y + the_locking_inset->insetInInsetY()); } -void InsetText::ToggleInsetCursor(BufferView * bv) +void InsetText::toggleInsetCursor(BufferView * bv) { - if (the_locking_inset) { - the_locking_inset->ToggleInsetCursor(bv); - return; - } + if (the_locking_inset) { + the_locking_inset->toggleInsetCursor(bv); + return; + } - LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv)); + LyXFont const font(getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv))); - int asc = lyxfont::maxAscent(font); - int desc = lyxfont::maxDescent(font); + int const asc = lyxfont::maxAscent(font); + int const desc = lyxfont::maxDescent(font); - if (cursor_visible) - bv->hideLockedInsetCursor(); - else - bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc); - cursor_visible = !cursor_visible; + if (isCursorVisible()) + bv->hideLockedInsetCursor(); + else + bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc); + toggleCursorVisible(); } -void InsetText::ShowInsetCursor(BufferView * bv, bool show) +void InsetText::showInsetCursor(BufferView * bv, bool show) { - if (the_locking_inset) { - the_locking_inset->ShowInsetCursor(bv); - return; - } - if (!cursor_visible) { - LyXFont font = TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv)); + if (the_locking_inset) { + the_locking_inset->showInsetCursor(bv, show); + return; + } + if (!isCursorVisible()) { + LyXFont const font = + getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)); - int asc = lyxfont::maxAscent(font); - int desc = lyxfont::maxDescent(font); + int const asc = lyxfont::maxAscent(font); + int const desc = lyxfont::maxDescent(font); - bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc); - if (show) - bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc); - cursor_visible = true; - } + bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc); + if (show) + bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc); + setCursorVisible(true); + } } -void InsetText::HideInsetCursor(BufferView * bv) +void InsetText::hideInsetCursor(BufferView * bv) { - if (cursor_visible) { - bv->hideLockedInsetCursor(); - cursor_visible = false; - } - if (the_locking_inset) - the_locking_inset->HideInsetCursor(bv); + if (isCursorVisible()) { + bv->hideLockedInsetCursor(); + setCursorVisible(false); + } + if (the_locking_inset) + the_locking_inset->hideInsetCursor(bv); +} + + +void InsetText::fitInsetCursor(BufferView * bv) const +{ + if (the_locking_inset) { + the_locking_inset->fitInsetCursor(bv); + return; + } + 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); } UpdatableInset::RESULT InsetText::moveRight(BufferView * bv, bool activate_inset, bool selecting) { - if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) - return moveLeftIntern(bv, false, activate_inset, selecting); - else - return moveRightIntern(bv, false, activate_inset, selecting); + if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) + return moveLeftIntern(bv, false, activate_inset, selecting); + else + return moveRightIntern(bv, false, activate_inset, selecting); } + UpdatableInset::RESULT InsetText::moveLeft(BufferView * bv, bool activate_inset, bool selecting) { - if (TEXT(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) - return moveRightIntern(bv, true, activate_inset, selecting); - else - return moveLeftIntern(bv, true, activate_inset, selecting); + if (getLyXText(bv)->cursor.par()->isRightToLeftPar(bv->buffer()->params)) + return moveRightIntern(bv, true, activate_inset, selecting); + else + return moveLeftIntern(bv, true, activate_inset, selecting); } UpdatableInset::RESULT InsetText::moveRightIntern(BufferView * bv, bool behind, - bool activate_inset, bool selecting) + bool activate_inset, bool selecting) { - if (!cpar(bv)->next && (cpos(bv) >= cpar(bv)->Last())) - return FINISHED; - if (activate_inset && checkAndActivateInset(bv, behind)) - return DISPATCHED; - TEXT(bv)->CursorRight(bv, selecting); - return DISPATCHED_NOUPDATE; + if (!cpar(bv)->next() && (cpos(bv) >= cpar(bv)->size())) + return FINISHED_RIGHT; + if (activate_inset && checkAndActivateInset(bv, behind)) + return DISPATCHED; + getLyXText(bv)->cursorRight(bv); + if (!selecting) + getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; + return DISPATCHED_NOUPDATE; } UpdatableInset::RESULT InsetText::moveLeftIntern(BufferView * bv, bool behind, - bool activate_inset, bool selecting) -{ - if (!cpar(bv)->previous && (cpos(bv) <= 0)) - return FINISHED; - TEXT(bv)->CursorLeft(bv, selecting); - if (activate_inset && checkAndActivateInset(bv, behind)) - return DISPATCHED; - return DISPATCHED_NOUPDATE; + bool activate_inset, bool selecting) +{ + if (!cpar(bv)->previous() && (cpos(bv) <= 0)) + return FINISHED; + getLyXText(bv)->cursorLeft(bv); + if (!selecting) + getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; + if (activate_inset && checkAndActivateInset(bv, behind)) + return DISPATCHED; + return DISPATCHED_NOUPDATE; } UpdatableInset::RESULT InsetText::moveUp(BufferView * bv) { - if (!crow(bv)->previous()) - return FINISHED; - TEXT(bv)->CursorUp(bv); - return DISPATCHED_NOUPDATE; + if (!crow(bv)->previous()) + return FINISHED_UP; + getLyXText(bv)->cursorUp(bv); + return DISPATCHED_NOUPDATE; } UpdatableInset::RESULT InsetText::moveDown(BufferView * bv) { - if (!crow(bv)->next()) - return FINISHED; - TEXT(bv)->CursorDown(bv); - return DISPATCHED_NOUPDATE; + if (!crow(bv)->next()) + return FINISHED_DOWN; + getLyXText(bv)->cursorDown(bv); + return DISPATCHED_NOUPDATE; } -bool InsetText::InsertInset(BufferView * bv, Inset * inset) +bool InsetText::insertInset(BufferView * bv, Inset * inset) { - if (the_locking_inset) { - if (the_locking_inset->InsertInsetAllowed(inset)) - return the_locking_inset->InsertInset(bv, inset); - return false; - } - bv->text->SetUndo(bv->buffer(), Undo::INSERT, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - inset->setOwner(this); - HideInsetCursor(bv); - TEXT(bv)->InsertInset(bv, inset); - if ((cpar(bv)->GetChar(cpos(bv)) != LyXParagraph::META_INSET) || - (cpar(bv)->GetInset(cpos(bv)) != inset)) - TEXT(bv)->CursorLeft(bv); - TEXT(bv)->selection = 0; - bv->fitCursor(TEXT(bv)); - UpdateLocal(bv, CURSOR_PAR, true); - ShowInsetCursor(bv); - return true; + if (the_locking_inset) { + if (the_locking_inset->insetAllowed(inset)) + return the_locking_inset->insertInset(bv, inset); + return false; + } + 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); + bv->fitCursor(); + if (clear) + lt = 0; + updateLocal(bv, CURSOR_PAR|CURSOR, true); + unFreezeUndo(); + return true; } -UpdatableInset * InsetText::GetLockingInset() +bool InsetText::insetAllowed(Inset::Code code) const { - return the_locking_inset ? the_locking_inset->GetLockingInset() : this; + // 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) + ret = the_locking_inset->insetAllowed(code); + else if (owner()) + ret = owner()->insetAllowed(code); + in_insetAllowed = false; + return ret; } -UpdatableInset * InsetText::GetFirstLockingInsetOfType(Inset::Code c) +UpdatableInset * InsetText::getLockingInset() const { - if (c == LyxCode()) - return this; - if (the_locking_inset) - return the_locking_inset->GetFirstLockingInsetOfType(c); - return 0; + return the_locking_inset ? the_locking_inset->getLockingInset() : + const_cast(this); } -void InsetText::SetFont(BufferView * bv, LyXFont const & font, bool toggleall) +UpdatableInset * InsetText::getFirstLockingInsetOfType(Inset::Code c) { - bv->text->SetUndo(bv->buffer(), Undo::EDIT, -#ifndef NEW_INSETS - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous, - bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next -#else - bv->text->cursor.par()->previous, - bv->text->cursor.par()->next -#endif - ); - TEXT(bv)->SetFont(bv, font, toggleall); - bv->fitCursor(TEXT(bv)); - UpdateLocal(bv, CURSOR_PAR, true); + if (c == lyxCode()) + return this; + if (the_locking_inset) + return the_locking_inset->getFirstLockingInsetOfType(c); + return 0; +} + + +bool InsetText::showInsetDialog(BufferView * bv) const +{ + if (the_locking_inset) + return the_locking_inset->showInsetDialog(bv); + return false; +} + + +vector const InsetText::getLabelList() const +{ + 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) { + vector const l = (*beg)->getLabelList(); + label_list.insert(label_list.end(), l.begin(), l.end()); + } + tpar = tpar->next(); + } + return label_list; +} + + +void InsetText::setFont(BufferView * bv, LyXFont const & font, bool toggleall, + bool selectall) +{ + if (the_locking_inset) { + the_locking_inset->setFont(bv, font, toggleall, selectall); + return; + } + if ((!par->next() && !par->size()) || !cpar(bv)->size()) { + getLyXText(bv)->setFont(bv, font, toggleall); + return; + } + 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); + lt->toggleFree(bv, font, toggleall); + if (selectall) + lt->clearSelection(); + bv->fitCursor(); + bool flag = (selectall || lt->selection.set()); + if (clear) + lt = 0; + if (flag) + updateLocal(bv, FULL, true); + else + updateLocal(bv, CURSOR_PAR, true); } bool InsetText::checkAndActivateInset(BufferView * bv, bool behind) { - if (cpar(bv)->GetChar(cpos(bv)) == LyXParagraph::META_INSET) { - unsigned int x; - unsigned int y; - Inset * inset = - static_cast(cpar(bv)->GetInset(cpos(bv))); - if (!inset || inset->Editable() != Inset::HIGHLY_EDITABLE) - return false; - LyXFont const font = - TEXT(bv)->GetFont(bv->buffer(), cpar(bv), cpos(bv)); - if (behind) { - x = inset->width(bv, font); - y = font.isRightToLeft() ? 0 : inset->descent(bv, font); - } else { - x = 0; - y = font.isRightToLeft() ? inset->descent(bv, font) : 0; + if (cpar(bv)->isInset(cpos(bv))) { + unsigned int x; + unsigned int y; + Inset * inset = + static_cast(cpar(bv)->getInset(cpos(bv))); + if (!isHighlyEditableInset(inset)) + return false; + LyXFont const font = + getLyXText(bv)->getFont(bv->buffer(), cpar(bv), cpos(bv)); + if (behind) { + x = inset->width(bv, font); + y = font.isRightToLeft() ? 0 : inset->descent(bv, font); + } else { + x = 0; + y = font.isRightToLeft() ? inset->descent(bv, font) : 0; + } + //inset_x = cx(bv) - top_x + drawTextXOffset; + //inset_y = cy(bv) + drawTextYOffset; + inset->edit(bv, x, y, 0); + if (!the_locking_inset) + return false; + updateLocal(bv, CURSOR, false); + return true; } - //inset_x = cx(bv) - top_x + drawTextXOffset; - //inset_y = cy(bv) + drawTextYOffset; - inset->Edit(bv, x, y, 0); - if (!the_locking_inset) - return false; - UpdateLocal(bv, CURSOR_PAR, false); - return true; - } - return false; + return false; } bool InsetText::checkAndActivateInset(BufferView * bv, int x, int y, int button) { - x = x - drawTextXOffset; - y = y + insetAscent; - Inset * inset = bv->checkInsetHit(TEXT(bv), x, y, button); + x -= drawTextXOffset; + int dummyx = x; + int dummyy = y + insetAscent; + Inset * inset = bv->checkInsetHit(getLyXText(bv), dummyx, dummyy); - if (inset) { - if (x < 0) - x = insetWidth; - if (y < 0) - y = insetDescent; - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - inset->Edit(bv, x - inset_x, y - inset_y, button); - if (!the_locking_inset) - return false; - UpdateLocal(bv, CURSOR_PAR, false); - return true; - } - return false; + if (inset) { + if (x < 0) + x = insetWidth; + if (y < 0) + y = insetDescent; + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + inset->edit(bv, x - inset_x, y - inset_y, button); + if (!the_locking_inset) + return false; + updateLocal(bv, CURSOR, false); + return true; + } + return false; } -int InsetText::getMaxWidth(Painter & pain, UpdatableInset const * inset) const +int InsetText::getMaxWidth(BufferView * bv, UpdatableInset const * inset) const { - int w = UpdatableInset::getMaxWidth(pain, inset); - if (w < 0) { - return w; - } - if (owner()) { - w = w - top_x + owner()->x(); - return w; - } - w -= (2 * TEXT_TO_INSET_OFFSET); - return w - top_x; -// return w - (2*TEXT_TO_INSET_OFFSET); +#if 0 + int w = UpdatableInset::getMaxWidth(bv, inset); + if (w < 0) { + return -1; + } + if (owner()) { + w = w - top_x + owner()->x(); + return w; + } + w -= (2 * TEXT_TO_INSET_OFFSET); + return w - top_x; +#else + return UpdatableInset::getMaxWidth(bv, inset); +#endif } -void InsetText::SetParagraphData(LyXParagraph *p) +void InsetText::setParagraphData(Paragraph * p, bool same_id) { - // delete all instances of LyXText before deleting the paragraps used - // by it. - for (Cache::iterator cit = cache.begin(); cit != cache.end(); ++cit){ - delete (*cit).second; - (*cit).second = 0; - } + // we have to unlock any locked inset otherwise we're in troubles + the_locking_inset = 0; + while (par) { + Paragraph * tmp = par->next(); + delete par; + par = tmp; + } - LyXParagraph * np; - if (par) { - np = par->next; - delete par; - while(np) { - par = np; - np = np->next; - delete par; + par = new Paragraph(*p, same_id); + par->setInsetOwner(this); + Paragraph * np = par; + while (p->next()) { + p = p->next(); + np->next(new Paragraph(*p, same_id)); + np->next()->previous(np); + np = np->next(); + np->setInsetOwner(this); } - } - par = p->Clone(); - par->SetInsetOwner(this); - np = par; - while(p->next) { - p = p->next; - np->next = p->Clone(); - np->next->previous = np; - np = np->next; - np->SetInsetOwner(this); - } - need_update = INIT; + reinitLyXText(); + need_update = INIT; } -void InsetText::SetText(string const & data) +void InsetText::setText(string const & data) { - clear(); - LyXFont font(LyXFont::ALL_SANE); - for(unsigned int i=0; i < data.length(); ++i) - par->InsertChar(i, data[i], font); + clear(); + LyXFont font(LyXFont::ALL_SANE); + for (unsigned int i=0; i < data.length(); ++i) + par->insertChar(i, data[i], font); } -void InsetText::SetAutoBreakRows(bool flag) +void InsetText::setAutoBreakRows(bool flag) { - if (flag != autoBreakRows) { - autoBreakRows = flag; - need_update = FULL; - if (!flag) - removeNewlines(); - } + if (flag != autoBreakRows) { + autoBreakRows = flag; + if (!flag) + removeNewlines(); + need_update = INIT; + } } -void InsetText::SetDrawFrame(BufferView * bv, DrawFrame how) +void InsetText::setDrawFrame(BufferView * bv, DrawFrame how) { - if (how != drawFrame) { - drawFrame = how; - if (bv) - UpdateLocal(bv, DRAW_FRAME, false); - } + if (how != drawFrame_) { + drawFrame_ = how; + if (bv) + updateLocal(bv, DRAW_FRAME, false); + } } -void InsetText::SetFrameColor(BufferView * bv, LColor::color col) -{ - if (frame_color != col) { - frame_color = col; - if (bv) - UpdateLocal(bv, DRAW_FRAME, false); - } -} - -#if 0 -LyXFont InsetText::GetDrawFont(BufferView * bv, LyXParagraph * p, int pos) const +void InsetText::setFrameColor(BufferView * bv, LColor::color col) { - return TEXT(bv)->GetFont(bv->buffer(), p, pos); + if (frame_color != col) { + frame_color = col; + if (bv) + updateLocal(bv, DRAW_FRAME, false); + } } -#endif int InsetText::cx(BufferView * bv) const { - LyXText * text = TEXT(bv); - int x = text->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 = text->GetFont(bv->buffer(), - text->cursor.par(), text->cursor.pos()); + LyXFont font = llt->getFont(bv->buffer(), llt->cursor.par(), + llt->cursor.pos()); if (font.isVisibleRightToLeft()) x -= the_locking_inset->width(bv, font); } @@ -1532,144 +2094,546 @@ int InsetText::cx(BufferView * bv) const int InsetText::cy(BufferView * bv) const { - LyXFont font; - return TEXT(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET; + LyXFont font; + return getLyXText(bv)->cursor.y() - ascent(bv, font) + TEXT_TO_INSET_OFFSET; } -LyXParagraph::size_type InsetText::cpos(BufferView * bv) const +pos_type InsetText::cpos(BufferView * bv) const { - return TEXT(bv)->cursor.pos(); + return getLyXText(bv)->cursor.pos(); } -LyXParagraph * InsetText::cpar(BufferView * bv) const +Paragraph * InsetText::cpar(BufferView * bv) const { - return TEXT(bv)->cursor.par(); + return getLyXText(bv)->cursor.par(); } + bool InsetText::cboundary(BufferView * bv) const { - return TEXT(bv)->cursor.boundary(); + return getLyXText(bv)->cursor.boundary(); } Row * InsetText::crow(BufferView * bv) const { - return TEXT(bv)->cursor.row(); + return getLyXText(bv)->cursor.row(); } -LyXText * InsetText::getLyXText(BufferView const * lbv) const +LyXText * InsetText::getLyXText(BufferView const * lbv, + bool const recursive) const { - // Super UGLY! (Lgb) - BufferView * bv = const_cast(lbv); + if (!recursive && (cached_bview == lbv)) { + LyXText * lt = cached_text.get(); + lyx::Assert(lt && lt->firstRow()->par() == par); + return lt; + } + + // Super UGLY! (Lgb) + BufferView * bv = const_cast(lbv); - if ((cache.find(bv) != cache.end()) && cache[bv]) - return cache[bv]; - LyXText * lt = new LyXText(const_cast(this)); - lt->init(bv); - cache[bv] = lt; - if (the_locking_inset) { - lt->SetCursor(bv, inset_par, inset_pos, true, inset_boundary); - } - return lt; + cached_bview = bv; + Cache::iterator it = cache.find(bv); + + if (it != cache.end()) { + if (do_reinit) { + reinitLyXText(); + } else if (do_resize) { + resizeLyXText(do_resize); + } 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); + } + return cached_text.get(); } void InsetText::deleteLyXText(BufferView * bv, bool recursive) const { - if ((cache.find(bv) == cache.end()) || !cache[bv]) - return; - delete cache[bv]; - cache.erase(bv); - if (recursive) { - /// then remove all LyXText in text-insets - LyXParagraph * p = par; - for (;p;p = p->next) { - p->deleteInsetsLyXText(bv); - } - } -} - - -void InsetText::resizeLyXText(BufferView * bv) const -{ - if (!par->next && !par->size()) // resize not neccessary! - return; - if ((cache.find(bv) == cache.end()) || !cache[bv]) - return; - - LyXParagraph * lpar = 0; - LyXParagraph * selstartpar = 0; - LyXParagraph * selendpar = 0; - LyXParagraph::size_type pos = 0; - LyXParagraph::size_type selstartpos = 0; - LyXParagraph::size_type selendpos = 0; - bool boundary = false; - bool selstartboundary = false; - bool selendboundary = false; - int selection = 0; - int mark_set = 0; - -// ProhibitInput(bv); - - if (locked) { - lpar = TEXT(bv)->cursor.par(); - pos = TEXT(bv)->cursor.pos(); - boundary = TEXT(bv)->cursor.boundary(); - selstartpar = TEXT(bv)->sel_start_cursor.par(); - selstartpos = TEXT(bv)->sel_start_cursor.pos(); - selstartboundary = TEXT(bv)->sel_start_cursor.boundary(); - selendpar = TEXT(bv)->sel_end_cursor.par(); - selendpos = TEXT(bv)->sel_end_cursor.pos(); - selendboundary = TEXT(bv)->sel_end_cursor.boundary(); - selection = TEXT(bv)->selection; - mark_set = TEXT(bv)->mark_set; - } - deleteLyXText(bv, (the_locking_inset == 0)); - - if (lpar) { - TEXT(bv)->selection = true; - /* at this point just to avoid the Delete-Empty-Paragraph - * Mechanism when setting the cursor */ - TEXT(bv)->mark_set = mark_set; - if (selection) { - TEXT(bv)->SetCursor(bv, selstartpar, selstartpos,true, - selstartboundary); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - TEXT(bv)->SetCursor(bv, selendpar, selendpos, true, selendboundary); - TEXT(bv)->SetSelection(); - TEXT(bv)->SetCursor(bv, lpar, pos); + cached_bview = 0; + + Cache::iterator it = cache.find(bv); + + if (it == cache.end()) { + return; + } + + lyx::Assert(it->second.text.get()); + + it->second.remove = true; + if (recursive) { + /// then remove all LyXText in text-insets + Paragraph * p = par; + for (; p; p = p->next()) { + p->deleteInsetsLyXText(bv); + } + } +} + + +void InsetText::resizeLyXText(BufferView * bv, bool force) const +{ + if (lt) { + // we cannot resize this because we are in use! + // so do this on the next possible getLyXText() + do_resize = bv; + return; + } + do_resize = 0; +// lyxerr << "InsetText::resizeLyXText\n"; + 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; + + Cache::iterator it = cache.find(bv); + if (it == cache.end()) { + return; + } + lyx::Assert(it->second.text.get()); + + LyXText * t = it->second.text.get(); + saveLyXTextState(t); + for (Paragraph * p = par; p; p = p->next()) { + p->resizeInsetsLyXText(bv); + } + t->init(bv, true); + restoreLyXTextState(bv, t); + if (the_locking_inset) { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + } + + if (bv->screen()) { + t->first = bv->screen()->topCursorVisible(t); + } + if (!owner()) { + updateLocal(bv, FULL, false); + // this will scroll the screen such that the cursor becomes visible + bv->updateScrollbar(); } else { - TEXT(bv)->SetCursor(bv, lpar, pos, true, boundary); - TEXT(bv)->sel_cursor = TEXT(bv)->cursor; - TEXT(bv)->selection = false; - } - } - if (bv->screen()) - TEXT(bv)->first = bv->screen()->TopCursorVisible(TEXT(bv)); - // this will scroll the screen such that the cursor becomes visible - bv->updateScrollbar(); -// AllowInput(bv); - if (the_locking_inset) { - /// then resize all LyXText in text-insets - inset_x = cx(bv) - top_x + drawTextXOffset; - inset_y = cy(bv) + drawTextYOffset; - for (LyXParagraph * p = par; p; p = p->next) { - p->resizeInsetsLyXText(bv); + need_update |= FULL; + } +} + + +void InsetText::reinitLyXText() const +{ + if (lt) { + // we cannot resize this because we are in use! + // so do this on the next possible getLyXText() + do_reinit = true; + return; + } + do_reinit = false; + do_resize = 0; +// lyxerr << "InsetText::reinitLyXText\n"; + for(Cache::iterator it = cache.begin(); it != cache.end(); ++it) { + lyx::Assert(it->second.text.get()); + + LyXText * t = it->second.text.get(); + BufferView * bv = it->first; + + saveLyXTextState(t); + for (Paragraph * p = par; p; p = p->next()) { + p->resizeInsetsLyXText(bv); + } + t->init(bv, true); + restoreLyXTextState(bv, t); + if (the_locking_inset) { + inset_x = cx(bv) - top_x + drawTextXOffset; + inset_y = cy(bv) + drawTextYOffset; + } + if (bv->screen()) { + t->first = bv->screen()->topCursorVisible(t); + } + if (!owner()) { + updateLocal(bv, FULL, false); + // this will scroll the screen such that the cursor becomes visible + bv->updateScrollbar(); + } else { + need_update = FULL; + } } - } - need_update = FULL; } void InsetText::removeNewlines() { - for (LyXParagraph * p = par; p; p = p->next) { - for (int i = 0; i < p->Last(); ++i) { - if (p->GetChar(i) == LyXParagraph::META_NEWLINE) - p->Erase(i); + 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) { + changed = true; + p->erase(i); + } + } } - } + if (changed) + reinitLyXText(); +} + + +bool InsetText::nodraw() const +{ + if (the_locking_inset) + return the_locking_inset->nodraw(); + return UpdatableInset::nodraw(); +} + + +int InsetText::scroll(bool recursive) const +{ + int sx = UpdatableInset::scroll(false); + + if (recursive && the_locking_inset) + sx += the_locking_inset->scroll(recursive); + + return sx; +} + + +bool InsetText::doClearArea() const +{ + return !locked || (need_update & (FULL|INIT)); +} + + +void InsetText::selectAll(BufferView * bv) +{ + getLyXText(bv)->cursorTop(bv); + getLyXText(bv)->selection.cursor = getLyXText(bv)->cursor; + getLyXText(bv)->cursorBottom(bv); + getLyXText(bv)->setSelection(bv); +} + + +void InsetText::clearSelection(BufferView * bv) +{ + getLyXText(bv)->clearSelection(); +} + + +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; + } + if ((ty + h) > pain.paperHeight()) + h = pain.paperHeight(); + if ((top_x + drawTextXOffset + w) > pain.paperWidth()) + w = pain.paperWidth(); +// w -= TEXT_TO_INSET_OFFSET; + pain.fillRectangle(top_x, ty, w+1, h+1, backgroundColor()); + cleared = true; + need_update = FULL; + frame_is_visible = false; +} + + +Paragraph * InsetText::getParFromID(int id) const +{ +#if 0 + Paragraph * result = par; + Paragraph * ires = 0; + while (result && result->id() != id) { + if ((ires = result->getParFromID(id))) + return ires; + result = result->next(); + } + return result; +#else + Paragraph * tmp = par; + while (tmp) { + if (tmp->id() == id) { + return tmp; + } + Paragraph * tmp2 = tmp->getParFromID(id); + if (tmp2 != 0) { + return tmp2; + } + tmp = tmp->next(); + } + return 0; +#endif +} + + +Paragraph * InsetText::firstParagraph() const +{ + Paragraph * result; + if (the_locking_inset) + if ((result = the_locking_inset->firstParagraph())) + return result; + return par; +} + + +Paragraph * InsetText::getFirstParagraph(int i) const +{ + return (i == 0) ? par : 0; +} + + +LyXCursor const & InsetText::cursor(BufferView * bv) const +{ + if (the_locking_inset) + return the_locking_inset->cursor(bv); + return getLyXText(bv)->cursor; +} + + +Paragraph * InsetText::paragraph() const +{ + return par; +} + + +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; + // set ourself as owner for all the paragraphs inserted! + Paragraph * np = par; + while (np) { + np->setInsetOwner(this); + np = np->next(); + } + reinitLyXText(); + // redraw myself when asked for + need_update = INIT; +} + + +Inset * InsetText::getInsetFromID(int id_arg) const +{ + if (id_arg == id()) + return const_cast(this); + + Paragraph * lp = par; + + while (lp) { + for (Paragraph::inset_iterator it = lp->inset_iterator_begin(), + en = lp->inset_iterator_end(); + it != en; ++it) + { + if ((*it)->id() == id_arg) + return *it; + Inset * in = (*it)->getInsetFromID(id_arg); + if (in) + return in; + } + lp = lp->next(); + } + return 0; +} + + +string const InsetText::selectNextWordToSpellcheck(BufferView * bv, float & value) const +{ + bool clear = false; + string str; + + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + if (the_locking_inset) { + str = the_locking_inset->selectNextWordToSpellcheck(bv, value); + if (!str.empty()) { + value += cy(bv); + if (clear) + lt = 0; + return str; + } + // we have to go on checking so move cusor to the next char + lt->cursor.pos(lt->cursor.pos() + 1); + } + str = lt->selectNextWordToSpellcheck(bv, value); + if (str.empty()) + bv->unlockInset(const_cast(this)); + else + value = cy(bv); + if (clear) + lt = 0; + return str; +} + + +void InsetText::selectSelectedWord(BufferView * bv) +{ + if (the_locking_inset) { + the_locking_inset->selectSelectedWord(bv); + return; + } + getLyXText(bv)->selectSelectedWord(bv); + updateLocal(bv, SELECTION, false); +} + + +void InsetText::toggleSelection(BufferView * bv, bool kill_selection) +{ + if (the_locking_inset) { + the_locking_inset->toggleSelection(bv, kill_selection); + } + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + + int x = top_x + TEXT_TO_INSET_OFFSET; + + Row * row = lt->firstRow(); + int y_offset = top_baseline - row->ascent_of_text(); + 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); + if (clear) + lt = 0; +} + + +bool InsetText::searchForward(BufferView * bv, string const & str, + bool cs, bool mw) +{ + if (the_locking_inset) { + if (the_locking_inset->searchForward(bv, str, cs, mw)) + return true; + bool clear = false; + if (!lt) { + lt = getLyXText(bv); + clear = true; + } + Paragraph * lpar = lt->cursor.par(); + pos_type pos = lt->cursor.pos(); + if (pos < lpar->size() - 1) + ++pos; + else { + pos = 0; + lpar = lpar->next(); + } + if (!lpar) { + if (clear) + lt = 0; + // we have to unlock ourself in this function by default! + bv->unlockInset(const_cast(this)); + return false; + } + lt->setCursor(bv, lpar, pos); + if (clear) + lt = 0; + } + if (LyXFind(bv, str, true, true, cs , mw)) { + return true; + } + // we have to unlock ourself in this function by default! + bv->unlockInset(const_cast(this)); + return false; +} + +bool InsetText::searchBackward(BufferView * bv, string const & str, + bool cs, bool mw) +{ + if (the_locking_inset) + if (the_locking_inset->searchBackward(bv, str, cs, mw)) + return true; + if (LyXFind(bv, str, false, true, cs, mw)) { + return true; + } + // we have to unlock ourself in this function by default! + 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->isSeparator(par->size()-1)) + par->insertChar(par->size()-1, ' '); + par->pasteParagraph(bparams); + } + reinitLyXText(); +} + + +void InsetText::getDrawFont(LyXFont & font) const +{ + if (!owner()) + return; + owner()->getDrawFont(font); }