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.