Index: fl_BlockLayout.cpp =================================================================== RCS file: /cvsroot/abi/src/text/fmt/xp/fl_BlockLayout.cpp,v retrieving revision 1.153 diff -u -5 -r1.153 fl_BlockLayout.cpp --- fl_BlockLayout.cpp 2000/05/28 21:25:11 1.153 +++ fl_BlockLayout.cpp 2000/06/01 15:30:42 @@ -726,10 +726,107 @@ m_pFirstLine->addRun(m_pFirstRun); m_pFirstLine->layout(); } +// Split the line the Run resides on, ensuring that the resulting two lines +// are both valid in the sense of being able to contain the point. +void fl_BlockLayout::_breakLineAfterRun(fp_Run* pRun) +{ + // First make sure the old line can contain the point + fp_Line* pLine = pRun->getLine(); + // (This is a sloppy check - may have to loop between the two Runs + // and check that at least one Run can contain the point.) + if (pLine->getFirstRun() == pRun) + { + // Add a new zero-length Run at the start of the old + // line. + GR_Graphics* pG = m_pLayout->getGraphics(); + fp_TextRun* pNewRun = new fp_TextRun(this, pG, pRun->getBlockOffset(), 0); + pRun->insertIntoRunListBeforeThis(*pNewRun); + pLine->insertRun(pNewRun); + // Update FirstRun if necessary + if (pLine->isFirstLineInBlock()) + m_pFirstRun = pNewRun; + } + + // Create the new line + fp_Line* pNewLine = new fp_Line(); + UT_ASSERT(pNewLine); + // Insert it after the current line + pNewLine->setPrev(pLine); + pNewLine->setNext(pLine->getNext()); + pLine->setNext(pNewLine); + // Update LastLine if necessary + if (m_pLastLine == pLine) + m_pLastLine = pNewLine; + // Set the block + pNewLine->setBlock(this); + // Add the line to the container + pLine->getContainer()->insertLineAfter(pNewLine, pLine); + + // Now add Runs following pRun on the same line to the new + // line. Keep track of whether any Runs that can contain Point + // are added. + UT_Bool bCanContaintPoint = UT_FALSE; + fp_Run* pCurrentRun = pRun->getNext(); + while (pCurrentRun && pCurrentRun->getLine() == pLine) + { + pLine->removeRun(pCurrentRun, UT_TRUE); + pNewLine->addRun(pCurrentRun); + if (pCurrentRun->canContainPoint()) + bCanContaintPoint = UT_TRUE; + pCurrentRun = pCurrentRun->getNext(); + } + + if (!bCanContaintPoint) + { + // No Runs that can contain Point were added to the + // new line. Add a new zero-length Run at the start of + // the new line. + GR_Graphics* pG = m_pLayout->getGraphics(); + fp_TextRun* pNewRun = new fp_TextRun(this, pG, pRun->getBlockOffset() + pRun->getLength(), 0); + pRun->insertIntoRunListAfterThis(*pNewRun); + pNewLine->insertRun(pNewRun); + } + + // Update the layout information in the lines. + pLine->layout(); + pNewLine->layout(); +} + +UT_Bool fl_BlockLayout::_validateBlockForPoint(void) +{ + // check that all lines in the block have at least one run + // which can contain the insertion point. + + fp_Line* pLine = getFirstLine(); + while (pLine) + { + UT_Bool bCanContainPoint = UT_FALSE; + + fp_Run* pRun = pLine->getFirstRun(); + while (pRun) + { + if (pRun->canContainPoint()) + { + bCanContainPoint = UT_TRUE; + break; + } + pRun = pRun->getNext(); + } + + if (!bCanContainPoint) + return UT_FALSE; + + pLine = pLine->getNext(); + } + + return UT_TRUE; +} + + int fl_BlockLayout::format() { if (m_pFirstRun) { if (m_bFixCharWidths) @@ -1886,27 +1983,39 @@ UT_Bool fl_BlockLayout::_doInsertForcedLineBreakRun(PT_BlockOffset blockOffset) { fp_Run* pNewRun = new fp_ForcedLineBreakRun(this, m_pLayout->getGraphics(), blockOffset, 1); UT_ASSERT(pNewRun); // TODO check for outofmem - return _doInsertRun(pNewRun); + UT_Bool bResult = _doInsertRun(pNewRun); + if (bResult) + _breakLineAfterRun(pNewRun); + + return bResult; } UT_Bool fl_BlockLayout::_doInsertForcedPageBreakRun(PT_BlockOffset blockOffset) { fp_Run* pNewRun = new fp_ForcedPageBreakRun(this, m_pLayout->getGraphics(), blockOffset, 1); UT_ASSERT(pNewRun); // TODO check for outofmem - return _doInsertRun(pNewRun); + UT_Bool bResult = _doInsertRun(pNewRun); + if (bResult) + _breakLineAfterRun(pNewRun); + + return bResult; } UT_Bool fl_BlockLayout::_doInsertForcedColumnBreakRun(PT_BlockOffset blockOffset) { fp_Run* pNewRun = new fp_ForcedColumnBreakRun(this, m_pLayout->getGraphics(), blockOffset, 1); UT_ASSERT(pNewRun); // TODO check for outofmem - return _doInsertRun(pNewRun); + UT_Bool bResult = _doInsertRun(pNewRun); + if (bResult) + _breakLineAfterRun(pNewRun); + + return bResult; } UT_Bool fl_BlockLayout::_doInsertTabRun(PT_BlockOffset blockOffset) { fp_Run* pNewRun = new fp_TabRun(this, m_pLayout->getGraphics(), blockOffset, 1); @@ -2161,13 +2270,15 @@ if (bNormal && (iNormalBase < i)) { _doInsertTextSpan(blockOffset + iNormalBase, i - iNormalBase); } - + setNeedsReformat(); + UT_ASSERT(_validateBlockForPoint()); + FV_View* pView = m_pLayout->getView(); if (pView) { pView->_setPoint(pcrs->getPosition()+len); pView->notifyListeners(AV_CHG_FMTCHAR); // TODO verify that this is necessary. Index: fl_BlockLayout.h =================================================================== RCS file: /cvsroot/abi/src/text/fmt/xp/fl_BlockLayout.h,v retrieving revision 1.75 diff -u -5 -r1.75 fl_BlockLayout.h --- fl_BlockLayout.h 2000/05/28 21:25:11 1.75 +++ fl_BlockLayout.h 2000/06/01 15:30:43 @@ -308,10 +308,12 @@ UT_Bool bToggleIP); UT_uint32 _getLastChar(); void _stuffAllRunsOnALine(void); void _insertFakeTextRun(void); + void _breakLineAfterRun(fp_Run* /*pRun*/); + UT_Bool _validateBlockForPoint(void); static void _prefsListener(XAP_App * /*pApp*/, XAP_Prefs *pPrefs, UT_AlphaHashTable * /*phChanges*/, void * data); UT_Bool m_bNeedsReformat; UT_Bool m_bNeedsRedraw;