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;
