richedit: Fixups to move over to reliance on CR and LF counters.
Text streamout now honors CR and LF counters. Tests to pin down required EM_STREAMOUT behavior.
This commit is contained in:
parent
d47f66191e
commit
8d37388fe7
|
@ -3278,6 +3278,9 @@ LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
||||||
|
|
||||||
editor->bEmulateVersion10 = TRUE;
|
editor->bEmulateVersion10 = TRUE;
|
||||||
editor->pBuffer->pLast->member.para.nCharOfs = 2;
|
editor->pBuffer->pLast->member.para.nCharOfs = 2;
|
||||||
|
assert(editor->pBuffer->pLast->prev->type == diRun);
|
||||||
|
assert(editor->pBuffer->pLast->prev->member.run.nFlags & MERF_ENDPARA);
|
||||||
|
editor->pBuffer->pLast->prev->member.run.nLF = 1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
||||||
|
|
||||||
run = ME_MakeRun(style, ME_MakeString(wszParagraphSign), MERF_ENDPARA);
|
run = ME_MakeRun(style, ME_MakeString(wszParagraphSign), MERF_ENDPARA);
|
||||||
run->member.run.nCharOfs = 0;
|
run->member.run.nCharOfs = 0;
|
||||||
|
run->member.run.nCR = 1;
|
||||||
|
run->member.run.nLF = (editor->bEmulateVersion10) ? 1 : 0;
|
||||||
|
|
||||||
ME_InsertBefore(text->pLast, para);
|
ME_InsertBefore(text->pLast, para);
|
||||||
ME_InsertBefore(text->pLast, run);
|
ME_InsertBefore(text->pLast, run);
|
||||||
|
|
|
@ -127,8 +127,10 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
|
||||||
p->member.run.nFlags,
|
p->member.run.nFlags,
|
||||||
p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
|
p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
|
||||||
assert(ofs == p->member.run.nCharOfs);
|
assert(ofs == p->member.run.nCharOfs);
|
||||||
if (p->member.run.nFlags & MERF_ENDPARA)
|
if (p->member.run.nFlags & MERF_ENDPARA) {
|
||||||
ofs += (editor->bEmulateVersion10 ? 2 : 1);
|
assert(p->member.run.nCR + p->member.run.nLF > 0);
|
||||||
|
ofs += p->member.run.nCR + p->member.run.nLF;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ofs += ME_StrLen(p->member.run.strText);
|
ofs += ME_StrLen(p->member.run.strText);
|
||||||
break;
|
break;
|
||||||
|
@ -209,10 +211,12 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **
|
||||||
}
|
}
|
||||||
*ppRun = pNext;
|
*ppRun = pNext;
|
||||||
}
|
}
|
||||||
/* the handling of bEmulateVersion10 may be a source of many bugs, I'm afraid */
|
/* Recover proper character length of this line break */
|
||||||
eollen = (editor->bEmulateVersion10 ? 2 : 1);
|
eollen = (*ppRun)->member.run.nCR + (*ppRun)->member.run.nLF;
|
||||||
if (nCharOfs >= nParaOfs + (*ppRun)->member.run.nCharOfs &&
|
if (nCharOfs >= nParaOfs + (*ppRun)->member.run.nCharOfs &&
|
||||||
nCharOfs < nParaOfs + (*ppRun)->member.run.nCharOfs + eollen) {
|
nCharOfs < nParaOfs + (*ppRun)->member.run.nCharOfs + eollen) {
|
||||||
|
/* FIXME: Might cause problems when actually requiring an offset in the
|
||||||
|
middle of a run that is considered a single line break */
|
||||||
*pOfs = 0;
|
*pOfs = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1125,6 +1125,60 @@ static void test_WM_SETTEXT()
|
||||||
DestroyWindow(hwndRichEdit);
|
DestroyWindow(hwndRichEdit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_EM_STREAMOUT(void)
|
||||||
|
{
|
||||||
|
HWND hwndRichEdit = new_richedit(NULL);
|
||||||
|
int r;
|
||||||
|
EDITSTREAM es;
|
||||||
|
char buf[1024] = {0};
|
||||||
|
char * p;
|
||||||
|
|
||||||
|
const char * TestItem1 = "TestSomeText";
|
||||||
|
const char * TestItem2 = "TestSomeText\r";
|
||||||
|
const char * TestItem3 = "TestSomeText\r\n";
|
||||||
|
|
||||||
|
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
|
||||||
|
p = buf;
|
||||||
|
es.dwCookie = (DWORD_PTR)&p;
|
||||||
|
es.dwError = 0;
|
||||||
|
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||||
|
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||||
|
r = strlen(buf);
|
||||||
|
ok(r == 12, "streamed text length is %d, expecting 12\n", r);
|
||||||
|
ok(strcmp(buf, TestItem1) == 0,
|
||||||
|
"streamed text different, got %s\n", buf);
|
||||||
|
|
||||||
|
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
|
||||||
|
p = buf;
|
||||||
|
es.dwCookie = (DWORD_PTR)&p;
|
||||||
|
es.dwError = 0;
|
||||||
|
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||||
|
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||||
|
r = strlen(buf);
|
||||||
|
/* Here again, \r gets converted to \r\n, like WM_GETTEXT */
|
||||||
|
ok(r == 14, "streamed text length is %d, expecting 14\n", r);
|
||||||
|
ok(strcmp(buf, TestItem3) == 0,
|
||||||
|
"streamed text different from, got %s\n", buf);
|
||||||
|
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
|
||||||
|
p = buf;
|
||||||
|
es.dwCookie = (DWORD_PTR)&p;
|
||||||
|
es.dwError = 0;
|
||||||
|
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||||
|
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||||
|
r = strlen(buf);
|
||||||
|
ok(r == 14, "streamed text length is %d, expecting 14\n", r);
|
||||||
|
ok(strcmp(buf, TestItem3) == 0,
|
||||||
|
"streamed text different, got %s\n", buf);
|
||||||
|
|
||||||
|
DestroyWindow(hwndRichEdit);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_EM_SETTEXTEX(void)
|
static void test_EM_SETTEXTEX(void)
|
||||||
{
|
{
|
||||||
HWND hwndRichEdit = new_richedit(NULL);
|
HWND hwndRichEdit = new_richedit(NULL);
|
||||||
|
@ -2952,6 +3006,7 @@ START_TEST( editor )
|
||||||
test_EM_EXSETSEL();
|
test_EM_EXSETSEL();
|
||||||
test_WM_PASTE();
|
test_WM_PASTE();
|
||||||
test_EM_STREAMIN();
|
test_EM_STREAMIN();
|
||||||
|
test_EM_STREAMOUT();
|
||||||
test_EM_StreamIn_Undo();
|
test_EM_StreamIn_Undo();
|
||||||
test_EM_FORMATRANGE();
|
test_EM_FORMATRANGE();
|
||||||
test_unicode_conversions();
|
test_unicode_conversions();
|
||||||
|
|
|
@ -711,9 +711,9 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
|
||||||
if (!ME_StreamOutPrint(pStream, "\r\n\\par"))
|
if (!ME_StreamOutPrint(pStream, "\r\n\\par"))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
nChars--;
|
/* Skip as many characters as required by current line break */
|
||||||
if (editor->bEmulateVersion10 && nChars)
|
nChars -= (p->member.run.nCR <= nChars) ? p->member.run.nCR : nChars;
|
||||||
nChars--;
|
nChars -= (p->member.run.nLF <= nChars) ? p->member.run.nLF : nChars;
|
||||||
} else if (p->member.run.nFlags & MERF_ENDROW) {
|
} else if (p->member.run.nFlags & MERF_ENDROW) {
|
||||||
if (!ME_StreamOutPrint(pStream, "\\line \r\n"))
|
if (!ME_StreamOutPrint(pStream, "\\line \r\n"))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -775,10 +775,39 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
|
||||||
if (item->member.run.nFlags & MERF_ENDPARA) {
|
if (item->member.run.nFlags & MERF_ENDPARA) {
|
||||||
static const WCHAR szEOL[2] = { '\r', '\n' };
|
static const WCHAR szEOL[2] = { '\r', '\n' };
|
||||||
|
|
||||||
if (dwFormat & SF_UNICODE)
|
if (!editor->bEmulateVersion10) {
|
||||||
success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
|
/* richedit 2.0 - all line breaks are \r\n */
|
||||||
else
|
if (dwFormat & SF_UNICODE)
|
||||||
success = ME_StreamOutMove(pStream, "\r\n", 2);
|
success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
|
||||||
|
else
|
||||||
|
success = ME_StreamOutMove(pStream, "\r\n", 2);
|
||||||
|
assert(nLen == 1);
|
||||||
|
} else {
|
||||||
|
int i; int tnLen;
|
||||||
|
|
||||||
|
/* richedit 1.0 - need to honor actual \r and \n amounts */
|
||||||
|
nLen = item->member.run.nCR + item->member.run.nLF;
|
||||||
|
if (nLen > nChars)
|
||||||
|
nLen = nChars;
|
||||||
|
tnLen = nLen;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (tnLen > 0 && i < item->member.run.nCR) {
|
||||||
|
if (dwFormat & SF_UNICODE)
|
||||||
|
success = ME_StreamOutMove(pStream, (const char *)(&szEOL[0]), sizeof(WCHAR));
|
||||||
|
else
|
||||||
|
success = ME_StreamOutMove(pStream, "\r", 1);
|
||||||
|
tnLen--; i++;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
while (tnLen > 0 && i < item->member.run.nLF) {
|
||||||
|
if (dwFormat & SF_UNICODE)
|
||||||
|
success = ME_StreamOutMove(pStream, (const char *)(&szEOL[1]), sizeof(WCHAR));
|
||||||
|
else
|
||||||
|
success = ME_StreamOutMove(pStream, "\n", 1);
|
||||||
|
tnLen--; i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dwFormat & SF_UNICODE)
|
if (dwFormat & SF_UNICODE)
|
||||||
success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart),
|
success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart),
|
||||||
|
@ -800,8 +829,6 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
|
||||||
}
|
}
|
||||||
|
|
||||||
nChars -= nLen;
|
nChars -= nLen;
|
||||||
if (editor->bEmulateVersion10 && nChars && item->member.run.nFlags & MERF_ENDPARA)
|
|
||||||
nChars--;
|
|
||||||
nStart = 0;
|
nStart = 0;
|
||||||
item = ME_FindItemFwd(item, diRun);
|
item = ME_FindItemFwd(item, diRun);
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,74 @@ static void test_EM_STREAMIN(void)
|
||||||
DestroyWindow(hwndRichEdit);
|
DestroyWindow(hwndRichEdit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
|
||||||
|
LPBYTE pbBuff,
|
||||||
|
LONG cb,
|
||||||
|
LONG *pcb)
|
||||||
|
{
|
||||||
|
char** str = (char**)dwCookie;
|
||||||
|
*pcb = cb;
|
||||||
|
if (*pcb > 0) {
|
||||||
|
memcpy(*str, pbBuff, *pcb);
|
||||||
|
*str += *pcb;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_EM_STREAMOUT(void)
|
||||||
|
{
|
||||||
|
HWND hwndRichEdit = new_richedit(NULL);
|
||||||
|
int r;
|
||||||
|
EDITSTREAM es;
|
||||||
|
char buf[1024] = {0};
|
||||||
|
char * p;
|
||||||
|
|
||||||
|
const char * TestItem1 = "TestSomeText";
|
||||||
|
const char * TestItem2 = "TestSomeText\r";
|
||||||
|
const char * TestItem3 = "TestSomeText\r\n";
|
||||||
|
|
||||||
|
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
|
||||||
|
p = buf;
|
||||||
|
es.dwCookie = (DWORD_PTR)&p;
|
||||||
|
es.dwError = 0;
|
||||||
|
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||||
|
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||||
|
r = strlen(buf);
|
||||||
|
ok(r == 12, "streamed text length is %d, expecting 12\n", r);
|
||||||
|
ok(strcmp(buf, TestItem1) == 0,
|
||||||
|
"streamed text different, got %s\n", buf);
|
||||||
|
|
||||||
|
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
|
||||||
|
p = buf;
|
||||||
|
es.dwCookie = (DWORD_PTR)&p;
|
||||||
|
es.dwError = 0;
|
||||||
|
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
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;
|
||||||
|
es.dwError = 0;
|
||||||
|
es.pfnCallback = test_WM_SETTEXT_esCallback;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
SendMessage(hwndRichEdit, EM_STREAMOUT,
|
||||||
|
(WPARAM)(SF_TEXT), (LPARAM)&es);
|
||||||
|
r = strlen(buf);
|
||||||
|
ok(r == 14, "streamed text length is %d, expecting 14\n", r);
|
||||||
|
ok(strcmp(buf, TestItem3) == 0,
|
||||||
|
"streamed text different, got %s\n", buf);
|
||||||
|
|
||||||
|
DestroyWindow(hwndRichEdit);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST( editor )
|
START_TEST( editor )
|
||||||
{
|
{
|
||||||
|
@ -298,6 +366,7 @@ START_TEST( editor )
|
||||||
test_WM_SETTEXT();
|
test_WM_SETTEXT();
|
||||||
test_WM_GETTEXTLENGTH();
|
test_WM_GETTEXTLENGTH();
|
||||||
test_EM_STREAMIN();
|
test_EM_STREAMIN();
|
||||||
|
test_EM_STREAMOUT();
|
||||||
|
|
||||||
/* Set the environment variable WINETEST_RICHED32 to keep windows
|
/* Set the environment variable WINETEST_RICHED32 to keep windows
|
||||||
* responsive and open for 30 seconds. This is useful for debugging.
|
* responsive and open for 30 seconds. This is useful for debugging.
|
||||||
|
|
Loading…
Reference in New Issue