richedit: Add more tests for URL autodetection on WM_CHAR, make them pass under Wine.
This commit is contained in:
parent
38d7ba6eff
commit
4a5d100097
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue