The attached patch is now pretty much complete, I think, so I'm sending it again to the list.

The basic idea has two parts. First, we hard code an "empty layout"
(called LyXDefault, 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.

The one remaining issue has to do with sorting, but I think there may be some issues with that code, anyway, since it seems to assume that the default layout will always appear first, and I'm not sure why that would have to be true.

Comments of course welcome. Better yet, fixes.

rh


Index: src/TextClass.h
===================================================================
--- src/TextClass.h	(revision 22792)
+++ src/TextClass.h	(working copy)
@@ -109,7 +109,14 @@
 	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;
 	///
 	docstring const & labelstring() const;
@@ -200,6 +207,8 @@
 	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.
Index: src/TextClass.cpp
===================================================================
--- src/TextClass.cpp	(revision 22792)
+++ src/TextClass.cpp	(working copy)
@@ -34,6 +34,7 @@
 #include "support/os.h"
 
 #include <sstream>
+#include <strstream>
 
 using namespace std;
 using namespace lyx::support;
@@ -111,6 +112,9 @@
 }
 
 
+docstring const TextClass::emptylayout_ = from_ascii("LyXDefault");
+
+
 bool TextClass::isTeXClassAvailable() const
 {
 	return texClassAvail_;
@@ -214,6 +218,27 @@
 	}
 	LYXERR(Debug::TCLASS, 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<Layout>(new Layout(lay)));
+	}
+
 	Lexer lexrc(textClassTags,
 		sizeof(textClassTags) / sizeof(textClassTags[0]));
 
@@ -483,7 +508,6 @@
 		}
 		LYXERR(Debug::TCLASS, "Minimum TocLevel is " << min_toclevel_
 			<< ", maximum is " << max_toclevel_);
-
 	}
 
 	return error;
@@ -1028,7 +1052,7 @@
 
 bool TextClass::deleteLayout(docstring const & name)
 {
-	if (name == defaultLayoutName())
+	if (name == defaultLayoutName() || name == emptyLayoutName())
 		return false;
 
 	LayoutList::iterator it =
Index: src/frontends/qt4/GuiToolbar.h
===================================================================
--- src/frontends/qt4/GuiToolbar.h	(revision 22792)
+++ src/frontends/qt4/GuiToolbar.h	(working copy)
@@ -24,6 +24,7 @@
 
 namespace lyx {
 
+class Inset;
 class TextClass;
 class ToolbarItem;
 
@@ -53,6 +54,7 @@
 private:
 	GuiView & owner_;
 	TextClass const * text_class_;
+	Inset const * inset_;
 };
 
 
Index: src/frontends/qt4/GuiToolbar.cpp
===================================================================
--- src/frontends/qt4/GuiToolbar.cpp	(revision 22792)
+++ src/frontends/qt4/GuiToolbar.cpp	(working copy)
@@ -304,16 +304,23 @@
 		clear();
 		setEnabled(false);
 		text_class_ = 0;
+		inset_ = 0;
 		return;
 	}
 
 	setEnabled(true);
 	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;
 
 	setUpdatesEnabled(false);
@@ -321,9 +328,21 @@
 
 	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);
+	}
+
 	setCurrentIndex(0);
 
 	// needed to recalculate size hint
Index: src/insets/InsetBox.h
===================================================================
--- src/insets/InsetBox.h	(revision 22792)
+++ src/insets/InsetBox.h	(working copy)
@@ -79,8 +79,10 @@
 	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; }
 	///
Index: src/insets/InsetBox.cpp
===================================================================
--- src/insets/InsetBox.cpp	(revision 22792)
+++ src/insets/InsetBox.cpp	(working copy)
@@ -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 @@
 
 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 @@
 }
 
 
-bool InsetBox::forceDefaultParagraphs(idx_type) const
+bool InsetBox::forceEmptyLayout() const
 {
 	return !params_.inner_box;
 }
Index: src/insets/InsetCaption.h
===================================================================
--- src/insets/InsetCaption.h	(revision 22792)
+++ src/insets/InsetCaption.h	(working copy)
@@ -81,8 +81,10 @@
 	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:
 	///
Index: src/insets/InsetCaption.cpp
===================================================================
--- src/insets/InsetCaption.cpp	(revision 22792)
+++ src/insets/InsetCaption.cpp	(working copy)
@@ -47,6 +47,7 @@
 namespace lyx {
 
 
+//FIXME Should this be set to empty layout? 
 InsetCaption::InsetCaption(InsetCaption const & ic)
 	: InsetText(ic), textclass_(ic.textclass_)
 {
@@ -61,6 +62,7 @@
 	setAutoBreakRows(true);
 	setDrawFrame(true);
 	setFrameColor(Color_captionframe);
+	paragraphs().back().layout(bp.getTextClass().emptyLayout());
 }
 
 
Index: src/insets/InsetCollapsable.h
===================================================================
--- src/insets/InsetCollapsable.h	(revision 22792)
+++ src/insets/InsetCollapsable.h	(working copy)
@@ -62,6 +62,8 @@
 	/// 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 @@
 	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:
 	///
Index: src/insets/InsetCollapsable.cpp
===================================================================
--- src/insets/InsetCollapsable.cpp	(revision 22792)
+++ src/insets/InsetCollapsable.cpp	(working copy)
@@ -82,6 +82,7 @@
 	setAutoBreakRows(true);
 	setDrawFrame(true);
 	setFrameColor(Color_collapsableframe);
+	paragraphs().back().layout(bp.getTextClass().emptyLayout());
 }
 
 
Index: src/insets/InsetERT.h
===================================================================
--- src/insets/InsetERT.h	(revision 22792)
+++ src/insets/InsetERT.h	(working copy)
@@ -67,8 +67,10 @@
 	///
 	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 &);
Index: src/insets/InsetERT.cpp
===================================================================
--- src/insets/InsetERT.cpp	(revision 22792)
+++ src/insets/InsetERT.cpp	(working copy)
@@ -119,7 +119,7 @@
 {
 	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) {
 
Index: src/insets/InsetFlex.h
===================================================================
--- src/insets/InsetFlex.h	(revision 22792)
+++ src/insets/InsetFlex.h	(working copy)
@@ -43,7 +43,7 @@
 	///
 	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 &,
Index: src/insets/Inset.h
===================================================================
--- src/insets/Inset.h	(revision 22792)
+++ src/insets/Inset.h	(working copy)
@@ -278,9 +278,15 @@
 
 	/// 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; }
 
Index: src/insets/InsetTabular.h
===================================================================
--- src/insets/InsetTabular.h	(revision 22792)
+++ src/insets/InsetTabular.h	(working copy)
@@ -734,9 +734,10 @@
 	// 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;
 
 	///
Index: src/insets/InsetTabular.cpp
===================================================================
--- src/insets/InsetTabular.cpp	(revision 22792)
+++ src/insets/InsetTabular.cpp	(working copy)
@@ -483,7 +483,9 @@
 	  usebox(BOX_NONE),
 	  rotate(false),
 	  inset(new InsetText(bp))
-{}
+{
+	inset->paragraphs().back().layout(bp.getTextClass().emptyLayout());
+}
 
 
 Tabular::cellstruct::cellstruct(cellstruct const & cs)
@@ -1089,7 +1091,7 @@
 	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();
 }
 
@@ -4700,7 +4702,7 @@
 }
 
 
-bool InsetTabular::forceDefaultParagraphs(idx_type cell) const
+bool InsetTabular::allowParagraphCustomization(idx_type cell) const
 {
 	return tabular.getPWidth(cell).zero();
 }
Index: src/insets/InsetText.cpp
===================================================================
--- src/insets/InsetText.cpp	(revision 22792)
+++ src/insets/InsetText.cpp	(working copy)
@@ -69,7 +69,10 @@
 	: 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();
 }
 
Index: src/BufferView.cpp
===================================================================
--- src/BufferView.cpp	(revision 22792)
+++ src/BufferView.cpp	(working copy)
@@ -877,7 +877,7 @@
 
 	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: {
Index: src/CutAndPaste.cpp
===================================================================
--- src/CutAndPaste.cpp	(revision 22792)
+++ src/CutAndPaste.cpp	(working copy)
@@ -143,11 +143,12 @@
 		}
 	}
 
-	// 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 @@
 }
 
 
-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 @@
 		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"),
Index: src/output_latex.cpp
===================================================================
--- src/output_latex.cpp	(revision 22792)
+++ src/output_latex.cpp	(working copy)
@@ -108,7 +108,9 @@
 
 	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 @@
 	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 @@
 		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 @@
 		}
 	}
 
-	// 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 @@
 			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 @@
 		// 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) {
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp	(revision 22792)
+++ src/Paragraph.cpp	(working copy)
@@ -1605,12 +1605,24 @@
 }
 
 
-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();
+}
+
+
 namespace {
 
 // paragraphs inside floats need different alignment tags to avoid
@@ -1809,7 +1821,7 @@
 	// 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();
Index: src/paragraph_funcs.cpp
===================================================================
--- src/paragraph_funcs.cpp	(revision 22792)
+++ src/paragraph_funcs.cpp	(working copy)
@@ -73,7 +73,10 @@
 
 	// without doing that we get a crash when typing <Return> 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());
 
Index: src/Paragraph.h
===================================================================
--- src/Paragraph.h	(revision 22792)
+++ src/Paragraph.h	(working copy)
@@ -145,9 +145,12 @@
 	///
 	InsetCode ownerCode() const;
 	///
-	bool forceDefaultParagraphs() const;
-
+	bool forceEmptyLayout() const;
 	///
+	bool allowParagraphCustomization() const;
+	///
+	bool useEmptyLayout() const;
+	///
 	pos_type size() const;
 	///
 	bool empty() const;
Index: src/Text3.cpp
===================================================================
--- src/Text3.cpp	(revision 22792)
+++ src/Text3.cpp	(working copy)
@@ -215,6 +215,7 @@
 			if (insetText && !insetText->allowMultiPar() 
 			    || cur.lastpit() == 0) {
 				// reset first par to default
+				//FIXME Check if this should be emptyLayout() in some cases.
 				LayoutPtr const layout =
 					cur.buffer().params().getTextClass().defaultLayout();
 				cur.text()->paragraphs().begin()->layout(layout);
@@ -227,6 +228,7 @@
 				}
 			} else {
 				// reset surrounding par to default
+				//FIXME Check if this should be emptyLayout() in some cases.
 				docstring const layoutname = 
 					cur.buffer().params().getTextClass().defaultLayoutName();
 				cur.leaveInset(*inset);
@@ -990,16 +992,35 @@
 		break;
 
 	case LFUN_LAYOUT: {
+		//FIXME Need to check forceEmptyLayout() etc here.
+		//
+		//
 		docstring layout = cmd.argument();
 		LYXERR(Debug::INFO, "LFUN_LAYOUT: (arg) " << to_utf8(layout));
 
-		docstring const old_layout = cur.paragraph().layout()->name();
+		Paragraph const & para = cur.paragraph();
+		docstring const old_layout = para.layout()->name();
+		Inset * inset = para.inInset();
+		TextClass const & tclass = bv->buffer().params().getTextClass();
 
-		// Derive layout number from given argument (string)
-		// and current buffer's textclass (number)
-		TextClass const & tclass = bv->buffer().params().getTextClass();
 		if (layout.empty())
 			layout = tclass.defaultLayoutName();
+
+		if (inset) {
+			if (inset->forceEmptyLayout()) 
+				// in this case only the empty layout is allowed
+				layout = tclass.emptyLayoutName();
+			else if (inset->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.
@@ -1363,6 +1384,7 @@
 		// add a separate paragraph for the caption inset
 		pars.push_back(Paragraph());
 		pars.back().setInsetOwner(pars[0].inInset());
+		//FIXME Check if this should be emptyLayout()
 		pars.back().layout(tclass.defaultLayout());
 
 		int cap_pit = pars.size() - 1;
@@ -1373,6 +1395,7 @@
 		if (!content) {
 			pars.push_back(Paragraph());
 			pars.back().setInsetOwner(pars[0].inInset());
+		//FIXME Check if this should be emptyLayout()
 			pars.back().layout(tclass.defaultLayout());
 
 		}
@@ -1618,7 +1641,8 @@
 		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<string>(accept) + '\n' + data;
 		bv->updateDialog("paragraph", data);
@@ -1661,6 +1685,7 @@
 				breakParagraph(cur);
 			}
 
+			//FIXME Check if this should be emptyLayout()
 			setLayout(cur, tclass.defaultLayoutName());
 			ParagraphParameters p;
 			setParagraphs(cur, p);
Index: src/Text.cpp
===================================================================
--- src/Text.cpp	(revision 22792)
+++ src/Text.cpp	(working copy)
@@ -103,16 +103,33 @@
 
 		TextClass const & tclass = bp.getTextClass();
 
-		if (layoutname.empty()) {
+		Inset * inset = par.inInset();
+
+		if (layoutname.empty())
 			layoutname = tclass.defaultLayoutName();
+
+		if (inset) {
+			if (inset->forceEmptyLayout()) 
+				// in this case only the empty layout is allowed
+				layoutname = tclass.emptyLayoutName();
+			else if (inset->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);
 
 		if (!hasLayout) {
 			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()));
+			//FIXME Check if this should be emptyLayout() in some cases
 			layoutname = tclass.defaultLayoutName();
 		}
 
@@ -388,9 +405,11 @@
 	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());
 	}
 
@@ -888,8 +907,8 @@
 			cur.updateFlags(Update::Force);
 		// if not, reset the paragraph to default
 		} else
-			cur.paragraph().layout(
-				bufparams.getTextClass().defaultLayout());
+			//FIXME Check if this should be emptyLayout() in some cases
+			cur.paragraph().layout(bufparams.getTextClass().defaultLayout());
 		return true;
 	}
 	return false;
@@ -974,8 +993,10 @@
 	// 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;
Index: src/TextMetrics.cpp
===================================================================
--- src/TextMetrics.cpp	(revision 22792)
+++ src/TextMetrics.cpp	(working copy)
@@ -1701,6 +1701,7 @@
 			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();
@@ -1822,7 +1823,7 @@
 	    && !(!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))
 	{

Reply via email to