Commit 4047df0f authored by Alex Villacís Lasso's avatar Alex Villacís Lasso Committed by Alexandre Julliard

richedit: Flip the big switch and encode actual CR and LF into end-of-paragraph runs.

Document remaining uses of bEmulateVersion10 and other checks for CRLF in editor.c. Make RTF reader emit a \r or a \r\n according to emulation, not a \n, which breaks streaming tests. Remove todo_wine from a bunch of riched32 tests that now succeed.
parent 3a271386
...@@ -524,6 +524,8 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, ...@@ -524,6 +524,8 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
if (pos-str < len) { /* handle EOLs */ if (pos-str < len) { /* handle EOLs */
ME_DisplayItem *tp, *end_run; ME_DisplayItem *tp, *end_run;
ME_Style *tmp_style; ME_Style *tmp_style;
int numCR, numLF;
if (pos!=str) if (pos!=str)
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0); ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
p = &editor->pCursors[nCursor]; p = &editor->pCursors[nCursor];
...@@ -534,38 +536,47 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, ...@@ -534,38 +536,47 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
tmp_style = ME_GetInsertStyle(editor, nCursor); tmp_style = ME_GetInsertStyle(editor, nCursor);
/* ME_SplitParagraph increases style refcount */ /* ME_SplitParagraph increases style refcount */
/* TODO: move here and fix logic for pos updating according to emulation, /* Encode and fill number of CR and LF according to emulation mode */
so that number of CR and LF encoded are a result of such logic, instead
of hardcoded as below.
*/
if (editor->bEmulateVersion10)
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, 1, 1);
else
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, 1, 0);
p->pRun = ME_FindItemFwd(tp, diRun);
end_run = ME_FindItemBack(tp, diRun);
ME_ReleaseStyle(end_run->member.run.style);
end_run->member.run.style = tmp_style;
p->nOffset = 0;
if (editor->bEmulateVersion10) { if (editor->bEmulateVersion10) {
const WCHAR * tpos; const WCHAR * tpos;
/* We have to find out how many consecutive \r are there, and if there
is a \n terminating the run of \r's. */
numCR = 0; numLF = 0;
tpos = pos; tpos = pos;
while (tpos-str < len && *tpos == '\r') { while (tpos-str < len && *tpos == '\r') {
tpos++; tpos++;
numCR++;
} }
if (tpos-str >= len) { if (tpos-str >= len) {
if (tpos != pos) pos++; /* Reached end of text without finding anything but '\r' */
} else if (*tpos == '\n') if (tpos != pos) {
pos++;
}
numCR = 1; numLF = 0;
} else if (*tpos == '\n') {
/* The entire run of \r's plus the one \n is one single line break */
pos = tpos + 1; pos = tpos + 1;
else numLF = 1;
} else {
/* Found some other content past the run of \r's */
pos++; pos++;
numCR = 1; numLF = 0;
}
} else { } else {
if(pos-str < len && *pos =='\r') if(pos-str < len && *pos =='\r')
pos++; pos++;
if(pos-str < len && *pos =='\n') if(pos-str < len && *pos =='\n')
pos++; pos++;
numCR = 1; numLF = 0;
} }
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF);
p->pRun = ME_FindItemFwd(tp, diRun);
end_run = ME_FindItemBack(tp, diRun);
ME_ReleaseStyle(end_run->member.run.style);
end_run->member.run.style = tmp_style;
p->nOffset = 0;
if(pos-str <= len) { if(pos-str <= len) {
len -= pos - str; len -= pos - str;
str = pos; str = pos;
......
...@@ -1101,7 +1101,10 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ...@@ -1101,7 +1101,10 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
if (parser.lpRichEditOle) if (parser.lpRichEditOle)
IRichEditOle_Release(parser.lpRichEditOle); IRichEditOle_Release(parser.lpRichEditOle);
/* Remove last line break, as mandated by tests */ /* Remove last line break, as mandated by tests. This is not affected by
CR/LF counters, since RTF streaming presents only \para tokens, which
are converted according to the standard rules: \r for 2.0, \r\n for 1.0
*/
if (stripLastCR) { if (stripLastCR) {
int newfrom, newto; int newfrom, newto;
ME_GetSelection(editor, &newfrom, &newto); ME_GetSelection(editor, &newfrom, &newto);
...@@ -1213,6 +1216,21 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int ...@@ -1213,6 +1216,21 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int
} while (item && (item->member.run.nCharOfs + runLength <= nOffset)); } while (item && (item->member.run.nCharOfs + runLength <= nOffset));
if (item) { if (item) {
nOffset -= item->member.run.nCharOfs; 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) if (nItemOffset)
*nItemOffset = nOffset; *nItemOffset = nOffset;
} }
...@@ -2487,6 +2505,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ...@@ -2487,6 +2505,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{ {
GETTEXTLENGTHEX how; GETTEXTLENGTHEX how;
/* CR/LF conversion required in 2.0 mode, verbatim in 1.0 mode */
how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS; how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS;
how.codepage = unicode ? 1200 : CP_ACP; how.codepage = unicode ? 1200 : CP_ACP;
return ME_GetTextLengthEx(editor, &how); return ME_GetTextLengthEx(editor, &how);
...@@ -2552,7 +2571,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ...@@ -2552,7 +2571,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
else else
{ {
/* potentially each char may be a CR, why calculate the exact value with O(N) when /* potentially each char may be a CR, why calculate the exact value with O(N) when
we can just take a bigger buffer? :) */ we can just take a bigger buffer? :)
The above assumption still holds with CR/LF counters, since CR->CRLF expansion
occurs only in richedit 2.0 mode, in which line breaks have only one CR
*/
int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1; int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1;
LPWSTR buffer; LPWSTR buffer;
DWORD buflen = ex->cb; DWORD buflen = ex->cb;
......
...@@ -2605,7 +2605,8 @@ static void SpecialChar (RTF_Info *info) ...@@ -2605,7 +2605,8 @@ static void SpecialChar (RTF_Info *info)
case rtfSect: case rtfSect:
case rtfRow: case rtfRow:
case rtfPar: case rtfPar:
RTFPutUnicodeChar (info, '\n'); RTFPutUnicodeChar (info, '\r');
if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n');
break; break;
case rtfNoBrkSpace: case rtfNoBrkSpace:
RTFPutUnicodeChar (info, 0x00A0); RTFPutUnicodeChar (info, 0x00A0);
......
...@@ -110,21 +110,21 @@ static void test_WM_SETTEXT() ...@@ -110,21 +110,21 @@ static void test_WM_SETTEXT()
} }
TEST_SETTEXT(TestItem1, TestItem1, 1, 0, 0) TEST_SETTEXT(TestItem1, TestItem1, 1, 0, 0)
TEST_SETTEXT(TestItem2, TestItem2, 1, 1, 1) TEST_SETTEXT(TestItem2, TestItem2, 1, 0, 1)
TEST_SETTEXT(TestItem3, TestItem3, 2, 1, 1) TEST_SETTEXT(TestItem3, TestItem3, 2, 0, 1)
TEST_SETTEXT(TestItem4, TestItem4, 3, 1, 0) TEST_SETTEXT(TestItem4, TestItem4, 3, 0, 0)
TEST_SETTEXT(TestItem5, TestItem5, 2, 1, 0) TEST_SETTEXT(TestItem5, TestItem5, 2, 0, 0)
TEST_SETTEXT(TestItem6, TestItem6, 3, 1, 0) TEST_SETTEXT(TestItem6, TestItem6, 3, 0, 0)
TEST_SETTEXT(TestItem7, TestItem7, 4, 1, 0) TEST_SETTEXT(TestItem7, TestItem7, 4, 0, 0)
TEST_SETTEXT(TestItem8, TestItem8, 2, 0, 0) TEST_SETTEXT(TestItem8, TestItem8, 2, 0, 0)
TEST_SETTEXT(TestItem9, TestItem9, 3, 0, 0) TEST_SETTEXT(TestItem9, TestItem9, 3, 0, 0)
TEST_SETTEXT(TestItem10, TestItem10, 3, 0, 0) TEST_SETTEXT(TestItem10, TestItem10, 3, 0, 0)
TEST_SETTEXT(TestItem11, TestItem11, 1, 0, 0) TEST_SETTEXT(TestItem11, TestItem11, 1, 0, 0)
TEST_SETTEXT(TestItem12, TestItem12, 2, 0, 0) TEST_SETTEXT(TestItem12, TestItem12, 2, 0, 0)
TEST_SETTEXT(TestItem13, TestItem13, 3, 0, 0) TEST_SETTEXT(TestItem13, TestItem13, 3, 0, 0)
TEST_SETTEXT(TestItem14, TestItem14, 2, 1, 0) TEST_SETTEXT(TestItem14, TestItem14, 2, 0, 0)
TEST_SETTEXT(TestItem15, TestItem15, 3, 1, 1) TEST_SETTEXT(TestItem15, TestItem15, 3, 0, 1)
TEST_SETTEXT(TestItem16, TestItem16, 4, 1, 0) TEST_SETTEXT(TestItem16, TestItem16, 4, 0, 0)
#undef TEST_SETTEXT #undef TEST_SETTEXT
DestroyWindow(hwndRichEdit); DestroyWindow(hwndRichEdit);
...@@ -332,11 +332,11 @@ static void test_EM_STREAMOUT(void) ...@@ -332,11 +332,11 @@ static void test_EM_STREAMOUT(void)
SendMessage(hwndRichEdit, EM_STREAMOUT, SendMessage(hwndRichEdit, EM_STREAMOUT,
(WPARAM)(SF_TEXT), (LPARAM)&es); (WPARAM)(SF_TEXT), (LPARAM)&es);
r = strlen(buf); r = strlen(buf);
todo_wine { /* Currently fails because of solitary \r mangling */
ok(r == 13, "streamed text length is %d, expecting 13\n", r); ok(r == 13, "streamed text length is %d, expecting 13\n", r);
ok(strcmp(buf, TestItem2) == 0, ok(strcmp(buf, TestItem2) == 0,
"streamed text different, got %s\n", buf); "streamed text different, got %s\n", buf);
}
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
p = buf; p = buf;
es.dwCookie = (DWORD_PTR)&p; es.dwCookie = (DWORD_PTR)&p;
...@@ -360,8 +360,8 @@ static const struct getline_s { ...@@ -360,8 +360,8 @@ static const struct getline_s {
int wine_todo; int wine_todo;
} gl[] = { } gl[] = {
{0, 10, "foo bar\r\n", 0}, {0, 10, "foo bar\r\n", 0},
{1, 10, "\n", 1}, {1, 10, "\n", 0},
{2, 10, "bar\n", 1}, {2, 10, "bar\n", 0},
{3, 10, "\r\n", 0}, {3, 10, "\r\n", 0},
/* Buffer smaller than line length */ /* Buffer smaller than line length */
...@@ -493,9 +493,9 @@ static void test_EM_GETTEXTRANGE(void) ...@@ -493,9 +493,9 @@ static void test_EM_GETTEXTRANGE(void)
result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange); result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n", ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n",
result, strlen(expect2)); result, strlen(expect2));
todo_wine {
ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer); ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
}
DestroyWindow(hwndRichEdit); DestroyWindow(hwndRichEdit);
} }
...@@ -524,9 +524,9 @@ static void test_EM_GETSELTEXT(void) ...@@ -524,9 +524,9 @@ static void test_EM_GETSELTEXT(void)
result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer); result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n", ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n",
result, strlen(expect2)); result, strlen(expect2));
todo_wine {
ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer); ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
}
DestroyWindow(hwndRichEdit); DestroyWindow(hwndRichEdit);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment