richedit: Store paragraph in cursors.

Dylan Smith dylan.ah.smith at gmail.com
Mon Feb 9 11:01:35 CST 2009


This prevents some needless searching for the start of the paragraph
from a run stored in a cursor.  Usually a pointer to the paragraph is
already available when the cursor is set anyway.
---
 dlls/riched20/caret.c   |   80 ++++++++++++++++++++++++++++++++--------------
 dlls/riched20/editor.c  |   52 +++++++++++++++++-------------
 dlls/riched20/editstr.h |    1 +
 dlls/riched20/paint.c   |    6 +--
 dlls/riched20/para.c    |   49 +++++++++++++++++-----------
 dlls/riched20/run.c     |   33 ++++++++++---------
 dlls/riched20/table.c   |   27 +++++++++++-----
 dlls/riched20/undo.c    |    4 +-
 8 files changed, 156 insertions(+), 96 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 43ad44c..2151e43 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -95,9 +95,11 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
   /* select all */
   if (from == 0 && to == -1)
   {
-    editor->pCursors[1].pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
-    editor->pCursors[1].nOffset = 0; 
-    editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); 
+    editor->pCursors[1].pPara = editor->pBuffer->pFirst->member.para.next_para;
+    editor->pCursors[1].pRun = ME_FindItemFwd(editor->pCursors[1].pPara, diRun);
+    editor->pCursors[1].nOffset = 0;
+    editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para;
+    editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
     editor->pCursors[0].nOffset = 0;
     ME_InvalidateSelection(editor);
     ME_ClearTempStyle(editor);
@@ -146,8 +148,10 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
 
   if (selectionEnd)
   {
-    editor->pCursors[1].pRun = editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
-    editor->pCursors[1].nOffset = editor->pCursors[0].nOffset = 0;
+    editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para;
+    editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
+    editor->pCursors[0].nOffset = 0;
+    editor->pCursors[1] = editor->pCursors[0];
     ME_InvalidateSelection(editor);
     ME_ClearTempStyle(editor);
     return len;
@@ -170,7 +174,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
 {
   ME_DisplayItem *row;
   ME_DisplayItem *run = pCursor->pRun;
-  ME_DisplayItem *para = ME_GetParagraph(run);
+  ME_DisplayItem *para = pCursor->pPara;
   ME_DisplayItem *pSizeRun = run;
   ME_Context c;
   SIZE sz = {0, 0};
@@ -266,7 +270,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
   nChars = min(nChars, ME_GetTextLength(editor) - nOfs);
 
   ME_CursorFromCharOfs(editor, nOfs, &c);
-  start_para = ME_GetParagraph(c.pRun);
+  start_para = c.pPara;
 
   if (!bForce)
   {
@@ -281,11 +285,12 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
     ME_CursorFromCharOfs(editor, nOfs+nChars, &c);
     if (!c.nOffset &&
         nOfs+nChars == (c.pRun->member.run.nCharOfs
-                        + ME_GetParagraph(c.pRun)->member.para.nCharOfs))
+                        + c.pPara->member.para.nCharOfs))
     {
       /* We aren't deleting anything in this run, so we will go back to the
        * last run we are deleting text in. */
       c.pRun = ME_FindItemBack(c.pRun, diRun);
+      c.pPara = ME_GetParagraph(c.pRun);
       c.nOffset = c.pRun->member.run.strText->nLen;
     }
     run = &c.pRun->member.run;
@@ -321,7 +326,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
           keepFirstParaFormat = TRUE;
         }
       }
-      ME_JoinParagraphs(editor, ME_GetParagraph(c.pRun), keepFirstParaFormat);
+      ME_JoinParagraphs(editor, c.pPara, keepFirstParaFormat);
       /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */
       ME_CheckCharOffsets(editor);
       nChars -= (eollen < nChars) ? eollen : nChars;
@@ -369,10 +374,10 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
       TRACE("Post deletion string: %s (%d)\n", debugstr_w(run->strText->szData), run->strText->nLen);
       TRACE("Shift value: %d\n", shift);
       ME_StrDeleteV(run->strText, c.nOffset, nCharsToDelete);
-      
+
       /* update cursors (including c) */
       for (i=-1; i<editor->nCursors; i++) {
-        ME_Cursor *pThisCur = editor->pCursors + i; 
+        ME_Cursor *pThisCur = editor->pCursors + i;
         if (i == -1) pThisCur = &c;
         if (pThisCur->pRun == cursor.pRun) {
           if (pThisCur->nOffset > cursor.nOffset) {
@@ -391,9 +396,9 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
           }
         }
       }
-      
+
       /* c = updated data now */
-      
+
       if (c.pRun == cursor.pRun)
         ME_SkipAndPropagateCharOffset(c.pRun, shift);
       else
@@ -405,7 +410,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
         ME_Remove(cursor.pRun);
         ME_DestroyDisplayItem(cursor.pRun);
       }
-      
+
       shift = 0;
       /*
       ME_CheckCharOffsets(editor);
@@ -560,6 +565,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
         /* ME_SplitParagraph increases style refcount */
         tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0);
         p->pRun = ME_FindItemFwd(tp, diRun);
+        p->pPara = ME_GetParagraph(p->pRun);
         end_run = ME_FindItemBack(tp, diRun);
         ME_ReleaseStyle(end_run->member.run.style);
         end_run->member.run.style = tmp_style;
@@ -581,6 +587,7 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
   {
     if (!pCursor->nOffset)
     {
+      ME_DisplayItem *pPara = pCursor->pPara;
       do {
         pRun = ME_FindItemBack(pRun, diRunOrParagraph);
         assert(pRun);
@@ -589,9 +596,11 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
           case diRun:
             break;
           case diParagraph:
-            if (pRun->member.para.prev_para->type == diTextStart)
+            pPara = pRun;
+            if (pPara->member.para.prev_para->type == diTextStart)
               return FALSE;
-            pRun = ME_FindItemBack(pRun, diRunOrParagraph);
+            pRun = ME_FindItemBack(pPara, diRunOrParagraph);
+            pPara = pPara->member.para.prev_para;
             /* every paragraph ought to have at least one run */
             assert(pRun && pRun->type == diRun);
             assert(pRun->member.run.nFlags & MERF_ENDPARA);
@@ -602,6 +611,7 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
         }
       } while (RUN_IS_HIDDEN(&pRun->member.run) ||
                pRun->member.run.nFlags & MERF_HIDDEN);
+      pCursor->pPara = pPara;
       pCursor->pRun = pRun;
       if (pRun->member.run.nFlags & MERF_ENDPARA)
         pCursor->nOffset = 0;
@@ -631,6 +641,7 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
                       pRun->member.run.nFlags & MERF_HIDDEN));
     if (pRun)
     {
+      pCursor->pPara = ME_GetParagraph(pRun);
       pCursor->pRun = pRun;
       pCursor->nOffset = 0;
       return TRUE;
@@ -653,7 +664,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
     {
       nOffset = ME_CallWordBreakProc(editor, pRun->member.run.strText,
                                      nOffset, WB_MOVEWORDLEFT);
-       if (nOffset)
+      if (nOffset)
         break;
       pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph);
       if (pOtherRun->type == diRun)
@@ -680,7 +691,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
           if (pOtherRun->member.para.prev_para->type == diTextStart)
             return FALSE;
 
-          pRun = ME_FindItemBack(pOtherRun, diRunOrParagraph);
+          pRun = ME_FindItemBack(pOtherRun, diRun);
         }
         break;
       }
@@ -726,6 +737,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
       }
     }
   }
+  cursor->pPara = ME_GetParagraph(pRun);
   cursor->pRun = pRun;
   cursor->nOffset = nOffset;
   return TRUE;
@@ -769,18 +781,22 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType)
           editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun);
       else
           editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun);
+      editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
       editor->pCursors[0].nOffset = 0;
 
       pItem = ME_FindItemBack(pItem, backSearchType);
       editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun);
+      editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
       editor->pCursors[1].nOffset = 0;
       break;
     }
     case stDocument:
       /* Select everything with cursor anchored from the start of the text */
       editor->nSelectionType = stDocument;
-      editor->pCursors[1].pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
+      editor->pCursors[1].pPara = editor->pBuffer->pFirst->member.para.next_para;
+      editor->pCursors[1].pRun = ME_FindItemFwd(editor->pCursors[1].pPara, diRun);
       editor->pCursors[1].nOffset = 0;
+      editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para;
       editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
       editor->pCursors[0].nOffset = 0;
       break;
@@ -794,8 +810,8 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType)
 int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor)
 {
   ME_Cursor *pCursor = &editor->pCursors[nCursor];
-  return ME_GetParagraph(pCursor->pRun)->member.para.nCharOfs
-    + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset;
+  return pCursor->pPara->member.para.nCharOfs
+         + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset;
 }
 
 /* Helper function for ME_FindPixelPos to find paragraph within tables */
@@ -851,6 +867,7 @@ static BOOL ME_ReturnFoundPos(ME_TextEditor *editor, ME_DisplayItem *found,
     result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun);
     result->nOffset = 0;
   }
+  result->pPara = ME_GetParagraph(result->pRun);
   return isExact;
 }
 
@@ -951,6 +968,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
     last = p;
   }
   result->pRun = ME_FindItemBack(p, diRun);
+  result->pPara = ME_GetParagraph(result->pRun);
   result->nOffset = 0;
   assert(result->pRun->member.run.nFlags & MERF_ENDPARA);
   return FALSE;
@@ -979,8 +997,8 @@ int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact)
   y += editor->vert_si.nPos;
   bResult = ME_FindPixelPos(editor, x, y, &cursor, NULL);
   if (isExact) *isExact = bResult;
-  return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs
-          + cursor.pRun->member.run.nCharOfs + cursor.nOffset);
+  return cursor.pPara->member.para.nCharOfs
+         + cursor.pRun->member.run.nCharOfs + cursor.nOffset;
 }
 
 
@@ -1021,6 +1039,7 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor)
                                   diStartRowOrParagraph:diParagraph);
           pItem = ME_FindItemBack(editor->pCursors[1].pRun, searchType);
           editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun);
+          editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
           editor->pCursors[1].nOffset = 0;
       }
   }
@@ -1040,6 +1059,7 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor)
               editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun);
           else
               editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun);
+          editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
           editor->pCursors[0].nOffset = 0;
       }
   }
@@ -1282,6 +1302,7 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
     return;
   }
   pCursor->pRun = ME_FindRunInRow(editor, pItem, x, &pCursor->nOffset, &editor->bCaretAtEnd);
+  pCursor->pPara = ME_GetParagraph(pCursor->pRun);
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);
 }
@@ -1292,7 +1313,8 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
 
   if (editor->vert_si.nPos < p->member.row.nHeight)
   {
-    pCursor->pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
+    pCursor->pPara = editor->pBuffer->pFirst->member.para.next_para;
+    pCursor->pRun = ME_FindItemFwd(pCursor->pPara, diRun);
     pCursor->nOffset = 0;
     editor->bCaretAtEnd = FALSE;
     /* Native clears seems to clear this x value on page up at the top
@@ -1338,6 +1360,7 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
 
     pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset,
                                     &editor->bCaretAtEnd);
+    pCursor->pPara = ME_GetParagraph(pCursor->pRun);
   }
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);
@@ -1357,6 +1380,7 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
 
   if (editor->vert_si.nPos >= y - editor->sizeWindow.cy)
   {
+    pCursor->pPara = editor->pBuffer->pLast->member.para.prev_para;
     pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
     pCursor->nOffset = 0;
     editor->bCaretAtEnd = FALSE;
@@ -1399,6 +1423,7 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
 
     pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset,
                                     &editor->bCaretAtEnd);
+    pCursor->pPara = ME_GetParagraph(pCursor->pRun);
   }
   assert(pCursor->pRun);
   assert(pCursor->pRun->type == diRun);
@@ -1417,6 +1442,7 @@ static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
     pRun = ME_FindItemFwd(pRow, diRun);
     if (pRun) {
       pCursor->pRun = pRun;
+      assert(pCursor->pPara == ME_GetParagraph(pRun));
       pCursor->nOffset = 0;
     }
   }
@@ -1425,7 +1451,8 @@ static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
 
 static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
-  pCursor->pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun);
+  pCursor->pPara = editor->pBuffer->pFirst->member.para.next_para;
+  pCursor->pRun = ME_FindItemFwd(pCursor->pPara, diRun);
   pCursor->nOffset = 0;
   editor->bCaretAtEnd = FALSE;
 }
@@ -1443,18 +1470,21 @@ static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
     ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun);
     assert(pRun);
     pCursor->pRun = pRun;
+    assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
     pCursor->nOffset = 0;
     editor->bCaretAtEnd = TRUE;
     return;
   }
   pCursor->pRun = ME_FindItemBack(pRow, diRun);
   assert(pCursor->pRun && pCursor->pRun->member.run.nFlags & MERF_ENDPARA);
+  assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
   pCursor->nOffset = 0;
   editor->bCaretAtEnd = FALSE;
 }
 
 static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
+  pCursor->pPara = editor->pBuffer->pLast->member.para.prev_para;
   pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
   assert(pCursor->pRun->member.run.nFlags & MERF_ENDPARA);
   pCursor->nOffset = 0;
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 0fdef8d..2a053d7 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -507,7 +507,7 @@ void ME_RTFParAttrHook(RTF_Info *info)
         /* We are just after a table row. */
         RTFFlushOutputBuffer(info);
         cursor = info->editor->pCursors[0];
-        para = ME_GetParagraph(cursor.pRun);
+        para = cursor.pPara;
         if (para  == info->tableDef->tableRowStart->member.para.next_para
             && !cursor.nOffset && !cursor.pRun->member.run.nCharOfs)
         {
@@ -860,7 +860,7 @@ void ME_RTFTblAttrHook(RTF_Info *info)
       if (cellNum < MAX_TAB_STOPS) {
         /* Tab stops were used to store cell positions before v4.1 but v4.1
          * still seems to set the tabstops without using them. */
-        ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun);
+        ME_DisplayItem *para = info->editor->pCursors[0].pPara;
         PARAFORMAT2 *pFmt = para->member.para.pFmt;
         pFmt->rgxTabs[cellNum] &= ~0x00FFFFFF;
         pFmt->rgxTabs[cellNum] = 0x00FFFFFF & info->rtfParam;
@@ -931,7 +931,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
           ME_InsertTableCellFromCursor(info->editor);
         }
       } else { /* v1.0 - v3.0 */
-        ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun);
+        ME_DisplayItem *para = info->editor->pCursors[0].pPara;
         PARAFORMAT2 *pFmt = para->member.para.pFmt;
         if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE &&
             tableDef->numCellsInserted < tableDef->numCellsDefined)
@@ -1009,6 +1009,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
           int nOfs, nChars;
           /* Delete inserted cells that aren't defined. */
           info->editor->pCursors[1].pRun = run;
+          info->editor->pCursors[1].pPara = ME_GetParagraph(run);
           info->editor->pCursors[1].nOffset = 0;
           nOfs = ME_GetCursorOfs(info->editor, 1);
           nChars = ME_GetCursorOfs(info->editor, 0) - nOfs;
@@ -1038,12 +1039,11 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
         }
       } else { /* v1.0 - v3.0 */
         WCHAR endl = '\r';
-        ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun);
+        ME_DisplayItem *para = info->editor->pCursors[0].pPara;
         PARAFORMAT2 *pFmt = para->member.para.pFmt;
         pFmt->dxOffset = info->tableDef->gapH;
         pFmt->dxStartIndent = info->tableDef->leftEdge;
 
-        para = ME_GetParagraph(info->editor->pCursors[0].pRun);
         ME_ApplyBorderProperties(info, &para->member.para.border,
                                  tableDef->border);
         while (tableDef->numCellsInserted < tableDef->numCellsDefined)
@@ -1066,7 +1066,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
         ME_DisplayItem *para;
         PARAFORMAT2 *pFmt;
         RTFFlushOutputBuffer(info);
-        para = ME_GetParagraph(info->editor->pCursors[0].pRun);
+        para = info->editor->pCursors[0].pPara;
         pFmt = para->member.para.pFmt;
         if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
         {
@@ -1404,16 +1404,18 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
 
     /* Don't insert text at the end of the table row */
     if (!editor->bEmulateVersion10) { /* v4.1 */
-      ME_DisplayItem *para = ME_GetParagraph(editor->pCursors->pRun);
+      ME_DisplayItem *para = editor->pCursors->pPara;
       if (para->member.para.nFlags & MEPF_ROWEND)
       {
         para = para->member.para.next_para;
+        editor->pCursors[0].pPara = para;
         editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
         editor->pCursors[0].nOffset = 0;
       }
       if (para->member.para.nFlags & MEPF_ROWSTART)
       {
         para = para->member.para.next_para;
+        editor->pCursors[0].pPara = para;
         editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
         editor->pCursors[0].nOffset = 0;
       }
@@ -1425,16 +1427,13 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
     }
   }
   else {
-    ME_DisplayItem *para_item;
     style = editor->pBuffer->pDefaultStyle;
     ME_AddRefStyle(style);
     ME_SetSelection(editor, 0, 0);
     ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE);
     from = to = 0;
     ME_ClearTempStyle(editor);
-
-    para_item = ME_GetParagraph(editor->pCursors[0].pRun);
-    ME_SetDefaultParaFormat(para_item->member.para.pFmt);
+    ME_SetDefaultParaFormat(editor->pCursors[0].pPara->member.para.pFmt);
   }
 
 
@@ -1517,6 +1516,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
           }
           pCell = para->member.para.pCell;
 
+          editor->pCursors[1].pPara = para;
           editor->pCursors[1].pRun = ME_FindItemFwd(para, diRun);
           editor->pCursors[1].nOffset = 0;
           nOfs = ME_GetCursorOfs(editor, 1);
@@ -1637,7 +1637,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
 
   TRACE("flags==0x%08x, chrg->cpMin==%d, chrg->cpMax==%d text==%s\n",
         flags, chrg->cpMin, chrg->cpMax, debugstr_w(text));
-  
+
   if (flags & ~(FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD))
     FIXME("Flags 0x%08x not implemented\n",
         flags & ~(FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD));
@@ -1647,7 +1647,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
     nMax = nTextLen;
   else
     nMax = chrg->cpMax > nTextLen ? nTextLen : chrg->cpMax;
-  
+
   /* In 1.0 emulation, if cpMax reaches end of text, add the FR_DOWN flag */
   if (editor->bEmulateVersion10 && nMax == nTextLen)
   {
@@ -2122,7 +2122,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
       if (editor->styleFlags & ES_MULTILINE)
       {
         ME_Cursor cursor = editor->pCursors[0];
-        ME_DisplayItem *para = ME_GetParagraph(cursor.pRun);
+        ME_DisplayItem *para = cursor.pPara;
         int from, to;
         const WCHAR endl = '\r';
         ME_Style *style;
@@ -2140,6 +2140,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
               /* Add a new table row after this row. */
               para = ME_AppendTableRow(editor, para);
               para = para->member.para.next_para;
+              editor->pCursors[0].pPara = para;
               editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
               editor->pCursors[0].nOffset = 0;
               editor->pCursors[1] = editor->pCursors[0];
@@ -2148,7 +2149,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
               ME_UpdateRepaint(editor);
               return TRUE;
             }
-            else if (para == ME_GetParagraph(editor->pCursors[1].pRun) &&
+            else if (para == editor->pCursors[1].pPara &&
                      cursor.nOffset + cursor.pRun->member.run.nCharOfs == 0 &&
                      para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART &&
                      !para->member.para.prev_para->member.para.nCharOfs)
@@ -2156,6 +2157,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
               /* Insert a newline before the table. */
               para = para->member.para.prev_para;
               para->member.para.nFlags &= ~MEPF_ROWSTART;
+              editor->pCursors[0].pPara = para;
               editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
               editor->pCursors[1] = editor->pCursors[0];
               ME_InsertTextFromCursor(editor, 0, &endl, 1,
@@ -2163,6 +2165,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
               para = editor->pBuffer->pFirst->member.para.next_para;
               ME_SetDefaultParaFormat(para->member.para.pFmt);
               para->member.para.nFlags = MEPF_REWRAP;
+              editor->pCursors[0].pPara = para;
               editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
               editor->pCursors[1] = editor->pCursors[0];
               para->member.para.next_para->member.para.nFlags |= MEPF_ROWSTART;
@@ -2172,7 +2175,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
               return TRUE;
             }
           } else { /* v1.0 - 3.0 */
-            ME_DisplayItem *para = ME_GetParagraph(cursor.pRun);
+            ME_DisplayItem *para = cursor.pPara;
             if (ME_IsInTable(para))
             {
               if (cursor.pRun->member.run.nFlags & MERF_ENDPARA)
@@ -2180,6 +2183,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
                 if (from == to) {
                   ME_ContinueCoalescingTransaction(editor);
                   para = ME_AppendTableRow(editor, para);
+                  editor->pCursors[0].pPara = para;
                   editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
                   editor->pCursors[0].nOffset = 0;
                   editor->pCursors[1] = editor->pCursors[0];
@@ -2194,8 +2198,10 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
                 {
                   /* Insert newline before table */
                   cursor.pRun = ME_FindItemBack(para, diRun);
-                  if (cursor.pRun)
+                  if (cursor.pRun) {
                     editor->pCursors[0].pRun = cursor.pRun;
+                    editor->pCursors[0].pPara = para->member.para.prev_para;
+                  }
                   editor->pCursors[0].nOffset = 0;
                   editor->pCursors[1] = editor->pCursors[0];
                   ME_InsertTextFromCursor(editor, 0, &endl, 1,
@@ -2203,6 +2209,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
                 } else {
                   editor->pCursors[1] = editor->pCursors[0];
                   para = ME_AppendTableRow(editor, para);
+                  editor->pCursors[0].pPara = para;
                   editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
                   editor->pCursors[0].nOffset = 0;
                   editor->pCursors[1] = editor->pCursors[0];
@@ -2325,7 +2332,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode,
   if ((unsigned)wstr >= ' ' || wstr == '\t')
   {
     ME_Cursor cursor = editor->pCursors[0];
-    ME_DisplayItem *para = ME_GetParagraph(cursor.pRun);
+    ME_DisplayItem *para = cursor.pPara;
     int from, to;
     BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000;
     ME_GetSelection(editor, &from, &to);
@@ -2336,7 +2343,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode,
       ME_DisplayItem *para;
       BOOL bSelectedRow = FALSE;
 
-      para = ME_GetParagraph(cursor.pRun);
+      para = cursor.pPara;
       if (ME_IsSelection(editor) &&
           cursor.pRun->member.run.nCharOfs + cursor.nOffset == 0 &&
           to == ME_GetCursorOfs(editor, 0) &&
@@ -2357,6 +2364,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode,
           para = para->member.para.next_para;
           if (para->member.para.nFlags & MEPF_ROWSTART)
             para = para->member.para.next_para;
+          editor->pCursors[0].pPara = para;
           editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
           editor->pCursors[0].nOffset = 0;
           editor->pCursors[1] = editor->pCursors[0];
@@ -2604,10 +2612,10 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
    */
   ed->nCursors = 4;
   ed->pCursors = ALLOC_N_OBJ(ME_Cursor, ed->nCursors);
-  ed->pCursors[0].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun);
+  ed->pCursors[0].pPara = ed->pBuffer->pFirst->member.para.next_para;
+  ed->pCursors[0].pRun = ME_FindItemFwd(ed->pCursors[0].pPara, diRun);
   ed->pCursors[0].nOffset = 0;
-  ed->pCursors[1].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun);
-  ed->pCursors[1].nOffset = 0;
+  ed->pCursors[1] = ed->pCursors[0];
   ed->pCursors[2] = ed->pCursors[0];
   ed->pCursors[3] = ed->pCursors[1];
   ed->nLastTotalLength = ed->nTotalLength = 0;
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index ac36e0e..889cbd8 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -263,6 +263,7 @@ typedef struct tagME_TextBuffer
 
 typedef struct tagME_Cursor
 {
+  ME_DisplayItem *pPara;
   ME_DisplayItem *pRun;
   int nOffset;
 } ME_Cursor;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index ba2b471..35ca097 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -137,7 +137,6 @@ void ME_Repaint(ME_TextEditor *editor)
 void ME_UpdateRepaint(ME_TextEditor *editor)
 {
   /* Should be called whenever the contents of the control have changed */
-  ME_Cursor *pCursor;
   BOOL wrappedParagraphs;
 
   wrappedParagraphs = ME_WrapMarkedParagraphs(editor);
@@ -145,8 +144,7 @@ void ME_UpdateRepaint(ME_TextEditor *editor)
     ME_UpdateScrollBar(editor);
 
   /* Ensure that the cursor is visible */
-  pCursor = &editor->pCursors[0];
-  ME_EnsureVisible(editor, pCursor);
+  ME_EnsureVisible(editor, &editor->pCursors[0]);
 
   /* send EN_CHANGE if the event mask asks for it */
   if(editor->nEventMask & ENM_CHANGE)
@@ -1226,7 +1224,7 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor)
 {
   ME_Run *pRun = &pCursor->pRun->member.run;
   ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
-  ME_DisplayItem *pPara = ME_FindItemBack(pCursor->pRun, diParagraph);
+  ME_DisplayItem *pPara = pCursor->pPara;
   int x, y, yheight;
 
   assert(pRow);
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index 0836390..94ef7ae 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -208,7 +208,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
   ME_DisplayItem *new_para = ME_MakeDI(diParagraph);
   ME_DisplayItem *end_run;
   ME_UndoItem *undo = NULL;
-  int ofs;
+  int ofs, i;
   ME_DisplayItem *pp;
   int run_flags = MERF_ENDPARA;
 
@@ -236,14 +236,23 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
   undo = ME_AddUndoItem(editor, diUndoJoinParagraphs, NULL);
   if (undo)
     undo->nStart = run_para->member.para.nCharOfs + ofs;
-  
+
+  /* Update selection cursors to point to the correct paragraph. */
+  for (i = 0; i < editor->nCursors; i++) {
+    if (editor->pCursors[i].pPara == run_para &&
+        run->member.run.nCharOfs <= editor->pCursors[i].pRun->member.run.nCharOfs)
+    {
+      editor->pCursors[i].pPara = new_para;
+    }
+  }
+
   /* the new paragraph will have a different starting offset, so let's update its runs */
   pp = run;
   while(pp->type == diRun) {
     pp->member.run.nCharOfs -= ofs;
     pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd);
   }
-  new_para->member.para.nCharOfs = ME_GetParagraph(run)->member.para.nCharOfs+ofs;
+  new_para->member.para.nCharOfs = run_para->member.para.nCharOfs + ofs;
   new_para->member.para.nCharOfs += eol_str->nLen;
   new_para->member.para.nFlags = MEPF_REWRAP;
 
@@ -309,11 +318,11 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
   /* force rewrap of the */
   run_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP;
   new_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP;
-  
+
   /* we've added the end run, so we need to modify nCharOfs in the next paragraphs */
   ME_PropagateCharOffset(next_para, eol_str->nLen);
   editor->nParagraphs++;
-  
+
   return new_para;
 }
 
@@ -330,9 +339,9 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
   assert(tp->type == diParagraph);
   assert(tp->member.para.next_para);
   assert(tp->member.para.next_para->type == diParagraph);
-  
+
   pNext = tp->member.para.next_para;
-  
+
   /* Need to locate end-of-paragraph run here, in order to know end_len */
   pRun = ME_FindItemBack(pNext, diRunOrParagraph);
 
@@ -397,19 +406,21 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
       pTmp = pTmp->next;
     }
   }
-  
+
   shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len;
-  
+
   pFirstRunInNext = ME_FindItemFwd(pNext, diRunOrParagraph);
 
   assert(pFirstRunInNext->type == diRun);
-  
-  /* if some cursor points at end of paragraph, make it point to the first
-     run of the next joined paragraph */
-  for (i=0; i<editor->nCursors; i++) {
+
+  /* Update selection cursors so they don't point to the removed end
+   * paragraph run, and point to the correct paragraph. */
+  for (i=0; i < editor->nCursors; i++) {
     if (editor->pCursors[i].pRun == pRun) {
       editor->pCursors[i].pRun = pFirstRunInNext;
       editor->pCursors[i].nOffset = 0;
+    } else if (editor->pCursors[i].pPara == pNext) {
+      editor->pCursors[i].pPara = tp;
     }
   }
 
@@ -421,7 +432,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
     TRACE("shifting \"%s\" by %d (previous %d)\n", debugstr_w(pTmp->member.run.strText->szData), shift, pTmp->member.run.nCharOfs);
     pTmp->member.run.nCharOfs += shift;
   } while(1);
-  
+
   ME_Remove(pRun);
   ME_DestroyDisplayItem(pRun);
 
@@ -429,16 +440,16 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
     editor->pLastSelStartPara = tp;
   if (editor->pLastSelEndPara == pNext)
     editor->pLastSelEndPara = tp;
-    
+
   tp->member.para.next_para = pNext->member.para.next_para;
   pNext->member.para.next_para->member.para.prev_para = tp;
   ME_Remove(pNext);
   ME_DestroyDisplayItem(pNext);
 
   ME_PropagateCharOffset(tp->member.para.next_para, -end_len);
-  
+
   ME_CheckCharOffsets(editor);
-  
+
   editor->nParagraphs--;
   tp->member.para.nFlags |= MEPF_REWRAP;
   return tp;
@@ -516,8 +527,8 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte
 {
   ME_Cursor *pEndCursor = &editor->pCursors[1];
 
-  *para = ME_GetParagraph(editor->pCursors[0].pRun);
-  *para_end = ME_GetParagraph(editor->pCursors[1].pRun);
+  *para = editor->pCursors[0].pPara;
+  *para_end = editor->pCursors[1].pPara;
   if (*para == *para_end)
     return;
 
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index d4aaaa2..9778ea9 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -163,7 +163,8 @@ int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara,
  */
 void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor)
 {
-  ME_RunOfsFromCharOfs(editor, nCharOfs, NULL, &pCursor->pRun, &pCursor->nOffset);
+  ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pPara,
+                       &pCursor->pRun, &pCursor->nOffset);
 }
 
 /******************************************************************************
@@ -243,10 +244,10 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p)
 
 /******************************************************************************
  * ME_SplitRun
- * 
+ *
  * Splits a run into two in a given place. It also updates the screen position
- * and size (extent) of the newly generated runs.  
- */    
+ * and size (extent) of the newly generated runs.
+ */
 ME_DisplayItem *ME_SplitRun(ME_WrapContext *wc, ME_DisplayItem *item, int nVChar)
 {
   ME_TextEditor *editor = wc->context->editor;
@@ -369,38 +370,38 @@ ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem
 
 /******************************************************************************
  * ME_InsertRunAtCursor
- * 
+ *
  * Inserts a new run with given style, flags and content at a given position,
  * which is passed as a cursor structure (which consists of a run and 
- * a run-relative character offset). 
- */   
+ * a run-relative character offset).
+ */
 ME_DisplayItem *
 ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
                      const WCHAR *str, int len, int flags)
 {
   ME_DisplayItem *pDI;
   ME_UndoItem *pUI;
-  
+
   if (cursor->nOffset) {
   	/* We're inserting at the middle of the existing run, which means that
 		 * that run must be split. It isn't always necessary, but */
     cursor->pRun = ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset);
     cursor->nOffset = 0;
   }
-  
+
   pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
   if (pUI) {
-    pUI->nStart = (ME_GetParagraph(cursor->pRun)->member.para.nCharOfs
-                   + cursor->pRun->member.run.nCharOfs);
+    pUI->nStart = cursor->pPara->member.para.nCharOfs
+                  + cursor->pRun->member.run.nCharOfs;
     pUI->nLen = len;
   }
-  
+
   pDI = ME_MakeRun(style, ME_MakeStringN(str, len), flags);
   pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs;
   ME_InsertBefore(cursor->pRun, pDI);
   TRACE("Shift length:%d\n", len);
   ME_PropagateCharOffset(cursor->pRun, len);
-  ME_GetParagraph(cursor->pRun)->member.para.nFlags |= MEPF_REWRAP;
+  cursor->pPara->member.para.nFlags |= MEPF_REWRAP;
   return pDI;
 }
 
@@ -577,10 +578,10 @@ static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style
 
 /******************************************************************************
  * ME_PointFromChar
- * 
+ *
  * Returns a run-relative pixel position given a run-relative character
  * position (character offset)
- */     
+ */
 int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
 {
   SIZE size;
@@ -776,7 +777,7 @@ void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W
   if (tmp2.nOffset)
     tmp2.pRun = ME_SplitRunSimple(editor, tmp2.pRun, tmp2.nOffset);
 
-  para = ME_GetParagraph(tmp.pRun);
+  para = tmp.pPara;
   para->member.para.nFlags |= MEPF_REWRAP;
 
   while(tmp.pRun != tmp2.pRun)
diff --git a/dlls/riched20/table.c b/dlls/riched20/table.c
index e7eca24..6c8ca76 100644
--- a/dlls/riched20/table.c
+++ b/dlls/riched20/table.c
@@ -70,6 +70,7 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
   }
 
   tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, paraFlags);
+  cursor->pPara = tp;
   cursor->pRun = ME_FindItemFwd(tp, diRun);
   return tp;
 }
@@ -89,6 +90,7 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor,
   ME_DisplayItem *prev_para, *end_para;
   ME_Cursor savedCursor = editor->pCursors[0];
   ME_DisplayItem *startRowPara;
+  editor->pCursors[0].pPara = para;
   editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
   editor->pCursors[0].nOffset = 0;
   editor->pCursors[1] = editor->pCursors[0];
@@ -96,7 +98,7 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor,
   editor->pCursors[0] = savedCursor;
   editor->pCursors[1] = editor->pCursors[0];
 
-  end_para = ME_GetParagraph(editor->pCursors[0].pRun)->member.para.next_para;
+  end_para = editor->pCursors[0].pPara->member.para.next_para;
   prev_para = startRowPara->member.para.next_para;
   para = prev_para->member.para.next_para;
   while (para != end_para)
@@ -276,9 +278,9 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
   ME_Cursor c, c2;
   ME_DisplayItem *this_para, *end_para;
   ME_CursorFromCharOfs(editor, nOfs, &c);
-  this_para = ME_GetParagraph(c.pRun);
+  this_para = c.pPara;
   ME_CursorFromCharOfs(editor, nOfs + *nChars, &c2);
-  end_para = ME_GetParagraph(c2.pRun);
+  end_para = c2.pPara;
   if (c2.pRun->member.run.nFlags & MERF_ENDPARA) {
     /* End offset might be in the middle of the end paragraph run.
      * If this is the case, then we need to use the next paragraph as the last
@@ -399,14 +401,15 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor,
     ME_DisplayItem *insertedCell, *para, *cell, *prevTableEnd;
     cell = ME_FindItemFwd(ME_GetTableRowStart(table_row), diCell);
     prevTableEnd = ME_GetTableRowEnd(table_row);
-    run = prevTableEnd->member.para.next_para;
-    run = ME_FindItemFwd(run, diRun);
+    para = prevTableEnd->member.para.next_para;
+    run = ME_FindItemFwd(para, diRun);
+    editor->pCursors[0].pPara = para;
     editor->pCursors[0].pRun = run;
     editor->pCursors[0].nOffset = 0;
     editor->pCursors[1] = editor->pCursors[0];
     para = ME_InsertTableRowStartFromCursor(editor);
     insertedCell = ME_FindItemFwd(para, diCell);
-      /* Copy cell properties */
+    /* Copy cell properties */
     insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary;
     insertedCell->member.cell.border = cell->member.cell.border;
     while (cell->member.cell.next_cell) {
@@ -425,6 +428,7 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor,
     run = ME_FindItemBack(table_row->member.para.next_para, diRun);
     pFmt = table_row->member.para.pFmt;
     assert(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE);
+    editor->pCursors[0].pPara = table_row;
     editor->pCursors[0].pRun = run;
     editor->pCursors[0].nOffset = 0;
     editor->pCursors[1] = editor->pCursors[0];
@@ -474,6 +478,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
         para = ME_AppendTableRow(editor, ME_GetTableRowStart(para));
         /* Put cursor at the start of the new table row */
         para = para->member.para.next_para;
+        editor->pCursors[0].pPara = para;
         editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
         editor->pCursors[0].nOffset = 0;
         editor->pCursors[1] = editor->pCursors[0];
@@ -483,10 +488,12 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
     }
     /* Select cell */
     editor->pCursors[1].pRun = ME_FindItemFwd(cell, diRun);
+    editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
     editor->pCursors[1].nOffset = 0;
     assert(editor->pCursors[0].pRun);
     cell = cell->member.cell.next_cell;
     editor->pCursors[0].pRun = ME_FindItemBack(cell, diRun);
+    editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
     editor->pCursors[0].nOffset = 0;
     assert(editor->pCursors[1].pRun);
   } else { /* v1.0 - 3.0 */
@@ -508,6 +515,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
           {
             run = ME_FindItemFwd(para, diRun);
             assert(run);
+            editor->pCursors[0].pPara = para;
             editor->pCursors[0].pRun = run;
             editor->pCursors[0].nOffset = 0;
             i = 1;
@@ -515,6 +523,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
             /* Insert table row */
             para = ME_AppendTableRow(editor, para->member.para.prev_para);
             /* Put cursor at the start of the new table row */
+            editor->pCursors[0].pPara = para;
             editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
             editor->pCursors[0].nOffset = 0;
             editor->pCursors[1] = editor->pCursors[0];
@@ -526,6 +535,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
       if (i == 0)
         run = ME_FindItemFwd(run, diRun);
       editor->pCursors[i].pRun = run;
+      editor->pCursors[i].pPara = ME_GetParagraph(run);
       editor->pCursors[i].nOffset = 0;
     }
   }
@@ -595,12 +605,13 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow)
  * without a selection. */
 void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor)
 {
-  ME_DisplayItem *para = ME_GetParagraph(editor->pCursors[0].pRun);
-  if (para == ME_GetParagraph(editor->pCursors[1].pRun) &&
+  ME_DisplayItem *para = editor->pCursors[0].pPara;
+  if (para == editor->pCursors[1].pPara &&
       para->member.para.nFlags & MEPF_ROWSTART) {
     /* The cursors should not be at the hidden start row paragraph without
      * a selection, so the cursor is moved into the first cell. */
     para = para->member.para.next_para;
+    editor->pCursors[0].pPara = para;
     editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
     editor->pCursors[0].nOffset = 0;
     editor->pCursors[1] = editor->pCursors[0];
diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c
index 423a6d4..c2f7125 100644
--- a/dlls/riched20/undo.c
+++ b/dlls/riched20/undo.c
@@ -316,7 +316,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
     ME_Cursor tmp;
     ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
     /* the only thing that's needed is paragraph offset, so no need to split runs */
-    ME_JoinParagraphs(editor, ME_GetParagraph(tmp.pRun), TRUE);
+    ME_JoinParagraphs(editor, tmp.pPara, TRUE);
     break;
   }
   case diUndoSplitParagraph:
@@ -329,7 +329,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
     if (tmp.nOffset)
       tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
     assert(pUItem->eol_str);
-    this_para = ME_GetParagraph(tmp.pRun);
+    this_para = tmp.pPara;
     bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART;
     if (bFixRowStart)
     {


More information about the wine-patches mailing list