X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetText.cpp;h=0e8f3ad5715f8bc42f3d32a99f235e91740b4e46;hb=2c357c1d23b7b83839a9beb8225d4f1ae4f793b4;hp=4aa3088c389f480aec8d910faa4bf7e6f0a761ca;hpb=42123ab8a71080b6d15fca4e0c43ae76abf00a1e;p=lyx.git diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 4aa3088c38..0e8f3ad571 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -14,22 +14,21 @@ #include "InsetNewline.h" #include "Buffer.h" +#include "buffer_funcs.h" #include "BufferParams.h" #include "BufferView.h" #include "CoordCache.h" #include "CutAndPaste.h" #include "Cursor.h" -#include "debug.h" #include "DispatchResult.h" #include "ErrorList.h" #include "FuncRequest.h" -#include "gettext.h" +#include "InsetList.h" #include "Intl.h" -#include "LColor.h" #include "lyxfind.h" #include "Lexer.h" #include "LyXRC.h" -#include "LyXText.h" +#include "Text.h" #include "MetricsInfo.h" #include "OutputParams.h" #include "output_docbook.h" @@ -38,68 +37,85 @@ #include "Paragraph.h" #include "paragraph_funcs.h" #include "ParagraphParameters.h" -#include "rowpainter.h" +#include "ParIterator.h" #include "Row.h" #include "sgml.h" +#include "TextClass.h" +#include "TextMetrics.h" #include "TexRow.h" -#include "Undo.h" -#include "frontends/Alert.h" +#include "frontends/alert.h" #include "frontends/Painter.h" -#include "support/lyxalgo.h" // count +#include "support/debug.h" +#include "support/gettext.h" +#include "support/lstrings.h" #include -#include +#include -#include +using namespace std; +using namespace lyx::support; +using boost::bind; +using boost::ref; namespace lyx { using graphics::PreviewLoader; -using support::isStrUnsignedInt; -using boost::bind; -using boost::ref; +class TextCompletionList : public Inset::CompletionList { +public: + /// + TextCompletionList(Cursor const & cur) + : buf_(cur.buffer()), it_(buf_.registeredWords().begin()), pos_(0) {} + /// + virtual ~TextCompletionList() {} -using std::endl; -using std::for_each; -using std::max; -using std::string; -using std::auto_ptr; -using std::ostream; -using std::vector; + /// + virtual size_t size() const { + return buf_.registeredWords().size(); + } + /// + virtual docstring data(size_t idx) const { + std::set::const_iterator it + = buf_.registeredWords().begin(); + for (size_t i = 0; i < idx; ++i) + it++; + return *it; + } +private: + Buffer const & buf_; + std::set::const_iterator const it_; + size_t pos_; +}; -int InsetText::border_ = 2; +///////////////////////////////////////////////////////////////////// InsetText::InsetText(BufferParams const & bp) - : drawFrame_(false), frame_color_(LColor::insetframe) + : drawFrame_(false), frame_color_(Color_insetframe) { paragraphs().push_back(Paragraph()); - paragraphs().back().layout(bp.getLyXTextClass().defaultLayout()); - // Dispose of the infamous L-shaped cursor. - text_.current_font.setLanguage(bp.language); - text_.real_current_font.setLanguage(bp.language); - init(); + Paragraph & ourpar = paragraphs().back(); + if (useEmptyLayout()) + ourpar.layout(bp.getTextClass().emptyLayout()); + else + ourpar.layout(bp.getTextClass().defaultLayout()); + ourpar.setInsetOwner(this); } InsetText::InsetText(InsetText const & in) - : InsetOld(in), text_() + : Inset(in), text_() { text_.autoBreakRows_ = in.text_.autoBreakRows_; drawFrame_ = in.drawFrame_; frame_color_ = in.frame_color_; text_.paragraphs() = in.text_.paragraphs(); - // Hand current buffer language down to "cloned" textinsets - // e.g. tabular cells - text_.current_font = in.text_.current_font; - text_.real_current_font = in.text_.real_current_font; - init(); + setParagraphOwner(); } @@ -107,7 +123,7 @@ InsetText::InsetText() {} -void InsetText::init() +void InsetText::setParagraphOwner() { for_each(paragraphs().begin(), paragraphs().end(), bind(&Paragraph::setInsetOwner, _1, this)); @@ -119,7 +135,7 @@ void InsetText::clear() ParagraphList & pars = paragraphs(); // This is a gross hack... - LyXLayout_ptr old_layout = pars.begin()->layout(); + LayoutPtr old_layout = pars.begin()->layout(); pars.clear(); pars.push_back(Paragraph()); @@ -128,9 +144,20 @@ void InsetText::clear() } -auto_ptr InsetText::doClone() const +Inset * InsetText::clone() const +{ + return new InsetText(*this); +} + + +Dimension const InsetText::dimension(BufferView const & bv) const { - return auto_ptr(new InsetText(*this)); + TextMetrics const & tm = bv.textMetrics(&text_); + Dimension dim = tm.dimension(); + dim.wid += 2 * TEXT_TO_INSET_OFFSET; + dim.des += TEXT_TO_INSET_OFFSET; + dim.asc += TEXT_TO_INSET_OFFSET; + return dim; } @@ -149,8 +176,7 @@ void InsetText::read(Buffer const & buf, Lexer & lex) Paragraph oldpar = *paragraphs().begin(); paragraphs().clear(); ErrorList errorList; - bool res = text_.read(buf, lex, errorList); - init(); + bool res = text_.read(buf, lex, errorList, this); if (!res) { lex.printError("Missing \\end_inset at this point. " @@ -164,70 +190,41 @@ void InsetText::read(Buffer const & buf, Lexer & lex) } -bool InsetText::metrics(MetricsInfo & mi, Dimension & dim) const +void InsetText::metrics(MetricsInfo & mi, Dimension & dim) const { TextMetrics & tm = mi.base.bv->textMetrics(&text_); //lyxerr << "InsetText::metrics: width: " << mi.base.textwidth << endl; - mi.base.textwidth -= 2 * border_; - font_ = mi.base.font; + // Hand font through to contained lyxtext: - text_.font_ = mi.base.font; - tm.metrics(mi, dim); - dim.asc += border_; - dim.des += border_; - dim.wid += 2 * border_; - mi.base.textwidth += 2 * border_; - bool const changed = dim_ != dim; - dim_ = dim; - return changed; + tm.font_.fontInfo() = mi.base.font; + mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET; + if (hasFixedWidth()) + tm.metrics(mi, dim, mi.base.textwidth); + else + tm.metrics(mi, dim); + mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET; + dim.asc += TEXT_TO_INSET_OFFSET; + dim.des += TEXT_TO_INSET_OFFSET; + dim.wid += 2 * TEXT_TO_INSET_OFFSET; } void InsetText::draw(PainterInfo & pi, int x, int y) const { - // update our idea of where we are - setPosCache(pi, x, y); - TextMetrics & tm = pi.base.bv->textMetrics(&text_); - text_.background_color_ = backgroundColor(); - text_.draw(pi, x + border_, y); - - if (drawFrame_) { - int const w = tm.width() + 2 * border_; - int const a = tm.ascent() + border_; - int const h = a + tm.descent() + border_; - pi.pain.rectangle(x, y - a, - ((wide() || hasFixedWidth()) ? tm.maxWidth() : w), - h, frameColor()); + if (drawFrame_ || pi.full_repaint) { + int const w = tm.width() + TEXT_TO_INSET_OFFSET; + int const yframe = y - TEXT_TO_INSET_OFFSET - tm.ascent(); + int const h = tm.height() + 2 * TEXT_TO_INSET_OFFSET; + int const xframe = x + TEXT_TO_INSET_OFFSET / 2; + if (pi.full_repaint) + pi.pain.fillRectangle(xframe, yframe, w, h, backgroundColor()); + if (drawFrame_) + pi.pain.rectangle(xframe, yframe, w, h, frameColor()); } -} - - -void InsetText::drawSelection(PainterInfo & pi, int x, int y) const -{ - TextMetrics & tm = pi.base.bv->textMetrics(&text_); - - int const w = tm.width() + 2 * border_; - int const a = tm.ascent() + border_; - int const h = a + tm.descent() + border_; - pi.pain.fillRectangle(x, y - a, - ((wide() || hasFixedWidth()) ? tm.maxWidth() : w), - h, backgroundColor()); - text_.drawSelection(pi, x + border_, y); -} - - -bool InsetText::covers(BufferView const & bv, int x, int y) const -{ - TextMetrics const & tm = bv.textMetrics(&text_); - - return bv.coordCache().getInsets().has(this) - && x >= xo(bv) - && x <= xo(bv) + width() + (wide() ? tm.maxWidth() : 0) - && y >= yo(bv) - ascent() - && y <= yo(bv) + descent(); + tm.draw(pi, x + TEXT_TO_INSET_OFFSET, y); } @@ -237,28 +234,36 @@ docstring const InsetText::editMessage() const } -void InsetText::edit(Cursor & cur, bool left) +void InsetText::edit(Cursor & cur, bool front, EntryDirection entry_from) { - //lyxerr << "InsetText: edit left/right" << endl; - int const pit = left ? 0 : paragraphs().size() - 1; - int const pos = left ? 0 : paragraphs().back().size(); + pit_type const pit = front ? 0 : paragraphs().size() - 1; + pos_type pos = front ? 0 : paragraphs().back().size(); + + // if visual information is not to be ignored, move to extreme right/left + if (entry_from != ENTRY_DIRECTION_IGNORE) { + Cursor temp_cur = cur; + temp_cur.pit() = pit; + temp_cur.pos() = pos; + temp_cur.posVisToRowExtremity(entry_from == ENTRY_DIRECTION_LEFT); + pos = temp_cur.pos(); + } + text_.setCursor(cur.top(), pit, pos); cur.clearSelection(); - finishUndo(); + cur.finishUndo(); } -InsetBase * InsetText::editXY(Cursor & cur, int x, int y) +Inset * InsetText::editXY(Cursor & cur, int x, int y) { - return text_.editXY(cur, x, y); + return cur.bv().textMetrics(&text_).editXY(cur, x, y); } void InsetText::doDispatch(Cursor & cur, FuncRequest & cmd) { - LYXERR(Debug::ACTION) << BOOST_CURRENT_FUNCTION - << " [ cmd.action = " - << cmd.action << ']' << endl; + LYXERR(Debug::ACTION, "InsetText::doDispatch()" + << " [ cmd.action = " << cmd.action << ']'); text_.dispatch(cur, cmd); } @@ -293,16 +298,16 @@ void InsetText::rejectChanges(BufferParams const & bparams) int InsetText::latex(Buffer const & buf, odocstream & os, - OutputParams const & runparams) const + OutputParams const & runparams) const { TexRow texrow; - latexParagraphs(buf, paragraphs(), os, texrow, runparams); + latexParagraphs(buf, text_, os, texrow, runparams); return texrow.rows(); } int InsetText::plaintext(Buffer const & buf, odocstream & os, - OutputParams const & runparams) const + OutputParams const & runparams) const { ParagraphList::const_iterator beg = paragraphs().begin(); ParagraphList::const_iterator end = paragraphs().end(); @@ -329,7 +334,7 @@ int InsetText::plaintext(Buffer const & buf, odocstream & os, int InsetText::docbook(Buffer const & buf, odocstream & os, - OutputParams const & runparams) const + OutputParams const & runparams) const { docbookParagraphs(paragraphs(), buf, os, runparams); return 0; @@ -346,8 +351,8 @@ void InsetText::validate(LaTeXFeatures & features) const void InsetText::cursorPos(BufferView const & bv, CursorSlice const & sl, bool boundary, int & x, int & y) const { - x = text_.cursorX(bv, sl, boundary) + border_; - y = text_.cursorY(bv, sl, boundary); + x = bv.textMetrics(&text_).cursorX(sl, boundary) + TEXT_TO_INSET_OFFSET; + y = bv.textMetrics(&text_).cursorY(sl, boundary); } @@ -357,7 +362,7 @@ bool InsetText::showInsetDialog(BufferView *) const } -void InsetText::setText(docstring const & data, LyXFont const & font, bool trackChanges) +void InsetText::setText(docstring const & data, Font const & font, bool trackChanges) { clear(); Paragraph & first = paragraphs().front(); @@ -393,13 +398,13 @@ void InsetText::setDrawFrame(bool flag) } -LColor_color InsetText::frameColor() const +ColorCode InsetText::frameColor() const { - return LColor::color(frame_color_); + return frame_color_; } -void InsetText::setFrameColor(LColor_color col) +void InsetText::setFrameColor(ColorCode col) { frame_color_ = col; } @@ -418,10 +423,10 @@ void InsetText::appendParagraphs(Buffer * buffer, ParagraphList & plist) ParagraphList::iterator ins = pl.insert(pl.end(), *pit); ++pit; mergeParagraph(buffer->params(), pl, - std::distance(pl.begin(), ins) - 1); + distance(pl.begin(), ins) - 1); for_each(pit, plist.end(), - bind(&ParagraphList::push_back, ref(pl), _1)); + bind(&ParagraphList::push_back, ref(pl), _1)); } @@ -431,8 +436,8 @@ void InsetText::addPreview(PreviewLoader & loader) const ParagraphList::const_iterator pend = paragraphs().end(); for (; pit != pend; ++pit) { - InsetList::const_iterator it = pit->insetlist.begin(); - InsetList::const_iterator end = pit->insetlist.end(); + InsetList::const_iterator it = pit->insetList().begin(); + InsetList::const_iterator end = pit->insetList().end(); for (; it != end; ++it) it->inset->addPreview(loader); } @@ -460,4 +465,109 @@ ParagraphList & InsetText::paragraphs() } +void InsetText::updateLabels(Buffer const & buf, ParIterator const & it) +{ + ParIterator it2 = it; + it2.forwardPos(); + BOOST_ASSERT(&it2.inset() == this && it2.pit() == 0); + lyx::updateLabels(buf, it2); +} + + +bool InsetText::completionSupported(Cursor const & cur) const +{ + Cursor const & bvCur = cur.bv().cursor(); + if (&bvCur.inset() != this) + return false; + Paragraph const & par = cur.paragraph(); + return cur.pos() > 0 + && (cur.pos() >= par.size() || !par.isLetter(cur.pos())) + && par.isLetter(cur.pos() - 1); +} + + +bool InsetText::inlineCompletionSupported(Cursor const & cur) const +{ + return completionSupported(cur); +} + + +bool InsetText::automaticInlineCompletion() const +{ + return lyxrc.completion_inline_text; +} + + +bool InsetText::automaticPopupCompletion() const +{ + return lyxrc.completion_popup_text; +} + + +Inset::CompletionList const * InsetText::completionList(Cursor const & cur) const +{ + if (!completionSupported(cur)) + return 0; + + return new TextCompletionList(cur); +} + + +docstring InsetText::previousWord(Buffer const & buffer, CursorSlice const & sl) const +{ + CursorSlice from = sl; + CursorSlice to = sl; + text_.getWord(from, to, PREVIOUS_WORD); + if (sl == from || to == from) + return docstring(); + + Paragraph const & par = sl.paragraph(); + return par.asString(buffer, from.pos(), to.pos(), false); +} + + +docstring InsetText::completionPrefix(Cursor const & cur) const +{ + if (!completionSupported(cur)) + return docstring(); + + return previousWord(cur.buffer(), cur.top()); +} + + +bool InsetText::insertCompletion(Cursor & cur, docstring const & s, + bool finished) +{ + if (!completionSupported(cur)) + return false; + + BOOST_ASSERT(cur.bv().cursor() == cur); + cur.insert(s); + cur.bv().cursor() = cur; + return true; +} + + +void InsetText::completionPosAndDim(Cursor const & cur, int & x, int & y, + Dimension & dim) const +{ + // get word in front of cursor + docstring word = previousWord(cur.buffer(), cur.top()); + DocIterator wordStart = cur; + wordStart.pos() -= word.length(); + + // get position on screen of the word start + Point lxy = cur.bv().getPos(wordStart, false); + x = lxy.x_; + y = lxy.y_; + + // Calculate dimensions of the word + TextMetrics const & tm = cur.bv().textMetrics(&text_); + dim = tm.rowHeight(cur.pit(), wordStart.pos(), cur.pos(), false); + Point rxy = cur.bv().getPos(cur, cur.boundary()); + dim.wid = abs(rxy.x_ - x); + x = (rxy.x_ < x) ? x - dim.wid : x; // for RTL +} + + } // namespace lyx