#include "FuncRequest.h"
#include "FuncStatus.h"
#include "InsetLayout.h"
+#include "InsetList.h"
#include "Language.h"
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "MetricsInfo.h"
+#include "output_xhtml.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
#include "sgml.h"
{
Dimension dim = dimensionCollapsed(bv);
if (geometry(bv) == NoButton)
- return translateIfPossible(layout_->labelstring());
+ return translateIfPossible(getLayout().labelstring());
if (x > xo(bv) + dim.wid || y > yo(bv) + dim.des || isOpen(bv))
return docstring();
}
-void InsetCollapsable::setLayout(BufferParams const & bp)
+void InsetCollapsable::setLayout()
{
- setLayout(bp.documentClassPtr());
+ setLayout(buffer().params().documentClassPtr());
}
{
if (dc) {
layout_ = &(dc->insetLayout(name()));
- labelstring_ = translateIfPossible(layout_->labelstring());
+ labelstring_ = translateIfPossible(getLayout().labelstring());
} else {
layout_ = &DocumentClass::plainInsetLayout();
labelstring_ = _("UNDEFINED");
status_ = Open;
// this must be set before we enter InsetText::read()
- setLayout(buffer().params());
+ setLayout();
InsetText::read(lex);
// set button label again as the inset contents was not read yet at
// setLayout() time.
{
LASSERT(layout_, /**/);
Dimension dim;
- theFontMetrics(layout_->labelfont()).buttonText(
+ theFontMetrics(getLayout().labelfont()).buttonText(
buttonLabel(bv), dim.wid, dim.asc, dim.des);
return dim;
}
void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
{
- LASSERT(layout_, /**/);
-
auto_open_[mi.base.bv] = mi.base.bv->cursor().isInside(this);
FontInfo tmpfont = mi.base.font;
- mi.base.font = layout_->font();
+ mi.base.font = getLayout().font();
mi.base.font.realize(tmpfont);
BufferView const & bv = *mi.base.bv;
case SubLabel: {
InsetText::metrics(mi, dim);
// consider width of the inset label
- FontInfo font(layout_->labelfont());
+ FontInfo font(getLayout().labelfont());
font.realize(sane_font);
font.decSize();
font.decSize();
void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
{
- LASSERT(layout_, /**/);
BufferView const & bv = *pi.base.bv;
auto_open_[&bv] = bv.cursor().isInside(this);
FontInfo tmpfont = pi.base.font;
- pi.base.font = layout_->font();
+ pi.base.font = getLayout().font();
pi.base.font.realize(tmpfont);
// Draw button first -- top, left or only
button_dim.y1 = y - dimc.asc;
button_dim.y2 = y + dimc.des;
- pi.pain.buttonText(x, y, buttonLabel(bv), layout_->labelfont(),
+ FontInfo labelfont = getLayout().labelfont();
+ labelfont.setColor(labelColor());
+ pi.pain.buttonText(x, y, buttonLabel(bv), labelfont,
mouse_hover_);
} else {
button_dim.x1 = 0;
const int xx2 = x + textdim.wid - TEXT_TO_INSET_OFFSET + 1;
pi.pain.line(xx1, y + desc - 4,
xx1, y + desc,
- layout_->labelfont().color());
+ labelColor());
if (status_ == Open)
pi.pain.line(xx1, y + desc,
xx2, y + desc,
- layout_->labelfont().color());
+ labelColor());
else {
// Make status_ value visible:
pi.pain.line(xx1, y + desc,
xx1 + 4, y + desc,
- layout_->labelfont().color());
+ labelColor());
pi.pain.line(xx2 - 4, y + desc,
xx2, y + desc,
- layout_->labelfont().color());
+ labelColor());
}
pi.pain.line(x + textdim.wid - 3, y + desc, x + textdim.wid - 3,
- y + desc - 4, layout_->labelfont().color());
+ y + desc - 4, labelColor());
// the label below the text. Can be toggled.
if (geometry(bv) == SubLabel) {
- FontInfo font(layout_->labelfont());
+ FontInfo font(getLayout().labelfont());
font.realize(sane_font);
font.decSize();
font.decSize();
if (cur.isInside(this)) {
y -= textdim.asc;
y += 3;
- pi.pain.line(xx1, y + 4, xx1, y, layout_->labelfont().color());
- pi.pain.line(xx1 + 4, y, xx1, y, layout_->labelfont().color());
+ pi.pain.line(xx1, y + 4, xx1, y, labelColor());
+ pi.pain.line(xx1 + 4, y, xx1, y, labelColor());
pi.pain.line(xx2, y + 4, xx2, y,
- layout_->labelfont().color());
+ labelColor());
pi.pain.line(xx2 - 4, y, xx2, y,
- layout_->labelfont().color());
+ labelColor());
}
break;
}
break;
}
+ case LFUN_TAB_INSERT: {
+ bool const multi_par_selection = cur.selection() &&
+ cur.selBegin().pit() != cur.selEnd().pit();
+ if (multi_par_selection) {
+ // If there is a multi-paragraph selection, a tab is inserted
+ // at the beginning of each paragraph.
+ cur.recordUndoSelection();
+ pit_type const pit_end = cur.selEnd().pit();
+ for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
+ paragraphs()[pit].insertChar(0, '\t',
+ buffer().params().trackChanges);
+ // Update the selection pos to make sure the selection does not
+ // change as the inserted tab will increase the logical pos.
+ if (cur.anchor_.pit() == pit)
+ cur.anchor_.forwardPos();
+ if (cur.pit() == pit)
+ cur.forwardPos();
+ }
+ cur.finishUndo();
+ } else {
+ // Maybe we shouldn't allow tabs within a line, because they
+ // are not (yet) aligned as one might do expect.
+ FuncRequest cmd(LFUN_SELF_INSERT, from_ascii("\t"));
+ dispatch(cur, cmd);
+ }
+ break;
+ }
+
+ case LFUN_TAB_DELETE:
+ if (cur.selection()) {
+ // If there is a selection, a tab (if present) is removed from
+ // the beginning of each paragraph.
+ cur.recordUndoSelection();
+ pit_type const pit_end = cur.selEnd().pit();
+ for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) {
+ Paragraph & par = paragraphs()[pit];
+ if (par.getChar(0) == '\t') {
+ if (cur.pit() == pit)
+ cur.posBackward();
+ if (cur.anchor_.pit() == pit && cur.anchor_.pos() > 0 )
+ cur.anchor_.backwardPos();
+
+ par.eraseChar(0, buffer().params().trackChanges);
+ } else
+ // If no tab was present, try to remove up to four spaces.
+ for (int n_spaces = 0;
+ par.getChar(0) == ' ' && n_spaces < 4; ++n_spaces) {
+ if (cur.pit() == pit)
+ cur.posBackward();
+ if (cur.anchor_.pit() == pit && cur.anchor_.pos() > 0 )
+ cur.anchor_.backwardPos();
+
+ par.eraseChar(0, buffer().params().trackChanges);
+ }
+ }
+ cur.finishUndo();
+ } else {
+ // If there is no selection, try to remove a tab or some spaces
+ // before the position of the cursor.
+ Paragraph & par = paragraphs()[cur.pit()];
+ pos_type const pos = cur.pos();
+
+ if (pos == 0)
+ break;
+
+ char_type const c = par.getChar(pos - 1);
+ cur.recordUndo();
+ if (c == '\t') {
+ cur.posBackward();
+ par.eraseChar(cur.pos(), buffer().params().trackChanges);
+ } else
+ for (int n_spaces = 0; cur.pos() > 0
+ && par.getChar(cur.pos() - 1) == ' ' && n_spaces < 4;
+ ++n_spaces) {
+ cur.posBackward();
+ par.eraseChar(cur.pos(), buffer().params().trackChanges);
+ }
+ cur.finishUndo();
+ }
+ break;
+
default:
- if (layout_ && layout_->isForceLtr()) {
+ if (getLayout().isForceLtr()) {
// 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
bool InsetCollapsable::allowMultiPar() const
{
- return layout_->isMultiPar();
+ return getLayout().isMultiPar();
}
void InsetCollapsable::resetParagraphsFont()
{
Font font(inherit_font, buffer().params().language);
- if (layout_->isForceLtr())
+ if (getLayout().isForceLtr())
font.setLanguage(latex_language);
- if (layout_->isPassThru()) {
+ if (getLayout().isPassThru()) {
ParagraphList::iterator par = paragraphs().begin();
ParagraphList::iterator const end = paragraphs().end();
while (par != end) {
case LFUN_MARGINALNOTE_INSERT:
case LFUN_MATH_DISPLAY:
case LFUN_MATH_INSERT:
+ case LFUN_MATH_AMS_MATRIX:
case LFUN_MATH_MATRIX:
case LFUN_MATH_MODE:
case LFUN_MENU_OPEN:
case LFUN_TEXTSTYLE_UPDATE:
case LFUN_TOC_INSERT:
case LFUN_WRAP_INSERT:
- if (layout_->isPassThru()) {
+ if (getLayout().isPassThru()) {
flag.setEnabled(false);
return true;
}
return true;
case LFUN_LANGUAGE:
- flag.setEnabled(!layout_->isForceLtr());
+ flag.setEnabled(!getLayout().isForceLtr());
return InsetText::getStatus(cur, cmd, flag);
case LFUN_BREAK_PARAGRAPH:
- flag.setEnabled(layout_->isMultiPar());
+ flag.setEnabled(getLayout().isMultiPar());
return true;
+ case LFUN_TAB_INSERT:
+ case LFUN_TAB_DELETE:
+ if (getLayout().isPassThru()) {
+ flag.setEnabled(true);
+ return true;
+ }
+ return InsetText::getStatus(cur, cmd, flag);
+
default:
return InsetText::getStatus(cur, cmd, flag);
}
}
-docstring InsetCollapsable::floatName(
- string const & type, BufferParams const & bp) const
+docstring InsetCollapsable::floatName(string const & type) const
{
+ BufferParams const & bp = buffer().params();
FloatList const & floats = bp.documentClass().floats();
FloatList::const_iterator it = floats[type];
// FIXME UNICODE
InsetLayout::InsetDecoration InsetCollapsable::decoration() const
{
- if (!layout_)
- return InsetLayout::CLASSIC;
- InsetLayout::InsetDecoration const dec = layout_->decoration();
+ InsetLayout::InsetDecoration const dec = getLayout().decoration();
switch (dec) {
case InsetLayout::CLASSIC:
case InsetLayout::MINIMALISTIC:
int InsetCollapsable::latex(odocstream & os,
OutputParams const & runparams) const
{
- // FIXME: What should we do layout_ is 0?
- // 1) assert
- // 2) throw an error
- if (!layout_)
- return 0;
-
// This implements the standard way of handling the LaTeX output of
// a collapsable inset, either a command or an environment. Standard
// collapsable insets should not redefine this, non-standard ones may
// call this.
- if (!layout_->latexname().empty()) {
- if (layout_->latextype() == InsetLayout::COMMAND) {
+ if (!getLayout().latexname().empty()) {
+ if (getLayout().latextype() == InsetLayout::COMMAND) {
// FIXME UNICODE
if (runparams.moving_arg)
os << "\\protect";
- os << '\\' << from_utf8(layout_->latexname());
- if (!layout_->latexparam().empty())
- os << from_utf8(layout_->latexparam());
+ os << '\\' << from_utf8(getLayout().latexname());
+ if (!getLayout().latexparam().empty())
+ os << from_utf8(getLayout().latexparam());
os << '{';
- } else if (layout_->latextype() == InsetLayout::ENVIRONMENT) {
- os << "%\n\\begin{" << from_utf8(layout_->latexname()) << "}\n";
- if (!layout_->latexparam().empty())
- os << from_utf8(layout_->latexparam());
+ } else if (getLayout().latextype() == InsetLayout::ENVIRONMENT) {
+ os << "%\n\\begin{" << from_utf8(getLayout().latexname()) << "}\n";
+ if (!getLayout().latexparam().empty())
+ os << from_utf8(getLayout().latexparam());
}
}
OutputParams rp = runparams;
- if (layout_->isPassThru())
+ if (getLayout().isPassThru())
rp.verbatim = true;
- if (layout_->isNeedProtect())
+ if (getLayout().isNeedProtect())
rp.moving_arg = true;
int i = InsetText::latex(os, rp);
- if (!layout_->latexname().empty()) {
- if (layout_->latextype() == InsetLayout::COMMAND) {
+ if (!getLayout().latexname().empty()) {
+ if (getLayout().latextype() == InsetLayout::COMMAND) {
os << "}";
- } else if (layout_->latextype() == InsetLayout::ENVIRONMENT) {
- os << "\n\\end{" << from_utf8(layout_->latexname()) << "}\n";
+ } else if (getLayout().latextype() == InsetLayout::ENVIRONMENT) {
+ os << "\n\\end{" << from_utf8(getLayout().latexname()) << "}\n";
i += 4;
}
}
}
+docstring InsetCollapsable::xhtml(odocstream & os, OutputParams const & runparams) const
+{
+ InsetLayout const & il = getLayout();
+ if (undefined())
+ return InsetText::xhtml(os, runparams);
+
+ bool const opened = html::openTag(os, il.htmltag(), il.htmlattr());
+ if (!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())
+ os << cntrs.counterLabel(from_utf8(il.htmllabel()), bp.language->code());
+ }
+ bool innertag_opened = false;
+ if (!il.htmlinnertag().empty())
+ innertag_opened = html::openTag(os, il.htmlinnertag(), il.htmlinnerattr());
+ docstring deferred = InsetText::xhtml(os, runparams);
+ if (innertag_opened)
+ html::closeTag(os, il.htmlinnertag());
+ if (opened)
+ html::closeTag(os, il.htmltag());
+ return deferred;
+}
+
+
void InsetCollapsable::validate(LaTeXFeatures & features) const
{
features.useInsetLayout(getLayout());