From c7cb9fdc43b82127622564710abe7b0850c17c1c Mon Sep 17 00:00:00 2001 From: Richard Heck Date: Mon, 25 Apr 2011 12:56:09 +0000 Subject: [PATCH] Fix crash when there are text insets in a table cell with decimal alignment. This is discussed in these threads: http://marc.info/?t=115869271700002&r=1&w=2&n=5 http://marc.info/?t=130349942500005&r=1&w=2&n=17 This is the simpler and more conservative of the two solutions proposed. It is possible, however, that we need the more complicated one, which is in x2a.patch here: http://marc.info/?l=lyx-devel&m=130359169107401&q=p4 Both patches contain work by me and Edwin. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@38496 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/insets/InsetTabular.cpp | 53 ++++++++++++++++++++++--------------- src/insets/InsetText.cpp | 20 ++++++++++++++ src/insets/InsetText.h | 2 ++ 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index a899706f38..fe33dbeef0 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -2484,14 +2484,17 @@ void Tabular::TeXRow(otexstream & os, row_type row, && 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 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const 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 diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 96d5a34d5a..77131a055b 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -99,6 +99,26 @@ void InsetText::setBuffer(Buffer & buf) } +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(); diff --git a/src/insets/InsetText.h b/src/insets/InsetText.h index 1f643c029f..704194c5d0 100644 --- a/src/insets/InsetText.h +++ b/src/insets/InsetText.h @@ -164,6 +164,8 @@ public: /// 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; -- 2.39.5