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 */
|
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,
|
|||||||
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
|
|||||||
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
|
|||||||
} 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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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)
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user