Abdelrazak Younes wrote:
Whenever I set the cursor inside a caption or an index, I get this message: "Trying to select non existent layout type Standard".
OK, here's the problem. It used to be that things like InsetFlex, InsetCaption, and the like used the default layout, whatever that is---usually Standard. That gave rise to bug 2178, the solution to which is to define a new empty layout, which insets like these use instead of the default.

So, when we have an older LyX file, it will look like this:
\begin_inset ERT
status open

\begin_layout Standard

this that
\end_layout

\end_inset
which is now invalid, because ERT uses only PlainLayout. So one possibility would be to write some lyx2lyx that would deal with this conversion. And maybe that's the way to go, though that might be complicated, since one would have to convert the layouts only inside certain insets, etc, and insets can be nested, which might make this hard to do right. It also seems worth making sure as we read the file that insets all have layouts that are valid for them. If so, then we need to do something else anyway.

So I put some code into Text::readParToken, where the layout for a paragraph gets set as it is read. We already had this:
       if (layoutname.empty())
           layoutname = tclass.defaultLayoutName();
So I added this:
       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();
       }
The idea here it to reset the default layout to the empty layout when that is needed, and conversely. Unfortunately, this turns out not to work. (I missed that.) The reason is that par.forceEmptyLayout() and par.useEmptyLayout() always return false here, because par.inInset() always returns a null pointer, because the paragraph's inset hasn't yet been set when Text::readParagraph() gets called from Text::read() gets called from InsetText::read(). The paragraph's containing inset only gets set when we return and call InsetText::init()---see InsetText.cpp, line 148.

I can see two solutions: (i) Add something equivalent to the code above to InsetText::init(); (ii) the patch that is attached. As a bonus, the patch allows us to fix up this strange code:
   bool const res = text().reads(*this, lex, errorList);
   for_each(text().paragraphs().begin(),
        text().paragraphs().end(),
        bind(&Paragraph::setInsetOwner, _1, &inset()));
in Buffer::readDocument(). Why should Buffer be setting the owner of these paragraphs?

I've tested this and it does the job, but I'd appreciate comments on the approach here.

rh

Index: insets/InsetText.h
===================================================================
--- insets/InsetText.h	(revision 23025)
+++ insets/InsetText.h	(working copy)
@@ -40,6 +40,8 @@
 	explicit InsetText(BufferParams const &);
 	///
 	InsetText();
+	///
+	InsetText(InsetText const &);
 
 	///
 	Dimension const dimension(BufferView const &) const;
@@ -133,8 +135,6 @@
 	virtual bool isMacroScope(Buffer const &) const { return true; }
 	///
 	virtual bool allowMultiPar() const { return true; }
-	///
-	InsetText(InsetText const &);
 
 	// Update the counters of this inset and of its contents
 	virtual void updateLabels(Buffer const &, ParIterator const &);
@@ -147,8 +147,7 @@
 
 private:
 	///
-	void init();
-
+	void setParagraphOwner();
 	///
 	bool drawFrame_;
 	///
Index: insets/InsetText.cpp
===================================================================
--- insets/InsetText.cpp	(revision 23025)
+++ insets/InsetText.cpp	(working copy)
@@ -69,11 +69,12 @@
 	: drawFrame_(false), frame_color_(Color_insetframe)
 {
 	paragraphs().push_back(Paragraph());
+	Paragraph & ourpar = paragraphs().back();
 	if (useEmptyLayout())
-		paragraphs().back().layout(bp.getTextClass().emptyLayout());
+		ourpar.layout(bp.getTextClass().emptyLayout());
 	else
-		paragraphs().back().layout(bp.getTextClass().defaultLayout());
-	init();
+		ourpar.layout(bp.getTextClass().defaultLayout());
+	ourpar.setInsetOwner(this);
 }
 
 
@@ -84,7 +85,7 @@
 	drawFrame_ = in.drawFrame_;
 	frame_color_ = in.frame_color_;
 	text_.paragraphs() = in.text_.paragraphs();
-	init();
+	setParagraphOwner();
 }
 
 
@@ -92,7 +93,7 @@
 {}
 
 
-void InsetText::init()
+void InsetText::setParagraphOwner()
 {
 	for_each(paragraphs().begin(), paragraphs().end(),
 		 bind(&Paragraph::setInsetOwner, _1, this));
@@ -145,8 +146,7 @@
 	Paragraph oldpar = *paragraphs().begin();
 	paragraphs().clear();
 	ErrorList errorList;
-	bool res = text_.read(buf, lex, errorList);
-	init();
+	bool res = text_.read(buf, lex, errorList, this);
 
 	if (!res) {
 		lex.printError("Missing \\end_inset at this point. "
Index: Text.cpp
===================================================================
--- Text.cpp	(revision 23025)
+++ Text.cpp	(working copy)
@@ -106,10 +106,10 @@
 		if (layoutname.empty())
 			layoutname = tclass.defaultLayoutName();
 
-		if (par.forceEmptyLayout()) 
+		if (par.forceEmptyLayout()) {
 			// in this case only the empty layout is allowed
 			layoutname = tclass.emptyLayoutName();
-		else if (par.useEmptyLayout()) {
+		} else if (par.useEmptyLayout()) {
 			// in this case, default layout maps to empty layout 
 			if (layoutname == tclass.defaultLayoutName())
 				layoutname = tclass.emptyLayoutName();
@@ -1164,7 +1164,8 @@
 }
 
 
-bool Text::read(Buffer const & buf, Lexer & lex, ErrorList & errorList)
+bool Text::read(Buffer const & buf, Lexer & lex, 
+		ErrorList & errorList, Inset * insetPtr)
 {
 	depth_type depth = 0;
 
@@ -1193,6 +1194,7 @@
 			Paragraph par;
 			par.params().depth(depth);
 			par.setFont(0, Font(inherit_font, buf.params().language));
+			par.setInsetOwner(insetPtr);
 			pars_.push_back(par);
 
 			// FIXME: goddamn InsetTabular makes us pass a Buffer
Index: paragraph_funcs.cpp
===================================================================
--- paragraph_funcs.cpp	(revision 23025)
+++ paragraph_funcs.cpp	(working copy)
@@ -71,14 +71,14 @@
 
 	Paragraph & par = pars[par_offset];
 
+	// remember to set the inset_owner
+	tmp->setInsetOwner(par.inInset());
 	// without doing that we get a crash when typing <Return> at the
 	// end of a paragraph
 	if (par.useEmptyLayout())
 		tmp->layout(bparams.getTextClass().emptyLayout());
 	else
 		tmp->layout(bparams.getTextClass().defaultLayout());
-	// remember to set the inset_owner
-	tmp->setInsetOwner(par.inInset());
 
 	// layout stays the same with latex-environments
 	if (keep_layout) {
Index: Buffer.cpp
===================================================================
--- Buffer.cpp	(revision 23025)
+++ Buffer.cpp	(working copy)
@@ -567,10 +567,7 @@
 	}
 
 	// read main text
-	bool const res = text().read(*this, lex, errorList);
-	for_each(text().paragraphs().begin(),
-		 text().paragraphs().end(),
-		 bind(&Paragraph::setInsetOwner, _1, &inset()));
+	bool const res = text().read(*this, lex, errorList, &inset());
 
 	updateMacros();
 	updateMacroInstances();
Index: Text.h
===================================================================
--- Text.h	(revision 23025)
+++ Text.h	(working copy)
@@ -259,7 +259,13 @@
 	///
 	void write(Buffer const & buf, std::ostream & os) const;
 	/// returns whether we've seen our usual 'end' marker
-	bool read(Buffer const & buf, Lexer & lex, ErrorList & errorList);
+	/// insetPtr is the containing Inset
+	/// FIXME This should really take an InsetText, but it can't yet
+	/// do so because Buffer::inset() returns an Inset and we have no
+	/// access to the InsetText hidden away in Buffer::Impl. This is 
+	/// easy enough to fix but will have to wait a bit.
+	bool read(Buffer const & buf, Lexer & lex, ErrorList & errorList, 
+	          Inset * insetPtr);
 
 	/// delete double spaces, leading spaces, and empty paragraphs around old cursor.
 	/// \retval true if a change has happened and we need a redraw.

Reply via email to