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.
This commit is contained in:
parent
3a271386ec
commit
4047df0f56
@ -524,6 +524,8 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||
if (pos-str < len) { /* handle EOLs */
|
||||
ME_DisplayItem *tp, *end_run;
|
||||
ME_Style *tmp_style;
|
||||
int numCR, numLF;
|
||||
|
||||
if (pos!=str)
|
||||
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
|
||||
p = &editor->pCursors[nCursor];
|
||||
@ -534,38 +536,47 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||
tmp_style = ME_GetInsertStyle(editor, nCursor);
|
||||
/* ME_SplitParagraph increases style refcount */
|
||||
|
||||
/* TODO: move here and fix logic for pos updating according to emulation,
|
||||
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;
|
||||
/* Encode and fill number of CR and LF according to emulation mode */
|
||||
if (editor->bEmulateVersion10) {
|
||||
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;
|
||||
while (tpos-str < len && *tpos == '\r') {
|
||||
tpos++;
|
||||
numCR++;
|
||||
}
|
||||
if (tpos-str >= len) {
|
||||
if (tpos != pos) pos++;
|
||||
} else if (*tpos == '\n')
|
||||
/* Reached end of text without finding anything but '\r' */
|
||||
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;
|
||||
else
|
||||
numLF = 1;
|
||||
} else {
|
||||
/* Found some other content past the run of \r's */
|
||||
pos++;
|
||||
numCR = 1; numLF = 0;
|
||||
}
|
||||
} else {
|
||||
if(pos-str < len && *pos =='\r')
|
||||
pos++;
|
||||
if(pos-str < len && *pos =='\n')
|
||||
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) {
|
||||
len -= pos - str;
|
||||
str = pos;
|
||||
|
@ -1101,7 +1101,10 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
||||
if (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) {
|
||||
int newfrom, newto;
|
||||
ME_GetSelection(editor, &newfrom, &newto);
|
||||
@ -1213,6 +1216,21 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int
|
||||
} 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;
|
||||
}
|
||||
@ -2487,6 +2505,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
|
||||
{
|
||||
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.codepage = unicode ? 1200 : CP_ACP;
|
||||
return ME_GetTextLengthEx(editor, &how);
|
||||
@ -2552,7 +2571,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
LPWSTR buffer;
|
||||
DWORD buflen = ex->cb;
|
||||
|
@ -2605,7 +2605,8 @@ static void SpecialChar (RTF_Info *info)
|
||||
case rtfSect:
|
||||
case rtfRow:
|
||||
case rtfPar:
|
||||
RTFPutUnicodeChar (info, '\n');
|
||||
RTFPutUnicodeChar (info, '\r');
|
||||
if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n');
|
||||
break;
|
||||
case rtfNoBrkSpace:
|
||||
RTFPutUnicodeChar (info, 0x00A0);
|
||||
|
@ -110,21 +110,21 @@ static void test_WM_SETTEXT()
|
||||
}
|
||||
|
||||
TEST_SETTEXT(TestItem1, TestItem1, 1, 0, 0)
|
||||
TEST_SETTEXT(TestItem2, TestItem2, 1, 1, 1)
|
||||
TEST_SETTEXT(TestItem3, TestItem3, 2, 1, 1)
|
||||
TEST_SETTEXT(TestItem4, TestItem4, 3, 1, 0)
|
||||
TEST_SETTEXT(TestItem5, TestItem5, 2, 1, 0)
|
||||
TEST_SETTEXT(TestItem6, TestItem6, 3, 1, 0)
|
||||
TEST_SETTEXT(TestItem7, TestItem7, 4, 1, 0)
|
||||
TEST_SETTEXT(TestItem2, TestItem2, 1, 0, 1)
|
||||
TEST_SETTEXT(TestItem3, TestItem3, 2, 0, 1)
|
||||
TEST_SETTEXT(TestItem4, TestItem4, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem5, TestItem5, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem6, TestItem6, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem7, TestItem7, 4, 0, 0)
|
||||
TEST_SETTEXT(TestItem8, TestItem8, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem9, TestItem9, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem10, TestItem10, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem11, TestItem11, 1, 0, 0)
|
||||
TEST_SETTEXT(TestItem12, TestItem12, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem13, TestItem13, 3, 0, 0)
|
||||
TEST_SETTEXT(TestItem14, TestItem14, 2, 1, 0)
|
||||
TEST_SETTEXT(TestItem15, TestItem15, 3, 1, 1)
|
||||
TEST_SETTEXT(TestItem16, TestItem16, 4, 1, 0)
|
||||
TEST_SETTEXT(TestItem14, TestItem14, 2, 0, 0)
|
||||
TEST_SETTEXT(TestItem15, TestItem15, 3, 0, 1)
|
||||
TEST_SETTEXT(TestItem16, TestItem16, 4, 0, 0)
|
||||
|
||||
#undef TEST_SETTEXT
|
||||
DestroyWindow(hwndRichEdit);
|
||||
@ -332,11 +332,11 @@ static void test_EM_STREAMOUT(void)
|
||||
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||
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(strcmp(buf, TestItem2) == 0,
|
||||
"streamed text different, got %s\n", buf);
|
||||
}
|
||||
|
||||
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
|
||||
p = buf;
|
||||
es.dwCookie = (DWORD_PTR)&p;
|
||||
@ -360,8 +360,8 @@ static const struct getline_s {
|
||||
int wine_todo;
|
||||
} gl[] = {
|
||||
{0, 10, "foo bar\r\n", 0},
|
||||
{1, 10, "\n", 1},
|
||||
{2, 10, "bar\n", 1},
|
||||
{1, 10, "\n", 0},
|
||||
{2, 10, "bar\n", 0},
|
||||
{3, 10, "\r\n", 0},
|
||||
|
||||
/* Buffer smaller than line length */
|
||||
@ -493,9 +493,9 @@ static void test_EM_GETTEXTRANGE(void)
|
||||
result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n",
|
||||
result, strlen(expect2));
|
||||
todo_wine {
|
||||
|
||||
ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
}
|
||||
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
@ -524,9 +524,9 @@ static void test_EM_GETSELTEXT(void)
|
||||
result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
|
||||
ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n",
|
||||
result, strlen(expect2));
|
||||
todo_wine {
|
||||
|
||||
ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
|
||||
}
|
||||
|
||||
|
||||
DestroyWindow(hwndRichEdit);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user