From b03c70a8454381a5607e6755f8a9bd1bebf2c6f0 Mon Sep 17 00:00:00 2001 From: Roger Hoang Date: Sat, 18 Feb 2006 22:32:24 -0800 Subject: [PATCH] riched20: Implemented EM_SETTEXTMODE options TM_RICHTEXT and TM_PLAINTEXT and their tests. --- dlls/riched20/editor.c | 53 ++++++-- dlls/riched20/editstr.h | 5 + dlls/riched20/tests/editor.c | 235 +++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 13 deletions(-) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index fd3137a027..4028468065 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -594,7 +594,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre editor->nEventMask = 0; ME_GetSelection(editor, &from, &to); - if (format & SFF_SELECTION) { + if ((format & SFF_SELECTION) && (editor->mode & TM_RICHTEXT)) { style = ME_GetSelectionInsertStyle(editor); ME_InternalDeleteText(editor, from, to-from); @@ -1015,6 +1015,7 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { ed->nInvalidOfs = -1; ed->pfnWordBreak = NULL; ed->lpOleCallback = NULL; + ed->mode = TM_RICHTEXT | TM_MULTILEVELUNDO | TM_MULTICODEPAGE; GetClientRect(hWnd, &ed->rcFormat); for (i=0; imode & TM_PLAINTEXT)) ME_SetDefaultCharFormat(editor, p); else if (wParam == (SCF_WORD | SCF_SELECTION)) FIXME("EM_SETCHARFORMAT: word selection not supported\n"); @@ -1748,16 +1748,17 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP ME_GetTextW(editor, data, from, to-from, TRUE); GlobalUnlock(hData); - gds.hData = GlobalAlloc(GMEM_MOVEABLE, 0); - gds.nLength = 0; - es.dwCookie = (DWORD)&gds; - es.pfnCallback = ME_AppendToHGLOBAL; - ME_StreamOutRange(editor, SF_RTF, from, to, &es); - GlobalReAlloc(gds.hData, gds.nLength+1, 0); - - SetClipboardData(CF_UNICODETEXT, hData); - SetClipboardData(RegisterClipboardFormatA("Rich Text Format"), gds.hData); - + if (editor->mode & TM_RICHTEXT) + { + gds.hData = GlobalAlloc(GMEM_MOVEABLE, 0); + gds.nLength = 0; + es.dwCookie = (DWORD)&gds; + es.pfnCallback = ME_AppendToHGLOBAL; + ME_StreamOutRange(editor, SF_RTF, from, to, &es); + GlobalReAlloc(gds.hData, gds.nLength+1, 0); + SetClipboardData(RegisterClipboardFormatA("Rich Text Format"), gds.hData); + } + SetClipboardData(CF_UNICODETEXT, hData); CloseClipboard(); if (msg == WM_CUT) { @@ -2237,6 +2238,32 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP editor->pfnWordBreak = (EDITWORDBREAKPROCW)lParam; return (LRESULT)pfnOld; } + case EM_SETTEXTMODE: + { + LRESULT ret; + int mask = 0; + int changes = 0; + if ((ret = RichEditANSIWndProc(hWnd, WM_GETTEXTLENGTH, 0, 0)) == 0) + { + /*Check for valid wParam*/ + if ((((wParam & TM_RICHTEXT) && ((wParam & TM_PLAINTEXT) << 1))) || + (((wParam & TM_MULTILEVELUNDO) && ((wParam & TM_SINGLELEVELUNDO) << 1))) || + (((wParam & TM_MULTICODEPAGE) && ((wParam & TM_SINGLECODEPAGE) << 1)))) + return 1; + else + { + if (wParam & (TM_RICHTEXT | TM_PLAINTEXT)) + { + mask |= (TM_RICHTEXT | TM_PLAINTEXT); + changes |= (wParam & (TM_RICHTEXT | TM_PLAINTEXT)); + } + /*FIXME: Currently no support for undo level and code page options*/ + editor->mode = (editor->mode & (~mask)) | changes; + return 0; + } + } + return ret; + } default: do_default: return DefWindowProcW(hWnd, msg, wParam, lParam); diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 3b8adbbe51..380b128202 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -308,6 +308,11 @@ typedef struct tagME_TextEditor int nInvalidOfs; EDITWORDBREAKPROCW pfnWordBreak; LPRICHEDITOLECALLBACK lpOleCallback; + /*TEXTMODE variable; contains only one of each of the following options: + *TM_RICHTEXT or TM_PLAINTEXT + *TM_SINGLELEVELUNDO or TM_MULTILEVELUNDO + *TM_SINGLECODEPAGE or TM_MULTICODEPAGE*/ + int mode; } ME_TextEditor; typedef struct tagME_Context diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 908bb90ffd..aa4d1d47dd 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -255,6 +255,239 @@ static void test_EM_SCROLLCARET(void) DestroyWindow(hwndRichEdit); } +static void test_EM_SETTEXTMODE(void) +{ + HWND hwndRichEdit = new_richedit(NULL); + CHARFORMAT2 cf2, cf2test; + CHARRANGE cr; + int rc = 0; + + /*Test that EM_SETTEXTMODE fails if text exists within the control*/ + /*Insert text into the control*/ + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); + + /*Attempt to change the control to plain text mode*/ + rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_PLAINTEXT, 0); + ok(rc != 0, "EM_SETTEXTMODE: changed text mode in control containing text - returned: %d\n", rc); + + /*Test that EM_SETTEXTMODE does not allow rich edit text to be pasted. + If rich text is pasted, it should have the same formatting as the rest + of the text in the control*/ + + /*Italicize the text + *NOTE: If the default text was already italicized, the test will simply + reverse; in other words, it will copy a regular "wine" into a plain + text window that uses an italicized format*/ + cf2.cbSize = sizeof(CHARFORMAT2); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT, + (LPARAM) &cf2); + + cf2.dwMask = CFM_ITALIC | cf2.dwMask; + cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects; + + /*EM_SETCHARFORMAT is not yet fully implemented for all WPARAMs in wine; + however, SCF_ALL has been implemented*/ + SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); + + /*Select the string "wine"*/ + cr.cpMin = 0; + cr.cpMax = 4; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /*Copy the italicized "wine" to the clipboard*/ + SendMessage(hwndRichEdit, WM_COPY, 0, 0); + + /*Reset the formatting to default*/ + cf2.dwEffects = CFE_ITALIC^cf2.dwEffects; + SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + + /*Clear the text in the control*/ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) ""); + + /*Switch to Plain Text Mode*/ + rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_PLAINTEXT, 0); + ok(rc == 0, "EM_SETTEXTMODE: unable to switch to plain text mode with empty control: returned: %d\n", rc); + + /*Input "wine" again in normal format*/ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); + + /*Paste the italicized "wine" into the control*/ + SendMessage(hwndRichEdit, WM_PASTE, 0, 0); + + /*Select a character from the first "wine" string*/ + cr.cpMin = 2; + cr.cpMax = 3; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /*Retrieve its formatting*/ + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, + (LPARAM) &cf2); + + /*Select a character from the second "wine" string*/ + cr.cpMin = 5; + cr.cpMax = 6; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /*Retrieve its formatting*/ + cf2test.cbSize = sizeof(CHARFORMAT2); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, + (LPARAM) &cf2test); + + /*Compare the two formattings*/ + ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects), + "two formats found in plain text mode - cf2.dwEffects: %f cf2test.dwEffects: %f\n",(double) cf2.dwEffects, (double) cf2test.dwEffects); + /*Test TM_RICHTEXT by: switching back to Rich Text mode + printing "wine" in the current format(normal) + pasting "wine" from the clipboard(italicized) + comparing the two formats(should differ)*/ + + /*Attempt to switch with text in control*/ + rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_RICHTEXT, 0); + ok(rc != 0, "EM_SETTEXTMODE: changed from plain text to rich text with text in control - returned: %d\n", rc); + + /*Clear control*/ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) ""); + + /*Switch into Rich Text mode*/ + rc = SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_RICHTEXT, 0); + ok(rc == 0, "EM_SETTEXTMODE: unable to change to rich text with empty control - returned: %d\n", rc); + + /*Print "wine" in normal formatting into the control*/ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); + + /*Paste italicized "wine" into the control*/ + SendMessage(hwndRichEdit, WM_PASTE, 0, 0); + + /*Select text from the first "wine" string*/ + cr.cpMin = 1; + cr.cpMax = 3; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /*Retrieve its formatting*/ + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, + (LPARAM) &cf2); + + /*Select text from the second "wine" string*/ + cr.cpMin = 6; + cr.cpMax = 7; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /*Retrieve its formatting*/ + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, + (LPARAM) &cf2test); + + /*Test that the two formattings are not the same*/ + ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects != cf2test.dwEffects), + "expected different formats - cf2.dwMask: %f, cf2test.dwMask: %f, cf2.dwEffects: %f, cf2test.dwEffects: %f\n", + (double) cf2.dwMask, (double) cf2test.dwMask, (double) cf2.dwEffects, (double) cf2test.dwEffects); + + DestroyWindow(hwndRichEdit); +} + +static void test_TM_PLAINTEXT() +{ + /*Tests plain text properties*/ + + HWND hwndRichEdit = new_richedit(NULL); + CHARFORMAT2 cf2, cf2test; + CHARRANGE cr; + + /*Switch to plain text mode*/ + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) ""); + SendMessage(hwndRichEdit, EM_SETTEXTMODE, TM_PLAINTEXT, 0); + + /*Fill control with text*/ + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "Is Wine an emulator? No it's not"); + + /*Select some text and bold it*/ + + cr.cpMin = 10; + cr.cpMax = 20; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + cf2.cbSize = sizeof(CHARFORMAT2); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT, + (LPARAM) &cf2); + + cf2.dwMask = CFM_BOLD | cf2.dwMask; + cf2.dwEffects = CFE_BOLD ^ cf2.dwEffects; + + SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2); + + /*Get the formatting of those characters*/ + + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2); + + /*Get the formatting of some other characters*/ + cf2test.cbSize = sizeof(CHARFORMAT2); + cr.cpMin = 21; + cr.cpMax = 30; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2test); + + /*Test that they are the same as plain text allows only one formatting*/ + + ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects), + "two selections' formats differ - cf2.dwMask: %f, cf2test.dwMask %f, cf2.dwEffects: %f, cf2test.dwEffects: %f\n", + (double) cf2.dwMask, (double) cf2test.dwMask, (double) cf2.dwEffects, (double) cf2test.dwEffects); + + /*Fill the control with a "wine" string, which when inserted will be bold*/ + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); + + /*Copy the bolded "wine" string*/ + + cr.cpMin = 0; + cr.cpMax = 4; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + SendMessage(hwndRichEdit, WM_COPY, 0, 0); + + /*Swap back to rich text*/ + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) ""); + SendMessage(hwndRichEdit, EM_SETTEXTMODE, (WPARAM) TM_RICHTEXT, 0); + + /*Set the default formatting to bold italics*/ + + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT, (LPARAM) &cf2); + cf2.dwMask |= CFM_ITALIC; + cf2.dwEffects ^= CFE_ITALIC; + SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + + /*Set the text in the control to "wine", which will be bold and italicized*/ + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); + + /*Paste the plain text "wine" string, which should take the insert + formatting, which at the moment is bold italics*/ + + SendMessage(hwndRichEdit, WM_PASTE, 0, 0); + + /*Select the first "wine" string and retrieve its formatting*/ + + cr.cpMin = 1; + cr.cpMax = 3; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2); + + /*Select the second "wine" string and retrieve its formatting*/ + + cr.cpMin = 5; + cr.cpMax = 7; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2test); + + /*Compare the two formattings. They should be the same.*/ + + ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects), + "Copied text retained formatting - cf2.dwMask: %f, cf2test.dwMask: %f, cf2.dwEffects: %f, cf2test.dwEffects: %f", + (double) cf2.dwMask, (double) cf2test.dwMask, (double) cf2.dwEffects, (double) cf2test.dwEffects); + DestroyWindow(hwndRichEdit); +} + START_TEST( editor ) { MSG msg; @@ -267,6 +500,8 @@ START_TEST( editor ) test_EM_FINDTEXT(); test_EM_SCROLLCARET(); + test_EM_SETTEXTMODE(); + test_TM_PLAINTEXT(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging.