diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index feb99c30eb8..a07f086bafb 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -24,7 +24,7 @@ API implementation status: Messages (ANSI versions not done yet) - - EM_AUTOURLDETECT 2.0 + + EM_AUTOURLDETECT 2.0 + EM_CANPASTE + EM_CANREDO 2.0 + EM_CANUNDO @@ -40,7 +40,7 @@ - EM_FINDWORDBREAK - EM_FMTLINES - EM_FORMATRANGE - - EM_GETAUTOURLDETECT 2.0 + + EM_GETAUTOURLDETECT 2.0 - EM_GETBIDIOPTIONS 3.0 - EM_GETCHARFORMAT (partly done) - EM_GETEDITSTYLE @@ -1290,13 +1290,11 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP switch(msg) { - UNSUPPORTED_MSG(EM_AUTOURLDETECT) UNSUPPORTED_MSG(EM_DISPLAYBAND) UNSUPPORTED_MSG(EM_EXLIMITTEXT) UNSUPPORTED_MSG(EM_FINDWORDBREAK) UNSUPPORTED_MSG(EM_FMTLINES) UNSUPPORTED_MSG(EM_FORMATRANGE) - UNSUPPORTED_MSG(EM_GETAUTOURLDETECT) UNSUPPORTED_MSG(EM_GETBIDIOPTIONS) UNSUPPORTED_MSG(EM_GETEDITSTYLE) UNSUPPORTED_MSG(EM_GETIMECOMPMODE) @@ -1447,6 +1445,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP ME_SendSelChange(editor); return 0; } + case EM_AUTOURLDETECT: + { + if (wParam==1 || wParam ==0) + { + editor->AutoURLDetect_bEnable = (BOOL)wParam; + return 0; + } + return E_INVALIDARG; + } + case EM_GETAUTOURLDETECT: + { + return editor->AutoURLDetect_bEnable; + } case EM_EXSETSEL: { CHARRANGE *pRange = (CHARRANGE *)lParam; @@ -2089,7 +2100,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP case WM_CHAR: { WCHAR wstr = LOWORD(wParam); - + if (editor->AutoURLDetect_bEnable) + ME_AutoURLDetect(editor, wstr); + switch (wstr) { case 3: /* Ctrl-C */ @@ -2513,3 +2526,95 @@ LRESULT WINAPI REExtendedRegisterClass(void) return result; } + +int ME_AutoURLDetect(ME_TextEditor *editor, WCHAR curChar) +{ + struct prefix_s { + char *text; + int length; + } prefixes[12] = { + {"http:", 5}, + {"file:", 6}, + {"mailto:", 8}, + {"ftp:", 5}, + {"https:", 7}, + {"gopher:", 8}, + {"nntp:", 6}, + {"prospero:", 10}, + {"telnet:", 8}, + {"news:", 6}, + {"wais:", 6}, + {"www.", 5} + }; + CHARRANGE ins_pt; + int curf_ef, link_ef, def_ef; + int cur_prefx, prefx_cnt; + int sel_min, sel_max; + int car_pos = 0; + int text_pos=-1; + int URLmin, URLmax; + CHARRANGE url; + FINDTEXTA ft; + CHARFORMAT2W cur_format; + CHARFORMAT2W default_format; + CHARFORMAT2W link; + RichEditANSIWndProc(editor->hWnd, EM_EXGETSEL, (WPARAM) 0, (LPARAM) &ins_pt); + sel_min = ins_pt.cpMin; + sel_max = ins_pt.cpMax; + if (sel_min==sel_max) + car_pos = sel_min; + if (sel_min!=sel_max) + car_pos = ME_GetTextLength(editor)+1; + cur_format.cbSize = sizeof(cur_format); + default_format.cbSize = sizeof(default_format); + RichEditANSIWndProc(editor->hWnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM) &cur_format); + RichEditANSIWndProc(editor->hWnd, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM) &default_format); + link.cbSize = sizeof(link); + link.dwMask = CFM_LINK | CFM_COLOR | CFM_UNDERLINE; + link.dwEffects = CFE_LINK | CFE_UNDERLINE; + link.crTextColor = RGB(0,0,255); + curf_ef = cur_format.dwEffects & link.dwEffects; + def_ef = default_format.dwEffects & link.dwEffects; + link_ef = link.dwEffects & link.dwEffects; + if (curf_ef == link_ef) + { + if( curChar == '\n' || curChar=='\r' || curChar==' ') + { + ME_SetSelection(editor, car_pos, car_pos); + RichEditANSIWndProc(editor->hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &default_format); + text_pos=-1; + return 0; + } + } + if (curf_ef == def_ef) + { + cur_prefx = 0; + prefx_cnt = (sizeof(prefixes)/sizeof(struct prefix_s))-1; + while (cur_prefx<=prefx_cnt) + { + if (text_pos == -1) + { + ft.lpstrText = prefixes[cur_prefx].text; + URLmin=max(0,(car_pos-prefixes[cur_prefx].length)); + URLmax=max(0, car_pos); + if ((car_pos == 0) && (ME_GetTextLength(editor) != 0)) + { + URLmax = ME_GetTextLength(editor)+1; + } + ft.chrg.cpMin = URLmin; + ft.chrg.cpMax = URLmax; + text_pos=RichEditANSIWndProc(editor->hWnd, EM_FINDTEXT, FR_DOWN, (LPARAM)&ft); + cur_prefx++; + } + if (text_pos != -1) + { + url.cpMin=text_pos; + url.cpMax=car_pos-1; + ME_SetCharFormat(editor, text_pos, (URLmax-text_pos), &link); + ME_Repaint(editor); + break; + } + } + } + return 0; +} diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 7376e28def8..5cafda13662 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -250,7 +250,7 @@ void ME_EmptyUndoStack(ME_TextEditor *editor); int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, BOOL bCRLF); ME_DisplayItem *ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int *nItemOffset); void ME_StreamInFill(ME_InStream *stream); - +int ME_AutoURLDetect(ME_TextEditor *editor, WCHAR curChar); extern int me_debug; extern HANDLE me_heap; extern void DoWrap(ME_TextEditor *editor); diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 17cf2d87918..0911e909379 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -317,6 +317,7 @@ typedef struct tagME_TextEditor *TM_SINGLECODEPAGE or TM_MULTICODEPAGE*/ int mode; BOOL bHideSelection; + BOOL AutoURLDetect_bEnable; } ME_TextEditor; typedef struct tagME_Context diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 4f34a6620be..8835f083bf5 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -536,6 +536,79 @@ static void test_EM_SETOPTIONS() DestroyWindow(hwndRichEdit); } +static void check_CFE_LINK_rcvd(HWND hwnd, int is_url) +{ + CHARFORMAT2W text_format; + int link_present = 0; + text_format.cbSize = sizeof(text_format); + SendMessage(hwnd, EM_SETSEL, 0, 0); + SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM) &text_format); + link_present = text_format.dwEffects & CFE_LINK; + if (is_url) + { /* control text is url; should get CFE_LINK */ + ok(0 != link_present, "URL Case: CFE_LINK not set.\n"); + } + else + { + ok(0 == link_present, "Non-URL Case: CFE_LINK set.\n"); + } +} + +static HWND new_static_wnd(HWND parent) { + return new_window("Static", 0, parent); +} + +static void test_EM_AUTOURLDETECT(void) +{ + struct urls_s { + char *text; + int is_url; + } urls[12] = { + {"winehq.org", 0}, + {"http://www.winehq.org", 1}, + {"http//winehq.org", 0}, + {"ww.winehq.org", 0}, + {"www.winehq.org", 1}, + {"ftp://192.168.1.1", 1}, + {"ftp//192.168.1.1", 0}, + {"mailto:your@email.com", 1}, + {"prospero:prosperoserver", 1}, + {"telnet:test", 1}, + {"news:newserver", 1}, + {"wais:waisserver", 1} + }; + + int i; + int urlRet=-1; + HWND hwndRichEdit, parent; + + parent = new_static_wnd(NULL); + hwndRichEdit = new_richedit(parent); + /* Try and pass EM_AUTOURLDETECT some test wParam values */ + urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, FALSE, 0); + ok(urlRet==0, "Good wParam: urlRet is: %d\n", urlRet); + urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, 1, 0); + ok(urlRet==0, "Good wParam2: urlRet is: %d\n", urlRet); + /* Windows returns -2147024809 (0x80070057) on bad wParam values */ + urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, 8, 0); + ok(urlRet==E_INVALIDARG, "Bad wParam: urlRet is: %d\n", urlRet); + urlRet=SendMessage(hwndRichEdit, EM_AUTOURLDETECT, (WPARAM)"h", (LPARAM)"h"); + ok(urlRet==E_INVALIDARG, "Bad wParam2: urlRet is: %d\n", urlRet); + /* for each url, check the text to see if CFE_LINK effect is present */ + for (i = 0; i < sizeof(urls)/sizeof(struct urls_s); i++) { + SendMessage(hwndRichEdit, EM_AUTOURLDETECT, FALSE, 0); + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) urls[i].text); + SendMessage(hwndRichEdit, WM_CHAR, 0, 0); + check_CFE_LINK_rcvd(hwndRichEdit, 0); + SendMessage(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0); + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) urls[i].text); + SendMessage(hwndRichEdit, WM_CHAR, 0, 0); + check_CFE_LINK_rcvd(hwndRichEdit, urls[i].is_url); + } + DestroyWindow(hwndRichEdit); + DestroyWindow(parent); +} + static void test_EM_SCROLL() { int i, j; @@ -686,7 +759,6 @@ START_TEST( editor ) * RICHED20.DLL, so the linker doesn't actually link to it. */ hmoduleRichEdit = LoadLibrary("RICHED20.DLL"); ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); - test_EM_FINDTEXT(); test_EM_SCROLLCARET(); test_EM_SCROLL(); @@ -694,6 +766,7 @@ START_TEST( editor ) test_TM_PLAINTEXT(); test_EM_SETOPTIONS(); test_WM_GETTEXT(); + test_EM_AUTOURLDETECT(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging.