richedit: End of line sequence limited to 2 carriage returns.

riched32.dll does preserve the carriage returns and line feeds unlike
later versions of the richedit control, however the tests previously
missed the fact that a sequence of carriage returns followed by a line
feed (e.g. \r\r\r\n) can actually cause multiple paragraph breaks.
This commit is contained in:
Dylan Smith 2009-01-27 03:38:49 -05:00 committed by Alexandre Julliard
parent 29ddbce288
commit 0832737427
2 changed files with 51 additions and 105 deletions

View File

@ -517,107 +517,66 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
if(editor->nTextLimit < oldLen +len) if(editor->nTextLimit < oldLen +len)
editor->nTextLimit = oldLen + len; editor->nTextLimit = oldLen + len;
pos = str;
while (len) while (len)
{ {
pos = str;
/* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */ /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t') while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
pos++; pos++;
if (pos-str < len && *pos == '\t') { /* handle tabs */
if (pos != str) { /* handle text */
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
} else if (*pos == '\t') { /* handle tabs */
WCHAR tab = '\t'; WCHAR tab = '\t';
if (pos!=str)
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB); ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
pos++; pos++;
if(pos-str <= len) { } else { /* handle EOLs */
len -= pos - str;
str = pos;
continue;
}
}
/* handle special \r\r\n sequence (richedit 2.x and higher only) */
if (!editor->bEmulateVersion10 && pos-str < len-2 && pos[0] == '\r' && pos[1] == '\r' && pos[2] == '\n') {
WCHAR space = ' ';
if (pos!=str)
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
pos+=3;
if(pos-str <= len) {
len -= pos - str;
str = pos;
continue;
}
}
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; int numCR, numLF;
if (pos!=str) /* Find number of CR and LF in end of paragraph run */
ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0); numCR = 0; numLF = 0;
p = &editor->pCursors[nCursor]; if (*pos =='\r')
if (p->nOffset) { {
ME_SplitRunSimple(editor, p->pRun, p->nOffset); numCR++;
p = &editor->pCursors[nCursor]; if (len > 1 && pos[1] == '\n')
} numLF++;
tmp_style = ME_GetInsertStyle(editor, nCursor); else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
/* ME_SplitParagraph increases style refcount */ numCR++, numLF++;
/* 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) {
/* 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;
numLF = 1;
} else {
/* Found some other content past the run of \r's */
pos++;
numCR = 1; numLF = 0;
}
} else { } else {
if(pos-str < len && *pos =='\r') assert(*pos == '\n');
pos++; numLF++;
if(pos-str < len && *pos =='\n')
pos++;
numCR = 1; numLF = 0;
} }
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 0); pos += 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 (!editor->bEmulateVersion10 && numCR == 2 && numLF == 1)
len -= pos - str; {
str = pos; /* handle special \r\r\n sequence (richedit 2.x and higher only) */
continue; WCHAR space = ' ';
ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
} else {
if (!editor->bEmulateVersion10)
numCR = 1, numLF = 0;
p = &editor->pCursors[nCursor];
if (p->nOffset) {
ME_SplitRunSimple(editor, p->pRun, p->nOffset);
p = &editor->pCursors[nCursor];
}
tmp_style = ME_GetInsertStyle(editor, nCursor);
/* ME_SplitParagraph increases style refcount */
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 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;
} }
} }
ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0); len -= pos - str;
len = 0; str = pos;
} }
} }

View File

@ -392,12 +392,8 @@ static void test_EM_GETLINE(void)
/* EM_GETLINE appends a "\r\0" to the end of the line /* EM_GETLINE appends a "\r\0" to the end of the line
* nCopied counts up to and including the '\r' */ * nCopied counts up to and including the '\r' */
nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest); nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest);
if (i >= 1 && i <= 4) ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
todo_wine ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied, expected_nCopied);
expected_nCopied);
else
ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
expected_nCopied);
/* two special cases since a parameter is passed via dest */ /* two special cases since a parameter is passed via dest */
if (gl[i].buffer_len == 0) if (gl[i].buffer_len == 0)
ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2), ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
@ -407,20 +403,11 @@ static void test_EM_GETLINE(void)
!strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n"); !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
else else
{ {
if (i >= 1 && i <= 4) ok(!strncmp(dest, gl[i].text, expected_bytes_written),
todo_wine ok(!strncmp(dest, gl[i].text, expected_bytes_written), "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
"%d: expected_bytes_written=%d\n", i, expected_bytes_written); ok(!strncmp(dest + expected_bytes_written, origdest
else + expected_bytes_written, nBuf - expected_bytes_written),
ok(!strncmp(dest, gl[i].text, expected_bytes_written), "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
if (i >= 1 && i <= 2)
todo_wine ok(!strncmp(dest + expected_bytes_written, origdest
+ expected_bytes_written, nBuf - expected_bytes_written),
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
else
ok(!strncmp(dest + expected_bytes_written, origdest
+ expected_bytes_written, nBuf - expected_bytes_written),
"%d: expected_bytes_written=%d\n", i, expected_bytes_written);
} }
} }