Alex Villacís Lasso : richedit: EM_LINELENGTH: honor CR and LF counters.

Alexandre Julliard julliard at winehq.org
Tue Apr 29 08:54:45 CDT 2008


Module: wine
Branch: master
Commit: d95cbeef671186421da94a585d6201e524e428d0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d95cbeef671186421da94a585d6201e524e428d0

Author: Alex Villacís Lasso <a_villacis at palosanto.com>
Date:   Sat Apr 26 18:14:13 2008 -0500

richedit: EM_LINELENGTH: honor CR and LF counters.

Add fixup to ME_FindItemAtOffset(), fixes crash by null-pointer access.
Add tests for EM_LINELENGTH.

---

 dlls/riched20/editor.c       |   19 ++++++++++++++++---
 dlls/riched20/tests/editor.c |   36 +++++++++++++++++++++++++++++++++++-
 dlls/riched32/tests/editor.c |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index da61cd2..01502bf 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1190,6 +1190,7 @@ 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);
@@ -1206,7 +1207,10 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int
   
   do {
     item = ME_FindItemFwd(item, diRun);
-  } while (item && (item->member.run.nCharOfs + ME_StrLen(item->member.run.strText) <= nOffset));
+    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;
     if (nItemOffset)
@@ -2735,8 +2739,17 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
     if (item_end->type == diStartRow)
       nNextLineOfs = ME_CharOfsFromRunOfs(editor, ME_FindItemFwd(item_end, diRun), 0);
     else
-      nNextLineOfs = ME_FindItemFwd(item, diParagraphOrEnd)->member.para.nCharOfs
-       - (editor->bEmulateVersion10?2:1);
+    {
+      ME_DisplayItem *endPara;
+
+      nNextLineOfs = ME_FindItemFwd(item, diParagraphOrEnd)->member.para.nCharOfs;
+      endPara = ME_FindItemFwd(item, diParagraphOrEnd);
+      endPara = ME_FindItemBack(endPara, diRun);
+      assert(endPara);
+      assert(endPara->type == diRun);
+      assert(endPara->member.run.nFlags & MERF_ENDPARA);
+      nNextLineOfs -= endPara->member.run.nCR + endPara->member.run.nLF;
+    }
     nChars = nNextLineOfs - nThisLineOfs;
     TRACE("EM_LINELENGTH(%ld)==%d\n",wParam, nChars);
     return nChars;
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index d78c7f6..28b4ce5 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -261,6 +261,40 @@ static void test_EM_GETLINE(void)
   DestroyWindow(hwndRichEdit);
 }
 
+static void test_EM_LINELENGTH(void)
+{
+  HWND hwndRichEdit = new_richedit(NULL);
+  const char * text =
+        "richedit1\r"
+        "richedit1\n"
+        "richedit1\r\n"
+        "richedit1";
+  int offset_test[10][2] = {
+        {0, 9},
+        {5, 9},
+        {10, 9},
+        {15, 9},
+        {20, 9},
+        {25, 9},
+        {30, 9},
+        {35, 9},
+        {40, 0},
+        {45, 0},
+  };
+  int i;
+  LRESULT result;
+
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
+
+  for (i = 0; i < 10; i++) {
+    result = SendMessage(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
+    ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
+        offset_test[i][0], result, offset_test[i][1]);
+  }
+
+  DestroyWindow(hwndRichEdit);
+}
+
 static int get_scroll_pos_y(HWND hwnd)
 {
   POINT p = {-1, -1};
@@ -2972,7 +3006,6 @@ static void test_eventMask(void)
 
 }
 
-
 START_TEST( editor )
 {
   MSG msg;
@@ -2989,6 +3022,7 @@ START_TEST( editor )
   test_EM_SCROLLCARET();
   test_EM_SCROLL();
   test_WM_SETTEXT();
+  test_EM_LINELENGTH();
   test_EM_SETCHARFORMAT();
   test_EM_SETTEXTMODE();
   test_TM_PLAINTEXT();
diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c
index 106cd65..6fe027b 100644
--- a/dlls/riched32/tests/editor.c
+++ b/dlls/riched32/tests/editor.c
@@ -430,6 +430,39 @@ static void test_EM_GETLINE(void)
   DestroyWindow(hwndRichEdit);
 }
 
+static void test_EM_LINELENGTH(void)
+{
+  HWND hwndRichEdit = new_richedit(NULL);
+  const char * text =
+        "richedit1\r"
+        "richedit1\n"
+        "richedit1\r\n"
+        "richedit1\r\r\r\r\r\n";
+  int offset_test[10][2] = {
+        {0, 9},
+        {5, 9},
+        {10, 9},
+        {15, 9},
+        {20, 9},
+        {25, 9},
+        {30, 9},
+        {35, 9},
+        {40, 9}, /* <----- in the middle of the \r run, but run not counted */
+        {45, 0},
+  };
+  int i;
+  LRESULT result;
+
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
+
+  for (i = 0; i < 10; i++) {
+    result = SendMessage(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
+    ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
+        offset_test[i][0], result, offset_test[i][1]);
+  }
+
+  DestroyWindow(hwndRichEdit);
+}
 
 START_TEST( editor )
 {
@@ -446,6 +479,7 @@ START_TEST( editor )
   test_EM_STREAMIN();
   test_EM_STREAMOUT();
   test_EM_GETLINE();
+  test_EM_LINELENGTH();
 
   /* Set the environment variable WINETEST_RICHED32 to keep windows
    * responsive and open for 30 seconds. This is useful for debugging.




More information about the wine-cvs mailing list