richedit: Add more tests for URL autodetection on WM_CHAR, make them pass under Wine.

This commit is contained in:
Alex Villacís Lasso 2008-06-18 11:05:52 -05:00 committed by Alexandre Julliard
parent 38d7ba6eff
commit 4a5d100097
3 changed files with 290 additions and 16 deletions

View File

@ -1558,6 +1558,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
else
return TRUE;
ME_CommitUndo(editor);
ME_UpdateSelectionLinkAttribute(editor);
ME_UpdateRepaint(editor);
ME_SendRequestResize(editor, FALSE);
return TRUE;
@ -2456,19 +2457,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
TRACE("WM_SETTEXT - NULL\n");
if (editor->AutoURLDetect_bEnable)
{
int cMin = 0, cMax = -1;
while (ME_FindNextURLCandidate(editor, cMin, cMax, &cMin, &cMax))
{
if (ME_IsCandidateAnURL(editor, cMin, cMax)) {
CHARFORMAT2W link;
link.cbSize = sizeof(link);
link.dwMask = CFM_LINK;
link.dwEffects = CFE_LINK;
ME_SetCharFormat(editor, cMin, cMax - cMin, &link);
}
cMin = cMax;
cMax = -1;
}
ME_UpdateLinkAttribute(editor, 0, -1);
}
ME_SetSelection(editor, 0, 0);
editor->nModifyStep = 0;
@ -3052,9 +3041,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
CHAR charA = wParam;
MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1);
}
if (editor->AutoURLDetect_bEnable)
ME_AutoURLDetect(editor, wstr);
switch (wstr)
{
case 1: /* Ctrl-A */
@ -3103,6 +3090,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_ReleaseStyle(style);
ME_CommitUndo(editor);
}
if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor);
ME_UpdateRepaint(editor);
}
return 0;
@ -3887,3 +3877,128 @@ BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max)
if (bufferW != NULL) heap_free(bufferW);
return FALSE;
}
/**
* This proc walks through the indicated selection and evaluates whether each
* section identified by ME_FindNextURLCandidate and in-between sections have
* their proper CFE_LINK attributes set or unset. If the CFE_LINK attribute is
* not what it is supposed to be, this proc sets or unsets it as appropriate.
*
* Returns TRUE if at least one section was modified.
*/
BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max)
{
BOOL modified = FALSE;
int cMin, cMax;
if (sel_max == -1) sel_max = ME_GetTextLength(editor);
do
{
int beforeURL[2];
int inURL[2];
CHARFORMAT2W link;
if (ME_FindNextURLCandidate(editor, sel_min, sel_max, &cMin, &cMax))
{
/* Section before candidate is not an URL */
beforeURL[0] = sel_min;
beforeURL[1] = cMin;
if (ME_IsCandidateAnURL(editor, cMin, cMax))
{
inURL[0] = cMin; inURL[1] = cMax;
}
else
{
beforeURL[1] = cMax;
inURL[0] = inURL[1] = -1;
}
sel_min = cMax;
}
else
{
/* No more candidates until end of selection */
beforeURL[0] = sel_min;
beforeURL[1] = sel_max;
inURL[0] = inURL[1] = -1;
sel_min = sel_max;
}
if (beforeURL[0] < beforeURL[1])
{
/* CFE_LINK effect should be consistently unset */
link.cbSize = sizeof(link);
ME_GetCharFormat(editor, beforeURL[0], beforeURL[1], &link);
/* FIXME: Workaround for what looks like a bug - ME_GetCharFormat does not
clear the CFM_LINK flag when selection spans text without CFE_LINK,
followed by CFE_LINK set. This needs a test for EM_GETCHARFORMAT */
#if 0
if (!(link.dwMask & CFM_LINK) || (link.dwEffects & CFE_LINK))
{
#endif
/* CFE_LINK must be unset from this range */
memset(&link, 0, sizeof(CHARFORMAT2W));
link.cbSize = sizeof(link);
link.dwMask = CFM_LINK;
link.dwEffects = 0;
ME_SetCharFormat(editor, beforeURL[0], beforeURL[1] - beforeURL[0], &link);
modified = TRUE;
#if 0
}
#endif
}
if (inURL[0] < inURL[1])
{
/* CFE_LINK effect should be consistently set */
link.cbSize = sizeof(link);
ME_GetCharFormat(editor, inURL[0], inURL[1], &link);
if (!(link.dwMask & CFM_LINK) || !(link.dwEffects & CFE_LINK))
{
/* CFE_LINK must be set on this range */
memset(&link, 0, sizeof(CHARFORMAT2W));
link.cbSize = sizeof(link);
link.dwMask = CFM_LINK;
link.dwEffects = CFE_LINK;
ME_SetCharFormat(editor, inURL[0], inURL[1] - inURL[0], &link);
modified = TRUE;
}
}
} while (sel_min < sel_max);
return modified;
}
void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor)
{
ME_DisplayItem * startPara, * endPara;
ME_DisplayItem * item;
int dummy;
int from, to;
ME_GetSelection(editor, &from, &to);
if (from > to) from ^= to, to ^=from, from ^= to;
startPara = NULL; endPara = NULL;
/* Find paragraph previous to the one that contains start cursor */
item = ME_FindItemAtOffset(editor, diRun, from, &dummy);
if (item) {
startPara = ME_FindItemBack(item, diParagraph);
item = ME_FindItemBack(startPara, diParagraph);
if (item) startPara = item;
}
/* Find paragraph that contains end cursor */
item = ME_FindItemAtOffset(editor, diRun, to, &dummy);
if (item) {
endPara = ME_FindItemFwd(item, diParagraph);
}
if (startPara && endPara) {
ME_UpdateLinkAttribute(editor,
startPara->member.para.nCharOfs,
endPara->member.para.nCharOfs);
} else if (startPara) {
ME_UpdateLinkAttribute(editor,
startPara->member.para.nCharOfs,
-1);
}
}

View File

@ -282,6 +282,8 @@ extern void DoWrap(ME_TextEditor *editor);
extern BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_max,
int * candidate_min, int * candidate_max);
extern BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max);
BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max);
void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor);
/* undo.c */
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi);

View File

@ -1040,6 +1040,7 @@ static void test_EM_AUTOURLDETECT(void)
"This is some text with X\\ on it",
};
char buffer[1024];
MSG msg;
parent = new_static_wnd(NULL);
hwndRichEdit = new_richedit(parent);
@ -1222,6 +1223,162 @@ static void test_EM_AUTOURLDETECT(void)
hwndRichEdit = NULL;
}
#define INSERT_CR \
do { \
keybd_event('\r', 0x1c, 0, 0); \
keybd_event('\r', 0x1c, KEYEVENTF_KEYUP, 0); \
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { \
TranslateMessage(&msg); \
DispatchMessage(&msg); \
} \
} while (0)
#define INSERT_BS \
do { \
keybd_event(0x08, 0x0e, 0, 0); \
keybd_event(0x08, 0x0e, KEYEVENTF_KEYUP, 0); \
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { \
TranslateMessage(&msg); \
DispatchMessage(&msg); \
} \
} while (0)
/* Test detection of URLs within normal text - WM_CHAR case. */
for (i = 0; i < sizeof(urls)/sizeof(struct urls_s); i++) {
hwndRichEdit = new_richedit(parent);
for (j = 0; j < sizeof(templates_delim) / sizeof(const char *); j++) {
char * at_pos;
int at_offset;
int end_offset;
int u, v;
at_pos = strchr(templates_delim[j], 'X');
at_offset = at_pos - templates_delim[j];
end_offset = at_offset + strlen(urls[i].text);
SendMessage(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
for (u = 0; templates_delim[j][u]; u++) {
if (templates_delim[j][u] == '\r') {
INSERT_CR;
} else if (templates_delim[j][u] != 'X') {
SendMessage(hwndRichEdit, WM_CHAR, templates_delim[j][u], 1);
} else {
for (v = 0; urls[i].text[v]; v++) {
SendMessage(hwndRichEdit, WM_CHAR, urls[i].text[v], 1);
}
}
}
SendMessage(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
trace("Using template: %s\n", templates_delim[j]);
/* This assumes no templates start with the URL itself, and that they
have at least two characters before the URL text */
ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
if (urls[i].is_url)
{
ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
"CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
"CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
}
else
{
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
}
if (buffer[end_offset] != '\0')
{
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
if (buffer[end_offset +1] != '\0')
{
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
}
}
/* The following will insert a paragraph break after the first character
of the URL candidate, thus breaking the URL. It is expected that the
CFE_LINK attribute should break across both pieces of the URL */
SendMessage(hwndRichEdit, EM_SETSEL, at_offset+1, at_offset+1);
INSERT_CR;
SendMessage(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
/* end_offset moved because of paragraph break */
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset+1, buffer);
if (buffer[end_offset+1] != '\0')
{
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset+1, end_offset +2),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset+1, end_offset +2, buffer);
if (buffer[end_offset +2] != '\0')
{
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +2, end_offset +3),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +2, end_offset +3, buffer);
}
}
/* The following will remove the just-inserted paragraph break, thus
restoring the URL */
SendMessage(hwndRichEdit, EM_SETSEL, at_offset+2, at_offset+2);
INSERT_BS;
SendMessage(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
if (urls[i].is_url)
{
ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
"CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
"CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
}
else
{
ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
}
if (buffer[end_offset] != '\0')
{
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
if (buffer[end_offset +1] != '\0')
{
ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
"CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
}
}
}
DestroyWindow(hwndRichEdit);
hwndRichEdit = NULL;
}
DestroyWindow(parent);
}