[7/7] richedit: Removed redundant ME_FindItemAtOffset using ME_RunOfsFromCharOfs.

Dylan Smith dylan.ah.smith at gmail.com
Tue Jan 27 02:39:23 CST 2009


The two functions ME_FindItemAtOffset and ME_RunOfsFromCharOfs were almost
identically used, since ME_FindItemAtOffset was always used to find a run.
The only difference was how they returned the offset within the run for an
end of paragraph run.

For ME_FindItemAtOffset it would return the next run if it was in between \r
and \n. ME_RunOfsFromCharOfs would instead return an nOffset of 0 for end
paragraph runs.  This subtle difference introduced bugs, so I decided to
avoid having special case in this function when creating this patch, and
instead let the caller handle this case.

I checked all the calls to ME_CursorFromOffset, ME_RunOfsFromCharOfs, and
ME_FindItemAtOffset to test how it handled should handle the special end of
paragraph run case.  Now all these calls are implemented using
ME_RunOfsFromCharOfs.
---
 dlls/riched20/caret.c  |    9 ++++-
 dlls/riched20/editor.c |   73 +++++++-----------------------------------
 dlls/riched20/editor.h |    1 -
 dlls/riched20/run.c    |   83 ++++++++++++++++++++---------------------------
 dlls/riched20/writer.c |    5 ++-
 5 files changed, 57 insertions(+), 114 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 460f9be..180688a 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -151,8 +151,13 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
     return len;
   }
 
-  ME_RunOfsFromCharOfs(editor, from, &editor->pCursors[1].pRun, &editor->pCursors[1].nOffset);
-  ME_RunOfsFromCharOfs(editor, to, &editor->pCursors[0].pRun, &editor->pCursors[0].nOffset);
+  ME_CursorFromCharOfs(editor, from, &editor->pCursors[1]);
+  ME_CursorFromCharOfs(editor, to, &editor->pCursors[0]);
+  /* Selection is not allowed in the middle of an end paragraph run. */
+  if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA)
+    editor->pCursors[1].nOffset = 0;
+  if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA)
+    editor->pCursors[0].nOffset = 0;
   return to;
 }
 
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index c66026d..b3f92bf 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1624,55 +1624,6 @@ ME_StreamInRTFString(ME_TextEditor *editor, BOOL selection, char *string)
 }
 
 
-ME_DisplayItem *
-ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int *nItemOffset)
-{
-  ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph);
-  int runLength;
-  
-  while (item && item->member.para.next_para->member.para.nCharOfs <= nOffset)
-    item = ME_FindItemFwd(item, diParagraph);
-
-  if (!item)
-    return item;
-
-  nOffset -= item->member.para.nCharOfs;
-  if (nItemType == diParagraph) {
-    if (nItemOffset)
-      *nItemOffset = nOffset;
-    return item;
-  }
-  
-  do {
-    item = ME_FindItemFwd(item, diRun);
-    runLength = ME_StrLen(item->member.run.strText);
-    if (item->member.run.nFlags & MERF_ENDPARA)
-      runLength = item->member.run.nCR + item->member.run.nLF;
-  } while (item && (item->member.run.nCharOfs + runLength <= nOffset));
-  if (item) {
-    nOffset -= item->member.run.nCharOfs;
-
-    /* Special case: nOffset may not point exactly at the division between the
-       \r and the \n in 1.0 emulation. If such a case happens, it is sent
-       into the next run, if one exists
-     */
-    if (   item->member.run.nFlags & MERF_ENDPARA
-        && nOffset == item->member.run.nCR
-        && item->member.run.nLF > 0) {
-      ME_DisplayItem *nextItem;
-      nextItem = ME_FindItemFwd(item, diRun);
-      if (nextItem) {
-        nOffset = 0;
-        item = nextItem;
-      }
-    }
-    if (nItemOffset)
-      *nItemOffset = nOffset;
-  }
-  return item;
-}
-
-
 static int
 ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCHAR *text, CHARRANGE *chrgText)
 {
@@ -1743,7 +1694,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
     if ((flags & FR_WHOLEWORD) && nMin)
     {
       nStart = nMin - 1;
-      item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
+      ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart);
       if (!item)
       {
         if (chrgText)
@@ -1754,7 +1705,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
     }
 
     nStart = nMin;
-    item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
+    ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart);
     if (!item)
     {
       if (chrgText)
@@ -1836,7 +1787,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
     if ((flags & FR_WHOLEWORD) && nMax < nTextLen - 1)
     {
       nEnd = nMax + 1;
-      item = ME_FindItemAtOffset(editor, diRun, nEnd, &nEnd);
+      ME_RunOfsFromCharOfs(editor, nEnd, &item, &nEnd);
       if (!item)
       {
         if (chrgText)
@@ -1847,7 +1798,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
     }
 
     nEnd = nMax;
-    item = ME_FindItemAtOffset(editor, diRun, nEnd, &nEnd);
+    ME_RunOfsFromCharOfs(editor, nEnd, &item, &nEnd);
     if (!item)
     {
       if (chrgText)
@@ -2117,7 +2068,7 @@ static void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor)
 {
   ME_DisplayItem * startPara, * endPara;
   ME_DisplayItem * item;
-  int dummy;
+  ME_Cursor cursor;
   int from, to;
 
   ME_GetSelection(editor, &from, &to);
@@ -2125,15 +2076,17 @@ static void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor)
   startPara = NULL; endPara = NULL;
 
   /* Find paragraph previous to the one that contains start cursor */
-  item = ME_FindItemAtOffset(editor, diRun, from, &dummy);
+  ME_CursorFromCharOfs(editor, from, &cursor);
+  item = cursor.pRun;
   if (item) {
     startPara = ME_FindItemBack(item, diParagraph);
-    item = ME_FindItemBack(startPara, diParagraph);
-    if (item) startPara = item;
+    item = startPara->member.para.prev_para;
+    if (item && item->type == diParagraph) startPara = item;
   }
 
   /* Find paragraph that contains end cursor */
-  item = ME_FindItemAtOffset(editor, diRun, to, &dummy);
+  ME_CursorFromCharOfs(editor, to, &cursor);
+  item = cursor.pRun;
   if (item) {
     endPara = ME_FindItemFwd(item, diParagraph);
   }
@@ -4576,8 +4529,6 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart,
   WCHAR *pStart = buffer;
 
   ME_RunOfsFromCharOfs(editor, nStart, &pRun, &nOffset);
-  /* Get actual offset within run (ME_RunOfsFromCharOfs sets to 0 if MERF_ENDPARA) */
-  nOffset = nStart - ME_GetParagraph(pRun)->member.para.nCharOfs - pRun->member.run.nCharOfs;
 
   /* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */
   if (editor->bEmulateVersion10) bCRLF = 0;
@@ -4772,7 +4723,7 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_
   TRACE("sel_min = %d sel_max = %d\n", sel_min, sel_max);
 
   *candidate_min = *candidate_max = -1;
-  item = ME_FindItemAtOffset(editor, diRun, sel_min, &nStart);
+  ME_RunOfsFromCharOfs(editor, sel_min, &item, &nStart);
   if (!item) return FALSE;
   TRACE("nStart = %d\n", nStart);
   para = ME_GetParagraph(item);
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 484acfb..a5826b1 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -265,7 +265,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
                          LPARAM lParam, BOOL unicode, HRESULT* phresult);
 void ME_SendOldNotify(ME_TextEditor *editor, int nCode);
 int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, BOOL bCRLF);
-ME_DisplayItem *ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int *nItemOffset);
 void ME_RTFCharAttrHook(struct _RTF_Info *info);
 void ME_RTFParAttrHook(struct _RTF_Info *info);
 void ME_RTFTblAttrHook(struct _RTF_Info *info);
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index 8ee95bb..d7fdfa6 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -166,11 +166,11 @@ int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int nOfs)
 
 /******************************************************************************
  * ME_CursorFromCharOfs
- * 
+ *
  * Converts a character offset (relative to the start of the document) to
  * a cursor structure (which contains a run and a position relative to that 
- * run).   
- */      
+ * run).
+ */
 void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor)
 {
   ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pRun, &pCursor->nOffset);
@@ -178,57 +178,42 @@ void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCurso
 
 /******************************************************************************
  * ME_RunOfsFromCharOfs
- * 
+ *
  * Find a run and relative character offset given an absolute character offset
  * (absolute offset being an offset relative to the start of the document).
- * Kind of a "global to local" offset conversion.    
- */      
+ * Kind of a "global to local" offset conversion.
+ */
 void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppRun, int *pOfs)
 {
-  ME_DisplayItem *pPara;
-  int nParaOfs;
+  ME_DisplayItem *item, *next_item;
 
-  pPara = editor->pBuffer->pFirst->member.para.next_para;
-  assert(pPara);
   assert(ppRun);
   assert(pOfs);
-  while (pPara->type == diParagraph)
-  {
-    nParaOfs = pPara->member.para.nCharOfs;
-    assert(nCharOfs >= nParaOfs);
 
-    if (nCharOfs < pPara->member.para.next_para->member.para.nCharOfs)
-    {
-      int eollen = 1;
-      *ppRun = ME_FindItemFwd(pPara, diRun);
-      assert(*ppRun);
-      while (!((*ppRun)->member.run.nFlags & MERF_ENDPARA))
-      {
-        ME_DisplayItem *pNext = ME_FindItemFwd(*ppRun, diRun);
-        assert(pNext);
-        assert(pNext->type == diRun);
-        if (nCharOfs < nParaOfs + pNext->member.run.nCharOfs) {
-          *pOfs = ME_PosToVPos((*ppRun)->member.run.strText,
-            nCharOfs - nParaOfs - (*ppRun)->member.run.nCharOfs);
-          return;
-        }
-        *ppRun = pNext;
-      }
-      /* Recover proper character length of this line break */
-      eollen = (*ppRun)->member.run.nCR + (*ppRun)->member.run.nLF;
-      if (nCharOfs >= nParaOfs + (*ppRun)->member.run.nCharOfs &&
-        nCharOfs < nParaOfs + (*ppRun)->member.run.nCharOfs + eollen) {
-        /* FIXME: Might cause problems when actually requiring an offset in the
-           middle of a run that is considered a single line break */
-        *pOfs = 0;
-        return;
-      }
-    }
-    pPara = pPara->member.para.next_para;
-  }
-  *ppRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
-  *pOfs = 0;
-  assert((*ppRun)->member.run.nFlags & MERF_ENDPARA);
+  nCharOfs = max(nCharOfs, 0);
+  nCharOfs = min(nCharOfs, ME_GetTextLength(editor));
+
+  /* Find the paragraph at the offset. */
+  next_item = editor->pBuffer->pFirst->member.para.next_para;
+  do {
+    item = next_item;
+    next_item = item->member.para.next_para;
+  } while (next_item->member.para.nCharOfs <= nCharOfs);
+  assert(item->type == diParagraph);
+  nCharOfs -= item->member.para.nCharOfs;
+
+  /* Find the run at the offset. */
+  next_item = ME_FindItemFwd(item, diRun);
+  do {
+    item = next_item;
+    next_item = ME_FindItemFwd(item, diRunOrParagraphOrEnd);
+  } while (next_item->type == diRun &&
+           next_item->member.run.nCharOfs <= nCharOfs);
+  assert(item->type == diRun);
+  nCharOfs -= item->member.run.nCharOfs;
+
+  *ppRun = item;
+  *pOfs = nCharOfs;
 }
 
 /******************************************************************************
@@ -621,9 +606,11 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
       ME_GetOLEObjectSize(&c, pRun, &size);
     ITextHost_TxReleaseDC(editor->texthost, c.hDC);
     return nOffset != 0;
+  } else if (pRun->nFlags & MERF_ENDPARA) {
+    nOffset = 0;
   }
-  
-   if (editor->cPasswordMask)
+
+  if (editor->cPasswordMask)
     strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText));
   else
     strRunText = pRun->strText;
diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c
index 98bb9d3..6ae3ccc 100644
--- a/dlls/riched20/writer.c
+++ b/dlls/riched20/writer.c
@@ -916,14 +916,15 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
 static BOOL
 ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nChars, DWORD dwFormat)
 {
-  /* FIXME: use ME_RunOfsFromCharOfs */
-  ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
+  ME_DisplayItem *item;
   int nLen;
   UINT nCodePage = CP_ACP;
   char *buffer = NULL;
   int nBufLen = 0;
   BOOL success = TRUE;
 
+  ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart);
+
   if (!item)
     return FALSE;
    


More information about the wine-patches mailing list