From 040f3431e7a2350806594319704ff97a0284e9c1 Mon Sep 17 00:00:00 2001 From: Richard Heck Date: Tue, 12 Feb 2008 17:31:07 +0000 Subject: [PATCH] Fix bug 4037 and related problems. The patch has been cleaned up a bit from the one posted to the list. The basic idea has two parts. First, we hard code an "empty layout" (called PlainLayout, for want of a better name) in TextClass and read it before doing anything else. It can therefore be customized by classes, if they want---say, to make it left-aligned. Second, InsetText's are divided into three types: (i) normal ones, that use the "default" layout defined by the text class; (ii) highly restrictive ones, such as ERT and (not quite an inset) table cells, which demand the empty layout; (iii) middling ones, which default to an empty layout and use the empty layout in place of the default. (This is so we don't get the same problem we had with ERT in e.g. footnotes.) The type of inset is signaled by new methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout(). (The latter might better be called: useEmptyLayoutInsteadOfDefault(), but that's silly.) The old InsetText::forceDefaultParagraphs() has been split into these, plus a new method InsetText::allowParagraphCustomization(). A lot of the changes just adapt to this change. The other big change is in GuiToolbar: We want to show LyXDefault and the "default" layout only when they're active. There are a handful of places where I'm not entirely sure whether we should be using forceEmptyLayout or !allowParagraphCustomization() or both. The InsetCaption is one of these. These places, and some others, are marked with FIXMEs, so I'd appreciate it if people would search through the patch and let me know whether these need changing. If they don't, the FIXMEs can be deleted. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/BufferView.cpp | 2 +- src/CutAndPaste.cpp | 37 ++++++++-------- src/Paragraph.cpp | 18 ++++++-- src/Paragraph.h | 7 ++- src/Text.cpp | 74 +++++++++++++++++++++----------- src/Text3.cpp | 44 ++++++++++++++----- src/TextClass.cpp | 30 ++++++++++++- src/TextClass.h | 9 ++++ src/TextMetrics.cpp | 3 +- src/frontends/qt4/GuiToolbar.cpp | 25 +++++++++-- src/frontends/qt4/GuiToolbar.h | 2 + src/insets/Inset.h | 12 ++++-- src/insets/InsetBox.cpp | 9 +++- src/insets/InsetBox.h | 4 +- src/insets/InsetCaption.cpp | 4 ++ src/insets/InsetCaption.h | 4 +- src/insets/InsetCollapsable.cpp | 1 + src/insets/InsetCollapsable.h | 4 ++ src/insets/InsetERT.cpp | 2 +- src/insets/InsetERT.h | 6 ++- src/insets/InsetFlex.h | 2 +- src/insets/InsetTabular.cpp | 8 ++-- src/insets/InsetTabular.h | 5 ++- src/insets/InsetText.cpp | 5 ++- src/output_latex.cpp | 27 ++++++------ src/paragraph_funcs.cpp | 5 ++- 26 files changed, 254 insertions(+), 95 deletions(-) diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 5558f2889b..05489a34d7 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -894,7 +894,7 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd) case LFUN_LAYOUT: case LFUN_LAYOUT_PARAGRAPH: - flag.enabled(cur.inset().forceDefaultParagraphs(cur.idx())); + flag.enabled(cur.inset().allowParagraphCustomization(cur.idx())); break; case LFUN_INSET_SETTINGS: { diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index befcaf3ba9..9347e3c76a 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -143,11 +143,12 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist, } } - // If we are in an inset which returns forceDefaultParagraphs, - // set the paragraphs to default - if (cur.inset().forceDefaultParagraphs(cur.idx())) { + // set the paragraphs to empty layout if necessary + // note that we are doing this if the empty layout is + // supposed to be the default, not just if it is forced + if (cur.inset().useEmptyLayout()) { LayoutPtr const layout = - buffer.params().getTextClass().defaultLayout(); + buffer.params().getTextClass().emptyLayout(); ParagraphList::iterator const end = insertion.end(); for (ParagraphList::iterator par = insertion.begin(); par != end; ++par) @@ -400,35 +401,35 @@ docstring grabAndEraseSelection(Cursor & cur) } -void switchBetweenClasses(TextClassPtr const & c1, - TextClassPtr const & c2, InsetText & in, ErrorList & errorlist) +void switchBetweenClasses(TextClassPtr const & oldone, + TextClassPtr const & newone, InsetText & in, ErrorList & errorlist) { errorlist.clear(); BOOST_ASSERT(!in.paragraphs().empty()); - if (c1 == c2) + if (oldone == newone) return; - TextClass const & tclass1 = *c1; - TextClass const & tclass2 = *c2; + TextClass const & oldtc = *oldone; + TextClass const & newtc = *newone; // layouts ParIterator end = par_iterator_end(in); for (ParIterator it = par_iterator_begin(in); it != end; ++it) { docstring const name = it->layout()->name(); - bool hasLayout = tclass2.hasLayout(name); + bool hasLayout = newtc.hasLayout(name); if (hasLayout) - it->layout(tclass2[name]); + it->layout(newtc[name]); else - it->layout(tclass2.defaultLayout()); + it->layout(newtc.defaultLayout()); - if (!hasLayout && name != tclass1.defaultLayoutName()) { + if (!hasLayout && name != oldtc.defaultLayoutName()) { docstring const s = bformat( _("Layout had to be changed from\n%1$s to %2$s\n" "because of class conversion from\n%3$s to %4$s"), name, it->layout()->name(), - from_utf8(tclass1.name()), from_utf8(tclass2.name())); + from_utf8(oldtc.name()), from_utf8(newtc.name())); // To warn the user that something had to be done. errorlist.push_back(ErrorItem(_("Changed Layout"), s, it->id(), 0, @@ -445,16 +446,16 @@ void switchBetweenClasses(TextClassPtr const & c1, if (inset->lyxCode() != FLEX_CODE) // FIXME: Should we verify all InsetCollapsable? continue; - inset->setLayout(c2); + inset->setLayout(newone); if (inset->getLayout().labelstring != from_utf8("UNDEFINED")) continue; - // The flex inset is undefined in tclass2 + // The flex inset is undefined in newtc docstring const s = bformat(_( "Flex inset %1$s is " "undefined because of class " "conversion from\n%2$s to %3$s"), - inset->name(), from_utf8(tclass1.name()), - from_utf8(tclass2.name())); + inset->name(), from_utf8(oldtc.name()), + from_utf8(newtc.name())); // To warn the user that something had to be done. errorlist.push_back(ErrorItem( _("Undefined flex inset"), diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index b5f31281f4..1a1f2e814a 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -1601,9 +1601,21 @@ void Paragraph::setBeginOfBody() } -bool Paragraph::forceDefaultParagraphs() const +bool Paragraph::forceEmptyLayout() const { - return inInset() && inInset()->forceDefaultParagraphs(0); + return inInset() && inInset()->forceEmptyLayout(); +} + + +bool Paragraph::allowParagraphCustomization() const +{ + return inInset() && inInset()->allowParagraphCustomization(0); +} + + +bool Paragraph::useEmptyLayout() const +{ + return inInset() && inInset()->useEmptyLayout(); } @@ -1805,7 +1817,7 @@ bool Paragraph::latex(Buffer const & buf, // any special options in the paragraph and also we don't allow // any environment other than the default layout of the text class // to be valid! - bool asdefault = forceDefaultParagraphs(); + bool asdefault = forceEmptyLayout(); if (asdefault) { style = bparams.getTextClass().defaultLayout(); diff --git a/src/Paragraph.h b/src/Paragraph.h index 04ce3f4fbc..e00f644f15 100644 --- a/src/Paragraph.h +++ b/src/Paragraph.h @@ -145,8 +145,11 @@ public: /// InsetCode ownerCode() const; /// - bool forceDefaultParagraphs() const; - + bool forceEmptyLayout() const; + /// + bool allowParagraphCustomization() const; + /// + bool useEmptyLayout() const; /// pos_type size() const; /// diff --git a/src/Text.cpp b/src/Text.cpp index 6e2ee99964..6913f22d3a 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -103,8 +103,20 @@ void readParToken(Buffer const & buf, Paragraph & par, Lexer & lex, TextClass const & tclass = bp.getTextClass(); - if (layoutname.empty()) { + if (layoutname.empty()) layoutname = tclass.defaultLayoutName(); + + if (par.forceEmptyLayout()) + // in this case only the empty layout is allowed + layoutname = tclass.emptyLayoutName(); + else if (par.useEmptyLayout()) { + // in this case, default layout maps to empty layout + if (layoutname == tclass.defaultLayoutName()) + layoutname = tclass.emptyLayoutName(); + } else { + // otherwise, the empty layout maps to the default + if (layoutname == tclass.emptyLayoutName()) + layoutname = tclass.defaultLayoutName(); } bool hasLayout = tclass.hasLayout(layoutname); @@ -113,7 +125,9 @@ void readParToken(Buffer const & buf, Paragraph & par, Lexer & lex, errorList.push_back(ErrorItem(_("Unknown layout"), bformat(_("Layout '%1$s' does not exist in textclass '%2$s'\nTrying to use the default instead.\n"), layoutname, from_utf8(tclass.name())), par.id(), 0, par.size())); - layoutname = tclass.defaultLayoutName(); + layoutname = par.useEmptyLayout() ? + tclass.emptyLayoutName() : + tclass.defaultLayoutName(); } par.layout(bp.getTextClass()[layoutname]); @@ -388,9 +402,11 @@ void Text::breakParagraph(Cursor & cur, bool inverse_logic) if (sensitive) { if (cur.pos() == 0) // set to standard-layout + //FIXME Check if this should be emptyLayout() in some cases pars_[cpit].applyLayout(tclass.defaultLayout()); else // set to standard-layout + //FIXME Check if this should be emptyLayout() in some cases pars_[next_par].applyLayout(tclass.defaultLayout()); } @@ -868,31 +884,37 @@ bool Text::handleBibitems(Cursor & cur) { if (cur.paragraph().layout()->labeltype != LABEL_BIBLIO) return false; + + if (cur.pos() != 0) + return false; + + BufferParams const & bufparams = cur.buffer().params(); + Paragraph const & par = cur.paragraph(); + Cursor prevcur = cur; + if (cur.pit() > 0) { + --prevcur.pit(); + prevcur.pos() = prevcur.lastpos(); + } + Paragraph const & prevpar = prevcur.paragraph(); + // if a bibitem is deleted, merge with previous paragraph // if this is a bibliography item as well - if (cur.pos() == 0) { - BufferParams const & bufparams = cur.buffer().params(); - Paragraph const & par = cur.paragraph(); - Cursor prevcur = cur; - if (cur.pit() > 0) { - --prevcur.pit(); - prevcur.pos() = prevcur.lastpos(); - } - Paragraph const & prevpar = prevcur.paragraph(); - if (cur.pit() > 0 && par.layout() == prevpar.layout()) { - cur.recordUndo(ATOMIC_UNDO, prevcur.pit()); - mergeParagraph(bufparams, cur.text()->paragraphs(), - prevcur.pit()); - updateLabels(cur.buffer()); - setCursorIntern(cur, prevcur.pit(), prevcur.pos()); - cur.updateFlags(Update::Force); - // if not, reset the paragraph to default - } else - cur.paragraph().layout( - bufparams.getTextClass().defaultLayout()); + if (cur.pit() > 0 && par.layout() == prevpar.layout()) { + cur.recordUndo(ATOMIC_UNDO, prevcur.pit()); + mergeParagraph(bufparams, cur.text()->paragraphs(), + prevcur.pit()); + updateLabels(cur.buffer()); + setCursorIntern(cur, prevcur.pit(), prevcur.pos()); + cur.updateFlags(Update::Force); return true; - } - return false; + } + + // otherwise reset to default + if (par.useEmptyLayout()) + cur.paragraph().layout(bufparams.getTextClass().emptyLayout()); + else + cur.paragraph().layout(bufparams.getTextClass().defaultLayout()); + return true; } @@ -974,8 +996,10 @@ bool Text::backspacePos0(Cursor & cur) // layouts. I think it is a real bug of all other // word processors to allow it. It confuses the user. // Correction: Pasting is always allowed with standard-layout + // or the empty layout. else if (par.layout() == prevpar.layout() - || par.layout() == tclass.defaultLayout()) { + || par.layout() == tclass.defaultLayout() + || par.layout() == tclass.emptyLayout()) { cur.recordUndo(ATOMIC_UNDO, prevcur.pit()); mergeParagraph(bufparams, plist, prevcur.pit()); needsUpdate = true; diff --git a/src/Text3.cpp b/src/Text3.cpp index 40cf65b702..191c291ce5 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -217,7 +217,8 @@ static bool doInsertInset(Cursor & cur, Text * text, InsetText * insetText = dynamic_cast(inset); if (insetText && !insetText->allowMultiPar() || cur.lastpit() == 0) { // reset first par to default - LayoutPtr const layout = + LayoutPtr const layout = insetText->useEmptyLayout() ? + cur.buffer().params().getTextClass().emptyLayout() : cur.buffer().params().getTextClass().defaultLayout(); cur.text()->paragraphs().begin()->layout(layout); cur.pos() = 0; @@ -229,8 +230,9 @@ static bool doInsertInset(Cursor & cur, Text * text, } } else { // reset surrounding par to default - docstring const layoutname = - cur.buffer().params().getTextClass().defaultLayoutName(); + docstring const layoutname = insetText->useEmptyLayout() ? + cur.buffer().params().getTextClass().emptyLayoutName() : + cur.buffer().params().getTextClass().defaultLayoutName(); cur.leaveInset(*inset); text->setLayout(cur, layoutname); } @@ -1015,13 +1017,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) docstring layout = cmd.argument(); LYXERR(Debug::INFO, "LFUN_LAYOUT: (arg) " << to_utf8(layout)); - docstring const old_layout = cur.paragraph().layout()->name(); - - // Derive layout number from given argument (string) - // and current buffer's textclass (number) + Paragraph const & para = cur.paragraph(); + docstring const old_layout = para.layout()->name(); TextClass const & tclass = bv->buffer().params().getTextClass(); + if (layout.empty()) layout = tclass.defaultLayoutName(); + + if (para.forceEmptyLayout()) + // in this case only the empty layout is allowed + layout = tclass.emptyLayoutName(); + else if (para.useEmptyLayout()) { + // in this case, default layout maps to empty layout + if (layout == tclass.defaultLayoutName()) + layout = tclass.emptyLayoutName(); + } else { + // otherwise, the empty layout maps to the default + if (layout == tclass.emptyLayoutName()) + layout = tclass.defaultLayoutName(); + } + bool hasLayout = tclass.hasLayout(layout); // If the entry is obsolete, use the new one instead. @@ -1385,7 +1400,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // add a separate paragraph for the caption inset pars.push_back(Paragraph()); pars.back().setInsetOwner(pars[0].inInset()); - pars.back().layout(tclass.defaultLayout()); + if (pars.back().useEmptyLayout()) + pars.back().layout(tclass.emptyLayout()); + else + pars.back().layout(tclass.defaultLayout()); int cap_pit = pars.size() - 1; @@ -1395,8 +1413,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (!content) { pars.push_back(Paragraph()); pars.back().setInsetOwner(pars[0].inInset()); - pars.back().layout(tclass.defaultLayout()); - + if (pars.back().useEmptyLayout()) + pars.back().layout(tclass.emptyLayout()); + else + pars.back().layout(tclass.defaultLayout()); } // reposition the cursor to the caption @@ -1646,7 +1666,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) params2string(cur.paragraph(), data); // Will the paragraph accept changes from the dialog? - bool const accept = !cur.inset().forceDefaultParagraphs(cur.idx()); + bool const accept = + cur.inset().allowParagraphCustomization(cur.idx()); data = "update " + convert(accept) + '\n' + data; bv->updateDialog("paragraph", data); @@ -1689,6 +1710,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) breakParagraph(cur); } + //FIXME Check if this should be emptyLayout() setLayout(cur, tclass.defaultLayoutName()); ParagraphParameters p; setParagraphs(cur, p); diff --git a/src/TextClass.cpp b/src/TextClass.cpp index 7a51403dd3..0e73f35d25 100644 --- a/src/TextClass.cpp +++ b/src/TextClass.cpp @@ -35,6 +35,7 @@ #include "support/os.h" #include +#include using namespace std; using namespace lyx::support; @@ -124,9 +125,15 @@ TextClass::TextClass(string const & fn, string const & cln, titletype_ = TITLE_COMMAND_AFTER; titlename_ = "maketitle"; loaded_ = false; + // a hack to make this available for translation + // i'm sure there must be a better way (rgh) + _("PlainLayout"); } +docstring const TextClass::emptylayout_ = from_ascii("PlainLayout"); + + bool TextClass::isTeXClassAvailable() const { return texClassAvail_; @@ -218,6 +225,27 @@ bool TextClass::read(FileName const & filename, ReadType rt) LYXERR(Debug::TCLASS, "Reading " + translateRT(rt) + ": " + to_utf8(makeDisplayPath(filename.absFilename()))); + // Define the `empty' layout used in table cells, ert, etc. Note that + // we do this before loading any layout file, so that classes can + // override features of this layout if they should choose to do so. + if (rt == BASECLASS) { + static char const * s = "Margin Static\n" + "LatexType Paragraph\n" + "LatexName dummy\n" + "Align Block\n" + "AlignPossible Left, Right, Center\n" + "LabelType No_Label\n" + "End"; + istrstream ss(s); + Lexer lex(textClassTags, sizeof(textClassTags) / sizeof(textClassTags[0])); + lex.setStream(ss); + Layout lay; + lay.setName(emptylayout_); + bool error = readStyle(lex, lay); + BOOST_ASSERT(!error); + layoutlist_.push_back(boost::shared_ptr(new Layout(lay))); + } + Lexer lexrc(textClassTags, sizeof(textClassTags) / sizeof(textClassTags[0])); @@ -1052,7 +1080,7 @@ LayoutPtr const & TextClass::operator[](docstring const & name) const bool TextClass::deleteLayout(docstring const & name) { - if (name == defaultLayoutName()) + if (name == defaultLayoutName() || name == emptyLayoutName()) return false; LayoutList::iterator it = diff --git a/src/TextClass.h b/src/TextClass.h index a64aff6463..bdfe8aa14c 100644 --- a/src/TextClass.h +++ b/src/TextClass.h @@ -109,6 +109,13 @@ public: docstring const & defaultLayoutName() const; /// LayoutPtr const & defaultLayout() const; + /// returns a special layout for use when we don't really want one, + /// e.g., in table cells + LayoutPtr const & emptyLayout() const + { return operator[](emptylayout_); }; + /// + docstring const & emptyLayoutName() const + { return emptylayout_; } /// std::string const & name() const; /// @@ -200,6 +207,8 @@ private: std::string class_header_; /// docstring defaultlayout_; + /// name of empty layout + static const docstring emptylayout_; /// preamble text to support layout styles docstring preamble_; /// latex packages loaded by document class. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 69eef18615..9d122678ff 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1709,6 +1709,7 @@ int TextMetrics::leftMargin(int max_width, if (pars[newpar].layout()->isEnvironment()) { l_margin = leftMargin(max_width, newpar); } + //FIXME Should this check for emptyLayout() as well? if (par.layout() == tclass.defaultLayout()) { if (pars[newpar].params().noindent()) parindent.erase(); @@ -1830,7 +1831,7 @@ int TextMetrics::leftMargin(int max_width, && !(!par.empty() && par.isInset(pos) && par.getInset(pos)->display()) - && (par.layout() != tclass.defaultLayout() + && (par.layout() != tclass.defaultLayout() //should this check emptyLayout()? || buffer.params().paragraph_separation == BufferParams::PARSEP_INDENT)) { diff --git a/src/frontends/qt4/GuiToolbar.cpp b/src/frontends/qt4/GuiToolbar.cpp index aa2bdc68e1..b384c2dd15 100644 --- a/src/frontends/qt4/GuiToolbar.cpp +++ b/src/frontends/qt4/GuiToolbar.cpp @@ -304,22 +304,41 @@ void GuiLayoutBox::updateContents(bool reset) clear(); setEnabled(false); text_class_ = 0; + inset_ = 0; return; } TextClass const * text_class = &buffer->params().getTextClass(); - if (!reset && text_class_ == text_class) { + Inset const * inset = + owner_.view()->cursor().innerParagraph().inInset(); + + // we'll only update the layout list if the text class has changed + // or we've moved from one inset to another + if (!reset && text_class_ == text_class && inset_ == inset) { set(owner_.view()->cursor().innerParagraph().layout()->name()); return; } + inset_ = inset; text_class_ = text_class; clear(); TextClass::const_iterator it = text_class_->begin(); TextClass::const_iterator const end = text_class_->end(); - for (; it != end; ++it) - addItemSort(toqstr(translateIfPossible((*it)->name())), lyxrc.sort_layouts); + + for (; it != end; ++it) { + docstring const & name = (*it)->name(); + // if this inset requires the empty layout, we skip the default + // layout + if (name == text_class_->defaultLayoutName() && inset && + (inset->forceEmptyLayout() || inset->useEmptyLayout())) + continue; + // if it doesn't require the empty layout, we skip it + if (name == text_class_->emptyLayoutName() && inset && + !inset->forceEmptyLayout() && !inset->useEmptyLayout()) + continue; + addItemSort(toqstr(translateIfPossible(name)), lyxrc.sort_layouts); + } set(owner_.view()->cursor().innerParagraph().layout()->name()); diff --git a/src/frontends/qt4/GuiToolbar.h b/src/frontends/qt4/GuiToolbar.h index 3d0dfc8105..d912f99074 100644 --- a/src/frontends/qt4/GuiToolbar.h +++ b/src/frontends/qt4/GuiToolbar.h @@ -24,6 +24,7 @@ namespace lyx { +class Inset; class TextClass; class ToolbarItem; @@ -53,6 +54,7 @@ private Q_SLOTS: private: GuiView & owner_; TextClass const * text_class_; + Inset const * inset_; }; diff --git a/src/insets/Inset.h b/src/insets/Inset.h index 4b03465e2e..42c5a6aa6d 100644 --- a/src/insets/Inset.h +++ b/src/insets/Inset.h @@ -286,9 +286,15 @@ public: /// returns true if the inset can hold an inset of given type virtual bool insetAllowed(InsetCode) const { return false; } - /// if this inset has paragraphs should they be output all as default - /// paragraphs with the default layout of the text class? - virtual bool forceDefaultParagraphs(idx_type) const { return false; } + /// should this inset use the empty layout by default rather than + /// the standard layout? (default: only if that is forced.) + virtual bool useEmptyLayout() const { return forceEmptyLayout(); } + /// if this inset has paragraphs should they be forced to use the + /// empty layout? + virtual bool forceEmptyLayout() const { return false; } + /// if this inset has paragraphs should the user be allowed to + /// customize alignment, etc? + virtual bool allowParagraphCustomization(idx_type) const { return true; } /// Is the width forced to some value? virtual bool hasFixedWidth() const { return false; } diff --git a/src/insets/InsetBox.cpp b/src/insets/InsetBox.cpp index cd4a1d62b8..2e04a4d93a 100644 --- a/src/insets/InsetBox.cpp +++ b/src/insets/InsetBox.cpp @@ -15,6 +15,7 @@ #include "InsetBox.h" #include "Buffer.h" +#include "BufferParams.h" #include "BufferView.h" #include "Cursor.h" #include "DispatchResult.h" @@ -25,6 +26,7 @@ #include "LaTeXFeatures.h" #include "Lexer.h" #include "MetricsInfo.h" +#include "TextClass.h" #include "support/Translator.h" @@ -85,7 +87,10 @@ BoxTranslatorLoc const & boxtranslator_loc() InsetBox::InsetBox(BufferParams const & bp, string const & label) : InsetCollapsable(bp), params_(label) -{} +{ + if (forceEmptyLayout()) + paragraphs().back().layout(bp.getTextClass().emptyLayout()); +} InsetBox::InsetBox(InsetBox const & in) @@ -173,7 +178,7 @@ void InsetBox::metrics(MetricsInfo & m, Dimension & dim) const } -bool InsetBox::forceDefaultParagraphs(idx_type) const +bool InsetBox::forceEmptyLayout() const { return !params_.inner_box; } diff --git a/src/insets/InsetBox.h b/src/insets/InsetBox.h index 3ae2c6946e..611647d6f3 100644 --- a/src/insets/InsetBox.h +++ b/src/insets/InsetBox.h @@ -79,8 +79,10 @@ public: bool showInsetDialog(BufferView * bv) const; /// DisplayType display() const { return Inline; } + //FIXME Is this the one we want? or is it: + //allowParagraphCustomization(idx_type)? /// - bool forceDefaultParagraphs(idx_type) const; + virtual bool forceEmptyLayout() const; /// bool neverIndent(Buffer const &) const { return true; } /// diff --git a/src/insets/InsetCaption.cpp b/src/insets/InsetCaption.cpp index aec5d2827e..e0a3d5555c 100644 --- a/src/insets/InsetCaption.cpp +++ b/src/insets/InsetCaption.cpp @@ -55,12 +55,16 @@ InsetCaption::InsetCaption(InsetCaption const & ic) setFrameColor(Color_captionframe); } + InsetCaption::InsetCaption(BufferParams const & bp) : InsetText(bp), textclass_(bp.getTextClass()) { setAutoBreakRows(true); setDrawFrame(true); setFrameColor(Color_captionframe); + //FIXME Do we need to set all paragraphs here? or will there + //always only be one? + paragraphs().back().layout(bp.getTextClass().emptyLayout()); } diff --git a/src/insets/InsetCaption.h b/src/insets/InsetCaption.h index f98c6b26e5..64301acfea 100644 --- a/src/insets/InsetCaption.h +++ b/src/insets/InsetCaption.h @@ -79,8 +79,10 @@ public: void setCustomLabel(docstring const & label); /// void addToToc(TocList &, Buffer const &, ParConstIterator const &) const; + /// + virtual bool forceEmptyLayout() const { return true; } /// Captions don't accept alignment, spacing, etc. - bool forceDefaultParagraphs(idx_type) const { return true; } + virtual bool allowParagraphCustomization(idx_type) const { return false; } private: /// diff --git a/src/insets/InsetCollapsable.cpp b/src/insets/InsetCollapsable.cpp index 051c4ed769..03de43e8c3 100644 --- a/src/insets/InsetCollapsable.cpp +++ b/src/insets/InsetCollapsable.cpp @@ -82,6 +82,7 @@ InsetCollapsable::InsetCollapsable(BufferParams const & bp, setAutoBreakRows(true); setDrawFrame(true); setFrameColor(Color_collapsableframe); + paragraphs().back().layout(bp.getTextClass().emptyLayout()); } diff --git a/src/insets/InsetCollapsable.h b/src/insets/InsetCollapsable.h index 26e29f7749..71dba17315 100644 --- a/src/insets/InsetCollapsable.h +++ b/src/insets/InsetCollapsable.h @@ -62,6 +62,8 @@ public: /// to name() void setLayout(TextClassPtr tc); /// + virtual bool useEmptyLayout() { return true; } + /// void read(Buffer const &, Lexer &); /// void write(Buffer const &, std::ostream &) const; @@ -157,6 +159,8 @@ public: virtual bool allowEmpty() const { return layout_->keepempty; } /// Force inset into LTR environment if surroundings are RTL? virtual bool forceLTR() const { return layout_->forceltr; } + /// + virtual bool useEmptyLayout() const { return true; } protected: /// diff --git a/src/insets/InsetERT.cpp b/src/insets/InsetERT.cpp index d419e136b2..763a448ec4 100644 --- a/src/insets/InsetERT.cpp +++ b/src/insets/InsetERT.cpp @@ -119,7 +119,7 @@ void InsetERT::doDispatch(Cursor & cur, FuncRequest & cmd) { BufferParams const & bp = cur.buffer().params(); LayoutPtr const layout = - bp.getTextClass().defaultLayout(); + bp.getTextClass().emptyLayout(); //lyxerr << "\nInsetERT::doDispatch (begin): cmd: " << cmd << endl; switch (cmd.action) { diff --git a/src/insets/InsetERT.h b/src/insets/InsetERT.h index 9a6577dcdc..05540aad27 100644 --- a/src/insets/InsetERT.h +++ b/src/insets/InsetERT.h @@ -67,8 +67,10 @@ public: /// bool showInsetDialog(BufferView *) const; /// - bool forceDefaultParagraphs(idx_type) const { return true; } - /// should paragraph indendation be ommitted in any case? + virtual bool forceEmptyLayout() const { return true; } + /// + virtual bool allowParagraphCustomization(idx_type) const { return false; } + /// should paragraph indendation be omitted in any case? bool neverIndent(Buffer const &) const { return true; } protected: InsetERT(InsetERT const &); diff --git a/src/insets/InsetFlex.h b/src/insets/InsetFlex.h index 7ea771bd9c..75c52bc02d 100644 --- a/src/insets/InsetFlex.h +++ b/src/insets/InsetFlex.h @@ -43,7 +43,7 @@ public: /// void read(Buffer const & buf, Lexer & lex); /// - bool forceDefaultParagraphs(idx_type) const { return true; } + virtual bool allowParagraphCustomization(idx_type) const { return false; } /// int plaintext(Buffer const &, odocstream &, diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 0c8ef364e7..09f0422ed2 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -484,7 +484,9 @@ Tabular::cellstruct::cellstruct(BufferParams const & bp) usebox(BOX_NONE), rotate(false), inset(new InsetText(bp)) -{} +{ + inset->paragraphs().back().layout(bp.getTextClass().emptyLayout()); +} Tabular::cellstruct::cellstruct(cellstruct const & cs) @@ -1090,7 +1092,7 @@ void toggleFixedWidth(Cursor & cur, InsetText * inset, bool fixedWidth) cur.push(*inset); // undo information has already been recorded inset->getText(0)->setLayout(cur.bv().buffer(), 0, cur.lastpit() + 1, - bp.getTextClass().defaultLayoutName()); + bp.getTextClass().emptyLayoutName()); cur.pop(); } @@ -4701,7 +4703,7 @@ void InsetTabular::rejectChanges(BufferParams const & bparams) } -bool InsetTabular::forceDefaultParagraphs(idx_type cell) const +bool InsetTabular::allowParagraphCustomization(idx_type cell) const { return tabular.getPWidth(cell).zero(); } diff --git a/src/insets/InsetTabular.h b/src/insets/InsetTabular.h index 677cf49e16..79bc8cea23 100644 --- a/src/insets/InsetTabular.h +++ b/src/insets/InsetTabular.h @@ -734,8 +734,9 @@ public: // this should return true if we have a "normal" cell, otherwise false. // "normal" means without width set! /// should all paragraphs be output with "Standard" layout? - bool forceDefaultParagraphs(idx_type cell = 0) const; - + virtual bool allowParagraphCustomization(idx_type cell = 0) const; + /// + virtual bool forceEmptyLayout() { return true; } /// void addPreview(graphics::PreviewLoader &) const; diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 3a8153a963..ecfe37be5c 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -69,7 +69,10 @@ InsetText::InsetText(BufferParams const & bp) : drawFrame_(false), frame_color_(Color_insetframe) { paragraphs().push_back(Paragraph()); - paragraphs().back().layout(bp.getTextClass().defaultLayout()); + if (useEmptyLayout()) + paragraphs().back().layout(bp.getTextClass().emptyLayout()); + else + paragraphs().back().layout(bp.getTextClass().defaultLayout()); init(); } diff --git a/src/output_latex.cpp b/src/output_latex.cpp index b0e42693aa..c6c9dcd0ea 100644 --- a/src/output_latex.cpp +++ b/src/output_latex.cpp @@ -108,7 +108,9 @@ TeXEnvironment(Buffer const & buf, BufferParams const & bparams = buf.params(); - LayoutPtr const & style = pit->layout(); + LayoutPtr const & style = pit->forceEmptyLayout() ? + bparams.getTextClass().emptyLayout() : + pit->layout(); ParagraphList const & paragraphs = text.paragraphs(); @@ -284,7 +286,6 @@ TeXOnePar(Buffer const & buf, LYXERR(Debug::LATEX, "TeXOnePar... " << &*pit << " '" << everypar << "'"); BufferParams const & bparams = buf.params(); - LayoutPtr style; ParagraphList const & paragraphs = text.paragraphs(); if (runparams_in.verbatim) { @@ -303,12 +304,14 @@ TeXOnePar(Buffer const & buf, return ++pit; } + // FIXME This comment doesn't make sense. What's the + // length got to do with forceEmptyLayout()? I.e., what + // was forceDefaultParagraphs()? // In an inset with unlimited length (all in one row), // force layout to default - if (!pit->forceDefaultParagraphs()) - style = pit->layout(); - else - style = bparams.getTextClass().defaultLayout(); + LayoutPtr const style = pit->forceEmptyLayout() ? + bparams.getTextClass().emptyLayout() : + pit->layout(); OutputParams runparams = runparams_in; runparams.moving_arg |= style->needprotect; @@ -476,10 +479,8 @@ TeXOnePar(Buffer const & buf, } } - // In an inset with unlimited length (all in one row), - // don't allow any special options in the paragraph bool const useSetSpace = bparams.getTextClass().provides("SetSpace"); - if (!pit->forceDefaultParagraphs()) { + if (pit->allowParagraphCustomization()) { if (pit->params().startOfAppendix()) { os << "\\appendix\n"; texrow.newline(); @@ -590,7 +591,7 @@ TeXOnePar(Buffer const & buf, pending_newline = true; } - if (!pit->forceDefaultParagraphs()) { + if (pit->allowParagraphCustomization()) { if (!pit->params().spacing().isDefault() && (boost::next(pit) == paragraphs.end() || !boost::next(pit)->hasSameLayout(*pit))) @@ -791,8 +792,10 @@ void latexParagraphs(Buffer const & buf, // any special options in the paragraph and also we don't allow // any environment other than the default layout of the // text class to be valid! - if (!par->forceDefaultParagraphs()) { - LayoutPtr const & layout = par->layout(); + if (par->allowParagraphCustomization()) { + LayoutPtr const & layout = par->forceEmptyLayout() ? + tclass.emptyLayout() : + par->layout(); if (layout->intitle) { if (already_title) { diff --git a/src/paragraph_funcs.cpp b/src/paragraph_funcs.cpp index 2f87daf5b5..6313d5e2cc 100644 --- a/src/paragraph_funcs.cpp +++ b/src/paragraph_funcs.cpp @@ -73,7 +73,10 @@ void breakParagraph(BufferParams const & bparams, // without doing that we get a crash when typing at the // end of a paragraph - tmp->layout(bparams.getTextClass().defaultLayout()); + if (par.useEmptyLayout()) + tmp->layout(bparams.getTextClass().emptyLayout()); + else + tmp->layout(bparams.getTextClass().defaultLayout()); // remember to set the inset_owner tmp->setInsetOwner(par.inInset()); -- 2.39.2