Regarding the x2.patch, the problem is that par_iterator_begin() does
not give us a "complete" DocIterator (one starting with the Buffer's own
InsetText, etc), which is what we need. I am constantly running into
this problem!
Regarding the other patch, adding the code to InsetText just seemed like
the easiest way to get the recursion going. Other ways would be fine
with me.
But I think there are some problems in the original code about how the
macro context is set. What the usual calls to updateBuffer() do is
always make the macro context a ParIterator that points to the first
paragraph in the current inset. (See e.g. the calls at
InsetText:682,695.) The existing code sets it to the first paragraph of
the *original* inset---the one that gets split or whatever---which just
seems like it has to be wrong.
In trying to fix both these issues, I found out that
cellInset(cell)->getText(0)->macrocontextPosition()
is actually an EMPTY DocIterator. This is likely due to the fact that
the Buffer has been cloned (at least here). That seems like an
independent problem and one that very much needs to be fixed. It's easy
to do that by adding an updateBuffer() call to the makeLaTeXFile()
routine, and it seems like a good idea to do that anyway, even if we're
not cloning the Buffer. The point is that, if you enter a footnote, say,
and then View>PDF, there won't be an updateBuffer() call before then,
and there probably needs to be.
So I'm attaching a few patches:
1. updateBuffer.diff solves the general problem mentioned.
2. x2a.patch is what seems to be a working version of x2.patch.
3. x3a.diff, which is a version of x3.patch that fixes the problem in
the old code.
I'm not sure what I prefer here, but (1) seems necessary no matter what.
I guess (3) is more cautious, and if there aren't other issues for which
(2) is needed, maybe that's what makes sense.
Richard
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp (revision 38484)
+++ src/Buffer.cpp (working copy)
@@ -1346,7 +1346,9 @@
// Don't move this behind the parent_buffer=0 code below,
// because then the macros will not get the right "redefinition"
// flag as they don't see the parent macros which are output before.
- updateMacros();
+ // NOTE This probably should be an OutputUpdate, but that is not
+ // significant at the moment for LaTeX.
+ updateBuffer(UpdateMaster, InternalUpdate);
// fold macros if possible, still with parent buffer as the
// macros will be put in the prefix anyway.
Index: src/insets/InsetTabular.cpp
===================================================================
--- src/insets/InsetTabular.cpp (revision 38484)
+++ src/insets/InsetTabular.cpp (working copy)
@@ -522,7 +522,7 @@
DocIterator dit = doc_iterator_begin(&head.buffer(), &head);
for (; dit; dit.forwardChar())
- if (dit.inTexted() && dit.depth()==1
+ if (dit.inTexted() && dit.depth() == 1
&& dit.paragraph().find(align_d, false, false, dit.pos()))
break;
@@ -2484,14 +2484,19 @@
&& cellInfo(cell).decimal_width != 0) {
// copy cell and split in 2
InsetTableCell head = InsetTableCell(*cellInset(cell).get());
- head.getText(0)->setMacrocontextPosition(
- cellInset(cell)->getText(0)->macrocontextPosition());
head.setBuffer(buffer());
+ DocIterator dit = cellInset(cell)->getText(0)->macrocontextPosition();
+ dit.pop_back();
+ dit.push_back(CursorSlice (head));
+ ParIterator pit(dit);
+ buffer().updateBuffer(pit, OutputUpdate);
bool hassep = false;
InsetTableCell tail = splitCell(head, column_info[c].decimal_point, hassep);
- tail.getText(0)->setMacrocontextPosition(
- head.getText(0)->macrocontextPosition());
- tail.setBuffer(head.buffer());
+ tail.setBuffer(buffer());
+ dit.pop_back();
+ dit.push_back(CursorSlice(tail));
+ pit = ParIterator(dit);
+ buffer().updateBuffer(pit, OutputUpdate);
head.latex(os, newrp);
os << '&';
tail.latex(os, newrp);
@@ -3465,30 +3470,37 @@
mi.base.bv->textMetrics(tabular.cellInset(cell)->getText(0));
// determine horizontal offset because of decimal align (if necessary)
- int decimal_hoffset = 0;
int decimal_width = 0;
if (tabular.getAlignment(cell) == LYX_ALIGN_DECIMAL) {
- // make a copy which we will split in 2
- InsetTableCell head = InsetTableCell(*tabular.cellInset(cell).get());
- head.getText(0)->setMacrocontextPosition(
- tabular.cellInset(cell)->getText(0)->macrocontextPosition());
- head.setBuffer(tabular.buffer());
- // split in 2 and calculate width of each part
- bool hassep = false;
- InsetTableCell tail =
- splitCell(head, tabular.column_info[c].decimal_point, hassep);
- tail.getText(0)->setMacrocontextPosition(
- head.getText(0)->macrocontextPosition());
- tail.setBuffer(head.buffer());
- Dimension dim1;
- head.metrics(m, dim1);
- decimal_hoffset = dim1.width();
- if (hassep) {
+ InsetTableCell tail = InsetTableCell(*tabular.cellInset(cell).get());
+ tail.setBuffer(tabular.buffer());
+ // we need to set macrocontext position everywhere
+ // otherwise we crash with nested insets (e.g. footnotes)
+ // after decimal point
+ DocIterator dit = tabular.cellInset(cell)->getText(0)->macrocontextPosition();
+ dit.pop_back();
+ dit.push_back(CursorSlice(tail));
+ ParIterator pit(dit);
+ buffer().updateBuffer(pit, OutputUpdate);
+
+ // remove text leading decimal point
+ docstring const align_d = tabular.column_info[c].decimal_point;
+ dit = doc_iterator_begin(&tail.buffer(), &tail);
+ for (; dit; dit.forwardChar())
+ if (dit.inTexted() && dit.depth() == 1
+ && dit.paragraph().find(align_d, false, false, dit.pos()))
+ break;
+
+ pit_type const psize = tail.paragraphs().front().size();
+ if (dit) {
+ tail.paragraphs().front().eraseChars(0,
+ dit.pos() < psize ? dit.pos() + 1 : psize, false);
+ Dimension dim1;
tail.metrics(m, dim1);
decimal_width = dim1.width();
}
}
- tabular.cell_info[r][c].decimal_hoffset = decimal_hoffset;
+ tabular.cell_info[r][c].decimal_hoffset = tm.width() - decimal_width;
tabular.cell_info[r][c].decimal_width = decimal_width;
// with LYX_VALIGN_BOTTOM the descent is relative to the last par
Index: src/insets/InsetTabular.cpp
===================================================================
--- src/insets/InsetTabular.cpp (revision 38484)
+++ src/insets/InsetTabular.cpp (working copy)
@@ -2484,14 +2484,17 @@
&& cellInfo(cell).decimal_width != 0) {
// copy cell and split in 2
InsetTableCell head = InsetTableCell(*cellInset(cell).get());
- head.getText(0)->setMacrocontextPosition(
- cellInset(cell)->getText(0)->macrocontextPosition());
head.setBuffer(buffer());
+ DocIterator dit = cellInset(cell)->getText(0)->macrocontextPosition();
+ dit.pop_back();
+ dit.push_back(CursorSlice(head));
+ head.setMacrocontextPositionRecursive(dit);
bool hassep = false;
InsetTableCell tail = splitCell(head, column_info[c].decimal_point, hassep);
- tail.getText(0)->setMacrocontextPosition(
- head.getText(0)->macrocontextPosition());
tail.setBuffer(head.buffer());
+ dit.pop_back();
+ dit.push_back(CursorSlice(tail));
+ tail.setMacrocontextPositionRecursive(dit);
head.latex(os, newrp);
os << '&';
tail.latex(os, newrp);
@@ -3465,30 +3468,36 @@
mi.base.bv->textMetrics(tabular.cellInset(cell)->getText(0));
// determine horizontal offset because of decimal align (if necessary)
- int decimal_hoffset = 0;
int decimal_width = 0;
if (tabular.getAlignment(cell) == LYX_ALIGN_DECIMAL) {
- // make a copy which we will split in 2
- InsetTableCell head = InsetTableCell(*tabular.cellInset(cell).get());
- head.getText(0)->setMacrocontextPosition(
- tabular.cellInset(cell)->getText(0)->macrocontextPosition());
- head.setBuffer(tabular.buffer());
- // split in 2 and calculate width of each part
- bool hassep = false;
- InsetTableCell tail =
- splitCell(head, tabular.column_info[c].decimal_point, hassep);
- tail.getText(0)->setMacrocontextPosition(
- head.getText(0)->macrocontextPosition());
- tail.setBuffer(head.buffer());
- Dimension dim1;
- head.metrics(m, dim1);
- decimal_hoffset = dim1.width();
- if (hassep) {
+ InsetTableCell tail = InsetTableCell(*tabular.cellInset(cell).get());
+ tail.setBuffer(tabular.buffer());
+ // we need to set macrocontext position everywhere
+ // otherwise we crash with nested insets (e.g. footnotes)
+ // after decimal point
+ DocIterator dit = tabular.cellInset(cell)->getText(0)->macrocontextPosition();
+ dit.pop_back();
+ dit.push_back(CursorSlice(tail));
+ tail.setMacrocontextPositionRecursive(dit);
+
+ // remove text leading decimal point
+ docstring const align_d = tabular.column_info[c].decimal_point;
+ dit = doc_iterator_begin(&tail.buffer(), &tail);
+ for (; dit; dit.forwardChar())
+ if (dit.inTexted() && dit.depth()==1
+ && dit.paragraph().find(align_d, false, false, dit.pos()))
+ break;
+
+ pit_type const psize = tail.paragraphs().front().size();
+ if (dit) {
+ tail.paragraphs().front().eraseChars(0,
+ dit.pos() < psize ? dit.pos() + 1 : psize, false);
+ Dimension dim1;
tail.metrics(m, dim1);
decimal_width = dim1.width();
}
}
- tabular.cell_info[r][c].decimal_hoffset = decimal_hoffset;
+ tabular.cell_info[r][c].decimal_hoffset = tm.width() - decimal_width;
tabular.cell_info[r][c].decimal_width = decimal_width;
// with LYX_VALIGN_BOTTOM the descent is relative to the last par
Index: src/insets/InsetText.cpp
===================================================================
--- src/insets/InsetText.cpp (revision 38484)
+++ src/insets/InsetText.cpp (working copy)
@@ -99,6 +99,26 @@
}
+void InsetText::setMacrocontextPositionRecursive(DocIterator const & pos)
+{
+ text_.setMacrocontextPosition(pos);
+
+ ParagraphList::const_iterator pit = paragraphs().begin();
+ ParagraphList::const_iterator pend = paragraphs().end();
+ for (; pit != pend; ++pit) {
+ InsetList::const_iterator iit = pit->insetList().begin();
+ InsetList::const_iterator end = pit->insetList().end();
+ for (; iit != end; ++iit) {
+ if (InsetText * txt = iit->inset->asInsetText()) {
+ DocIterator ppos(pos);
+ ppos.push_back(CursorSlice(*txt));
+ iit->inset->asInsetText()->setMacrocontextPositionRecursive(ppos);
+ }
+ }
+ }
+}
+
+
void InsetText::clear()
{
ParagraphList & pars = paragraphs();
Index: src/insets/InsetText.h
===================================================================
--- src/insets/InsetText.h (revision 38484)
+++ src/insets/InsetText.h (working copy)
@@ -164,6 +164,8 @@
/// Update the counters of this inset and of its contents
virtual void updateBuffer(ParIterator const &, UpdateType);
///
+ void setMacrocontextPositionRecursive(DocIterator const & pos);
+ ///
void toString(odocstream &) const;
///
void forToc(docstring &, size_t) const;