From d95cbeef671186421da94a585d6201e524e428d0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alex=20Villac=C3=ADs=20Lasso?= Date: Sat, 26 Apr 2008 18:14:13 -0500 Subject: [PATCH] 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 da61cd280f..01502bf67d 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 d78c7f6e9b..28b4ce5293 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 106cd650f2..6fe027b7b8 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. -- 2.32.0.93.g670b81a890