* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
- * \author Jürgen Vigna
+ * \author Jürgen Vigna
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetText.h"
-#include "InsetNewline.h"
-#include "Buffer.h"
+#include "insets/InsetOptArg.h"
+
#include "buffer_funcs.h"
+#include "Buffer.h"
#include "BufferParams.h"
#include "BufferView.h"
+#include "CompletionList.h"
#include "CoordCache.h"
-#include "CutAndPaste.h"
#include "Cursor.h"
+#include "CutAndPaste.h"
#include "DispatchResult.h"
#include "ErrorList.h"
#include "FuncRequest.h"
+#include "FuncStatus.h"
+#include "InsetCaption.h"
#include "InsetList.h"
#include "Intl.h"
-#include "lyxfind.h"
+#include "Language.h"
+#include "LaTeXFeatures.h"
#include "Lexer.h"
+#include "lyxfind.h"
#include "LyXRC.h"
-#include "Text.h"
#include "MetricsInfo.h"
-#include "OutputParams.h"
#include "output_docbook.h"
#include "output_latex.h"
+#include "output_xhtml.h"
+#include "OutputParams.h"
#include "output_plaintext.h"
#include "Paragraph.h"
-#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
#include "Row.h"
#include "sgml.h"
+#include "TexRow.h"
#include "TextClass.h"
+#include "Text.h"
#include "TextMetrics.h"
-#include "TexRow.h"
+#include "TocBackend.h"
#include "frontends/alert.h"
#include "frontends/Painter.h"
#include "support/lstrings.h"
#include <boost/bind.hpp>
-#include <boost/assert.hpp>
+#include "support/lassert.h"
using namespace std;
using namespace lyx::support;
using graphics::PreviewLoader;
-class TextCompletionList : public Inset::CompletionList {
-public:
- ///
- TextCompletionList(Cursor const & cur)
- : buf_(cur.buffer()), it_(buf_.registeredWords().begin()), pos_(0) {}
- ///
- virtual ~TextCompletionList() {}
-
- ///
- virtual size_t size() const {
- return buf_.registeredWords().size();
- }
- ///
- virtual docstring data(size_t idx) const {
- std::set<docstring>::const_iterator it
- = buf_.registeredWords().begin();
- for (size_t i = 0; i < idx; ++i)
- it++;
- return *it;
- }
-
-private:
- Buffer const & buf_;
- std::set<docstring>::const_iterator const it_;
- size_t pos_;
-};
-
-
/////////////////////////////////////////////////////////////////////
-InsetText::InsetText(BufferParams const & bp)
- : drawFrame_(false), frame_color_(Color_insetframe)
+InsetText::InsetText(Buffer * buf, UsePlain type)
+ : Inset(buf), drawFrame_(false), frame_color_(Color_insetframe),
+ text_(this, type == DefaultLayout)
{
- paragraphs().push_back(Paragraph());
- Paragraph & ourpar = paragraphs().back();
- ourpar.setEmptyOrDefaultLayout(bp.textClass());
- ourpar.setInsetOwner(this);
}
InsetText::InsetText(InsetText const & in)
- : Inset(in), text_()
+ : Inset(in), text_(this, in.text_)
{
- text_.autoBreakRows_ = in.text_.autoBreakRows_;
drawFrame_ = in.drawFrame_;
frame_color_ = in.frame_color_;
- text_.paragraphs() = in.text_.paragraphs();
- setParagraphOwner();
}
-InsetText::InsetText()
-{}
-
-
-void InsetText::setParagraphOwner()
+void InsetText::setBuffer(Buffer & buf)
{
- for_each(paragraphs().begin(), paragraphs().end(),
- bind(&Paragraph::setInsetOwner, _1, this));
+ ParagraphList::iterator end = paragraphs().end();
+ for (ParagraphList::iterator it = paragraphs().begin(); it != end; ++it)
+ it->setBuffer(buf);
+ Inset::setBuffer(buf);
}
void InsetText::clear()
{
ParagraphList & pars = paragraphs();
+ LASSERT(!pars.empty(), /**/);
// This is a gross hack...
- LayoutPtr old_layout = pars.begin()->layout();
+ Layout const & old_layout = pars.begin()->layout();
pars.clear();
pars.push_back(Paragraph());
}
-Inset * InsetText::clone() const
-{
- return new InsetText(*this);
-}
-
-
Dimension const InsetText::dimension(BufferView const & bv) const
{
TextMetrics const & tm = bv.textMetrics(&text_);
}
-void InsetText::write(Buffer const & buf, ostream & os) const
+void InsetText::write(ostream & os) const
{
os << "Text\n";
- text_.write(buf, os);
+ text_.write(os);
}
-void InsetText::read(Buffer const & buf, Lexer & lex)
+void InsetText::read(Lexer & lex)
{
clear();
Paragraph oldpar = *paragraphs().begin();
paragraphs().clear();
ErrorList errorList;
- bool res = text_.read(buf, lex, errorList, this);
+ lex.setContext("InsetText::read");
+ bool res = text_.read(lex, errorList, this);
- if (!res) {
- lex.printError("Missing \\end_inset at this point. "
- "Read: `$$Token'");
- }
+ if (!res)
+ lex.printError("Missing \\end_inset at this point. ");
// sanity check
// ensure we have at least one paragraph.
if (paragraphs().empty())
paragraphs().push_back(oldpar);
+ // Force default font, if so requested
+ // This avoids paragraphs in buffer language that would have a
+ // foreign language after a document language change, and it ensures
+ // that all new text in ERT and similar gets the "latex" language,
+ // since new text inherits the language from the last position of the
+ // existing text. As a side effect this makes us also robust against
+ // bugs in LyX that might lead to font changes in ERT in .lyx files.
+ fixParagraphsFont();
}
// Hand font through to contained lyxtext:
tm.font_.fontInfo() = mi.base.font;
mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET;
+
+ // This can happen when a layout has a left and right margin,
+ // and the view is made very narrow. We can't do better than
+ // to draw it partly out of view (bug 5890).
+ if (mi.base.textwidth < 1)
+ mi.base.textwidth = 1;
+
if (hasFixedWidth())
tm.metrics(mi, dim, mi.base.textwidth);
else
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());
+ pi.pain.fillRectangle(xframe, yframe, w, h,
+ pi.backgroundColor(this));
+
if (drawFrame_)
pi.pain.rectangle(xframe, yframe, w, h, frameColor());
}
- tm.draw(pi, x + TEXT_TO_INSET_OFFSET, y);
-}
+ ColorCode const old_color = pi.background_color;
+ pi.background_color = pi.backgroundColor(this, false);
+ tm.draw(pi, x + TEXT_TO_INSET_OFFSET, y);
-docstring const InsetText::editMessage() const
-{
- return _("Opened Text Inset");
+ pi.background_color = old_color;
}
{
LYXERR(Debug::ACTION, "InsetText::doDispatch()"
<< " [ cmd.action = " << cmd.action << ']');
- text_.dispatch(cur, cmd);
+
+ if (getLayout().isPassThru()) {
+ // Force any new text to latex_language FIXME: This
+ // should only be necessary in constructor, but new
+ // paragraphs that are created by pressing enter at
+ // the start of an existing paragraph get the buffer
+ // language and not latex_language, so we take this
+ // brute force approach.
+ cur.current_font.setLanguage(latex_language);
+ cur.real_current_font.setLanguage(latex_language);
+ }
+
+ switch (cmd.action) {
+ case LFUN_PASTE:
+ case LFUN_CLIPBOARD_PASTE:
+ case LFUN_SELECTION_PASTE:
+ case LFUN_PRIMARY_SELECTION_PASTE:
+ text_.dispatch(cur, cmd);
+ // If we we can only store plain text, we must reset all
+ // attributes.
+ // FIXME: Change only the pasted paragraphs
+ fixParagraphsFont();
+ break;
+
+ case LFUN_INSET_DISSOLVE: {
+ bool const main_inset = &buffer().inset() == this;
+ bool const target_inset = cmd.argument().empty()
+ || cmd.getArg(0) == insetName(lyxCode());
+ bool const one_cell = nargs() == 1;
+
+ if (!main_inset && target_inset && one_cell) {
+ // Text::dissolveInset assumes that the cursor
+ // is inside the Inset.
+ if (&cur.inset() != this)
+ cur.pushBackward(*this);
+ cur.beginUndoGroup();
+ text_.dispatch(cur, cmd);
+ cur.endUndoGroup();
+ } else
+ cur.undispatched();
+ break;
+ }
+
+ default:
+ text_.dispatch(cur, cmd);
+ }
+
+ if (!cur.result().dispatched())
+ Inset::doDispatch(cur, cmd);
}
bool InsetText::getStatus(Cursor & cur, FuncRequest const & cmd,
FuncStatus & status) const
{
- return text_.getStatus(cur, cmd, status);
+ switch (cmd.action) {
+ case LFUN_LAYOUT:
+ status.setEnabled(!forcePlainLayout());
+ return true;
+
+ case LFUN_LAYOUT_PARAGRAPH:
+ case LFUN_PARAGRAPH_PARAMS:
+ case LFUN_PARAGRAPH_PARAMS_APPLY:
+ case LFUN_PARAGRAPH_UPDATE:
+ status.setEnabled(allowParagraphCustomization());
+ return true;
+
+ case LFUN_INSET_DISSOLVE: {
+ bool const main_inset = &buffer().inset() == this;
+ bool const target_inset = cmd.argument().empty()
+ || cmd.getArg(0) == insetName(lyxCode());
+ bool const one_cell = nargs() == 1;
+
+ if (target_inset)
+ status.setEnabled(!main_inset && one_cell);
+ return target_inset;
+ }
+
+ default:
+ // Dispatch only to text_ if the cursor is inside
+ // the text_. It is not for context menus (bug 5797).
+ bool ret = false;
+ if (cur.text() == &text_)
+ ret = text_.getStatus(cur, cmd, status);
+
+ if (!ret)
+ ret = Inset::getStatus(cur, cmd, status);
+ return ret;
+ }
+}
+
+
+void InsetText::fixParagraphsFont()
+{
+ if (!getLayout().isPassThru())
+ return;
+
+ Font font(inherit_font, buffer().params().language);
+ font.setLanguage(latex_language);
+ ParagraphList::iterator par = paragraphs().begin();
+ ParagraphList::iterator const end = paragraphs().end();
+ while (par != end) {
+ par->resetFonts(font);
+ par->params().clear();
+ ++par;
+ }
}
}
-void InsetText::acceptChanges(BufferParams const & bparams)
+void InsetText::acceptChanges()
{
- text_.acceptChanges(bparams);
+ text_.acceptChanges();
}
-void InsetText::rejectChanges(BufferParams const & bparams)
+void InsetText::rejectChanges()
{
- text_.rejectChanges(bparams);
+ text_.rejectChanges();
}
-int InsetText::latex(Buffer const & buf, odocstream & os,
- OutputParams const & runparams) const
+void InsetText::validate(LaTeXFeatures & features) const
{
+ features.useInsetLayout(getLayout());
+ for_each(paragraphs().begin(), paragraphs().end(),
+ bind(&Paragraph::validate, _1, ref(features)));
+}
+
+
+int InsetText::latex(odocstream & os, OutputParams const & runparams) const
+{
+ // This implements the standard way of handling the LaTeX
+ // output of a text inset, either a command or an
+ // environment. Standard collapsable insets should not
+ // redefine this, non-standard ones may call this.
+ InsetLayout const & il = getLayout();
+ int rows = 0;
+ if (!il.latexname().empty()) {
+ if (il.latextype() == InsetLayout::COMMAND) {
+ // FIXME UNICODE
+ if (runparams.moving_arg)
+ os << "\\protect";
+ os << '\\' << from_utf8(il.latexname());
+ if (!il.latexparam().empty())
+ os << from_utf8(il.latexparam());
+ os << '{';
+ } else if (il.latextype() == InsetLayout::ENVIRONMENT) {
+ os << "%\n\\begin{" << from_utf8(il.latexname()) << "}\n";
+ if (!il.latexparam().empty())
+ os << from_utf8(il.latexparam());
+ rows += 2;
+ }
+ }
+ OutputParams rp = runparams;
+ if (il.isPassThru())
+ rp.verbatim = true;
+ if (il.isNeedProtect())
+ rp.moving_arg = true;
+
+ // Output the contents of the inset
TexRow texrow;
- latexParagraphs(buf, text_, os, texrow, runparams);
- return texrow.rows();
+ latexParagraphs(buffer(), text_, os, texrow, rp);
+ rows += texrow.rows();
+
+ if (!il.latexname().empty()) {
+ if (il.latextype() == InsetLayout::COMMAND) {
+ os << "}";
+ } else if (il.latextype() == InsetLayout::ENVIRONMENT) {
+ os << "\n\\end{" << from_utf8(il.latexname()) << "}\n";
+ rows += 2;
+ }
+ }
+ return rows;
}
-int InsetText::plaintext(Buffer const & buf, odocstream & os,
- OutputParams const & runparams) const
+int InsetText::plaintext(odocstream & os, OutputParams const & runparams) const
{
ParagraphList::const_iterator beg = paragraphs().begin();
ParagraphList::const_iterator end = paragraphs().end();
os << '\n';
}
odocstringstream oss;
- writePlaintextParagraph(buf, *it, oss, runparams, ref_printed);
+ writePlaintextParagraph(buffer(), *it, oss, runparams, ref_printed);
docstring const str = oss.str();
os << str;
// FIXME: len is not computed fully correctly; in principle,
}
-int InsetText::docbook(Buffer const & buf, odocstream & os,
- OutputParams const & runparams) const
+int InsetText::docbook(odocstream & os, OutputParams const & runparams) const
{
- docbookParagraphs(paragraphs(), buf, os, runparams);
+ ParagraphList::const_iterator const beg = paragraphs().begin();
+
+ if (!undefined())
+ sgml::openTag(os, getLayout().latexname(),
+ beg->getID(buffer(), runparams) + getLayout().latexparam());
+
+ docbookParagraphs(text_, buffer(), os, runparams);
+
+ if (!undefined())
+ sgml::closeTag(os, getLayout().latexname());
+
return 0;
}
-void InsetText::validate(LaTeXFeatures & features) const
+docstring InsetText::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
{
- for_each(paragraphs().begin(), paragraphs().end(),
- bind(&Paragraph::validate, _1, ref(features)));
+ return insetAsXHTML(xs, runparams, WriteEverything);
+}
+
+
+// FIXME XHTML
+// There are cases where we may need to close open fonts and such
+// and then re-open them when we are done. This would be the case, e.g.,
+// if we were otherwise about to write:
+// <em>word <div class='foot'>footnote text.</div> emph</em>
+// The problem isn't so much that the footnote text will get emphasized:
+// we can handle that with CSS. The problem is that this is invalid XHTML.
+// One solution would be to make the footnote <span>, but the problem is
+// completely general, and so we'd have to make absolutely everything into
+// span. What I think will work is to check if we're about to write "div" and,
+// if so, try to close fonts, etc.
+// There are probably limits to how well we can do here, though, and we will
+// have to rely upon users not putting footnotes inside noun-type insets.
+docstring InsetText::insetAsXHTML(XHTMLStream & xs, OutputParams const & runparams,
+ XHTMLOptions opts) const
+{
+ if (undefined()) {
+ xhtmlParagraphs(text_, buffer(), xs, runparams);
+ return docstring();
+ }
+
+ InsetLayout const & il = getLayout();
+ if (opts & WriteOuterTag)
+ xs << StartTag(il.htmltag(), il.htmlattr());
+ if ((opts & WriteLabel) && !il.counter().empty()) {
+ BufferParams const & bp = buffer().masterBuffer()->params();
+ Counters & cntrs = bp.documentClass().counters();
+ cntrs.step(il.counter());
+ // FIXME: translate to paragraph language
+ if (!il.htmllabel().empty()) {
+ docstring const lbl =
+ cntrs.counterLabel(from_utf8(il.htmllabel()), bp.language->code());
+ // FIXME is this check necessary?
+ if (!lbl.empty()) {
+ xs << StartTag(il.htmllabeltag(), il.htmllabelattr());
+ xs << lbl;
+ xs << EndTag(il.htmllabeltag());
+ }
+ }
+ }
+
+ if (opts & WriteInnerTag)
+ xs << StartTag(il.htmlinnertag(), il.htmlinnerattr());
+ if (il.isMultiPar())
+ xhtmlParagraphs(text_, buffer(), xs, runparams);
+ else {
+ OutputParams ours = runparams;
+ ours.html_make_pars = false;
+ xhtmlParagraphs(text_, buffer(), xs, ours);
+ }
+ if (opts & WriteInnerTag)
+ xs << EndTag(il.htmlinnertag());
+ if (opts & WriteOuterTag)
+ xs << EndTag(il.htmltag());
+ return docstring();
}
}
-void InsetText::appendParagraphs(Buffer * buffer, ParagraphList & plist)
+void InsetText::appendParagraphs(ParagraphList & plist)
{
// There is little we can do here to keep track of changes.
// As of 2006/10/20, appendParagraphs is used exclusively by
ParagraphList::iterator pit = plist.begin();
ParagraphList::iterator ins = pl.insert(pl.end(), *pit);
++pit;
- mergeParagraph(buffer->params(), pl,
+ mergeParagraph(buffer().params(), pl,
distance(pl.begin(), ins) - 1);
for_each(pit, plist.end(),
}
-void InsetText::addPreview(PreviewLoader & loader) const
+void InsetText::addPreview(DocIterator const & text_inset_pos,
+ PreviewLoader & loader) const
{
ParagraphList::const_iterator pit = paragraphs().begin();
ParagraphList::const_iterator pend = paragraphs().end();
+ int pidx = 0;
+
+ DocIterator inset_pos = text_inset_pos;
+ inset_pos.push_back(CursorSlice(*const_cast<InsetText *>(this)));
- for (; pit != pend; ++pit) {
+ for (; pit != pend; ++pit, ++pidx) {
InsetList::const_iterator it = pit->insetList().begin();
InsetList::const_iterator end = pit->insetList().end();
- for (; it != end; ++it)
- it->inset->addPreview(loader);
+ inset_pos.pit() = pidx;
+ for (; it != end; ++it) {
+ inset_pos.pos() = it->pos;
+ it->inset->addPreview(inset_pos, loader);
+ }
}
}
-//FIXME: instead of this hack, which only works by chance,
-// cells should have their own insetcell type, which returns CELL_CODE!
-bool InsetText::neverIndent(Buffer const & buffer) const
-{
- // this is only true for tabular cells
- return !text_.isMainText(buffer) && lyxCode() == TEXT_CODE;
-}
-
-
ParagraphList const & InsetText::paragraphs() const
{
return text_.paragraphs();
}
-void InsetText::updateLabels(Buffer const & buf, ParIterator const & it)
+void InsetText::updateLabels(ParIterator const & it, bool out)
{
ParIterator it2 = it;
it2.forwardPos();
- BOOST_ASSERT(&it2.inset() == this && it2.pit() == 0);
- lyx::updateLabels(buf, it2);
+ LASSERT(&it2.inset() == this && it2.pit() == 0, return);
+ if (producesOutput())
+ buffer().updateLabels(it2, out);
+ else {
+ DocumentClass const & tclass = buffer().masterBuffer()->params().documentClass();
+ Counters const savecnt = tclass.counters();
+ buffer().updateLabels(it2, out);
+ tclass.counters() = savecnt;
+ }
+}
+
+
+void InsetText::tocString(odocstream & os) const
+{
+ if (!getLayout().isInToc())
+ return;
+ os << text().asString(0, 1, AS_STR_LABEL | AS_STR_INSETS);
+}
+
+
+
+void InsetText::addToToc(DocIterator const & cdit)
+{
+ DocIterator dit = cdit;
+ dit.push_back(CursorSlice(*this));
+ Toc & toc = buffer().tocBackend().toc("tableofcontents");
+
+ BufferParams const & bufparams = buffer_->params();
+ const int min_toclevel = bufparams.documentClass().min_toclevel();
+
+ // For each paragraph, traverse its insets and let them add
+ // their toc items
+ ParagraphList & pars = paragraphs();
+ pit_type pend = paragraphs().size();
+ for (pit_type pit = 0; pit != pend; ++pit) {
+ Paragraph const & par = pars[pit];
+ dit.pit() = pit;
+ // the string that goes to the toc (could be the optarg)
+ docstring tocstring;
+ InsetList::const_iterator it = par.insetList().begin();
+ InsetList::const_iterator end = par.insetList().end();
+ for (; it != end; ++it) {
+ Inset & inset = *it->inset;
+ dit.pos() = it->pos;
+ //lyxerr << (void*)&inset << " code: " << inset.lyxCode() << std::endl;
+ inset.addToToc(dit);
+ switch (inset.lyxCode()) {
+ case OPTARG_CODE: {
+ if (!tocstring.empty())
+ break;
+ dit.pos() = 0;
+ Paragraph const & insetpar =
+ *static_cast<InsetOptArg&>(inset).paragraphs().begin();
+ if (!par.labelString().empty())
+ tocstring = par.labelString() + ' ';
+ tocstring += insetpar.asString(AS_STR_INSETS);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ // now the toc entry for the paragraph
+ int const toclevel = par.layout().toclevel;
+ if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) {
+ dit.pos() = 0;
+ // insert this into the table of contents
+ if (tocstring.empty())
+ tocstring = par.asString(AS_STR_LABEL | AS_STR_INSETS);
+ toc.push_back(TocItem(dit, toclevel - min_toclevel, tocstring));
+ }
+
+ // And now the list of changes.
+ par.addChangesToToc(dit, buffer());
+ }
+}
+
+
+bool InsetText::notifyCursorLeaves(Cursor const & old, Cursor & cur)
+{
+ if (buffer().isClean())
+ return Inset::notifyCursorLeaves(old, cur);
+
+ // find text inset in old cursor
+ Cursor insetCur = old;
+ int scriptSlice = insetCur.find(this);
+ LASSERT(scriptSlice != -1, /**/);
+ insetCur.cutOff(scriptSlice);
+ LASSERT(&insetCur.inset() == this, /**/);
+
+ // update the old paragraph's words
+ insetCur.paragraph().updateWords();
+
+ return Inset::notifyCursorLeaves(old, cur);
}
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);
+ //LASSERT(&cur.bv().cursor().inset() != this, return false);
+ return text_.completionSupported(cur);
}
}
-Inset::CompletionList const
-* InsetText::createCompletionList(Cursor const & cur) const
+bool InsetText::showCompletionCursor() const
{
- if (!completionSupported(cur))
- return 0;
-
- return new TextCompletionList(cur);
+ return lyxrc.completion_cursor_text;
}
-docstring InsetText::previousWord(Buffer const & buffer, CursorSlice const & sl) const
+CompletionList const * InsetText::createCompletionList(Cursor const & cur) 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);
+ return completionSupported(cur) ? text_.createCompletionList(cur) : 0;
}
{
if (!completionSupported(cur))
return docstring();
-
- return previousWord(cur.buffer(), cur.top());
+ return text_.completionPrefix(cur);
}
bool InsetText::insertCompletion(Cursor & cur, docstring const & s,
- bool finished)
+ bool finished)
{
if (!completionSupported(cur))
return false;
- BOOST_ASSERT(cur.bv().cursor() == cur);
- cur.insert(s);
- cur.bv().cursor() = cur;
- return true;
+ return text_.insertCompletion(cur, s, finished);
}
void InsetText::completionPosAndDim(Cursor const & cur, int & x, int & y,
- Dimension & dim) const
+ Dimension & dim) const
{
- Cursor const & bvcur = cur.bv().cursor();
-
- // get word in front of cursor
- docstring word = previousWord(cur.buffer(), bvcur.top());
- DocIterator wordStart = bvcur;
- wordStart.pos() -= word.length();
-
- // get position on screen of the word start and end
- Point lxy = cur.bv().getPos(wordStart, false);
- Point rxy = cur.bv().getPos(bvcur, bvcur.boundary());
-
- // calculate dimensions of the word
TextMetrics const & tm = cur.bv().textMetrics(&text_);
- dim = tm.rowHeight(bvcur.pit(), wordStart.pos(), bvcur.pos(), false);
- dim.wid = abs(rxy.x_ - lxy.x_);
-
- // calculate position of word
- y = lxy.y_;
- x = min(rxy.x_, lxy.x_);
-
- //lyxerr << "wid=" << dim.width() << " x=" << x << " y=" << y << " lxy.x_=" << lxy.x_ << " rxy.x_=" << rxy.x_ << " word=" << word << std::endl;
- //lyxerr << " wordstart=" << wordStart << " bvcur=" << bvcur << " cur=" << cur << std::endl;
+ tm.completionPosAndDim(cur, x, y, dim);
}
+docstring InsetText::contextMenu(BufferView const &, int, int) const
+{
+ return from_ascii("context-edit");
+}
+
+
+InsetCaption const * InsetText::getCaptionInset() const
+{
+ ParagraphList::const_iterator pit = paragraphs().begin();
+ for (; pit != paragraphs().end(); ++pit) {
+ InsetList::const_iterator it = pit->insetList().begin();
+ for (; it != pit->insetList().end(); ++it) {
+ Inset & inset = *it->inset;
+ if (inset.lyxCode() == CAPTION_CODE) {
+ InsetCaption const * ins =
+ static_cast<InsetCaption const *>(it->inset);
+ return ins;
+ }
+ }
+ }
+ return 0;
+}
+
+
+docstring InsetText::getCaptionText(OutputParams const & runparams) const
+{
+ InsetCaption const * ins = getCaptionInset();
+ if (ins == 0)
+ return docstring();
+
+ odocstringstream ods;
+ ins->getCaptionAsPlaintext(ods, runparams);
+ return ods.str();
+}
+
+
+docstring InsetText::getCaptionHTML(OutputParams const & runparams) const
+{
+ InsetCaption const * ins = getCaptionInset();
+ if (ins == 0)
+ return docstring();
+
+ odocstringstream ods;
+ XHTMLStream xs(ods);
+ docstring def = ins->getCaptionAsHTML(xs, runparams);
+ if (!def.empty())
+ // should already have been escaped
+ xs << XHTMLStream::NextRaw() << def << '\n';
+ return ods.str();
+}
+
+
+InsetText::XHTMLOptions operator|(InsetText::XHTMLOptions a1, InsetText::XHTMLOptions a2)
+{
+ return static_cast<InsetText::XHTMLOptions>((int)a1 | (int)a2);
+}
+
} // namespace lyx