1c2c66affSColin Finck /*
2c2c66affSColin Finck * Unit test suite for rich edit control
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2006 Google (Thomas Kho)
5c2c66affSColin Finck * Copyright 2007 Matt Finnicum
6c2c66affSColin Finck * Copyright 2007 Dmitry Timoshkov
7c2c66affSColin Finck *
8c2c66affSColin Finck * This library is free software; you can redistribute it and/or
9c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
10c2c66affSColin Finck * License as published by the Free Software Foundation; either
11c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
12c2c66affSColin Finck *
13c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
14c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
15c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16c2c66affSColin Finck * Lesser General Public License for more details.
17c2c66affSColin Finck *
18c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
19c2c66affSColin Finck * License along with this library; if not, write to the Free Software
20c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21c2c66affSColin Finck */
22c2c66affSColin Finck 
239e90c368SAmine Khaldi #define COBJMACROS
249e90c368SAmine Khaldi 
25c2c66affSColin Finck #include <stdarg.h>
26c2c66affSColin Finck #include <stdio.h>
27c2c66affSColin Finck #include <assert.h>
28c2c66affSColin Finck #include <windef.h>
29c2c66affSColin Finck #include <winbase.h>
30c2c66affSColin Finck #include <wingdi.h>
31c2c66affSColin Finck #include <winuser.h>
32c2c66affSColin Finck #include <winnls.h>
33c2c66affSColin Finck #include <ole2.h>
34c2c66affSColin Finck #include <richedit.h>
359e90c368SAmine Khaldi #include <richole.h>
36c2c66affSColin Finck #include <commdlg.h>
37c2c66affSColin Finck #include <time.h>
38c2c66affSColin Finck #include <wine/test.h>
39c2c66affSColin Finck 
40c2c66affSColin Finck #define ID_RICHEDITTESTDBUTTON 0x123
41c2c66affSColin Finck 
42c2c66affSColin Finck static CHAR string1[MAX_PATH], string2[MAX_PATH], string3[MAX_PATH];
43c2c66affSColin Finck 
44c2c66affSColin Finck #define ok_w3(format, szString1, szString2, szString3) \
45c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \
46c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \
47c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, szString3, -1, string3, MAX_PATH, NULL, NULL); \
48c2c66affSColin Finck     ok(!lstrcmpW(szString3, szString1) || !lstrcmpW(szString3, szString2), \
49c2c66affSColin Finck        format, string1, string2, string3);
50c2c66affSColin Finck 
51c2c66affSColin Finck static HMODULE hmoduleRichEdit;
52c2c66affSColin Finck static BOOL is_lang_japanese;
53c2c66affSColin Finck 
new_window(LPCSTR lpClassName,DWORD dwStyle,HWND parent)54c2c66affSColin Finck static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) {
55c2c66affSColin Finck   HWND hwnd;
56c2c66affSColin Finck   hwnd = CreateWindowA(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
57c2c66affSColin Finck                       |WS_VISIBLE, 0, 0, 200, 60, parent, NULL,
58c2c66affSColin Finck                       hmoduleRichEdit, NULL);
59c2c66affSColin Finck   ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
60c2c66affSColin Finck   return hwnd;
61c2c66affSColin Finck }
62c2c66affSColin Finck 
new_windowW(LPCWSTR lpClassName,DWORD dwStyle,HWND parent)63c2c66affSColin Finck static HWND new_windowW(LPCWSTR lpClassName, DWORD dwStyle, HWND parent) {
64c2c66affSColin Finck   HWND hwnd;
65c2c66affSColin Finck   hwnd = CreateWindowW(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
66c2c66affSColin Finck                       |WS_VISIBLE, 0, 0, 200, 60, parent, NULL,
67c2c66affSColin Finck                       hmoduleRichEdit, NULL);
68c2c66affSColin Finck   ok(hwnd != NULL, "class: %s, error: %d\n", wine_dbgstr_w(lpClassName), (int) GetLastError());
69c2c66affSColin Finck   return hwnd;
70c2c66affSColin Finck }
71c2c66affSColin Finck 
new_richedit(HWND parent)72c2c66affSColin Finck static HWND new_richedit(HWND parent) {
73c2c66affSColin Finck   return new_window(RICHEDIT_CLASS20A, ES_MULTILINE, parent);
74c2c66affSColin Finck }
75c2c66affSColin Finck 
new_richedit_with_style(HWND parent,DWORD style)7644f07538SAmine Khaldi static HWND new_richedit_with_style(HWND parent, DWORD style) {
7744f07538SAmine Khaldi   return new_window(RICHEDIT_CLASS20A, style, parent);
7844f07538SAmine Khaldi }
7944f07538SAmine Khaldi 
new_richeditW(HWND parent)80c2c66affSColin Finck static HWND new_richeditW(HWND parent) {
81c2c66affSColin Finck   return new_windowW(RICHEDIT_CLASS20W, ES_MULTILINE, parent);
82c2c66affSColin Finck }
83c2c66affSColin Finck 
84c2c66affSColin Finck /* Keeps the window reponsive for the deley_time in seconds.
85c2c66affSColin Finck  * This is useful for debugging a test to see what is happening. */
keep_responsive(time_t delay_time)86c2c66affSColin Finck static void keep_responsive(time_t delay_time)
87c2c66affSColin Finck {
88c2c66affSColin Finck     MSG msg;
89c2c66affSColin Finck     time_t end;
90c2c66affSColin Finck 
91c2c66affSColin Finck     /* The message pump uses PeekMessage() to empty the queue and then
92c2c66affSColin Finck      * sleeps for 50ms before retrying the queue. */
93c2c66affSColin Finck     end = time(NULL) + delay_time;
94c2c66affSColin Finck     while (time(NULL) < end) {
95c2c66affSColin Finck       if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
96c2c66affSColin Finck         TranslateMessage(&msg);
97c2c66affSColin Finck         DispatchMessageA(&msg);
98c2c66affSColin Finck       } else {
99c2c66affSColin Finck         Sleep(50);
100c2c66affSColin Finck       }
101c2c66affSColin Finck     }
102c2c66affSColin Finck }
103c2c66affSColin Finck 
simulate_typing_characters(HWND hwnd,const char * szChars)104c2c66affSColin Finck static void simulate_typing_characters(HWND hwnd, const char* szChars)
105c2c66affSColin Finck {
106c2c66affSColin Finck     int ret;
107c2c66affSColin Finck 
108c2c66affSColin Finck     while (*szChars != '\0') {
109c2c66affSColin Finck         SendMessageA(hwnd, WM_KEYDOWN, *szChars, 1);
110c2c66affSColin Finck         ret = SendMessageA(hwnd, WM_CHAR, *szChars, 1);
111c2c66affSColin Finck         ok(ret == 0, "WM_CHAR('%c') ret=%d\n", *szChars, ret);
112c2c66affSColin Finck         SendMessageA(hwnd, WM_KEYUP, *szChars, 1);
113c2c66affSColin Finck         szChars++;
114c2c66affSColin Finck     }
115c2c66affSColin Finck }
116c2c66affSColin Finck 
hold_key(int vk)117c2c66affSColin Finck static BOOL hold_key(int vk)
118c2c66affSColin Finck {
119c2c66affSColin Finck   BYTE key_state[256];
120c2c66affSColin Finck   BOOL result;
121c2c66affSColin Finck 
122c2c66affSColin Finck   result = GetKeyboardState(key_state);
123c2c66affSColin Finck   ok(result, "GetKeyboardState failed.\n");
124c2c66affSColin Finck   if (!result) return FALSE;
125c2c66affSColin Finck   key_state[vk] |= 0x80;
126c2c66affSColin Finck   result = SetKeyboardState(key_state);
127c2c66affSColin Finck   ok(result, "SetKeyboardState failed.\n");
128c2c66affSColin Finck   return result != 0;
129c2c66affSColin Finck }
130c2c66affSColin Finck 
release_key(int vk)131c2c66affSColin Finck static BOOL release_key(int vk)
132c2c66affSColin Finck {
133c2c66affSColin Finck   BYTE key_state[256];
134c2c66affSColin Finck   BOOL result;
135c2c66affSColin Finck 
136c2c66affSColin Finck   result = GetKeyboardState(key_state);
137c2c66affSColin Finck   ok(result, "GetKeyboardState failed.\n");
138c2c66affSColin Finck   if (!result) return FALSE;
139c2c66affSColin Finck   key_state[vk] &= ~0x80;
140c2c66affSColin Finck   result = SetKeyboardState(key_state);
141c2c66affSColin Finck   ok(result, "SetKeyboardState failed.\n");
142c2c66affSColin Finck   return result != 0;
143c2c66affSColin Finck }
144c2c66affSColin Finck 
145c2c66affSColin Finck static const char haystack[] = "WINEWine wineWine wine WineWine";
146c2c66affSColin Finck                              /* ^0        ^10       ^20       ^30 */
147c2c66affSColin Finck 
148c2c66affSColin Finck struct find_s {
149c2c66affSColin Finck   int start;
150c2c66affSColin Finck   int end;
151c2c66affSColin Finck   const char *needle;
152c2c66affSColin Finck   int flags;
153c2c66affSColin Finck   int expected_loc;
154c2c66affSColin Finck };
155c2c66affSColin Finck 
156c2c66affSColin Finck 
157c2c66affSColin Finck static struct find_s find_tests[] = {
158c2c66affSColin Finck   /* Find in empty text */
159c2c66affSColin Finck   {0, -1, "foo", FR_DOWN, -1},
160c2c66affSColin Finck   {0, -1, "foo", 0, -1},
161c2c66affSColin Finck   {0, -1, "", FR_DOWN, -1},
162c2c66affSColin Finck   {20, 5, "foo", FR_DOWN, -1},
163c2c66affSColin Finck   {5, 20, "foo", FR_DOWN, -1}
164c2c66affSColin Finck };
165c2c66affSColin Finck 
166c2c66affSColin Finck static struct find_s find_tests2[] = {
167c2c66affSColin Finck   /* No-result find */
168c2c66affSColin Finck   {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1},
169c2c66affSColin Finck   {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1},
170c2c66affSColin Finck 
171c2c66affSColin Finck   /* Subsequent finds */
172c2c66affSColin Finck   {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4},
173c2c66affSColin Finck   {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13},
174c2c66affSColin Finck   {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
175c2c66affSColin Finck   {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
176c2c66affSColin Finck 
177c2c66affSColin Finck   /* Find backwards */
178c2c66affSColin Finck   {19, 20, "Wine", FR_MATCHCASE, 13},
179c2c66affSColin Finck   {10, 20, "Wine", FR_MATCHCASE, 4},
180c2c66affSColin Finck   {20, 10, "Wine", FR_MATCHCASE, 13},
181c2c66affSColin Finck 
182c2c66affSColin Finck   /* Case-insensitive */
183c2c66affSColin Finck   {1, 31, "wInE", FR_DOWN, 4},
184c2c66affSColin Finck   {1, 31, "Wine", FR_DOWN, 4},
185c2c66affSColin Finck 
186c2c66affSColin Finck   /* High-to-low ranges */
187c2c66affSColin Finck   {20, 5, "Wine", FR_DOWN, -1},
188c2c66affSColin Finck   {2, 1, "Wine", FR_DOWN, -1},
189c2c66affSColin Finck   {30, 29, "Wine", FR_DOWN, -1},
190c2c66affSColin Finck   {20, 5, "Wine", 0, 13},
191c2c66affSColin Finck 
192c2c66affSColin Finck   /* Find nothing */
193c2c66affSColin Finck   {5, 10, "", FR_DOWN, -1},
194c2c66affSColin Finck   {10, 5, "", FR_DOWN, -1},
195c2c66affSColin Finck   {0, -1, "", FR_DOWN, -1},
196c2c66affSColin Finck   {10, 5, "", 0, -1},
197c2c66affSColin Finck 
198c2c66affSColin Finck   /* Whole-word search */
199c2c66affSColin Finck   {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
200c2c66affSColin Finck   {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1},
201c2c66affSColin Finck   {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
202c2c66affSColin Finck   {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0},
203c2c66affSColin Finck   {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23},
204c2c66affSColin Finck   {11, -1, "winewine", FR_WHOLEWORD, 0},
205c2c66affSColin Finck   {31, -1, "winewine", FR_WHOLEWORD, 23},
206c2c66affSColin Finck 
207c2c66affSColin Finck   /* Bad ranges */
208c2c66affSColin Finck   {5, 200, "XXX", FR_DOWN, -1},
209c2c66affSColin Finck   {-20, 20, "Wine", FR_DOWN, -1},
210c2c66affSColin Finck   {-20, 20, "Wine", FR_DOWN, -1},
211c2c66affSColin Finck   {-15, -20, "Wine", FR_DOWN, -1},
212c2c66affSColin Finck   {1<<12, 1<<13, "Wine", FR_DOWN, -1},
213c2c66affSColin Finck 
214c2c66affSColin Finck   /* Check the case noted in bug 4479 where matches at end aren't recognized */
215c2c66affSColin Finck   {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
216c2c66affSColin Finck   {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
217c2c66affSColin Finck   {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27},
218c2c66affSColin Finck   {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
219c2c66affSColin Finck   {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
220c2c66affSColin Finck 
221c2c66affSColin Finck   /* The backwards case of bug 4479; bounds look right
222c2c66affSColin Finck    * Fails because backward find is wrong */
223c2c66affSColin Finck   {19, 20, "WINE", FR_MATCHCASE, 0},
224c2c66affSColin Finck   {0, 20, "WINE", FR_MATCHCASE, -1},
225c2c66affSColin Finck 
226c2c66affSColin Finck   {0, -1, "wineWine wine", 0, -1},
227c2c66affSColin Finck };
228c2c66affSColin Finck 
atowstr(const char * str)229c2c66affSColin Finck static WCHAR *atowstr(const char *str)
230c2c66affSColin Finck {
231c2c66affSColin Finck     WCHAR *ret;
232c2c66affSColin Finck     DWORD len;
233c2c66affSColin Finck     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
234c2c66affSColin Finck     ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
235c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
236c2c66affSColin Finck     return ret;
237c2c66affSColin Finck }
238c2c66affSColin Finck 
check_EM_FINDTEXT(HWND hwnd,const char * name,struct find_s * f,int id,BOOL unicode)239c2c66affSColin Finck static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id, BOOL unicode)
240c2c66affSColin Finck {
241c2c66affSColin Finck   int findloc;
242c2c66affSColin Finck 
243c2c66affSColin Finck   if(unicode){
244c2c66affSColin Finck       FINDTEXTW ftw;
245c2c66affSColin Finck       memset(&ftw, 0, sizeof(ftw));
246c2c66affSColin Finck       ftw.chrg.cpMin = f->start;
247c2c66affSColin Finck       ftw.chrg.cpMax = f->end;
248c2c66affSColin Finck       ftw.lpstrText = atowstr(f->needle);
249c2c66affSColin Finck 
250c2c66affSColin Finck       findloc = SendMessageA(hwnd, EM_FINDTEXT, f->flags, (LPARAM)&ftw);
251c2c66affSColin Finck       ok(findloc == f->expected_loc,
252c2c66affSColin Finck          "EM_FINDTEXT(%s,%d,%u) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
253c2c66affSColin Finck          name, id, unicode, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
254c2c66affSColin Finck 
255c2c66affSColin Finck       findloc = SendMessageA(hwnd, EM_FINDTEXTW, f->flags, (LPARAM)&ftw);
256c2c66affSColin Finck       ok(findloc == f->expected_loc,
257c2c66affSColin Finck          "EM_FINDTEXTW(%s,%d,%u) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
258c2c66affSColin Finck          name, id, unicode, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
259c2c66affSColin Finck 
260c2c66affSColin Finck       HeapFree(GetProcessHeap(), 0, (void*)ftw.lpstrText);
261c2c66affSColin Finck   }else{
262c2c66affSColin Finck       FINDTEXTA fta;
263c2c66affSColin Finck       memset(&fta, 0, sizeof(fta));
264c2c66affSColin Finck       fta.chrg.cpMin = f->start;
265c2c66affSColin Finck       fta.chrg.cpMax = f->end;
266c2c66affSColin Finck       fta.lpstrText = f->needle;
267c2c66affSColin Finck 
268c2c66affSColin Finck       findloc = SendMessageA(hwnd, EM_FINDTEXT, f->flags, (LPARAM)&fta);
269c2c66affSColin Finck       ok(findloc == f->expected_loc,
270c2c66affSColin Finck          "EM_FINDTEXT(%s,%d,%u) '%s' in range(%d,%d), flags %08x, got start at %d, expected %d\n",
271c2c66affSColin Finck          name, id, unicode, f->needle, f->start, f->end, f->flags, findloc, f->expected_loc);
272c2c66affSColin Finck   }
273c2c66affSColin Finck }
274c2c66affSColin Finck 
check_EM_FINDTEXTEX(HWND hwnd,const char * name,struct find_s * f,int id,BOOL unicode)275c2c66affSColin Finck static void check_EM_FINDTEXTEX(HWND hwnd, const char *name, struct find_s *f,
276c2c66affSColin Finck     int id, BOOL unicode)
277c2c66affSColin Finck {
278c2c66affSColin Finck   int findloc;
279c2c66affSColin Finck   int expected_end_loc;
280c2c66affSColin Finck 
281c2c66affSColin Finck   if(unicode){
282c2c66affSColin Finck       FINDTEXTEXW ftw;
283c2c66affSColin Finck       memset(&ftw, 0, sizeof(ftw));
284c2c66affSColin Finck       ftw.chrg.cpMin = f->start;
285c2c66affSColin Finck       ftw.chrg.cpMax = f->end;
286c2c66affSColin Finck       ftw.lpstrText = atowstr(f->needle);
287c2c66affSColin Finck       findloc = SendMessageA(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM)&ftw);
288c2c66affSColin Finck       ok(findloc == f->expected_loc,
289c2c66affSColin Finck           "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
290c2c66affSColin Finck           name, id, f->needle, f->start, f->end, f->flags, findloc);
291c2c66affSColin Finck       ok(ftw.chrgText.cpMin == f->expected_loc,
292c2c66affSColin Finck           "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
293c2c66affSColin Finck           name, id, f->needle, f->start, f->end, f->flags, ftw.chrgText.cpMin);
294c2c66affSColin Finck       expected_end_loc = ((f->expected_loc == -1) ? -1
295c2c66affSColin Finck             : f->expected_loc + strlen(f->needle));
296c2c66affSColin Finck       ok(ftw.chrgText.cpMax == expected_end_loc,
297c2c66affSColin Finck           "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d, expected %d\n",
298c2c66affSColin Finck           name, id, f->needle, f->start, f->end, f->flags, ftw.chrgText.cpMax, expected_end_loc);
299c2c66affSColin Finck       HeapFree(GetProcessHeap(), 0, (void*)ftw.lpstrText);
300c2c66affSColin Finck   }else{
301c2c66affSColin Finck       FINDTEXTEXA fta;
302c2c66affSColin Finck       memset(&fta, 0, sizeof(fta));
303c2c66affSColin Finck       fta.chrg.cpMin = f->start;
304c2c66affSColin Finck       fta.chrg.cpMax = f->end;
305c2c66affSColin Finck       fta.lpstrText = f->needle;
306c2c66affSColin Finck       findloc = SendMessageA(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM)&fta);
307c2c66affSColin Finck       ok(findloc == f->expected_loc,
308c2c66affSColin Finck           "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
309c2c66affSColin Finck           name, id, f->needle, f->start, f->end, f->flags, findloc);
310c2c66affSColin Finck       ok(fta.chrgText.cpMin == f->expected_loc,
311c2c66affSColin Finck           "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
312c2c66affSColin Finck           name, id, f->needle, f->start, f->end, f->flags, fta.chrgText.cpMin);
313c2c66affSColin Finck       expected_end_loc = ((f->expected_loc == -1) ? -1
314c2c66affSColin Finck             : f->expected_loc + strlen(f->needle));
315c2c66affSColin Finck       ok(fta.chrgText.cpMax == expected_end_loc,
316c2c66affSColin Finck           "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %d, expected %d\n",
317c2c66affSColin Finck           name, id, f->needle, f->start, f->end, f->flags, fta.chrgText.cpMax, expected_end_loc);
318c2c66affSColin Finck   }
319c2c66affSColin Finck }
320c2c66affSColin Finck 
run_tests_EM_FINDTEXT(HWND hwnd,const char * name,struct find_s * find,int num_tests,BOOL unicode)321c2c66affSColin Finck static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *find,
322c2c66affSColin Finck     int num_tests, BOOL unicode)
323c2c66affSColin Finck {
324c2c66affSColin Finck   int i;
325c2c66affSColin Finck 
326c2c66affSColin Finck   for (i = 0; i < num_tests; i++) {
327c2c66affSColin Finck       check_EM_FINDTEXT(hwnd, name, &find[i], i, unicode);
328c2c66affSColin Finck       check_EM_FINDTEXTEX(hwnd, name, &find[i], i, unicode);
329c2c66affSColin Finck   }
330c2c66affSColin Finck }
331c2c66affSColin Finck 
test_EM_FINDTEXT(BOOL unicode)332c2c66affSColin Finck static void test_EM_FINDTEXT(BOOL unicode)
333c2c66affSColin Finck {
334c2c66affSColin Finck   HWND hwndRichEdit;
335c2c66affSColin Finck   CHARFORMAT2A cf2;
336c2c66affSColin Finck 
337c2c66affSColin Finck   if(unicode)
338c2c66affSColin Finck        hwndRichEdit = new_richeditW(NULL);
339c2c66affSColin Finck   else
340c2c66affSColin Finck        hwndRichEdit = new_richedit(NULL);
341c2c66affSColin Finck 
342c2c66affSColin Finck   /* Empty rich edit control */
34376cf09cfSAmine Khaldi   run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests, ARRAY_SIZE(find_tests), unicode);
344c2c66affSColin Finck 
345c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)haystack);
346c2c66affSColin Finck 
347c2c66affSColin Finck   /* Haystack text */
34876cf09cfSAmine Khaldi   run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2, ARRAY_SIZE(find_tests2), unicode);
349c2c66affSColin Finck 
350c2c66affSColin Finck   /* Setting a format on an arbitrary range should have no effect in search
351c2c66affSColin Finck      results. This tests correct offset reporting across runs. */
352c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
353c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2);
354c2c66affSColin Finck   cf2.dwMask = CFM_ITALIC | cf2.dwMask;
355c2c66affSColin Finck   cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
356c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 6, 20);
357c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
358c2c66affSColin Finck 
359c2c66affSColin Finck   /* Haystack text, again */
36076cf09cfSAmine Khaldi   run_tests_EM_FINDTEXT(hwndRichEdit, "2-bis", find_tests2, ARRAY_SIZE(find_tests2), unicode);
361c2c66affSColin Finck 
362c2c66affSColin Finck   /* Yet another range */
363c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | cf2.dwMask;
364c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD ^ cf2.dwEffects;
365c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 11, 15);
366c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
367c2c66affSColin Finck 
368c2c66affSColin Finck   /* Haystack text, again */
36976cf09cfSAmine Khaldi   run_tests_EM_FINDTEXT(hwndRichEdit, "2-bisbis", find_tests2, ARRAY_SIZE(find_tests2), unicode);
370c2c66affSColin Finck 
371c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
372c2c66affSColin Finck }
373c2c66affSColin Finck 
374c2c66affSColin Finck static const struct getline_s {
375c2c66affSColin Finck   int line;
376c2c66affSColin Finck   size_t buffer_len;
377c2c66affSColin Finck   const char *text;
378c2c66affSColin Finck } gl[] = {
379c2c66affSColin Finck   {0, 10, "foo bar\r"},
380c2c66affSColin Finck   {1, 10, "\r"},
381c2c66affSColin Finck   {2, 10, "bar\r"},
382c2c66affSColin Finck   {3, 10, "\r"},
383c2c66affSColin Finck 
384c2c66affSColin Finck   /* Buffer smaller than line length */
385c2c66affSColin Finck   {0, 2, "foo bar\r"},
386c2c66affSColin Finck   {0, 1, "foo bar\r"},
387c2c66affSColin Finck   {0, 0, "foo bar\r"}
388c2c66affSColin Finck };
389c2c66affSColin Finck 
test_EM_GETLINE(void)390c2c66affSColin Finck static void test_EM_GETLINE(void)
391c2c66affSColin Finck {
392c2c66affSColin Finck   int i;
393c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
394c2c66affSColin Finck   static const int nBuf = 1024;
395c2c66affSColin Finck   char dest[1024], origdest[1024];
396c2c66affSColin Finck   const char text[] = "foo bar\n"
397c2c66affSColin Finck       "\n"
398c2c66affSColin Finck       "bar\n";
399c2c66affSColin Finck 
400c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
401c2c66affSColin Finck 
402c2c66affSColin Finck   memset(origdest, 0xBB, nBuf);
40376cf09cfSAmine Khaldi   for (i = 0; i < ARRAY_SIZE(gl); i++)
404c2c66affSColin Finck   {
405c2c66affSColin Finck     int nCopied;
406c2c66affSColin Finck     int expected_nCopied = min(gl[i].buffer_len, strlen(gl[i].text));
407c2c66affSColin Finck     int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text));
408c2c66affSColin Finck     memset(dest, 0xBB, nBuf);
409c2c66affSColin Finck     *(WORD *) dest = gl[i].buffer_len;
410c2c66affSColin Finck 
411c2c66affSColin Finck     /* EM_GETLINE appends a "\r\0" to the end of the line
412c2c66affSColin Finck      * nCopied counts up to and including the '\r' */
413c2c66affSColin Finck     nCopied = SendMessageA(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM)dest);
414c2c66affSColin Finck     ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
415c2c66affSColin Finck        expected_nCopied);
416c2c66affSColin Finck     /* two special cases since a parameter is passed via dest */
417c2c66affSColin Finck     if (gl[i].buffer_len == 0)
418c2c66affSColin Finck       ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
419c2c66affSColin Finck          "buffer_len=0\n");
420c2c66affSColin Finck     else if (gl[i].buffer_len == 1)
421c2c66affSColin Finck       ok(dest[0] == gl[i].text[0] && !dest[1] &&
422c2c66affSColin Finck          !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
423c2c66affSColin Finck     else
424c2c66affSColin Finck     {
425c2c66affSColin Finck       /* Prepare hex strings of buffers to dump on failure. */
426c2c66affSColin Finck       char expectedbuf[1024];
427c2c66affSColin Finck       char resultbuf[1024];
428c2c66affSColin Finck       int j;
429c2c66affSColin Finck       resultbuf[0] = '\0';
430c2c66affSColin Finck       for (j = 0; j < 32; j++)
431c2c66affSColin Finck         sprintf(resultbuf+strlen(resultbuf), "%02x", dest[j] & 0xFF);
432c2c66affSColin Finck       expectedbuf[0] = '\0';
433c2c66affSColin Finck       for (j = 0; j < expected_bytes_written; j++) /* Written bytes */
434c2c66affSColin Finck         sprintf(expectedbuf+strlen(expectedbuf), "%02x", gl[i].text[j] & 0xFF);
435c2c66affSColin Finck       for (; j < gl[i].buffer_len; j++) /* Ignored bytes */
436c2c66affSColin Finck         sprintf(expectedbuf+strlen(expectedbuf), "??");
437c2c66affSColin Finck       for (; j < 32; j++) /* Bytes after declared buffer size */
438c2c66affSColin Finck         sprintf(expectedbuf+strlen(expectedbuf), "%02x", origdest[j] & 0xFF);
439c2c66affSColin Finck 
440c2c66affSColin Finck       /* Test the part of the buffer that is expected to be written according
441c2c66affSColin Finck        * to the MSDN documentation fo EM_GETLINE, which does not state that
442c2c66affSColin Finck        * a NULL terminating character will be added unless no text is copied.
443c2c66affSColin Finck        *
444c2c66affSColin Finck        * Windows NT does not append a NULL terminating character, but
445c2c66affSColin Finck        * Windows 2000 and up do append a NULL terminating character if there
446c2c66affSColin Finck        * is space in the buffer. The test will ignore this difference. */
447c2c66affSColin Finck       ok(!strncmp(dest, gl[i].text, expected_bytes_written),
448c2c66affSColin Finck          "%d: expected_bytes_written=%d\n" "expected=0x%s\n" "but got= 0x%s\n",
449c2c66affSColin Finck          i, expected_bytes_written, expectedbuf, resultbuf);
450c2c66affSColin Finck       /* Test the part of the buffer after the declared length to make sure
451c2c66affSColin Finck        * there are no buffer overruns. */
452c2c66affSColin Finck       ok(!strncmp(dest + gl[i].buffer_len, origdest + gl[i].buffer_len,
453c2c66affSColin Finck                   nBuf - gl[i].buffer_len),
454c2c66affSColin Finck          "%d: expected_bytes_written=%d\n" "expected=0x%s\n" "but got= 0x%s\n",
455c2c66affSColin Finck          i, expected_bytes_written, expectedbuf, resultbuf);
456c2c66affSColin Finck     }
457c2c66affSColin Finck   }
458c2c66affSColin Finck 
459c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
460c2c66affSColin Finck }
461c2c66affSColin Finck 
test_EM_LINELENGTH(void)462c2c66affSColin Finck static void test_EM_LINELENGTH(void)
463c2c66affSColin Finck {
464c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
465c2c66affSColin Finck   const char * text =
466c2c66affSColin Finck         "richedit1\r"
467c2c66affSColin Finck         "richedit1\n"
468c2c66affSColin Finck         "richedit1\r\n"
469c2c66affSColin Finck         "richedit1";
470c2c66affSColin Finck   int offset_test[10][2] = {
471c2c66affSColin Finck         {0, 9},
472c2c66affSColin Finck         {5, 9},
473c2c66affSColin Finck         {10, 9},
474c2c66affSColin Finck         {15, 9},
475c2c66affSColin Finck         {20, 9},
476c2c66affSColin Finck         {25, 9},
477c2c66affSColin Finck         {30, 9},
478c2c66affSColin Finck         {35, 9},
479c2c66affSColin Finck         {40, 0},
480c2c66affSColin Finck         {45, 0},
481c2c66affSColin Finck   };
482c2c66affSColin Finck   int i;
483c2c66affSColin Finck   LRESULT result;
484c2c66affSColin Finck 
485c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
486c2c66affSColin Finck 
487c2c66affSColin Finck   for (i = 0; i < 10; i++) {
488c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_LINELENGTH, offset_test[i][0], 0);
489c2c66affSColin Finck     ok(result == offset_test[i][1], "Length of line at offset %d is %ld, expected %d\n",
490c2c66affSColin Finck         offset_test[i][0], result, offset_test[i][1]);
491c2c66affSColin Finck   }
492c2c66affSColin Finck 
493c2c66affSColin Finck   /* Test with multibyte character */
494c2c66affSColin Finck   if (!is_lang_japanese)
495c2c66affSColin Finck     skip("Skip multibyte character tests on non-Japanese platform\n");
496c2c66affSColin Finck   else
497c2c66affSColin Finck   {
498c2c66affSColin Finck     const char *text1 =
499c2c66affSColin Finck           "wine\n"
500c2c66affSColin Finck           "richedit\x8e\xf0\n"
501c2c66affSColin Finck           "wine";
502c2c66affSColin Finck     int offset_test1[3][2] = {
503c2c66affSColin Finck            {0, 4},  /* Line 1: |wine\n */
504c2c66affSColin Finck            {5, 9},  /* Line 2: |richedit\x8e\xf0\n */
505c2c66affSColin Finck            {15, 4}, /* Line 3: |wine */
506c2c66affSColin Finck     };
507c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
50876cf09cfSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(offset_test1); i++) {
509c2c66affSColin Finck       result = SendMessageA(hwndRichEdit, EM_LINELENGTH, offset_test1[i][0], 0);
510c2c66affSColin Finck       ok(result == offset_test1[i][1], "Length of line at offset %d is %ld, expected %d\n",
511c2c66affSColin Finck          offset_test1[i][0], result, offset_test1[i][1]);
512c2c66affSColin Finck     }
513c2c66affSColin Finck   }
514c2c66affSColin Finck 
515c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
516c2c66affSColin Finck }
517c2c66affSColin Finck 
get_scroll_pos_y(HWND hwnd)518c2c66affSColin Finck static int get_scroll_pos_y(HWND hwnd)
519c2c66affSColin Finck {
520c2c66affSColin Finck   POINT p = {-1, -1};
521c2c66affSColin Finck   SendMessageA(hwnd, EM_GETSCROLLPOS, 0, (LPARAM)&p);
522c2c66affSColin Finck   ok(p.x != -1 && p.y != -1, "p.x:%d p.y:%d\n", p.x, p.y);
523c2c66affSColin Finck   return p.y;
524c2c66affSColin Finck }
525c2c66affSColin Finck 
move_cursor(HWND hwnd,LONG charindex)526c2c66affSColin Finck static void move_cursor(HWND hwnd, LONG charindex)
527c2c66affSColin Finck {
528c2c66affSColin Finck   CHARRANGE cr;
529c2c66affSColin Finck   cr.cpMax = charindex;
530c2c66affSColin Finck   cr.cpMin = charindex;
531c2c66affSColin Finck   SendMessageA(hwnd, EM_EXSETSEL, 0, (LPARAM)&cr);
532c2c66affSColin Finck }
533c2c66affSColin Finck 
line_scroll(HWND hwnd,int amount)534c2c66affSColin Finck static void line_scroll(HWND hwnd, int amount)
535c2c66affSColin Finck {
536c2c66affSColin Finck   SendMessageA(hwnd, EM_LINESCROLL, 0, amount);
537c2c66affSColin Finck }
538c2c66affSColin Finck 
test_EM_SCROLLCARET(void)539c2c66affSColin Finck static void test_EM_SCROLLCARET(void)
540c2c66affSColin Finck {
541c2c66affSColin Finck   int prevY, curY;
542c2c66affSColin Finck   const char text[] = "aa\n"
543c2c66affSColin Finck       "this is a long line of text that should be longer than the "
544c2c66affSColin Finck       "control's width\n"
545c2c66affSColin Finck       "cc\n"
546c2c66affSColin Finck       "dd\n"
547c2c66affSColin Finck       "ee\n"
548c2c66affSColin Finck       "ff\n"
549c2c66affSColin Finck       "gg\n"
550c2c66affSColin Finck       "hh\n";
551c2c66affSColin Finck   /* The richedit window height needs to be large enough vertically to fit in
552c2c66affSColin Finck    * more than two lines of text, so the new_richedit function can't be used
553c2c66affSColin Finck    * since a height of 60 was not large enough on some systems.
554c2c66affSColin Finck    */
555c2c66affSColin Finck   HWND hwndRichEdit = CreateWindowA(RICHEDIT_CLASS20A, NULL,
556c2c66affSColin Finck                                    ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
557c2c66affSColin Finck                                    0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
558c2c66affSColin Finck   ok(hwndRichEdit != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
559c2c66affSColin Finck 
560c2c66affSColin Finck   /* Can't verify this */
561c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLLCARET, 0, 0);
562c2c66affSColin Finck 
563c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
564c2c66affSColin Finck 
565c2c66affSColin Finck   /* Caret above visible window */
566c2c66affSColin Finck   line_scroll(hwndRichEdit, 3);
567c2c66affSColin Finck   prevY = get_scroll_pos_y(hwndRichEdit);
568c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLLCARET, 0, 0);
569c2c66affSColin Finck   curY = get_scroll_pos_y(hwndRichEdit);
570c2c66affSColin Finck   ok(prevY != curY, "%d == %d\n", prevY, curY);
571c2c66affSColin Finck 
572c2c66affSColin Finck   /* Caret below visible window */
573c2c66affSColin Finck   move_cursor(hwndRichEdit, sizeof(text) - 1);
574c2c66affSColin Finck   line_scroll(hwndRichEdit, -3);
575c2c66affSColin Finck   prevY = get_scroll_pos_y(hwndRichEdit);
576c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLLCARET, 0, 0);
577c2c66affSColin Finck   curY = get_scroll_pos_y(hwndRichEdit);
578c2c66affSColin Finck   ok(prevY != curY, "%d == %d\n", prevY, curY);
579c2c66affSColin Finck 
580c2c66affSColin Finck   /* Caret in visible window */
581c2c66affSColin Finck   move_cursor(hwndRichEdit, sizeof(text) - 2);
582c2c66affSColin Finck   prevY = get_scroll_pos_y(hwndRichEdit);
583c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLLCARET, 0, 0);
584c2c66affSColin Finck   curY = get_scroll_pos_y(hwndRichEdit);
585c2c66affSColin Finck   ok(prevY == curY, "%d != %d\n", prevY, curY);
586c2c66affSColin Finck 
587c2c66affSColin Finck   /* Caret still in visible window */
588c2c66affSColin Finck   line_scroll(hwndRichEdit, -1);
589c2c66affSColin Finck   prevY = get_scroll_pos_y(hwndRichEdit);
590c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLLCARET, 0, 0);
591c2c66affSColin Finck   curY = get_scroll_pos_y(hwndRichEdit);
592c2c66affSColin Finck   ok(prevY == curY, "%d != %d\n", prevY, curY);
593c2c66affSColin Finck 
594c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
595c2c66affSColin Finck }
596c2c66affSColin Finck 
test_EM_POSFROMCHAR(void)597c2c66affSColin Finck static void test_EM_POSFROMCHAR(void)
598c2c66affSColin Finck {
599c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
600c2c66affSColin Finck   int i, expected;
601c2c66affSColin Finck   LRESULT result;
602c2c66affSColin Finck   unsigned int height = 0;
603c2c66affSColin Finck   int xpos = 0;
604c2c66affSColin Finck   POINTL pt;
605c2c66affSColin Finck   LOCALESIGNATURE sig;
606c2c66affSColin Finck   BOOL rtl;
607c2c66affSColin Finck   PARAFORMAT2 fmt;
608c2c66affSColin Finck   static const char text[] = "aa\n"
609c2c66affSColin Finck       "this is a long line of text that should be longer than the "
610c2c66affSColin Finck       "control's width\n"
611c2c66affSColin Finck       "cc\n"
612c2c66affSColin Finck       "dd\n"
613c2c66affSColin Finck       "ee\n"
614c2c66affSColin Finck       "ff\n"
615c2c66affSColin Finck       "gg\n"
616c2c66affSColin Finck       "hh\n";
617c2c66affSColin Finck 
618c2c66affSColin Finck   rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE,
619c2c66affSColin Finck                         (LPSTR) &sig, sizeof(LOCALESIGNATURE)) &&
620c2c66affSColin Finck          (sig.lsUsb[3] & 0x08000000) != 0);
621c2c66affSColin Finck 
622c2c66affSColin Finck   /* Fill the control to lines to ensure that most of them are offscreen */
623c2c66affSColin Finck   for (i = 0; i < 50; i++)
624c2c66affSColin Finck   {
625c2c66affSColin Finck     /* Do not modify the string; it is exactly 16 characters long. */
626c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 0);
627c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"0123456789ABCDE\n");
628c2c66affSColin Finck   }
629c2c66affSColin Finck 
630c2c66affSColin Finck   /*
631c2c66affSColin Finck    Richedit 1.0 receives a POINTL* on wParam and character offset on lParam, returns void.
632c2c66affSColin Finck    Richedit 2.0 receives character offset on wParam, ignores lParam, returns MAKELONG(x,y)
633c2c66affSColin Finck    Richedit 3.0 accepts either of the above API conventions.
634c2c66affSColin Finck    */
635c2c66affSColin Finck 
636c2c66affSColin Finck   /* Testing Richedit 2.0 API format */
637c2c66affSColin Finck 
638c2c66affSColin Finck   /* Testing start of lines. X-offset should be constant on all cases (native is 1).
639c2c66affSColin Finck      Since all lines are identical and drawn with the same font,
640c2c66affSColin Finck      they should have the same height... right?
641c2c66affSColin Finck    */
642c2c66affSColin Finck   for (i = 0; i < 50; i++)
643c2c66affSColin Finck   {
644c2c66affSColin Finck     /* All the lines are 16 characters long */
645c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, i * 16, 0);
646c2c66affSColin Finck     if (i == 0)
647c2c66affSColin Finck     {
648c2c66affSColin Finck       ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result));
649c2c66affSColin Finck       ok(LOWORD(result) == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
650c2c66affSColin Finck       xpos = LOWORD(result);
651c2c66affSColin Finck     }
652c2c66affSColin Finck     else if (i == 1)
653c2c66affSColin Finck     {
654c2c66affSColin Finck       ok(HIWORD(result) > 0, "EM_POSFROMCHAR reports y=%d, expected > 0\n", HIWORD(result));
655c2c66affSColin Finck       ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
656c2c66affSColin Finck       height = HIWORD(result);
657c2c66affSColin Finck     }
658c2c66affSColin Finck     else
659c2c66affSColin Finck     {
660e26c8bc6STimo Kreuzer       ros_skip_flaky
661c2c66affSColin Finck       ok(HIWORD(result) == i * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), i * height);
662c2c66affSColin Finck       ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
663c2c66affSColin Finck     }
664c2c66affSColin Finck   }
665c2c66affSColin Finck 
666c2c66affSColin Finck   /* Testing position at end of text */
667c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, 50 * 16, 0);
668c2c66affSColin Finck   ok(HIWORD(result) == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), 50 * height);
669c2c66affSColin Finck   ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
670c2c66affSColin Finck 
671c2c66affSColin Finck   /* Testing position way past end of text */
672c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, 55 * 16, 0);
673c2c66affSColin Finck   ok(HIWORD(result) == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), 50 * height);
674c2c66affSColin Finck   expected = (rtl ? 8 : 1);
675c2c66affSColin Finck   ok(LOWORD(result) == expected, "EM_POSFROMCHAR reports x=%d, expected %d\n", LOWORD(result), expected);
676c2c66affSColin Finck 
677c2c66affSColin Finck   /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */
678c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */
679c2c66affSColin Finck   for (i = 0; i < 50; i++)
680c2c66affSColin Finck   {
681c2c66affSColin Finck     /* All the lines are 16 characters long */
682c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, i * 16, 0);
683c2c66affSColin Finck     ok((signed short)(HIWORD(result)) == (i - 1) * height,
684c2c66affSColin Finck         "EM_POSFROMCHAR reports y=%hd, expected %d\n",
685c2c66affSColin Finck         (signed short)(HIWORD(result)), (i - 1) * height);
686c2c66affSColin Finck     ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
687c2c66affSColin Finck   }
688c2c66affSColin Finck 
689c2c66affSColin Finck   /* Testing position at end of text */
690c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, 50 * 16, 0);
691c2c66affSColin Finck   ok(HIWORD(result) == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), (50 - 1) * height);
692c2c66affSColin Finck   ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
693c2c66affSColin Finck 
694c2c66affSColin Finck   /* Testing position way past end of text */
695c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, 55 * 16, 0);
696c2c66affSColin Finck   ok(HIWORD(result) == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), (50 - 1) * height);
697c2c66affSColin Finck   expected = (rtl ? 8 : 1);
698c2c66affSColin Finck   ok(LOWORD(result) == expected, "EM_POSFROMCHAR reports x=%d, expected %d\n", LOWORD(result), expected);
699c2c66affSColin Finck 
700c2c66affSColin Finck   /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */
701c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
702c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */
703c2c66affSColin Finck 
704c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, 0, 0);
705c2c66affSColin Finck   ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result));
706c2c66affSColin Finck   ok(LOWORD(result) == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result));
707c2c66affSColin Finck   xpos = LOWORD(result);
708c2c66affSColin Finck 
709c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0);
710c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_POSFROMCHAR, 0, 0);
711c2c66affSColin Finck   ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result));
712c2c66affSColin Finck   ok((signed short)(LOWORD(result)) < xpos,
713c2c66affSColin Finck         "EM_POSFROMCHAR reports x=%hd, expected value less than %d\n",
714c2c66affSColin Finck         (signed short)(LOWORD(result)), xpos);
715c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_HSCROLL, SB_LINELEFT, 0);
716c2c66affSColin Finck 
717c2c66affSColin Finck   /* Test around end of text that doesn't end in a newline. */
718c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"12345678901234");
719c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt,
720c2c66affSColin Finck               SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0)-1);
721c2c66affSColin Finck   ok(pt.x > 1, "pt.x = %d\n", pt.x);
722c2c66affSColin Finck   xpos = pt.x;
723c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt,
724c2c66affSColin Finck               SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0));
725c2c66affSColin Finck   ok(pt.x > xpos, "pt.x = %d\n", pt.x);
726c2c66affSColin Finck   xpos = (rtl ? pt.x + 7 : pt.x);
727c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt,
728c2c66affSColin Finck               SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0)+1);
729c2c66affSColin Finck   ok(pt.x == xpos, "pt.x = %d\n", pt.x);
730c2c66affSColin Finck 
731c2c66affSColin Finck   /* Try a negative position. */
732c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, -1);
733c2c66affSColin Finck   ok(pt.x == 1, "pt.x = %d\n", pt.x);
734c2c66affSColin Finck 
735c2c66affSColin Finck   /* test negative indentation */
736c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0,
737c2c66affSColin Finck           (LPARAM)"{\\rtf1\\pard\\fi-200\\li-200\\f1 TestSomeText\\par}");
738c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, 0);
739c2c66affSColin Finck   ok(pt.x == 1, "pt.x = %d\n", pt.x);
740c2c66affSColin Finck 
741c2c66affSColin Finck   fmt.cbSize = sizeof(fmt);
742c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
743c2c66affSColin Finck   ok(fmt.dxStartIndent == -400, "got %d\n", fmt.dxStartIndent);
744c2c66affSColin Finck   ok(fmt.dxOffset == 200, "got %d\n", fmt.dxOffset);
745c2c66affSColin Finck   ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment);
746c2c66affSColin Finck 
747c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
748c2c66affSColin Finck }
749c2c66affSColin Finck 
test_EM_SETCHARFORMAT(void)750c2c66affSColin Finck static void test_EM_SETCHARFORMAT(void)
751c2c66affSColin Finck {
752c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
753c2c66affSColin Finck   CHARFORMAT2A cf2;
754c2c66affSColin Finck   CHARFORMAT2W cfW;
75576cf09cfSAmine Khaldi   CHARFORMATA cf1a;
75676cf09cfSAmine Khaldi   CHARFORMATW cf1w;
757c2c66affSColin Finck   int rc = 0;
758c2c66affSColin Finck   int tested_effects[] = {
759c2c66affSColin Finck     CFE_BOLD,
760c2c66affSColin Finck     CFE_ITALIC,
761c2c66affSColin Finck     CFE_UNDERLINE,
762c2c66affSColin Finck     CFE_STRIKEOUT,
763c2c66affSColin Finck     CFE_PROTECTED,
764c2c66affSColin Finck     CFE_LINK,
765c2c66affSColin Finck     CFE_SUBSCRIPT,
766c2c66affSColin Finck     CFE_SUPERSCRIPT,
767c2c66affSColin Finck     0
768c2c66affSColin Finck   };
769c2c66affSColin Finck   int i;
770c2c66affSColin Finck   CHARRANGE cr;
771c2c66affSColin Finck   LOCALESIGNATURE sig;
772c2c66affSColin Finck   BOOL rtl;
773c2c66affSColin Finck   DWORD expect_effects;
774c2c66affSColin Finck 
775c2c66affSColin Finck   rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE,
776c2c66affSColin Finck                         (LPSTR) &sig, sizeof(LOCALESIGNATURE)) &&
777c2c66affSColin Finck          (sig.lsUsb[3] & 0x08000000) != 0);
778c2c66affSColin Finck 
779c2c66affSColin Finck   /* check charformat defaults */
780c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
781c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
782c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
783c2c66affSColin Finck   ok(cf2.dwMask == CFM_ALL2, "got %08x\n", cf2.dwMask);
784c2c66affSColin Finck   expect_effects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
785c2c66affSColin Finck   if (cf2.wWeight > 550) expect_effects |= CFE_BOLD;
786c2c66affSColin Finck   ok(cf2.dwEffects == expect_effects, "got %08x\n", cf2.dwEffects);
787c2c66affSColin Finck   ok(cf2.yOffset == 0, "got %d\n", cf2.yOffset);
788c2c66affSColin Finck   ok(cf2.sSpacing == 0, "got %d\n", cf2.sSpacing);
789c2c66affSColin Finck   ok(cf2.lcid == GetSystemDefaultLCID(), "got %x\n", cf2.lcid);
790c2c66affSColin Finck   ok(cf2.sStyle == 0, "got %d\n", cf2.sStyle);
791c2c66affSColin Finck   ok(cf2.wKerning == 0, "got %d\n", cf2.wKerning);
792c2c66affSColin Finck   ok(cf2.bAnimation == 0, "got %d\n", cf2.bAnimation);
793c2c66affSColin Finck   ok(cf2.bRevAuthor == 0, "got %d\n", cf2.bRevAuthor);
794c2c66affSColin Finck 
795c2c66affSColin Finck   /* Invalid flags, CHARFORMAT2 structure blanked out */
796c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
797c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)0xfffffff0, (LPARAM)&cf2);
798c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
799c2c66affSColin Finck 
800c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure blanked out */
801c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
802c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_DEFAULT, (LPARAM)&cf2);
803c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
804c2c66affSColin Finck 
805c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure blanked out */
806c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
807c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&cf2);
808c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
809c2c66affSColin Finck 
810c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure blanked out */
811c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
812c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_WORD, (LPARAM)&cf2);
813c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
814c2c66affSColin Finck 
815c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure blanked out */
816c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
817c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf2);
818c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
819c2c66affSColin Finck 
820c2c66affSColin Finck   /* Invalid flags, CHARFORMAT2 structure minimally filled */
821c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
822c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
823c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)0xfffffff0, (LPARAM)&cf2);
824c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
825c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
826c2c66affSColin Finck   ok(rc == FALSE, "Should not be able to undo here.\n");
827c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0);
828c2c66affSColin Finck 
829c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure minimally filled */
830c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
831c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
832c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_DEFAULT, (LPARAM)&cf2);
833c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
834c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
835c2c66affSColin Finck   ok(rc == FALSE, "Should not be able to undo here.\n");
836c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0);
837c2c66affSColin Finck 
838c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure minimally filled */
839c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
840c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
841c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&cf2);
842c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
843c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
844c2c66affSColin Finck   ok(rc == FALSE, "Should not be able to undo here.\n");
845c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0);
846c2c66affSColin Finck 
847c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure minimally filled */
848c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
849c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
850c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_WORD, (LPARAM)&cf2);
851c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
852c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
853c2c66affSColin Finck   todo_wine ok(rc == TRUE, "Should not be able to undo here.\n");
854c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0);
855c2c66affSColin Finck 
856c2c66affSColin Finck   /* A valid flag, CHARFORMAT2 structure minimally filled */
857c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
858c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
859c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf2);
860c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
861c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
862c2c66affSColin Finck   ok(rc == TRUE, "Should not be able to undo here.\n");
863c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0);
864c2c66affSColin Finck 
865c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
866c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_DEFAULT, (LPARAM)&cf2);
867c2c66affSColin Finck 
868c2c66affSColin Finck   /* Test state of modify flag before and after valid EM_SETCHARFORMAT */
869c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
870c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_DEFAULT, (LPARAM)&cf2);
871c2c66affSColin Finck   cf2.dwMask = CFM_ITALIC | cf2.dwMask;
872c2c66affSColin Finck   cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
873c2c66affSColin Finck 
874c2c66affSColin Finck   /* wParam==0 is default char format, does not set modify */
875c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
876c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
877c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
878c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, 0, (LPARAM)&cf2);
879c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
880c2c66affSColin Finck   if (! rtl)
881c2c66affSColin Finck   {
882c2c66affSColin Finck     rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
883c2c66affSColin Finck     ok(rc == 0, "Text marked as modified, expected not modified!\n");
884c2c66affSColin Finck   }
885c2c66affSColin Finck   else
886c2c66affSColin Finck     skip("RTL language found\n");
887c2c66affSColin Finck 
888c2c66affSColin Finck   /* wParam==SCF_SELECTION sets modify if nonempty selection */
889c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
890c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
891c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
892c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
893c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
894c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
895c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
896c2c66affSColin Finck 
897c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
898c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
899c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
900c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
901c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
902c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
903c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
904c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
905c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
906c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
907c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
908c2c66affSColin Finck   ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
909c2c66affSColin Finck 
910c2c66affSColin Finck   /* wParam==SCF_ALL sets modify regardless of whether text is present */
911c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
912c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
913c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
914c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf2);
915c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
916c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
917c2c66affSColin Finck   ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
918c2c66affSColin Finck 
919c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
920c2c66affSColin Finck 
921c2c66affSColin Finck   /* EM_GETCHARFORMAT tests */
922c2c66affSColin Finck   for (i = 0; tested_effects[i]; i++)
923c2c66affSColin Finck   {
924c2c66affSColin Finck     hwndRichEdit = new_richedit(NULL);
925c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
926c2c66affSColin Finck 
927c2c66affSColin Finck     /* Need to set a TrueType font to get consistent CFM_BOLD results */
928c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
929c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
930c2c66affSColin Finck     cf2.dwMask = CFM_FACE|CFM_WEIGHT;
931c2c66affSColin Finck     cf2.dwEffects = 0;
932c2c66affSColin Finck     strcpy(cf2.szFaceName, "Courier New");
933c2c66affSColin Finck     cf2.wWeight = FW_DONTCARE;
934c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf2);
935c2c66affSColin Finck 
936c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
937c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
938c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 4);
939c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
940c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
941c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == CFM_SUPERSCRIPT)
942c2c66affSColin Finck           ||
943c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == tested_effects[i]),
944c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, tested_effects[i]);
945c2c66affSColin Finck     ok((cf2.dwEffects & tested_effects[i]) == 0,
946c2c66affSColin Finck         "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x clear\n", i, cf2.dwEffects, tested_effects[i]);
947c2c66affSColin Finck 
948c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
949c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
950c2c66affSColin Finck     cf2.dwMask = tested_effects[i];
951c2c66affSColin Finck     if (cf2.dwMask == CFE_SUBSCRIPT || cf2.dwMask == CFE_SUPERSCRIPT)
952c2c66affSColin Finck       cf2.dwMask = CFM_SUPERSCRIPT;
953c2c66affSColin Finck     cf2.dwEffects = tested_effects[i];
954c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
955c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
956c2c66affSColin Finck 
957c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
958c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
959c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
960c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
961c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
962c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == CFM_SUPERSCRIPT)
963c2c66affSColin Finck           ||
964c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == tested_effects[i]),
965c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, tested_effects[i]);
966c2c66affSColin Finck     ok((cf2.dwEffects & tested_effects[i]) == tested_effects[i],
967c2c66affSColin Finck         "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, tested_effects[i]);
968c2c66affSColin Finck 
969c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
970c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
971c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 2, 4);
972c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
973c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
974c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == CFM_SUPERSCRIPT)
975c2c66affSColin Finck           ||
976c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == tested_effects[i]),
977c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, tested_effects[i]);
978c2c66affSColin Finck     ok((cf2.dwEffects & tested_effects[i]) == 0,
979c2c66affSColin Finck         "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x clear\n", i, cf2.dwEffects, tested_effects[i]);
980c2c66affSColin Finck 
981c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
982c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
983c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 1, 3);
984c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
985c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
986c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == 0)
987c2c66affSColin Finck           ||
988c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == 0),
989c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x clear\n", i, cf2.dwMask, tested_effects[i]);
990c2c66affSColin Finck 
991c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
992c2c66affSColin Finck   }
993c2c66affSColin Finck 
994c2c66affSColin Finck   for (i = 0; tested_effects[i]; i++)
995c2c66affSColin Finck   {
996c2c66affSColin Finck     hwndRichEdit = new_richedit(NULL);
997c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
998c2c66affSColin Finck 
999c2c66affSColin Finck     /* Need to set a TrueType font to get consistent CFM_BOLD results */
1000c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
1001c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
1002c2c66affSColin Finck     cf2.dwMask = CFM_FACE|CFM_WEIGHT;
1003c2c66affSColin Finck     cf2.dwEffects = 0;
1004c2c66affSColin Finck     strcpy(cf2.szFaceName, "Courier New");
1005c2c66affSColin Finck     cf2.wWeight = FW_DONTCARE;
1006c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf2);
1007c2c66affSColin Finck 
1008c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
1009c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
1010c2c66affSColin Finck     cf2.dwMask = tested_effects[i];
1011c2c66affSColin Finck     if (cf2.dwMask == CFE_SUBSCRIPT || cf2.dwMask == CFE_SUPERSCRIPT)
1012c2c66affSColin Finck       cf2.dwMask = CFM_SUPERSCRIPT;
1013c2c66affSColin Finck     cf2.dwEffects = tested_effects[i];
1014c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 2, 4);
1015c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1016c2c66affSColin Finck 
1017c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
1018c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
1019c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
1020c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1021c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
1022c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == CFM_SUPERSCRIPT)
1023c2c66affSColin Finck           ||
1024c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == tested_effects[i]),
1025c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, tested_effects[i]);
1026c2c66affSColin Finck     ok((cf2.dwEffects & tested_effects[i]) == 0,
1027c2c66affSColin Finck         "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x clear\n", i, cf2.dwEffects, tested_effects[i]);
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
1030c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
1031c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 2, 4);
1032c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1033c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
1034c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == CFM_SUPERSCRIPT)
1035c2c66affSColin Finck           ||
1036c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == tested_effects[i]),
1037c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, tested_effects[i]);
1038c2c66affSColin Finck     ok((cf2.dwEffects & tested_effects[i]) == tested_effects[i],
1039c2c66affSColin Finck         "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, tested_effects[i]);
1040c2c66affSColin Finck 
1041c2c66affSColin Finck     memset(&cf2, 0, sizeof(CHARFORMAT2A));
1042c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
1043c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 1, 3);
1044c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1045c2c66affSColin Finck     ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) &&
1046c2c66affSColin Finck           (cf2.dwMask & CFM_SUPERSCRIPT) == 0)
1047c2c66affSColin Finck           ||
1048c2c66affSColin Finck           (cf2.dwMask & tested_effects[i]) == 0),
1049c2c66affSColin Finck         "%d, cf2.dwMask == 0x%08x expected mask 0x%08x clear\n", i, cf2.dwMask, tested_effects[i]);
1050c2c66affSColin Finck     ok((cf2.dwEffects & tested_effects[i]) == tested_effects[i],
1051c2c66affSColin Finck         "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x set\n", i, cf2.dwEffects, tested_effects[i]);
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
1054c2c66affSColin Finck   }
1055c2c66affSColin Finck 
1056c2c66affSColin Finck   /* Effects applied on an empty selection should take effect when selection is
1057c2c66affSColin Finck      replaced with text */
1058c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
1059c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1060c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
1061c2c66affSColin Finck 
1062c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1063c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1064c2c66affSColin Finck   cf2.dwMask = CFM_BOLD;
1065c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD;
1066c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1067c2c66affSColin Finck 
1068c2c66affSColin Finck   /* Selection is now nonempty */
1069c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"newi");
1070c2c66affSColin Finck 
1071c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1072c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1073c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 6);
1074c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1075c2c66affSColin Finck 
1076c2c66affSColin Finck   ok (((cf2.dwMask & CFM_BOLD) == CFM_BOLD),
1077c2c66affSColin Finck       "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, CFM_BOLD);
1078c2c66affSColin Finck   ok((cf2.dwEffects & CFE_BOLD) == CFE_BOLD,
1079c2c66affSColin Finck       "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
1080c2c66affSColin Finck 
1081c2c66affSColin Finck 
1082c2c66affSColin Finck   /* Set two effects on an empty selection */
1083c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1084c2c66affSColin Finck   /* first clear bold, italic */
1085c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
1086c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1087c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1088c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | CFM_ITALIC;
1089c2c66affSColin Finck   cf2.dwEffects = 0;
1090c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1091c2c66affSColin Finck 
1092c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
1093c2c66affSColin Finck 
1094c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1095c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1096c2c66affSColin Finck   cf2.dwMask = CFM_BOLD;
1097c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD;
1098c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1099c2c66affSColin Finck   cf2.dwMask = CFM_ITALIC;
1100c2c66affSColin Finck   cf2.dwEffects = CFE_ITALIC;
1101c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1102c2c66affSColin Finck 
1103c2c66affSColin Finck   /* Selection is now nonempty */
1104c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"newi");
1105c2c66affSColin Finck 
1106c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1107c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1108c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 6);
1109c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1110c2c66affSColin Finck 
1111c2c66affSColin Finck   ok (((cf2.dwMask & (CFM_BOLD|CFM_ITALIC)) == (CFM_BOLD|CFM_ITALIC)),
1112c2c66affSColin Finck       "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, (CFM_BOLD|CFM_ITALIC));
1113c2c66affSColin Finck   ok((cf2.dwEffects & (CFE_BOLD|CFE_ITALIC)) == (CFE_BOLD|CFE_ITALIC),
1114c2c66affSColin Finck       "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, (CFE_BOLD|CFE_ITALIC));
1115c2c66affSColin Finck 
1116c2c66affSColin Finck   /* Setting the (empty) selection to exactly the same place as before should
1117c2c66affSColin Finck      NOT clear the insertion style! */
1118c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1119c2c66affSColin Finck   /* first clear bold, italic */
1120c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
1121c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1122c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1123c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | CFM_ITALIC;
1124c2c66affSColin Finck   cf2.dwEffects = 0;
1125c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1126c2c66affSColin Finck 
1127c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
1128c2c66affSColin Finck 
1129c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1130c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1131c2c66affSColin Finck   cf2.dwMask = CFM_BOLD;
1132c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD;
1133c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1134c2c66affSColin Finck 
1135c2c66affSColin Finck   /* Empty selection in same place, insert style should NOT be forgotten here. */
1136c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2);
1137c2c66affSColin Finck 
1138c2c66affSColin Finck   /* Selection is now nonempty */
1139c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"newi");
1140c2c66affSColin Finck 
1141c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1142c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1143c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 6);
1144c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1145c2c66affSColin Finck 
1146c2c66affSColin Finck   ok (((cf2.dwMask & CFM_BOLD) == CFM_BOLD),
1147c2c66affSColin Finck       "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, CFM_BOLD);
1148c2c66affSColin Finck   ok((cf2.dwEffects & CFE_BOLD) == CFE_BOLD,
1149c2c66affSColin Finck       "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
1150c2c66affSColin Finck 
1151c2c66affSColin Finck   /* Moving the selection will clear the insertion style */
1152c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1153c2c66affSColin Finck   /* first clear bold, italic */
1154c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
1155c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1156c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1157c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | CFM_ITALIC;
1158c2c66affSColin Finck   cf2.dwEffects = 0;
1159c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1160c2c66affSColin Finck 
1161c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
1162c2c66affSColin Finck 
1163c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1164c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1165c2c66affSColin Finck   cf2.dwMask = CFM_BOLD;
1166c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD;
1167c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1168c2c66affSColin Finck 
1169c2c66affSColin Finck   /* Move selection and then put it back, insert style should be forgotten here. */
1170c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 3, 3);
1171c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
1172c2c66affSColin Finck 
1173c2c66affSColin Finck   /* Selection is now nonempty */
1174c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"newi");
1175c2c66affSColin Finck 
1176c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1177c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1178c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 2, 6);
1179c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1180c2c66affSColin Finck 
1181c2c66affSColin Finck   ok(((cf2.dwMask & CFM_BOLD) == CFM_BOLD),
1182c2c66affSColin Finck       "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, CFM_BOLD);
1183c2c66affSColin Finck   ok((cf2.dwEffects & CFE_BOLD) == 0,
1184c2c66affSColin Finck       "%d, cf2.dwEffects == 0x%08x not expecting effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
1185c2c66affSColin Finck 
1186c2c66affSColin Finck   /* Ditto with EM_EXSETSEL */
1187c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1188c2c66affSColin Finck   /* first clear bold, italic */
1189c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
1190c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1191c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1192c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | CFM_ITALIC;
1193c2c66affSColin Finck   cf2.dwEffects = 0;
1194c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1195c2c66affSColin Finck 
1196c2c66affSColin Finck   cr.cpMin = 2; cr.cpMax = 2;
1197c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr); /* Empty selection */
1198c2c66affSColin Finck 
1199c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1200c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1201c2c66affSColin Finck   cf2.dwMask = CFM_BOLD;
1202c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD;
1203c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1204c2c66affSColin Finck 
1205c2c66affSColin Finck   /* Empty selection in same place, insert style should NOT be forgotten here. */
1206c2c66affSColin Finck   cr.cpMin = 2; cr.cpMax = 2;
1207c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr); /* Empty selection */
1208c2c66affSColin Finck 
1209c2c66affSColin Finck   /* Selection is now nonempty */
1210c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"newi");
1211c2c66affSColin Finck 
1212c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1213c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1214c2c66affSColin Finck   cr.cpMin = 2; cr.cpMax = 6;
1215c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr); /* Empty selection */
1216c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1217c2c66affSColin Finck 
1218c2c66affSColin Finck   ok (((cf2.dwMask & CFM_BOLD) == CFM_BOLD),
1219c2c66affSColin Finck       "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, CFM_BOLD);
1220c2c66affSColin Finck   ok((cf2.dwEffects & CFE_BOLD) == CFE_BOLD,
1221c2c66affSColin Finck       "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
1222c2c66affSColin Finck 
1223c2c66affSColin Finck   /* show that wWeight is at the correct offset in CHARFORMAT2A */
1224c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
1225c2c66affSColin Finck   cf2.cbSize = sizeof(cf2);
1226c2c66affSColin Finck   cf2.dwMask = CFM_WEIGHT;
1227c2c66affSColin Finck   cf2.wWeight = 100;
1228c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1229c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
1230c2c66affSColin Finck   cf2.cbSize = sizeof(cf2);
1231c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1232c2c66affSColin Finck   ok(cf2.wWeight == 100, "got %d\n", cf2.wWeight);
1233c2c66affSColin Finck 
1234c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
1235c2c66affSColin Finck   cf2.cbSize = sizeof(cf2);
1236c2c66affSColin Finck   cf2.dwMask = CFM_SPACING;
1237c2c66affSColin Finck   cf2.sSpacing = 10;
1238c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1239c2c66affSColin Finck   memset(&cf2, 0, sizeof(cf2));
1240c2c66affSColin Finck   cf2.cbSize = sizeof(cf2);
1241c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1242c2c66affSColin Finck   ok(cf2.sSpacing == 10, "got %d\n", cf2.sSpacing);
1243c2c66affSColin Finck 
1244c2c66affSColin Finck   /* show that wWeight is at the correct offset in CHARFORMAT2W */
1245c2c66affSColin Finck   memset(&cfW, 0, sizeof(cfW));
1246c2c66affSColin Finck   cfW.cbSize = sizeof(cfW);
1247c2c66affSColin Finck   cfW.dwMask = CFM_WEIGHT;
1248c2c66affSColin Finck   cfW.wWeight = 100;
1249c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
1250c2c66affSColin Finck   memset(&cfW, 0, sizeof(cfW));
1251c2c66affSColin Finck   cfW.cbSize = sizeof(cfW);
1252c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
1253c2c66affSColin Finck   ok(cfW.wWeight == 100, "got %d\n", cfW.wWeight);
1254c2c66affSColin Finck 
1255c2c66affSColin Finck   memset(&cfW, 0, sizeof(cfW));
1256c2c66affSColin Finck   cfW.cbSize = sizeof(cfW);
1257c2c66affSColin Finck   cfW.dwMask = CFM_SPACING;
1258c2c66affSColin Finck   cfW.sSpacing = 10;
1259c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
1260c2c66affSColin Finck   memset(&cfW, 0, sizeof(cfW));
1261c2c66affSColin Finck   cfW.cbSize = sizeof(cfW);
1262c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
1263c2c66affSColin Finck   ok(cfW.sSpacing == 10, "got %d\n", cfW.sSpacing);
1264c2c66affSColin Finck 
1265c2c66affSColin Finck   /* test CFE_UNDERLINE and bUnderlineType interaction */
1266c2c66affSColin Finck   /* clear bold, italic */
1267c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
1268c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1269c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1270c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | CFM_ITALIC;
1271c2c66affSColin Finck   cf2.dwEffects = 0;
1272c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1273c2c66affSColin Finck 
1274c2c66affSColin Finck   /* check CFE_UNDERLINE is clear and bUnderlineType is CFU_UNDERLINE */
1275c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1276c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1277c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1278c2c66affSColin Finck   ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
1279c2c66affSColin Finck      "got %08x\n", cf2.dwMask);
1280c2c66affSColin Finck   ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects);
1281c2c66affSColin Finck   ok(cf2.bUnderlineType == CFU_UNDERLINE, "got %x\n", cf2.bUnderlineType);
1282c2c66affSColin Finck 
1283c2c66affSColin Finck   /* simply touching bUnderlineType will toggle CFE_UNDERLINE */
1284c2c66affSColin Finck   cf2.dwMask = CFM_UNDERLINETYPE;
1285c2c66affSColin Finck   cf2.bUnderlineType = CFU_UNDERLINE;
1286c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1287c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1288c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1289c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1290c2c66affSColin Finck   ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
1291c2c66affSColin Finck      "got %08x\n", cf2.dwMask);
1292c2c66affSColin Finck   ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects);
1293c2c66affSColin Finck   ok(cf2.bUnderlineType == CFU_UNDERLINE, "got %x\n", cf2.bUnderlineType);
1294c2c66affSColin Finck 
1295c2c66affSColin Finck   /* setting bUnderline to CFU_UNDERLINENONE clears CFE_UNDERLINE */
1296c2c66affSColin Finck   cf2.dwMask = CFM_UNDERLINETYPE;
1297c2c66affSColin Finck   cf2.bUnderlineType = CFU_UNDERLINENONE;
1298c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1299c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1300c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1301c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1302c2c66affSColin Finck   ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
1303c2c66affSColin Finck      "got %08x\n", cf2.dwMask);
1304c2c66affSColin Finck   ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects);
1305c2c66affSColin Finck   ok(cf2.bUnderlineType == CFU_UNDERLINENONE, "got %x\n", cf2.bUnderlineType);
1306c2c66affSColin Finck 
1307c2c66affSColin Finck   /* another underline type also sets CFE_UNDERLINE */
1308c2c66affSColin Finck   cf2.dwMask = CFM_UNDERLINETYPE;
1309c2c66affSColin Finck   cf2.bUnderlineType = CFU_UNDERLINEDOUBLE;
1310c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1311c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1312c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1313c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1314c2c66affSColin Finck   ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
1315c2c66affSColin Finck      "got %08x\n", cf2.dwMask);
1316c2c66affSColin Finck   ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects);
1317c2c66affSColin Finck   ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType);
1318c2c66affSColin Finck 
1319c2c66affSColin Finck   /* However explicitly clearing CFE_UNDERLINE results in it remaining cleared */
1320c2c66affSColin Finck   cf2.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
1321c2c66affSColin Finck   cf2.bUnderlineType = CFU_UNDERLINEDOUBLE;
1322c2c66affSColin Finck   cf2.dwEffects = 0;
1323c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1324c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1325c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1326c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1327c2c66affSColin Finck   ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
1328c2c66affSColin Finck      "got %08x\n", cf2.dwMask);
1329c2c66affSColin Finck   ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects);
1330c2c66affSColin Finck   ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType);
1331c2c66affSColin Finck 
1332c2c66affSColin Finck   /* And turing it back on again by just setting CFE_UNDERLINE */
1333c2c66affSColin Finck   cf2.dwMask = CFM_UNDERLINE;
1334c2c66affSColin Finck   cf2.dwEffects = CFE_UNDERLINE;
1335c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1336c2c66affSColin Finck   memset(&cf2, 0, sizeof(CHARFORMAT2A));
1337c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1338c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1339c2c66affSColin Finck   ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
1340c2c66affSColin Finck      "got %08x\n", cf2.dwMask);
1341c2c66affSColin Finck   ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects);
1342c2c66affSColin Finck   ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType);
1343c2c66affSColin Finck 
134476cf09cfSAmine Khaldi   /* Check setting CFM_ALL2/CFM_EFFECTS2 in CHARFORMAT(A/W). */
134576cf09cfSAmine Khaldi   memset(&cf1a, 0, sizeof(CHARFORMATA));
134676cf09cfSAmine Khaldi   memset(&cf1w, 0, sizeof(CHARFORMATW));
134776cf09cfSAmine Khaldi   cf1a.cbSize = sizeof(CHARFORMATA);
134876cf09cfSAmine Khaldi   cf1w.cbSize = sizeof(CHARFORMATW);
134976cf09cfSAmine Khaldi   cf1a.dwMask = cf1w.dwMask = CFM_ALL2;
135076cf09cfSAmine Khaldi   cf1a.dwEffects = cf1w.dwEffects = CFM_EFFECTS2;
135176cf09cfSAmine Khaldi   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf1a);
135276cf09cfSAmine Khaldi   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf1a);
135376cf09cfSAmine Khaldi   /* flags only valid for CHARFORMAT2 should be masked out */
135476cf09cfSAmine Khaldi   ok((cf1a.dwMask & (CFM_ALL2 & ~CFM_ALL)) == 0, "flags were not masked out\n");
135576cf09cfSAmine Khaldi   ok((cf1a.dwEffects & (CFM_EFFECTS2 & ~CFM_EFFECTS)) == 0, "flags were not masked out\n");
135676cf09cfSAmine Khaldi   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf1w);
135776cf09cfSAmine Khaldi   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf1w);
135876cf09cfSAmine Khaldi   ok((cf1w.dwMask & (CFM_ALL2 & ~CFM_ALL)) == 0, "flags were not masked out\n");
135976cf09cfSAmine Khaldi   ok((cf1w.dwEffects & (CFM_EFFECTS2 & ~CFM_EFFECTS)) == 0, "flags were not masked out\n");
136076cf09cfSAmine Khaldi 
1361c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
1362c2c66affSColin Finck }
1363c2c66affSColin Finck 
test_EM_SETTEXTMODE(void)1364c2c66affSColin Finck static void test_EM_SETTEXTMODE(void)
1365c2c66affSColin Finck {
1366c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
1367c2c66affSColin Finck   CHARFORMAT2A cf2, cf2test;
1368c2c66affSColin Finck   CHARRANGE cr;
1369c2c66affSColin Finck   int rc = 0;
1370c2c66affSColin Finck 
1371c2c66affSColin Finck   /*Attempt to use mutually exclusive modes*/
1372c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT|TM_RICHTEXT, 0);
1373c2c66affSColin Finck   ok(rc == E_INVALIDARG,
1374c2c66affSColin Finck      "EM_SETTEXTMODE: using mutually exclusive mode flags - returned: %x\n", rc);
1375c2c66affSColin Finck 
1376c2c66affSColin Finck   /*Test that EM_SETTEXTMODE fails if text exists within the control*/
1377c2c66affSColin Finck   /*Insert text into the control*/
1378c2c66affSColin Finck 
1379c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1380c2c66affSColin Finck 
1381c2c66affSColin Finck   /*Attempt to change the control to plain text mode*/
1382c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT, 0);
1383c2c66affSColin Finck   ok(rc == E_UNEXPECTED,
1384c2c66affSColin Finck      "EM_SETTEXTMODE: changed text mode in control containing text - returned: %x\n", rc);
1385c2c66affSColin Finck 
1386c2c66affSColin Finck   /*Test that EM_SETTEXTMODE does not allow rich edit text to be pasted.
1387c2c66affSColin Finck   If rich text is pasted, it should have the same formatting as the rest
1388c2c66affSColin Finck   of the text in the control*/
1389c2c66affSColin Finck 
1390c2c66affSColin Finck   /*Italicize the text
1391c2c66affSColin Finck   *NOTE: If the default text was already italicized, the test will simply
1392c2c66affSColin Finck   reverse; in other words, it will copy a regular "wine" into a plain
1393c2c66affSColin Finck   text window that uses an italicized format*/
1394c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1395c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_DEFAULT, (LPARAM)&cf2);
1396c2c66affSColin Finck 
1397c2c66affSColin Finck   cf2.dwMask = CFM_ITALIC | cf2.dwMask;
1398c2c66affSColin Finck   cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
1399c2c66affSColin Finck 
1400c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
1401c2c66affSColin Finck   ok(rc == 0, "Text marked as modified, expected not modified!\n");
1402c2c66affSColin Finck 
1403c2c66affSColin Finck   /*EM_SETCHARFORMAT is not yet fully implemented for all WPARAMs in wine;
1404c2c66affSColin Finck   however, SCF_ALL has been implemented*/
1405c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf2);
1406c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
1407c2c66affSColin Finck 
1408c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
1409c2c66affSColin Finck   ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
1410c2c66affSColin Finck 
1411c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1412c2c66affSColin Finck 
1413c2c66affSColin Finck   /*Select the string "wine"*/
1414c2c66affSColin Finck   cr.cpMin = 0;
1415c2c66affSColin Finck   cr.cpMax = 4;
1416c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1417c2c66affSColin Finck 
1418c2c66affSColin Finck   /*Copy the italicized "wine" to the clipboard*/
1419c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
1420c2c66affSColin Finck 
1421c2c66affSColin Finck   /*Reset the formatting to default*/
1422c2c66affSColin Finck   cf2.dwEffects = CFE_ITALIC^cf2.dwEffects;
1423c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf2);
1424c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
1425c2c66affSColin Finck 
1426c2c66affSColin Finck   /*Clear the text in the control*/
1427c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
1428c2c66affSColin Finck 
1429c2c66affSColin Finck   /*Switch to Plain Text Mode*/
1430c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT, 0);
1431c2c66affSColin Finck   ok(rc == 0, "EM_SETTEXTMODE: unable to switch to plain text mode with empty control:  returned: %d\n", rc);
1432c2c66affSColin Finck 
1433c2c66affSColin Finck   /*Input "wine" again in normal format*/
1434c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1435c2c66affSColin Finck 
1436c2c66affSColin Finck   /*Paste the italicized "wine" into the control*/
1437c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
1438c2c66affSColin Finck 
1439c2c66affSColin Finck   /*Select a character from the first "wine" string*/
1440c2c66affSColin Finck   cr.cpMin = 2;
1441c2c66affSColin Finck   cr.cpMax = 3;
1442c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1443c2c66affSColin Finck 
1444c2c66affSColin Finck   /*Retrieve its formatting*/
1445c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&cf2);
1446c2c66affSColin Finck 
1447c2c66affSColin Finck   /*Select a character from the second "wine" string*/
1448c2c66affSColin Finck   cr.cpMin = 5;
1449c2c66affSColin Finck   cr.cpMax = 6;
1450c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1451c2c66affSColin Finck 
1452c2c66affSColin Finck   /*Retrieve its formatting*/
1453c2c66affSColin Finck   cf2test.cbSize = sizeof(CHARFORMAT2A);
1454c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&cf2test);
1455c2c66affSColin Finck 
1456c2c66affSColin Finck   /*Compare the two formattings*/
1457c2c66affSColin Finck     ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects),
1458c2c66affSColin Finck       "two formats found in plain text mode - cf2.dwEffects: %x cf2test.dwEffects: %x\n",
1459c2c66affSColin Finck        cf2.dwEffects, cf2test.dwEffects);
1460c2c66affSColin Finck   /*Test TM_RICHTEXT by: switching back to Rich Text mode
1461c2c66affSColin Finck                          printing "wine" in the current format(normal)
1462c2c66affSColin Finck                          pasting "wine" from the clipboard(italicized)
1463c2c66affSColin Finck                          comparing the two formats(should differ)*/
1464c2c66affSColin Finck 
1465c2c66affSColin Finck   /*Attempt to switch with text in control*/
1466c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETTEXTMODE, (WPARAM)TM_RICHTEXT, 0);
1467c2c66affSColin Finck   ok(rc != 0, "EM_SETTEXTMODE: changed from plain text to rich text with text in control - returned: %d\n", rc);
1468c2c66affSColin Finck 
1469c2c66affSColin Finck   /*Clear control*/
1470c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
1471c2c66affSColin Finck 
1472c2c66affSColin Finck   /*Switch into Rich Text mode*/
1473c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETTEXTMODE, (WPARAM)TM_RICHTEXT, 0);
1474c2c66affSColin Finck   ok(rc == 0, "EM_SETTEXTMODE: unable to change to rich text with empty control - returned: %d\n", rc);
1475c2c66affSColin Finck 
1476c2c66affSColin Finck   /*Print "wine" in normal formatting into the control*/
1477c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1478c2c66affSColin Finck 
1479c2c66affSColin Finck   /*Paste italicized "wine" into the control*/
1480c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
1481c2c66affSColin Finck 
1482c2c66affSColin Finck   /*Select text from the first "wine" string*/
1483c2c66affSColin Finck   cr.cpMin = 1;
1484c2c66affSColin Finck   cr.cpMax = 3;
1485c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1486c2c66affSColin Finck 
1487c2c66affSColin Finck   /*Retrieve its formatting*/
1488c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&cf2);
1489c2c66affSColin Finck 
1490c2c66affSColin Finck   /*Select text from the second "wine" string*/
1491c2c66affSColin Finck   cr.cpMin = 6;
1492c2c66affSColin Finck   cr.cpMax = 7;
1493c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1494c2c66affSColin Finck 
1495c2c66affSColin Finck   /*Retrieve its formatting*/
1496c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&cf2test);
1497c2c66affSColin Finck 
1498c2c66affSColin Finck   /*Test that the two formattings are not the same*/
1499c2c66affSColin Finck   todo_wine ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects != cf2test.dwEffects),
1500c2c66affSColin Finck       "expected different formats - cf2.dwMask: %x, cf2test.dwMask: %x, cf2.dwEffects: %x, cf2test.dwEffects: %x\n",
1501c2c66affSColin Finck       cf2.dwMask, cf2test.dwMask, cf2.dwEffects, cf2test.dwEffects);
1502c2c66affSColin Finck 
1503c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
1504c2c66affSColin Finck }
1505c2c66affSColin Finck 
test_SETPARAFORMAT(void)1506c2c66affSColin Finck static void test_SETPARAFORMAT(void)
1507c2c66affSColin Finck {
1508c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
1509c2c66affSColin Finck   PARAFORMAT2 fmt;
1510c2c66affSColin Finck   HRESULT ret;
1511c2c66affSColin Finck   LONG expectedMask = PFM_ALL2 & ~PFM_TABLEROWDELIMITER;
1512c2c66affSColin Finck   fmt.cbSize = sizeof(PARAFORMAT2);
1513c2c66affSColin Finck   fmt.dwMask = PFM_ALIGNMENT;
1514c2c66affSColin Finck   fmt.wAlignment = PFA_LEFT;
1515c2c66affSColin Finck 
1516c2c66affSColin Finck   ret = SendMessageA(hwndRichEdit, EM_SETPARAFORMAT, 0, (LPARAM)&fmt);
1517c2c66affSColin Finck   ok(ret != 0, "expected non-zero got %d\n", ret);
1518c2c66affSColin Finck 
1519c2c66affSColin Finck   fmt.cbSize = sizeof(PARAFORMAT2);
1520c2c66affSColin Finck   fmt.dwMask = -1;
1521c2c66affSColin Finck   ret = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
1522c2c66affSColin Finck   /* Ignore the PFM_TABLEROWDELIMITER bit because it changes
1523c2c66affSColin Finck    * between richedit different native builds of riched20.dll
1524c2c66affSColin Finck    * used on different Windows versions. */
1525c2c66affSColin Finck   ret &= ~PFM_TABLEROWDELIMITER;
1526c2c66affSColin Finck   fmt.dwMask &= ~PFM_TABLEROWDELIMITER;
1527c2c66affSColin Finck 
1528c2c66affSColin Finck   ok(ret == expectedMask, "expected %x got %x\n", expectedMask, ret);
1529c2c66affSColin Finck   ok(fmt.dwMask == expectedMask, "expected %x got %x\n", expectedMask, fmt.dwMask);
1530c2c66affSColin Finck 
1531c2c66affSColin Finck   /* Test some other paraformat field defaults */
1532c2c66affSColin Finck   ok( fmt.wNumbering == 0, "got %d\n", fmt.wNumbering );
1533c2c66affSColin Finck   ok( fmt.wNumberingStart == 0, "got %d\n", fmt.wNumberingStart );
1534c2c66affSColin Finck   ok( fmt.wNumberingStyle == 0, "got %04x\n", fmt.wNumberingStyle );
1535c2c66affSColin Finck   ok( fmt.wNumberingTab == 0, "got %d\n", fmt.wNumberingTab );
1536c2c66affSColin Finck 
1537c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
1538c2c66affSColin Finck }
1539c2c66affSColin Finck 
test_TM_PLAINTEXT(void)1540c2c66affSColin Finck static void test_TM_PLAINTEXT(void)
1541c2c66affSColin Finck {
1542c2c66affSColin Finck   /*Tests plain text properties*/
1543c2c66affSColin Finck 
1544c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
1545c2c66affSColin Finck   CHARFORMAT2A cf2, cf2test;
1546c2c66affSColin Finck   CHARRANGE cr;
1547c2c66affSColin Finck   int rc = 0;
1548c2c66affSColin Finck 
1549c2c66affSColin Finck   /*Switch to plain text mode*/
1550c2c66affSColin Finck 
1551c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
1552c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTMODE, TM_PLAINTEXT, 0);
1553c2c66affSColin Finck 
1554c2c66affSColin Finck   /*Fill control with text*/
1555c2c66affSColin Finck 
1556c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"Is Wine an emulator? No it's not");
1557c2c66affSColin Finck 
1558c2c66affSColin Finck   /*Select some text and bold it*/
1559c2c66affSColin Finck 
1560c2c66affSColin Finck   cr.cpMin = 10;
1561c2c66affSColin Finck   cr.cpMax = 20;
1562c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1563c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
1564c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2);
1565c2c66affSColin Finck 
1566c2c66affSColin Finck   cf2.dwMask = CFM_BOLD | cf2.dwMask;
1567c2c66affSColin Finck   cf2.dwEffects = CFE_BOLD ^ cf2.dwEffects;
1568c2c66affSColin Finck 
1569c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1570c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
1571c2c66affSColin Finck 
1572c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_WORD | SCF_SELECTION, (LPARAM)&cf2);
1573c2c66affSColin Finck   ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc);
1574c2c66affSColin Finck 
1575c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf2);
1576c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
1577c2c66affSColin Finck 
1578c2c66affSColin Finck   /*Get the formatting of those characters*/
1579c2c66affSColin Finck 
1580c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1581c2c66affSColin Finck 
1582c2c66affSColin Finck   /*Get the formatting of some other characters*/
1583c2c66affSColin Finck   cf2test.cbSize = sizeof(CHARFORMAT2A);
1584c2c66affSColin Finck   cr.cpMin = 21;
1585c2c66affSColin Finck   cr.cpMax = 30;
1586c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1587c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2test);
1588c2c66affSColin Finck 
1589c2c66affSColin Finck   /*Test that they are the same as plain text allows only one formatting*/
1590c2c66affSColin Finck 
1591c2c66affSColin Finck   ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects),
1592c2c66affSColin Finck      "two selections' formats differ - cf2.dwMask: %x, cf2test.dwMask %x, cf2.dwEffects: %x, cf2test.dwEffects: %x\n",
1593c2c66affSColin Finck      cf2.dwMask, cf2test.dwMask, cf2.dwEffects, cf2test.dwEffects);
1594c2c66affSColin Finck 
1595c2c66affSColin Finck   /*Fill the control with a "wine" string, which when inserted will be bold*/
1596c2c66affSColin Finck 
1597c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1598c2c66affSColin Finck 
1599c2c66affSColin Finck   /*Copy the bolded "wine" string*/
1600c2c66affSColin Finck 
1601c2c66affSColin Finck   cr.cpMin = 0;
1602c2c66affSColin Finck   cr.cpMax = 4;
1603c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1604c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
1605c2c66affSColin Finck 
1606c2c66affSColin Finck   /*Swap back to rich text*/
1607c2c66affSColin Finck 
1608c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
1609c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTMODE, TM_RICHTEXT, 0);
1610c2c66affSColin Finck 
1611c2c66affSColin Finck   /*Set the default formatting to bold italics*/
1612c2c66affSColin Finck 
1613c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2);
1614c2c66affSColin Finck   cf2.dwMask |= CFM_ITALIC;
1615c2c66affSColin Finck   cf2.dwEffects ^= CFE_ITALIC;
1616c2c66affSColin Finck   rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf2);
1617c2c66affSColin Finck   ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc);
1618c2c66affSColin Finck 
1619c2c66affSColin Finck   /*Set the text in the control to "wine", which will be bold and italicized*/
1620c2c66affSColin Finck 
1621c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
1622c2c66affSColin Finck 
1623c2c66affSColin Finck   /*Paste the plain text "wine" string, which should take the insert
1624c2c66affSColin Finck    formatting, which at the moment is bold italics*/
1625c2c66affSColin Finck 
1626c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
1627c2c66affSColin Finck 
1628c2c66affSColin Finck   /*Select the first "wine" string and retrieve its formatting*/
1629c2c66affSColin Finck 
1630c2c66affSColin Finck   cr.cpMin = 1;
1631c2c66affSColin Finck   cr.cpMax = 3;
1632c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1633c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
1634c2c66affSColin Finck 
1635c2c66affSColin Finck   /*Select the second "wine" string and retrieve its formatting*/
1636c2c66affSColin Finck 
1637c2c66affSColin Finck   cr.cpMin = 5;
1638c2c66affSColin Finck   cr.cpMax = 7;
1639c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
1640c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2test);
1641c2c66affSColin Finck 
1642c2c66affSColin Finck   /*Compare the two formattings. They should be the same.*/
1643c2c66affSColin Finck 
1644c2c66affSColin Finck   ok((cf2.dwMask == cf2test.dwMask) && (cf2.dwEffects == cf2test.dwEffects),
1645c2c66affSColin Finck      "Copied text retained formatting - cf2.dwMask: %x, cf2test.dwMask: %x, cf2.dwEffects: %x, cf2test.dwEffects: %x\n",
1646c2c66affSColin Finck      cf2.dwMask, cf2test.dwMask, cf2.dwEffects, cf2test.dwEffects);
1647c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
1648c2c66affSColin Finck }
1649c2c66affSColin Finck 
test_WM_GETTEXT(void)1650c2c66affSColin Finck static void test_WM_GETTEXT(void)
1651c2c66affSColin Finck {
1652c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
1653c2c66affSColin Finck     static const char text[] = "Hello. My name is RichEdit!";
1654c2c66affSColin Finck     static const char text2[] = "Hello. My name is RichEdit!\r";
1655c2c66affSColin Finck     static const char text2_after[] = "Hello. My name is RichEdit!\r\n";
1656c2c66affSColin Finck     char buffer[1024] = {0};
1657c2c66affSColin Finck     int result;
1658c2c66affSColin Finck 
1659c2c66affSColin Finck     /* Baseline test with normal-sized buffer */
1660c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
1661c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
1662c2c66affSColin Finck     ok(result == lstrlenA(buffer),
1663c2c66affSColin Finck         "WM_GETTEXT returned %d, expected %d\n", result, lstrlenA(buffer));
1664c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
1665c2c66affSColin Finck     result = strcmp(buffer,text);
1666c2c66affSColin Finck     ok(result == 0,
1667c2c66affSColin Finck         "WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
1668c2c66affSColin Finck 
1669c2c66affSColin Finck     /* Test for returned value of WM_GETTEXTLENGTH */
1670c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
1671c2c66affSColin Finck     ok(result == lstrlenA(text),
1672c2c66affSColin Finck         "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
1673c2c66affSColin Finck         result, lstrlenA(text));
1674c2c66affSColin Finck 
1675c2c66affSColin Finck     /* Test for behavior in overflow case */
1676c2c66affSColin Finck     memset(buffer, 0, 1024);
1677c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, strlen(text), (LPARAM)buffer);
1678c2c66affSColin Finck     ok(result == 0 ||
1679c2c66affSColin Finck        result == lstrlenA(text) - 1, /* XP, win2k3 */
1680c2c66affSColin Finck         "WM_GETTEXT returned %d, expected 0 or %d\n", result, lstrlenA(text) - 1);
1681c2c66affSColin Finck     result = strcmp(buffer,text);
1682c2c66affSColin Finck     if (result)
1683c2c66affSColin Finck         result = strncmp(buffer, text, lstrlenA(text) - 1); /* XP, win2k3 */
1684c2c66affSColin Finck     ok(result == 0,
1685c2c66affSColin Finck         "WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
1686c2c66affSColin Finck 
1687c2c66affSColin Finck     /* Baseline test with normal-sized buffer and carriage return */
1688c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
1689c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
1690c2c66affSColin Finck     ok(result == lstrlenA(buffer),
1691c2c66affSColin Finck         "WM_GETTEXT returned %d, expected %d\n", result, lstrlenA(buffer));
1692c2c66affSColin Finck     result = strcmp(buffer,text2_after);
1693c2c66affSColin Finck     ok(result == 0,
1694c2c66affSColin Finck         "WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
1695c2c66affSColin Finck 
1696c2c66affSColin Finck     /* Test for returned value of WM_GETTEXTLENGTH */
1697c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
1698c2c66affSColin Finck     ok(result == lstrlenA(text2_after),
1699c2c66affSColin Finck         "WM_GETTEXTLENGTH reports incorrect length %d, expected %d\n",
1700c2c66affSColin Finck         result, lstrlenA(text2_after));
1701c2c66affSColin Finck 
1702c2c66affSColin Finck     /* Test for behavior of CRLF conversion in case of overflow */
1703c2c66affSColin Finck     memset(buffer, 0, 1024);
1704c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, strlen(text2), (LPARAM)buffer);
1705c2c66affSColin Finck     ok(result == 0 ||
1706c2c66affSColin Finck        result == lstrlenA(text2) - 1, /* XP, win2k3 */
1707c2c66affSColin Finck         "WM_GETTEXT returned %d, expected 0 or %d\n", result, lstrlenA(text2) - 1);
1708c2c66affSColin Finck     result = strcmp(buffer,text2);
1709c2c66affSColin Finck     if (result)
1710c2c66affSColin Finck         result = strncmp(buffer, text2, lstrlenA(text2) - 1); /* XP, win2k3 */
1711c2c66affSColin Finck     ok(result == 0,
1712c2c66affSColin Finck         "WM_GETTEXT: settext and gettext differ. strcmp: %d\n", result);
1713c2c66affSColin Finck 
1714c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
1715c2c66affSColin Finck }
1716c2c66affSColin Finck 
test_EM_GETTEXTRANGE(void)1717c2c66affSColin Finck static void test_EM_GETTEXTRANGE(void)
1718c2c66affSColin Finck {
1719c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
1720c2c66affSColin Finck     const char * text1 = "foo bar\r\nfoo bar";
1721c2c66affSColin Finck     const char * text2 = "foo bar\rfoo bar";
1722c2c66affSColin Finck     const char * expect = "bar\rfoo";
1723c2c66affSColin Finck     char buffer[1024] = {0};
1724c2c66affSColin Finck     LRESULT result;
1725c2c66affSColin Finck     TEXTRANGEA textRange;
1726c2c66affSColin Finck 
1727c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
1728c2c66affSColin Finck 
1729c2c66affSColin Finck     textRange.lpstrText = buffer;
1730c2c66affSColin Finck     textRange.chrg.cpMin = 4;
1731c2c66affSColin Finck     textRange.chrg.cpMax = 11;
1732c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1733c2c66affSColin Finck     ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
1734c2c66affSColin Finck     ok(!strcmp(expect, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1735c2c66affSColin Finck 
1736c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
1737c2c66affSColin Finck 
1738c2c66affSColin Finck     textRange.lpstrText = buffer;
1739c2c66affSColin Finck     textRange.chrg.cpMin = 4;
1740c2c66affSColin Finck     textRange.chrg.cpMax = 11;
1741c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1742c2c66affSColin Finck     ok(result == 7, "EM_GETTEXTRANGE returned %ld\n", result);
1743c2c66affSColin Finck     ok(!strcmp(expect, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1744c2c66affSColin Finck 
1745c2c66affSColin Finck     /* cpMax of text length is used instead of -1 in this case */
1746c2c66affSColin Finck     textRange.lpstrText = buffer;
1747c2c66affSColin Finck     textRange.chrg.cpMin = 0;
1748c2c66affSColin Finck     textRange.chrg.cpMax = -1;
1749c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1750c2c66affSColin Finck     ok(result == strlen(text2), "EM_GETTEXTRANGE returned %ld\n", result);
1751c2c66affSColin Finck     ok(!strcmp(text2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1752c2c66affSColin Finck 
1753c2c66affSColin Finck     /* cpMin < 0 causes no text to be copied, and 0 to be returned */
1754c2c66affSColin Finck     textRange.lpstrText = buffer;
1755c2c66affSColin Finck     textRange.chrg.cpMin = -1;
1756c2c66affSColin Finck     textRange.chrg.cpMax = 1;
1757c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1758c2c66affSColin Finck     ok(result == 0, "EM_GETTEXTRANGE returned %ld\n", result);
1759c2c66affSColin Finck     ok(!strcmp(text2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1760c2c66affSColin Finck 
1761c2c66affSColin Finck     /* cpMax of -1 is not replaced with text length if cpMin != 0 */
1762c2c66affSColin Finck     textRange.lpstrText = buffer;
1763c2c66affSColin Finck     textRange.chrg.cpMin = 1;
1764c2c66affSColin Finck     textRange.chrg.cpMax = -1;
1765c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1766c2c66affSColin Finck     ok(result == 0, "EM_GETTEXTRANGE returned %ld\n", result);
1767c2c66affSColin Finck     ok(!strcmp(text2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1768c2c66affSColin Finck 
1769c2c66affSColin Finck     /* no end character is copied if cpMax - cpMin < 0 */
1770c2c66affSColin Finck     textRange.lpstrText = buffer;
1771c2c66affSColin Finck     textRange.chrg.cpMin = 5;
1772c2c66affSColin Finck     textRange.chrg.cpMax = 5;
1773c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1774c2c66affSColin Finck     ok(result == 0, "EM_GETTEXTRANGE returned %ld\n", result);
1775c2c66affSColin Finck     ok(!strcmp(text2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1776c2c66affSColin Finck 
1777c2c66affSColin Finck     /* cpMax of text length is used if cpMax > text length*/
1778c2c66affSColin Finck     textRange.lpstrText = buffer;
1779c2c66affSColin Finck     textRange.chrg.cpMin = 0;
1780c2c66affSColin Finck     textRange.chrg.cpMax = 1000;
1781c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1782c2c66affSColin Finck     ok(result == strlen(text2), "EM_GETTEXTRANGE returned %ld\n", result);
1783c2c66affSColin Finck     ok(!strcmp(text2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1784c2c66affSColin Finck 
1785c2c66affSColin Finck     /* Test with multibyte character */
1786c2c66affSColin Finck     if (!is_lang_japanese)
1787c2c66affSColin Finck         skip("Skip multibyte character tests on non-Japanese platform\n");
1788c2c66affSColin Finck     else
1789c2c66affSColin Finck     {
1790c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
1791c2c66affSColin Finck         textRange.chrg.cpMin = 4;
1792c2c66affSColin Finck         textRange.chrg.cpMax = 8;
1793c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
1794c2c66affSColin Finck         todo_wine ok(result == 5, "EM_GETTEXTRANGE returned %ld\n", result);
1795c2c66affSColin Finck         todo_wine ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
1796c2c66affSColin Finck     }
1797c2c66affSColin Finck 
1798c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
1799c2c66affSColin Finck }
1800c2c66affSColin Finck 
test_EM_GETSELTEXT(void)1801c2c66affSColin Finck static void test_EM_GETSELTEXT(void)
1802c2c66affSColin Finck {
1803c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
1804c2c66affSColin Finck     const char * text1 = "foo bar\r\nfoo bar";
1805c2c66affSColin Finck     const char * text2 = "foo bar\rfoo bar";
1806c2c66affSColin Finck     const char * expect = "bar\rfoo";
1807c2c66affSColin Finck     char buffer[1024] = {0};
1808c2c66affSColin Finck     LRESULT result;
1809c2c66affSColin Finck 
1810c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
1811c2c66affSColin Finck 
1812c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 4, 11);
1813c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
1814c2c66affSColin Finck     ok(result == 7, "EM_GETSELTEXT returned %ld\n", result);
1815c2c66affSColin Finck     ok(!strcmp(expect, buffer), "EM_GETSELTEXT filled %s\n", buffer);
1816c2c66affSColin Finck 
1817c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 4, 11);
1820c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
1821c2c66affSColin Finck     ok(result == 7, "EM_GETSELTEXT returned %ld\n", result);
1822c2c66affSColin Finck     ok(!strcmp(expect, buffer), "EM_GETSELTEXT filled %s\n", buffer);
1823c2c66affSColin Finck 
1824c2c66affSColin Finck     /* Test with multibyte character */
1825c2c66affSColin Finck     if (!is_lang_japanese)
1826c2c66affSColin Finck         skip("Skip multibyte character tests on non-Japanese platform\n");
1827c2c66affSColin Finck     else
1828c2c66affSColin Finck     {
1829c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
1830c2c66affSColin Finck         SendMessageA(hwndRichEdit, EM_SETSEL, 4, 8);
1831c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
1832c2c66affSColin Finck         todo_wine ok(result == 5, "EM_GETSELTEXT returned %ld\n", result);
1833c2c66affSColin Finck         todo_wine ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETSELTEXT filled %s\n", buffer);
1834c2c66affSColin Finck     }
1835c2c66affSColin Finck 
1836c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
1837c2c66affSColin Finck }
1838c2c66affSColin Finck 
1839c2c66affSColin Finck /* FIXME: need to test unimplemented options and robustly test wparam */
test_EM_SETOPTIONS(void)1840c2c66affSColin Finck static void test_EM_SETOPTIONS(void)
1841c2c66affSColin Finck {
1842c2c66affSColin Finck     HWND hwndRichEdit;
1843c2c66affSColin Finck     static const char text[] = "Hello. My name is RichEdit!";
1844c2c66affSColin Finck     char buffer[1024] = {0};
1845c2c66affSColin Finck     DWORD dwStyle, options, oldOptions;
1846c2c66affSColin Finck     DWORD optionStyles = ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_NOHIDESEL|
1847c2c66affSColin Finck                          ES_READONLY|ES_WANTRETURN|ES_SAVESEL|
1848c2c66affSColin Finck                          ES_SELECTIONBAR|ES_VERTICAL;
1849c2c66affSColin Finck 
1850c2c66affSColin Finck     /* Test initial options. */
1851c2c66affSColin Finck     hwndRichEdit = CreateWindowA(RICHEDIT_CLASS20A, NULL, WS_POPUP,
1852c2c66affSColin Finck                                 0, 0, 200, 60, NULL, NULL,
1853c2c66affSColin Finck                                 hmoduleRichEdit, NULL);
1854c2c66affSColin Finck     ok(hwndRichEdit != NULL, "class: %s, error: %d\n",
1855c2c66affSColin Finck        RICHEDIT_CLASS20A, (int) GetLastError());
1856c2c66affSColin Finck     options = SendMessageA(hwndRichEdit, EM_GETOPTIONS, 0, 0);
1857c2c66affSColin Finck     ok(options == 0, "Incorrect initial options %x\n", options);
1858c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
1859c2c66affSColin Finck 
1860c2c66affSColin Finck     hwndRichEdit = CreateWindowA(RICHEDIT_CLASS20A, NULL,
1861c2c66affSColin Finck                                 WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
1862c2c66affSColin Finck                                 0, 0, 200, 60, NULL, NULL,
1863c2c66affSColin Finck                                 hmoduleRichEdit, NULL);
1864c2c66affSColin Finck     ok(hwndRichEdit != NULL, "class: %s, error: %d\n",
1865c2c66affSColin Finck        RICHEDIT_CLASS20A, (int) GetLastError());
1866c2c66affSColin Finck     options = SendMessageA(hwndRichEdit, EM_GETOPTIONS, 0, 0);
1867c2c66affSColin Finck     /* WS_[VH]SCROLL cause the ECO_AUTO[VH]SCROLL options to be set */
1868c2c66affSColin Finck     ok(options == (ECO_AUTOVSCROLL|ECO_AUTOHSCROLL),
1869c2c66affSColin Finck        "Incorrect initial options %x\n", options);
1870c2c66affSColin Finck 
1871c2c66affSColin Finck     /* NEGATIVE TESTING - NO OPTIONS SET */
1872c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
1873c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETOPTIONS, ECOOP_SET, 0);
1874c2c66affSColin Finck 
1875c2c66affSColin Finck     /* testing no readonly by sending 'a' to the control*/
1876c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_CHAR, 'a', 0x1E0001);
1877c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
1878c2c66affSColin Finck     ok(buffer[0]=='a',
1879c2c66affSColin Finck        "EM_SETOPTIONS: Text not changed! s1:%s s2:%s\n", text, buffer);
1880c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
1881c2c66affSColin Finck 
1882c2c66affSColin Finck     /* READONLY - sending 'a' to the control */
1883c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
1884c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETOPTIONS, ECOOP_SET, ECO_READONLY);
1885c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_CHAR, 'a', 0x1E0001);
1886c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
1887c2c66affSColin Finck     ok(buffer[0]==text[0],
1888c2c66affSColin Finck        "EM_SETOPTIONS: Text changed! s1:%s s2:%s\n", text, buffer);
1889c2c66affSColin Finck 
1890c2c66affSColin Finck     /* EM_SETOPTIONS changes the window style, but changing the
1891c2c66affSColin Finck      * window style does not change the options. */
1892c2c66affSColin Finck     dwStyle = GetWindowLongA(hwndRichEdit, GWL_STYLE);
1893c2c66affSColin Finck     ok(dwStyle & ES_READONLY, "Readonly style not set by EM_SETOPTIONS\n");
1894c2c66affSColin Finck     SetWindowLongA(hwndRichEdit, GWL_STYLE, dwStyle & ~ES_READONLY);
1895c2c66affSColin Finck     options = SendMessageA(hwndRichEdit, EM_GETOPTIONS, 0, 0);
1896c2c66affSColin Finck     ok(options & ES_READONLY, "Readonly option set by SetWindowLong\n");
1897c2c66affSColin Finck     /* Confirm that the text is still read only. */
1898c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_CHAR, 'a', ('a' << 16) | 0x0001);
1899c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
1900c2c66affSColin Finck     ok(buffer[0]==text[0],
1901c2c66affSColin Finck        "EM_SETOPTIONS: Text changed! s1:%s s2:%s\n", text, buffer);
1902c2c66affSColin Finck 
1903c2c66affSColin Finck     oldOptions = options;
1904c2c66affSColin Finck     SetWindowLongA(hwndRichEdit, GWL_STYLE, dwStyle|optionStyles);
1905c2c66affSColin Finck     options = SendMessageA(hwndRichEdit, EM_GETOPTIONS, 0, 0);
1906c2c66affSColin Finck     ok(options == oldOptions,
1907c2c66affSColin Finck        "Options set by SetWindowLong (%x -> %x)\n", oldOptions, options);
1908c2c66affSColin Finck 
1909c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
1910c2c66affSColin Finck }
1911c2c66affSColin Finck 
check_CFE_LINK_selection(HWND hwnd,int sel_start,int sel_end)1912c2c66affSColin Finck static BOOL check_CFE_LINK_selection(HWND hwnd, int sel_start, int sel_end)
1913c2c66affSColin Finck {
1914c2c66affSColin Finck   CHARFORMAT2A text_format;
1915c2c66affSColin Finck   text_format.cbSize = sizeof(text_format);
1916c2c66affSColin Finck   SendMessageA(hwnd, EM_SETSEL, sel_start, sel_end);
1917c2c66affSColin Finck   SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&text_format);
1918c2c66affSColin Finck   return (text_format.dwEffects & CFE_LINK) != 0;
1919c2c66affSColin Finck }
1920c2c66affSColin Finck 
check_CFE_LINK_rcvd(HWND hwnd,BOOL is_url,const char * url)1921c2c66affSColin Finck static void check_CFE_LINK_rcvd(HWND hwnd, BOOL is_url, const char * url)
1922c2c66affSColin Finck {
1923c2c66affSColin Finck   BOOL link_present = FALSE;
1924c2c66affSColin Finck 
1925c2c66affSColin Finck   link_present = check_CFE_LINK_selection(hwnd, 0, 1);
1926c2c66affSColin Finck   if (is_url)
1927c2c66affSColin Finck   { /* control text is url; should get CFE_LINK */
1928c2c66affSColin Finck     ok(link_present, "URL Case: CFE_LINK not set for [%s].\n", url);
1929c2c66affSColin Finck   }
1930c2c66affSColin Finck   else
1931c2c66affSColin Finck   {
1932c2c66affSColin Finck     ok(!link_present, "Non-URL Case: CFE_LINK set for [%s].\n", url);
1933c2c66affSColin Finck   }
1934c2c66affSColin Finck }
1935c2c66affSColin Finck 
new_static_wnd(HWND parent)1936c2c66affSColin Finck static HWND new_static_wnd(HWND parent) {
1937c2c66affSColin Finck   return new_window("Static", 0, parent);
1938c2c66affSColin Finck }
1939c2c66affSColin Finck 
test_EM_AUTOURLDETECT(void)1940c2c66affSColin Finck static void test_EM_AUTOURLDETECT(void)
1941c2c66affSColin Finck {
1942c2c66affSColin Finck   /* DO NOT change the properties of the first two elements. To shorten the
1943c2c66affSColin Finck      tests, all tests after WM_SETTEXT test just the first two elements -
1944c2c66affSColin Finck      one non-URL and one URL */
1945c2c66affSColin Finck   struct urls_s {
1946c2c66affSColin Finck     const char *text;
1947c2c66affSColin Finck     BOOL is_url;
1948c2c66affSColin Finck   } urls[12] = {
1949c2c66affSColin Finck     {"winehq.org", FALSE},
1950c2c66affSColin Finck     {"http://www.winehq.org", TRUE},
1951c2c66affSColin Finck     {"http//winehq.org", FALSE},
1952c2c66affSColin Finck     {"ww.winehq.org", FALSE},
1953c2c66affSColin Finck     {"www.winehq.org", TRUE},
1954c2c66affSColin Finck     {"ftp://192.168.1.1", TRUE},
1955c2c66affSColin Finck     {"ftp//192.168.1.1", FALSE},
1956c2c66affSColin Finck     {"mailto:your@email.com", TRUE},
1957c2c66affSColin Finck     {"prospero:prosperoserver", TRUE},
1958c2c66affSColin Finck     {"telnet:test", TRUE},
1959c2c66affSColin Finck     {"news:newserver", TRUE},
1960c2c66affSColin Finck     {"wais:waisserver", TRUE}
1961c2c66affSColin Finck   };
1962c2c66affSColin Finck 
1963c2c66affSColin Finck   int i, j;
1964c2c66affSColin Finck   int urlRet=-1;
1965c2c66affSColin Finck   HWND hwndRichEdit, parent;
1966c2c66affSColin Finck 
1967c2c66affSColin Finck   /* All of the following should cause the URL to be detected  */
1968c2c66affSColin Finck   const char * templates_delim[] = {
1969c2c66affSColin Finck     "This is some text with X on it",
1970c2c66affSColin Finck     "This is some text with (X) on it",
1971c2c66affSColin Finck     "This is some text with X\r on it",
1972c2c66affSColin Finck     "This is some text with ---X--- on it",
1973c2c66affSColin Finck     "This is some text with \"X\" on it",
1974c2c66affSColin Finck     "This is some text with 'X' on it",
1975c2c66affSColin Finck     "This is some text with 'X' on it",
1976c2c66affSColin Finck     "This is some text with :X: on it",
1977c2c66affSColin Finck 
1978c2c66affSColin Finck     "This text ends with X",
1979c2c66affSColin Finck 
1980c2c66affSColin Finck     "This is some text with X) on it",
1981c2c66affSColin Finck     "This is some text with X--- on it",
1982c2c66affSColin Finck     "This is some text with X\" on it",
1983c2c66affSColin Finck     "This is some text with X' on it",
1984c2c66affSColin Finck     "This is some text with X: on it",
1985c2c66affSColin Finck 
1986c2c66affSColin Finck     "This is some text with (X on it",
1987c2c66affSColin Finck     "This is some text with \rX on it",
1988c2c66affSColin Finck     "This is some text with ---X on it",
1989c2c66affSColin Finck     "This is some text with \"X on it",
1990c2c66affSColin Finck     "This is some text with 'X on it",
1991c2c66affSColin Finck     "This is some text with :X on it",
1992c2c66affSColin Finck   };
1993c2c66affSColin Finck   /* None of these should cause the URL to be detected */
1994c2c66affSColin Finck   const char * templates_non_delim[] = {
1995c2c66affSColin Finck     "This is some text with |X| on it",
1996c2c66affSColin Finck     "This is some text with *X* on it",
1997c2c66affSColin Finck     "This is some text with /X/ on it",
1998c2c66affSColin Finck     "This is some text with +X+ on it",
1999c2c66affSColin Finck     "This is some text with %X% on it",
2000c2c66affSColin Finck     "This is some text with #X# on it",
2001c2c66affSColin Finck     "This is some text with @X@ on it",
2002c2c66affSColin Finck     "This is some text with \\X\\ on it",
2003c2c66affSColin Finck     "This is some text with |X on it",
2004c2c66affSColin Finck     "This is some text with *X on it",
2005c2c66affSColin Finck     "This is some text with /X on it",
2006c2c66affSColin Finck     "This is some text with +X on it",
2007c2c66affSColin Finck     "This is some text with %X on it",
2008c2c66affSColin Finck     "This is some text with #X on it",
2009c2c66affSColin Finck     "This is some text with @X on it",
2010c2c66affSColin Finck     "This is some text with \\X on it",
2011c2c66affSColin Finck     "This is some text with _X on it",
2012c2c66affSColin Finck   };
2013c2c66affSColin Finck   /* All of these cause the URL detection to be extended by one more byte,
2014c2c66affSColin Finck      thus demonstrating that the tested character is considered as part
2015c2c66affSColin Finck      of the URL. */
2016c2c66affSColin Finck   const char * templates_xten_delim[] = {
2017c2c66affSColin Finck     "This is some text with X| on it",
2018c2c66affSColin Finck     "This is some text with X* on it",
2019c2c66affSColin Finck     "This is some text with X/ on it",
2020c2c66affSColin Finck     "This is some text with X+ on it",
2021c2c66affSColin Finck     "This is some text with X% on it",
2022c2c66affSColin Finck     "This is some text with X# on it",
2023c2c66affSColin Finck     "This is some text with X@ on it",
2024c2c66affSColin Finck     "This is some text with X\\ on it",
2025c2c66affSColin Finck     "This is some text with X_ on it",
2026c2c66affSColin Finck   };
2027c2c66affSColin Finck   /* These delims act as neutral breaks.  Whether the url is ended
2028c2c66affSColin Finck      or not depends on the next non-neutral character.  We'll test
2029c2c66affSColin Finck      with Y unchanged, in which case the url should include the
2030c2c66affSColin Finck      deliminator and the Y.  We'll also test with the Y changed
2031c2c66affSColin Finck      to a space, in which case the url stops before the
2032c2c66affSColin Finck      deliminator. */
2033c2c66affSColin Finck   const char * templates_neutral_delim[] = {
2034c2c66affSColin Finck     "This is some text with X-Y on it",
2035c2c66affSColin Finck     "This is some text with X--Y on it",
2036c2c66affSColin Finck     "This is some text with X!Y on it",
2037c2c66affSColin Finck     "This is some text with X[Y on it",
2038c2c66affSColin Finck     "This is some text with X]Y on it",
2039c2c66affSColin Finck     "This is some text with X{Y on it",
2040c2c66affSColin Finck     "This is some text with X}Y on it",
2041c2c66affSColin Finck     "This is some text with X(Y on it",
2042c2c66affSColin Finck     "This is some text with X)Y on it",
2043c2c66affSColin Finck     "This is some text with X\"Y on it",
2044c2c66affSColin Finck     "This is some text with X;Y on it",
2045c2c66affSColin Finck     "This is some text with X:Y on it",
2046c2c66affSColin Finck     "This is some text with X'Y on it",
2047c2c66affSColin Finck     "This is some text with X?Y on it",
2048c2c66affSColin Finck     "This is some text with X<Y on it",
2049c2c66affSColin Finck     "This is some text with X>Y on it",
2050c2c66affSColin Finck     "This is some text with X.Y on it",
2051c2c66affSColin Finck     "This is some text with X,Y on it",
2052c2c66affSColin Finck   };
2053c2c66affSColin Finck   char buffer[1024];
2054c2c66affSColin Finck 
2055c2c66affSColin Finck   parent = new_static_wnd(NULL);
2056c2c66affSColin Finck   hwndRichEdit = new_richedit(parent);
2057c2c66affSColin Finck   /* Try and pass EM_AUTOURLDETECT some test wParam values */
2058c2c66affSColin Finck   urlRet=SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, FALSE, 0);
2059c2c66affSColin Finck   ok(urlRet==0, "Good wParam: urlRet is: %d\n", urlRet);
2060c2c66affSColin Finck   urlRet=SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, 1, 0);
2061c2c66affSColin Finck   ok(urlRet==0, "Good wParam2: urlRet is: %d\n", urlRet);
2062c2c66affSColin Finck   /* Windows returns -2147024809 (0x80070057) on bad wParam values */
2063c2c66affSColin Finck   urlRet=SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, 8, 0);
2064c2c66affSColin Finck   ok(urlRet==E_INVALIDARG, "Bad wParam: urlRet is: %d\n", urlRet);
2065c2c66affSColin Finck   urlRet=SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, (WPARAM)"h", (LPARAM)"h");
2066c2c66affSColin Finck   ok(urlRet==E_INVALIDARG, "Bad wParam2: urlRet is: %d\n", urlRet);
2067c2c66affSColin Finck   /* for each url, check the text to see if CFE_LINK effect is present */
206876cf09cfSAmine Khaldi   for (i = 0; i < ARRAY_SIZE(urls); i++) {
2069c2c66affSColin Finck 
2070c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, FALSE, 0);
2071c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)urls[i].text);
2072c2c66affSColin Finck     check_CFE_LINK_rcvd(hwndRichEdit, FALSE, urls[i].text);
2073c2c66affSColin Finck 
2074c2c66affSColin Finck     /* Link detection should happen immediately upon WM_SETTEXT */
2075c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2076c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)urls[i].text);
2077c2c66affSColin Finck     check_CFE_LINK_rcvd(hwndRichEdit, urls[i].is_url, urls[i].text);
2078c2c66affSColin Finck   }
2079c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
2080c2c66affSColin Finck 
2081c2c66affSColin Finck   /* Test detection of URLs within normal text - WM_SETTEXT case. */
208276cf09cfSAmine Khaldi   for (i = 0; i < ARRAY_SIZE(urls); i++) {
2083c2c66affSColin Finck     hwndRichEdit = new_richedit(parent);
2084c2c66affSColin Finck 
208576cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_delim); j++) {
2086c2c66affSColin Finck       char * at_pos;
2087c2c66affSColin Finck       int at_offset;
2088c2c66affSColin Finck       int end_offset;
2089c2c66affSColin Finck 
2090c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2091c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2092c2c66affSColin Finck       memcpy(buffer, templates_delim[j], at_offset);
2093c2c66affSColin Finck       buffer[at_offset] = '\0';
2094c2c66affSColin Finck       strcat(buffer, urls[i].text);
2095c2c66affSColin Finck       strcat(buffer, templates_delim[j] + at_offset + 1);
2096c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2097c2c66affSColin Finck 
2098c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2099c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
2100c2c66affSColin Finck 
2101c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2102c2c66affSColin Finck          have at least two characters before the URL text */
2103c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2104c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2105c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2106c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2107c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2108c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2109c2c66affSColin Finck 
2110c2c66affSColin Finck       if (urls[i].is_url)
2111c2c66affSColin Finck       {
2112c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2113c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2114c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2115c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2116c2c66affSColin Finck       }
2117c2c66affSColin Finck       else
2118c2c66affSColin Finck       {
2119c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2120c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2121c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2122c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2123c2c66affSColin Finck       }
2124c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2125c2c66affSColin Finck       {
2126c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2127c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2128c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2129c2c66affSColin Finck         {
2130c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2131c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2132c2c66affSColin Finck         }
2133c2c66affSColin Finck       }
2134c2c66affSColin Finck     }
2135c2c66affSColin Finck 
213676cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_non_delim); j++) {
2137c2c66affSColin Finck       char * at_pos;
2138c2c66affSColin Finck       int at_offset;
2139c2c66affSColin Finck       int end_offset;
2140c2c66affSColin Finck 
2141c2c66affSColin Finck       at_pos = strchr(templates_non_delim[j], 'X');
2142c2c66affSColin Finck       at_offset = at_pos - templates_non_delim[j];
2143c2c66affSColin Finck       memcpy(buffer, templates_non_delim[j], at_offset);
2144c2c66affSColin Finck       buffer[at_offset] = '\0';
2145c2c66affSColin Finck       strcat(buffer, urls[i].text);
2146c2c66affSColin Finck       strcat(buffer, templates_non_delim[j] + at_offset + 1);
2147c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2148c2c66affSColin Finck 
2149c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2150c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
2151c2c66affSColin Finck 
2152c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2153c2c66affSColin Finck          have at least two characters before the URL text */
2154c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2155c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2156c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2157c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2158c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2159c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2160c2c66affSColin Finck 
2161c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2162c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2163c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2164c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2165c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2166c2c66affSColin Finck       {
2167c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2168c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2169c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2170c2c66affSColin Finck         {
2171c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2172c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2173c2c66affSColin Finck         }
2174c2c66affSColin Finck       }
2175c2c66affSColin Finck     }
2176c2c66affSColin Finck 
217776cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_xten_delim); j++) {
2178c2c66affSColin Finck       char * at_pos;
2179c2c66affSColin Finck       int at_offset;
2180c2c66affSColin Finck       int end_offset;
2181c2c66affSColin Finck 
2182c2c66affSColin Finck       at_pos = strchr(templates_xten_delim[j], 'X');
2183c2c66affSColin Finck       at_offset = at_pos - templates_xten_delim[j];
2184c2c66affSColin Finck       memcpy(buffer, templates_xten_delim[j], at_offset);
2185c2c66affSColin Finck       buffer[at_offset] = '\0';
2186c2c66affSColin Finck       strcat(buffer, urls[i].text);
2187c2c66affSColin Finck       strcat(buffer, templates_xten_delim[j] + at_offset + 1);
2188c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2189c2c66affSColin Finck 
2190c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2191c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
2192c2c66affSColin Finck 
2193c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2194c2c66affSColin Finck          have at least two characters before the URL text */
2195c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2196c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2197c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2198c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2199c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2200c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2201c2c66affSColin Finck 
2202c2c66affSColin Finck       if (urls[i].is_url)
2203c2c66affSColin Finck       {
2204c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2205c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2206c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2207c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2208c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2209c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset, end_offset +1, buffer);
2210c2c66affSColin Finck       }
2211c2c66affSColin Finck       else
2212c2c66affSColin Finck       {
2213c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2214c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2215c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2216c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2217c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2218c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset +1, buffer);
2219c2c66affSColin Finck       }
2220c2c66affSColin Finck       if (buffer[end_offset +1] != '\0')
2221c2c66affSColin Finck       {
2222c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2223c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset + 2, buffer);
2224c2c66affSColin Finck         if (buffer[end_offset +2] != '\0')
2225c2c66affSColin Finck         {
2226c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +2, end_offset +3),
2227c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +2, end_offset +3, buffer);
2228c2c66affSColin Finck         }
2229c2c66affSColin Finck       }
2230c2c66affSColin Finck     }
2231c2c66affSColin Finck 
223276cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_neutral_delim); j++) {
2233c2c66affSColin Finck       char * at_pos, * end_pos;
2234c2c66affSColin Finck       int at_offset;
2235c2c66affSColin Finck       int end_offset;
2236c2c66affSColin Finck 
2237c2c66affSColin Finck       if (!urls[i].is_url) continue;
2238c2c66affSColin Finck 
2239c2c66affSColin Finck       at_pos = strchr(templates_neutral_delim[j], 'X');
2240c2c66affSColin Finck       at_offset = at_pos - templates_neutral_delim[j];
2241c2c66affSColin Finck       memcpy(buffer, templates_neutral_delim[j], at_offset);
2242c2c66affSColin Finck       buffer[at_offset] = '\0';
2243c2c66affSColin Finck       strcat(buffer, urls[i].text);
2244c2c66affSColin Finck       strcat(buffer, templates_neutral_delim[j] + at_offset + 1);
2245c2c66affSColin Finck 
2246c2c66affSColin Finck       end_pos = strchr(buffer, 'Y');
2247c2c66affSColin Finck       end_offset = end_pos - buffer;
2248c2c66affSColin Finck 
2249c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2250c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
2251c2c66affSColin Finck 
2252c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2253c2c66affSColin Finck          have at least two characters before the URL text */
2254c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2255c2c66affSColin Finck          "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2256c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2257c2c66affSColin Finck          "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2258c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2259c2c66affSColin Finck          "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2260c2c66affSColin Finck 
2261c2c66affSColin Finck       ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2262c2c66affSColin Finck          "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2263c2c66affSColin Finck       ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2264c2c66affSColin Finck          "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2265c2c66affSColin Finck       ok(check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2266c2c66affSColin Finck          "CFE_LINK not set in (%d-%d), text: %s\n", end_offset, end_offset +1, buffer);
2267c2c66affSColin Finck 
2268c2c66affSColin Finck       *end_pos = ' ';
2269c2c66affSColin Finck 
2270c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2271c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
2272c2c66affSColin Finck 
2273c2c66affSColin Finck       ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2274c2c66affSColin Finck          "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2275c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2276c2c66affSColin Finck          "CFE_LINK set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2277c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2278c2c66affSColin Finck          "CFE_LINK set in (%d-%d), text: %s\n", end_offset, end_offset +1, buffer);
2279c2c66affSColin Finck     }
2280c2c66affSColin Finck 
2281c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
2282c2c66affSColin Finck     hwndRichEdit = NULL;
2283c2c66affSColin Finck   }
2284c2c66affSColin Finck 
2285c2c66affSColin Finck   /* Test detection of URLs within normal text - WM_CHAR case. */
2286c2c66affSColin Finck   /* Test only the first two URL examples for brevity */
2287c2c66affSColin Finck   for (i = 0; i < 2; i++) {
2288c2c66affSColin Finck     hwndRichEdit = new_richedit(parent);
2289c2c66affSColin Finck 
2290c2c66affSColin Finck     /* Also for brevity, test only the first three delimiters */
2291c2c66affSColin Finck     for (j = 0; j < 3; j++) {
2292c2c66affSColin Finck       char * at_pos;
2293c2c66affSColin Finck       int at_offset;
2294c2c66affSColin Finck       int end_offset;
2295c2c66affSColin Finck       int u, v;
2296c2c66affSColin Finck 
2297c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2298c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2299c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2300c2c66affSColin Finck 
2301c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2302c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
2303c2c66affSColin Finck       for (u = 0; templates_delim[j][u]; u++) {
2304c2c66affSColin Finck         if (templates_delim[j][u] == '\r') {
2305c2c66affSColin Finck           simulate_typing_characters(hwndRichEdit, "\r");
2306c2c66affSColin Finck         } else if (templates_delim[j][u] != 'X') {
2307c2c66affSColin Finck           SendMessageA(hwndRichEdit, WM_CHAR, templates_delim[j][u], 1);
2308c2c66affSColin Finck         } else {
2309c2c66affSColin Finck           for (v = 0; urls[i].text[v]; v++) {
2310c2c66affSColin Finck             SendMessageA(hwndRichEdit, WM_CHAR, urls[i].text[v], 1);
2311c2c66affSColin Finck           }
2312c2c66affSColin Finck         }
2313c2c66affSColin Finck       }
2314c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2315c2c66affSColin Finck 
2316c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2317c2c66affSColin Finck          have at least two characters before the URL text */
2318c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2319c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2320c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2321c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2322c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2323c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2324c2c66affSColin Finck 
2325c2c66affSColin Finck       if (urls[i].is_url)
2326c2c66affSColin Finck       {
2327c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2328c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2329c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2330c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2331c2c66affSColin Finck       }
2332c2c66affSColin Finck       else
2333c2c66affSColin Finck       {
2334c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2335c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2336c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2337c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2338c2c66affSColin Finck       }
2339c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2340c2c66affSColin Finck       {
2341c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2342c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2343c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2344c2c66affSColin Finck         {
2345c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2346c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2347c2c66affSColin Finck         }
2348c2c66affSColin Finck       }
2349c2c66affSColin Finck 
2350c2c66affSColin Finck       /* The following will insert a paragraph break after the first character
2351c2c66affSColin Finck          of the URL candidate, thus breaking the URL. It is expected that the
2352c2c66affSColin Finck          CFE_LINK attribute should break across both pieces of the URL */
2353c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset+1, at_offset+1);
2354c2c66affSColin Finck       simulate_typing_characters(hwndRichEdit, "\r");
2355c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2356c2c66affSColin Finck 
2357c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2358c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2359c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2360c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2361c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2362c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2363c2c66affSColin Finck 
2364c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2365c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2366c2c66affSColin Finck       /* end_offset moved because of paragraph break */
2367c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2368c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset+1, buffer);
2369c2c66affSColin Finck       ok(buffer[end_offset], "buffer \"%s\" ended prematurely. Is it missing a newline character?\n", buffer);
2370c2c66affSColin Finck       if (buffer[end_offset] != 0  && buffer[end_offset+1] != '\0')
2371c2c66affSColin Finck       {
2372c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset+1, end_offset +2),
2373c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset+1, end_offset +2, buffer);
2374c2c66affSColin Finck         if (buffer[end_offset +2] != '\0')
2375c2c66affSColin Finck         {
2376c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +2, end_offset +3),
2377c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +2, end_offset +3, buffer);
2378c2c66affSColin Finck         }
2379c2c66affSColin Finck       }
2380c2c66affSColin Finck 
2381c2c66affSColin Finck       /* The following will remove the just-inserted paragraph break, thus
2382c2c66affSColin Finck          restoring the URL */
2383c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset+2, at_offset+2);
2384c2c66affSColin Finck       simulate_typing_characters(hwndRichEdit, "\b");
2385c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2386c2c66affSColin Finck 
2387c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2388c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2389c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2390c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2391c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2392c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2393c2c66affSColin Finck 
2394c2c66affSColin Finck       if (urls[i].is_url)
2395c2c66affSColin Finck       {
2396c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2397c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2398c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2399c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2400c2c66affSColin Finck       }
2401c2c66affSColin Finck       else
2402c2c66affSColin Finck       {
2403c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2404c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2405c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2406c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2407c2c66affSColin Finck       }
2408c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2409c2c66affSColin Finck       {
2410c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2411c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2412c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2413c2c66affSColin Finck         {
2414c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2415c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2416c2c66affSColin Finck         }
2417c2c66affSColin Finck       }
2418c2c66affSColin Finck     }
2419c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
2420c2c66affSColin Finck     hwndRichEdit = NULL;
2421c2c66affSColin Finck   }
2422c2c66affSColin Finck 
2423c2c66affSColin Finck   /* Test detection of URLs within normal text - EM_SETTEXTEX case. */
2424c2c66affSColin Finck   /* Test just the first two URL examples for brevity */
2425c2c66affSColin Finck   for (i = 0; i < 2; i++) {
2426c2c66affSColin Finck     SETTEXTEX st;
2427c2c66affSColin Finck 
2428c2c66affSColin Finck     hwndRichEdit = new_richedit(parent);
2429c2c66affSColin Finck 
2430c2c66affSColin Finck     /* There are at least three ways in which EM_SETTEXTEX must cause URLs to
2431c2c66affSColin Finck        be detected:
2432c2c66affSColin Finck        1) Set entire text, a la WM_SETTEXT
2433c2c66affSColin Finck        2) Set a selection of the text to the URL
2434c2c66affSColin Finck        3) Set a portion of the text at a time, which eventually results in
2435c2c66affSColin Finck           an URL
2436c2c66affSColin Finck        All of them should give equivalent results
2437c2c66affSColin Finck      */
2438c2c66affSColin Finck 
2439c2c66affSColin Finck     /* Set entire text in one go, like WM_SETTEXT */
244076cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_delim); j++) {
2441c2c66affSColin Finck       char * at_pos;
2442c2c66affSColin Finck       int at_offset;
2443c2c66affSColin Finck       int end_offset;
2444c2c66affSColin Finck 
2445c2c66affSColin Finck       st.codepage = CP_ACP;
2446c2c66affSColin Finck       st.flags = ST_DEFAULT;
2447c2c66affSColin Finck 
2448c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2449c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2450c2c66affSColin Finck       memcpy(buffer, templates_delim[j], at_offset);
2451c2c66affSColin Finck       buffer[at_offset] = '\0';
2452c2c66affSColin Finck       strcat(buffer, urls[i].text);
2453c2c66affSColin Finck       strcat(buffer, templates_delim[j] + at_offset + 1);
2454c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2455c2c66affSColin Finck 
2456c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2457c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)buffer);
2458c2c66affSColin Finck 
2459c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2460c2c66affSColin Finck          have at least two characters before the URL text */
2461c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2462c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2463c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2464c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2465c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2466c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2467c2c66affSColin Finck 
2468c2c66affSColin Finck       if (urls[i].is_url)
2469c2c66affSColin Finck       {
2470c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2471c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2472c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2473c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2474c2c66affSColin Finck       }
2475c2c66affSColin Finck       else
2476c2c66affSColin Finck       {
2477c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2478c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2479c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2480c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2481c2c66affSColin Finck       }
2482c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2483c2c66affSColin Finck       {
2484c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2485c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2486c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2487c2c66affSColin Finck         {
2488c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2489c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2490c2c66affSColin Finck         }
2491c2c66affSColin Finck       }
2492c2c66affSColin Finck     }
2493c2c66affSColin Finck 
2494c2c66affSColin Finck     /* Set selection with X to the URL */
249576cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_delim); j++) {
2496c2c66affSColin Finck       char * at_pos;
2497c2c66affSColin Finck       int at_offset;
2498c2c66affSColin Finck       int end_offset;
2499c2c66affSColin Finck 
2500c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2501c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2502c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2503c2c66affSColin Finck 
2504c2c66affSColin Finck       st.codepage = CP_ACP;
2505c2c66affSColin Finck       st.flags = ST_DEFAULT;
2506c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2507c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)templates_delim[j]);
2508c2c66affSColin Finck       st.flags = ST_SELECTION;
2509c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset, at_offset+1);
2510c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)urls[i].text);
2511c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2512c2c66affSColin Finck 
2513c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2514c2c66affSColin Finck          have at least two characters before the URL text */
2515c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2516c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2517c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2518c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2519c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2520c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2521c2c66affSColin Finck 
2522c2c66affSColin Finck       if (urls[i].is_url)
2523c2c66affSColin Finck       {
2524c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2525c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2526c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2527c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2528c2c66affSColin Finck       }
2529c2c66affSColin Finck       else
2530c2c66affSColin Finck       {
2531c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2532c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2533c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2534c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2535c2c66affSColin Finck       }
2536c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2537c2c66affSColin Finck       {
2538c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2539c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2540c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2541c2c66affSColin Finck         {
2542c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2543c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2544c2c66affSColin Finck         }
2545c2c66affSColin Finck       }
2546c2c66affSColin Finck     }
2547c2c66affSColin Finck 
2548c2c66affSColin Finck     /* Set selection with X to the first character of the URL, then the rest */
254976cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_delim); j++) {
2550c2c66affSColin Finck       char * at_pos;
2551c2c66affSColin Finck       int at_offset;
2552c2c66affSColin Finck       int end_offset;
2553c2c66affSColin Finck 
2554c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2555c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2556c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2557c2c66affSColin Finck 
2558c2c66affSColin Finck       strcpy(buffer, "YY");
2559c2c66affSColin Finck       buffer[0] = urls[i].text[0];
2560c2c66affSColin Finck 
2561c2c66affSColin Finck       st.codepage = CP_ACP;
2562c2c66affSColin Finck       st.flags = ST_DEFAULT;
2563c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2564c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)templates_delim[j]);
2565c2c66affSColin Finck       st.flags = ST_SELECTION;
2566c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset, at_offset+1);
2567c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)buffer);
2568c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset+1, at_offset+2);
2569c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)(urls[i].text + 1));
2570c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2571c2c66affSColin Finck 
2572c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2573c2c66affSColin Finck          have at least two characters before the URL text */
2574c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2575c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2576c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2577c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2578c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2579c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2580c2c66affSColin Finck 
2581c2c66affSColin Finck       if (urls[i].is_url)
2582c2c66affSColin Finck       {
2583c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2584c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2585c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2586c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2587c2c66affSColin Finck       }
2588c2c66affSColin Finck       else
2589c2c66affSColin Finck       {
2590c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2591c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2592c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2593c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2594c2c66affSColin Finck       }
2595c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2596c2c66affSColin Finck       {
2597c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2598c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2599c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2600c2c66affSColin Finck         {
2601c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2602c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2603c2c66affSColin Finck         }
2604c2c66affSColin Finck       }
2605c2c66affSColin Finck     }
2606c2c66affSColin Finck 
2607c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
2608c2c66affSColin Finck     hwndRichEdit = NULL;
2609c2c66affSColin Finck   }
2610c2c66affSColin Finck 
2611c2c66affSColin Finck   /* Test detection of URLs within normal text - EM_REPLACESEL case. */
2612c2c66affSColin Finck   /* Test just the first two URL examples for brevity */
2613c2c66affSColin Finck   for (i = 0; i < 2; i++) {
2614c2c66affSColin Finck     hwndRichEdit = new_richedit(parent);
2615c2c66affSColin Finck 
2616c2c66affSColin Finck     /* Set selection with X to the URL */
261776cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_delim); j++) {
2618c2c66affSColin Finck       char * at_pos;
2619c2c66affSColin Finck       int at_offset;
2620c2c66affSColin Finck       int end_offset;
2621c2c66affSColin Finck 
2622c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2623c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2624c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2625c2c66affSColin Finck 
2626c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2627c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)templates_delim[j]);
2628c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset, at_offset+1);
2629c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)urls[i].text);
2630c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2631c2c66affSColin Finck 
2632c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2633c2c66affSColin Finck          have at least two characters before the URL text */
2634c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2635c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2636c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2637c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2638c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2639c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2640c2c66affSColin Finck 
2641c2c66affSColin Finck       if (urls[i].is_url)
2642c2c66affSColin Finck       {
2643c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2644c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2645c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2646c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2647c2c66affSColin Finck       }
2648c2c66affSColin Finck       else
2649c2c66affSColin Finck       {
2650c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2651c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2652c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2653c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2654c2c66affSColin Finck       }
2655c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2656c2c66affSColin Finck       {
2657c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2658c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2659c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2660c2c66affSColin Finck         {
2661c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2662c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2663c2c66affSColin Finck         }
2664c2c66affSColin Finck       }
2665c2c66affSColin Finck     }
2666c2c66affSColin Finck 
2667c2c66affSColin Finck     /* Set selection with X to the first character of the URL, then the rest */
266876cf09cfSAmine Khaldi     for (j = 0; j < ARRAY_SIZE(templates_delim); j++) {
2669c2c66affSColin Finck       char * at_pos;
2670c2c66affSColin Finck       int at_offset;
2671c2c66affSColin Finck       int end_offset;
2672c2c66affSColin Finck 
2673c2c66affSColin Finck       at_pos = strchr(templates_delim[j], 'X');
2674c2c66affSColin Finck       at_offset = at_pos - templates_delim[j];
2675c2c66affSColin Finck       end_offset = at_offset + strlen(urls[i].text);
2676c2c66affSColin Finck 
2677c2c66affSColin Finck       strcpy(buffer, "YY");
2678c2c66affSColin Finck       buffer[0] = urls[i].text[0];
2679c2c66affSColin Finck 
2680c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
2681c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)templates_delim[j]);
2682c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset, at_offset+1);
2683c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)buffer);
2684c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SETSEL, at_offset+1, at_offset+2);
2685c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)(urls[i].text + 1));
2686c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
2687c2c66affSColin Finck 
2688c2c66affSColin Finck       /* This assumes no templates start with the URL itself, and that they
2689c2c66affSColin Finck          have at least two characters before the URL text */
2690c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
2691c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
2692c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
2693c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
2694c2c66affSColin Finck       ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
2695c2c66affSColin Finck         "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
2696c2c66affSColin Finck 
2697c2c66affSColin Finck       if (urls[i].is_url)
2698c2c66affSColin Finck       {
2699c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2700c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
2701c2c66affSColin Finck         ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2702c2c66affSColin Finck           "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2703c2c66affSColin Finck       }
2704c2c66affSColin Finck       else
2705c2c66affSColin Finck       {
2706c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
2707c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset, at_offset + 1, buffer);
2708c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
2709c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
2710c2c66affSColin Finck       }
2711c2c66affSColin Finck       if (buffer[end_offset] != '\0')
2712c2c66affSColin Finck       {
2713c2c66affSColin Finck         ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
2714c2c66affSColin Finck           "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset, end_offset + 1, buffer);
2715c2c66affSColin Finck         if (buffer[end_offset +1] != '\0')
2716c2c66affSColin Finck         {
2717c2c66affSColin Finck           ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset +1, end_offset +2),
2718c2c66affSColin Finck             "CFE_LINK incorrectly set in (%d-%d), text: %s\n", end_offset +1, end_offset +2, buffer);
2719c2c66affSColin Finck         }
2720c2c66affSColin Finck       }
2721c2c66affSColin Finck     }
2722c2c66affSColin Finck 
2723c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
2724c2c66affSColin Finck     hwndRichEdit = NULL;
2725c2c66affSColin Finck   }
2726c2c66affSColin Finck 
2727c2c66affSColin Finck   DestroyWindow(parent);
2728c2c66affSColin Finck }
2729c2c66affSColin Finck 
test_EM_SCROLL(void)2730c2c66affSColin Finck static void test_EM_SCROLL(void)
2731c2c66affSColin Finck {
2732c2c66affSColin Finck   int i, j;
2733c2c66affSColin Finck   int r; /* return value */
2734c2c66affSColin Finck   int expr; /* expected return value */
2735c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
2736c2c66affSColin Finck   int y_before, y_after; /* units of lines of text */
2737c2c66affSColin Finck 
2738c2c66affSColin Finck   /* test a richedit box containing a single line of text */
2739c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");/* one line of text */
2740c2c66affSColin Finck   expr = 0x00010000;
2741c2c66affSColin Finck   for (i = 0; i < 4; i++) {
2742c2c66affSColin Finck     static const int cmd[4] = { SB_PAGEDOWN, SB_PAGEUP, SB_LINEDOWN, SB_LINEUP };
2743c2c66affSColin Finck 
2744c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL, cmd[i], 0);
2745c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2746c2c66affSColin Finck     ok(expr == r, "EM_SCROLL improper return value returned (i == %d). "
2747c2c66affSColin Finck        "Got 0x%08x, expected 0x%08x\n", i, r, expr);
2748c2c66affSColin Finck     ok(y_after == 0, "EM_SCROLL improper scroll. scrolled to line %d, not 1 "
2749c2c66affSColin Finck        "(i == %d)\n", y_after, i);
2750c2c66affSColin Finck   }
2751c2c66affSColin Finck 
2752c2c66affSColin Finck   /*
2753c2c66affSColin Finck    * test a richedit box that will scroll. There are two general
2754c2c66affSColin Finck    * cases: the case without any long lines and the case with a long
2755c2c66affSColin Finck    * line.
2756c2c66affSColin Finck    */
2757c2c66affSColin Finck   for (i = 0; i < 2; i++) { /* iterate through different bodies of text */
2758c2c66affSColin Finck     if (i == 0)
2759c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a\nb\nc\nd\ne");
2760c2c66affSColin Finck     else
2761c2c66affSColin Finck       SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)
2762c2c66affSColin Finck                   "a LONG LINE LONG LINE LONG LINE LONG LINE LONG LINE "
2763c2c66affSColin Finck                   "LONG LINE LONG LINE LONG LINE LONG LINE LONG LINE "
2764c2c66affSColin Finck                   "LONG LINE \nb\nc\nd\ne");
2765c2c66affSColin Finck     for (j = 0; j < 12; j++) /* reset scroll position to top */
2766c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SCROLL, SB_PAGEUP, 0);
2767c2c66affSColin Finck 
2768c2c66affSColin Finck     /* get first visible line */
2769c2c66affSColin Finck     y_before = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2770c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL, SB_PAGEDOWN, 0); /* page down */
2771c2c66affSColin Finck 
2772c2c66affSColin Finck     /* get new current first visible line */
2773c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2774c2c66affSColin Finck 
2775c2c66affSColin Finck     ok(((r & 0xffffff00) == 0x00010000) &&
2776c2c66affSColin Finck        ((r & 0x000000ff) != 0x00000000),
2777c2c66affSColin Finck        "EM_SCROLL page down didn't scroll by a small positive number of "
2778c2c66affSColin Finck        "lines (r == 0x%08x)\n", r);
2779c2c66affSColin Finck     ok(y_after > y_before, "EM_SCROLL page down not functioning "
2780c2c66affSColin Finck        "(line %d scrolled to line %d\n", y_before, y_after);
2781c2c66affSColin Finck 
2782c2c66affSColin Finck     y_before = y_after;
2783c2c66affSColin Finck 
2784c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL, SB_PAGEUP, 0); /* page up */
2785c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2786c2c66affSColin Finck     ok(((r & 0xffffff00) == 0x0001ff00),
2787c2c66affSColin Finck        "EM_SCROLL page up didn't scroll by a small negative number of lines "
2788c2c66affSColin Finck        "(r == 0x%08x)\n", r);
2789c2c66affSColin Finck     ok(y_after < y_before, "EM_SCROLL page up not functioning (line "
2790c2c66affSColin Finck        "%d scrolled to line %d\n", y_before, y_after);
2791c2c66affSColin Finck 
2792c2c66affSColin Finck     y_before = y_after;
2793c2c66affSColin Finck 
2794c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */
2795c2c66affSColin Finck 
2796c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2797c2c66affSColin Finck 
2798c2c66affSColin Finck     ok(r == 0x00010001, "EM_SCROLL line down didn't scroll by one line "
2799c2c66affSColin Finck        "(r == 0x%08x)\n", r);
2800c2c66affSColin Finck     ok(y_after -1 == y_before, "EM_SCROLL line down didn't go down by "
2801c2c66affSColin Finck        "1 line (%d scrolled to %d)\n", y_before, y_after);
2802c2c66affSColin Finck 
2803c2c66affSColin Finck     y_before = y_after;
2804c2c66affSColin Finck 
2805c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */
2806c2c66affSColin Finck 
2807c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2808c2c66affSColin Finck 
2809c2c66affSColin Finck     ok(r == 0x0001ffff, "EM_SCROLL line up didn't scroll by one line "
2810c2c66affSColin Finck        "(r == 0x%08x)\n", r);
2811c2c66affSColin Finck     ok(y_after +1 == y_before, "EM_SCROLL line up didn't go up by 1 "
2812c2c66affSColin Finck        "line (%d scrolled to %d)\n", y_before, y_after);
2813c2c66affSColin Finck 
2814c2c66affSColin Finck     y_before = y_after;
2815c2c66affSColin Finck 
2816c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL,
2817c2c66affSColin Finck                     SB_LINEUP, 0); /* lineup beyond top */
2818c2c66affSColin Finck 
2819c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2820c2c66affSColin Finck 
2821c2c66affSColin Finck     ok(r == 0x00010000,
2822c2c66affSColin Finck        "EM_SCROLL line up returned indicating movement (0x%08x)\n", r);
2823c2c66affSColin Finck     ok(y_before == y_after,
2824c2c66affSColin Finck        "EM_SCROLL line up beyond top worked (%d)\n", y_after);
2825c2c66affSColin Finck 
2826c2c66affSColin Finck     y_before = y_after;
2827c2c66affSColin Finck 
2828c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL,
2829c2c66affSColin Finck                     SB_PAGEUP, 0);/*page up beyond top */
2830c2c66affSColin Finck 
2831c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2832c2c66affSColin Finck 
2833c2c66affSColin Finck     ok(r == 0x00010000,
2834c2c66affSColin Finck        "EM_SCROLL page up returned indicating movement (0x%08x)\n", r);
2835c2c66affSColin Finck     ok(y_before == y_after,
2836c2c66affSColin Finck        "EM_SCROLL page up beyond top worked (%d)\n", y_after);
2837c2c66affSColin Finck 
2838c2c66affSColin Finck     for (j = 0; j < 12; j++) /* page down all the way to the bottom */
2839c2c66affSColin Finck       SendMessageA(hwndRichEdit, EM_SCROLL, SB_PAGEDOWN, 0);
2840c2c66affSColin Finck     y_before = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2841c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL,
2842c2c66affSColin Finck                     SB_PAGEDOWN, 0); /* page down beyond bot */
2843c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2844c2c66affSColin Finck 
2845c2c66affSColin Finck     ok(r == 0x00010000,
2846c2c66affSColin Finck        "EM_SCROLL page down returned indicating movement (0x%08x)\n", r);
2847c2c66affSColin Finck     ok(y_before == y_after,
2848c2c66affSColin Finck        "EM_SCROLL page down beyond bottom worked (%d -> %d)\n",
2849c2c66affSColin Finck        y_before, y_after);
2850c2c66affSColin Finck 
2851c2c66affSColin Finck     y_before = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2852c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down beyond bot */
2853c2c66affSColin Finck     y_after = SendMessageA(hwndRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
2854c2c66affSColin Finck 
2855c2c66affSColin Finck     ok(r == 0x00010000,
2856c2c66affSColin Finck        "EM_SCROLL line down returned indicating movement (0x%08x)\n", r);
2857c2c66affSColin Finck     ok(y_before == y_after,
2858c2c66affSColin Finck        "EM_SCROLL line down beyond bottom worked (%d -> %d)\n",
2859c2c66affSColin Finck        y_before, y_after);
2860c2c66affSColin Finck   }
2861c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
2862c2c66affSColin Finck }
2863c2c66affSColin Finck 
2864c2c66affSColin Finck static unsigned int recursionLevel = 0;
2865c2c66affSColin Finck static unsigned int WM_SIZE_recursionLevel = 0;
2866c2c66affSColin Finck static BOOL bailedOutOfRecursion = FALSE;
2867c2c66affSColin Finck static LRESULT (WINAPI *richeditProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
2868c2c66affSColin Finck 
RicheditStupidOverrideProcA(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)2869c2c66affSColin Finck static LRESULT WINAPI RicheditStupidOverrideProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2870c2c66affSColin Finck {
2871c2c66affSColin Finck     LRESULT r;
2872c2c66affSColin Finck 
2873c2c66affSColin Finck     if (bailedOutOfRecursion) return 0;
2874c2c66affSColin Finck     if (recursionLevel >= 32) {
2875c2c66affSColin Finck         bailedOutOfRecursion = TRUE;
2876c2c66affSColin Finck         return 0;
2877c2c66affSColin Finck     }
2878c2c66affSColin Finck 
2879c2c66affSColin Finck     recursionLevel++;
2880c2c66affSColin Finck     switch (message) {
2881c2c66affSColin Finck     case WM_SIZE:
2882c2c66affSColin Finck         WM_SIZE_recursionLevel++;
2883c2c66affSColin Finck         r = richeditProc(hwnd, message, wParam, lParam);
2884c2c66affSColin Finck         /* Because, uhhhh... I never heard of ES_DISABLENOSCROLL */
2885c2c66affSColin Finck         ShowScrollBar(hwnd, SB_VERT, TRUE);
2886c2c66affSColin Finck         WM_SIZE_recursionLevel--;
2887c2c66affSColin Finck         break;
2888c2c66affSColin Finck     default:
2889c2c66affSColin Finck         r = richeditProc(hwnd, message, wParam, lParam);
2890c2c66affSColin Finck         break;
2891c2c66affSColin Finck     }
2892c2c66affSColin Finck     recursionLevel--;
2893c2c66affSColin Finck     return r;
2894c2c66affSColin Finck }
2895c2c66affSColin Finck 
test_scrollbar_visibility(void)2896c2c66affSColin Finck static void test_scrollbar_visibility(void)
2897c2c66affSColin Finck {
2898c2c66affSColin Finck   HWND hwndRichEdit;
2899c2c66affSColin Finck   const char * text="a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n";
2900c2c66affSColin Finck   SCROLLINFO si;
2901c2c66affSColin Finck   WNDCLASSA cls;
2902c2c66affSColin Finck   BOOL r;
2903c2c66affSColin Finck 
2904c2c66affSColin Finck   /* These tests show that richedit should temporarily refrain from automatically
2905c2c66affSColin Finck      hiding or showing its scrollbars (vertical at least) when an explicit request
2906c2c66affSColin Finck      is made via ShowScrollBar() or similar, outside of standard richedit logic.
2907c2c66affSColin Finck      Some applications depend on forced showing (when otherwise richedit would
2908c2c66affSColin Finck      hide the vertical scrollbar) and are thrown on an endless recursive loop
2909c2c66affSColin Finck      if richedit auto-hides the scrollbar again. Apparently they never heard of
2910c2c66affSColin Finck      the ES_DISABLENOSCROLL style... */
2911c2c66affSColin Finck 
2912c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
2913c2c66affSColin Finck 
2914c2c66affSColin Finck   /* Test default scrollbar visibility behavior */
2915c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2916c2c66affSColin Finck   si.cbSize = sizeof(si);
2917c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2918c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2919c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
2920c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
2921c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
2922c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
2923c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2924c2c66affSColin Finck 
2925c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
2926c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2927c2c66affSColin Finck   si.cbSize = sizeof(si);
2928c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2929c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2930c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
2931c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
2932c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
2933c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
2934c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2935c2c66affSColin Finck 
2936c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
2937c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2938c2c66affSColin Finck   si.cbSize = sizeof(si);
2939c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2940c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2941c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
2942c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
2943c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
2944c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
2945c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2946c2c66affSColin Finck 
2947c2c66affSColin Finck   /* Oddly, setting text to NULL does *not* reset the scrollbar range,
2948c2c66affSColin Finck      even though it hides the scrollbar */
2949c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
2950c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2951c2c66affSColin Finck   si.cbSize = sizeof(si);
2952c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2953c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2954c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
2955c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
2956c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
2957c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
2958c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2959c2c66affSColin Finck 
2960c2c66affSColin Finck   /* Setting non-scrolling text again does *not* reset scrollbar range */
2961c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
2962c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2963c2c66affSColin Finck   si.cbSize = sizeof(si);
2964c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2965c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2966c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
2967c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
2968c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
2969c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
2970c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2971c2c66affSColin Finck 
2972c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
2973c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2974c2c66affSColin Finck   si.cbSize = sizeof(si);
2975c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2976c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2977c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
2978c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
2979c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
2980c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
2981c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2982c2c66affSColin Finck 
2983c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
2984c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2985c2c66affSColin Finck   si.cbSize = sizeof(si);
2986c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2987c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2988c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
2989c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
2990c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
2991c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
2992c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
2993c2c66affSColin Finck 
2994c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
2995c2c66affSColin Finck   memset(&si, 0, sizeof(si));
2996c2c66affSColin Finck   si.cbSize = sizeof(si);
2997c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
2998c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
2999c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3000c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3001c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3002c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3003c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3004c2c66affSColin Finck 
3005c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3006c2c66affSColin Finck 
3007c2c66affSColin Finck   /* Test again, with ES_DISABLENOSCROLL style */
3008c2c66affSColin Finck   hwndRichEdit = new_window(RICHEDIT_CLASS20A, ES_MULTILINE|ES_DISABLENOSCROLL, NULL);
3009c2c66affSColin Finck 
3010c2c66affSColin Finck   /* Test default scrollbar visibility behavior */
3011c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3012c2c66affSColin Finck   si.cbSize = sizeof(si);
3013c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3014c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3015c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3016c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3017c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 1,
3018c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..1)\n",
3019c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3020c2c66affSColin Finck 
3021c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3022c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3023c2c66affSColin Finck   si.cbSize = sizeof(si);
3024c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3025c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3026c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3027c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3028c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 1,
3029c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..1)\n",
3030c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3031c2c66affSColin Finck 
3032c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3033c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3034c2c66affSColin Finck   si.cbSize = sizeof(si);
3035c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3036c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3037c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3038c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3039c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax > 1,
3040c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3041c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3042c2c66affSColin Finck 
3043c2c66affSColin Finck   /* Oddly, setting text to NULL does *not* reset the scrollbar range */
3044c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3045c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3046c2c66affSColin Finck   si.cbSize = sizeof(si);
3047c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3048c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3049c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3050c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3051c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax > 1,
3052c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3053c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3054c2c66affSColin Finck 
3055c2c66affSColin Finck   /* Setting non-scrolling text again does *not* reset scrollbar range */
3056c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
3057c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3058c2c66affSColin Finck   si.cbSize = sizeof(si);
3059c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3060c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3061c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3062c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3063c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax > 1,
3064c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3065c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3066c2c66affSColin Finck 
3067c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3068c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3069c2c66affSColin Finck   si.cbSize = sizeof(si);
3070c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3071c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3072c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3073c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3074c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax > 1,
3075c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3076c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3077c2c66affSColin Finck 
3078c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
3079c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3080c2c66affSColin Finck   si.cbSize = sizeof(si);
3081c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3082c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3083c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3084c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3085c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax > 1,
3086c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3087c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3088c2c66affSColin Finck 
3089c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
3090c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3091c2c66affSColin Finck   si.cbSize = sizeof(si);
3092c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3093c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3094c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3095c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3096c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax > 1,
3097c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3098c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3099c2c66affSColin Finck 
3100c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3101c2c66affSColin Finck 
3102c2c66affSColin Finck   /* Test behavior with explicit visibility request, using ShowScrollBar() */
3103c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
3104c2c66affSColin Finck 
3105c2c66affSColin Finck   /* Previously failed because builtin incorrectly re-hides scrollbar forced visible */
3106c2c66affSColin Finck   ShowScrollBar(hwndRichEdit, SB_VERT, TRUE);
3107c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3108c2c66affSColin Finck   si.cbSize = sizeof(si);
3109c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3110c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3111c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3112c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3113c2c66affSColin Finck   todo_wine {
3114c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100,
3115c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..100)\n",
3116c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3117c2c66affSColin Finck   }
3118c2c66affSColin Finck 
3119c2c66affSColin Finck   /* Ditto, see above */
3120c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3121c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3122c2c66affSColin Finck   si.cbSize = sizeof(si);
3123c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3124c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3125c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3126c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3127c2c66affSColin Finck   todo_wine {
3128c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100,
3129c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..100)\n",
3130c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3131c2c66affSColin Finck   }
3132c2c66affSColin Finck 
3133c2c66affSColin Finck   /* Ditto, see above */
3134c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
3135c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3136c2c66affSColin Finck   si.cbSize = sizeof(si);
3137c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3138c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3139c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3140c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3141c2c66affSColin Finck   todo_wine {
3142c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100,
3143c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..100)\n",
3144c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3145c2c66affSColin Finck   }
3146c2c66affSColin Finck 
3147c2c66affSColin Finck   /* Ditto, see above */
3148c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a\na");
3149c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3150c2c66affSColin Finck   si.cbSize = sizeof(si);
3151c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3152c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3153c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3154c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3155c2c66affSColin Finck   todo_wine {
3156c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100,
3157c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..100)\n",
3158c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3159c2c66affSColin Finck   }
3160c2c66affSColin Finck 
3161c2c66affSColin Finck   /* Ditto, see above */
3162c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3163c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3164c2c66affSColin Finck   si.cbSize = sizeof(si);
3165c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3166c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3167c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3168c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3169c2c66affSColin Finck   todo_wine {
3170c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100,
3171c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected 0 (0..100)\n",
3172c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3173c2c66affSColin Finck   }
3174c2c66affSColin Finck 
3175c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3176c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3177c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3178c2c66affSColin Finck   si.cbSize = sizeof(si);
3179c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3180c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3181c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3182c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3183c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3184c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3185c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3186c2c66affSColin Finck 
3187c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3188c2c66affSColin Finck 
3189c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
3190c2c66affSColin Finck 
3191c2c66affSColin Finck   ShowScrollBar(hwndRichEdit, SB_VERT, FALSE);
3192c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3193c2c66affSColin Finck   si.cbSize = sizeof(si);
3194c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3195c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3196c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3197c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3198c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3199c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3200c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3201c2c66affSColin Finck 
3202c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3203c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3204c2c66affSColin Finck   si.cbSize = sizeof(si);
3205c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3206c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3207c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3208c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3209c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3210c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3211c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3212c2c66affSColin Finck 
3213c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
3214c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3215c2c66affSColin Finck   si.cbSize = sizeof(si);
3216c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3217c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3218c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3219c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3220c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3221c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3222c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3223c2c66affSColin Finck 
3224c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3225c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3226c2c66affSColin Finck   si.cbSize = sizeof(si);
3227c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3228c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3229c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3230c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3231c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3232c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3233c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3234c2c66affSColin Finck 
3235c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3236c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3237c2c66affSColin Finck   si.cbSize = sizeof(si);
3238c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3239c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3240c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3241c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3242c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3243c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3244c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3245c2c66affSColin Finck 
3246c2c66affSColin Finck   /* Previously, builtin incorrectly re-shows explicitly hidden scrollbar */
3247c2c66affSColin Finck   ShowScrollBar(hwndRichEdit, SB_VERT, FALSE);
3248c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3249c2c66affSColin Finck   si.cbSize = sizeof(si);
3250c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3251c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3252c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3253c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3254c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3255c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3256c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3257c2c66affSColin Finck 
3258c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3259c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3260c2c66affSColin Finck   si.cbSize = sizeof(si);
3261c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3262c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3263c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3264c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3265c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3266c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3267c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3268c2c66affSColin Finck 
3269c2c66affSColin Finck   /* Testing effect of EM_SCROLL on scrollbar visibility. It seems that
3270c2c66affSColin Finck      EM_SCROLL will make visible any forcefully invisible scrollbar */
3271c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0);
3272c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3273c2c66affSColin Finck   si.cbSize = sizeof(si);
3274c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3275c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3276c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3277c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3278c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3279c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3280c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3281c2c66affSColin Finck 
3282c2c66affSColin Finck   ShowScrollBar(hwndRichEdit, SB_VERT, FALSE);
3283c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3284c2c66affSColin Finck   si.cbSize = sizeof(si);
3285c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3286c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3287c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3288c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3289c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3290c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3291c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3292c2c66affSColin Finck 
3293c2c66affSColin Finck   /* Again, EM_SCROLL, with SB_LINEUP */
3294c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0);
3295c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3296c2c66affSColin Finck   si.cbSize = sizeof(si);
3297c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3298c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3299c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3300c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3301c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3302c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3303c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3304c2c66affSColin Finck 
3305c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3306c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3307c2c66affSColin Finck   si.cbSize = sizeof(si);
3308c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3309c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3310c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3311c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3312c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3313c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3314c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3315c2c66affSColin Finck 
3316c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3317c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3318c2c66affSColin Finck   si.cbSize = sizeof(si);
3319c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3320c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3321c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3322c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3323c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3324c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3325c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3326c2c66affSColin Finck 
3327c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3328c2c66affSColin Finck 
3329c2c66affSColin Finck 
3330c2c66affSColin Finck   /* Test behavior with explicit visibility request, using SetWindowLongA()() */
3331c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
3332c2c66affSColin Finck 
3333c2c66affSColin Finck #define ENABLE_WS_VSCROLL(hwnd) \
3334c2c66affSColin Finck     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | WS_VSCROLL)
3335c2c66affSColin Finck #define DISABLE_WS_VSCROLL(hwnd) \
3336c2c66affSColin Finck     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~WS_VSCROLL)
3337c2c66affSColin Finck 
3338c2c66affSColin Finck   /* Previously failed because builtin incorrectly re-hides scrollbar forced visible */
3339c2c66affSColin Finck   ENABLE_WS_VSCROLL(hwndRichEdit);
3340c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3341c2c66affSColin Finck   si.cbSize = sizeof(si);
3342c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3343c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3344c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3345c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3346c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3347c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3348c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3349c2c66affSColin Finck 
3350c2c66affSColin Finck   /* Ditto, see above */
3351c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3352c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3353c2c66affSColin Finck   si.cbSize = sizeof(si);
3354c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3355c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3356c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3357c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3358c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3359c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3360c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3361c2c66affSColin Finck 
3362c2c66affSColin Finck   /* Ditto, see above */
3363c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
3364c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3365c2c66affSColin Finck   si.cbSize = sizeof(si);
3366c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3367c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3368c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3369c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3370c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3371c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3372c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3373c2c66affSColin Finck 
3374c2c66affSColin Finck   /* Ditto, see above */
3375c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a\na");
3376c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3377c2c66affSColin Finck   si.cbSize = sizeof(si);
3378c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3379c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3380c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3381c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3382c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3383c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3384c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3385c2c66affSColin Finck 
3386c2c66affSColin Finck   /* Ditto, see above */
3387c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3388c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3389c2c66affSColin Finck   si.cbSize = sizeof(si);
3390c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3391c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3392c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3393c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3394c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3395c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3396c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3397c2c66affSColin Finck 
3398c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3399c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3400c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3401c2c66affSColin Finck   si.cbSize = sizeof(si);
3402c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3403c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3404c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3405c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3406c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3407c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3408c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3409c2c66affSColin Finck 
3410c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3411c2c66affSColin Finck 
3412c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
3413c2c66affSColin Finck 
3414c2c66affSColin Finck   DISABLE_WS_VSCROLL(hwndRichEdit);
3415c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3416c2c66affSColin Finck   si.cbSize = sizeof(si);
3417c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3418c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3419c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3420c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3421c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3422c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3423c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3424c2c66affSColin Finck 
3425c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3426c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3427c2c66affSColin Finck   si.cbSize = sizeof(si);
3428c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3429c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3430c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3431c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3432c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3433c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3434c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3435c2c66affSColin Finck 
3436c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
3437c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3438c2c66affSColin Finck   si.cbSize = sizeof(si);
3439c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3440c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3441c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3442c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3443c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3444c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3445c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3446c2c66affSColin Finck 
3447c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3448c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3449c2c66affSColin Finck   si.cbSize = sizeof(si);
3450c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3451c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3452c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3453c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3454c2c66affSColin Finck   ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
3455c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
3456c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3457c2c66affSColin Finck 
3458c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3459c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3460c2c66affSColin Finck   si.cbSize = sizeof(si);
3461c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3462c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3463c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3464c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3465c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3466c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3467c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3468c2c66affSColin Finck 
3469c2c66affSColin Finck   /* Previously, builtin incorrectly re-shows explicitly hidden scrollbar */
3470c2c66affSColin Finck   DISABLE_WS_VSCROLL(hwndRichEdit);
3471c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3472c2c66affSColin Finck   si.cbSize = sizeof(si);
3473c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3474c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3475c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3476c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3477c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3478c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3479c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3480c2c66affSColin Finck 
3481c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
3482c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3483c2c66affSColin Finck   si.cbSize = sizeof(si);
3484c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3485c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3486c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3487c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3488c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3489c2c66affSColin Finck         "reported page/range is %d (%d..%d) expected nMax/nPage nonzero\n",
3490c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3491c2c66affSColin Finck 
3492c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
3493c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3494c2c66affSColin Finck   si.cbSize = sizeof(si);
3495c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3496c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3497c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3498c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3499c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3500c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3501c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3502c2c66affSColin Finck 
3503c2c66affSColin Finck   DISABLE_WS_VSCROLL(hwndRichEdit);
3504c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3505c2c66affSColin Finck   si.cbSize = sizeof(si);
3506c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3507c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3508c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3509c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3510c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3511c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3512c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3513c2c66affSColin Finck 
3514c2c66affSColin Finck   /* Testing effect of EM_SCROLL on scrollbar visibility. It seems that
3515c2c66affSColin Finck      EM_SCROLL will make visible any forcefully invisible scrollbar */
3516c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0);
3517c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3518c2c66affSColin Finck   si.cbSize = sizeof(si);
3519c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3520c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3521c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3522c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3523c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3524c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3525c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3526c2c66affSColin Finck 
3527c2c66affSColin Finck   DISABLE_WS_VSCROLL(hwndRichEdit);
3528c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3529c2c66affSColin Finck   si.cbSize = sizeof(si);
3530c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3531c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3532c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
3533c2c66affSColin Finck     "Vertical scrollbar is visible, should be invisible.\n");
3534c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3535c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3536c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3537c2c66affSColin Finck 
3538c2c66affSColin Finck   /* Again, EM_SCROLL, with SB_LINEUP */
3539c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0);
3540c2c66affSColin Finck   memset(&si, 0, sizeof(si));
3541c2c66affSColin Finck   si.cbSize = sizeof(si);
3542c2c66affSColin Finck   si.fMask = SIF_PAGE | SIF_RANGE;
3543c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
3544c2c66affSColin Finck   ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
3545c2c66affSColin Finck     "Vertical scrollbar is invisible, should be visible.\n");
3546c2c66affSColin Finck   ok(si.nPage != 0 && si.nMin == 0 && si.nMax != 0,
3547c2c66affSColin Finck         "reported page/range is %d (%d..%d)\n",
3548c2c66affSColin Finck         si.nPage, si.nMin, si.nMax);
3549c2c66affSColin Finck 
3550c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3551c2c66affSColin Finck 
3552c2c66affSColin Finck   /* This window proc models what is going on with Corman Lisp 3.0.
3553c2c66affSColin Finck      At WM_SIZE, this proc unconditionally calls ShowScrollBar() to
3554c2c66affSColin Finck      force the scrollbar into visibility. Recursion should NOT happen
3555c2c66affSColin Finck      as a result of this action.
3556c2c66affSColin Finck    */
3557c2c66affSColin Finck   r = GetClassInfoA(NULL, RICHEDIT_CLASS20A, &cls);
3558c2c66affSColin Finck   if (r) {
3559c2c66affSColin Finck     richeditProc = cls.lpfnWndProc;
3560c2c66affSColin Finck     cls.lpfnWndProc = RicheditStupidOverrideProcA;
3561c2c66affSColin Finck     cls.lpszClassName = "RicheditStupidOverride";
3562c2c66affSColin Finck     if(!RegisterClassA(&cls)) assert(0);
3563c2c66affSColin Finck 
3564c2c66affSColin Finck     recursionLevel = 0;
3565c2c66affSColin Finck     WM_SIZE_recursionLevel = 0;
3566c2c66affSColin Finck     bailedOutOfRecursion = FALSE;
3567c2c66affSColin Finck     hwndRichEdit = new_window(cls.lpszClassName, ES_MULTILINE, NULL);
3568c2c66affSColin Finck     ok(!bailedOutOfRecursion,
3569c2c66affSColin Finck         "WM_SIZE/scrollbar mutual recursion detected, expected none!\n");
3570c2c66affSColin Finck 
3571c2c66affSColin Finck     recursionLevel = 0;
3572c2c66affSColin Finck     WM_SIZE_recursionLevel = 0;
3573c2c66affSColin Finck     bailedOutOfRecursion = FALSE;
3574c2c66affSColin Finck     MoveWindow(hwndRichEdit, 0, 0, 250, 100, TRUE);
3575c2c66affSColin Finck     ok(!bailedOutOfRecursion,
3576c2c66affSColin Finck         "WM_SIZE/scrollbar mutual recursion detected, expected none!\n");
3577c2c66affSColin Finck 
3578c2c66affSColin Finck     /* Unblock window in order to process WM_DESTROY */
3579c2c66affSColin Finck     recursionLevel = 0;
3580c2c66affSColin Finck     bailedOutOfRecursion = FALSE;
3581c2c66affSColin Finck     WM_SIZE_recursionLevel = 0;
3582c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
3583c2c66affSColin Finck   }
3584c2c66affSColin Finck }
3585c2c66affSColin Finck 
test_EM_SETUNDOLIMIT(void)3586c2c66affSColin Finck static void test_EM_SETUNDOLIMIT(void)
3587c2c66affSColin Finck {
3588c2c66affSColin Finck   /* cases we test for:
3589c2c66affSColin Finck    * default behaviour - limiting at 100 undo's
3590c2c66affSColin Finck    * undo disabled - setting a limit of 0
3591c2c66affSColin Finck    * undo limited -  undo limit set to some to some number, like 2
3592c2c66affSColin Finck    * bad input - sending a negative number should default to 100 undo's */
3593c2c66affSColin Finck 
3594c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
3595c2c66affSColin Finck   CHARRANGE cr;
3596c2c66affSColin Finck   int i;
3597c2c66affSColin Finck   int result;
3598c2c66affSColin Finck 
3599c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"x");
3600c2c66affSColin Finck   cr.cpMin = 0;
3601c2c66affSColin Finck   cr.cpMax = -1;
3602c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
3603c2c66affSColin Finck 
3604c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
3605c2c66affSColin Finck     /*Load "x" into the clipboard. Paste is an easy, undo'able operation.
3606c2c66affSColin Finck       also, multiple pastes don't combine like WM_CHAR would */
3607c2c66affSColin Finck 
3608c2c66affSColin Finck   /* first case - check the default */
3609c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
3610c2c66affSColin Finck   for (i=0; i<101; i++) /* Put 101 undo's on the stack */
3611c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
3612c2c66affSColin Finck   for (i=0; i<100; i++) /* Undo 100 of them */
3613c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_UNDO, 0, 0);
3614c2c66affSColin Finck   ok(!SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0),
3615c2c66affSColin Finck      "EM_SETUNDOLIMIT allowed more than a hundred undo's by default.\n");
3616c2c66affSColin Finck 
3617c2c66affSColin Finck   /* second case - cannot undo */
3618c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0, 0);
3619c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETUNDOLIMIT, 0, 0);
3620c2c66affSColin Finck   SendMessageA(hwndRichEdit,
3621c2c66affSColin Finck               WM_PASTE, 0, 0); /* Try to put something in the undo stack */
3622c2c66affSColin Finck   ok(!SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0),
3623c2c66affSColin Finck      "EM_SETUNDOLIMIT allowed undo with UNDOLIMIT set to 0\n");
3624c2c66affSColin Finck 
3625c2c66affSColin Finck   /* third case - set it to an arbitrary number */
3626c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0, 0);
3627c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETUNDOLIMIT, 2, 0);
3628c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
3629c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
3630c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
3631c2c66affSColin Finck   /* If SETUNDOLIMIT is working, there should only be two undo's after this */
3632c2c66affSColin Finck   ok(SendMessageA(hwndRichEdit, EM_CANUNDO, 0,0),
3633c2c66affSColin Finck      "EM_SETUNDOLIMIT didn't allow the first undo with UNDOLIMIT set to 2\n");
3634c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_UNDO, 0, 0);
3635c2c66affSColin Finck   ok(SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0),
3636c2c66affSColin Finck      "EM_SETUNDOLIMIT didn't allow a second undo with UNDOLIMIT set to 2\n");
3637c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_UNDO, 0, 0);
3638c2c66affSColin Finck   ok(!SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0),
3639c2c66affSColin Finck      "EM_SETUNDOLIMIT allowed a third undo with UNDOLIMIT set to 2\n");
3640c2c66affSColin Finck 
3641c2c66affSColin Finck   /* fourth case - setting negative numbers should default to 100 undos */
3642c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
3643c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETUNDOLIMIT, -1, 0);
3644c2c66affSColin Finck   ok (result == 100,
3645c2c66affSColin Finck       "EM_SETUNDOLIMIT returned %d when set to -1, instead of 100\n",result);
3646c2c66affSColin Finck 
3647c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3648c2c66affSColin Finck }
3649c2c66affSColin Finck 
test_ES_PASSWORD(void)3650c2c66affSColin Finck static void test_ES_PASSWORD(void)
3651c2c66affSColin Finck {
3652c2c66affSColin Finck   /* This isn't hugely testable, so we're just going to run it through its paces */
3653c2c66affSColin Finck 
3654c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
3655c2c66affSColin Finck   WCHAR result;
3656c2c66affSColin Finck 
3657c2c66affSColin Finck   /* First, check the default of a regular control */
3658c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
3659c2c66affSColin Finck   ok (result == 0,
3660c2c66affSColin Finck 	"EM_GETPASSWORDCHAR returned %c by default, instead of NULL\n",result);
3661c2c66affSColin Finck 
3662c2c66affSColin Finck   /* Now, set it to something normal */
3663c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETPASSWORDCHAR, 'x', 0);
3664c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
3665c2c66affSColin Finck   ok (result == 120,
3666c2c66affSColin Finck 	"EM_GETPASSWORDCHAR returned %c (%d) when set to 'x', instead of x (120)\n",result,result);
3667c2c66affSColin Finck 
3668c2c66affSColin Finck   /* Now, set it to something odd */
3669c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETPASSWORDCHAR, (WCHAR)1234, 0);
3670c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETPASSWORDCHAR, 0, 0);
3671c2c66affSColin Finck   ok (result == 1234,
3672c2c66affSColin Finck 	"EM_GETPASSWORDCHAR returned %c (%d) when set to 'x', instead of x (120)\n",result,result);
3673c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3674c2c66affSColin Finck }
3675c2c66affSColin Finck 
3676c2c66affSColin Finck LONG streamout_written = 0;
3677c2c66affSColin Finck 
test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)3678c2c66affSColin Finck static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
3679c2c66affSColin Finck                                          LPBYTE pbBuff,
3680c2c66affSColin Finck                                          LONG cb,
3681c2c66affSColin Finck                                          LONG *pcb)
3682c2c66affSColin Finck {
3683c2c66affSColin Finck   char** str = (char**)dwCookie;
3684c2c66affSColin Finck   *pcb = cb;
3685c2c66affSColin Finck   if (*pcb > 0) {
3686c2c66affSColin Finck     memcpy(*str, pbBuff, *pcb);
3687c2c66affSColin Finck     *str += *pcb;
3688c2c66affSColin Finck   }
3689c2c66affSColin Finck   streamout_written = *pcb;
3690c2c66affSColin Finck   return 0;
3691c2c66affSColin Finck }
3692c2c66affSColin Finck 
test_WM_SETTEXT(void)3693c2c66affSColin Finck static void test_WM_SETTEXT(void)
3694c2c66affSColin Finck {
3695c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
3696c2c66affSColin Finck   const char * TestItem1 = "TestSomeText";
3697c2c66affSColin Finck   const char * TestItem2 = "TestSomeText\r";
3698c2c66affSColin Finck   const char * TestItem2_after = "TestSomeText\r\n";
3699c2c66affSColin Finck   const char * TestItem3 = "TestSomeText\rSomeMoreText\r";
3700c2c66affSColin Finck   const char * TestItem3_after = "TestSomeText\r\nSomeMoreText\r\n";
3701c2c66affSColin Finck   const char * TestItem4 = "TestSomeText\n\nTestSomeText";
3702c2c66affSColin Finck   const char * TestItem4_after = "TestSomeText\r\n\r\nTestSomeText";
3703c2c66affSColin Finck   const char * TestItem5 = "TestSomeText\r\r\nTestSomeText";
3704c2c66affSColin Finck   const char * TestItem5_after = "TestSomeText TestSomeText";
3705c2c66affSColin Finck   const char * TestItem6 = "TestSomeText\r\r\n\rTestSomeText";
3706c2c66affSColin Finck   const char * TestItem6_after = "TestSomeText \r\nTestSomeText";
3707c2c66affSColin Finck   const char * TestItem7 = "TestSomeText\r\n\r\r\n\rTestSomeText";
3708c2c66affSColin Finck   const char * TestItem7_after = "TestSomeText\r\n \r\nTestSomeText";
3709c2c66affSColin Finck 
3710c2c66affSColin Finck   const char rtftextA[] = "{\\rtf sometext}";
3711c2c66affSColin Finck   const char urtftextA[] = "{\\urtf sometext}";
3712c2c66affSColin Finck   const WCHAR rtftextW[] = {'{','\\','r','t','f',' ','s','o','m','e','t','e','x','t','}',0};
3713c2c66affSColin Finck   const WCHAR urtftextW[] = {'{','\\','u','r','t','f',' ','s','o','m','e','t','e','x','t','}',0};
3714c2c66affSColin Finck   const WCHAR sometextW[] = {'s','o','m','e','t','e','x','t',0};
3715c2c66affSColin Finck 
3716c2c66affSColin Finck   char buf[1024] = {0};
3717c2c66affSColin Finck   WCHAR bufW[1024] = {0};
3718c2c66affSColin Finck   LRESULT result;
3719c2c66affSColin Finck 
3720c2c66affSColin Finck   /* This test attempts to show that WM_SETTEXT on a riched20 control causes
3721c2c66affSColin Finck      any solitary \r to be converted to \r\n on return. Properly paired
3722c2c66affSColin Finck      \r\n are not affected. It also shows that the special sequence \r\r\n
3723c2c66affSColin Finck      gets converted to a single space.
3724c2c66affSColin Finck    */
3725c2c66affSColin Finck 
3726c2c66affSColin Finck #define TEST_SETTEXT(a, b) \
3727c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)a); \
3728c2c66affSColin Finck   ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); \
3729c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buf); \
3730c2c66affSColin Finck   ok (result == lstrlenA(buf), \
3731c2c66affSColin Finck 	"WM_GETTEXT returned %ld instead of expected %u\n", \
3732c2c66affSColin Finck 	result, lstrlenA(buf)); \
3733c2c66affSColin Finck   result = strcmp(b, buf); \
3734c2c66affSColin Finck   ok(result == 0, \
3735c2c66affSColin Finck         "WM_SETTEXT round trip: strcmp = %ld, text=\"%s\"\n", result, buf);
3736c2c66affSColin Finck 
3737c2c66affSColin Finck   TEST_SETTEXT(TestItem1, TestItem1)
3738c2c66affSColin Finck   TEST_SETTEXT(TestItem2, TestItem2_after)
3739c2c66affSColin Finck   TEST_SETTEXT(TestItem3, TestItem3_after)
3740c2c66affSColin Finck   TEST_SETTEXT(TestItem3_after, TestItem3_after)
3741c2c66affSColin Finck   TEST_SETTEXT(TestItem4, TestItem4_after)
3742c2c66affSColin Finck   TEST_SETTEXT(TestItem5, TestItem5_after)
3743c2c66affSColin Finck   TEST_SETTEXT(TestItem6, TestItem6_after)
3744c2c66affSColin Finck   TEST_SETTEXT(TestItem7, TestItem7_after)
3745c2c66affSColin Finck 
3746c2c66affSColin Finck   /* The following tests demonstrate that WM_SETTEXT supports RTF strings */
3747c2c66affSColin Finck   TEST_SETTEXT(rtftextA, "sometext") /* interpreted as ascii rtf */
3748c2c66affSColin Finck   TEST_SETTEXT(urtftextA, "sometext") /* interpreted as ascii rtf */
3749c2c66affSColin Finck   TEST_SETTEXT(rtftextW, "{") /* interpreted as ascii text */
3750c2c66affSColin Finck   TEST_SETTEXT(urtftextW, "{") /* interpreted as ascii text */
3751c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3752c2c66affSColin Finck #undef TEST_SETTEXT
3753c2c66affSColin Finck 
3754c2c66affSColin Finck #define TEST_SETTEXTW(a, b) \
3755c2c66affSColin Finck   result = SendMessageW(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)a); \
3756c2c66affSColin Finck   ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); \
3757c2c66affSColin Finck   result = SendMessageW(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufW); \
3758c2c66affSColin Finck   ok (result == lstrlenW(bufW), \
3759c2c66affSColin Finck 	"WM_GETTEXT returned %ld instead of expected %u\n", \
3760c2c66affSColin Finck 	result, lstrlenW(bufW)); \
3761c2c66affSColin Finck   result = lstrcmpW(b, bufW); \
3762c2c66affSColin Finck   ok(result == 0, "WM_SETTEXT round trip: strcmp = %ld\n", result);
3763c2c66affSColin Finck 
3764c2c66affSColin Finck   hwndRichEdit = CreateWindowW(RICHEDIT_CLASS20W, NULL,
3765c2c66affSColin Finck                                ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
3766c2c66affSColin Finck                                0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
3767c2c66affSColin Finck   ok(hwndRichEdit != NULL, "class: RichEdit20W, error: %d\n", (int) GetLastError());
3768c2c66affSColin Finck   TEST_SETTEXTW(rtftextA, sometextW) /* interpreted as ascii rtf */
3769c2c66affSColin Finck   TEST_SETTEXTW(urtftextA, sometextW) /* interpreted as ascii rtf */
3770c2c66affSColin Finck   TEST_SETTEXTW(rtftextW, rtftextW) /* interpreted as ascii text */
3771c2c66affSColin Finck   TEST_SETTEXTW(urtftextW, urtftextW) /* interpreted as ascii text */
3772c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3773c2c66affSColin Finck #undef TEST_SETTEXTW
377444f07538SAmine Khaldi 
377544f07538SAmine Khaldi   /* Single-line richedit */
377644f07538SAmine Khaldi   hwndRichEdit = new_richedit_with_style(NULL, 0);
377744f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"line1\r\nline2");
377844f07538SAmine Khaldi   ok(result == 1, "WM_SETTEXT returned %ld, expected 12\n", result);
377944f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buf);
378044f07538SAmine Khaldi   ok(result == 5, "WM_GETTEXT returned %ld, expected 5\n", result);
378144f07538SAmine Khaldi   ok(!strcmp(buf, "line1"), "WM_GETTEXT returned incorrect string '%s'\n", buf);
378244f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"{\\rtf1 ABC\\rtlpar\\par DEF\\par HIJ\\pard\\par}");
378344f07538SAmine Khaldi   ok(result == 1, "WM_SETTEXT returned %ld, expected 1\n", result);
378444f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buf);
378544f07538SAmine Khaldi   ok(result == 3, "WM_GETTEXT returned %ld, expected 3\n", result);
378644f07538SAmine Khaldi   ok(!strcmp(buf, "ABC"), "WM_GETTEXT returned incorrect string '%s'\n", buf);
378744f07538SAmine Khaldi   DestroyWindow(hwndRichEdit);
3788c2c66affSColin Finck }
3789c2c66affSColin Finck 
3790c2c66affSColin Finck /* Set *pcb to one to show that the remaining cb-1 bytes are not
3791c2c66affSColin Finck    resent to the callkack. */
test_esCallback_written_1(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)3792c2c66affSColin Finck static DWORD CALLBACK test_esCallback_written_1(DWORD_PTR dwCookie,
3793c2c66affSColin Finck                                                 LPBYTE pbBuff,
3794c2c66affSColin Finck                                                 LONG cb,
3795c2c66affSColin Finck                                                 LONG *pcb)
3796c2c66affSColin Finck {
3797c2c66affSColin Finck   char** str = (char**)dwCookie;
3798c2c66affSColin Finck   ok(*pcb == cb || *pcb == 0, "cb %d, *pcb %d\n", cb, *pcb);
3799c2c66affSColin Finck   *pcb = 0;
3800c2c66affSColin Finck   if (cb > 0) {
3801c2c66affSColin Finck     memcpy(*str, pbBuff, cb);
3802c2c66affSColin Finck     *str += cb;
3803c2c66affSColin Finck     *pcb = 1;
3804c2c66affSColin Finck   }
3805c2c66affSColin Finck   return 0;
3806c2c66affSColin Finck }
3807c2c66affSColin Finck 
count_pars(const char * buf)3808c2c66affSColin Finck static int count_pars(const char *buf)
3809c2c66affSColin Finck {
3810c2c66affSColin Finck     const char *p = buf;
3811c2c66affSColin Finck     int count = 0;
3812c2c66affSColin Finck     while ((p = strstr( p, "\\par" )) != NULL)
3813c2c66affSColin Finck     {
3814c2c66affSColin Finck         if (!isalpha( p[4] ))
3815c2c66affSColin Finck            count++;
3816c2c66affSColin Finck         p++;
3817c2c66affSColin Finck     }
3818c2c66affSColin Finck     return count;
3819c2c66affSColin Finck }
3820c2c66affSColin Finck 
test_EM_STREAMOUT(void)3821c2c66affSColin Finck static void test_EM_STREAMOUT(void)
3822c2c66affSColin Finck {
3823c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
3824c2c66affSColin Finck   int r;
3825c2c66affSColin Finck   EDITSTREAM es;
3826c2c66affSColin Finck   char buf[1024] = {0};
3827c2c66affSColin Finck   char * p;
3828c2c66affSColin Finck   LRESULT result;
3829c2c66affSColin Finck 
3830c2c66affSColin Finck   const char * TestItem1 = "TestSomeText";
3831c2c66affSColin Finck   const char * TestItem2 = "TestSomeText\r";
3832c2c66affSColin Finck   const char * TestItem3 = "TestSomeText\r\n";
3833c2c66affSColin Finck 
3834c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem1);
3835c2c66affSColin Finck   p = buf;
3836c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
3837c2c66affSColin Finck   es.dwError = 0;
3838c2c66affSColin Finck   es.pfnCallback = test_WM_SETTEXT_esCallback;
3839c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
3840c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_TEXT, (LPARAM)&es);
3841c2c66affSColin Finck   r = strlen(buf);
3842c2c66affSColin Finck   ok(r == 12, "streamed text length is %d, expecting 12\n", r);
3843c2c66affSColin Finck   ok(strcmp(buf, TestItem1) == 0,
3844c2c66affSColin Finck         "streamed text different, got %s\n", buf);
3845c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3846c2c66affSColin Finck 
3847c2c66affSColin Finck   /* RTF mode writes the final end of para \r if it's part of the selection */
3848c2c66affSColin Finck   p = buf;
3849c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
3850c2c66affSColin Finck   ok (count_pars(buf) == 1, "got %s\n", buf);
3851c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3852c2c66affSColin Finck   p = buf;
3853c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 12);
3854c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF|SFF_SELECTION, (LPARAM)&es);
3855c2c66affSColin Finck   ok (count_pars(buf) == 0, "got %s\n", buf);
3856c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3857c2c66affSColin Finck   p = buf;
3858c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
3859c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF|SFF_SELECTION, (LPARAM)&es);
3860c2c66affSColin Finck   ok (count_pars(buf) == 1, "got %s\n", buf);
3861c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3862c2c66affSColin Finck 
3863c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem2);
3864c2c66affSColin Finck   p = buf;
3865c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
3866c2c66affSColin Finck   es.dwError = 0;
3867c2c66affSColin Finck   es.pfnCallback = test_WM_SETTEXT_esCallback;
3868c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
3869c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_TEXT, (LPARAM)&es);
3870c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3871c2c66affSColin Finck   r = strlen(buf);
3872c2c66affSColin Finck   /* Here again, \r gets converted to \r\n, like WM_GETTEXT */
3873c2c66affSColin Finck   ok(r == 14, "streamed text length is %d, expecting 14\n", r);
3874c2c66affSColin Finck   ok(strcmp(buf, TestItem3) == 0,
3875c2c66affSColin Finck         "streamed text different from, got %s\n", buf);
3876c2c66affSColin Finck 
3877c2c66affSColin Finck   /* And again RTF mode writes the final end of para \r if it's part of the selection */
3878c2c66affSColin Finck   p = buf;
3879c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
3880c2c66affSColin Finck   ok (count_pars(buf) == 2, "got %s\n", buf);
3881c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3882c2c66affSColin Finck   p = buf;
3883c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 13);
3884c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF|SFF_SELECTION, (LPARAM)&es);
3885c2c66affSColin Finck   ok (count_pars(buf) == 1, "got %s\n", buf);
3886c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3887c2c66affSColin Finck   p = buf;
3888c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
3889c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF|SFF_SELECTION, (LPARAM)&es);
3890c2c66affSColin Finck   ok (count_pars(buf) == 2, "got %s\n", buf);
3891c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3892c2c66affSColin Finck 
3893c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem3);
3894c2c66affSColin Finck   p = buf;
3895c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
3896c2c66affSColin Finck   es.dwError = 0;
3897c2c66affSColin Finck   es.pfnCallback = test_WM_SETTEXT_esCallback;
3898c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
3899c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_TEXT, (LPARAM)&es);
3900c2c66affSColin Finck   ok(result == streamout_written, "got %ld expected %d\n", result, streamout_written);
3901c2c66affSColin Finck   r = strlen(buf);
3902c2c66affSColin Finck   ok(r == 14, "streamed text length is %d, expecting 14\n", r);
3903c2c66affSColin Finck   ok(strcmp(buf, TestItem3) == 0,
3904c2c66affSColin Finck         "streamed text different, got %s\n", buf);
3905c2c66affSColin Finck 
3906c2c66affSColin Finck   /* Use a callback that sets *pcb to one */
3907c2c66affSColin Finck   p = buf;
3908c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
3909c2c66affSColin Finck   es.dwError = 0;
3910c2c66affSColin Finck   es.pfnCallback = test_esCallback_written_1;
3911c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
3912c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_TEXT, (LPARAM)&es);
3913c2c66affSColin Finck   r = strlen(buf);
3914c2c66affSColin Finck   ok(r == 14, "streamed text length is %d, expecting 14\n", r);
3915c2c66affSColin Finck   ok(strcmp(buf, TestItem3) == 0,
3916c2c66affSColin Finck         "streamed text different, got %s\n", buf);
3917c2c66affSColin Finck   ok(result == 0, "got %ld expected 0\n", result);
3918c2c66affSColin Finck 
3919c2c66affSColin Finck 
3920c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3921c2c66affSColin Finck }
3922c2c66affSColin Finck 
test_EM_STREAMOUT_FONTTBL(void)3923c2c66affSColin Finck static void test_EM_STREAMOUT_FONTTBL(void)
3924c2c66affSColin Finck {
3925c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
3926c2c66affSColin Finck   EDITSTREAM es;
3927c2c66affSColin Finck   char buf[1024] = {0};
3928c2c66affSColin Finck   char * p;
3929c2c66affSColin Finck   char * fontTbl;
3930c2c66affSColin Finck   int brackCount;
3931c2c66affSColin Finck 
3932c2c66affSColin Finck   const char * TestItem = "TestSomeText";
3933c2c66affSColin Finck 
3934c2c66affSColin Finck   /* fills in the richedit control with some text */
3935c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem);
3936c2c66affSColin Finck 
3937c2c66affSColin Finck   /* streams out the text in rtf format */
3938c2c66affSColin Finck   p = buf;
3939c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
3940c2c66affSColin Finck   es.dwError = 0;
3941c2c66affSColin Finck   es.pfnCallback = test_WM_SETTEXT_esCallback;
3942c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
3943c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
3944c2c66affSColin Finck 
3945c2c66affSColin Finck   /* scans for \fonttbl, error if not found */
3946c2c66affSColin Finck   fontTbl = strstr(buf, "\\fonttbl");
3947c2c66affSColin Finck   ok(fontTbl != NULL, "missing \\fonttbl section\n");
3948c2c66affSColin Finck   if(fontTbl)
3949c2c66affSColin Finck   {
3950c2c66affSColin Finck       /* scans for terminating closing bracket */
3951c2c66affSColin Finck       brackCount = 1;
3952c2c66affSColin Finck       while(*fontTbl && brackCount)
3953c2c66affSColin Finck       {
3954c2c66affSColin Finck           if(*fontTbl == '{')
3955c2c66affSColin Finck               brackCount++;
3956c2c66affSColin Finck           else if(*fontTbl == '}')
3957c2c66affSColin Finck               brackCount--;
3958c2c66affSColin Finck           fontTbl++;
3959c2c66affSColin Finck       }
3960c2c66affSColin Finck     /* checks whether closing bracket is ok */
3961c2c66affSColin Finck       ok(brackCount == 0, "missing closing bracket in \\fonttbl block\n");
3962c2c66affSColin Finck       if(!brackCount)
3963c2c66affSColin Finck       {
3964c2c66affSColin Finck           /* char before closing fonttbl block should be a closed bracket */
3965c2c66affSColin Finck           fontTbl -= 2;
3966c2c66affSColin Finck           ok(*fontTbl == '}', "spurious character '%02x' before \\fonttbl closing bracket\n", *fontTbl);
3967c2c66affSColin Finck 
3968c2c66affSColin Finck           /* char after fonttbl block should be a crlf */
3969c2c66affSColin Finck           fontTbl += 2;
3970c2c66affSColin Finck           ok(*fontTbl == 0x0d && *(fontTbl+1) == 0x0a, "missing crlf after \\fonttbl block\n");
3971c2c66affSColin Finck       }
3972c2c66affSColin Finck   }
3973c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
3974c2c66affSColin Finck }
3975c2c66affSColin Finck 
test_EM_STREAMOUT_empty_para(void)3976c2c66affSColin Finck static void test_EM_STREAMOUT_empty_para(void)
3977c2c66affSColin Finck {
3978c2c66affSColin Finck     HWND hwnd = new_richedit(NULL);
3979c2c66affSColin Finck     char buf[1024], *p = buf;
3980c2c66affSColin Finck     EDITSTREAM es;
3981c2c66affSColin Finck 
3982c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
3983c2c66affSColin Finck 
3984c2c66affSColin Finck     memset(buf, 0, sizeof(buf));
3985c2c66affSColin Finck     es.dwCookie    = (DWORD_PTR)&p;
3986c2c66affSColin Finck     es.dwError     = 0;
3987c2c66affSColin Finck     es.pfnCallback = test_WM_SETTEXT_esCallback;
3988c2c66affSColin Finck 
3989c2c66affSColin Finck     SendMessageA(hwnd, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
3990c2c66affSColin Finck     ok((p = strstr(buf, "\\pard")) != NULL, "missing \\pard\n");
3991c2c66affSColin Finck     ok(((p = strstr(p, "\\fs")) && isdigit(p[3])), "missing \\fs\n");
3992c2c66affSColin Finck 
3993c2c66affSColin Finck     DestroyWindow(hwnd);
3994c2c66affSColin Finck }
3995c2c66affSColin Finck 
test_EM_SETTEXTEX(void)3996c2c66affSColin Finck static void test_EM_SETTEXTEX(void)
3997c2c66affSColin Finck {
3998c2c66affSColin Finck   HWND hwndRichEdit, parent;
3999c2c66affSColin Finck   SCROLLINFO si;
4000c2c66affSColin Finck   int sel_start, sel_end;
4001c2c66affSColin Finck   SETTEXTEX setText;
4002c2c66affSColin Finck   GETTEXTEX getText;
4003c2c66affSColin Finck   WCHAR TestItem1[] = {'T', 'e', 's', 't',
4004c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4005c2c66affSColin Finck                        'T', 'e', 'x', 't', 0};
4006c2c66affSColin Finck   WCHAR TestItem1alt[] = {'T', 'T', 'e', 's',
4007c2c66affSColin Finck                           't', 'S', 'o', 'm',
4008c2c66affSColin Finck                           'e', 'T', 'e', 'x',
4009c2c66affSColin Finck                           't', 't', 'S', 'o',
4010c2c66affSColin Finck                           'm', 'e', 'T', 'e',
4011c2c66affSColin Finck                           'x', 't', 0};
4012c2c66affSColin Finck   WCHAR TestItem1altn[] = {'T','T','e','s','t','S','o','m','e','T','e','x','t',
4013c2c66affSColin Finck                            '\r','t','S','o','m','e','T','e','x','t',0};
4014c2c66affSColin Finck   WCHAR TestItem2[] = {'T', 'e', 's', 't',
4015c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4016c2c66affSColin Finck                        'T', 'e', 'x', 't',
4017c2c66affSColin Finck                       '\r', 0};
4018c2c66affSColin Finck   const char * TestItem2_after = "TestSomeText\r\n";
4019c2c66affSColin Finck   WCHAR TestItem3[] = {'T', 'e', 's', 't',
4020c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4021c2c66affSColin Finck                        'T', 'e', 'x', 't',
4022c2c66affSColin Finck                       '\r','\n','\r','\n', 0};
4023c2c66affSColin Finck   WCHAR TestItem3alt[] = {'T', 'e', 's', 't',
4024c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4025c2c66affSColin Finck                        'T', 'e', 'x', 't',
4026c2c66affSColin Finck                        '\n','\n', 0};
4027c2c66affSColin Finck   WCHAR TestItem3_after[] = {'T', 'e', 's', 't',
4028c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4029c2c66affSColin Finck                        'T', 'e', 'x', 't',
4030c2c66affSColin Finck                        '\r','\r', 0};
4031c2c66affSColin Finck   WCHAR TestItem4[] = {'T', 'e', 's', 't',
4032c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4033c2c66affSColin Finck                        'T', 'e', 'x', 't',
4034c2c66affSColin Finck                       '\r','\r','\n','\r',
4035c2c66affSColin Finck                       '\n', 0};
4036c2c66affSColin Finck   WCHAR TestItem4_after[] = {'T', 'e', 's', 't',
4037c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4038c2c66affSColin Finck                        'T', 'e', 'x', 't',
4039c2c66affSColin Finck                        ' ','\r', 0};
4040c2c66affSColin Finck #define MAX_BUF_LEN 1024
4041c2c66affSColin Finck   WCHAR buf[MAX_BUF_LEN];
4042c2c66affSColin Finck   char bufACP[MAX_BUF_LEN];
4043c2c66affSColin Finck   char * p;
4044c2c66affSColin Finck   int result;
4045c2c66affSColin Finck   CHARRANGE cr;
4046c2c66affSColin Finck   EDITSTREAM es;
4047c2c66affSColin Finck   WNDCLASSA cls;
4048c2c66affSColin Finck 
4049c2c66affSColin Finck   /* Test the scroll position with and without a parent window.
4050c2c66affSColin Finck    *
4051c2c66affSColin Finck    * For some reason the scroll position is 0 after EM_SETTEXTEX
4052c2c66affSColin Finck    * with the ST_SELECTION flag only when the control has a parent
4053c2c66affSColin Finck    * window, even though the selection is at the end. */
4054c2c66affSColin Finck   cls.style = 0;
4055c2c66affSColin Finck   cls.lpfnWndProc = DefWindowProcA;
4056c2c66affSColin Finck   cls.cbClsExtra = 0;
4057c2c66affSColin Finck   cls.cbWndExtra = 0;
4058c2c66affSColin Finck   cls.hInstance = GetModuleHandleA(0);
4059c2c66affSColin Finck   cls.hIcon = 0;
4060c2c66affSColin Finck   cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
4061c2c66affSColin Finck   cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4062c2c66affSColin Finck   cls.lpszMenuName = NULL;
4063c2c66affSColin Finck   cls.lpszClassName = "ParentTestClass";
4064c2c66affSColin Finck   if(!RegisterClassA(&cls)) assert(0);
4065c2c66affSColin Finck 
4066c2c66affSColin Finck   parent = CreateWindowA(cls.lpszClassName, NULL, WS_POPUP|WS_VISIBLE,
4067c2c66affSColin Finck                         0, 0, 200, 60, NULL, NULL, NULL, NULL);
4068c2c66affSColin Finck   ok (parent != 0, "Failed to create parent window\n");
4069c2c66affSColin Finck 
4070c2c66affSColin Finck   hwndRichEdit = CreateWindowExA(0,
4071c2c66affSColin Finck                         RICHEDIT_CLASS20A, NULL,
4072c2c66affSColin Finck                         ES_MULTILINE|WS_VSCROLL|WS_VISIBLE|WS_CHILD,
4073c2c66affSColin Finck                         0, 0, 200, 60, parent, NULL,
4074c2c66affSColin Finck                         hmoduleRichEdit, NULL);
4075c2c66affSColin Finck 
4076c2c66affSColin Finck   setText.codepage = CP_ACP;
4077c2c66affSColin Finck   setText.flags = ST_SELECTION;
4078c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText,
4079c2c66affSColin Finck                         (LPARAM)"{\\rtf 1\\par 2\\par 3\\par 4\\par 5\\par 6\\par 7\\par 8\\par 9\\par}");
4080c2c66affSColin Finck   todo_wine ok(result == 18, "EM_SETTEXTEX returned %d, expected 18\n", result);
4081c2c66affSColin Finck   si.cbSize = sizeof(si);
4082c2c66affSColin Finck   si.fMask = SIF_ALL;
4083c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
4084c2c66affSColin Finck   todo_wine ok(si.nPos == 0, "Position is incorrectly at %d\n", si.nPos);
4085c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
4086c2c66affSColin Finck   ok(sel_start == 18, "Selection start incorrectly at %d\n", sel_start);
4087c2c66affSColin Finck   ok(sel_end == 18, "Selection end incorrectly at %d\n", sel_end);
4088c2c66affSColin Finck 
4089c2c66affSColin Finck   DestroyWindow(parent);
4090c2c66affSColin Finck 
4091c2c66affSColin Finck   /* Test without a parent window */
4092c2c66affSColin Finck   hwndRichEdit = new_richedit(NULL);
4093c2c66affSColin Finck   setText.codepage = CP_ACP;
4094c2c66affSColin Finck   setText.flags = ST_SELECTION;
4095c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText,
4096c2c66affSColin Finck                         (LPARAM)"{\\rtf 1\\par 2\\par 3\\par 4\\par 5\\par 6\\par 7\\par 8\\par 9\\par}");
4097c2c66affSColin Finck   todo_wine ok(result == 18, "EM_SETTEXTEX returned %d, expected 18\n", result);
4098c2c66affSColin Finck   si.cbSize = sizeof(si);
4099c2c66affSColin Finck   si.fMask = SIF_ALL;
4100c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
4101c2c66affSColin Finck   ok(si.nPos != 0, "Position is incorrectly at %d\n", si.nPos);
4102c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
4103c2c66affSColin Finck   ok(sel_start == 18, "Selection start incorrectly at %d\n", sel_start);
4104c2c66affSColin Finck   ok(sel_end == 18, "Selection end incorrectly at %d\n", sel_end);
4105c2c66affSColin Finck 
4106c2c66affSColin Finck   /* The scroll position should also be 0 after EM_SETTEXTEX with ST_DEFAULT,
4107c2c66affSColin Finck    * but this time it is because the selection is at the beginning. */
4108c2c66affSColin Finck   setText.codepage = CP_ACP;
4109c2c66affSColin Finck   setText.flags = ST_DEFAULT;
4110c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText,
4111c2c66affSColin Finck                         (LPARAM)"{\\rtf 1\\par 2\\par 3\\par 4\\par 5\\par 6\\par 7\\par 8\\par 9\\par}");
4112c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4113c2c66affSColin Finck   si.cbSize = sizeof(si);
4114c2c66affSColin Finck   si.fMask = SIF_ALL;
4115c2c66affSColin Finck   GetScrollInfo(hwndRichEdit, SB_VERT, &si);
4116c2c66affSColin Finck   ok(si.nPos == 0, "Position is incorrectly at %d\n", si.nPos);
4117c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
4118c2c66affSColin Finck   ok(sel_start == 0, "Selection start incorrectly at %d\n", sel_start);
4119c2c66affSColin Finck   ok(sel_end == 0, "Selection end incorrectly at %d\n", sel_end);
4120c2c66affSColin Finck 
4121c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4122c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4123c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4124c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4125c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4126c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4127c2c66affSColin Finck 
4128c2c66affSColin Finck   setText.flags = 0;
4129c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4130c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4131c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4132c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem1) == 0,
4133c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
4134c2c66affSColin Finck 
4135c2c66affSColin Finck   /* Unlike WM_SETTEXT/WM_GETTEXT pair, EM_SETTEXTEX/EM_GETTEXTEX does not
4136c2c66affSColin Finck      convert \r to \r\n on return: !ST_SELECTION && Unicode && !\rtf
4137c2c66affSColin Finck    */
4138c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4139c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4140c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4141c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4142c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4143c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4144c2c66affSColin Finck   setText.flags = 0;
4145c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem2);
4146c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4147c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4148c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem2) == 0,
4149c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
4150c2c66affSColin Finck 
4151c2c66affSColin Finck   /* However, WM_GETTEXT *does* see \r\n where EM_GETTEXTEX would see \r */
4152c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, MAX_BUF_LEN, (LPARAM)buf);
4153c2c66affSColin Finck   ok(strcmp((const char *)buf, TestItem2_after) == 0,
4154c2c66affSColin Finck       "WM_GETTEXT did *not* see \\r converted to \\r\\n pairs.\n");
4155c2c66affSColin Finck 
4156c2c66affSColin Finck   /* Baseline test for just-enough buffer space for string */
4157c2c66affSColin Finck   getText.cb = (lstrlenW(TestItem2) + 1) * sizeof(WCHAR);
4158c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4159c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4160c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4161c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4162c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
4163c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4164c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem2) == 0,
4165c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
4166c2c66affSColin Finck 
4167c2c66affSColin Finck   /* When there is enough space for one character, but not both, of the CRLF
4168c2c66affSColin Finck      pair at the end of the string, the CR is not copied at all. That is,
4169c2c66affSColin Finck      the caller must not see CRLF pairs truncated to CR at the end of the
4170c2c66affSColin Finck      string.
4171c2c66affSColin Finck    */
4172c2c66affSColin Finck   getText.cb = (lstrlenW(TestItem2) + 1) * sizeof(WCHAR);
4173c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4174c2c66affSColin Finck   getText.flags = GT_USECRLF;   /* <-- asking for CR -> CRLF conversion */
4175c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4176c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4177c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
4178c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4179c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem1) == 0,
4180c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
4181c2c66affSColin Finck 
4182c2c66affSColin Finck 
4183c2c66affSColin Finck   /* \r\n pairs get changed into \r: !ST_SELECTION && Unicode && !\rtf */
4184c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4185c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4186c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4187c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4188c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4189c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4190c2c66affSColin Finck   setText.flags = 0;
4191c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem3);
4192c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4193c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4194c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem3_after) == 0,
4195c2c66affSColin Finck       "EM_SETTEXTEX did not convert properly\n");
4196c2c66affSColin Finck 
4197c2c66affSColin Finck   /* \n also gets changed to \r: !ST_SELECTION && Unicode && !\rtf */
4198c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4199c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4200c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4201c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4202c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4203c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4204c2c66affSColin Finck   setText.flags = 0;
4205c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem3alt);
4206c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4207c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4208c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem3_after) == 0,
4209c2c66affSColin Finck       "EM_SETTEXTEX did not convert properly\n");
4210c2c66affSColin Finck 
4211c2c66affSColin Finck   /* \r\r\n gets changed into single space: !ST_SELECTION && Unicode && !\rtf */
4212c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4213c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4214c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4215c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4216c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4217c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4218c2c66affSColin Finck   setText.flags = 0;
4219c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem4);
4220c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4221c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4222c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem4_after) == 0,
4223c2c66affSColin Finck       "EM_SETTEXTEX did not convert properly\n");
4224c2c66affSColin Finck 
4225c2c66affSColin Finck   /* !ST_SELECTION && Unicode && !\rtf */
4226c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, 0);
4227c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4228c2c66affSColin Finck 
4229c2c66affSColin Finck   ok (result == 1,
4230c2c66affSColin Finck       "EM_SETTEXTEX returned %d, instead of 1\n",result);
4231c2c66affSColin Finck   ok(!buf[0], "EM_SETTEXTEX with NULL lParam should clear rich edit.\n");
4232c2c66affSColin Finck 
4233c2c66affSColin Finck   /* put some text back: !ST_SELECTION && Unicode && !\rtf */
4234c2c66affSColin Finck   setText.flags = 0;
4235c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4236c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4237c2c66affSColin Finck   /* select some text */
4238c2c66affSColin Finck   cr.cpMax = 1;
4239c2c66affSColin Finck   cr.cpMin = 3;
4240c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
4241c2c66affSColin Finck   /* replace current selection: ST_SELECTION && Unicode && !\rtf */
4242c2c66affSColin Finck   setText.flags = ST_SELECTION;
4243c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, 0);
4244c2c66affSColin Finck   ok(result == 0,
4245c2c66affSColin Finck       "EM_SETTEXTEX with NULL lParam to replace selection"
4246c2c66affSColin Finck       " with no text should return 0. Got %i\n",
4247c2c66affSColin Finck       result);
4248c2c66affSColin Finck 
4249c2c66affSColin Finck   /* put some text back: !ST_SELECTION && Unicode && !\rtf */
4250c2c66affSColin Finck   setText.flags = 0;
4251c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4252c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4253c2c66affSColin Finck   /* select some text */
4254c2c66affSColin Finck   cr.cpMax = 1;
4255c2c66affSColin Finck   cr.cpMin = 3;
4256c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
4257c2c66affSColin Finck   /* replace current selection: ST_SELECTION && Unicode && !\rtf */
4258c2c66affSColin Finck   setText.flags = ST_SELECTION;
4259c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4260c2c66affSColin Finck   /* get text */
4261c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4262c2c66affSColin Finck   ok(result == lstrlenW(TestItem1),
4263c2c66affSColin Finck       "EM_SETTEXTEX with NULL lParam to replace selection"
4264c2c66affSColin Finck       " with no text should return 0. Got %i\n",
4265c2c66affSColin Finck       result);
4266c2c66affSColin Finck   ok(lstrlenW(buf) == 22,
4267c2c66affSColin Finck       "EM_SETTEXTEX to replace selection with more text failed: %i.\n",
4268c2c66affSColin Finck       lstrlenW(buf) );
4269c2c66affSColin Finck 
4270c2c66affSColin Finck   /* The following test demonstrates that EM_SETTEXTEX supports RTF strings */
4271c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"TestSomeText"); /* TestItem1 */
4272c2c66affSColin Finck   p = (char *)buf;
4273c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
4274c2c66affSColin Finck   es.dwError = 0;
4275c2c66affSColin Finck   es.pfnCallback = test_WM_SETTEXT_esCallback;
4276c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
4277c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMOUT,
4278c2c66affSColin Finck               (WPARAM)(SF_RTF), (LPARAM)&es);
4279c2c66affSColin Finck   trace("EM_STREAMOUT produced:\n%s\n", (char *)buf);
4280c2c66affSColin Finck 
4281c2c66affSColin Finck   /* !ST_SELECTION && !Unicode && \rtf */
4282c2c66affSColin Finck   setText.codepage = CP_ACP;/* EM_STREAMOUT saved as ANSI string */
4283c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4284c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4285c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4286c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4287c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4288c2c66affSColin Finck 
4289c2c66affSColin Finck   setText.flags = 0;
4290c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)buf);
4291c2c66affSColin Finck   ok(result == 1, "EM_SETTEXTEX returned %d, expected 1\n", result);
4292c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4293c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem1) == 0,
4294c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
4295c2c66affSColin Finck 
4296c2c66affSColin Finck   /* The following test demonstrates that EM_SETTEXTEX treats text as ASCII if it
4297c2c66affSColin Finck    * starts with ASCII characters "{\rtf" even when the codepage is unicode. */
4298c2c66affSColin Finck   setText.codepage = 1200; /* Lie about code page (actual ASCII) */
4299c2c66affSColin Finck   getText.codepage = CP_ACP;
4300c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4301c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4302c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4303c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4304c2c66affSColin Finck 
4305c2c66affSColin Finck   setText.flags = ST_SELECTION;
4306c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4307c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"{\\rtf not unicode}");
4308c2c66affSColin Finck   todo_wine ok(result == 11, "EM_SETTEXTEX incorrectly returned %d\n", result);
4309c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)bufACP);
4310c2c66affSColin Finck   ok(lstrcmpA(bufACP, "not unicode") == 0, "'%s' != 'not unicode'\n", bufACP);
4311c2c66affSColin Finck 
4312c2c66affSColin Finck   /* The following test demonstrates that EM_SETTEXTEX supports RTF strings with a selection */
4313c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"TestSomeText"); /* TestItem1 */
4314c2c66affSColin Finck   p = (char *)buf;
4315c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&p;
4316c2c66affSColin Finck   es.dwError = 0;
4317c2c66affSColin Finck   es.pfnCallback = test_WM_SETTEXT_esCallback;
4318c2c66affSColin Finck   memset(buf, 0, sizeof(buf));
4319c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMOUT,
4320c2c66affSColin Finck               (WPARAM)(SF_RTF), (LPARAM)&es);
4321c2c66affSColin Finck   trace("EM_STREAMOUT produced:\n%s\n", (char *)buf);
4322c2c66affSColin Finck 
4323c2c66affSColin Finck   /* select some text */
4324c2c66affSColin Finck   cr.cpMax = 1;
4325c2c66affSColin Finck   cr.cpMin = 3;
4326c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
4327c2c66affSColin Finck 
4328c2c66affSColin Finck   /* ST_SELECTION && !Unicode && \rtf */
4329c2c66affSColin Finck   setText.codepage = CP_ACP;/* EM_STREAMOUT saved as ANSI string */
4330c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4331c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4332c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4333c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4334c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4335c2c66affSColin Finck 
4336c2c66affSColin Finck   setText.flags = ST_SELECTION;
4337c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)buf);
4338c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4339c2c66affSColin Finck   ok_w3("Expected \"%s\" or \"%s\", got \"%s\"\n", TestItem1alt, TestItem1altn, buf);
4340c2c66affSColin Finck 
4341c2c66affSColin Finck   /* The following test demonstrates that EM_SETTEXTEX replacing a selection */
4342c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4343c2c66affSColin Finck   getText.codepage = CP_ACP;
4344c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4345c2c66affSColin Finck 
4346c2c66affSColin Finck   setText.flags = 0;
4347c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1); /* TestItem1 */
4348c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)bufACP);
4349c2c66affSColin Finck 
4350c2c66affSColin Finck   /* select some text */
4351c2c66affSColin Finck   cr.cpMax = 1;
4352c2c66affSColin Finck   cr.cpMin = 3;
4353c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
4354c2c66affSColin Finck 
4355c2c66affSColin Finck   /* ST_SELECTION && !Unicode && !\rtf */
4356c2c66affSColin Finck   setText.codepage = CP_ACP;
4357c2c66affSColin Finck   getText.codepage = 1200;  /* no constant for unicode */
4358c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4359c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4360c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4361c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4362c2c66affSColin Finck 
4363c2c66affSColin Finck   setText.flags = ST_SELECTION;
4364c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)bufACP);
4365c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
4366c2c66affSColin Finck   ok(lstrcmpW(buf, TestItem1alt) == 0,
4367c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_SETTEXTEX when"
4368c2c66affSColin Finck       " using ST_SELECTION and non-Unicode\n");
4369c2c66affSColin Finck 
4370c2c66affSColin Finck   /* Test setting text using rich text format */
4371c2c66affSColin Finck   setText.flags = 0;
4372c2c66affSColin Finck   setText.codepage = CP_ACP;
4373c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"{\\rtf richtext}");
4374c2c66affSColin Finck   getText.codepage = CP_ACP;
4375c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4376c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4377c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4378c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4379c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)bufACP);
4380c2c66affSColin Finck   ok(!strcmp(bufACP, "richtext"), "expected 'richtext' but got '%s'\n", bufACP);
4381c2c66affSColin Finck 
4382c2c66affSColin Finck   setText.flags = 0;
4383c2c66affSColin Finck   setText.codepage = CP_ACP;
4384c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"{\\urtf morerichtext}");
4385c2c66affSColin Finck   getText.codepage = CP_ACP;
4386c2c66affSColin Finck   getText.cb = MAX_BUF_LEN;
4387c2c66affSColin Finck   getText.flags = GT_DEFAULT;
4388c2c66affSColin Finck   getText.lpDefaultChar = NULL;
4389c2c66affSColin Finck   getText.lpUsedDefChar = NULL;
4390c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)bufACP);
4391c2c66affSColin Finck   ok(!strcmp(bufACP, "morerichtext"), "expected 'morerichtext' but got '%s'\n", bufACP);
4392c2c66affSColin Finck 
4393c2c66affSColin Finck   /* test for utf8 text with BOM */
4394c2c66affSColin Finck   setText.flags = 0;
4395c2c66affSColin Finck   setText.codepage = CP_ACP;
4396c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"\xef\xbb\xbfTestUTF8WithBOM");
4397c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufACP);
4398c2c66affSColin Finck   ok(result == 15, "EM_SETTEXTEX: Test UTF8 with BOM returned %d, expected 15\n", result);
4399c2c66affSColin Finck   result = strcmp(bufACP, "TestUTF8WithBOM");
4400c2c66affSColin Finck   ok(result == 0, "EM_SETTEXTEX: Test UTF8 with BOM set wrong text: Result: %s\n", bufACP);
4401c2c66affSColin Finck 
4402c2c66affSColin Finck   setText.flags = 0;
4403c2c66affSColin Finck   setText.codepage = CP_UTF8;
4404c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"\xef\xbb\xbfTestUTF8WithBOM");
4405c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufACP);
4406c2c66affSColin Finck   ok(result == 15, "EM_SETTEXTEX: Test UTF8 with BOM returned %d, expected 15\n", result);
4407c2c66affSColin Finck   result = strcmp(bufACP, "TestUTF8WithBOM");
4408c2c66affSColin Finck   ok(result == 0, "EM_SETTEXTEX: Test UTF8 with BOM set wrong text: Result: %s\n", bufACP);
4409c2c66affSColin Finck 
4410c2c66affSColin Finck   /* Test multibyte character */
4411c2c66affSColin Finck   if (!is_lang_japanese)
4412c2c66affSColin Finck     skip("Skip multibyte character tests on non-Japanese platform\n");
4413c2c66affSColin Finck   else
4414c2c66affSColin Finck   {
4415c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4416c2c66affSColin Finck     setText.flags = ST_SELECTION;
4417c2c66affSColin Finck     setText.codepage = CP_ACP;
4418c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"abc\x8e\xf0");
4419c2c66affSColin Finck     todo_wine ok(result == 5, "EM_SETTEXTEX incorrectly returned %d, expected 5\n", result);
4420c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufACP);
4421c2c66affSColin Finck     ok(result == 5, "WM_GETTEXT incorrectly returned %d, expected 5\n", result);
4422c2c66affSColin Finck     ok(!strcmp(bufACP, "abc\x8e\xf0"),
4423c2c66affSColin Finck        "EM_SETTEXTEX: Test multibyte character set wrong text: Result: %s\n", bufACP);
4424c2c66affSColin Finck 
4425c2c66affSColin Finck     setText.flags = ST_DEFAULT;
4426c2c66affSColin Finck     setText.codepage = CP_ACP;
4427c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"abc\x8e\xf0");
4428c2c66affSColin Finck     ok(result == 1, "EM_SETTEXTEX incorrectly returned %d, expected 1\n", result);
4429c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufACP);
4430c2c66affSColin Finck     ok(result == 5, "WM_GETTEXT incorrectly returned %d, expected 5\n", result);
4431c2c66affSColin Finck     ok(!strcmp(bufACP, "abc\x8e\xf0"),
4432c2c66affSColin Finck        "EM_SETTEXTEX: Test multibyte character set wrong text: Result: %s\n", bufACP);
4433c2c66affSColin Finck 
4434c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4435c2c66affSColin Finck     setText.flags = ST_SELECTION;
4436c2c66affSColin Finck     setText.codepage = CP_ACP;
4437c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"{\\rtf abc\x8e\xf0}");
4438c2c66affSColin Finck     todo_wine ok(result == 4, "EM_SETTEXTEX incorrectly returned %d, expected 4\n", result);
4439c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufACP);
4440c2c66affSColin Finck     ok(result == 5, "WM_GETTEXT incorrectly returned %d, expected 5\n", result);
4441c2c66affSColin Finck     todo_wine ok(!strcmp(bufACP, "abc\x8e\xf0"),
4442c2c66affSColin Finck                  "EM_SETTEXTEX: Test multibyte character set wrong text: Result: %s\n", bufACP);
4443c2c66affSColin Finck   }
4444c2c66affSColin Finck 
4445c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
444644f07538SAmine Khaldi 
444744f07538SAmine Khaldi   /* Single-line richedit */
444844f07538SAmine Khaldi   hwndRichEdit = new_richedit_with_style(NULL, 0);
444944f07538SAmine Khaldi   setText.flags = ST_DEFAULT;
445044f07538SAmine Khaldi   setText.codepage = CP_ACP;
445144f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"line1\r\nline2");
445244f07538SAmine Khaldi   ok(result == 1, "EM_SETTEXTEX incorrectly returned %d, expected 1\n", result);
445344f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)bufACP);
445444f07538SAmine Khaldi   ok(result == 5, "WM_GETTEXT incorrectly returned %d, expected 5\n", result);
445544f07538SAmine Khaldi   ok(!strcmp(bufACP, "line1"), "EM_SETTEXTEX: Test single-line text: Result: %s\n", bufACP);
445644f07538SAmine Khaldi   DestroyWindow(hwndRichEdit);
4457c2c66affSColin Finck }
4458c2c66affSColin Finck 
test_EM_LIMITTEXT(void)4459c2c66affSColin Finck static void test_EM_LIMITTEXT(void)
4460c2c66affSColin Finck {
4461c2c66affSColin Finck   int ret;
4462c2c66affSColin Finck 
4463c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
4464c2c66affSColin Finck 
4465c2c66affSColin Finck   /* The main purpose of this test is to demonstrate that the nonsense in MSDN
4466c2c66affSColin Finck    * about setting the length to -1 for multiline edit controls doesn't happen.
4467c2c66affSColin Finck    */
4468c2c66affSColin Finck 
4469c2c66affSColin Finck   /* Don't check default gettextlimit case. That's done in other tests */
4470c2c66affSColin Finck 
4471c2c66affSColin Finck   /* Set textlimit to 100 */
4472c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_LIMITTEXT, 100, 0);
4473c2c66affSColin Finck   ret = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4474c2c66affSColin Finck   ok (ret == 100,
4475c2c66affSColin Finck       "EM_LIMITTEXT: set to 100, returned: %d, expected: 100\n", ret);
4476c2c66affSColin Finck 
4477c2c66affSColin Finck   /* Set textlimit to 0 */
4478c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_LIMITTEXT, 0, 0);
4479c2c66affSColin Finck   ret = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4480c2c66affSColin Finck   ok (ret == 65536,
4481c2c66affSColin Finck       "EM_LIMITTEXT: set to 0, returned: %d, expected: 65536\n", ret);
4482c2c66affSColin Finck 
4483c2c66affSColin Finck   /* Set textlimit to -1 */
4484c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_LIMITTEXT, -1, 0);
4485c2c66affSColin Finck   ret = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4486c2c66affSColin Finck   ok (ret == -1,
4487c2c66affSColin Finck       "EM_LIMITTEXT: set to -1, returned: %d, expected: -1\n", ret);
4488c2c66affSColin Finck 
4489c2c66affSColin Finck   /* Set textlimit to -2 */
4490c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_LIMITTEXT, -2, 0);
4491c2c66affSColin Finck   ret = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4492c2c66affSColin Finck   ok (ret == -2,
4493c2c66affSColin Finck       "EM_LIMITTEXT: set to -2, returned: %d, expected: -2\n", ret);
4494c2c66affSColin Finck 
4495c2c66affSColin Finck   DestroyWindow (hwndRichEdit);
4496c2c66affSColin Finck }
4497c2c66affSColin Finck 
4498c2c66affSColin Finck 
test_EM_EXLIMITTEXT(void)4499c2c66affSColin Finck static void test_EM_EXLIMITTEXT(void)
4500c2c66affSColin Finck {
4501c2c66affSColin Finck   int i, selBegin, selEnd, len1, len2;
4502c2c66affSColin Finck   int result;
4503c2c66affSColin Finck   char text[1024 + 1];
4504c2c66affSColin Finck   char buffer[1024 + 1];
4505c2c66affSColin Finck   int textlimit = 0; /* multiple of 100 */
4506c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
4507c2c66affSColin Finck 
4508c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4509c2c66affSColin Finck   ok(32767 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 32767, i); /* default */
4510c2c66affSColin Finck 
4511c2c66affSColin Finck   textlimit = 256000;
4512c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
4513c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4514c2c66affSColin Finck   /* set higher */
4515c2c66affSColin Finck   ok(textlimit == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", textlimit, i);
4516c2c66affSColin Finck 
4517c2c66affSColin Finck   textlimit = 1000;
4518c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
4519c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4520c2c66affSColin Finck   /* set lower */
4521c2c66affSColin Finck   ok(textlimit == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", textlimit, i);
4522c2c66affSColin Finck 
4523c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, 0);
4524c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4525c2c66affSColin Finck   /* default for WParam = 0 */
4526c2c66affSColin Finck   ok(65536 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 65536, i);
4527c2c66affSColin Finck 
4528c2c66affSColin Finck   textlimit = sizeof(text)-1;
4529c2c66affSColin Finck   memset(text, 'W', textlimit);
4530c2c66affSColin Finck   text[sizeof(text)-1] = 0;
4531c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
4532c2c66affSColin Finck   /* maxed out text */
4533c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
4534c2c66affSColin Finck 
4535c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);  /* select everything */
4536c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
4537c2c66affSColin Finck   len1 = selEnd - selBegin;
4538c2c66affSColin Finck 
4539c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYDOWN, VK_BACK, 1);
4540c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CHAR, VK_BACK, 1);
4541c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYUP, VK_BACK, 1);
4542c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4543c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
4544c2c66affSColin Finck   len2 = selEnd - selBegin;
4545c2c66affSColin Finck 
4546c2c66affSColin Finck   ok(len1 != len2,
4547c2c66affSColin Finck     "EM_EXLIMITTEXT: Change Expected\nOld Length: %d, New Length: %d, Limit: %d\n",
4548c2c66affSColin Finck     len1,len2,i);
4549c2c66affSColin Finck 
4550c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYDOWN, 'A', 1);
4551c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CHAR, 'A', 1);
4552c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYUP, 'A', 1);
4553c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4554c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
4555c2c66affSColin Finck   len1 = selEnd - selBegin;
4556c2c66affSColin Finck 
4557c2c66affSColin Finck   ok(len1 != len2,
4558c2c66affSColin Finck     "EM_EXLIMITTEXT: Change Expected\nOld Length: %d, New Length: %d, Limit: %d\n",
4559c2c66affSColin Finck     len1,len2,i);
4560c2c66affSColin Finck 
4561c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYDOWN, 'A', 1);
4562c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CHAR, 'A', 1);
4563c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYUP, 'A', 1);  /* full; should be no effect */
4564c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4565c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
4566c2c66affSColin Finck   len2 = selEnd - selBegin;
4567c2c66affSColin Finck 
4568c2c66affSColin Finck   ok(len1 == len2,
4569c2c66affSColin Finck     "EM_EXLIMITTEXT: No Change Expected\nOld Length: %d, New Length: %d, Limit: %d\n",
4570c2c66affSColin Finck     len1,len2,i);
4571c2c66affSColin Finck 
4572c2c66affSColin Finck   /* set text up to the limit, select all the text, then add a char */
4573c2c66affSColin Finck   textlimit = 5;
4574c2c66affSColin Finck   memset(text, 'W', textlimit);
4575c2c66affSColin Finck   text[textlimit] = 0;
4576c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
4577c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
4578c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
4579c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CHAR, 'A', 1);
4580c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
4581c2c66affSColin Finck   result = strcmp(buffer, "A");
4582c2c66affSColin Finck   ok(0 == result, "got string = \"%s\"\n", buffer);
4583c2c66affSColin Finck 
4584c2c66affSColin Finck   /* WM_SETTEXT not limited */
4585c2c66affSColin Finck   textlimit = 10;
4586c2c66affSColin Finck   memset(text, 'W', textlimit);
4587c2c66affSColin Finck   text[textlimit] = 0;
4588c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit-5);
4589c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
4590c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
4591c2c66affSColin Finck   i = strlen(buffer);
4592c2c66affSColin Finck   ok(10 == i, "expected 10 chars\n");
4593c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4594c2c66affSColin Finck   ok(10 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 10, i);
4595c2c66affSColin Finck 
4596c2c66affSColin Finck   /* try inserting more text at end */
4597c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, WM_CHAR, 'A', 0);
4598c2c66affSColin Finck   ok(0 == i, "WM_CHAR wasn't processed\n");
4599c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
4600c2c66affSColin Finck   i = strlen(buffer);
4601c2c66affSColin Finck   ok(10 == i, "expected 10 chars, got %i\n", i);
4602c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4603c2c66affSColin Finck   ok(10 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 10, i);
4604c2c66affSColin Finck 
4605c2c66affSColin Finck   /* try inserting text at beginning */
4606c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 0);
4607c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, WM_CHAR, 'A', 0);
4608c2c66affSColin Finck   ok(0 == i, "WM_CHAR wasn't processed\n");
4609c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
4610c2c66affSColin Finck   i = strlen(buffer);
4611c2c66affSColin Finck   ok(10 == i, "expected 10 chars, got %i\n", i);
4612c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4613c2c66affSColin Finck   ok(10 == i, "EM_EXLIMITTEXT: expected: %d, actual: %d\n", 10, i);
4614c2c66affSColin Finck 
4615c2c66affSColin Finck   /* WM_CHAR is limited */
4616c2c66affSColin Finck   textlimit = 1;
4617c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, textlimit);
4618c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);  /* select everything */
4619c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, WM_CHAR, 'A', 0);
4620c2c66affSColin Finck   ok(0 == i, "WM_CHAR wasn't processed\n");
4621c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, WM_CHAR, 'A', 0);
4622c2c66affSColin Finck   ok(0 == i, "WM_CHAR wasn't processed\n");
4623c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
4624c2c66affSColin Finck   i = strlen(buffer);
4625c2c66affSColin Finck   ok(1 == i, "expected 1 chars, got %i instead\n", i);
4626c2c66affSColin Finck 
4627c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
4628c2c66affSColin Finck }
4629c2c66affSColin Finck 
test_EM_GETLIMITTEXT(void)4630c2c66affSColin Finck static void test_EM_GETLIMITTEXT(void)
4631c2c66affSColin Finck {
4632c2c66affSColin Finck   int i;
4633c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
4634c2c66affSColin Finck 
4635c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4636c2c66affSColin Finck   ok(32767 == i, "expected: %d, actual: %d\n", 32767, i); /* default value */
4637c2c66affSColin Finck 
4638c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_EXLIMITTEXT, 0, 50000);
4639c2c66affSColin Finck   i = SendMessageA(hwndRichEdit, EM_GETLIMITTEXT, 0, 0);
4640c2c66affSColin Finck   ok(50000 == i, "expected: %d, actual: %d\n", 50000, i);
4641c2c66affSColin Finck 
4642c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
4643c2c66affSColin Finck }
4644c2c66affSColin Finck 
test_WM_SETFONT(void)4645c2c66affSColin Finck static void test_WM_SETFONT(void)
4646c2c66affSColin Finck {
4647c2c66affSColin Finck   /* There is no invalid input or error conditions for this function.
4648c2c66affSColin Finck    * NULL wParam and lParam just fall back to their default values
4649c2c66affSColin Finck    * It should be noted that even if you use a gibberish name for your fonts
4650c2c66affSColin Finck    * here, it will still work because the name is stored. They will display as
4651c2c66affSColin Finck    * System, but will report their name to be whatever they were created as */
4652c2c66affSColin Finck 
4653c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
4654c2c66affSColin Finck   HFONT testFont1 = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
4655c2c66affSColin Finck     OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
4656c2c66affSColin Finck     FF_DONTCARE, "Marlett");
4657c2c66affSColin Finck   HFONT testFont2 = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
4658c2c66affSColin Finck     OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
4659c2c66affSColin Finck     FF_DONTCARE, "MS Sans Serif");
4660c2c66affSColin Finck   HFONT testFont3 = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
4661c2c66affSColin Finck     OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
4662c2c66affSColin Finck     FF_DONTCARE, "Courier");
4663c2c66affSColin Finck   LOGFONTA sentLogFont;
4664c2c66affSColin Finck   CHARFORMAT2A returnedCF2A;
4665c2c66affSColin Finck 
4666c2c66affSColin Finck   returnedCF2A.cbSize = sizeof(returnedCF2A);
4667c2c66affSColin Finck 
4668c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"x");
4669c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETFONT, (WPARAM)testFont1, MAKELPARAM(TRUE, 0));
4670c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT,   SCF_DEFAULT,  (LPARAM)&returnedCF2A);
4671c2c66affSColin Finck 
4672c2c66affSColin Finck   GetObjectA(testFont1, sizeof(LOGFONTA), &sentLogFont);
4673c2c66affSColin Finck   ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
4674c2c66affSColin Finck     "EM_GETCHARFORMAT: Returned wrong font on test 1. Sent: %s, Returned: %s\n",
4675c2c66affSColin Finck     sentLogFont.lfFaceName,returnedCF2A.szFaceName);
4676c2c66affSColin Finck 
4677c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETFONT, (WPARAM)testFont2, MAKELPARAM(TRUE, 0));
4678c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT,   SCF_DEFAULT,  (LPARAM)&returnedCF2A);
4679c2c66affSColin Finck   GetObjectA(testFont2, sizeof(LOGFONTA), &sentLogFont);
4680c2c66affSColin Finck   ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
4681c2c66affSColin Finck     "EM_GETCHARFORMAT: Returned wrong font on test 2. Sent: %s, Returned: %s\n",
4682c2c66affSColin Finck     sentLogFont.lfFaceName,returnedCF2A.szFaceName);
4683c2c66affSColin Finck 
4684c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETFONT, (WPARAM)testFont3, MAKELPARAM(TRUE, 0));
4685c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT,   SCF_DEFAULT,  (LPARAM)&returnedCF2A);
4686c2c66affSColin Finck   GetObjectA(testFont3, sizeof(LOGFONTA), &sentLogFont);
4687c2c66affSColin Finck   ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
4688c2c66affSColin Finck     "EM_GETCHARFORMAT: Returned wrong font on test 3. Sent: %s, Returned: %s\n",
4689c2c66affSColin Finck     sentLogFont.lfFaceName,returnedCF2A.szFaceName);
4690c2c66affSColin Finck 
4691c2c66affSColin Finck   /* This last test is special since we send in NULL. We clear the variables
4692c2c66affSColin Finck    * and just compare to "System" instead of the sent in font name. */
4693c2c66affSColin Finck   ZeroMemory(&returnedCF2A,sizeof(returnedCF2A));
4694c2c66affSColin Finck   ZeroMemory(&sentLogFont,sizeof(sentLogFont));
4695c2c66affSColin Finck   returnedCF2A.cbSize = sizeof(returnedCF2A);
4696c2c66affSColin Finck 
4697c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETFONT, 0, MAKELPARAM((WORD) TRUE, 0));
4698c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT,   SCF_DEFAULT,  (LPARAM)&returnedCF2A);
4699c2c66affSColin Finck   GetObjectA(NULL, sizeof(LOGFONTA), &sentLogFont);
4700c2c66affSColin Finck   ok (!strcmp("System",returnedCF2A.szFaceName),
4701c2c66affSColin Finck     "EM_GETCHARFORMAT: Returned wrong font on test 4. Sent: NULL, Returned: %s. Expected \"System\".\n",returnedCF2A.szFaceName);
4702c2c66affSColin Finck 
4703c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
4704c2c66affSColin Finck }
4705c2c66affSColin Finck 
4706c2c66affSColin Finck 
test_EM_GETMODIFY_esCallback(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)4707c2c66affSColin Finck static DWORD CALLBACK test_EM_GETMODIFY_esCallback(DWORD_PTR dwCookie,
4708c2c66affSColin Finck                                          LPBYTE pbBuff,
4709c2c66affSColin Finck                                          LONG cb,
4710c2c66affSColin Finck                                          LONG *pcb)
4711c2c66affSColin Finck {
4712c2c66affSColin Finck   const char** str = (const char**)dwCookie;
4713c2c66affSColin Finck   int size = strlen(*str);
4714c2c66affSColin Finck   if(size > 3)  /* let's make it piecemeal for fun */
4715c2c66affSColin Finck     size = 3;
4716c2c66affSColin Finck   *pcb = cb;
4717c2c66affSColin Finck   if (*pcb > size) {
4718c2c66affSColin Finck     *pcb = size;
4719c2c66affSColin Finck   }
4720c2c66affSColin Finck   if (*pcb > 0) {
4721c2c66affSColin Finck     memcpy(pbBuff, *str, *pcb);
4722c2c66affSColin Finck     *str += *pcb;
4723c2c66affSColin Finck   }
4724c2c66affSColin Finck   return 0;
4725c2c66affSColin Finck }
4726c2c66affSColin Finck 
test_EM_GETMODIFY(void)4727c2c66affSColin Finck static void test_EM_GETMODIFY(void)
4728c2c66affSColin Finck {
4729c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
4730c2c66affSColin Finck   LRESULT result;
4731c2c66affSColin Finck   SETTEXTEX setText;
4732c2c66affSColin Finck   WCHAR TestItem1[] = {'T', 'e', 's', 't',
4733c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4734c2c66affSColin Finck                        'T', 'e', 'x', 't', 0};
4735c2c66affSColin Finck   WCHAR TestItem2[] = {'T', 'e', 's', 't',
4736c2c66affSColin Finck                        'S', 'o', 'm', 'e',
4737c2c66affSColin Finck                        'O', 't', 'h', 'e', 'r',
4738c2c66affSColin Finck                        'T', 'e', 'x', 't', 0};
4739c2c66affSColin Finck   const char* streamText = "hello world";
4740c2c66affSColin Finck   CHARFORMAT2A cf2;
4741c2c66affSColin Finck   PARAFORMAT2 pf2;
4742c2c66affSColin Finck   EDITSTREAM es;
4743c2c66affSColin Finck 
4744c2c66affSColin Finck   HFONT testFont = CreateFontA (0,0,0,0,FW_LIGHT, 0, 0, 0, ANSI_CHARSET,
4745c2c66affSColin Finck     OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
4746c2c66affSColin Finck     FF_DONTCARE, "Courier");
4747c2c66affSColin Finck 
4748c2c66affSColin Finck   setText.codepage = 1200;  /* no constant for unicode */
4749c2c66affSColin Finck   setText.flags = ST_KEEPUNDO;
4750c2c66affSColin Finck 
4751c2c66affSColin Finck 
4752c2c66affSColin Finck   /* modify flag shouldn't be set when richedit is first created */
4753c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4754c2c66affSColin Finck   ok (result == 0,
4755c2c66affSColin Finck       "EM_GETMODIFY returned non-zero, instead of zero on create\n");
4756c2c66affSColin Finck 
4757c2c66affSColin Finck   /* setting modify flag should actually set it */
4758c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, TRUE, 0);
4759c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4760c2c66affSColin Finck   ok (result != 0,
4761c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero on EM_SETMODIFY\n");
4762c2c66affSColin Finck 
4763c2c66affSColin Finck   /* clearing modify flag should actually clear it */
4764c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4765c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4766c2c66affSColin Finck   ok (result == 0,
4767c2c66affSColin Finck       "EM_GETMODIFY returned non-zero, instead of zero on EM_SETMODIFY\n");
4768c2c66affSColin Finck 
4769c2c66affSColin Finck   /* setting font doesn't change modify flag */
4770c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4771c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETFONT, (WPARAM)testFont, MAKELPARAM(TRUE, 0));
4772c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4773c2c66affSColin Finck   ok (result == 0,
4774c2c66affSColin Finck       "EM_GETMODIFY returned non-zero, instead of zero on setting font\n");
4775c2c66affSColin Finck 
4776c2c66affSColin Finck   /* setting text should set modify flag */
4777c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4778c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4779c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4780c2c66affSColin Finck   ok (result != 0,
4781c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero on setting text\n");
4782c2c66affSColin Finck 
4783c2c66affSColin Finck   /* undo previous text doesn't reset modify flag */
4784c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_UNDO, 0, 0);
4785c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4786c2c66affSColin Finck   ok (result != 0,
4787c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero on undo after setting text\n");
4788c2c66affSColin Finck 
4789c2c66affSColin Finck   /* set text with no flag to keep undo stack should not set modify flag */
4790c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4791c2c66affSColin Finck   setText.flags = 0;
4792c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4793c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4794c2c66affSColin Finck   ok (result == 0,
4795c2c66affSColin Finck       "EM_GETMODIFY returned non-zero, instead of zero when setting text while not keeping undo stack\n");
4796c2c66affSColin Finck 
4797c2c66affSColin Finck   /* WM_SETTEXT doesn't modify */
4798c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4799c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)TestItem2);
4800c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4801c2c66affSColin Finck   ok (result == 0,
4802c2c66affSColin Finck       "EM_GETMODIFY returned non-zero for WM_SETTEXT\n");
4803c2c66affSColin Finck 
4804c2c66affSColin Finck   /* clear the text */
4805c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4806c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CLEAR, 0, 0);
4807c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4808c2c66affSColin Finck   ok (result == 0,
4809c2c66affSColin Finck       "EM_GETMODIFY returned non-zero, instead of zero for WM_CLEAR\n");
4810c2c66affSColin Finck 
4811c2c66affSColin Finck   /* replace text */
4812c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4813c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)TestItem1);
4814c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
4815c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_REPLACESEL, TRUE, (LPARAM)TestItem2);
4816c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4817c2c66affSColin Finck   ok (result != 0,
4818c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero when replacing text\n");
4819c2c66affSColin Finck 
4820c2c66affSColin Finck   /* copy/paste text 1 */
4821c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4822c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
4823c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
4824c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
4825c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4826c2c66affSColin Finck   ok (result != 0,
4827c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero when pasting identical text\n");
4828c2c66affSColin Finck 
4829c2c66affSColin Finck   /* copy/paste text 2 */
4830c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4831c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 2);
4832c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
4833c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 3);
4834c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
4835c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4836c2c66affSColin Finck   ok (result != 0,
4837c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero when pasting different text\n");
4838c2c66affSColin Finck 
4839c2c66affSColin Finck   /* press char */
4840c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4841c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL, 0, 1);
4842c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CHAR, 'A', 0);
4843c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4844c2c66affSColin Finck   ok (result != 0,
4845c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero for WM_CHAR\n");
4846c2c66affSColin Finck 
4847c2c66affSColin Finck   /* press del */
4848c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_CHAR, 'A', 0);
4849c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4850c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_KEYDOWN, VK_BACK, 0);
4851c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4852c2c66affSColin Finck   ok (result != 0,
4853c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero for backspace\n");
4854c2c66affSColin Finck 
4855c2c66affSColin Finck   /* set char format */
4856c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4857c2c66affSColin Finck   cf2.cbSize = sizeof(CHARFORMAT2A);
4858c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2);
4859c2c66affSColin Finck   cf2.dwMask = CFM_ITALIC | cf2.dwMask;
4860c2c66affSColin Finck   cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
4861c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf2);
4862c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf2);
4863c2c66affSColin Finck   ok(result == 1, "EM_SETCHARFORMAT returned %ld instead of 1\n", result);
4864c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4865c2c66affSColin Finck   ok (result != 0,
4866c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero for EM_SETCHARFORMAT\n");
4867c2c66affSColin Finck 
4868c2c66affSColin Finck   /* set para format */
4869c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4870c2c66affSColin Finck   pf2.cbSize = sizeof(PARAFORMAT2);
4871c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&pf2);
4872c2c66affSColin Finck   pf2.dwMask = PFM_ALIGNMENT | pf2.dwMask;
4873c2c66affSColin Finck   pf2.wAlignment = PFA_RIGHT;
4874c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
4875c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4876c2c66affSColin Finck   ok (result == 0,
4877c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero for EM_SETPARAFORMAT\n");
4878c2c66affSColin Finck 
4879c2c66affSColin Finck   /* EM_STREAM */
4880c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
4881c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamText;
4882c2c66affSColin Finck   es.dwError = 0;
4883c2c66affSColin Finck   es.pfnCallback = test_EM_GETMODIFY_esCallback;
4884c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es);
4885c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETMODIFY, 0, 0);
4886c2c66affSColin Finck   ok (result != 0,
4887c2c66affSColin Finck       "EM_GETMODIFY returned zero, instead of non-zero for EM_STREAM\n");
4888c2c66affSColin Finck 
4889c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
4890c2c66affSColin Finck }
4891c2c66affSColin Finck 
4892c2c66affSColin Finck struct exsetsel_s {
4893c2c66affSColin Finck   LONG min;
4894c2c66affSColin Finck   LONG max;
4895c2c66affSColin Finck   LRESULT expected_retval;
4896c2c66affSColin Finck   int expected_getsel_start;
4897c2c66affSColin Finck   int expected_getsel_end;
4898c2c66affSColin Finck   BOOL todo;
4899c2c66affSColin Finck };
4900c2c66affSColin Finck 
4901c2c66affSColin Finck static const struct exsetsel_s exsetsel_tests[] = {
4902c2c66affSColin Finck   /* sanity tests */
4903c2c66affSColin Finck   {5, 10, 10, 5, 10 },
4904c2c66affSColin Finck   {15, 17, 17, 15, 17 },
4905c2c66affSColin Finck   /* test cpMax > strlen() */
4906c2c66affSColin Finck   {0, 100, 18, 0, 18 },
4907c2c66affSColin Finck   /* test cpMin < 0 && cpMax >= 0 after cpMax > strlen() */
4908c2c66affSColin Finck   {-1, 1, 17, 17, 17 },
4909c2c66affSColin Finck   /* test cpMin == cpMax */
4910c2c66affSColin Finck   {5, 5, 5, 5, 5 },
4911c2c66affSColin Finck   /* test cpMin < 0 && cpMax >= 0 (bug 4462) */
4912c2c66affSColin Finck   {-1, 0, 5, 5, 5 },
4913c2c66affSColin Finck   {-1, 17, 5, 5, 5 },
4914c2c66affSColin Finck   {-1, 18, 5, 5, 5 },
4915c2c66affSColin Finck   /* test cpMin < 0 && cpMax < 0 */
4916c2c66affSColin Finck   {-1, -1, 17, 17, 17 },
4917c2c66affSColin Finck   {-4, -5, 17, 17, 17 },
4918c2c66affSColin Finck   /* test cpMin >=0 && cpMax < 0 (bug 6814) */
4919c2c66affSColin Finck   {0, -1, 18, 0, 18 },
4920c2c66affSColin Finck   {17, -5, 18, 17, 18 },
4921c2c66affSColin Finck   {18, -3, 17, 17, 17 },
4922c2c66affSColin Finck   /* test if cpMin > cpMax */
4923c2c66affSColin Finck   {15, 19, 18, 15, 18 },
4924c2c66affSColin Finck   {19, 15, 18, 15, 18 },
4925c2c66affSColin Finck   /* cpMin == strlen() && cpMax > cpMin */
4926c2c66affSColin Finck   {17, 18, 18, 17, 18 },
4927c2c66affSColin Finck   {17, 50, 18, 17, 18 },
4928c2c66affSColin Finck };
4929c2c66affSColin Finck 
check_EM_EXSETSEL(HWND hwnd,const struct exsetsel_s * setsel,int id)4930c2c66affSColin Finck static void check_EM_EXSETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id) {
4931c2c66affSColin Finck     CHARRANGE cr;
4932c2c66affSColin Finck     LRESULT result;
4933c2c66affSColin Finck     int start, end;
4934c2c66affSColin Finck 
4935c2c66affSColin Finck     cr.cpMin = setsel->min;
4936c2c66affSColin Finck     cr.cpMax = setsel->max;
4937c2c66affSColin Finck     result = SendMessageA(hwnd, EM_EXSETSEL, 0, (LPARAM)&cr);
4938c2c66affSColin Finck 
4939c2c66affSColin Finck     ok(result == setsel->expected_retval, "EM_EXSETSEL(%d): expected: %ld actual: %ld\n", id, setsel->expected_retval, result);
4940c2c66affSColin Finck 
4941c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
4942c2c66affSColin Finck 
4943c2c66affSColin Finck     todo_wine_if (setsel->todo)
4944c2c66affSColin Finck         ok(start == setsel->expected_getsel_start && end == setsel->expected_getsel_end, "EM_EXSETSEL(%d): expected (%d,%d) actual:(%d,%d)\n",
4945c2c66affSColin Finck             id, setsel->expected_getsel_start, setsel->expected_getsel_end, start, end);
4946c2c66affSColin Finck }
4947c2c66affSColin Finck 
test_EM_EXSETSEL(void)4948c2c66affSColin Finck static void test_EM_EXSETSEL(void)
4949c2c66affSColin Finck {
4950c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
4951c2c66affSColin Finck     int i;
495276cf09cfSAmine Khaldi     const int num_tests = ARRAY_SIZE(exsetsel_tests);
4953c2c66affSColin Finck 
4954c2c66affSColin Finck     /* sending some text to the window */
4955c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"testing selection");
4956c2c66affSColin Finck     /*                                                 01234567890123456*/
4957c2c66affSColin Finck     /*                                                          10      */
4958c2c66affSColin Finck 
4959c2c66affSColin Finck     for (i = 0; i < num_tests; i++) {
4960c2c66affSColin Finck         check_EM_EXSETSEL(hwndRichEdit, &exsetsel_tests[i], i);
4961c2c66affSColin Finck     }
4962c2c66affSColin Finck 
4963c2c66affSColin Finck     if (!is_lang_japanese)
4964c2c66affSColin Finck         skip("Skip multibyte character tests on non-Japanese platform\n");
4965c2c66affSColin Finck     else
4966c2c66affSColin Finck     {
4967c2c66affSColin Finck         CHARRANGE cr;
4968c2c66affSColin Finck         char bufA[MAX_BUF_LEN] = {0};
4969c2c66affSColin Finck         LRESULT result;
4970c2c66affSColin Finck 
4971c2c66affSColin Finck         /* Test with multibyte character */
4972c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
4973c2c66affSColin Finck         /*                                                 012345     6  78901 */
497476cf09cfSAmine Khaldi         cr.cpMin = 4; cr.cpMax = 8;
4975c2c66affSColin Finck         result =  SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
4976c2c66affSColin Finck         ok(result == 8, "EM_EXSETSEL return %ld expected 8\n", result);
4977c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, sizeof(bufA), (LPARAM)bufA);
4978c2c66affSColin Finck         ok(!strcmp(bufA, "ef\x8e\xf0g"), "EM_GETSELTEXT return incorrect string\n");
4979c2c66affSColin Finck         SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
4980c2c66affSColin Finck         ok(cr.cpMin == 4, "Selection start incorrectly: %d expected 4\n", cr.cpMin);
4981c2c66affSColin Finck         ok(cr.cpMax == 8, "Selection end incorrectly: %d expected 8\n", cr.cpMax);
4982c2c66affSColin Finck     }
4983c2c66affSColin Finck 
4984c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
4985c2c66affSColin Finck }
4986c2c66affSColin Finck 
check_EM_SETSEL(HWND hwnd,const struct exsetsel_s * setsel,int id)4987c2c66affSColin Finck static void check_EM_SETSEL(HWND hwnd, const struct exsetsel_s *setsel, int id) {
4988c2c66affSColin Finck     LRESULT result;
4989c2c66affSColin Finck     int start, end;
4990c2c66affSColin Finck 
4991c2c66affSColin Finck     result = SendMessageA(hwnd, EM_SETSEL, setsel->min, setsel->max);
4992c2c66affSColin Finck 
4993c2c66affSColin Finck     ok(result == setsel->expected_retval, "EM_SETSEL(%d): expected: %ld actual: %ld\n", id, setsel->expected_retval, result);
4994c2c66affSColin Finck 
4995c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
4996c2c66affSColin Finck 
4997c2c66affSColin Finck     todo_wine_if (setsel->todo)
4998c2c66affSColin Finck         ok(start == setsel->expected_getsel_start && end == setsel->expected_getsel_end, "EM_SETSEL(%d): expected (%d,%d) actual:(%d,%d)\n",
4999c2c66affSColin Finck             id, setsel->expected_getsel_start, setsel->expected_getsel_end, start, end);
5000c2c66affSColin Finck }
5001c2c66affSColin Finck 
test_EM_SETSEL(void)5002c2c66affSColin Finck static void test_EM_SETSEL(void)
5003c2c66affSColin Finck {
5004c2c66affSColin Finck     char buffA[32] = {0};
5005c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
5006c2c66affSColin Finck     int i;
500776cf09cfSAmine Khaldi     const int num_tests = ARRAY_SIZE(exsetsel_tests);
5008c2c66affSColin Finck 
5009c2c66affSColin Finck     /* sending some text to the window */
5010c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"testing selection");
5011c2c66affSColin Finck     /*                                                 01234567890123456*/
5012c2c66affSColin Finck     /*                                                          10      */
5013c2c66affSColin Finck 
5014c2c66affSColin Finck     for (i = 0; i < num_tests; i++) {
5015c2c66affSColin Finck         check_EM_SETSEL(hwndRichEdit, &exsetsel_tests[i], i);
5016c2c66affSColin Finck     }
5017c2c66affSColin Finck 
5018c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 17, 18);
5019c2c66affSColin Finck     buffA[0] = 123;
5020c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffA);
5021c2c66affSColin Finck     ok(buffA[0] == 0, "selection text %s\n", buffA);
5022c2c66affSColin Finck 
5023c2c66affSColin Finck     if (!is_lang_japanese)
5024c2c66affSColin Finck         skip("Skip multibyte character tests on non-Japanese platform\n");
5025c2c66affSColin Finck     else
5026c2c66affSColin Finck     {
5027c2c66affSColin Finck         int sel_start, sel_end;
5028c2c66affSColin Finck         LRESULT result;
5029c2c66affSColin Finck 
5030c2c66affSColin Finck         /* Test with multibyte character */
5031c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk");
5032c2c66affSColin Finck         /*                                                 012345     6  78901 */
5033c2c66affSColin Finck         result =  SendMessageA(hwndRichEdit, EM_SETSEL, 4, 8);
5034c2c66affSColin Finck         ok(result == 8, "EM_SETSEL return %ld expected 8\n", result);
5035c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, sizeof(buffA), (LPARAM)buffA);
5036c2c66affSColin Finck         ok(!strcmp(buffA, "ef\x8e\xf0g"), "EM_GETSELTEXT return incorrect string\n");
5037c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
5038c2c66affSColin Finck         ok(sel_start == 4, "Selection start incorrectly: %d expected 4\n", sel_start);
5039c2c66affSColin Finck         ok(sel_end == 8, "Selection end incorrectly: %d expected 8\n", sel_end);
5040c2c66affSColin Finck     }
5041c2c66affSColin Finck 
5042c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
5043c2c66affSColin Finck }
5044c2c66affSColin Finck 
test_EM_REPLACESEL(int redraw)5045c2c66affSColin Finck static void test_EM_REPLACESEL(int redraw)
5046c2c66affSColin Finck {
5047c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
5048c2c66affSColin Finck     char buffer[1024] = {0};
5049c2c66affSColin Finck     int r;
5050c2c66affSColin Finck     GETTEXTEX getText;
5051c2c66affSColin Finck     CHARRANGE cr;
5052c2c66affSColin Finck     CHAR rtfstream[] = "{\\rtf1 TestSomeText}";
5053c2c66affSColin Finck     CHAR urtfstream[] = "{\\urtf1 TestSomeText}";
5054c2c66affSColin Finck 
5055c2c66affSColin Finck     /* sending some text to the window */
5056c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"testing selection");
5057c2c66affSColin Finck     /*                                                 01234567890123456*/
5058c2c66affSColin Finck     /*                                                          10      */
5059c2c66affSColin Finck 
5060c2c66affSColin Finck     /* FIXME add more tests */
5061c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 7, 17);
5062c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, 0);
5063c2c66affSColin Finck     ok(0 == r, "EM_REPLACESEL returned %d, expected 0\n", r);
5064c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5065c2c66affSColin Finck     r = strcmp(buffer, "testing");
5066c2c66affSColin Finck     ok(0 == r, "expected %d, got %d\n", 0, r);
5067c2c66affSColin Finck 
5068c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
5069c2c66affSColin Finck 
5070c2c66affSColin Finck     hwndRichEdit = new_richedit(NULL);
5071c2c66affSColin Finck 
5072c2c66affSColin Finck     trace("Testing EM_REPLACESEL behavior with redraw=%d\n", redraw);
5073c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETREDRAW, redraw, 0);
5074c2c66affSColin Finck 
5075c2c66affSColin Finck     /* Test behavior with carriage returns and newlines */
5076c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5077c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"RichEdit1");
5078c2c66affSColin Finck     ok(9 == r, "EM_REPLACESEL returned %d, expected 9\n", r);
5079c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5080c2c66affSColin Finck     r = strcmp(buffer, "RichEdit1");
5081c2c66affSColin Finck     ok(0 == r, "expected %d, got %d\n", 0, r);
5082c2c66affSColin Finck     getText.cb = 1024;
5083c2c66affSColin Finck     getText.codepage = CP_ACP;
5084c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5085c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5086c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5087c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5088c2c66affSColin Finck     ok(strcmp(buffer, "RichEdit1") == 0,
5089c2c66affSColin Finck       "EM_GETTEXTEX results not what was set by EM_REPLACESEL\n");
5090c2c66affSColin Finck 
5091c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5092c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5093c2c66affSColin Finck     ok(r == 1, "EM_GETLINECOUNT returned %d, expected 1\n", r);
5094c2c66affSColin Finck 
5095c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5096c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"RichEdit1\r");
5097c2c66affSColin Finck     ok(10 == r, "EM_REPLACESEL returned %d, expected 10\n", r);
5098c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5099c2c66affSColin Finck     r = strcmp(buffer, "RichEdit1\r\n");
5100c2c66affSColin Finck     ok(0 == r, "expected %d, got %d\n", 0, r);
5101c2c66affSColin Finck     getText.cb = 1024;
5102c2c66affSColin Finck     getText.codepage = CP_ACP;
5103c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5104c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5105c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5106c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5107c2c66affSColin Finck     ok(strcmp(buffer, "RichEdit1\r") == 0,
5108c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5109c2c66affSColin Finck 
5110c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5111c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5112c2c66affSColin Finck     ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
5113c2c66affSColin Finck 
5114c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5115c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"RichEdit1\r\n");
5116c2c66affSColin Finck     ok(r == 11, "EM_REPLACESEL returned %d, expected 11\n", r);
5117c2c66affSColin Finck 
5118c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5119c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5120c2c66affSColin Finck     ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
5121c2c66affSColin Finck 
5122c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5123c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5124c2c66affSColin Finck     ok(cr.cpMin == 10, "EM_EXGETSEL returned cpMin=%d, expected 10\n", cr.cpMin);
5125c2c66affSColin Finck     ok(cr.cpMax == 10, "EM_EXGETSEL returned cpMax=%d, expected 10\n", cr.cpMax);
5126c2c66affSColin Finck 
5127c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5128c2c66affSColin Finck     r = strcmp(buffer, "RichEdit1\r\n");
5129c2c66affSColin Finck     ok(0 == r, "expected %d, got %d\n", 0, r);
5130c2c66affSColin Finck     getText.cb = 1024;
5131c2c66affSColin Finck     getText.codepage = CP_ACP;
5132c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5133c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5134c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5135c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5136c2c66affSColin Finck     ok(strcmp(buffer, "RichEdit1\r") == 0,
5137c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5138c2c66affSColin Finck 
5139c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5140c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5141c2c66affSColin Finck     ok(cr.cpMin == 10, "EM_EXGETSEL returned cpMin=%d, expected 10\n", cr.cpMin);
5142c2c66affSColin Finck     ok(cr.cpMax == 10, "EM_EXGETSEL returned cpMax=%d, expected 10\n", cr.cpMax);
5143c2c66affSColin Finck 
5144c2c66affSColin Finck     /* The following tests show that richedit should handle the special \r\r\n
5145c2c66affSColin Finck        sequence by turning it into a single space on insertion. However,
5146c2c66affSColin Finck        EM_REPLACESEL on WinXP returns the number of characters in the original
5147c2c66affSColin Finck        string.
5148c2c66affSColin Finck      */
5149c2c66affSColin Finck 
5150c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5151c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\r\r");
5152c2c66affSColin Finck     ok(2 == r, "EM_REPLACESEL returned %d, expected 4\n", r);
5153c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5154c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5155c2c66affSColin Finck     ok(cr.cpMin == 2, "EM_EXGETSEL returned cpMin=%d, expected 2\n", cr.cpMin);
5156c2c66affSColin Finck     ok(cr.cpMax == 2, "EM_EXGETSEL returned cpMax=%d, expected 2\n", cr.cpMax);
5157c2c66affSColin Finck 
5158c2c66affSColin Finck     /* Test the actual string */
5159c2c66affSColin Finck     getText.cb = 1024;
5160c2c66affSColin Finck     getText.codepage = CP_ACP;
5161c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5162c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5163c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5164c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5165c2c66affSColin Finck     ok(strcmp(buffer, "\r\r") == 0,
5166c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5167c2c66affSColin Finck 
5168c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5169c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5170c2c66affSColin Finck     ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
5171c2c66affSColin Finck 
5172c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5173c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\r\r\n");
5174c2c66affSColin Finck     ok(r == 3, "EM_REPLACESEL returned %d, expected 3\n", r);
5175c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5176c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5177c2c66affSColin Finck     ok(cr.cpMin == 1, "EM_EXGETSEL returned cpMin=%d, expected 1\n", cr.cpMin);
5178c2c66affSColin Finck     ok(cr.cpMax == 1, "EM_EXGETSEL returned cpMax=%d, expected 1\n", cr.cpMax);
5179c2c66affSColin Finck 
5180c2c66affSColin Finck     /* Test the actual string */
5181c2c66affSColin Finck     getText.cb = 1024;
5182c2c66affSColin Finck     getText.codepage = CP_ACP;
5183c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5184c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5185c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5186c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5187c2c66affSColin Finck     ok(strcmp(buffer, " ") == 0,
5188c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5189c2c66affSColin Finck 
5190c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5191c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5192c2c66affSColin Finck     ok(r == 1, "EM_GETLINECOUNT returned %d, expected 1\n", r);
5193c2c66affSColin Finck 
5194c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5195c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\r\r\r\r\r\n\r\r\r");
5196c2c66affSColin Finck     ok(r == 9, "EM_REPLACESEL returned %d, expected 9\n", r);
5197c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5198c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5199c2c66affSColin Finck     ok(cr.cpMin == 7, "EM_EXGETSEL returned cpMin=%d, expected 7\n", cr.cpMin);
5200c2c66affSColin Finck     ok(cr.cpMax == 7, "EM_EXGETSEL returned cpMax=%d, expected 7\n", cr.cpMax);
5201c2c66affSColin Finck 
5202c2c66affSColin Finck     /* Test the actual string */
5203c2c66affSColin Finck     getText.cb = 1024;
5204c2c66affSColin Finck     getText.codepage = CP_ACP;
5205c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5206c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5207c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5208c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5209c2c66affSColin Finck     ok(strcmp(buffer, "\r\r\r \r\r\r") == 0,
5210c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5211c2c66affSColin Finck 
5212c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5213c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5214c2c66affSColin Finck     ok(r == 7, "EM_GETLINECOUNT returned %d, expected 7\n", r);
5215c2c66affSColin Finck 
5216c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5217c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\r\r\n\r\n");
5218c2c66affSColin Finck     ok(r == 5, "EM_REPLACESEL returned %d, expected 5\n", r);
5219c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5220c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5221c2c66affSColin Finck     ok(cr.cpMin == 2, "EM_EXGETSEL returned cpMin=%d, expected 2\n", cr.cpMin);
5222c2c66affSColin Finck     ok(cr.cpMax == 2, "EM_EXGETSEL returned cpMax=%d, expected 2\n", cr.cpMax);
5223c2c66affSColin Finck 
5224c2c66affSColin Finck     /* Test the actual string */
5225c2c66affSColin Finck     getText.cb = 1024;
5226c2c66affSColin Finck     getText.codepage = CP_ACP;
5227c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5228c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5229c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5230c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5231c2c66affSColin Finck     ok(strcmp(buffer, " \r") == 0,
5232c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5233c2c66affSColin Finck 
5234c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5235c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5236c2c66affSColin Finck     ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
5237c2c66affSColin Finck 
5238c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5239c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\r\r\n\r\r");
5240c2c66affSColin Finck     ok(r == 5, "EM_REPLACESEL returned %d, expected 5\n", r);
5241c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5242c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5243c2c66affSColin Finck     ok(cr.cpMin == 3, "EM_EXGETSEL returned cpMin=%d, expected 3\n", cr.cpMin);
5244c2c66affSColin Finck     ok(cr.cpMax == 3, "EM_EXGETSEL returned cpMax=%d, expected 3\n", cr.cpMax);
5245c2c66affSColin Finck 
5246c2c66affSColin Finck     /* Test the actual string */
5247c2c66affSColin Finck     getText.cb = 1024;
5248c2c66affSColin Finck     getText.codepage = CP_ACP;
5249c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5250c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5251c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5252c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5253c2c66affSColin Finck     ok(strcmp(buffer, " \r\r") == 0,
5254c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5255c2c66affSColin Finck 
5256c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5257c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5258c2c66affSColin Finck     ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
5259c2c66affSColin Finck 
5260c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5261c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\rX\r\n\r\r");
5262c2c66affSColin Finck     ok(r == 6, "EM_REPLACESEL returned %d, expected 6\n", r);
5263c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5264c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5265c2c66affSColin Finck     ok(cr.cpMin == 5, "EM_EXGETSEL returned cpMin=%d, expected 5\n", cr.cpMin);
5266c2c66affSColin Finck     ok(cr.cpMax == 5, "EM_EXGETSEL returned cpMax=%d, expected 5\n", cr.cpMax);
5267c2c66affSColin Finck 
5268c2c66affSColin Finck     /* Test the actual string */
5269c2c66affSColin Finck     getText.cb = 1024;
5270c2c66affSColin Finck     getText.codepage = CP_ACP;
5271c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5272c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5273c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5274c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5275c2c66affSColin Finck     ok(strcmp(buffer, "\rX\r\r\r") == 0,
5276c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5277c2c66affSColin Finck 
5278c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5279c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5280c2c66affSColin Finck     ok(r == 5, "EM_GETLINECOUNT returned %d, expected 5\n", r);
5281c2c66affSColin Finck 
5282c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5283c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\n\n");
5284c2c66affSColin Finck     ok(2 == r, "EM_REPLACESEL returned %d, expected 2\n", r);
5285c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5286c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5287c2c66affSColin Finck     ok(cr.cpMin == 2, "EM_EXGETSEL returned cpMin=%d, expected 2\n", cr.cpMin);
5288c2c66affSColin Finck     ok(cr.cpMax == 2, "EM_EXGETSEL returned cpMax=%d, expected 2\n", cr.cpMax);
5289c2c66affSColin Finck 
5290c2c66affSColin Finck     /* Test the actual string */
5291c2c66affSColin Finck     getText.cb = 1024;
5292c2c66affSColin Finck     getText.codepage = CP_ACP;
5293c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5294c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5295c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5296c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5297c2c66affSColin Finck     ok(strcmp(buffer, "\r\r") == 0,
5298c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5299c2c66affSColin Finck 
5300c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5301c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5302c2c66affSColin Finck     ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
5303c2c66affSColin Finck 
5304c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5305c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"\n\n\n\n\r\r\r\r\n");
5306c2c66affSColin Finck     ok(r == 9, "EM_REPLACESEL returned %d, expected 9\n", r);
5307c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5308c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5309c2c66affSColin Finck     ok(cr.cpMin == 7, "EM_EXGETSEL returned cpMin=%d, expected 7\n", cr.cpMin);
5310c2c66affSColin Finck     ok(cr.cpMax == 7, "EM_EXGETSEL returned cpMax=%d, expected 7\n", cr.cpMax);
5311c2c66affSColin Finck 
5312c2c66affSColin Finck     /* Test the actual string */
5313c2c66affSColin Finck     getText.cb = 1024;
5314c2c66affSColin Finck     getText.codepage = CP_ACP;
5315c2c66affSColin Finck     getText.flags = GT_DEFAULT;
5316c2c66affSColin Finck     getText.lpDefaultChar = NULL;
5317c2c66affSColin Finck     getText.lpUsedDefChar = NULL;
5318c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buffer);
5319c2c66affSColin Finck     ok(strcmp(buffer, "\r\r\r\r\r\r ") == 0,
5320c2c66affSColin Finck       "EM_GETTEXTEX returned incorrect string\n");
5321c2c66affSColin Finck 
5322c2c66affSColin Finck     /* Test number of lines reported after EM_REPLACESEL */
5323c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
5324c2c66affSColin Finck     ok(r == 7, "EM_GETLINECOUNT returned %d, expected 7\n", r);
5325c2c66affSColin Finck 
5326c2c66affSColin Finck     /* Test with  multibyte character */
5327c2c66affSColin Finck     if (!is_lang_japanese)
5328c2c66affSColin Finck         skip("Skip multibyte character tests on non-Japanese platform\n");
5329c2c66affSColin Finck     else
5330c2c66affSColin Finck     {
5331c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5332c2c66affSColin Finck         r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"abc\x8e\xf0");
5333c2c66affSColin Finck         todo_wine ok(r == 5, "EM_REPLACESEL returned %d, expected 5\n", r);
5334c2c66affSColin Finck         r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5335c2c66affSColin Finck         ok(r == 0, "EM_EXGETSEL returned %d, expected 0\n", r);
5336c2c66affSColin Finck         ok(cr.cpMin == 4, "EM_EXGETSEL returned cpMin=%d, expected 4\n", cr.cpMin);
5337c2c66affSColin Finck         ok(cr.cpMax == 4, "EM_EXGETSEL returned cpMax=%d, expected 4\n", cr.cpMax);
5338c2c66affSColin Finck         r = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5339c2c66affSColin Finck         ok(!strcmp(buffer, "abc\x8e\xf0"), "WM_GETTEXT returned incorrect string\n");
5340c2c66affSColin Finck         ok(r == 5, "WM_GETTEXT returned %d, expected 5\n", r);
5341c2c66affSColin Finck 
5342c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5343c2c66affSColin Finck         r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"{\\rtf abc\x8e\xf0}");
5344c2c66affSColin Finck         todo_wine ok(r == 4, "EM_REPLACESEL returned %d, expected 4\n", r);
5345c2c66affSColin Finck         r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5346c2c66affSColin Finck         ok(r == 0, "EM_EXGETSEL returned %d, expected 0\n", r);
5347c2c66affSColin Finck         todo_wine ok(cr.cpMin == 4, "EM_EXGETSEL returned cpMin=%d, expected 4\n", cr.cpMin);
5348c2c66affSColin Finck         todo_wine ok(cr.cpMax == 4, "EM_EXGETSEL returned cpMax=%d, expected 4\n", cr.cpMax);
5349c2c66affSColin Finck         r = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5350c2c66affSColin Finck         todo_wine ok(!strcmp(buffer, "abc\x8e\xf0"), "WM_GETTEXT returned incorrect string\n");
5351c2c66affSColin Finck         todo_wine ok(r == 5, "WM_GETTEXT returned %d, expected 5\n", r);
5352c2c66affSColin Finck     }
5353c2c66affSColin Finck 
5354c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5355c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)rtfstream);
5356c2c66affSColin Finck     todo_wine ok(r == 12, "EM_REPLACESEL returned %d, expected 12\n", r);
5357c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5358c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5359c2c66affSColin Finck     todo_wine ok(cr.cpMin == 12, "EM_EXGETSEL returned cpMin=%d, expected 12\n", cr.cpMin);
5360c2c66affSColin Finck     todo_wine ok(cr.cpMax == 12, "EM_EXGETSEL returned cpMax=%d, expected 12\n", cr.cpMax);
5361c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5362c2c66affSColin Finck     todo_wine ok(!strcmp(buffer, "TestSomeText"), "WM_GETTEXT returned incorrect string\n");
5363c2c66affSColin Finck 
5364c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5365c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)urtfstream);
5366c2c66affSColin Finck     todo_wine ok(r == 12, "EM_REPLACESEL returned %d, expected 12\n", r);
5367c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5368c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5369c2c66affSColin Finck     todo_wine ok(cr.cpMin == 12, "EM_EXGETSEL returned cpMin=%d, expected 12\n", cr.cpMin);
5370c2c66affSColin Finck     todo_wine ok(cr.cpMax == 12, "EM_EXGETSEL returned cpMax=%d, expected 12\n", cr.cpMax);
5371c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5372c2c66affSColin Finck     todo_wine ok(!strcmp(buffer, "TestSomeText"), "WM_GETTEXT returned incorrect string\n");
5373c2c66affSColin Finck 
5374c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"Wine");
5375c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 1, 2);
5376c2c66affSColin Finck     todo_wine r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)rtfstream);
5377c2c66affSColin Finck     todo_wine ok(r == 12, "EM_REPLACESEL returned %d, expected 12\n", r);
5378c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5379c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5380c2c66affSColin Finck     todo_wine ok(cr.cpMin == 13, "EM_EXGETSEL returned cpMin=%d, expected 13\n", cr.cpMin);
5381c2c66affSColin Finck     todo_wine ok(cr.cpMax == 13, "EM_EXGETSEL returned cpMax=%d, expected 13\n", cr.cpMax);
5382c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5383c2c66affSColin Finck     todo_wine ok(!strcmp(buffer, "WTestSomeTextne"), "WM_GETTEXT returned incorrect string\n");
5384c2c66affSColin Finck 
5385c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"{\\rtf1 Wine}");
5386c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 1, 2);
5387c2c66affSColin Finck     todo_wine r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)rtfstream);
5388c2c66affSColin Finck     todo_wine ok(r == 12, "EM_REPLACESEL returned %d, expected 12\n", r);
5389c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
5390c2c66affSColin Finck     ok(0 == r, "EM_EXGETSEL returned %d, expected 0\n", r);
5391c2c66affSColin Finck     todo_wine ok(cr.cpMin == 13, "EM_EXGETSEL returned cpMin=%d, expected 13\n", cr.cpMin);
5392c2c66affSColin Finck     todo_wine ok(cr.cpMax == 13, "EM_EXGETSEL returned cpMax=%d, expected 13\n", cr.cpMax);
5393c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5394c2c66affSColin Finck     todo_wine ok(!strcmp(buffer, "WTestSomeTextne"), "WM_GETTEXT returned incorrect string\n");
5395c2c66affSColin Finck 
5396c2c66affSColin Finck     if (!redraw)
5397c2c66affSColin Finck         /* This is needed to avoid interfering with keybd_event calls
5398c2c66affSColin Finck          * on other tests that simulate keyboard events. */
5399c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETREDRAW, TRUE, 0);
5400c2c66affSColin Finck 
5401c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
540244f07538SAmine Khaldi 
540344f07538SAmine Khaldi     /* Single-line richedit */
540444f07538SAmine Khaldi     hwndRichEdit = new_richedit_with_style(NULL, 0);
540544f07538SAmine Khaldi     r = SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"line1\r\nline2");
540644f07538SAmine Khaldi     ok(r == 12, "EM_REPLACESEL returned %d, expected 12\n", r);
540744f07538SAmine Khaldi     r = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
540844f07538SAmine Khaldi     ok(r == 5, "WM_GETTEXT returned %d, expected 5\n", r);
540944f07538SAmine Khaldi     ok(!strcmp(buffer, "line1"), "WM_GETTEXT returned incorrect string '%s'\n", buffer);
541044f07538SAmine Khaldi     DestroyWindow(hwndRichEdit);
5411c2c66affSColin Finck }
5412c2c66affSColin Finck 
5413c2c66affSColin Finck /* Native riched20 inspects the keyboard state (e.g. GetKeyState)
5414c2c66affSColin Finck  * to test the state of the modifiers (Ctrl/Alt/Shift).
5415c2c66affSColin Finck  *
5416c2c66affSColin Finck  * Therefore Ctrl-<key> keystrokes need to be simulated with
5417c2c66affSColin Finck  * keybd_event or by using SetKeyboardState to set the modifiers
5418c2c66affSColin Finck  * and SendMessage to simulate the keystrokes.
5419c2c66affSColin Finck  */
send_ctrl_key(HWND hwnd,UINT key)5420c2c66affSColin Finck static LRESULT send_ctrl_key(HWND hwnd, UINT key)
5421c2c66affSColin Finck {
5422c2c66affSColin Finck     LRESULT result;
5423c2c66affSColin Finck     hold_key(VK_CONTROL);
5424c2c66affSColin Finck     result = SendMessageA(hwnd, WM_KEYDOWN, key, 1);
5425c2c66affSColin Finck     release_key(VK_CONTROL);
5426c2c66affSColin Finck     return result;
5427c2c66affSColin Finck }
5428c2c66affSColin Finck 
test_WM_PASTE(void)5429c2c66affSColin Finck static void test_WM_PASTE(void)
5430c2c66affSColin Finck {
5431c2c66affSColin Finck     int result;
5432c2c66affSColin Finck     char buffer[1024] = {0};
5433c2c66affSColin Finck     const char* text1 = "testing paste\r";
5434c2c66affSColin Finck     const char* text1_step1 = "testing paste\r\ntesting paste\r\n";
5435c2c66affSColin Finck     const char* text1_after = "testing paste\r\n";
5436c2c66affSColin Finck     const char* text2 = "testing paste\r\rtesting paste";
5437c2c66affSColin Finck     const char* text2_after = "testing paste\r\n\r\ntesting paste";
5438c2c66affSColin Finck     const char* text3 = "testing paste\r\npaste\r\ntesting paste";
5439c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
5440c2c66affSColin Finck 
5441c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
5442c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 14);
5443c2c66affSColin Finck 
5444c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'C');   /* Copy */
5445c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 14, 14);
5446c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'V');   /* Paste */
5447c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5448c2c66affSColin Finck     /* Pasted text should be visible at this step */
5449c2c66affSColin Finck     result = strcmp(text1_step1, buffer);
5450c2c66affSColin Finck     ok(result == 0,
5451c2c66affSColin Finck         "test paste: strcmp = %i, text='%s'\n", result, buffer);
5452c2c66affSColin Finck 
5453c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'Z');   /* Undo */
5454c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5455c2c66affSColin Finck     /* Text should be the same as before (except for \r -> \r\n conversion) */
5456c2c66affSColin Finck     result = strcmp(text1_after, buffer);
5457c2c66affSColin Finck     ok(result == 0,
5458c2c66affSColin Finck         "test paste: strcmp = %i, text='%s'\n", result, buffer);
5459c2c66affSColin Finck 
5460c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
5461c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 8, 13);
5462c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'C');   /* Copy */
5463c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 14, 14);
5464c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'V');   /* Paste */
5465c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5466c2c66affSColin Finck     /* Pasted text should be visible at this step */
5467c2c66affSColin Finck     result = strcmp(text3, buffer);
5468c2c66affSColin Finck     ok(result == 0,
5469c2c66affSColin Finck         "test paste: strcmp = %i\n", result);
5470c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'Z');   /* Undo */
5471c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5472c2c66affSColin Finck     /* Text should be the same as before (except for \r -> \r\n conversion) */
5473c2c66affSColin Finck     result = strcmp(text2_after, buffer);
5474c2c66affSColin Finck     ok(result == 0,
5475c2c66affSColin Finck         "test paste: strcmp = %i\n", result);
5476c2c66affSColin Finck     send_ctrl_key(hwndRichEdit, 'Y');   /* Redo */
5477c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5478c2c66affSColin Finck     /* Text should revert to post-paste state */
5479c2c66affSColin Finck     result = strcmp(buffer,text3);
5480c2c66affSColin Finck     ok(result == 0,
5481c2c66affSColin Finck         "test paste: strcmp = %i\n", result);
5482c2c66affSColin Finck 
5483c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5484c2c66affSColin Finck     /* Send WM_CHAR to simulate Ctrl-V */
5485c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_CHAR, 22,
5486c2c66affSColin Finck                 (MapVirtualKeyA('V', MAPVK_VK_TO_VSC) << 16) | 1);
5487c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5488c2c66affSColin Finck     /* Shouldn't paste because pasting is handled by WM_KEYDOWN */
5489c2c66affSColin Finck     result = strcmp(buffer,"");
5490c2c66affSColin Finck     ok(result == 0,
5491c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5492c2c66affSColin Finck 
5493c2c66affSColin Finck     /* Send keystrokes with WM_KEYDOWN after setting the modifiers
5494c2c66affSColin Finck      * with SetKeyboard state. */
5495c2c66affSColin Finck 
5496c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5497c2c66affSColin Finck     /* Simulates paste (Ctrl-V) */
5498c2c66affSColin Finck     hold_key(VK_CONTROL);
5499c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_KEYDOWN, 'V',
5500c2c66affSColin Finck                 (MapVirtualKeyA('V', MAPVK_VK_TO_VSC) << 16) | 1);
5501c2c66affSColin Finck     release_key(VK_CONTROL);
5502c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5503c2c66affSColin Finck     result = strcmp(buffer,"paste");
5504c2c66affSColin Finck     ok(result == 0,
5505c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5506c2c66affSColin Finck 
5507c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
5508c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 7);
5509c2c66affSColin Finck     /* Simulates copy (Ctrl-C) */
5510c2c66affSColin Finck     hold_key(VK_CONTROL);
5511c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_KEYDOWN, 'C',
5512c2c66affSColin Finck                 (MapVirtualKeyA('C', MAPVK_VK_TO_VSC) << 16) | 1);
5513c2c66affSColin Finck     release_key(VK_CONTROL);
5514c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5515c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
5516c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5517c2c66affSColin Finck     result = strcmp(buffer,"testing");
5518c2c66affSColin Finck     ok(result == 0,
5519c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5520c2c66affSColin Finck 
5521c2c66affSColin Finck     /* Cut with WM_KEYDOWN to simulate Ctrl-X */
5522c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"cut");
5523c2c66affSColin Finck     /* Simulates select all (Ctrl-A) */
5524c2c66affSColin Finck     hold_key(VK_CONTROL);
5525c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_KEYDOWN, 'A',
5526c2c66affSColin Finck                 (MapVirtualKeyA('A', MAPVK_VK_TO_VSC) << 16) | 1);
5527c2c66affSColin Finck     /* Simulates select cut (Ctrl-X) */
5528c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_KEYDOWN, 'X',
5529c2c66affSColin Finck                 (MapVirtualKeyA('X', MAPVK_VK_TO_VSC) << 16) | 1);
5530c2c66affSColin Finck     release_key(VK_CONTROL);
5531c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5532c2c66affSColin Finck     result = strcmp(buffer,"");
5533c2c66affSColin Finck     ok(result == 0,
5534c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5535c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0);
5536c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
5537c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5538c2c66affSColin Finck     result = strcmp(buffer,"cut\r\n");
5539c2c66affSColin Finck     ok(result == 0,
5540c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5541c2c66affSColin Finck     /* Simulates undo (Ctrl-Z) */
5542c2c66affSColin Finck     hold_key(VK_CONTROL);
5543c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_KEYDOWN, 'Z',
5544c2c66affSColin Finck                 (MapVirtualKeyA('Z', MAPVK_VK_TO_VSC) << 16) | 1);
5545c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5546c2c66affSColin Finck     result = strcmp(buffer,"");
5547c2c66affSColin Finck     ok(result == 0,
5548c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5549c2c66affSColin Finck     /* Simulates redo (Ctrl-Y) */
5550c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_KEYDOWN, 'Y',
5551c2c66affSColin Finck                 (MapVirtualKeyA('Y', MAPVK_VK_TO_VSC) << 16) | 1);
5552c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5553c2c66affSColin Finck     result = strcmp(buffer,"cut\r\n");
5554c2c66affSColin Finck     ok(result == 0,
5555c2c66affSColin Finck         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5556c2c66affSColin Finck     release_key(VK_CONTROL);
5557c2c66affSColin Finck 
555844f07538SAmine Khaldi     /* Copy multiline text to clipboard for future use */
555944f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text3);
556044f07538SAmine Khaldi     SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
556144f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
556244f07538SAmine Khaldi     SendMessageA(hwndRichEdit, EM_SETSEL, 0, 0);
556344f07538SAmine Khaldi 
556444f07538SAmine Khaldi     /* Paste into read-only control */
556544f07538SAmine Khaldi     result = SendMessageA(hwndRichEdit, EM_SETREADONLY, TRUE, 0);
556644f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
556744f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
556844f07538SAmine Khaldi     result = strcmp(buffer, text3);
556944f07538SAmine Khaldi     ok(result == 0,
557044f07538SAmine Khaldi         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
557144f07538SAmine Khaldi 
557244f07538SAmine Khaldi     /* Cut from read-only control */
557344f07538SAmine Khaldi     SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
557444f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_CUT, 0, 0);
557544f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
557644f07538SAmine Khaldi     result = strcmp(buffer, text3);
557744f07538SAmine Khaldi     ok(result == 0,
557844f07538SAmine Khaldi         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
557944f07538SAmine Khaldi 
558044f07538SAmine Khaldi     /* FIXME: Wine doesn't flush Ole clipboard when window is destroyed so do it manually */
558144f07538SAmine Khaldi     OleFlushClipboard();
558244f07538SAmine Khaldi     DestroyWindow(hwndRichEdit);
558344f07538SAmine Khaldi 
558444f07538SAmine Khaldi     /* Paste multi-line text into single-line control */
558544f07538SAmine Khaldi     hwndRichEdit = new_richedit_with_style(NULL, 0);
558644f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_PASTE, 0, 0);
558744f07538SAmine Khaldi     SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
558844f07538SAmine Khaldi     result = strcmp(buffer, "testing paste");
558944f07538SAmine Khaldi     ok(result == 0,
559044f07538SAmine Khaldi         "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
5591c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
5592c2c66affSColin Finck }
5593c2c66affSColin Finck 
test_EM_FORMATRANGE(void)5594c2c66affSColin Finck static void test_EM_FORMATRANGE(void)
5595c2c66affSColin Finck {
5596c2c66affSColin Finck   int r, i, tpp_x, tpp_y;
5597c2c66affSColin Finck   HDC hdc;
5598c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
5599c2c66affSColin Finck   FORMATRANGE fr;
5600c2c66affSColin Finck   BOOL skip_non_english;
5601c2c66affSColin Finck   static const struct {
5602c2c66affSColin Finck     const char *string; /* The string */
5603c2c66affSColin Finck     int first;          /* First 'pagebreak', 0 for don't care */
5604c2c66affSColin Finck     int second;         /* Second 'pagebreak', 0 for don't care */
5605c2c66affSColin Finck   } fmtstrings[] = {
5606c2c66affSColin Finck     {"WINE wine", 0, 0},
5607c2c66affSColin Finck     {"WINE wineWine", 0, 0},
5608c2c66affSColin Finck     {"WINE\r\nwine\r\nwine", 5, 10},
5609c2c66affSColin Finck     {"WINE\r\nWINEwine\r\nWINEwine", 5, 14},
5610c2c66affSColin Finck     {"WINE\r\n\r\nwine\r\nwine", 5, 6}
5611c2c66affSColin Finck   };
5612c2c66affSColin Finck 
5613c2c66affSColin Finck   skip_non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH);
5614c2c66affSColin Finck   if (skip_non_english)
5615c2c66affSColin Finck     skip("Skipping some tests on non-English platform\n");
5616c2c66affSColin Finck 
5617c2c66affSColin Finck   hdc = GetDC(hwndRichEdit);
5618c2c66affSColin Finck   ok(hdc != NULL, "Could not get HDC\n");
5619c2c66affSColin Finck 
5620c2c66affSColin Finck   /* Calculate the twips per pixel */
5621c2c66affSColin Finck   tpp_x = 1440 / GetDeviceCaps(hdc, LOGPIXELSX);
5622c2c66affSColin Finck   tpp_y = 1440 / GetDeviceCaps(hdc, LOGPIXELSY);
5623c2c66affSColin Finck 
5624c2c66affSColin Finck   /* Test the simple case where all the text fits in the page rect. */
5625c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
5626c2c66affSColin Finck   fr.hdc = fr.hdcTarget = hdc;
5627c2c66affSColin Finck   fr.rc.top = fr.rcPage.top = fr.rc.left = fr.rcPage.left = 0;
5628c2c66affSColin Finck   fr.rc.right = fr.rcPage.right = 500 * tpp_x;
5629c2c66affSColin Finck   fr.rc.bottom = fr.rcPage.bottom = 500 * tpp_y;
5630c2c66affSColin Finck   fr.chrg.cpMin = 0;
5631c2c66affSColin Finck   fr.chrg.cpMax = -1;
5632c2c66affSColin Finck   r = SendMessageA(hwndRichEdit, EM_FORMATRANGE, FALSE, (LPARAM)&fr);
5633c2c66affSColin Finck   todo_wine ok(r == 2, "r=%d expected r=2\n", r);
5634c2c66affSColin Finck 
5635c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"ab");
5636c2c66affSColin Finck   fr.rc.bottom = fr.rcPage.bottom;
5637c2c66affSColin Finck   r = SendMessageA(hwndRichEdit, EM_FORMATRANGE, FALSE, (LPARAM)&fr);
5638c2c66affSColin Finck   todo_wine ok(r == 3, "r=%d expected r=3\n", r);
5639c2c66affSColin Finck 
5640c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_FORMATRANGE, FALSE, 0);
5641c2c66affSColin Finck 
564276cf09cfSAmine Khaldi   for (i = 0; i < ARRAY_SIZE(fmtstrings); i++)
5643c2c66affSColin Finck   {
5644c2c66affSColin Finck     GETTEXTLENGTHEX gtl;
5645c2c66affSColin Finck     SIZE stringsize;
5646c2c66affSColin Finck     int len;
5647c2c66affSColin Finck 
5648c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)fmtstrings[i].string);
5649c2c66affSColin Finck 
5650c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
5651c2c66affSColin Finck     gtl.codepage = CP_ACP;
5652c2c66affSColin Finck     len = SendMessageA(hwndRichEdit, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
5653c2c66affSColin Finck 
5654c2c66affSColin Finck     /* Get some size information for the string */
5655c2c66affSColin Finck     GetTextExtentPoint32A(hdc, fmtstrings[i].string, strlen(fmtstrings[i].string), &stringsize);
5656c2c66affSColin Finck 
5657c2c66affSColin Finck     /* Define the box to be half the width needed and a bit larger than the height.
5658c2c66affSColin Finck      * Changes to the width means we have at least 2 pages. Changes to the height
5659c2c66affSColin Finck      * is done so we can check the changing of fr.rc.bottom.
5660c2c66affSColin Finck      */
5661c2c66affSColin Finck     fr.hdc = fr.hdcTarget = hdc;
5662c2c66affSColin Finck     fr.rc.top = fr.rcPage.top = fr.rc.left = fr.rcPage.left = 0;
5663c2c66affSColin Finck     fr.rc.right = fr.rcPage.right = (stringsize.cx / 2) * tpp_x;
5664c2c66affSColin Finck     fr.rc.bottom = fr.rcPage.bottom = (stringsize.cy + 10) * tpp_y;
5665c2c66affSColin Finck 
5666c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_FORMATRANGE, TRUE, 0);
5667c2c66affSColin Finck     todo_wine {
5668c2c66affSColin Finck     ok(r == len, "Expected %d, got %d\n", len, r);
5669c2c66affSColin Finck     }
5670c2c66affSColin Finck 
5671c2c66affSColin Finck     /* We know that the page can't hold the full string. See how many characters
5672c2c66affSColin Finck      * are on the first one
5673c2c66affSColin Finck      */
5674c2c66affSColin Finck     fr.chrg.cpMin = 0;
5675c2c66affSColin Finck     fr.chrg.cpMax = -1;
5676c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
5677c2c66affSColin Finck     todo_wine {
5678c2c66affSColin Finck     if (! skip_non_english)
5679c2c66affSColin Finck       ok(fr.rc.bottom == (stringsize.cy * tpp_y), "Expected bottom to be %d, got %d\n", (stringsize.cy * tpp_y), fr.rc.bottom);
5680c2c66affSColin Finck     }
5681c2c66affSColin Finck     if (fmtstrings[i].first)
5682c2c66affSColin Finck       todo_wine {
5683c2c66affSColin Finck       ok(r == fmtstrings[i].first, "Expected %d, got %d\n", fmtstrings[i].first, r);
5684c2c66affSColin Finck       }
5685c2c66affSColin Finck     else
5686c2c66affSColin Finck       ok(r < len, "Expected < %d, got %d\n", len, r);
5687c2c66affSColin Finck 
5688c2c66affSColin Finck     /* Do another page */
5689c2c66affSColin Finck     fr.chrg.cpMin = r;
5690c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
5691c2c66affSColin Finck     if (fmtstrings[i].second)
5692c2c66affSColin Finck       todo_wine {
5693c2c66affSColin Finck       ok(r == fmtstrings[i].second, "Expected %d, got %d\n", fmtstrings[i].second, r);
5694c2c66affSColin Finck       }
5695c2c66affSColin Finck     else if (! skip_non_english)
5696c2c66affSColin Finck       ok (r < len, "Expected < %d, got %d\n", len, r);
5697c2c66affSColin Finck 
5698c2c66affSColin Finck     /* There is at least on more page, but we don't care */
5699c2c66affSColin Finck 
5700c2c66affSColin Finck     r = SendMessageA(hwndRichEdit, EM_FORMATRANGE, TRUE, 0);
5701c2c66affSColin Finck     todo_wine {
5702c2c66affSColin Finck     ok(r == len, "Expected %d, got %d\n", len, r);
5703c2c66affSColin Finck     }
5704c2c66affSColin Finck   }
5705c2c66affSColin Finck 
5706c2c66affSColin Finck   ReleaseDC(NULL, hdc);
5707c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
5708c2c66affSColin Finck }
5709c2c66affSColin Finck 
5710c2c66affSColin Finck static int nCallbackCount = 0;
5711c2c66affSColin Finck 
EditStreamCallback(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)5712c2c66affSColin Finck static DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff,
5713c2c66affSColin Finck 				 LONG cb, LONG* pcb)
5714c2c66affSColin Finck {
5715c2c66affSColin Finck   const char text[] = {'t','e','s','t'};
5716c2c66affSColin Finck 
5717c2c66affSColin Finck   if (sizeof(text) <= cb)
5718c2c66affSColin Finck   {
5719c2c66affSColin Finck     if ((int)dwCookie != nCallbackCount)
5720c2c66affSColin Finck     {
5721c2c66affSColin Finck       *pcb = 0;
5722c2c66affSColin Finck       return 0;
5723c2c66affSColin Finck     }
5724c2c66affSColin Finck 
5725c2c66affSColin Finck     memcpy (pbBuff, text, sizeof(text));
5726c2c66affSColin Finck     *pcb = sizeof(text);
5727c2c66affSColin Finck 
5728c2c66affSColin Finck     nCallbackCount++;
5729c2c66affSColin Finck 
5730c2c66affSColin Finck     return 0;
5731c2c66affSColin Finck   }
5732c2c66affSColin Finck   else
5733c2c66affSColin Finck     return 1; /* indicates callback failed */
5734c2c66affSColin Finck }
5735c2c66affSColin Finck 
test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)5736c2c66affSColin Finck static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie,
5737c2c66affSColin Finck                                          LPBYTE pbBuff,
5738c2c66affSColin Finck                                          LONG cb,
5739c2c66affSColin Finck                                          LONG *pcb)
5740c2c66affSColin Finck {
5741c2c66affSColin Finck   const char** str = (const char**)dwCookie;
5742c2c66affSColin Finck   int size = strlen(*str);
5743c2c66affSColin Finck   *pcb = cb;
5744c2c66affSColin Finck   if (*pcb > size) {
5745c2c66affSColin Finck     *pcb = size;
5746c2c66affSColin Finck   }
5747c2c66affSColin Finck   if (*pcb > 0) {
5748c2c66affSColin Finck     memcpy(pbBuff, *str, *pcb);
5749c2c66affSColin Finck     *str += *pcb;
5750c2c66affSColin Finck   }
5751c2c66affSColin Finck   return 0;
5752c2c66affSColin Finck }
5753c2c66affSColin Finck 
test_EM_STREAMIN_esCallback_UTF8Split(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)5754c2c66affSColin Finck static DWORD CALLBACK test_EM_STREAMIN_esCallback_UTF8Split(DWORD_PTR dwCookie,
5755c2c66affSColin Finck                                          LPBYTE pbBuff,
5756c2c66affSColin Finck                                          LONG cb,
5757c2c66affSColin Finck                                          LONG *pcb)
5758c2c66affSColin Finck {
5759c2c66affSColin Finck     DWORD *phase = (DWORD *)dwCookie;
5760c2c66affSColin Finck 
5761c2c66affSColin Finck     if(*phase == 0){
5762c2c66affSColin Finck         static const char first[] = "\xef\xbb\xbf\xc3\x96\xc3";
5763c2c66affSColin Finck         *pcb = sizeof(first) - 1;
5764c2c66affSColin Finck         memcpy(pbBuff, first, *pcb);
5765c2c66affSColin Finck     }else if(*phase == 1){
5766c2c66affSColin Finck         static const char second[] = "\x8f\xc3\x8b";
5767c2c66affSColin Finck         *pcb = sizeof(second) - 1;
5768c2c66affSColin Finck         memcpy(pbBuff, second, *pcb);
5769c2c66affSColin Finck     }else
5770c2c66affSColin Finck         *pcb = 0;
5771c2c66affSColin Finck 
5772c2c66affSColin Finck     ++*phase;
5773c2c66affSColin Finck 
5774c2c66affSColin Finck     return 0;
5775c2c66affSColin Finck }
5776c2c66affSColin Finck 
test_EM_STREAMIN_null_bytes(DWORD_PTR cookie,BYTE * buf,LONG size,LONG * written)577776cf09cfSAmine Khaldi static DWORD CALLBACK test_EM_STREAMIN_null_bytes(DWORD_PTR cookie, BYTE *buf, LONG size, LONG *written)
577876cf09cfSAmine Khaldi {
577976cf09cfSAmine Khaldi     DWORD *phase = (DWORD *)cookie;
578076cf09cfSAmine Khaldi 
578176cf09cfSAmine Khaldi     if (*phase == 0)
578276cf09cfSAmine Khaldi     {
578376cf09cfSAmine Khaldi         static const char first[] = "{\\rtf1\\ansi{Th\0is";
578476cf09cfSAmine Khaldi         *written = sizeof(first);
578576cf09cfSAmine Khaldi         memcpy(buf, first, *written);
578676cf09cfSAmine Khaldi     }
578776cf09cfSAmine Khaldi     else if (*phase == 1)
578876cf09cfSAmine Khaldi     {
578976cf09cfSAmine Khaldi         static const char second[] = " is a test}}";
579076cf09cfSAmine Khaldi         *written = sizeof(second);
579176cf09cfSAmine Khaldi         memcpy(buf, second, *written);
579276cf09cfSAmine Khaldi     }
579376cf09cfSAmine Khaldi     else
579476cf09cfSAmine Khaldi         *written = 0;
579576cf09cfSAmine Khaldi 
579676cf09cfSAmine Khaldi     ++*phase;
579776cf09cfSAmine Khaldi 
579876cf09cfSAmine Khaldi     return 0;
579976cf09cfSAmine Khaldi }
580076cf09cfSAmine Khaldi 
5801c2c66affSColin Finck struct StringWithLength {
5802c2c66affSColin Finck     int length;
5803c2c66affSColin Finck     char *buffer;
5804c2c66affSColin Finck };
5805c2c66affSColin Finck 
5806c2c66affSColin Finck /* This callback is used to handled the null characters in a string. */
test_EM_STREAMIN_esCallback2(DWORD_PTR dwCookie,LPBYTE pbBuff,LONG cb,LONG * pcb)5807c2c66affSColin Finck static DWORD CALLBACK test_EM_STREAMIN_esCallback2(DWORD_PTR dwCookie,
5808c2c66affSColin Finck                                                    LPBYTE pbBuff,
5809c2c66affSColin Finck                                                    LONG cb,
5810c2c66affSColin Finck                                                    LONG *pcb)
5811c2c66affSColin Finck {
5812c2c66affSColin Finck     struct StringWithLength* str = (struct StringWithLength*)dwCookie;
5813c2c66affSColin Finck     int size = str->length;
5814c2c66affSColin Finck     *pcb = cb;
5815c2c66affSColin Finck     if (*pcb > size) {
5816c2c66affSColin Finck       *pcb = size;
5817c2c66affSColin Finck     }
5818c2c66affSColin Finck     if (*pcb > 0) {
5819c2c66affSColin Finck       memcpy(pbBuff, str->buffer, *pcb);
5820c2c66affSColin Finck       str->buffer += *pcb;
5821c2c66affSColin Finck       str->length -= *pcb;
5822c2c66affSColin Finck     }
5823c2c66affSColin Finck     return 0;
5824c2c66affSColin Finck }
5825c2c66affSColin Finck 
test_EM_STREAMIN(void)5826c2c66affSColin Finck static void test_EM_STREAMIN(void)
5827c2c66affSColin Finck {
5828c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
5829c2c66affSColin Finck   DWORD phase;
5830c2c66affSColin Finck   LRESULT result;
5831c2c66affSColin Finck   EDITSTREAM es;
5832c2c66affSColin Finck   char buffer[1024] = {0}, tmp[16];
5833c2c66affSColin Finck   CHARRANGE range;
5834c2c66affSColin Finck   PARAFORMAT2 fmt;
5835c2c66affSColin Finck 
5836c2c66affSColin Finck   const char * streamText0 = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText}";
5837c2c66affSColin Finck   const char * streamText0a = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText\\par}";
5838c2c66affSColin Finck   const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
5839c2c66affSColin Finck   const char * ptr;
5840c2c66affSColin Finck 
5841c2c66affSColin Finck   const char * streamText1 =
5842c2c66affSColin Finck   "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n"
5843c2c66affSColin Finck   "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n"
5844c2c66affSColin Finck   "}\r\n";
5845c2c66affSColin Finck 
5846c2c66affSColin Finck   /* In richedit 2.0 mode, this should NOT be accepted, unlike 1.0 */
5847c2c66affSColin Finck   const char * streamText2 =
5848c2c66affSColin Finck     "{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;"
5849c2c66affSColin Finck     "\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255"
5850c2c66affSColin Finck     "\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 "
5851c2c66affSColin Finck     "\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 "
5852c2c66affSColin Finck     "\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 "
5853c2c66affSColin Finck     "\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 "
5854c2c66affSColin Finck     "\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line }";
5855c2c66affSColin Finck 
5856c2c66affSColin Finck   const char * streamText3 = "RichEdit1";
5857c2c66affSColin Finck 
5858c2c66affSColin Finck   const char * streamTextUTF8BOM = "\xef\xbb\xbfTestUTF8WithBOM";
5859c2c66affSColin Finck 
5860c2c66affSColin Finck   const char * streamText4 =
5861c2c66affSColin Finck       "This text just needs to be long enough to cause run to be split onto "
5862c2c66affSColin Finck       "two separate lines and make sure the null terminating character is "
5863c2c66affSColin Finck       "handled properly.\0";
5864c2c66affSColin Finck 
5865c2c66affSColin Finck   const WCHAR UTF8Split_exp[4] = {0xd6, 0xcf, 0xcb, 0};
5866c2c66affSColin Finck 
5867c2c66affSColin Finck   int length4 = strlen(streamText4) + 1;
5868c2c66affSColin Finck   struct StringWithLength cookieForStream4 = {
5869c2c66affSColin Finck       length4,
5870c2c66affSColin Finck       (char *)streamText4,
5871c2c66affSColin Finck   };
5872c2c66affSColin Finck 
5873c2c66affSColin Finck   const WCHAR streamText5[] = { 'T', 'e', 's', 't', 'S', 'o', 'm', 'e', 'T', 'e', 'x', 't' };
587476cf09cfSAmine Khaldi   int length5 = ARRAY_SIZE(streamText5);
5875c2c66affSColin Finck   struct StringWithLength cookieForStream5 = {
5876c2c66affSColin Finck       sizeof(streamText5),
5877c2c66affSColin Finck       (char *)streamText5,
5878c2c66affSColin Finck   };
5879c2c66affSColin Finck 
5880c2c66affSColin Finck   /* Minimal test without \par at the end */
5881c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamText0;
5882c2c66affSColin Finck   es.dwError = 0;
5883c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
5884c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
5885c2c66affSColin Finck   ok(result == 12, "got %ld, expected %d\n", result, 12);
5886c2c66affSColin Finck 
5887c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5888c2c66affSColin Finck   ok (result  == 12,
5889c2c66affSColin Finck       "EM_STREAMIN: Test 0 returned %ld, expected 12\n", result);
5890c2c66affSColin Finck   result = strcmp (buffer,"TestSomeText");
5891c2c66affSColin Finck   ok (result  == 0,
5892c2c66affSColin Finck       "EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
5893c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
5894c2c66affSColin Finck   /* Show that para fmts are ignored */
5895c2c66affSColin Finck   range.cpMin = 2;
5896c2c66affSColin Finck   range.cpMax = 2;
5897c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range);
5898c2c66affSColin Finck   memset(&fmt, 0xcc, sizeof(fmt));
5899c2c66affSColin Finck   fmt.cbSize = sizeof(fmt);
5900c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
5901c2c66affSColin Finck   ok(fmt.dxStartIndent == 0, "got %d\n", fmt.dxStartIndent);
5902c2c66affSColin Finck   ok(fmt.dxOffset == 0, "got %d\n", fmt.dxOffset);
5903c2c66affSColin Finck   ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment);
5904c2c66affSColin Finck   ok((fmt.wEffects & PFE_RTLPARA) == 0, "got %x\n", fmt.wEffects);
5905c2c66affSColin Finck 
5906c2c66affSColin Finck   /* Native richedit 2.0 ignores last \par */
5907c2c66affSColin Finck   ptr = streamText0a;
5908c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&ptr;
5909c2c66affSColin Finck   es.dwError = 0;
5910c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
5911c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
5912c2c66affSColin Finck   ok(result == 12, "got %ld, expected %d\n", result, 12);
5913c2c66affSColin Finck 
5914c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5915c2c66affSColin Finck   ok (result  == 12,
5916c2c66affSColin Finck       "EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
5917c2c66affSColin Finck   result = strcmp (buffer,"TestSomeText");
5918c2c66affSColin Finck   ok (result  == 0,
5919c2c66affSColin Finck       "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
5920c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 0-a set error %d, expected %d\n", es.dwError, 0);
5921c2c66affSColin Finck   /* This time para fmts are processed */
5922c2c66affSColin Finck   range.cpMin = 2;
5923c2c66affSColin Finck   range.cpMax = 2;
5924c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range);
5925c2c66affSColin Finck   memset(&fmt, 0xcc, sizeof(fmt));
5926c2c66affSColin Finck   fmt.cbSize = sizeof(fmt);
5927c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
5928c2c66affSColin Finck   ok(fmt.dxStartIndent == 300, "got %d\n", fmt.dxStartIndent);
5929c2c66affSColin Finck   ok(fmt.dxOffset == -100, "got %d\n", fmt.dxOffset);
5930c2c66affSColin Finck   ok(fmt.wAlignment == PFA_RIGHT, "got %d\n", fmt.wAlignment);
5931c2c66affSColin Finck   ok((fmt.wEffects & PFE_RTLPARA) == PFE_RTLPARA, "got %x\n", fmt.wEffects);
5932c2c66affSColin Finck 
5933c2c66affSColin Finck   /* Native richedit 2.0 ignores last \par, next-to-last \par appears */
5934c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamText0b;
5935c2c66affSColin Finck   es.dwError = 0;
5936c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
5937c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
5938c2c66affSColin Finck   ok(result == 13, "got %ld, expected %d\n", result, 13);
5939c2c66affSColin Finck 
5940c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5941c2c66affSColin Finck   ok (result  == 14,
5942c2c66affSColin Finck       "EM_STREAMIN: Test 0-b returned %ld, expected 14\n", result);
5943c2c66affSColin Finck   result = strcmp (buffer,"TestSomeText\r\n");
5944c2c66affSColin Finck   ok (result  == 0,
5945c2c66affSColin Finck       "EM_STREAMIN: Test 0-b set wrong text: Result: %s\n",buffer);
5946c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 0-b set error %d, expected %d\n", es.dwError, 0);
5947c2c66affSColin Finck 
5948c2c66affSColin Finck   /* Show that when using SFF_SELECTION the last \par is not ignored. */
5949c2c66affSColin Finck   ptr = streamText0a;
5950c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&ptr;
5951c2c66affSColin Finck   es.dwError = 0;
5952c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
5953c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
5954c2c66affSColin Finck   ok(result == 12, "got %ld, expected %d\n", result, 12);
5955c2c66affSColin Finck 
5956c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5957c2c66affSColin Finck   ok (result  == 12,
5958c2c66affSColin Finck       "EM_STREAMIN: Test 0-a returned %ld, expected 12\n", result);
5959c2c66affSColin Finck   result = strcmp (buffer,"TestSomeText");
5960c2c66affSColin Finck   ok (result  == 0,
5961c2c66affSColin Finck       "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
5962c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 0-a set error %d, expected %d\n", es.dwError, 0);
5963c2c66affSColin Finck 
5964c2c66affSColin Finck   range.cpMin = 0;
5965c2c66affSColin Finck   range.cpMax = -1;
5966c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range);
5967c2c66affSColin Finck   ok (result == 13, "got %ld\n", result);
5968c2c66affSColin Finck 
5969c2c66affSColin Finck   ptr = streamText0a;
5970c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&ptr;
5971c2c66affSColin Finck   es.dwError = 0;
5972c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
5973c2c66affSColin Finck 
5974c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SFF_SELECTION | SF_RTF, (LPARAM)&es);
5975c2c66affSColin Finck   ok(result == 13, "got %ld, expected 13\n", result);
5976c2c66affSColin Finck 
5977c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5978c2c66affSColin Finck   ok (result  == 14,
5979c2c66affSColin Finck       "EM_STREAMIN: Test SFF_SELECTION 0-a returned %ld, expected 14\n", result);
5980c2c66affSColin Finck   result = strcmp (buffer,"TestSomeText\r\n");
5981c2c66affSColin Finck   ok (result  == 0,
5982c2c66affSColin Finck       "EM_STREAMIN: Test SFF_SELECTION 0-a set wrong text: Result: %s\n",buffer);
5983c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test SFF_SELECTION 0-a set error %d, expected %d\n", es.dwError, 0);
5984c2c66affSColin Finck 
5985c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamText1;
5986c2c66affSColin Finck   es.dwError = 0;
5987c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
5988c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
5989c2c66affSColin Finck   ok(result == 12, "got %ld, expected %d\n", result, 12);
5990c2c66affSColin Finck 
5991c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
5992c2c66affSColin Finck   ok (result  == 12,
5993c2c66affSColin Finck       "EM_STREAMIN: Test 1 returned %ld, expected 12\n", result);
5994c2c66affSColin Finck   result = strcmp (buffer,"TestSomeText");
5995c2c66affSColin Finck   ok (result  == 0,
5996c2c66affSColin Finck       "EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
5997c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 1 set error %d, expected %d\n", es.dwError, 0);
5998c2c66affSColin Finck 
5999c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamText2;
6000c2c66affSColin Finck   es.dwError = 0;
6001c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
6002c2c66affSColin Finck   ok(result == 0, "got %ld, expected %d\n", result, 0);
6003c2c66affSColin Finck 
6004c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6005c2c66affSColin Finck   ok (result  == 0,
6006c2c66affSColin Finck       "EM_STREAMIN: Test 2 returned %ld, expected 0\n", result);
6007c2c66affSColin Finck   ok(!buffer[0], "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
6008c2c66affSColin Finck   ok(es.dwError == -16, "EM_STREAMIN: Test 2 set error %d, expected %d\n", es.dwError, -16);
6009c2c66affSColin Finck 
6010c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamText3;
6011c2c66affSColin Finck   es.dwError = 0;
6012c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
6013c2c66affSColin Finck   ok(result == 0, "got %ld, expected %d\n", result, 0);
6014c2c66affSColin Finck 
6015c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6016c2c66affSColin Finck   ok (result  == 0,
6017c2c66affSColin Finck       "EM_STREAMIN: Test 3 returned %ld, expected 0\n", result);
6018c2c66affSColin Finck   ok(!buffer[0], "EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer);
6019c2c66affSColin Finck   ok(es.dwError == -16, "EM_STREAMIN: Test 3 set error %d, expected %d\n", es.dwError, -16);
6020c2c66affSColin Finck 
6021c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&streamTextUTF8BOM;
6022c2c66affSColin Finck   es.dwError = 0;
6023c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback;
6024c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es);
6025c2c66affSColin Finck   ok(result == 18, "got %ld, expected %d\n", result, 18);
6026c2c66affSColin Finck 
6027c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6028c2c66affSColin Finck   ok(result  == 15,
6029c2c66affSColin Finck       "EM_STREAMIN: Test UTF8WithBOM returned %ld, expected 15\n", result);
6030c2c66affSColin Finck   result = strcmp (buffer,"TestUTF8WithBOM");
6031c2c66affSColin Finck   ok(result  == 0,
6032c2c66affSColin Finck       "EM_STREAMIN: Test UTF8WithBOM set wrong text: Result: %s\n",buffer);
6033c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test UTF8WithBOM set error %d, expected %d\n", es.dwError, 0);
6034c2c66affSColin Finck 
6035c2c66affSColin Finck   phase = 0;
6036c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&phase;
6037c2c66affSColin Finck   es.dwError = 0;
6038c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback_UTF8Split;
6039c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es);
6040c2c66affSColin Finck   ok(result == 8, "got %ld\n", result);
6041c2c66affSColin Finck 
6042c2c66affSColin Finck   WideCharToMultiByte(CP_ACP, 0, UTF8Split_exp, -1, tmp, sizeof(tmp), NULL, NULL);
6043c2c66affSColin Finck 
6044c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6045c2c66affSColin Finck   ok(result  == 3,
6046c2c66affSColin Finck       "EM_STREAMIN: Test UTF8Split returned %ld\n", result);
6047c2c66affSColin Finck   result = memcmp (buffer, tmp, 3);
6048c2c66affSColin Finck   ok(result  == 0,
6049c2c66affSColin Finck       "EM_STREAMIN: Test UTF8Split set wrong text: Result: %s\n",buffer);
6050c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test UTF8Split set error %d, expected %d\n", es.dwError, 0);
6051c2c66affSColin Finck 
6052c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&cookieForStream4;
6053c2c66affSColin Finck   es.dwError = 0;
6054c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback2;
6055c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es);
6056c2c66affSColin Finck   ok(result == length4, "got %ld, expected %d\n", result, length4);
6057c2c66affSColin Finck 
6058c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6059c2c66affSColin Finck   ok (result  == length4,
6060c2c66affSColin Finck       "EM_STREAMIN: Test 4 returned %ld, expected %d\n", result, length4);
6061c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 4 set error %d, expected %d\n", es.dwError, 0);
6062c2c66affSColin Finck 
6063c2c66affSColin Finck   es.dwCookie = (DWORD_PTR)&cookieForStream5;
6064c2c66affSColin Finck   es.dwError = 0;
6065c2c66affSColin Finck   es.pfnCallback = test_EM_STREAMIN_esCallback2;
6066c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT | SF_UNICODE, (LPARAM)&es);
6067c2c66affSColin Finck   ok(result == sizeof(streamText5), "got %ld, expected %u\n", result, (UINT)sizeof(streamText5));
6068c2c66affSColin Finck 
6069c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6070c2c66affSColin Finck   ok (result  == length5,
6071c2c66affSColin Finck       "EM_STREAMIN: Test 5 returned %ld, expected %d\n", result, length5);
6072c2c66affSColin Finck   ok(es.dwError == 0, "EM_STREAMIN: Test 5 set error %d, expected %d\n", es.dwError, 0);
6073c2c66affSColin Finck 
6074c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
607544f07538SAmine Khaldi 
607644f07538SAmine Khaldi   /* Single-line richedit */
607744f07538SAmine Khaldi   hwndRichEdit = new_richedit_with_style(NULL, 0);
607844f07538SAmine Khaldi   ptr = "line1\r\nline2";
607944f07538SAmine Khaldi   es.dwCookie = (DWORD_PTR)&ptr;
608044f07538SAmine Khaldi   es.dwError = 0;
608144f07538SAmine Khaldi   es.pfnCallback = test_EM_STREAMIN_esCallback;
608244f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es);
608344f07538SAmine Khaldi   ok(result == 12, "got %ld, expected %d\n", result, 12);
608444f07538SAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
608544f07538SAmine Khaldi   ok (!strcmp(buffer, "line1"),
608644f07538SAmine Khaldi       "EM_STREAMIN: Unexpected text '%s'\n", buffer);
608776cf09cfSAmine Khaldi 
608876cf09cfSAmine Khaldi   /* Test 0-bytes inside text */
608976cf09cfSAmine Khaldi   hwndRichEdit = new_richedit_with_style(NULL, 0);
609076cf09cfSAmine Khaldi   phase = 0;
609176cf09cfSAmine Khaldi   es.dwCookie = (DWORD_PTR)&phase;
609276cf09cfSAmine Khaldi   es.dwError = 0;
609376cf09cfSAmine Khaldi   es.pfnCallback = test_EM_STREAMIN_null_bytes;
609476cf09cfSAmine Khaldi   result = SendMessageA(hwndRichEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
609576cf09cfSAmine Khaldi   ok(result == 16, "got %ld, expected %d\n", result, 16);
609676cf09cfSAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
609776cf09cfSAmine Khaldi   ok (!strcmp(buffer, "Th is  is a test"), "EM_STREAMIN: Unexpected text '%s'\n", buffer);
6098c2c66affSColin Finck }
6099c2c66affSColin Finck 
test_EM_StreamIn_Undo(void)6100c2c66affSColin Finck static void test_EM_StreamIn_Undo(void)
6101c2c66affSColin Finck {
6102c2c66affSColin Finck   /* The purpose of this test is to determine when a EM_StreamIn should be
6103c2c66affSColin Finck    * undoable. This is important because WM_PASTE currently uses StreamIn and
6104c2c66affSColin Finck    * pasting should always be undoable but streaming isn't always.
6105c2c66affSColin Finck    *
6106c2c66affSColin Finck    * cases to test:
6107c2c66affSColin Finck    * StreamIn plain text without SFF_SELECTION.
6108c2c66affSColin Finck    * StreamIn plain text with SFF_SELECTION set but a zero-length selection
6109c2c66affSColin Finck    * StreamIn plain text with SFF_SELECTION and a valid, normal selection
6110c2c66affSColin Finck    * StreamIn plain text with SFF_SELECTION and a backwards-selection (from>to)
6111c2c66affSColin Finck    * Feel free to add tests for other text modes or StreamIn things.
6112c2c66affSColin Finck    */
6113c2c66affSColin Finck 
6114c2c66affSColin Finck 
6115c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
6116c2c66affSColin Finck   LRESULT result;
6117c2c66affSColin Finck   EDITSTREAM es;
6118c2c66affSColin Finck   char buffer[1024] = {0};
6119c2c66affSColin Finck   const char randomtext[] = "Some text";
6120c2c66affSColin Finck 
6121c2c66affSColin Finck   es.pfnCallback = EditStreamCallback;
6122c2c66affSColin Finck 
6123c2c66affSColin Finck   /* StreamIn, no SFF_SELECTION */
6124c2c66affSColin Finck   es.dwCookie = nCallbackCount;
6125c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
6126c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)randomtext);
6127c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL,0,0);
6128c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT, (LPARAM)&es);
6129c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6130c2c66affSColin Finck   result = strcmp (buffer,"test");
6131c2c66affSColin Finck   ok (result  == 0,
6132c2c66affSColin Finck       "EM_STREAMIN: Test 1 set wrong text: Result: %s\n",buffer);
6133c2c66affSColin Finck 
6134c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
6135c2c66affSColin Finck   ok (result == FALSE,
6136c2c66affSColin Finck       "EM_STREAMIN without SFF_SELECTION wrongly allows undo\n");
6137c2c66affSColin Finck 
6138c2c66affSColin Finck   /* StreamIn, SFF_SELECTION, but nothing selected */
6139c2c66affSColin Finck   es.dwCookie = nCallbackCount;
6140c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
6141c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)randomtext);
6142c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL,0,0);
6143c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT|SFF_SELECTION, (LPARAM)&es);
6144c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6145c2c66affSColin Finck   result = strcmp (buffer,"testSome text");
6146c2c66affSColin Finck   ok (result  == 0,
6147c2c66affSColin Finck       "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
6148c2c66affSColin Finck 
6149c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
6150c2c66affSColin Finck   ok (result == TRUE,
6151c2c66affSColin Finck      "EM_STREAMIN with SFF_SELECTION but no selection set "
6152c2c66affSColin Finck       "should create an undo\n");
6153c2c66affSColin Finck 
6154c2c66affSColin Finck   /* StreamIn, SFF_SELECTION, with a selection */
6155c2c66affSColin Finck   es.dwCookie = nCallbackCount;
6156c2c66affSColin Finck   SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
6157c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)randomtext);
6158c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_SETSEL,4,5);
6159c2c66affSColin Finck   SendMessageA(hwndRichEdit, EM_STREAMIN, SF_TEXT|SFF_SELECTION, (LPARAM)&es);
6160c2c66affSColin Finck   SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buffer);
6161c2c66affSColin Finck   result = strcmp (buffer,"Sometesttext");
6162c2c66affSColin Finck   ok (result  == 0,
6163c2c66affSColin Finck       "EM_STREAMIN: Test 2 set wrong text: Result: %s\n",buffer);
6164c2c66affSColin Finck 
6165c2c66affSColin Finck   result = SendMessageA(hwndRichEdit, EM_CANUNDO, 0, 0);
6166c2c66affSColin Finck   ok (result == TRUE,
6167c2c66affSColin Finck       "EM_STREAMIN with SFF_SELECTION and selection set "
6168c2c66affSColin Finck       "should create an undo\n");
6169c2c66affSColin Finck 
6170c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
6171c2c66affSColin Finck }
6172c2c66affSColin Finck 
is_em_settextex_supported(HWND hwnd)6173c2c66affSColin Finck static BOOL is_em_settextex_supported(HWND hwnd)
6174c2c66affSColin Finck {
6175c2c66affSColin Finck     SETTEXTEX stex = { ST_DEFAULT, CP_ACP };
6176c2c66affSColin Finck     return SendMessageA(hwnd, EM_SETTEXTEX, (WPARAM)&stex, 0) != 0;
6177c2c66affSColin Finck }
6178c2c66affSColin Finck 
test_unicode_conversions(void)6179c2c66affSColin Finck static void test_unicode_conversions(void)
6180c2c66affSColin Finck {
6181c2c66affSColin Finck     static const WCHAR tW[] = {'t',0};
6182c2c66affSColin Finck     static const WCHAR teW[] = {'t','e',0};
6183c2c66affSColin Finck     static const WCHAR textW[] = {'t','e','s','t',0};
6184c2c66affSColin Finck     static const char textA[] = "test";
6185c2c66affSColin Finck     char bufA[64];
6186c2c66affSColin Finck     WCHAR bufW[64];
6187c2c66affSColin Finck     HWND hwnd;
6188c2c66affSColin Finck     int em_settextex_supported, ret;
6189c2c66affSColin Finck 
6190c2c66affSColin Finck #define set_textA(hwnd, wm_set_text, txt) \
6191c2c66affSColin Finck     do { \
6192c2c66affSColin Finck         SETTEXTEX stex = { ST_DEFAULT, CP_ACP }; \
6193c2c66affSColin Finck         WPARAM wparam = (wm_set_text == WM_SETTEXT) ? 0 : (WPARAM)&stex; \
6194c2c66affSColin Finck         assert(wm_set_text == WM_SETTEXT || wm_set_text == EM_SETTEXTEX); \
6195c2c66affSColin Finck         ret = SendMessageA(hwnd, wm_set_text, wparam, (LPARAM)txt); \
6196c2c66affSColin Finck         ok(ret, "SendMessageA(%02x) error %u\n", wm_set_text, GetLastError()); \
6197c2c66affSColin Finck     } while(0)
6198c2c66affSColin Finck #define expect_textA(hwnd, wm_get_text, txt) \
6199c2c66affSColin Finck     do { \
6200c2c66affSColin Finck         GETTEXTEX gtex = { 64, GT_DEFAULT, CP_ACP, NULL, NULL }; \
6201c2c66affSColin Finck         WPARAM wparam = (wm_get_text == WM_GETTEXT) ? 64 : (WPARAM)&gtex; \
6202c2c66affSColin Finck         assert(wm_get_text == WM_GETTEXT || wm_get_text == EM_GETTEXTEX); \
6203c2c66affSColin Finck         memset(bufA, 0xAA, sizeof(bufA)); \
6204c2c66affSColin Finck         ret = SendMessageA(hwnd, wm_get_text, wparam, (LPARAM)bufA); \
6205c2c66affSColin Finck         ok(ret, "SendMessageA(%02x) error %u\n", wm_get_text, GetLastError()); \
6206c2c66affSColin Finck         ret = lstrcmpA(bufA, txt); \
6207c2c66affSColin Finck         ok(!ret, "%02x: strings do not match: expected %s got %s\n", wm_get_text, txt, bufA); \
6208c2c66affSColin Finck     } while(0)
6209c2c66affSColin Finck 
6210c2c66affSColin Finck #define set_textW(hwnd, wm_set_text, txt) \
6211c2c66affSColin Finck     do { \
6212c2c66affSColin Finck         SETTEXTEX stex = { ST_DEFAULT, 1200 }; \
6213c2c66affSColin Finck         WPARAM wparam = (wm_set_text == WM_SETTEXT) ? 0 : (WPARAM)&stex; \
6214c2c66affSColin Finck         assert(wm_set_text == WM_SETTEXT || wm_set_text == EM_SETTEXTEX); \
6215c2c66affSColin Finck         ret = SendMessageW(hwnd, wm_set_text, wparam, (LPARAM)txt); \
6216c2c66affSColin Finck         ok(ret, "SendMessageW(%02x) error %u\n", wm_set_text, GetLastError()); \
6217c2c66affSColin Finck     } while(0)
6218c2c66affSColin Finck #define expect_textW(hwnd, wm_get_text, txt) \
6219c2c66affSColin Finck     do { \
6220c2c66affSColin Finck         GETTEXTEX gtex = { 64, GT_DEFAULT, 1200, NULL, NULL }; \
6221c2c66affSColin Finck         WPARAM wparam = (wm_get_text == WM_GETTEXT) ? 64 : (WPARAM)&gtex; \
6222c2c66affSColin Finck         assert(wm_get_text == WM_GETTEXT || wm_get_text == EM_GETTEXTEX); \
6223c2c66affSColin Finck         memset(bufW, 0xAA, sizeof(bufW)); \
6224c2c66affSColin Finck         ret = SendMessageW(hwnd, wm_get_text, wparam, (LPARAM)bufW); \
6225c2c66affSColin Finck         ok(ret, "SendMessageW(%02x) error %u\n", wm_get_text, GetLastError()); \
6226c2c66affSColin Finck         ret = lstrcmpW(bufW, txt); \
6227c2c66affSColin Finck         ok(!ret, "%02x: strings do not match: expected[0] %x got[0] %x\n", wm_get_text, txt[0], bufW[0]); \
6228c2c66affSColin Finck     } while(0)
6229c2c66affSColin Finck #define expect_empty(hwnd, wm_get_text) \
6230c2c66affSColin Finck     do { \
6231c2c66affSColin Finck         GETTEXTEX gtex = { 64, GT_DEFAULT, CP_ACP, NULL, NULL }; \
6232c2c66affSColin Finck         WPARAM wparam = (wm_get_text == WM_GETTEXT) ? 64 : (WPARAM)&gtex; \
6233c2c66affSColin Finck         assert(wm_get_text == WM_GETTEXT || wm_get_text == EM_GETTEXTEX); \
6234c2c66affSColin Finck         memset(bufA, 0xAA, sizeof(bufA)); \
6235c2c66affSColin Finck         ret = SendMessageA(hwnd, wm_get_text, wparam, (LPARAM)bufA); \
6236c2c66affSColin Finck         ok(!ret, "empty richedit should return 0, got %d\n", ret); \
6237c2c66affSColin Finck         ok(!*bufA, "empty richedit should return empty string, got %s\n", bufA); \
6238c2c66affSColin Finck     } while(0)
6239c2c66affSColin Finck 
6240c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
6241c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6242c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6243c2c66affSColin Finck 
6244c2c66affSColin Finck     ret = IsWindowUnicode(hwnd);
6245c2c66affSColin Finck     ok(ret, "RichEdit20W should be unicode under NT\n");
6246c2c66affSColin Finck 
6247c2c66affSColin Finck     /* EM_SETTEXTEX is supported starting from version 3.0 */
6248c2c66affSColin Finck     em_settextex_supported = is_em_settextex_supported(hwnd);
6249c2c66affSColin Finck     trace("EM_SETTEXTEX is %ssupported on this platform\n",
6250c2c66affSColin Finck           em_settextex_supported ? "" : "NOT ");
6251c2c66affSColin Finck 
6252c2c66affSColin Finck     expect_empty(hwnd, WM_GETTEXT);
6253c2c66affSColin Finck     expect_empty(hwnd, EM_GETTEXTEX);
6254c2c66affSColin Finck 
6255c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_CHAR, textW[0], 0);
6256c2c66affSColin Finck     ok(!ret, "SendMessageA(WM_CHAR) should return 0, got %d\n", ret);
6257c2c66affSColin Finck     expect_textA(hwnd, WM_GETTEXT, "t");
6258c2c66affSColin Finck     expect_textA(hwnd, EM_GETTEXTEX, "t");
6259c2c66affSColin Finck     expect_textW(hwnd, EM_GETTEXTEX, tW);
6260c2c66affSColin Finck 
6261c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_CHAR, textA[1], 0);
6262c2c66affSColin Finck     ok(!ret, "SendMessageA(WM_CHAR) should return 0, got %d\n", ret);
6263c2c66affSColin Finck     expect_textA(hwnd, WM_GETTEXT, "te");
6264c2c66affSColin Finck     expect_textA(hwnd, EM_GETTEXTEX, "te");
6265c2c66affSColin Finck     expect_textW(hwnd, EM_GETTEXTEX, teW);
6266c2c66affSColin Finck 
6267c2c66affSColin Finck     set_textA(hwnd, WM_SETTEXT, NULL);
6268c2c66affSColin Finck     expect_empty(hwnd, WM_GETTEXT);
6269c2c66affSColin Finck     expect_empty(hwnd, EM_GETTEXTEX);
6270c2c66affSColin Finck 
6271c2c66affSColin Finck     set_textA(hwnd, WM_SETTEXT, textA);
6272c2c66affSColin Finck     expect_textA(hwnd, WM_GETTEXT, textA);
6273c2c66affSColin Finck     expect_textA(hwnd, EM_GETTEXTEX, textA);
6274c2c66affSColin Finck     expect_textW(hwnd, EM_GETTEXTEX, textW);
6275c2c66affSColin Finck 
6276c2c66affSColin Finck     if (em_settextex_supported)
6277c2c66affSColin Finck     {
6278c2c66affSColin Finck         set_textA(hwnd, EM_SETTEXTEX, textA);
6279c2c66affSColin Finck         expect_textA(hwnd, WM_GETTEXT, textA);
6280c2c66affSColin Finck         expect_textA(hwnd, EM_GETTEXTEX, textA);
6281c2c66affSColin Finck         expect_textW(hwnd, EM_GETTEXTEX, textW);
6282c2c66affSColin Finck     }
6283c2c66affSColin Finck 
6284c2c66affSColin Finck     set_textW(hwnd, WM_SETTEXT, textW);
6285c2c66affSColin Finck     expect_textW(hwnd, WM_GETTEXT, textW);
6286c2c66affSColin Finck     expect_textA(hwnd, WM_GETTEXT, textA);
6287c2c66affSColin Finck     expect_textW(hwnd, EM_GETTEXTEX, textW);
6288c2c66affSColin Finck     expect_textA(hwnd, EM_GETTEXTEX, textA);
6289c2c66affSColin Finck 
6290c2c66affSColin Finck     if (em_settextex_supported)
6291c2c66affSColin Finck     {
6292c2c66affSColin Finck         set_textW(hwnd, EM_SETTEXTEX, textW);
6293c2c66affSColin Finck         expect_textW(hwnd, WM_GETTEXT, textW);
6294c2c66affSColin Finck         expect_textA(hwnd, WM_GETTEXT, textA);
6295c2c66affSColin Finck         expect_textW(hwnd, EM_GETTEXTEX, textW);
6296c2c66affSColin Finck         expect_textA(hwnd, EM_GETTEXTEX, textA);
6297c2c66affSColin Finck     }
6298c2c66affSColin Finck     DestroyWindow(hwnd);
6299c2c66affSColin Finck 
6300c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP,
6301c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6302c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6303c2c66affSColin Finck 
6304c2c66affSColin Finck     ret = IsWindowUnicode(hwnd);
6305c2c66affSColin Finck     ok(!ret, "RichEdit20A should NOT be unicode\n");
6306c2c66affSColin Finck 
6307c2c66affSColin Finck     set_textA(hwnd, WM_SETTEXT, textA);
6308c2c66affSColin Finck     expect_textA(hwnd, WM_GETTEXT, textA);
6309c2c66affSColin Finck     expect_textA(hwnd, EM_GETTEXTEX, textA);
6310c2c66affSColin Finck     expect_textW(hwnd, EM_GETTEXTEX, textW);
6311c2c66affSColin Finck 
6312c2c66affSColin Finck     if (em_settextex_supported)
6313c2c66affSColin Finck     {
6314c2c66affSColin Finck         set_textA(hwnd, EM_SETTEXTEX, textA);
6315c2c66affSColin Finck         expect_textA(hwnd, WM_GETTEXT, textA);
6316c2c66affSColin Finck         expect_textA(hwnd, EM_GETTEXTEX, textA);
6317c2c66affSColin Finck         expect_textW(hwnd, EM_GETTEXTEX, textW);
6318c2c66affSColin Finck     }
6319c2c66affSColin Finck 
6320c2c66affSColin Finck         set_textW(hwnd, WM_SETTEXT, textW);
6321c2c66affSColin Finck         expect_textW(hwnd, WM_GETTEXT, textW);
6322c2c66affSColin Finck         expect_textA(hwnd, WM_GETTEXT, textA);
6323c2c66affSColin Finck         expect_textW(hwnd, EM_GETTEXTEX, textW);
6324c2c66affSColin Finck         expect_textA(hwnd, EM_GETTEXTEX, textA);
6325c2c66affSColin Finck 
6326c2c66affSColin Finck     if (em_settextex_supported)
6327c2c66affSColin Finck     {
6328c2c66affSColin Finck         set_textW(hwnd, EM_SETTEXTEX, textW);
6329c2c66affSColin Finck         expect_textW(hwnd, WM_GETTEXT, textW);
6330c2c66affSColin Finck         expect_textA(hwnd, WM_GETTEXT, textA);
6331c2c66affSColin Finck         expect_textW(hwnd, EM_GETTEXTEX, textW);
6332c2c66affSColin Finck         expect_textA(hwnd, EM_GETTEXTEX, textA);
6333c2c66affSColin Finck     }
6334c2c66affSColin Finck     DestroyWindow(hwnd);
6335c2c66affSColin Finck }
6336c2c66affSColin Finck 
test_WM_CHAR(void)6337c2c66affSColin Finck static void test_WM_CHAR(void)
6338c2c66affSColin Finck {
6339c2c66affSColin Finck     HWND hwnd;
6340c2c66affSColin Finck     int ret;
6341c2c66affSColin Finck     const char * char_list = "abc\rabc\r";
6342c2c66affSColin Finck     const char * expected_content_single = "abcabc";
6343c2c66affSColin Finck     const char * expected_content_multi = "abc\r\nabc\r\n";
6344c2c66affSColin Finck     char buffer[64] = {0};
6345c2c66affSColin Finck     const char * p;
6346c2c66affSColin Finck 
6347c2c66affSColin Finck     /* single-line control must IGNORE carriage returns */
6348c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
6349c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6350c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6351c2c66affSColin Finck 
6352c2c66affSColin Finck     p = char_list;
6353c2c66affSColin Finck     while (*p != '\0') {
6354c2c66affSColin Finck         SendMessageA(hwnd, WM_KEYDOWN, *p, 1);
6355c2c66affSColin Finck         ret = SendMessageA(hwnd, WM_CHAR, *p, 1);
6356c2c66affSColin Finck         ok(ret == 0, "WM_CHAR('%c') ret=%d\n", *p, ret);
6357c2c66affSColin Finck         SendMessageA(hwnd, WM_KEYUP, *p, 1);
6358c2c66affSColin Finck         p++;
6359c2c66affSColin Finck     }
6360c2c66affSColin Finck 
6361c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
6362c2c66affSColin Finck     ret = strcmp(buffer, expected_content_single);
6363c2c66affSColin Finck     ok(ret == 0, "WM_GETTEXT recovered incorrect string!\n");
6364c2c66affSColin Finck 
6365c2c66affSColin Finck     DestroyWindow(hwnd);
6366c2c66affSColin Finck 
6367c2c66affSColin Finck     /* multi-line control inserts CR normally */
6368c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE,
6369c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6370c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6371c2c66affSColin Finck 
6372c2c66affSColin Finck     p = char_list;
6373c2c66affSColin Finck     while (*p != '\0') {
6374c2c66affSColin Finck         SendMessageA(hwnd, WM_KEYDOWN, *p, 1);
6375c2c66affSColin Finck         ret = SendMessageA(hwnd, WM_CHAR, *p, 1);
6376c2c66affSColin Finck         ok(ret == 0, "WM_CHAR('%c') ret=%d\n", *p, ret);
6377c2c66affSColin Finck         SendMessageA(hwnd, WM_KEYUP, *p, 1);
6378c2c66affSColin Finck         p++;
6379c2c66affSColin Finck     }
6380c2c66affSColin Finck 
6381c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
6382c2c66affSColin Finck     ret = strcmp(buffer, expected_content_multi);
6383c2c66affSColin Finck     ok(ret == 0, "WM_GETTEXT recovered incorrect string!\n");
6384c2c66affSColin Finck 
6385c2c66affSColin Finck     DestroyWindow(hwnd);
6386c2c66affSColin Finck }
6387c2c66affSColin Finck 
test_EM_GETTEXTLENGTHEX(void)6388c2c66affSColin Finck static void test_EM_GETTEXTLENGTHEX(void)
6389c2c66affSColin Finck {
6390c2c66affSColin Finck     HWND hwnd;
6391c2c66affSColin Finck     GETTEXTLENGTHEX gtl;
6392c2c66affSColin Finck     int ret;
6393c2c66affSColin Finck     const char * base_string = "base string";
6394c2c66affSColin Finck     const char * test_string = "a\nb\n\n\r\n";
6395c2c66affSColin Finck     const char * test_string_after = "a";
6396c2c66affSColin Finck     const char * test_string_2 = "a\rtest\rstring";
6397c2c66affSColin Finck     char buffer[64] = {0};
6398c2c66affSColin Finck 
6399c2c66affSColin Finck     /* single line */
6400c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
6401c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6402c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6403c2c66affSColin Finck 
6404c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6405c2c66affSColin Finck     gtl.codepage = CP_ACP;
6406c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6407c2c66affSColin Finck     ok(ret == 0, "ret %d\n",ret);
6408c2c66affSColin Finck 
6409c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6410c2c66affSColin Finck     gtl.codepage = CP_ACP;
6411c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6412c2c66affSColin Finck     ok(ret == 0, "ret %d\n",ret);
6413c2c66affSColin Finck 
6414c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)base_string);
6415c2c66affSColin Finck 
6416c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6417c2c66affSColin Finck     gtl.codepage = CP_ACP;
6418c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6419c2c66affSColin Finck     ok(ret == strlen(base_string), "ret %d\n",ret);
6420c2c66affSColin Finck 
6421c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6422c2c66affSColin Finck     gtl.codepage = CP_ACP;
6423c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6424c2c66affSColin Finck     ok(ret == strlen(base_string), "ret %d\n",ret);
6425c2c66affSColin Finck 
6426c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_string);
6427c2c66affSColin Finck 
6428c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6429c2c66affSColin Finck     gtl.codepage = CP_ACP;
6430c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6431c2c66affSColin Finck     ok(ret == 1, "ret %d\n",ret);
6432c2c66affSColin Finck 
6433c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6434c2c66affSColin Finck     gtl.codepage = CP_ACP;
6435c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6436c2c66affSColin Finck     ok(ret == 1, "ret %d\n",ret);
6437c2c66affSColin Finck 
6438c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
6439c2c66affSColin Finck     ret = strcmp(buffer, test_string_after);
6440c2c66affSColin Finck     ok(ret == 0, "WM_GETTEXT recovered incorrect string!\n");
6441c2c66affSColin Finck 
6442c2c66affSColin Finck     DestroyWindow(hwnd);
6443c2c66affSColin Finck 
6444c2c66affSColin Finck     /* multi line */
6445c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP | ES_MULTILINE,
6446c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6447c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6448c2c66affSColin Finck 
6449c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6450c2c66affSColin Finck     gtl.codepage = CP_ACP;
6451c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6452c2c66affSColin Finck     ok(ret == 0, "ret %d\n",ret);
6453c2c66affSColin Finck 
6454c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6455c2c66affSColin Finck     gtl.codepage = CP_ACP;
6456c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6457c2c66affSColin Finck     ok(ret == 0, "ret %d\n",ret);
6458c2c66affSColin Finck 
6459c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)base_string);
6460c2c66affSColin Finck 
6461c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6462c2c66affSColin Finck     gtl.codepage = CP_ACP;
6463c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6464c2c66affSColin Finck     ok(ret == strlen(base_string), "ret %d\n",ret);
6465c2c66affSColin Finck 
6466c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6467c2c66affSColin Finck     gtl.codepage = CP_ACP;
6468c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6469c2c66affSColin Finck     ok(ret == strlen(base_string), "ret %d\n",ret);
6470c2c66affSColin Finck 
6471c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_string_2);
6472c2c66affSColin Finck 
6473c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6474c2c66affSColin Finck     gtl.codepage = CP_ACP;
6475c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6476c2c66affSColin Finck     ok(ret == strlen(test_string_2) + 2, "ret %d\n",ret);
6477c2c66affSColin Finck 
6478c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6479c2c66affSColin Finck     gtl.codepage = CP_ACP;
6480c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6481c2c66affSColin Finck     ok(ret == strlen(test_string_2), "ret %d\n",ret);
6482c2c66affSColin Finck 
6483c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_string);
6484c2c66affSColin Finck 
6485c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
6486c2c66affSColin Finck     gtl.codepage = CP_ACP;
6487c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6488c2c66affSColin Finck     ok(ret == 10, "ret %d\n",ret);
6489c2c66affSColin Finck 
6490c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6491c2c66affSColin Finck     gtl.codepage = CP_ACP;
6492c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6493c2c66affSColin Finck     ok(ret == 6, "ret %d\n",ret);
6494c2c66affSColin Finck 
6495c2c66affSColin Finck     /* Unicode/NUMCHARS/NUMBYTES */
6496c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_string_2);
6497c2c66affSColin Finck 
6498c2c66affSColin Finck     gtl.flags = GTL_DEFAULT;
6499c2c66affSColin Finck     gtl.codepage = 1200;
6500c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6501c2c66affSColin Finck     ok(ret == lstrlenA(test_string_2),
6502c2c66affSColin Finck        "GTL_DEFAULT gave %i, expected %i\n", ret, lstrlenA(test_string_2));
6503c2c66affSColin Finck 
6504c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS;
6505c2c66affSColin Finck     gtl.codepage = 1200;
6506c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6507c2c66affSColin Finck     ok(ret == lstrlenA(test_string_2),
6508c2c66affSColin Finck        "GTL_NUMCHARS gave %i, expected %i\n", ret, lstrlenA(test_string_2));
6509c2c66affSColin Finck 
6510c2c66affSColin Finck     gtl.flags = GTL_NUMBYTES;
6511c2c66affSColin Finck     gtl.codepage = 1200;
6512c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6513c2c66affSColin Finck     ok(ret == lstrlenA(test_string_2)*2,
6514c2c66affSColin Finck        "GTL_NUMBYTES gave %i, expected %i\n", ret, lstrlenA(test_string_2)*2);
6515c2c66affSColin Finck 
6516c2c66affSColin Finck     gtl.flags = GTL_PRECISE;
6517c2c66affSColin Finck     gtl.codepage = 1200;
6518c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6519c2c66affSColin Finck     ok(ret == lstrlenA(test_string_2)*2,
6520c2c66affSColin Finck        "GTL_PRECISE gave %i, expected %i\n", ret, lstrlenA(test_string_2)*2);
6521c2c66affSColin Finck 
6522c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_PRECISE;
6523c2c66affSColin Finck     gtl.codepage = 1200;
6524c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6525c2c66affSColin Finck     ok(ret == lstrlenA(test_string_2),
6526c2c66affSColin Finck        "GTL_NUMCHAR | GTL_PRECISE gave %i, expected %i\n", ret, lstrlenA(test_string_2));
6527c2c66affSColin Finck 
6528c2c66affSColin Finck     gtl.flags = GTL_NUMCHARS | GTL_NUMBYTES;
6529c2c66affSColin Finck     gtl.codepage = 1200;
6530c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
6531c2c66affSColin Finck     ok(ret == E_INVALIDARG,
6532c2c66affSColin Finck        "GTL_NUMCHARS | GTL_NUMBYTES gave %i, expected %i\n", ret, E_INVALIDARG);
6533c2c66affSColin Finck 
6534c2c66affSColin Finck     DestroyWindow(hwnd);
6535c2c66affSColin Finck }
6536c2c66affSColin Finck 
6537c2c66affSColin Finck 
6538c2c66affSColin Finck /* globals that parent and child access when checking event masks & notifications */
6539c2c66affSColin Finck static HWND eventMaskEditHwnd = 0;
6540c2c66affSColin Finck static int queriedEventMask;
6541c2c66affSColin Finck static int watchForEventMask = 0;
6542c2c66affSColin Finck 
6543c2c66affSColin Finck /* parent proc that queries the edit's event mask when it gets a WM_COMMAND */
ParentMsgCheckProcA(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)6544c2c66affSColin Finck static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6545c2c66affSColin Finck {
6546c2c66affSColin Finck     if(message == WM_COMMAND && (watchForEventMask & (wParam >> 16)))
6547c2c66affSColin Finck     {
6548c2c66affSColin Finck       queriedEventMask = SendMessageA(eventMaskEditHwnd, EM_GETEVENTMASK, 0, 0);
6549c2c66affSColin Finck     }
6550c2c66affSColin Finck     return DefWindowProcA(hwnd, message, wParam, lParam);
6551c2c66affSColin Finck }
6552c2c66affSColin Finck 
6553c2c66affSColin Finck /* test event masks in combination with WM_COMMAND */
test_eventMask(void)6554c2c66affSColin Finck static void test_eventMask(void)
6555c2c66affSColin Finck {
6556c2c66affSColin Finck     HWND parent;
6557c2c66affSColin Finck     int ret, style;
6558c2c66affSColin Finck     WNDCLASSA cls;
6559c2c66affSColin Finck     const char text[] = "foo bar\n";
6560c2c66affSColin Finck     int eventMask;
6561c2c66affSColin Finck 
6562c2c66affSColin Finck     /* register class to capture WM_COMMAND */
6563c2c66affSColin Finck     cls.style = 0;
6564c2c66affSColin Finck     cls.lpfnWndProc = ParentMsgCheckProcA;
6565c2c66affSColin Finck     cls.cbClsExtra = 0;
6566c2c66affSColin Finck     cls.cbWndExtra = 0;
6567c2c66affSColin Finck     cls.hInstance = GetModuleHandleA(0);
6568c2c66affSColin Finck     cls.hIcon = 0;
6569c2c66affSColin Finck     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6570c2c66affSColin Finck     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6571c2c66affSColin Finck     cls.lpszMenuName = NULL;
6572c2c66affSColin Finck     cls.lpszClassName = "EventMaskParentClass";
6573c2c66affSColin Finck     if(!RegisterClassA(&cls)) assert(0);
6574c2c66affSColin Finck 
6575c2c66affSColin Finck     parent = CreateWindowA(cls.lpszClassName, NULL, WS_POPUP|WS_VISIBLE,
6576c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, NULL, NULL);
6577c2c66affSColin Finck     ok (parent != 0, "Failed to create parent window\n");
6578c2c66affSColin Finck 
6579c2c66affSColin Finck     eventMaskEditHwnd = new_richedit(parent);
6580c2c66affSColin Finck     ok(eventMaskEditHwnd != 0, "Failed to create edit window\n");
6581c2c66affSColin Finck 
6582c2c66affSColin Finck     eventMask = ENM_CHANGE | ENM_UPDATE;
6583c2c66affSColin Finck     ret = SendMessageA(eventMaskEditHwnd, EM_SETEVENTMASK, 0, eventMask);
6584c2c66affSColin Finck     ok(ret == ENM_NONE, "wrong event mask\n");
6585c2c66affSColin Finck     ret = SendMessageA(eventMaskEditHwnd, EM_GETEVENTMASK, 0, 0);
6586c2c66affSColin Finck     ok(ret == eventMask, "failed to set event mask\n");
6587c2c66affSColin Finck 
6588c2c66affSColin Finck     /* check what happens when we ask for EN_CHANGE and send WM_SETTEXT */
6589c2c66affSColin Finck     queriedEventMask = 0;  /* initialize to something other than we expect */
6590c2c66affSColin Finck     watchForEventMask = EN_CHANGE;
6591c2c66affSColin Finck     ret = SendMessageA(eventMaskEditHwnd, WM_SETTEXT, 0, (LPARAM)text);
6592c2c66affSColin Finck     ok(ret == TRUE, "failed to set text\n");
6593c2c66affSColin Finck     /* richedit should mask off ENM_CHANGE when it sends an EN_CHANGE
6594c2c66affSColin Finck        notification in response to WM_SETTEXT */
6595c2c66affSColin Finck     ok(queriedEventMask == (eventMask & ~ENM_CHANGE),
6596c2c66affSColin Finck             "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
6597c2c66affSColin Finck 
6598c2c66affSColin Finck     /* check to see if EN_CHANGE is sent when redraw is turned off */
6599c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, WM_CLEAR, 0, 0);
6600c2c66affSColin Finck     ok(IsWindowVisible(eventMaskEditHwnd), "Window should be visible.\n");
6601c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, WM_SETREDRAW, FALSE, 0);
6602c2c66affSColin Finck     /* redraw is disabled by making the window invisible. */
6603c2c66affSColin Finck     ok(!IsWindowVisible(eventMaskEditHwnd), "Window shouldn't be visible.\n");
6604c2c66affSColin Finck     queriedEventMask = 0;  /* initialize to something other than we expect */
6605c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, EM_REPLACESEL, 0, (LPARAM)text);
6606c2c66affSColin Finck     ok(queriedEventMask == (eventMask & ~ENM_CHANGE),
6607c2c66affSColin Finck             "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
6608c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, WM_SETREDRAW, TRUE, 0);
6609c2c66affSColin Finck     ok(IsWindowVisible(eventMaskEditHwnd), "Window should be visible.\n");
6610c2c66affSColin Finck 
6611c2c66affSColin Finck     /* check to see if EN_UPDATE is sent when the editor isn't visible */
6612c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, WM_CLEAR, 0, 0);
6613c2c66affSColin Finck     style = GetWindowLongA(eventMaskEditHwnd, GWL_STYLE);
6614c2c66affSColin Finck     SetWindowLongA(eventMaskEditHwnd, GWL_STYLE, style & ~WS_VISIBLE);
6615c2c66affSColin Finck     ok(!IsWindowVisible(eventMaskEditHwnd), "Window shouldn't be visible.\n");
6616c2c66affSColin Finck     watchForEventMask = EN_UPDATE;
6617c2c66affSColin Finck     queriedEventMask = 0;  /* initialize to something other than we expect */
6618c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, EM_REPLACESEL, 0, (LPARAM)text);
6619c2c66affSColin Finck     ok(queriedEventMask == 0,
6620c2c66affSColin Finck             "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
6621c2c66affSColin Finck     SetWindowLongA(eventMaskEditHwnd, GWL_STYLE, style);
6622c2c66affSColin Finck     ok(IsWindowVisible(eventMaskEditHwnd), "Window should be visible.\n");
6623c2c66affSColin Finck     queriedEventMask = 0;  /* initialize to something other than we expect */
6624c2c66affSColin Finck     SendMessageA(eventMaskEditHwnd, EM_REPLACESEL, 0, (LPARAM)text);
6625c2c66affSColin Finck     ok(queriedEventMask == eventMask,
6626c2c66affSColin Finck             "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
6627c2c66affSColin Finck 
6628c2c66affSColin Finck 
6629c2c66affSColin Finck     DestroyWindow(parent);
6630c2c66affSColin Finck }
6631c2c66affSColin Finck 
6632c2c66affSColin Finck static int received_WM_NOTIFY = 0;
6633c2c66affSColin Finck static int modify_at_WM_NOTIFY = 0;
6634c2c66affSColin Finck static BOOL filter_on_WM_NOTIFY = FALSE;
6635c2c66affSColin Finck static HWND hwndRichedit_WM_NOTIFY;
6636c2c66affSColin Finck 
WM_NOTIFY_ParentMsgCheckProcA(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)6637c2c66affSColin Finck static LRESULT WINAPI WM_NOTIFY_ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6638c2c66affSColin Finck {
6639c2c66affSColin Finck     if(message == WM_NOTIFY)
6640c2c66affSColin Finck     {
6641c2c66affSColin Finck       received_WM_NOTIFY = 1;
6642c2c66affSColin Finck       modify_at_WM_NOTIFY = SendMessageA(hwndRichedit_WM_NOTIFY, EM_GETMODIFY, 0, 0);
6643c2c66affSColin Finck       if (filter_on_WM_NOTIFY) return TRUE;
6644c2c66affSColin Finck     }
6645c2c66affSColin Finck     return DefWindowProcA(hwnd, message, wParam, lParam);
6646c2c66affSColin Finck }
6647c2c66affSColin Finck 
test_WM_NOTIFY(void)6648c2c66affSColin Finck static void test_WM_NOTIFY(void)
6649c2c66affSColin Finck {
6650c2c66affSColin Finck     HWND parent;
6651c2c66affSColin Finck     WNDCLASSA cls;
6652c2c66affSColin Finck     CHARFORMAT2A cf2;
6653c2c66affSColin Finck     int sel_start, sel_end;
6654c2c66affSColin Finck 
6655c2c66affSColin Finck     /* register class to capture WM_NOTIFY */
6656c2c66affSColin Finck     cls.style = 0;
6657c2c66affSColin Finck     cls.lpfnWndProc = WM_NOTIFY_ParentMsgCheckProcA;
6658c2c66affSColin Finck     cls.cbClsExtra = 0;
6659c2c66affSColin Finck     cls.cbWndExtra = 0;
6660c2c66affSColin Finck     cls.hInstance = GetModuleHandleA(0);
6661c2c66affSColin Finck     cls.hIcon = 0;
6662c2c66affSColin Finck     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6663c2c66affSColin Finck     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6664c2c66affSColin Finck     cls.lpszMenuName = NULL;
6665c2c66affSColin Finck     cls.lpszClassName = "WM_NOTIFY_ParentClass";
6666c2c66affSColin Finck     if(!RegisterClassA(&cls)) assert(0);
6667c2c66affSColin Finck 
6668c2c66affSColin Finck     parent = CreateWindowA(cls.lpszClassName, NULL, WS_POPUP|WS_VISIBLE,
6669c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, NULL, NULL);
6670c2c66affSColin Finck     ok (parent != 0, "Failed to create parent window\n");
6671c2c66affSColin Finck 
6672c2c66affSColin Finck     hwndRichedit_WM_NOTIFY = new_richedit(parent);
6673c2c66affSColin Finck     ok(hwndRichedit_WM_NOTIFY != 0, "Failed to create edit window\n");
6674c2c66affSColin Finck 
6675c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_SETEVENTMASK, 0, ENM_SELCHANGE);
6676c2c66affSColin Finck 
6677c2c66affSColin Finck     /* Notifications for selection change should only be sent when selection
6678c2c66affSColin Finck        actually changes. EM_SETCHARFORMAT is one message that calls
6679c2c66affSColin Finck        ME_CommitUndo, which should check whether message should be sent */
6680c2c66affSColin Finck     received_WM_NOTIFY = 0;
6681c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
6682c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2);
6683c2c66affSColin Finck     cf2.dwMask = CFM_ITALIC | cf2.dwMask;
6684c2c66affSColin Finck     cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
6685c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_SETCHARFORMAT, 0, (LPARAM)&cf2);
6686c2c66affSColin Finck     ok(received_WM_NOTIFY == 0, "Unexpected WM_NOTIFY was sent!\n");
6687c2c66affSColin Finck 
6688c2c66affSColin Finck     /* WM_SETTEXT should NOT cause a WM_NOTIFY to be sent when selection is
6689c2c66affSColin Finck        already at 0. */
6690c2c66affSColin Finck     received_WM_NOTIFY = 0;
6691c2c66affSColin Finck     modify_at_WM_NOTIFY = 0;
6692c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_SETTEXT, 0, (LPARAM)"sometext");
6693c2c66affSColin Finck     ok(received_WM_NOTIFY == 0, "Unexpected WM_NOTIFY was sent!\n");
6694c2c66affSColin Finck     ok(modify_at_WM_NOTIFY == 0, "WM_NOTIFY callback saw text flagged as modified!\n");
6695c2c66affSColin Finck 
6696c2c66affSColin Finck     received_WM_NOTIFY = 0;
6697c2c66affSColin Finck     modify_at_WM_NOTIFY = 0;
6698c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_SETSEL, 4, 4);
6699c2c66affSColin Finck     ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
6700c2c66affSColin Finck 
6701c2c66affSColin Finck     received_WM_NOTIFY = 0;
6702c2c66affSColin Finck     modify_at_WM_NOTIFY = 0;
6703c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_SETTEXT, 0, (LPARAM)"sometext");
6704c2c66affSColin Finck     ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
6705c2c66affSColin Finck     ok(modify_at_WM_NOTIFY == 0, "WM_NOTIFY callback saw text flagged as modified!\n");
6706c2c66affSColin Finck 
6707c2c66affSColin Finck     /* Test for WM_NOTIFY messages with redraw disabled. */
6708c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_SETSEL, 0, 0);
6709c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_SETREDRAW, FALSE, 0);
6710c2c66affSColin Finck     received_WM_NOTIFY = 0;
6711c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_REPLACESEL, FALSE, (LPARAM)"inserted");
6712c2c66affSColin Finck     ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
6713c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_SETREDRAW, TRUE, 0);
6714c2c66affSColin Finck 
6715c2c66affSColin Finck     /* Test filtering key events. */
6716c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_SETSEL, 0, 0);
6717c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_SETEVENTMASK, 0, ENM_KEYEVENTS);
6718c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
6719c2c66affSColin Finck     received_WM_NOTIFY = 0;
6720c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_KEYDOWN, VK_RIGHT, 0);
6721c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
6722c2c66affSColin Finck     ok(sel_start == 1 && sel_end == 1,
6723c2c66affSColin Finck        "selections is incorrectly at (%d,%d)\n", sel_start, sel_end);
6724c2c66affSColin Finck     filter_on_WM_NOTIFY = TRUE;
6725c2c66affSColin Finck     received_WM_NOTIFY = 0;
6726c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_KEYDOWN, VK_RIGHT, 0);
6727c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
6728c2c66affSColin Finck     ok(sel_start == 1 && sel_end == 1,
6729c2c66affSColin Finck        "selections is incorrectly at (%d,%d)\n", sel_start, sel_end);
6730c2c66affSColin Finck 
6731c2c66affSColin Finck     /* test with owner set to NULL */
6732c2c66affSColin Finck     SetWindowLongPtrA(hwndRichedit_WM_NOTIFY, GWLP_HWNDPARENT, 0);
6733c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, WM_KEYDOWN, VK_RIGHT, 0);
6734c2c66affSColin Finck     SendMessageA(hwndRichedit_WM_NOTIFY, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
6735c2c66affSColin Finck     ok(sel_start == 1 && sel_end == 1,
6736c2c66affSColin Finck        "selections is incorrectly at (%d,%d)\n", sel_start, sel_end);
6737c2c66affSColin Finck 
6738c2c66affSColin Finck     DestroyWindow(hwndRichedit_WM_NOTIFY);
6739c2c66affSColin Finck     DestroyWindow(parent);
6740c2c66affSColin Finck }
6741c2c66affSColin Finck 
6742c2c66affSColin Finck static ENLINK enlink;
6743c2c66affSColin Finck #define CURSOR_CLIENT_X 5
6744c2c66affSColin Finck #define CURSOR_CLIENT_Y 5
6745c2c66affSColin Finck #define WP_PARENT 1
6746c2c66affSColin Finck #define WP_CHILD 2
6747c2c66affSColin Finck 
EN_LINK_ParentMsgCheckProcA(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)6748c2c66affSColin Finck static LRESULT WINAPI EN_LINK_ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6749c2c66affSColin Finck {
6750c2c66affSColin Finck     if(message == WM_NOTIFY && ((NMHDR*)lParam)->code == EN_LINK)
6751c2c66affSColin Finck     {
6752c2c66affSColin Finck         enlink = *(ENLINK*)lParam;
6753c2c66affSColin Finck     }
6754c2c66affSColin Finck     return DefWindowProcA(hwnd, message, wParam, lParam);
6755c2c66affSColin Finck }
6756c2c66affSColin Finck 
link_notify_test(const char * desc,int i,HWND hwnd,HWND parent,UINT msg,WPARAM wParam,LPARAM lParam,BOOL notifies)6757c2c66affSColin Finck static void link_notify_test(const char *desc, int i, HWND hwnd, HWND parent,
6758c2c66affSColin Finck                              UINT msg, WPARAM wParam, LPARAM lParam, BOOL notifies)
6759c2c66affSColin Finck {
6760c2c66affSColin Finck     ENLINK junk_enlink;
6761c2c66affSColin Finck 
6762c2c66affSColin Finck     switch (msg)
6763c2c66affSColin Finck     {
6764c2c66affSColin Finck     case WM_LBUTTONDBLCLK:
6765c2c66affSColin Finck     case WM_LBUTTONDOWN:
6766c2c66affSColin Finck     case WM_LBUTTONUP:
6767c2c66affSColin Finck     case WM_MOUSEHOVER:
6768c2c66affSColin Finck     case WM_MOUSEMOVE:
6769c2c66affSColin Finck     case WM_MOUSEWHEEL:
6770c2c66affSColin Finck     case WM_RBUTTONDBLCLK:
6771c2c66affSColin Finck     case WM_RBUTTONDOWN:
6772c2c66affSColin Finck     case WM_RBUTTONUP:
6773c2c66affSColin Finck         lParam = MAKELPARAM(CURSOR_CLIENT_X, CURSOR_CLIENT_Y);
6774c2c66affSColin Finck         break;
6775c2c66affSColin Finck     case WM_SETCURSOR:
6776c2c66affSColin Finck         if (wParam == WP_PARENT)
6777c2c66affSColin Finck             wParam = (WPARAM)parent;
6778c2c66affSColin Finck         else if (wParam == WP_CHILD)
6779c2c66affSColin Finck             wParam = (WPARAM)hwnd;
6780c2c66affSColin Finck         break;
6781c2c66affSColin Finck     }
6782c2c66affSColin Finck 
6783c2c66affSColin Finck     memset(&junk_enlink, 0x23, sizeof(junk_enlink));
6784c2c66affSColin Finck     enlink = junk_enlink;
6785c2c66affSColin Finck 
6786c2c66affSColin Finck     SendMessageA(hwnd, msg, wParam, lParam);
6787c2c66affSColin Finck 
6788c2c66affSColin Finck     if (notifies)
6789c2c66affSColin Finck     {
6790c2c66affSColin Finck         ok(enlink.nmhdr.hwndFrom == hwnd,
6791c2c66affSColin Finck            "%s test %i: Expected hwnd %p got %p\n", desc, i, hwnd, enlink.nmhdr.hwndFrom);
6792c2c66affSColin Finck         ok(enlink.nmhdr.idFrom == 0,
6793c2c66affSColin Finck            "%s test %i: Expected idFrom 0 got 0x%lx\n", desc, i, enlink.nmhdr.idFrom);
6794c2c66affSColin Finck         ok(enlink.msg == msg,
6795c2c66affSColin Finck            "%s test %i: Expected msg 0x%x got 0x%x\n", desc, i, msg, enlink.msg);
6796c2c66affSColin Finck         if (msg == WM_SETCURSOR)
6797c2c66affSColin Finck         {
6798c2c66affSColin Finck             ok(enlink.wParam == 0,
6799c2c66affSColin Finck                "%s test %i: Expected wParam 0 got 0x%lx\n", desc, i, enlink.wParam);
6800c2c66affSColin Finck         }
6801c2c66affSColin Finck         else
6802c2c66affSColin Finck         {
6803c2c66affSColin Finck             ok(enlink.wParam == wParam,
6804c2c66affSColin Finck                "%s test %i: Expected wParam 0x%lx got 0x%lx\n", desc, i, wParam, enlink.wParam);
6805c2c66affSColin Finck         }
6806c2c66affSColin Finck         ok(enlink.lParam == MAKELPARAM(CURSOR_CLIENT_X, CURSOR_CLIENT_Y),
6807c2c66affSColin Finck            "%s test %i: Expected lParam 0x%lx got 0x%lx\n",
6808c2c66affSColin Finck            desc, i, MAKELPARAM(CURSOR_CLIENT_X, CURSOR_CLIENT_Y), enlink.lParam);
6809c2c66affSColin Finck         ok(enlink.chrg.cpMin == 0 && enlink.chrg.cpMax == 31,
6810c2c66affSColin Finck            "%s test %i: Expected link range [0,31) got [%i,%i)\n", desc, i, enlink.chrg.cpMin, enlink.chrg.cpMax);
6811c2c66affSColin Finck     }
6812c2c66affSColin Finck     else
6813c2c66affSColin Finck     {
6814c2c66affSColin Finck         ok(memcmp(&enlink, &junk_enlink, sizeof(enlink)) == 0,
6815c2c66affSColin Finck            "%s test %i: Expected enlink to remain unmodified\n", desc, i);
6816c2c66affSColin Finck     }
6817c2c66affSColin Finck }
6818c2c66affSColin Finck 
test_EN_LINK(void)6819c2c66affSColin Finck static void test_EN_LINK(void)
6820c2c66affSColin Finck {
6821c2c66affSColin Finck     HWND hwnd, parent;
6822c2c66affSColin Finck     WNDCLASSA cls;
6823c2c66affSColin Finck     CHARFORMAT2A cf2;
6824c2c66affSColin Finck     POINT orig_cursor_pos;
6825c2c66affSColin Finck     POINT cursor_screen_pos = {CURSOR_CLIENT_X, CURSOR_CLIENT_Y};
6826c2c66affSColin Finck     int i;
6827c2c66affSColin Finck 
6828c2c66affSColin Finck     static const struct
6829c2c66affSColin Finck     {
6830c2c66affSColin Finck         UINT msg;
6831c2c66affSColin Finck         WPARAM wParam;
6832c2c66affSColin Finck         LPARAM lParam;
6833c2c66affSColin Finck         BOOL notifies;
6834c2c66affSColin Finck     }
6835c2c66affSColin Finck     link_notify_tests[] =
6836c2c66affSColin Finck     {
6837c2c66affSColin Finck         /* hold down the left button and try some messages */
6838c2c66affSColin Finck         { WM_LBUTTONDOWN,    0,          0,  TRUE  }, /* 0 */
6839c2c66affSColin Finck         { EM_LINESCROLL,     0,          1,  FALSE },
6840c2c66affSColin Finck         { EM_SCROLL,         SB_BOTTOM,  0,  FALSE },
6841c2c66affSColin Finck         { WM_LBUTTONDBLCLK,  0,          0,  TRUE  },
6842c2c66affSColin Finck         { WM_MOUSEHOVER,     0,          0,  FALSE },
6843c2c66affSColin Finck         { WM_MOUSEMOVE,      0,          0,  FALSE },
6844c2c66affSColin Finck         { WM_MOUSEWHEEL,     0,          0,  FALSE },
6845c2c66affSColin Finck         { WM_RBUTTONDBLCLK,  0,          0,  TRUE  },
6846c2c66affSColin Finck         { WM_RBUTTONDOWN,    0,          0,  TRUE  },
6847c2c66affSColin Finck         { WM_RBUTTONUP,      0,          0,  TRUE  },
6848c2c66affSColin Finck         { WM_SETCURSOR,      0,          0,  FALSE },
6849c2c66affSColin Finck         { WM_SETCURSOR,      WP_PARENT,  0,  FALSE },
6850c2c66affSColin Finck         { WM_SETCURSOR,      WP_CHILD,   0,  TRUE  },
6851c2c66affSColin Finck         { WM_SETCURSOR,      WP_CHILD,   1,  TRUE  },
6852c2c66affSColin Finck         { WM_VSCROLL,        SB_BOTTOM,  0,  FALSE },
6853c2c66affSColin Finck         { WM_LBUTTONUP,      0,          0,  TRUE  },
6854c2c66affSColin Finck         /* hold down the right button and try some messages */
6855c2c66affSColin Finck         { WM_RBUTTONDOWN,    0,          0,  TRUE  }, /* 16 */
6856c2c66affSColin Finck         { EM_LINESCROLL,     0,          1,  FALSE },
6857c2c66affSColin Finck         { EM_SCROLL,         SB_BOTTOM,  0,  FALSE },
6858c2c66affSColin Finck         { WM_LBUTTONDBLCLK,  0,          0,  TRUE  },
6859c2c66affSColin Finck         { WM_LBUTTONDOWN,    0,          0,  TRUE  },
6860c2c66affSColin Finck         { WM_LBUTTONUP,      0,          0,  TRUE  },
6861c2c66affSColin Finck         { WM_MOUSEHOVER,     0,          0,  FALSE },
6862c2c66affSColin Finck         { WM_MOUSEMOVE,      0,          0,  TRUE  },
6863c2c66affSColin Finck         { WM_MOUSEWHEEL,     0,          0,  FALSE },
6864c2c66affSColin Finck         { WM_RBUTTONDBLCLK,  0,          0,  TRUE  },
6865c2c66affSColin Finck         { WM_SETCURSOR,      0,          0,  FALSE },
6866c2c66affSColin Finck         { WM_SETCURSOR,      WP_PARENT,  0,  FALSE },
6867c2c66affSColin Finck         { WM_SETCURSOR,      WP_CHILD,   0,  TRUE  },
6868c2c66affSColin Finck         { WM_SETCURSOR,      WP_CHILD,   1,  TRUE  },
6869c2c66affSColin Finck         { WM_VSCROLL,        SB_BOTTOM,  0,  FALSE },
6870c2c66affSColin Finck         { WM_RBUTTONUP,      0,          0,  TRUE  },
6871c2c66affSColin Finck         /* try the messages with both buttons released */
6872c2c66affSColin Finck         { EM_LINESCROLL,     0,          1,  FALSE }, /* 32 */
6873c2c66affSColin Finck         { EM_SCROLL,         SB_BOTTOM,  0,  FALSE },
6874c2c66affSColin Finck         { WM_LBUTTONDBLCLK,  0,          0,  TRUE  },
6875c2c66affSColin Finck         { WM_LBUTTONDOWN,    0,          0,  TRUE  },
6876c2c66affSColin Finck         { WM_LBUTTONUP,      0,          0,  TRUE  },
6877c2c66affSColin Finck         { WM_MOUSEHOVER,     0,          0,  FALSE },
6878c2c66affSColin Finck         { WM_MOUSEMOVE,      0,          0,  TRUE  },
6879c2c66affSColin Finck         { WM_MOUSEWHEEL,     0,          0,  FALSE },
6880c2c66affSColin Finck         { WM_RBUTTONDBLCLK,  0,          0,  TRUE  },
6881c2c66affSColin Finck         { WM_RBUTTONDOWN,    0,          0,  TRUE  },
6882c2c66affSColin Finck         { WM_RBUTTONUP,      0,          0,  TRUE  },
6883c2c66affSColin Finck         { WM_SETCURSOR,      0,          0,  FALSE },
6884c2c66affSColin Finck         { WM_SETCURSOR,      WP_CHILD,   0,  TRUE  },
6885c2c66affSColin Finck         { WM_SETCURSOR,      WP_CHILD,   1,  TRUE  },
6886c2c66affSColin Finck         { WM_SETCURSOR,      WP_PARENT,  0,  FALSE },
6887c2c66affSColin Finck         { WM_VSCROLL,        SB_BOTTOM,  0,  FALSE }
6888c2c66affSColin Finck     };
6889c2c66affSColin Finck 
6890c2c66affSColin Finck     /* register class to capture WM_NOTIFY */
6891c2c66affSColin Finck     cls.style = 0;
6892c2c66affSColin Finck     cls.lpfnWndProc = EN_LINK_ParentMsgCheckProcA;
6893c2c66affSColin Finck     cls.cbClsExtra = 0;
6894c2c66affSColin Finck     cls.cbWndExtra = 0;
6895c2c66affSColin Finck     cls.hInstance = GetModuleHandleA(0);
6896c2c66affSColin Finck     cls.hIcon = 0;
6897c2c66affSColin Finck     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6898c2c66affSColin Finck     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6899c2c66affSColin Finck     cls.lpszMenuName = NULL;
6900c2c66affSColin Finck     cls.lpszClassName = "EN_LINK_ParentClass";
6901c2c66affSColin Finck     if(!RegisterClassA(&cls)) assert(0);
6902c2c66affSColin Finck 
6903c2c66affSColin Finck     parent = CreateWindowA(cls.lpszClassName, NULL, WS_POPUP|WS_VISIBLE,
6904c2c66affSColin Finck                            0, 0, 200, 60, NULL, NULL, NULL, NULL);
6905c2c66affSColin Finck     ok(parent != 0, "Failed to create parent window\n");
6906c2c66affSColin Finck 
6907c2c66affSColin Finck     hwnd = new_richedit(parent);
6908c2c66affSColin Finck     ok(hwnd != 0, "Failed to create edit window\n");
6909c2c66affSColin Finck 
6910c2c66affSColin Finck     SendMessageA(hwnd, EM_SETEVENTMASK, 0, ENM_LINK);
6911c2c66affSColin Finck 
6912c2c66affSColin Finck     cf2.cbSize = sizeof(CHARFORMAT2A);
6913c2c66affSColin Finck     cf2.dwMask = CFM_LINK;
6914c2c66affSColin Finck     cf2.dwEffects = CFE_LINK;
6915c2c66affSColin Finck     SendMessageA(hwnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf2);
6916c2c66affSColin Finck     /* mixing letters and numbers causes runs to be split */
6917c2c66affSColin Finck     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"link text with at least 2 runs");
6918c2c66affSColin Finck 
6919c2c66affSColin Finck     GetCursorPos(&orig_cursor_pos);
6920c2c66affSColin Finck     SetCursorPos(0, 0);
6921c2c66affSColin Finck 
692276cf09cfSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(link_notify_tests); i++)
6923c2c66affSColin Finck     {
6924c2c66affSColin Finck         link_notify_test("cursor position simulated", i, hwnd, parent,
6925c2c66affSColin Finck                          link_notify_tests[i].msg, link_notify_tests[i].wParam, link_notify_tests[i].lParam,
6926c2c66affSColin Finck                          link_notify_tests[i].msg == WM_SETCURSOR ? FALSE : link_notify_tests[i].notifies);
6927c2c66affSColin Finck     }
6928c2c66affSColin Finck 
6929c2c66affSColin Finck     ClientToScreen(hwnd, &cursor_screen_pos);
6930c2c66affSColin Finck     SetCursorPos(cursor_screen_pos.x, cursor_screen_pos.y);
6931c2c66affSColin Finck 
693276cf09cfSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(link_notify_tests); i++)
6933c2c66affSColin Finck     {
6934c2c66affSColin Finck         link_notify_test("cursor position set", i, hwnd, parent,
6935c2c66affSColin Finck                          link_notify_tests[i].msg, link_notify_tests[i].wParam, link_notify_tests[i].lParam,
6936c2c66affSColin Finck                          link_notify_tests[i].notifies);
6937c2c66affSColin Finck     }
6938c2c66affSColin Finck 
6939c2c66affSColin Finck     SetCursorPos(orig_cursor_pos.x, orig_cursor_pos.y);
6940c2c66affSColin Finck     DestroyWindow(hwnd);
6941c2c66affSColin Finck     DestroyWindow(parent);
6942c2c66affSColin Finck }
6943c2c66affSColin Finck 
test_undo_coalescing(void)6944c2c66affSColin Finck static void test_undo_coalescing(void)
6945c2c66affSColin Finck {
6946c2c66affSColin Finck     HWND hwnd;
6947c2c66affSColin Finck     int result;
6948c2c66affSColin Finck     char buffer[64] = {0};
6949c2c66affSColin Finck 
6950c2c66affSColin Finck     /* multi-line control inserts CR normally */
6951c2c66affSColin Finck     hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE,
6952c2c66affSColin Finck                            0, 0, 200, 60, 0, 0, 0, 0);
6953c2c66affSColin Finck     ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
6954c2c66affSColin Finck 
6955c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANUNDO, 0, 0);
6956c2c66affSColin Finck     ok (result == FALSE, "Can undo after window creation.\n");
6957c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
6958c2c66affSColin Finck     ok (result == FALSE, "Undo operation successful with nothing to undo.\n");
6959c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANREDO, 0, 0);
6960c2c66affSColin Finck     ok (result == FALSE, "Can redo after window creation.\n");
6961c2c66affSColin Finck     result = SendMessageA(hwnd, EM_REDO, 0, 0);
6962c2c66affSColin Finck     ok (result == FALSE, "Redo operation successful with nothing undone.\n");
6963c2c66affSColin Finck 
6964c2c66affSColin Finck     /* Test the effect of arrows keys during typing on undo transactions*/
6965c2c66affSColin Finck     simulate_typing_characters(hwnd, "one two three");
6966c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYDOWN, VK_RIGHT, 1);
6967c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYUP, VK_RIGHT, 1);
6968c2c66affSColin Finck     simulate_typing_characters(hwnd, " four five six");
6969c2c66affSColin Finck 
6970c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANREDO, 0, 0);
6971c2c66affSColin Finck     ok (result == FALSE, "Can redo before anything is undone.\n");
6972c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANUNDO, 0, 0);
6973c2c66affSColin Finck     ok (result == TRUE, "Cannot undo typed characters.\n");
6974c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
6975c2c66affSColin Finck     ok (result == TRUE, "EM_UNDO Failed to undo typed characters.\n");
6976c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANREDO, 0, 0);
6977c2c66affSColin Finck     ok (result == TRUE, "Cannot redo after undo.\n");
6978c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
6979c2c66affSColin Finck     result = strcmp(buffer, "one two three");
6980c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "one two three", buffer);
6981c2c66affSColin Finck 
6982c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANUNDO, 0, 0);
6983c2c66affSColin Finck     ok (result == TRUE, "Cannot undo typed characters.\n");
6984c2c66affSColin Finck     result = SendMessageA(hwnd, WM_UNDO, 0, 0);
6985c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
6986c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
6987c2c66affSColin Finck     result = strcmp(buffer, "");
6988c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "", buffer);
6989c2c66affSColin Finck 
6990c2c66affSColin Finck     /* Test the effect of focus changes during typing on undo transactions*/
6991c2c66affSColin Finck     simulate_typing_characters(hwnd, "one two three");
6992c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANREDO, 0, 0);
6993c2c66affSColin Finck     ok (result == FALSE, "Redo buffer should have been cleared by typing.\n");
6994c2c66affSColin Finck     SendMessageA(hwnd, WM_KILLFOCUS, 0, 0);
6995c2c66affSColin Finck     SendMessageA(hwnd, WM_SETFOCUS, 0, 0);
6996c2c66affSColin Finck     simulate_typing_characters(hwnd, " four five six");
6997c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
6998c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
6999c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
7000c2c66affSColin Finck     result = strcmp(buffer, "one two three");
7001c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "one two three", buffer);
7002c2c66affSColin Finck 
7003c2c66affSColin Finck     /* Test the effect of the back key during typing on undo transactions */
7004c2c66affSColin Finck     SendMessageA(hwnd, EM_EMPTYUNDOBUFFER, 0, 0);
7005c2c66affSColin Finck     result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
7006c2c66affSColin Finck     ok (result == TRUE, "Failed to clear the text.\n");
7007c2c66affSColin Finck     simulate_typing_characters(hwnd, "one two threa");
7008c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CANREDO, 0, 0);
7009c2c66affSColin Finck     ok (result == FALSE, "Redo buffer should have been cleared by typing.\n");
7010c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYDOWN, VK_BACK, 1);
7011c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYUP, VK_BACK, 1);
7012c2c66affSColin Finck     simulate_typing_characters(hwnd, "e four five six");
7013c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
7014c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
7015c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
7016c2c66affSColin Finck     result = strcmp(buffer, "");
7017c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "", buffer);
7018c2c66affSColin Finck 
7019c2c66affSColin Finck     /* Test the effect of the delete key during typing on undo transactions */
7020c2c66affSColin Finck     SendMessageA(hwnd, EM_EMPTYUNDOBUFFER, 0, 0);
7021c2c66affSColin Finck     result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"abcd");
7022c2c66affSColin Finck     ok(result == TRUE, "Failed to set the text.\n");
7023c2c66affSColin Finck     SendMessageA(hwnd, EM_SETSEL, 1, 1);
7024c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYDOWN, VK_DELETE, 1);
7025c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYUP, VK_DELETE, 1);
7026c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYDOWN, VK_DELETE, 1);
7027c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYUP, VK_DELETE, 1);
7028c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
7029c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
7030c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
7031c2c66affSColin Finck     result = strcmp(buffer, "acd");
7032c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "acd", buffer);
7033c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
7034c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
7035c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
7036c2c66affSColin Finck     result = strcmp(buffer, "abcd");
7037c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "abcd", buffer);
7038c2c66affSColin Finck 
7039c2c66affSColin Finck     /* Test the effect of EM_STOPGROUPTYPING on undo transactions*/
7040c2c66affSColin Finck     SendMessageA(hwnd, EM_EMPTYUNDOBUFFER, 0, 0);
7041c2c66affSColin Finck     result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
7042c2c66affSColin Finck     ok (result == TRUE, "Failed to clear the text.\n");
7043c2c66affSColin Finck     simulate_typing_characters(hwnd, "one two three");
7044c2c66affSColin Finck     result = SendMessageA(hwnd, EM_STOPGROUPTYPING, 0, 0);
7045c2c66affSColin Finck     ok (result == 0, "expected %d but got %d\n", 0, result);
7046c2c66affSColin Finck     simulate_typing_characters(hwnd, " four five six");
7047c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
7048c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
7049c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
7050c2c66affSColin Finck     result = strcmp(buffer, "one two three");
7051c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "one two three", buffer);
7052c2c66affSColin Finck     result = SendMessageA(hwnd, EM_UNDO, 0, 0);
7053c2c66affSColin Finck     ok (result == TRUE, "Failed to undo typed characters.\n");
7054c2c66affSColin Finck     SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
7055c2c66affSColin Finck     result = strcmp(buffer, "");
7056c2c66affSColin Finck     ok (result == 0, "expected '%s' but got '%s'\n", "", buffer);
7057c2c66affSColin Finck 
7058c2c66affSColin Finck     DestroyWindow(hwnd);
7059c2c66affSColin Finck }
7060c2c66affSColin Finck 
customWordBreakProc(WCHAR * text,int pos,int bytes,int code)7061c2c66affSColin Finck static LONG CALLBACK customWordBreakProc(WCHAR *text, int pos, int bytes, int code)
7062c2c66affSColin Finck {
7063c2c66affSColin Finck     int length;
7064c2c66affSColin Finck 
7065c2c66affSColin Finck     /* MSDN lied, length is actually the number of bytes. */
7066c2c66affSColin Finck     length = bytes / sizeof(WCHAR);
7067c2c66affSColin Finck     switch(code)
7068c2c66affSColin Finck     {
7069c2c66affSColin Finck         case WB_ISDELIMITER:
7070c2c66affSColin Finck             return text[pos] == 'X';
7071c2c66affSColin Finck         case WB_LEFT:
7072c2c66affSColin Finck         case WB_MOVEWORDLEFT:
7073c2c66affSColin Finck             if (customWordBreakProc(text, pos, bytes, WB_ISDELIMITER))
7074c2c66affSColin Finck                 return pos-1;
7075c2c66affSColin Finck             return min(customWordBreakProc(text, pos, bytes, WB_LEFTBREAK)-1, 0);
7076c2c66affSColin Finck         case WB_LEFTBREAK:
7077c2c66affSColin Finck             pos--;
7078c2c66affSColin Finck             while (pos > 0 && !customWordBreakProc(text, pos, bytes, WB_ISDELIMITER))
7079c2c66affSColin Finck                 pos--;
7080c2c66affSColin Finck             return pos;
7081c2c66affSColin Finck         case WB_RIGHT:
7082c2c66affSColin Finck         case WB_MOVEWORDRIGHT:
7083c2c66affSColin Finck             if (customWordBreakProc(text, pos, bytes, WB_ISDELIMITER))
7084c2c66affSColin Finck                 return pos+1;
7085c2c66affSColin Finck             return min(customWordBreakProc(text, pos, bytes, WB_RIGHTBREAK)+1, length);
7086c2c66affSColin Finck         case WB_RIGHTBREAK:
7087c2c66affSColin Finck             pos++;
7088c2c66affSColin Finck             while (pos < length && !customWordBreakProc(text, pos, bytes, WB_ISDELIMITER))
7089c2c66affSColin Finck                 pos++;
7090c2c66affSColin Finck             return pos;
7091c2c66affSColin Finck         default:
7092c2c66affSColin Finck             ok(FALSE, "Unexpected code %d\n", code);
7093c2c66affSColin Finck             break;
7094c2c66affSColin Finck     }
7095c2c66affSColin Finck     return 0;
7096c2c66affSColin Finck }
7097c2c66affSColin Finck 
test_word_movement(void)7098c2c66affSColin Finck static void test_word_movement(void)
7099c2c66affSColin Finck {
7100c2c66affSColin Finck     HWND hwnd;
7101c2c66affSColin Finck     int result;
7102c2c66affSColin Finck     int sel_start, sel_end;
7103c2c66affSColin Finck     const WCHAR textW[] = {'o','n','e',' ','t','w','o','X','t','h','r','e','e',0};
7104c2c66affSColin Finck 
7105c2c66affSColin Finck     /* multi-line control inserts CR normally */
7106c2c66affSColin Finck     hwnd = new_richedit(NULL);
7107c2c66affSColin Finck 
7108c2c66affSColin Finck     result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"one two  three");
7109c2c66affSColin Finck     ok (result == TRUE, "Failed to clear the text.\n");
7110c2c66affSColin Finck     SendMessageA(hwnd, EM_SETSEL, 0, 0);
7111c2c66affSColin Finck     /* |one two three */
7112c2c66affSColin Finck 
7113c2c66affSColin Finck     send_ctrl_key(hwnd, VK_RIGHT);
7114c2c66affSColin Finck     /* one |two  three */
7115c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7116c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7117c2c66affSColin Finck     ok(sel_start == 4, "Cursor is at %d instead of %d\n", sel_start, 4);
7118c2c66affSColin Finck 
7119c2c66affSColin Finck     send_ctrl_key(hwnd, VK_RIGHT);
7120c2c66affSColin Finck     /* one two  |three */
7121c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7122c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7123c2c66affSColin Finck     ok(sel_start == 9, "Cursor is at %d instead of %d\n", sel_start, 9);
7124c2c66affSColin Finck 
7125c2c66affSColin Finck     send_ctrl_key(hwnd, VK_LEFT);
7126c2c66affSColin Finck     /* one |two  three */
7127c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7128c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7129c2c66affSColin Finck     ok(sel_start == 4, "Cursor is at %d instead of %d\n", sel_start, 4);
7130c2c66affSColin Finck 
7131c2c66affSColin Finck     send_ctrl_key(hwnd, VK_LEFT);
7132c2c66affSColin Finck     /* |one two  three */
7133c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7134c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7135c2c66affSColin Finck     ok(sel_start == 0, "Cursor is at %d instead of %d\n", sel_start, 0);
7136c2c66affSColin Finck 
7137c2c66affSColin Finck     SendMessageA(hwnd, EM_SETSEL, 8, 8);
7138c2c66affSColin Finck     /* one two | three */
7139c2c66affSColin Finck     send_ctrl_key(hwnd, VK_RIGHT);
7140c2c66affSColin Finck     /* one two  |three */
7141c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7142c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7143c2c66affSColin Finck     ok(sel_start == 9, "Cursor is at %d instead of %d\n", sel_start, 9);
7144c2c66affSColin Finck 
7145c2c66affSColin Finck     SendMessageA(hwnd, EM_SETSEL, 11, 11);
7146c2c66affSColin Finck     /* one two  th|ree */
7147c2c66affSColin Finck     send_ctrl_key(hwnd, VK_LEFT);
7148c2c66affSColin Finck     /* one two  |three */
7149c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7150c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7151c2c66affSColin Finck     ok(sel_start == 9, "Cursor is at %d instead of %d\n", sel_start, 9);
7152c2c66affSColin Finck 
7153c2c66affSColin Finck     /* Test with a custom word break procedure that uses X as the delimiter. */
7154c2c66affSColin Finck     result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"one twoXthree");
7155c2c66affSColin Finck     ok (result == TRUE, "Failed to clear the text.\n");
7156c2c66affSColin Finck     SendMessageA(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)customWordBreakProc);
7157c2c66affSColin Finck     /* |one twoXthree */
7158c2c66affSColin Finck     send_ctrl_key(hwnd, VK_RIGHT);
7159c2c66affSColin Finck     /* one twoX|three */
7160c2c66affSColin Finck     SendMessageA(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7161c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7162c2c66affSColin Finck     ok(sel_start == 8, "Cursor is at %d instead of %d\n", sel_start, 8);
7163c2c66affSColin Finck 
7164c2c66affSColin Finck     DestroyWindow(hwnd);
7165c2c66affSColin Finck 
7166c2c66affSColin Finck     /* Make sure the behaviour is the same with a unicode richedit window,
7167c2c66affSColin Finck      * and using unicode functions. */
7168c2c66affSColin Finck 
7169c2c66affSColin Finck     hwnd = CreateWindowW(RICHEDIT_CLASS20W, NULL,
7170c2c66affSColin Finck                         ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
7171c2c66affSColin Finck                         0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7172c2c66affSColin Finck 
7173c2c66affSColin Finck     /* Test with a custom word break procedure that uses X as the delimiter. */
7174c2c66affSColin Finck     result = SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW);
7175c2c66affSColin Finck     ok (result == TRUE, "Failed to clear the text.\n");
7176c2c66affSColin Finck     SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)customWordBreakProc);
7177c2c66affSColin Finck     /* |one twoXthree */
7178c2c66affSColin Finck     send_ctrl_key(hwnd, VK_RIGHT);
7179c2c66affSColin Finck     /* one twoX|three */
7180c2c66affSColin Finck     SendMessageW(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
7181c2c66affSColin Finck     ok(sel_start == sel_end, "Selection should be empty\n");
7182c2c66affSColin Finck     ok(sel_start == 8, "Cursor is at %d instead of %d\n", sel_start, 8);
7183c2c66affSColin Finck 
7184c2c66affSColin Finck     DestroyWindow(hwnd);
7185c2c66affSColin Finck }
7186c2c66affSColin Finck 
test_EM_CHARFROMPOS(void)7187c2c66affSColin Finck static void test_EM_CHARFROMPOS(void)
7188c2c66affSColin Finck {
7189c2c66affSColin Finck     HWND hwnd;
7190c2c66affSColin Finck     int result;
7191c2c66affSColin Finck     RECT rcClient;
7192c2c66affSColin Finck     POINTL point;
7193c2c66affSColin Finck     point.x = 0;
7194c2c66affSColin Finck     point.y = 40;
7195c2c66affSColin Finck 
7196c2c66affSColin Finck     /* multi-line control inserts CR normally */
7197c2c66affSColin Finck     hwnd = new_richedit(NULL);
7198c2c66affSColin Finck     result = SendMessageA(hwnd, WM_SETTEXT, 0,
7199c2c66affSColin Finck                           (LPARAM)"one two three four five six seven\reight");
7200c2c66affSColin Finck     ok(result == 1, "Expected 1, got %d\n", result);
7201c2c66affSColin Finck     GetClientRect(hwnd, &rcClient);
7202c2c66affSColin Finck 
7203c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7204c2c66affSColin Finck     ok(result == 34, "expected character index of 34 but got %d\n", result);
7205c2c66affSColin Finck 
7206c2c66affSColin Finck     /* Test with points outside the bounds of the richedit control. */
7207c2c66affSColin Finck     point.x = -1;
7208c2c66affSColin Finck     point.y = 40;
7209c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7210c2c66affSColin Finck     todo_wine ok(result == 34, "expected character index of 34 but got %d\n", result);
7211c2c66affSColin Finck 
7212c2c66affSColin Finck     point.x = 1000;
7213c2c66affSColin Finck     point.y = 0;
7214c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7215c2c66affSColin Finck     todo_wine ok(result == 33, "expected character index of 33 but got %d\n", result);
7216c2c66affSColin Finck 
7217c2c66affSColin Finck     point.x = 1000;
7218c2c66affSColin Finck     point.y = 36;
7219c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7220c2c66affSColin Finck     todo_wine ok(result == 39, "expected character index of 39 but got %d\n", result);
7221c2c66affSColin Finck 
7222c2c66affSColin Finck     point.x = 1000;
7223c2c66affSColin Finck     point.y = -1;
7224c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7225c2c66affSColin Finck     todo_wine ok(result == 0, "expected character index of 0 but got %d\n", result);
7226c2c66affSColin Finck 
7227c2c66affSColin Finck     point.x = 1000;
7228c2c66affSColin Finck     point.y = rcClient.bottom + 1;
7229c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7230c2c66affSColin Finck     todo_wine ok(result == 34, "expected character index of 34 but got %d\n", result);
7231c2c66affSColin Finck 
7232c2c66affSColin Finck     point.x = 1000;
7233c2c66affSColin Finck     point.y = rcClient.bottom;
7234c2c66affSColin Finck     result = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7235c2c66affSColin Finck     todo_wine ok(result == 39, "expected character index of 39 but got %d\n", result);
7236c2c66affSColin Finck 
7237c2c66affSColin Finck     DestroyWindow(hwnd);
7238c2c66affSColin Finck }
7239c2c66affSColin Finck 
test_word_wrap(void)7240c2c66affSColin Finck static void test_word_wrap(void)
7241c2c66affSColin Finck {
7242c2c66affSColin Finck     HWND hwnd;
7243c2c66affSColin Finck     POINTL point = {0, 60}; /* This point must be below the first line */
7244c2c66affSColin Finck     const char *text = "Must be long enough to test line wrapping";
7245c2c66affSColin Finck     DWORD dwCommonStyle = WS_VISIBLE|WS_POPUP|WS_VSCROLL|ES_MULTILINE;
7246c2c66affSColin Finck     int res, pos, lines;
7247c2c66affSColin Finck 
7248c2c66affSColin Finck     /* Test the effect of WS_HSCROLL and ES_AUTOHSCROLL styles on wrapping
7249c2c66affSColin Finck      * when specified on window creation and set later. */
7250c2c66affSColin Finck     hwnd = CreateWindowA(RICHEDIT_CLASS20A, NULL, dwCommonStyle,
7251c2c66affSColin Finck                         0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
7252c2c66affSColin Finck     ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
7253c2c66affSColin Finck     res = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text);
7254c2c66affSColin Finck     ok(res, "WM_SETTEXT failed.\n");
7255c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7256c2c66affSColin Finck     ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
7257c2c66affSColin Finck     lines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
7258c2c66affSColin Finck     ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
7259c2c66affSColin Finck 
7260c2c66affSColin Finck     SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL);
7261c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7262c2c66affSColin Finck     ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
7263c2c66affSColin Finck     DestroyWindow(hwnd);
7264c2c66affSColin Finck 
7265c2c66affSColin Finck     hwnd = CreateWindowA(RICHEDIT_CLASS20A, NULL, dwCommonStyle|WS_HSCROLL,
7266c2c66affSColin Finck                         0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
7267c2c66affSColin Finck     ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
7268c2c66affSColin Finck 
7269c2c66affSColin Finck     res = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text);
7270c2c66affSColin Finck     ok(res, "WM_SETTEXT failed.\n");
7271c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7272c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7273c2c66affSColin Finck     lines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
7274c2c66affSColin Finck     ok(lines == 1, "Line wasn't expected to wrap (lines=%d).\n", lines);
7275c2c66affSColin Finck 
7276c2c66affSColin Finck     SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle);
7277c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7278c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7279c2c66affSColin Finck     DestroyWindow(hwnd);
7280c2c66affSColin Finck 
7281c2c66affSColin Finck     hwnd = CreateWindowA(RICHEDIT_CLASS20A, NULL, dwCommonStyle|ES_AUTOHSCROLL,
7282c2c66affSColin Finck                         0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
7283c2c66affSColin Finck     ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
7284c2c66affSColin Finck     res = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text);
7285c2c66affSColin Finck     ok(res, "WM_SETTEXT failed.\n");
7286c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7287c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7288c2c66affSColin Finck 
7289c2c66affSColin Finck     SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle);
7290c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7291c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7292c2c66affSColin Finck     DestroyWindow(hwnd);
7293c2c66affSColin Finck 
7294c2c66affSColin Finck     hwnd = CreateWindowA(RICHEDIT_CLASS20A, NULL,
7295c2c66affSColin Finck                         dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL,
7296c2c66affSColin Finck                         0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
7297c2c66affSColin Finck     ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
7298c2c66affSColin Finck     res = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text);
7299c2c66affSColin Finck     ok(res, "WM_SETTEXT failed.\n");
7300c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7301c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7302c2c66affSColin Finck 
7303c2c66affSColin Finck     SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle);
7304c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7305c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7306c2c66affSColin Finck 
7307c2c66affSColin Finck     /* Test the effect of EM_SETTARGETDEVICE on word wrap. */
7308c2c66affSColin Finck     res = SendMessageA(hwnd, EM_SETTARGETDEVICE, 0, 1);
7309c2c66affSColin Finck     ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
7310c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7311c2c66affSColin Finck     ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
7312c2c66affSColin Finck 
7313c2c66affSColin Finck     res = SendMessageA(hwnd, EM_SETTARGETDEVICE, 0, 0);
7314c2c66affSColin Finck     ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
7315c2c66affSColin Finck     pos = SendMessageA(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&point);
7316c2c66affSColin Finck     ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
7317c2c66affSColin Finck     DestroyWindow(hwnd);
7318c2c66affSColin Finck 
7319c2c66affSColin Finck     /* Test to see if wrapping happens with redraw disabled. */
7320c2c66affSColin Finck     hwnd = CreateWindowA(RICHEDIT_CLASS20A, NULL, dwCommonStyle,
7321c2c66affSColin Finck                         0, 0, 400, 80, NULL, NULL, hmoduleRichEdit, NULL);
7322c2c66affSColin Finck     ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
7323c2c66affSColin Finck     SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
7324c2c66affSColin Finck     res = SendMessageA(hwnd, EM_REPLACESEL, FALSE, (LPARAM)text);
7325c2c66affSColin Finck     ok(res, "EM_REPLACESEL failed.\n");
7326c2c66affSColin Finck     lines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
7327c2c66affSColin Finck     ok(lines == 1, "Line wasn't expected to wrap (lines=%d).\n", lines);
7328c2c66affSColin Finck     MoveWindow(hwnd, 0, 0, 200, 80, FALSE);
7329c2c66affSColin Finck     lines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
7330c2c66affSColin Finck     ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
7331c2c66affSColin Finck 
7332c2c66affSColin Finck     SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
7333c2c66affSColin Finck     DestroyWindow(hwnd);
7334c2c66affSColin Finck }
7335c2c66affSColin Finck 
test_autoscroll(void)7336c2c66affSColin Finck static void test_autoscroll(void)
7337c2c66affSColin Finck {
7338c2c66affSColin Finck     HWND hwnd = new_richedit(NULL);
7339c2c66affSColin Finck     int lines, ret, redraw;
7340c2c66affSColin Finck     POINT pt;
7341c2c66affSColin Finck 
7342c2c66affSColin Finck     for (redraw = 0; redraw <= 1; redraw++) {
7343c2c66affSColin Finck         trace("testing with WM_SETREDRAW=%d\n", redraw);
7344c2c66affSColin Finck         SendMessageA(hwnd, WM_SETREDRAW, redraw, 0);
7345c2c66affSColin Finck         SendMessageA(hwnd, EM_REPLACESEL, 0, (LPARAM)"1\n2\n3\n4\n5\n6\n7\n8");
7346c2c66affSColin Finck         lines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
7347c2c66affSColin Finck         ok(lines == 8, "%d lines instead of 8\n", lines);
7348c2c66affSColin Finck         ret = SendMessageA(hwnd, EM_GETSCROLLPOS, 0, (LPARAM)&pt);
7349c2c66affSColin Finck         ok(ret == 1, "EM_GETSCROLLPOS returned %d instead of 1\n", ret);
7350c2c66affSColin Finck         ok(pt.y != 0, "Didn't scroll down after replacing text.\n");
7351c2c66affSColin Finck         ret = GetWindowLongA(hwnd, GWL_STYLE);
7352c2c66affSColin Finck         ok(ret & WS_VSCROLL, "Scrollbar was not shown yet (style=%x).\n", (UINT)ret);
7353c2c66affSColin Finck 
7354c2c66affSColin Finck         SendMessageA(hwnd, WM_SETTEXT, 0, 0);
7355c2c66affSColin Finck         lines = SendMessageA(hwnd, EM_GETLINECOUNT, 0, 0);
7356c2c66affSColin Finck         ok(lines == 1, "%d lines instead of 1\n", lines);
7357c2c66affSColin Finck         ret = SendMessageA(hwnd, EM_GETSCROLLPOS, 0, (LPARAM)&pt);
7358c2c66affSColin Finck         ok(ret == 1, "EM_GETSCROLLPOS returned %d instead of 1\n", ret);
7359c2c66affSColin Finck         ok(pt.y == 0, "y scroll position is %d after clearing text.\n", pt.y);
7360c2c66affSColin Finck         ret = GetWindowLongA(hwnd, GWL_STYLE);
7361c2c66affSColin Finck         ok(!(ret & WS_VSCROLL), "Scrollbar is still shown (style=%x).\n", (UINT)ret);
7362c2c66affSColin Finck     }
7363c2c66affSColin Finck 
7364c2c66affSColin Finck     SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
7365c2c66affSColin Finck     DestroyWindow(hwnd);
7366c2c66affSColin Finck 
7367c2c66affSColin Finck     /* The WS_VSCROLL and WS_HSCROLL styles implicitly set
7368c2c66affSColin Finck      * auto vertical/horizontal scrolling options. */
7369c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7370c2c66affSColin Finck                           WS_POPUP|ES_MULTILINE|WS_VSCROLL|WS_HSCROLL,
7371c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7372c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7373c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETOPTIONS, 0, 0);
7374c2c66affSColin Finck     ok(ret & ECO_AUTOVSCROLL, "ECO_AUTOVSCROLL isn't set.\n");
7375c2c66affSColin Finck     ok(ret & ECO_AUTOHSCROLL, "ECO_AUTOHSCROLL isn't set.\n");
7376c2c66affSColin Finck     ret = GetWindowLongA(hwnd, GWL_STYLE);
7377c2c66affSColin Finck     ok(!(ret & ES_AUTOVSCROLL), "ES_AUTOVSCROLL is set.\n");
7378c2c66affSColin Finck     ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
7379c2c66affSColin Finck     DestroyWindow(hwnd);
7380c2c66affSColin Finck 
7381c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7382c2c66affSColin Finck                           WS_POPUP|ES_MULTILINE,
7383c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7384c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7385c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETOPTIONS, 0, 0);
7386c2c66affSColin Finck     ok(!(ret & ECO_AUTOVSCROLL), "ECO_AUTOVSCROLL is set.\n");
7387c2c66affSColin Finck     ok(!(ret & ECO_AUTOHSCROLL), "ECO_AUTOHSCROLL is set.\n");
7388c2c66affSColin Finck     ret = GetWindowLongA(hwnd, GWL_STYLE);
7389c2c66affSColin Finck     ok(!(ret & ES_AUTOVSCROLL), "ES_AUTOVSCROLL is set.\n");
7390c2c66affSColin Finck     ok(!(ret & ES_AUTOHSCROLL), "ES_AUTOHSCROLL is set.\n");
7391c2c66affSColin Finck     DestroyWindow(hwnd);
7392c2c66affSColin Finck }
7393c2c66affSColin Finck 
7394c2c66affSColin Finck 
test_format_rect(void)7395c2c66affSColin Finck static void test_format_rect(void)
7396c2c66affSColin Finck {
7397c2c66affSColin Finck     HWND hwnd;
7398c2c66affSColin Finck     RECT rc, expected, clientRect;
7399c2c66affSColin Finck     int n;
7400c2c66affSColin Finck     DWORD options;
7401c2c66affSColin Finck 
7402c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7403c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
7404c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7405c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7406c2c66affSColin Finck 
7407c2c66affSColin Finck     GetClientRect(hwnd, &clientRect);
7408c2c66affSColin Finck 
7409c2c66affSColin Finck     expected = clientRect;
7410c2c66affSColin Finck     InflateRect(&expected, -1, 0);
7411c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7412c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7413c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7414c2c66affSColin Finck 
7415c2c66affSColin Finck     for (n = -3; n <= 3; n++)
7416c2c66affSColin Finck     {
7417c2c66affSColin Finck       rc = clientRect;
7418c2c66affSColin Finck       InflateRect(&rc, -n, -n);
7419c2c66affSColin Finck       SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
7420c2c66affSColin Finck 
7421c2c66affSColin Finck       expected = rc;
7422c2c66affSColin Finck       expected.top = max(0, rc.top);
7423c2c66affSColin Finck       expected.left = max(0, rc.left);
7424c2c66affSColin Finck       expected.bottom = min(clientRect.bottom, rc.bottom);
7425c2c66affSColin Finck       expected.right = min(clientRect.right, rc.right);
7426c2c66affSColin Finck       SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7427c2c66affSColin Finck       ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc),
7428c2c66affSColin Finck          wine_dbgstr_rect(&expected));
7429c2c66affSColin Finck     }
7430c2c66affSColin Finck 
7431c2c66affSColin Finck     rc = clientRect;
7432c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
7433c2c66affSColin Finck     expected = clientRect;
7434c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7435c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7436c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7437c2c66affSColin Finck 
7438c2c66affSColin Finck     /* Adding the selectionbar adds the selectionbar width to the left side. */
7439c2c66affSColin Finck     SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR);
7440c2c66affSColin Finck     options = SendMessageA(hwnd, EM_GETOPTIONS, 0, 0);
7441c2c66affSColin Finck     ok(options & ECO_SELECTIONBAR, "EM_SETOPTIONS failed to add selectionbar.\n");
7442c2c66affSColin Finck     expected.left += 8; /* selection bar width */
7443c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7444c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7445c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7446c2c66affSColin Finck 
7447c2c66affSColin Finck     rc = clientRect;
7448c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
7449c2c66affSColin Finck     expected = clientRect;
7450c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7451c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7452c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7453c2c66affSColin Finck 
7454c2c66affSColin Finck     /* Removing the selectionbar subtracts the selectionbar width from the left side,
7455c2c66affSColin Finck      * even if the left side is already 0. */
7456c2c66affSColin Finck     SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_AND, ~ECO_SELECTIONBAR);
7457c2c66affSColin Finck     options = SendMessageA(hwnd, EM_GETOPTIONS, 0, 0);
7458c2c66affSColin Finck     ok(!(options & ECO_SELECTIONBAR), "EM_SETOPTIONS failed to remove selectionbar.\n");
7459c2c66affSColin Finck     expected.left -= 8; /* selection bar width */
7460c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7461c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7462c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7463c2c66affSColin Finck 
7464c2c66affSColin Finck     /* Set the absolute value of the formatting rectangle. */
7465c2c66affSColin Finck     rc = clientRect;
7466c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
7467c2c66affSColin Finck     expected = clientRect;
7468c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7469c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc),
7470c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7471c2c66affSColin Finck 
7472c2c66affSColin Finck     /* MSDN documents the EM_SETRECT message as using the rectangle provided in
7473c2c66affSColin Finck      * LPARAM as being a relative offset when the WPARAM value is 1, but these
7474c2c66affSColin Finck      * tests show that this isn't true. */
7475c2c66affSColin Finck     rc.top = 15;
7476c2c66affSColin Finck     rc.left = 15;
7477c2c66affSColin Finck     rc.bottom = clientRect.bottom - 15;
7478c2c66affSColin Finck     rc.right = clientRect.right - 15;
7479c2c66affSColin Finck     expected = rc;
7480c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
7481c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7482c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7483c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7484c2c66affSColin Finck 
7485c2c66affSColin Finck     /* For some reason it does not limit the values to the client rect with
7486c2c66affSColin Finck      * a WPARAM value of 1. */
7487c2c66affSColin Finck     rc.top = -15;
7488c2c66affSColin Finck     rc.left = -15;
7489c2c66affSColin Finck     rc.bottom = clientRect.bottom + 15;
7490c2c66affSColin Finck     rc.right = clientRect.right + 15;
7491c2c66affSColin Finck     expected = rc;
7492c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
7493c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7494c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7495c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7496c2c66affSColin Finck 
7497c2c66affSColin Finck     /* Reset to default rect and check how the format rect adjusts to window
7498c2c66affSColin Finck      * resize and how it copes with very small windows */
7499c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 0, 0);
7500c2c66affSColin Finck 
7501c2c66affSColin Finck     MoveWindow(hwnd, 0, 0, 100, 30, FALSE);
7502c2c66affSColin Finck     GetClientRect(hwnd, &clientRect);
7503c2c66affSColin Finck 
7504c2c66affSColin Finck     expected = clientRect;
7505c2c66affSColin Finck     InflateRect(&expected, -1, 0);
7506c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7507c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7508c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7509c2c66affSColin Finck 
7510c2c66affSColin Finck     MoveWindow(hwnd, 0, 0, 0, 30, FALSE);
7511c2c66affSColin Finck     GetClientRect(hwnd, &clientRect);
7512c2c66affSColin Finck 
7513c2c66affSColin Finck     expected = clientRect;
7514c2c66affSColin Finck     InflateRect(&expected, -1, 0);
7515c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7516c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7517c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7518c2c66affSColin Finck 
7519c2c66affSColin Finck     MoveWindow(hwnd, 0, 0, 100, 0, FALSE);
7520c2c66affSColin Finck     GetClientRect(hwnd, &clientRect);
7521c2c66affSColin Finck 
7522c2c66affSColin Finck     expected = clientRect;
7523c2c66affSColin Finck     InflateRect(&expected, -1, 0);
7524c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7525c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7526c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7527c2c66affSColin Finck 
7528c2c66affSColin Finck     DestroyWindow(hwnd);
7529c2c66affSColin Finck 
7530c2c66affSColin Finck     /* The extended window style affects the formatting rectangle. */
7531c2c66affSColin Finck     hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, RICHEDIT_CLASS20A, NULL,
7532c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
7533c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7534c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7535c2c66affSColin Finck 
7536c2c66affSColin Finck     GetClientRect(hwnd, &clientRect);
7537c2c66affSColin Finck 
7538c2c66affSColin Finck     expected = clientRect;
7539c2c66affSColin Finck     expected.top += 1;
7540c2c66affSColin Finck     InflateRect(&expected, -1, 0);
7541c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7542c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7543c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7544c2c66affSColin Finck 
7545c2c66affSColin Finck     rc = clientRect;
7546c2c66affSColin Finck     InflateRect(&rc, -5, -5);
7547c2c66affSColin Finck     expected = rc;
7548c2c66affSColin Finck     expected.top -= 1;
7549c2c66affSColin Finck     InflateRect(&expected, 1, 0);
7550c2c66affSColin Finck     SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
7551c2c66affSColin Finck     SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
7552c2c66affSColin Finck     ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
7553c2c66affSColin Finck        wine_dbgstr_rect(&expected));
7554c2c66affSColin Finck 
7555c2c66affSColin Finck     DestroyWindow(hwnd);
7556c2c66affSColin Finck }
7557c2c66affSColin Finck 
test_WM_GETDLGCODE(void)7558c2c66affSColin Finck static void test_WM_GETDLGCODE(void)
7559c2c66affSColin Finck {
7560c2c66affSColin Finck     HWND hwnd;
7561c2c66affSColin Finck     UINT res, expected;
7562c2c66affSColin Finck     MSG msg;
7563c2c66affSColin Finck 
7564c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL|DLGC_WANTMESSAGE;
7565c2c66affSColin Finck 
7566c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7567c2c66affSColin Finck                           ES_MULTILINE|ES_WANTRETURN|WS_POPUP,
7568c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7569c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7570c2c66affSColin Finck     msg.hwnd = hwnd;
7571c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, 0);
7572c2c66affSColin Finck     expected = expected | DLGC_WANTMESSAGE;
7573c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7574c2c66affSColin Finck        res, expected);
7575c2c66affSColin Finck     DestroyWindow(hwnd);
7576c2c66affSColin Finck 
7577c2c66affSColin Finck     msg.message = WM_KEYDOWN;
7578c2c66affSColin Finck     msg.wParam = VK_RETURN;
7579c2c66affSColin Finck     msg.lParam = (MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_VSC) << 16) | 0x0001;
7580c2c66affSColin Finck     msg.pt.x = 0;
7581c2c66affSColin Finck     msg.pt.y = 0;
7582c2c66affSColin Finck     msg.time = GetTickCount();
7583c2c66affSColin Finck 
7584c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7585c2c66affSColin Finck                           ES_MULTILINE|ES_WANTRETURN|WS_POPUP,
7586c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7587c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7588c2c66affSColin Finck     msg.hwnd = hwnd;
7589c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7590c2c66affSColin Finck     expected = expected | DLGC_WANTMESSAGE;
7591c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7592c2c66affSColin Finck        res, expected);
7593c2c66affSColin Finck     DestroyWindow(hwnd);
7594c2c66affSColin Finck 
7595c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7596c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP,
7597c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7598c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7599c2c66affSColin Finck     msg.hwnd = hwnd;
7600c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7601c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL|DLGC_WANTMESSAGE;
7602c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7603c2c66affSColin Finck        res, expected);
7604c2c66affSColin Finck     DestroyWindow(hwnd);
7605c2c66affSColin Finck 
7606c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7607c2c66affSColin Finck                           ES_WANTRETURN|WS_POPUP,
7608c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7609c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7610c2c66affSColin Finck     msg.hwnd = hwnd;
7611c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7612c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
7613c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7614c2c66affSColin Finck        res, expected);
7615c2c66affSColin Finck     DestroyWindow(hwnd);
7616c2c66affSColin Finck 
7617c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7618c2c66affSColin Finck                           WS_POPUP,
7619c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7620c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7621c2c66affSColin Finck     msg.hwnd = hwnd;
7622c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7623c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
7624c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7625c2c66affSColin Finck        res, expected);
7626c2c66affSColin Finck     DestroyWindow(hwnd);
7627c2c66affSColin Finck 
7628c2c66affSColin Finck     msg.wParam = VK_TAB;
7629c2c66affSColin Finck     msg.lParam = (MapVirtualKeyA(VK_TAB, MAPVK_VK_TO_VSC) << 16) | 0x0001;
7630c2c66affSColin Finck 
7631c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7632c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP,
7633c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7634c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7635c2c66affSColin Finck     msg.hwnd = hwnd;
7636c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7637c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL|DLGC_WANTMESSAGE;
7638c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7639c2c66affSColin Finck        res, expected);
7640c2c66affSColin Finck     DestroyWindow(hwnd);
7641c2c66affSColin Finck 
7642c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7643c2c66affSColin Finck                           WS_POPUP,
7644c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7645c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7646c2c66affSColin Finck     msg.hwnd = hwnd;
7647c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7648c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
7649c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7650c2c66affSColin Finck        res, expected);
7651c2c66affSColin Finck     DestroyWindow(hwnd);
7652c2c66affSColin Finck 
7653c2c66affSColin Finck     hold_key(VK_CONTROL);
7654c2c66affSColin Finck 
7655c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7656c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP,
7657c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7658c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7659c2c66affSColin Finck     msg.hwnd = hwnd;
7660c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7661c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL|DLGC_WANTMESSAGE;
7662c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7663c2c66affSColin Finck        res, expected);
7664c2c66affSColin Finck     DestroyWindow(hwnd);
7665c2c66affSColin Finck 
7666c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7667c2c66affSColin Finck                           WS_POPUP,
7668c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7669c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7670c2c66affSColin Finck     msg.hwnd = hwnd;
7671c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7672c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
7673c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7674c2c66affSColin Finck        res, expected);
7675c2c66affSColin Finck     DestroyWindow(hwnd);
7676c2c66affSColin Finck 
7677c2c66affSColin Finck     release_key(VK_CONTROL);
7678c2c66affSColin Finck 
7679c2c66affSColin Finck     msg.wParam = 'a';
7680c2c66affSColin Finck     msg.lParam = (MapVirtualKeyA('a', MAPVK_VK_TO_VSC) << 16) | 0x0001;
7681c2c66affSColin Finck 
7682c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7683c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP,
7684c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7685c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7686c2c66affSColin Finck     msg.hwnd = hwnd;
7687c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7688c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL|DLGC_WANTMESSAGE;
7689c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7690c2c66affSColin Finck        res, expected);
7691c2c66affSColin Finck     DestroyWindow(hwnd);
7692c2c66affSColin Finck 
7693c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7694c2c66affSColin Finck                           WS_POPUP,
7695c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7696c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7697c2c66affSColin Finck     msg.hwnd = hwnd;
7698c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7699c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
7700c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7701c2c66affSColin Finck        res, expected);
7702c2c66affSColin Finck     DestroyWindow(hwnd);
7703c2c66affSColin Finck 
7704c2c66affSColin Finck     msg.message = WM_CHAR;
7705c2c66affSColin Finck 
7706c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7707c2c66affSColin Finck                           ES_MULTILINE|WS_POPUP,
7708c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7709c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7710c2c66affSColin Finck     msg.hwnd = hwnd;
7711c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7712c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL|DLGC_WANTMESSAGE;
7713c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7714c2c66affSColin Finck        res, expected);
7715c2c66affSColin Finck     DestroyWindow(hwnd);
7716c2c66affSColin Finck 
7717c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7718c2c66affSColin Finck                           WS_POPUP,
7719c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7720c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7721c2c66affSColin Finck     msg.hwnd = hwnd;
7722c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, VK_RETURN, (LPARAM)&msg);
7723c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
7724c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7725c2c66affSColin Finck        res, expected);
7726c2c66affSColin Finck     DestroyWindow(hwnd);
7727c2c66affSColin Finck 
7728c2c66affSColin Finck     hwnd = CreateWindowExA(0, RICHEDIT_CLASS20A, NULL,
7729c2c66affSColin Finck                           WS_POPUP|ES_SAVESEL,
7730c2c66affSColin Finck                           0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
7731c2c66affSColin Finck     ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
7732c2c66affSColin Finck     res = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
7733c2c66affSColin Finck     expected = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS;
7734c2c66affSColin Finck     ok(res == expected, "WM_GETDLGCODE returned %x but expected %x\n",
7735c2c66affSColin Finck        res, expected);
7736c2c66affSColin Finck     DestroyWindow(hwnd);
7737c2c66affSColin Finck }
7738c2c66affSColin Finck 
test_zoom(void)7739c2c66affSColin Finck static void test_zoom(void)
7740c2c66affSColin Finck {
7741c2c66affSColin Finck     HWND hwnd;
7742c2c66affSColin Finck     UINT ret;
7743c2c66affSColin Finck     RECT rc;
7744c2c66affSColin Finck     POINT pt;
7745c2c66affSColin Finck     int numerator, denominator;
7746c2c66affSColin Finck 
7747c2c66affSColin Finck     hwnd = new_richedit(NULL);
7748c2c66affSColin Finck     GetClientRect(hwnd, &rc);
7749c2c66affSColin Finck     pt.x = (rc.right - rc.left) / 2;
7750c2c66affSColin Finck     pt.y = (rc.bottom - rc.top) / 2;
7751c2c66affSColin Finck     ClientToScreen(hwnd, &pt);
7752c2c66affSColin Finck 
7753c2c66affSColin Finck     /* Test initial zoom value */
7754c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7755c2c66affSColin Finck     ok(numerator == 0, "Numerator should be initialized to 0 (got %d).\n", numerator);
7756c2c66affSColin Finck     ok(denominator == 0, "Denominator should be initialized to 0 (got %d).\n", denominator);
7757c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7758c2c66affSColin Finck 
7759c2c66affSColin Finck     /* test scroll wheel */
7760c2c66affSColin Finck     hold_key(VK_CONTROL);
7761c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(MK_CONTROL, WHEEL_DELTA),
7762c2c66affSColin Finck                       MAKELPARAM(pt.x, pt.y));
7763c2c66affSColin Finck     ok(!ret, "WM_MOUSEWHEEL failed (%d).\n", ret);
7764c2c66affSColin Finck     release_key(VK_CONTROL);
7765c2c66affSColin Finck 
7766c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7767c2c66affSColin Finck     ok(numerator == 110, "incorrect numerator is %d\n", numerator);
7768c2c66affSColin Finck     ok(denominator == 100, "incorrect denominator is %d\n", denominator);
7769c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7770c2c66affSColin Finck 
7771c2c66affSColin Finck     /* Test how much the mouse wheel can zoom in and out. */
7772c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 490, 100);
7773c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM failed (%d).\n", ret);
7774c2c66affSColin Finck 
7775c2c66affSColin Finck     hold_key(VK_CONTROL);
7776c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(MK_CONTROL, WHEEL_DELTA),
7777c2c66affSColin Finck                       MAKELPARAM(pt.x, pt.y));
7778c2c66affSColin Finck     ok(!ret, "WM_MOUSEWHEEL failed (%d).\n", ret);
7779c2c66affSColin Finck     release_key(VK_CONTROL);
7780c2c66affSColin Finck 
7781c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7782c2c66affSColin Finck     ok(numerator == 500, "incorrect numerator is %d\n", numerator);
7783c2c66affSColin Finck     ok(denominator == 100, "incorrect denominator is %d\n", denominator);
7784c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7785c2c66affSColin Finck 
7786c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 491, 100);
7787c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM failed (%d).\n", ret);
7788c2c66affSColin Finck 
7789c2c66affSColin Finck     hold_key(VK_CONTROL);
7790c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(MK_CONTROL, WHEEL_DELTA),
7791c2c66affSColin Finck                       MAKELPARAM(pt.x, pt.y));
7792c2c66affSColin Finck     ok(!ret, "WM_MOUSEWHEEL failed (%d).\n", ret);
7793c2c66affSColin Finck     release_key(VK_CONTROL);
7794c2c66affSColin Finck 
7795c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7796c2c66affSColin Finck     ok(numerator == 491, "incorrect numerator is %d\n", numerator);
7797c2c66affSColin Finck     ok(denominator == 100, "incorrect denominator is %d\n", denominator);
7798c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7799c2c66affSColin Finck 
7800c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 20, 100);
7801c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM failed (%d).\n", ret);
7802c2c66affSColin Finck 
7803c2c66affSColin Finck     hold_key(VK_CONTROL);
7804c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(MK_CONTROL, -WHEEL_DELTA),
7805c2c66affSColin Finck                       MAKELPARAM(pt.x, pt.y));
7806c2c66affSColin Finck     ok(!ret, "WM_MOUSEWHEEL failed (%d).\n", ret);
7807c2c66affSColin Finck     release_key(VK_CONTROL);
7808c2c66affSColin Finck 
7809c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7810c2c66affSColin Finck     ok(numerator == 10, "incorrect numerator is %d\n", numerator);
7811c2c66affSColin Finck     ok(denominator == 100, "incorrect denominator is %d\n", denominator);
7812c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7813c2c66affSColin Finck 
7814c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 19, 100);
7815c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM failed (%d).\n", ret);
7816c2c66affSColin Finck 
7817c2c66affSColin Finck     hold_key(VK_CONTROL);
7818c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(MK_CONTROL, -WHEEL_DELTA),
7819c2c66affSColin Finck                       MAKELPARAM(pt.x, pt.y));
7820c2c66affSColin Finck     ok(!ret, "WM_MOUSEWHEEL failed (%d).\n", ret);
7821c2c66affSColin Finck     release_key(VK_CONTROL);
7822c2c66affSColin Finck 
7823c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7824c2c66affSColin Finck     ok(numerator == 19, "incorrect numerator is %d\n", numerator);
7825c2c66affSColin Finck     ok(denominator == 100, "incorrect denominator is %d\n", denominator);
7826c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7827c2c66affSColin Finck 
7828c2c66affSColin Finck     /* Test how WM_SCROLLWHEEL treats our custom denominator. */
7829c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 50, 13);
7830c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM failed (%d).\n", ret);
7831c2c66affSColin Finck 
7832c2c66affSColin Finck     hold_key(VK_CONTROL);
7833c2c66affSColin Finck     ret = SendMessageA(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(MK_CONTROL, WHEEL_DELTA),
7834c2c66affSColin Finck                       MAKELPARAM(pt.x, pt.y));
7835c2c66affSColin Finck     ok(!ret, "WM_MOUSEWHEEL failed (%d).\n", ret);
7836c2c66affSColin Finck     release_key(VK_CONTROL);
7837c2c66affSColin Finck 
7838c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7839c2c66affSColin Finck     ok(numerator == 394, "incorrect numerator is %d\n", numerator);
7840c2c66affSColin Finck     ok(denominator == 100, "incorrect denominator is %d\n", denominator);
7841c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7842c2c66affSColin Finck 
7843c2c66affSColin Finck     /* Test bounds checking on EM_SETZOOM */
7844c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 2, 127);
7845c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM rejected valid values (%d).\n", ret);
7846c2c66affSColin Finck 
7847c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 127, 2);
7848c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM rejected valid values (%d).\n", ret);
7849c2c66affSColin Finck 
7850c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 2, 128);
7851c2c66affSColin Finck     ok(ret == FALSE, "EM_SETZOOM accepted invalid values (%d).\n", ret);
7852c2c66affSColin Finck 
7853c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7854c2c66affSColin Finck     ok(numerator == 127, "incorrect numerator is %d\n", numerator);
7855c2c66affSColin Finck     ok(denominator == 2, "incorrect denominator is %d\n", denominator);
7856c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7857c2c66affSColin Finck 
7858c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 128, 2);
7859c2c66affSColin Finck     ok(ret == FALSE, "EM_SETZOOM accepted invalid values (%d).\n", ret);
7860c2c66affSColin Finck 
7861c2c66affSColin Finck     /* See if negative numbers are accepted. */
7862c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, -100, -100);
7863c2c66affSColin Finck     ok(ret == FALSE, "EM_SETZOOM accepted invalid values (%d).\n", ret);
7864c2c66affSColin Finck 
7865c2c66affSColin Finck     /* See if negative numbers are accepted. */
7866c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 0, 100);
7867c2c66affSColin Finck     ok(ret == FALSE, "EM_SETZOOM failed (%d).\n", ret);
7868c2c66affSColin Finck 
7869c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_GETZOOM, (WPARAM)&numerator, (LPARAM)&denominator);
7870c2c66affSColin Finck     ok(numerator == 127, "incorrect numerator is %d\n", numerator);
7871c2c66affSColin Finck     ok(denominator == 2, "incorrect denominator is %d\n", denominator);
7872c2c66affSColin Finck     ok(ret == TRUE, "EM_GETZOOM failed (%d).\n", ret);
7873c2c66affSColin Finck 
7874c2c66affSColin Finck     /* Reset the zoom value */
7875c2c66affSColin Finck     ret = SendMessageA(hwnd, EM_SETZOOM, 0, 0);
7876c2c66affSColin Finck     ok(ret == TRUE, "EM_SETZOOM failed (%d).\n", ret);
7877c2c66affSColin Finck 
7878c2c66affSColin Finck     DestroyWindow(hwnd);
7879c2c66affSColin Finck }
7880c2c66affSColin Finck 
7881c2c66affSColin Finck struct dialog_mode_messages
7882c2c66affSColin Finck {
7883c2c66affSColin Finck     int wm_getdefid, wm_close, wm_nextdlgctl;
7884c2c66affSColin Finck };
7885c2c66affSColin Finck 
7886c2c66affSColin Finck static struct dialog_mode_messages dm_messages;
7887c2c66affSColin Finck 
7888c2c66affSColin Finck #define test_dm_messages(wmclose, wmgetdefid, wmnextdlgctl) \
7889c2c66affSColin Finck     ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE message, " \
7890c2c66affSColin Finck     "got %d\n", wmclose, dm_messages.wm_close); \
7891c2c66affSColin Finck     ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID message, " \
7892c2c66affSColin Finck     "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
7893c2c66affSColin Finck     ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL message, " \
7894c2c66affSColin Finck     "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
7895c2c66affSColin Finck 
dialog_mode_wnd_proc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)7896c2c66affSColin Finck static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
7897c2c66affSColin Finck {
7898c2c66affSColin Finck     switch (iMsg)
7899c2c66affSColin Finck     {
7900c2c66affSColin Finck         case DM_GETDEFID:
7901c2c66affSColin Finck             dm_messages.wm_getdefid++;
7902c2c66affSColin Finck             return MAKELONG(ID_RICHEDITTESTDBUTTON, DC_HASDEFID);
7903c2c66affSColin Finck         case WM_NEXTDLGCTL:
7904c2c66affSColin Finck             dm_messages.wm_nextdlgctl++;
7905c2c66affSColin Finck             break;
7906c2c66affSColin Finck         case WM_CLOSE:
7907c2c66affSColin Finck             dm_messages.wm_close++;
7908c2c66affSColin Finck             break;
7909c2c66affSColin Finck     }
7910c2c66affSColin Finck 
7911c2c66affSColin Finck     return DefWindowProcA(hwnd, iMsg, wParam, lParam);
7912c2c66affSColin Finck }
7913c2c66affSColin Finck 
test_dialogmode(void)7914c2c66affSColin Finck static void test_dialogmode(void)
7915c2c66affSColin Finck {
7916c2c66affSColin Finck     HWND hwRichEdit, hwParent, hwButton;
7917c2c66affSColin Finck     MSG msg= {0};
7918c2c66affSColin Finck     int lcount, r;
7919c2c66affSColin Finck     WNDCLASSA cls;
7920c2c66affSColin Finck 
7921c2c66affSColin Finck     cls.style = 0;
7922c2c66affSColin Finck     cls.lpfnWndProc = dialog_mode_wnd_proc;
7923c2c66affSColin Finck     cls.cbClsExtra = 0;
7924c2c66affSColin Finck     cls.cbWndExtra = 0;
7925c2c66affSColin Finck     cls.hInstance = GetModuleHandleA(0);
7926c2c66affSColin Finck     cls.hIcon = 0;
7927c2c66affSColin Finck     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
7928c2c66affSColin Finck     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
7929c2c66affSColin Finck     cls.lpszMenuName = NULL;
7930c2c66affSColin Finck     cls.lpszClassName = "DialogModeParentClass";
7931c2c66affSColin Finck     if(!RegisterClassA(&cls)) assert(0);
7932c2c66affSColin Finck 
7933c2c66affSColin Finck     hwParent = CreateWindowA("DialogModeParentClass", NULL, WS_OVERLAPPEDWINDOW,
7934c2c66affSColin Finck       CW_USEDEFAULT, 0, 200, 120, NULL, NULL, GetModuleHandleA(0), NULL);
7935c2c66affSColin Finck 
7936c2c66affSColin Finck     /* Test richedit(ES_MULTILINE) */
7937c2c66affSColin Finck 
7938c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, ES_MULTILINE, hwParent);
7939c2c66affSColin Finck 
7940c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
7941c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7942c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit,  EM_GETLINECOUNT, 0, 0);
7943c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
7944c2c66affSColin Finck 
7945c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, 0);
7946c2c66affSColin Finck     ok(0x8f == r, "expected 0x8f, got 0x%x\n", r);
7947c2c66affSColin Finck 
7948c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
7949c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7950c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
7951c2c66affSColin Finck     ok(3 == lcount, "expected 3, got %d\n", lcount);
7952c2c66affSColin Finck 
7953c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
7954c2c66affSColin Finck     ok(0x8f == r, "expected 0x8f, got 0x%x\n", r);
7955c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
7956c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7957c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
7958c2c66affSColin Finck     ok(3 == lcount, "expected 3, got %d\n", lcount);
7959c2c66affSColin Finck 
7960c2c66affSColin Finck     DestroyWindow(hwRichEdit);
7961c2c66affSColin Finck 
7962c2c66affSColin Finck     /* Test standalone richedit(ES_MULTILINE) */
7963c2c66affSColin Finck 
7964c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, ES_MULTILINE, NULL);
7965c2c66affSColin Finck 
7966c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
7967c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7968c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
7969c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
7970c2c66affSColin Finck 
7971c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
7972c2c66affSColin Finck     ok(0x8f == r, "expected 0x8f, got 0x%x\n", r);
7973c2c66affSColin Finck 
7974c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
7975c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7976c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
7977c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
7978c2c66affSColin Finck 
7979c2c66affSColin Finck     DestroyWindow(hwRichEdit);
7980c2c66affSColin Finck 
7981c2c66affSColin Finck     /* Check  a destination for messages */
7982c2c66affSColin Finck 
7983c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, ES_MULTILINE, hwParent);
7984c2c66affSColin Finck 
7985c2c66affSColin Finck     SetWindowLongA(hwRichEdit, GWL_STYLE, GetWindowLongA(hwRichEdit, GWL_STYLE)& ~WS_POPUP);
7986c2c66affSColin Finck     SetParent( hwRichEdit, NULL);
7987c2c66affSColin Finck 
7988c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
7989c2c66affSColin Finck     ok(0x8f == r, "expected 0x8f, got 0x%x\n", r);
7990c2c66affSColin Finck 
7991c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
7992c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
7993c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7994c2c66affSColin Finck     test_dm_messages(0, 1, 0);
7995c2c66affSColin Finck 
7996c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
7997c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
7998c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
7999c2c66affSColin Finck     test_dm_messages(0, 0, 1);
8000c2c66affSColin Finck 
8001c2c66affSColin Finck     DestroyWindow(hwRichEdit);
8002c2c66affSColin Finck 
8003c2c66affSColin Finck     /* Check messages from richedit(ES_MULTILINE) */
8004c2c66affSColin Finck 
8005c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, ES_MULTILINE, hwParent);
8006c2c66affSColin Finck 
8007c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8008c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8009c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8010c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8011c2c66affSColin Finck 
8012c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
8013c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
8014c2c66affSColin Finck 
8015c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8016c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
8017c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8018c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8019c2c66affSColin Finck 
8020c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8021c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
8022c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8023c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8024c2c66affSColin Finck 
8025c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8026c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
8027c2c66affSColin Finck     ok(0x8f == r, "expected 0x8f, got 0x%x\n", r);
8028c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8029c2c66affSColin Finck 
8030c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8031c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8032c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8033c2c66affSColin Finck     test_dm_messages(0, 1, 0);
8034c2c66affSColin Finck 
8035c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
8036c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
8037c2c66affSColin Finck 
8038c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8039c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
8040c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8041c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8042c2c66affSColin Finck 
8043c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8044c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
8045c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8046c2c66affSColin Finck     test_dm_messages(0, 0, 1);
8047c2c66affSColin Finck 
8048c2c66affSColin Finck     hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
8049c2c66affSColin Finck         100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL);
8050c2c66affSColin Finck     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
8051c2c66affSColin Finck 
8052c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8053c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8054c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8055c2c66affSColin Finck     test_dm_messages(0, 1, 1);
8056c2c66affSColin Finck 
8057c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
8058c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
8059c2c66affSColin Finck 
8060c2c66affSColin Finck     DestroyWindow(hwButton);
8061c2c66affSColin Finck     DestroyWindow(hwRichEdit);
8062c2c66affSColin Finck 
8063c2c66affSColin Finck     /* Check messages from richedit(ES_MULTILINE|ES_WANTRETURN) */
8064c2c66affSColin Finck 
8065c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, ES_MULTILINE|ES_WANTRETURN, hwParent);
8066c2c66affSColin Finck 
8067c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8068c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8069c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8070c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8071c2c66affSColin Finck 
8072c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
8073c2c66affSColin Finck     ok(2 == lcount, "expected 2, got %d\n", lcount);
8074c2c66affSColin Finck 
8075c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8076c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
8077c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8078c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8079c2c66affSColin Finck 
8080c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8081c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
8082c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8083c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8084c2c66affSColin Finck 
8085c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8086c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
8087c2c66affSColin Finck     ok(0x8f == r, "expected 0x8f, got 0x%x\n", r);
8088c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8089c2c66affSColin Finck 
8090c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8091c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8092c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8093c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8094c2c66affSColin Finck 
8095c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
8096c2c66affSColin Finck     ok(3 == lcount, "expected 3, got %d\n", lcount);
8097c2c66affSColin Finck 
8098c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8099c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
8100c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8101c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8102c2c66affSColin Finck 
8103c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8104c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
8105c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8106c2c66affSColin Finck     test_dm_messages(0, 0, 1);
8107c2c66affSColin Finck 
8108c2c66affSColin Finck     hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
8109c2c66affSColin Finck         100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL);
8110c2c66affSColin Finck     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
8111c2c66affSColin Finck 
8112c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8113c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8114c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8115c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8116c2c66affSColin Finck 
8117c2c66affSColin Finck     lcount = SendMessageA(hwRichEdit, EM_GETLINECOUNT, 0, 0);
8118c2c66affSColin Finck     ok(4 == lcount, "expected 4, got %d\n", lcount);
8119c2c66affSColin Finck 
8120c2c66affSColin Finck     DestroyWindow(hwButton);
8121c2c66affSColin Finck     DestroyWindow(hwRichEdit);
8122c2c66affSColin Finck 
8123c2c66affSColin Finck     /* Check messages from richedit(0) */
8124c2c66affSColin Finck 
8125c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, 0, hwParent);
8126c2c66affSColin Finck 
8127c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8128c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8129c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8130c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8131c2c66affSColin Finck 
8132c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8133c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
8134c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8135c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8136c2c66affSColin Finck 
8137c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8138c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
8139c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8140c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8141c2c66affSColin Finck 
8142c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8143c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
8144c2c66affSColin Finck     ok(0x8b == r, "expected 0x8b, got 0x%x\n", r);
8145c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8146c2c66affSColin Finck 
8147c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8148c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8149c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8150c2c66affSColin Finck     test_dm_messages(0, 1, 0);
8151c2c66affSColin Finck 
8152c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8153c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
8154c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8155c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8156c2c66affSColin Finck 
8157c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8158c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
8159c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8160c2c66affSColin Finck     test_dm_messages(0, 0, 1);
8161c2c66affSColin Finck 
8162c2c66affSColin Finck     hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
8163c2c66affSColin Finck         100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL);
8164c2c66affSColin Finck     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
8165c2c66affSColin Finck 
8166c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8167c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8168c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8169c2c66affSColin Finck     test_dm_messages(0, 1, 1);
8170c2c66affSColin Finck 
8171c2c66affSColin Finck     DestroyWindow(hwRichEdit);
8172c2c66affSColin Finck 
8173c2c66affSColin Finck     /* Check messages from richedit(ES_WANTRETURN) */
8174c2c66affSColin Finck 
8175c2c66affSColin Finck     hwRichEdit = new_window(RICHEDIT_CLASS20A, ES_WANTRETURN, hwParent);
8176c2c66affSColin Finck 
8177c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8178c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8179c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8180c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8181c2c66affSColin Finck 
8182c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8183c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
8184c2c66affSColin Finck     ok(0x8b == r, "expected 0x8b, got 0x%x\n", r);
8185c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8186c2c66affSColin Finck 
8187c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8188c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8189c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8190c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8191c2c66affSColin Finck 
8192c2c66affSColin Finck     hwButton = CreateWindowA("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
8193c2c66affSColin Finck         100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL);
8194c2c66affSColin Finck     ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
8195c2c66affSColin Finck 
8196c2c66affSColin Finck     memset(&dm_messages, 0, sizeof(dm_messages));
8197c2c66affSColin Finck     r = SendMessageA(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
8198c2c66affSColin Finck     ok(0 == r, "expected 0, got %d\n", r);
8199c2c66affSColin Finck     test_dm_messages(0, 0, 0);
8200c2c66affSColin Finck 
8201c2c66affSColin Finck     DestroyWindow(hwRichEdit);
8202c2c66affSColin Finck     DestroyWindow(hwParent);
8203c2c66affSColin Finck }
8204c2c66affSColin Finck 
test_EM_FINDWORDBREAK_W(void)8205c2c66affSColin Finck static void test_EM_FINDWORDBREAK_W(void)
8206c2c66affSColin Finck {
8207c2c66affSColin Finck     static const struct {
8208c2c66affSColin Finck         WCHAR c;
8209c2c66affSColin Finck         BOOL isdelimiter;        /* expected result of WB_ISDELIMITER */
8210c2c66affSColin Finck     } delimiter_tests[] = {
8211c2c66affSColin Finck         {0x0a,   FALSE},         /* newline */
8212c2c66affSColin Finck         {0x0b,   FALSE},         /* vertical tab */
8213c2c66affSColin Finck         {0x0c,   FALSE},         /* form feed */
8214c2c66affSColin Finck         {0x0d,   FALSE},         /* carriage return */
8215c2c66affSColin Finck         {0x20,   TRUE},          /* space */
8216c2c66affSColin Finck         {0x61,   FALSE},         /* capital letter a */
8217c2c66affSColin Finck         {0xa0,   FALSE},         /* no-break space */
8218c2c66affSColin Finck         {0x2000, FALSE},         /* en quad */
8219c2c66affSColin Finck         {0x3000, FALSE},         /* Ideographic space */
8220c2c66affSColin Finck         {0x1100, FALSE},         /* Hangul Choseong Kiyeok (G sound) Ordinary Letter*/
8221c2c66affSColin Finck         {0x11ff, FALSE},         /* Hangul Jongseoung Kiyeok-Hieuh (Hard N sound) Ordinary Letter*/
8222c2c66affSColin Finck         {0x115f, FALSE},         /* Hangul Choseong Filler (no sound, used with two letter Hangul words) Ordinary Letter */
8223c2c66affSColin Finck         {0xac00, FALSE},         /* Hangul character GA*/
8224c2c66affSColin Finck         {0xd7af, FALSE},         /* End of Hangul character chart */
8225c2c66affSColin Finck         {0xf020, TRUE},          /* MS private for CP_SYMBOL round trip?, see kb897872 */
8226c2c66affSColin Finck         {0xff20, FALSE},         /* fullwidth commercial @ */
8227c2c66affSColin Finck         {WCH_EMBEDDING, FALSE},  /* object replacement character*/
8228c2c66affSColin Finck     };
8229c2c66affSColin Finck     int i;
8230c2c66affSColin Finck     HWND hwndRichEdit = new_richeditW(NULL);
8231c2c66affSColin Finck     ok(IsWindowUnicode(hwndRichEdit), "window should be unicode\n");
823276cf09cfSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(delimiter_tests); i++)
8233c2c66affSColin Finck     {
8234c2c66affSColin Finck         WCHAR wbuf[2];
8235c2c66affSColin Finck         int result;
8236c2c66affSColin Finck 
8237c2c66affSColin Finck         wbuf[0] = delimiter_tests[i].c;
8238c2c66affSColin Finck         wbuf[1] = 0;
8239c2c66affSColin Finck         SendMessageW(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)wbuf);
8240c2c66affSColin Finck         result = SendMessageW(hwndRichEdit, EM_FINDWORDBREAK, WB_ISDELIMITER,0);
8241c2c66affSColin Finck         todo_wine_if (wbuf[0] == 0x20 || wbuf[0] == 0xf020)
8242c2c66affSColin Finck             ok(result == delimiter_tests[i].isdelimiter,
8243c2c66affSColin Finck                 "wanted ISDELIMITER_W(0x%x) %d, got %d\n",
8244c2c66affSColin Finck                 delimiter_tests[i].c, delimiter_tests[i].isdelimiter, result);
8245c2c66affSColin Finck     }
8246c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
8247c2c66affSColin Finck }
8248c2c66affSColin Finck 
test_EM_FINDWORDBREAK_A(void)8249c2c66affSColin Finck static void test_EM_FINDWORDBREAK_A(void)
8250c2c66affSColin Finck {
8251c2c66affSColin Finck     static const struct {
8252c2c66affSColin Finck         WCHAR c;
8253c2c66affSColin Finck         BOOL isdelimiter;        /* expected result of WB_ISDELIMITER */
8254c2c66affSColin Finck     } delimiter_tests[] = {
8255c2c66affSColin Finck         {0x0a,   FALSE},         /* newline */
8256c2c66affSColin Finck         {0x0b,   FALSE},         /* vertical tab */
8257c2c66affSColin Finck         {0x0c,   FALSE},         /* form feed */
8258c2c66affSColin Finck         {0x0d,   FALSE},         /* carriage return */
8259c2c66affSColin Finck         {0x20,   TRUE},          /* space */
8260c2c66affSColin Finck         {0x61,   FALSE},         /* capital letter a */
8261c2c66affSColin Finck     };
8262c2c66affSColin Finck     int i;
8263c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
8264c2c66affSColin Finck 
8265c2c66affSColin Finck     ok(!IsWindowUnicode(hwndRichEdit), "window should not be unicode\n");
826676cf09cfSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(delimiter_tests); i++)
8267c2c66affSColin Finck     {
8268c2c66affSColin Finck         int result;
8269c2c66affSColin Finck         char buf[2];
8270c2c66affSColin Finck         buf[0] = delimiter_tests[i].c;
8271c2c66affSColin Finck         buf[1] = 0;
8272c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buf);
8273c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, EM_FINDWORDBREAK, WB_ISDELIMITER, 0);
8274c2c66affSColin Finck         todo_wine_if (buf[0] == 0x20)
8275c2c66affSColin Finck             ok(result == delimiter_tests[i].isdelimiter,
8276c2c66affSColin Finck                "wanted ISDELIMITER_A(0x%x) %d, got %d\n",
8277c2c66affSColin Finck                delimiter_tests[i].c, delimiter_tests[i].isdelimiter, result);
8278c2c66affSColin Finck     }
8279c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
8280c2c66affSColin Finck }
8281c2c66affSColin Finck 
format_test_result(char * target,const char * src)828276cf09cfSAmine Khaldi static void format_test_result(char *target, const char *src)
828376cf09cfSAmine Khaldi {
828476cf09cfSAmine Khaldi     int i;
828576cf09cfSAmine Khaldi     for (i = 0; i < strlen(src); i++)
828676cf09cfSAmine Khaldi         sprintf(target + 2*i, "%02x", src[i] & 0xFF);
828776cf09cfSAmine Khaldi     target[2*i] = 0;
828876cf09cfSAmine Khaldi }
828976cf09cfSAmine Khaldi 
8290c2c66affSColin Finck /*
8291c2c66affSColin Finck  * This test attempts to show the effect of enter on a richedit
8292c2c66affSColin Finck  * control v1.0 inserts CRLF whereas for higher versions it only
8293c2c66affSColin Finck  * inserts CR. If shows that EM_GETTEXTEX with GT_USECRLF == WM_GETTEXT
8294c2c66affSColin Finck  * and also shows that GT_USECRLF has no effect in richedit 1.0, but
8295c2c66affSColin Finck  * does for higher. The same test is cloned in riched32 and riched20.
829676cf09cfSAmine Khaldi  * Also shows the difference between WM_CHAR/WM_KEYDOWN in v1.0 and higher versions
8297c2c66affSColin Finck  */
test_enter(void)8298c2c66affSColin Finck static void test_enter(void)
8299c2c66affSColin Finck {
8300c2c66affSColin Finck     static const struct {
8301c2c66affSColin Finck       const char *initialtext;
8302c2c66affSColin Finck       const int   cursor;
8303c2c66affSColin Finck       const char *expectedwmtext;
8304c2c66affSColin Finck       const char *expectedemtext;
8305c2c66affSColin Finck       const char *expectedemtextcrlf;
8306c2c66affSColin Finck     } testenteritems[] = {
8307c2c66affSColin Finck       { "aaabbb\r\n", 3, "aaa\r\nbbb\r\n", "aaa\rbbb\r", "aaa\r\nbbb\r\n"},
8308c2c66affSColin Finck       { "aaabbb\r\n", 6, "aaabbb\r\n\r\n", "aaabbb\r\r", "aaabbb\r\n\r\n"},
8309c2c66affSColin Finck       { "aa\rabbb\r\n", 7, "aa\r\nabbb\r\n\r\n", "aa\rabbb\r\r", "aa\r\nabbb\r\n\r\n"},
8310c2c66affSColin Finck       { "aa\rabbb\r\n", 3, "aa\r\n\r\nabbb\r\n", "aa\r\rabbb\r", "aa\r\n\r\nabbb\r\n"},
8311c2c66affSColin Finck       { "aa\rabbb\r\n", 2, "aa\r\n\r\nabbb\r\n", "aa\r\rabbb\r", "aa\r\n\r\nabbb\r\n"}
8312c2c66affSColin Finck     };
8313c2c66affSColin Finck 
8314c2c66affSColin Finck   char expectedbuf[1024];
8315c2c66affSColin Finck   char resultbuf[1024];
8316c2c66affSColin Finck   HWND hwndRichEdit = new_richedit(NULL);
831776cf09cfSAmine Khaldi   UINT i;
8318c2c66affSColin Finck   char buf[1024] = {0};
831976cf09cfSAmine Khaldi   GETTEXTEX getText = {sizeof(buf)};
8320c2c66affSColin Finck   LRESULT result;
8321c2c66affSColin Finck   const char *expected;
8322c2c66affSColin Finck 
832376cf09cfSAmine Khaldi   for (i = 0; i < ARRAY_SIZE(testenteritems); i++)
832476cf09cfSAmine Khaldi   {
8325c2c66affSColin Finck     /* Set the text to the initial text */
8326c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)testenteritems[i].initialtext);
8327c2c66affSColin Finck     ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
8328c2c66affSColin Finck 
8329c2c66affSColin Finck     /* Send Enter */
8330c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETSEL, testenteritems[i].cursor, testenteritems[i].cursor);
8331c2c66affSColin Finck     simulate_typing_characters(hwndRichEdit, "\r");
8332c2c66affSColin Finck 
8333c2c66affSColin Finck     /* 1. Retrieve with WM_GETTEXT */
8334c2c66affSColin Finck     buf[0] = 0x00;
8335c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM)buf);
8336c2c66affSColin Finck     expected = testenteritems[i].expectedwmtext;
8337c2c66affSColin Finck 
833876cf09cfSAmine Khaldi     format_test_result(resultbuf, buf);
833976cf09cfSAmine Khaldi     format_test_result(expectedbuf, expected);
8340c2c66affSColin Finck 
8341c2c66affSColin Finck     result = strcmp(expected, buf);
8342c2c66affSColin Finck     ok (result == 0,
8343c2c66affSColin Finck         "[%d] WM_GETTEXT unexpected '%s' expected '%s'\n",
8344c2c66affSColin Finck         i, resultbuf, expectedbuf);
8345c2c66affSColin Finck 
8346c2c66affSColin Finck     /* 2. Retrieve with EM_GETTEXTEX, GT_DEFAULT */
8347c2c66affSColin Finck     getText.flags = GT_DEFAULT;
8348c2c66affSColin Finck     getText.codepage = CP_ACP;
8349c2c66affSColin Finck     buf[0] = 0x00;
8350c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
8351c2c66affSColin Finck     expected = testenteritems[i].expectedemtext;
8352c2c66affSColin Finck 
835376cf09cfSAmine Khaldi     format_test_result(resultbuf, buf);
835476cf09cfSAmine Khaldi     format_test_result(expectedbuf, expected);
8355c2c66affSColin Finck 
8356c2c66affSColin Finck     result = strcmp(expected, buf);
8357c2c66affSColin Finck     ok (result == 0,
8358c2c66affSColin Finck         "[%d] EM_GETTEXTEX, GT_DEFAULT unexpected '%s', expected '%s'\n",
8359c2c66affSColin Finck         i, resultbuf, expectedbuf);
8360c2c66affSColin Finck 
8361c2c66affSColin Finck     /* 3. Retrieve with EM_GETTEXTEX, GT_USECRLF */
8362c2c66affSColin Finck     getText.flags = GT_USECRLF;
8363c2c66affSColin Finck     getText.codepage = CP_ACP;
8364c2c66affSColin Finck     buf[0] = 0x00;
8365c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
8366c2c66affSColin Finck     expected = testenteritems[i].expectedemtextcrlf;
8367c2c66affSColin Finck 
836876cf09cfSAmine Khaldi     format_test_result(resultbuf, buf);
836976cf09cfSAmine Khaldi     format_test_result(expectedbuf, expected);
8370c2c66affSColin Finck 
8371c2c66affSColin Finck     result = strcmp(expected, buf);
8372c2c66affSColin Finck     ok (result == 0,
8373c2c66affSColin Finck         "[%d] EM_GETTEXTEX, GT_USECRLF unexpected '%s', expected '%s'\n",
8374c2c66affSColin Finck         i, resultbuf, expectedbuf);
8375c2c66affSColin Finck   }
8376c2c66affSColin Finck 
837776cf09cfSAmine Khaldi   /* Show that WM_CHAR is handled differently from WM_KEYDOWN */
837876cf09cfSAmine Khaldi   getText.flags    = GT_DEFAULT;
837976cf09cfSAmine Khaldi   getText.codepage = CP_ACP;
838076cf09cfSAmine Khaldi 
838176cf09cfSAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
838276cf09cfSAmine Khaldi   ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
838376cf09cfSAmine Khaldi   SendMessageW(hwndRichEdit, WM_CHAR, 'T', 0);
838476cf09cfSAmine Khaldi   SendMessageW(hwndRichEdit, WM_KEYDOWN, VK_RETURN, 0);
838576cf09cfSAmine Khaldi 
838676cf09cfSAmine Khaldi   result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
838776cf09cfSAmine Khaldi   ok(result == 2, "Got %d\n", (int)result);
838876cf09cfSAmine Khaldi   format_test_result(resultbuf, buf);
838976cf09cfSAmine Khaldi   format_test_result(expectedbuf, "T\r");
839076cf09cfSAmine Khaldi   result = strcmp(resultbuf, expectedbuf);
839176cf09cfSAmine Khaldi   ok (result == 0, "[%d] EM_GETTEXTEX, GT_DEFAULT unexpected '%s', expected '%s'\n", i, resultbuf, expectedbuf);
839276cf09cfSAmine Khaldi 
839376cf09cfSAmine Khaldi   result = SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"");
839476cf09cfSAmine Khaldi   ok (result == 1, "[%d] WM_SETTEXT returned %ld instead of 1\n", i, result);
839576cf09cfSAmine Khaldi   SendMessageW(hwndRichEdit, WM_CHAR, 'T', 0);
839676cf09cfSAmine Khaldi   SendMessageW(hwndRichEdit, WM_CHAR, '\r', 0);
839776cf09cfSAmine Khaldi 
839876cf09cfSAmine Khaldi   result = SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
839976cf09cfSAmine Khaldi   ok(result == 1, "Got %d\n", (int)result);
840076cf09cfSAmine Khaldi   format_test_result(resultbuf, buf);
840176cf09cfSAmine Khaldi   format_test_result(expectedbuf, "T");
840276cf09cfSAmine Khaldi   result = strcmp(resultbuf, expectedbuf);
840376cf09cfSAmine Khaldi   ok (result == 0, "[%d] EM_GETTEXTEX, GT_DEFAULT unexpected '%s', expected '%s'\n", i, resultbuf, expectedbuf);
840476cf09cfSAmine Khaldi 
8405c2c66affSColin Finck   DestroyWindow(hwndRichEdit);
8406c2c66affSColin Finck }
8407c2c66affSColin Finck 
test_WM_CREATE(void)8408c2c66affSColin Finck static void test_WM_CREATE(void)
8409c2c66affSColin Finck {
8410c2c66affSColin Finck     static const WCHAR titleW[] = {'l','i','n','e','1','\n','l','i','n','e','2',0};
8411c2c66affSColin Finck     static const char title[] = "line1\nline2";
8412c2c66affSColin Finck 
8413c2c66affSColin Finck     HWND rich_edit;
8414c2c66affSColin Finck     LRESULT res;
8415c2c66affSColin Finck     char buf[64];
8416c2c66affSColin Finck     int len;
8417c2c66affSColin Finck 
8418c2c66affSColin Finck     rich_edit = CreateWindowA(RICHEDIT_CLASS20A, title, WS_POPUP|WS_VISIBLE,
8419c2c66affSColin Finck             0, 0, 200, 80, NULL, NULL, NULL, NULL);
8420c2c66affSColin Finck     ok(rich_edit != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError());
8421c2c66affSColin Finck 
8422c2c66affSColin Finck     len = GetWindowTextA(rich_edit, buf, sizeof(buf));
8423c2c66affSColin Finck     ok(len == 5, "GetWindowText returned %d\n", len);
8424c2c66affSColin Finck     ok(!strcmp(buf, "line1"), "buf = %s\n", buf);
8425c2c66affSColin Finck 
8426c2c66affSColin Finck     res = SendMessageA(rich_edit, EM_GETSEL, 0, 0);
8427c2c66affSColin Finck     ok(res == 0, "SendMessage(EM_GETSEL) returned %lx\n", res);
8428c2c66affSColin Finck 
8429c2c66affSColin Finck     DestroyWindow(rich_edit);
8430c2c66affSColin Finck 
8431c2c66affSColin Finck     rich_edit = CreateWindowW(RICHEDIT_CLASS20W, titleW, WS_POPUP|WS_VISIBLE|ES_MULTILINE,
8432c2c66affSColin Finck             0, 0, 200, 80, NULL, NULL, NULL, NULL);
8433c2c66affSColin Finck     ok(rich_edit != NULL, "class: %s, error: %d\n", wine_dbgstr_w(RICHEDIT_CLASS20W), (int) GetLastError());
8434c2c66affSColin Finck 
8435c2c66affSColin Finck     len = GetWindowTextA(rich_edit, buf, sizeof(buf));
8436c2c66affSColin Finck     ok(len == 12, "GetWindowText returned %d\n", len);
8437c2c66affSColin Finck     ok(!strcmp(buf, "line1\r\nline2"), "buf = %s\n", buf);
8438c2c66affSColin Finck 
8439c2c66affSColin Finck     res = SendMessageA(rich_edit, EM_GETSEL, 0, 0);
8440c2c66affSColin Finck     ok(res == 0, "SendMessage(EM_GETSEL) returned %lx\n", res);
8441c2c66affSColin Finck 
8442c2c66affSColin Finck     DestroyWindow(rich_edit);
8443c2c66affSColin Finck }
8444c2c66affSColin Finck 
8445c2c66affSColin Finck /*******************************************************************
8446c2c66affSColin Finck  * Test that after deleting all of the text, the first paragraph
8447c2c66affSColin Finck  * format reverts to the default.
8448c2c66affSColin Finck  */
test_reset_default_para_fmt(void)8449c2c66affSColin Finck static void test_reset_default_para_fmt( void )
8450c2c66affSColin Finck {
8451c2c66affSColin Finck     HWND richedit = new_richeditW( NULL );
8452c2c66affSColin Finck     PARAFORMAT2 fmt;
8453c2c66affSColin Finck     WORD def_align, new_align;
8454c2c66affSColin Finck 
8455c2c66affSColin Finck     memset( &fmt, 0, sizeof(fmt) );
8456c2c66affSColin Finck     fmt.cbSize = sizeof(PARAFORMAT2);
8457c2c66affSColin Finck     fmt.dwMask = -1;
8458c2c66affSColin Finck     SendMessageA( richedit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8459c2c66affSColin Finck     def_align = fmt.wAlignment;
8460c2c66affSColin Finck     new_align = (def_align == PFA_LEFT) ? PFA_RIGHT : PFA_LEFT;
8461c2c66affSColin Finck 
8462c2c66affSColin Finck     simulate_typing_characters( richedit, "123" );
8463c2c66affSColin Finck 
8464c2c66affSColin Finck     SendMessageA( richedit, EM_SETSEL, 0, -1 );
8465c2c66affSColin Finck     fmt.dwMask = PFM_ALIGNMENT;
8466c2c66affSColin Finck     fmt.wAlignment = new_align;
8467c2c66affSColin Finck     SendMessageA( richedit, EM_SETPARAFORMAT, 0, (LPARAM)&fmt );
8468c2c66affSColin Finck 
8469c2c66affSColin Finck     SendMessageA( richedit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8470c2c66affSColin Finck     ok( fmt.wAlignment == new_align, "got %d expect %d\n", fmt.wAlignment, new_align );
8471c2c66affSColin Finck 
8472c2c66affSColin Finck     SendMessageA( richedit, EM_SETSEL, 0, -1 );
8473c2c66affSColin Finck     SendMessageA( richedit, WM_CUT, 0, 0 );
8474c2c66affSColin Finck 
8475c2c66affSColin Finck     SendMessageA( richedit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8476c2c66affSColin Finck     ok( fmt.wAlignment == def_align, "got %d expect %d\n", fmt.wAlignment, def_align );
8477c2c66affSColin Finck 
8478c2c66affSColin Finck     DestroyWindow( richedit );
8479c2c66affSColin Finck }
8480c2c66affSColin Finck 
test_EM_SETREADONLY(void)8481c2c66affSColin Finck static void test_EM_SETREADONLY(void)
8482c2c66affSColin Finck {
8483c2c66affSColin Finck     HWND richedit = new_richeditW(NULL);
8484c2c66affSColin Finck     DWORD dwStyle;
8485c2c66affSColin Finck     LRESULT res;
8486c2c66affSColin Finck 
8487c2c66affSColin Finck     res = SendMessageA(richedit, EM_SETREADONLY, TRUE, 0);
8488c2c66affSColin Finck     ok(res == 1, "EM_SETREADONLY\n");
8489c2c66affSColin Finck     dwStyle = GetWindowLongA(richedit, GWL_STYLE);
8490c2c66affSColin Finck     ok(dwStyle & ES_READONLY, "got wrong value: 0x%x\n", dwStyle);
8491c2c66affSColin Finck 
8492c2c66affSColin Finck     res = SendMessageA(richedit, EM_SETREADONLY, FALSE, 0);
8493c2c66affSColin Finck     ok(res == 1, "EM_SETREADONLY\n");
8494c2c66affSColin Finck     dwStyle = GetWindowLongA(richedit, GWL_STYLE);
8495c2c66affSColin Finck     ok(!(dwStyle & ES_READONLY), "got wrong value: 0x%x\n", dwStyle);
8496c2c66affSColin Finck 
8497c2c66affSColin Finck     DestroyWindow(richedit);
8498c2c66affSColin Finck }
8499c2c66affSColin Finck 
twips2points(LONG value)8500c2c66affSColin Finck static inline LONG twips2points(LONG value)
8501c2c66affSColin Finck {
8502c2c66affSColin Finck     return value / 20;
8503c2c66affSColin Finck }
8504c2c66affSColin Finck 
8505c2c66affSColin Finck #define TEST_EM_SETFONTSIZE(hwnd,size,expected_size,expected_res,expected_undo) \
8506c2c66affSColin Finck     _test_font_size(__LINE__,hwnd,size,expected_size,expected_res,expected_undo)
_test_font_size(unsigned line,HWND hwnd,LONG size,LONG expected_size,LRESULT expected_res,BOOL expected_undo)8507c2c66affSColin Finck static void _test_font_size(unsigned line, HWND hwnd, LONG size, LONG expected_size,
8508c2c66affSColin Finck                             LRESULT expected_res, BOOL expected_undo)
8509c2c66affSColin Finck {
8510c2c66affSColin Finck     CHARFORMAT2A cf;
8511c2c66affSColin Finck     LRESULT res;
8512c2c66affSColin Finck     BOOL isundo;
8513c2c66affSColin Finck 
8514c2c66affSColin Finck     cf.cbSize = sizeof(cf);
8515c2c66affSColin Finck     cf.dwMask = CFM_SIZE;
8516c2c66affSColin Finck 
8517c2c66affSColin Finck     res = SendMessageA(hwnd, EM_SETFONTSIZE, size, 0);
8518c2c66affSColin Finck     SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
8519c2c66affSColin Finck     isundo = SendMessageA(hwnd, EM_CANUNDO, 0, 0);
8520c2c66affSColin Finck     ok_(__FILE__,line)(res == expected_res, "EM_SETFONTSIZE unexpected return value: %lx.\n", res);
8521c2c66affSColin Finck     ok_(__FILE__,line)(twips2points(cf.yHeight) == expected_size, "got wrong font size: %d, expected: %d\n",
8522c2c66affSColin Finck                        twips2points(cf.yHeight), expected_size);
8523c2c66affSColin Finck     ok_(__FILE__,line)(isundo == expected_undo, "get wrong undo mark: %d, expected: %d.\n",
8524c2c66affSColin Finck                        isundo, expected_undo);
8525c2c66affSColin Finck }
8526c2c66affSColin Finck 
test_EM_SETFONTSIZE(void)8527c2c66affSColin Finck static void test_EM_SETFONTSIZE(void)
8528c2c66affSColin Finck {
8529c2c66affSColin Finck     HWND richedit = new_richedit(NULL);
8530c2c66affSColin Finck     CHAR text[] = "wine";
8531c2c66affSColin Finck     CHARFORMAT2A tmp_cf;
8532c2c66affSColin Finck     LONG default_size;
8533c2c66affSColin Finck 
8534c2c66affSColin Finck     tmp_cf.cbSize = sizeof(tmp_cf);
8535c2c66affSColin Finck     tmp_cf.dwMask = CFM_SIZE;
8536c2c66affSColin Finck     tmp_cf.yHeight = 9 * 20.0;
8537c2c66affSColin Finck     SendMessageA(richedit, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&tmp_cf);
8538c2c66affSColin Finck 
8539c2c66affSColin Finck     SendMessageA(richedit, WM_SETTEXT, 0, (LPARAM)text);
8540c2c66affSColin Finck 
8541c2c66affSColin Finck     SendMessageA(richedit, EM_SETMODIFY, FALSE, 0);
8542c2c66affSColin Finck     /* without selection */
8543c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 10, TRUE, FALSE); /* 9 + 1 -> 10 */
8544c2c66affSColin Finck     SendMessageA(richedit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&tmp_cf);
8545c2c66affSColin Finck     default_size = twips2points(tmp_cf.yHeight);
8546c2c66affSColin Finck     ok(default_size == 9, "Default font size should not be changed.\n");
8547c2c66affSColin Finck     ok(SendMessageA(richedit, EM_SETMODIFY, 0, 0) == FALSE, "Modify flag should not be changed.\n");
8548c2c66affSColin Finck 
8549c2c66affSColin Finck     SendMessageA(richedit, EM_SETSEL, 0, 2);
8550c2c66affSColin Finck 
8551c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 9, TRUE, TRUE); /* 9 + 0 -> 9 */
8552c2c66affSColin Finck 
8553c2c66affSColin Finck     SendMessageA(richedit, EM_SETMODIFY, FALSE, 0);
8554c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 3, 12, TRUE, TRUE); /* 9 + 3 -> 12 */
8555c2c66affSColin Finck     ok(SendMessageA(richedit, EM_SETMODIFY, 0, 0) == FALSE, "Modify flag should not be changed.\n");
8556c2c66affSColin Finck 
8557c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 14, TRUE, TRUE); /* 12 + 1 + 1 -> 14 */
8558c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -1, 12, TRUE, TRUE); /* 14 - 1 - 1 -> 12 */
8559c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 4, 16, TRUE, TRUE); /* 12 + 4 -> 16 */
8560c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 3, 20, TRUE, TRUE); /* 16 + 3 + 1 -> 20 */
8561c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 20, TRUE, TRUE); /* 20 + 0 -> 20 */
8562c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 8, 28, TRUE, TRUE); /* 20 + 8 -> 28 */
8563c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 28, TRUE, TRUE); /* 28 + 0 -> 28 */
8564c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 36, TRUE, TRUE); /* 28 + 1 -> 36 */
8565c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 36, TRUE, TRUE); /* 36 + 0 -> 36 */
8566c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 48, TRUE, TRUE); /* 36 + 1 -> 48 */
8567c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 48, TRUE, TRUE); /* 48 + 0 -> 48 */
8568c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 72, TRUE, TRUE); /* 48 + 1 -> 72 */
8569c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 72, TRUE, TRUE); /* 72 + 0 -> 72 */
8570c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 80, TRUE, TRUE); /* 72 + 1 -> 80 */
8571c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 80, TRUE, TRUE); /* 80 + 0 -> 80 */
8572c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 90, TRUE, TRUE); /* 80 + 1 -> 90 */
8573c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 90, TRUE, TRUE); /* 90 + 0 -> 90 */
8574c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 1, 100, TRUE, TRUE); /* 90 + 1 -> 100 */
8575c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 25, 130, TRUE, TRUE); /* 100 + 25 -> 130 */
8576c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -1, 120, TRUE, TRUE); /* 130 - 1 -> 120 */
8577c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -35, 80, TRUE, TRUE); /* 120 - 35 -> 80 */
8578c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -7, 72, TRUE, TRUE); /* 80 - 7 -> 72 */
8579c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -42, 28, TRUE, TRUE); /* 72 - 42 -> 28 */
8580c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -16, 12, TRUE, TRUE); /* 28 - 16 -> 12 */
8581c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -3, 9, TRUE, TRUE); /* 12 - 3 -> 9 */
8582c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -8, 1, TRUE, TRUE); /* 9 - 8 -> 1 */
8583c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, -111, 1, TRUE, TRUE); /* 1 - 111 -> 1 */
8584c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 10086, 1638, TRUE, TRUE); /* 1 + 10086 -> 1638 */
8585c2c66affSColin Finck 
8586c2c66affSColin Finck     /* return FALSE when richedit is TM_PLAINTEXT mode */
8587c2c66affSColin Finck     SendMessageA(richedit, WM_SETTEXT, 0, (LPARAM)"");
8588c2c66affSColin Finck     SendMessageA(richedit, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT, 0);
8589c2c66affSColin Finck     TEST_EM_SETFONTSIZE(richedit, 0, 9, FALSE, FALSE);
8590c2c66affSColin Finck 
8591c2c66affSColin Finck     DestroyWindow(richedit);
8592c2c66affSColin Finck }
8593c2c66affSColin Finck 
test_alignment_style(void)8594c2c66affSColin Finck static void test_alignment_style(void)
8595c2c66affSColin Finck {
8596c2c66affSColin Finck     HWND richedit = NULL;
8597c2c66affSColin Finck     PARAFORMAT2 pf;
8598c2c66affSColin Finck     DWORD align_style[] = {ES_LEFT, ES_CENTER, ES_RIGHT, ES_RIGHT | ES_CENTER,
8599c2c66affSColin Finck                            ES_LEFT | ES_CENTER, ES_LEFT | ES_RIGHT,
8600c2c66affSColin Finck                            ES_LEFT | ES_RIGHT | ES_CENTER};
8601c2c66affSColin Finck     DWORD align_mask[] = {PFA_LEFT, PFA_CENTER, PFA_RIGHT, PFA_CENTER, PFA_CENTER,
8602c2c66affSColin Finck                           PFA_RIGHT, PFA_CENTER};
8603c2c66affSColin Finck     const char * streamtext =
8604c2c66affSColin Finck         "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 System;}}\r\n"
8605c2c66affSColin Finck         "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n"
8606c2c66affSColin Finck         "}\r\n";
8607c2c66affSColin Finck     EDITSTREAM es;
8608c2c66affSColin Finck     int i;
8609c2c66affSColin Finck 
861076cf09cfSAmine Khaldi     for (i = 0; i < ARRAY_SIZE(align_style); i++)
8611c2c66affSColin Finck     {
8612c2c66affSColin Finck         DWORD dwStyle, new_align;
8613c2c66affSColin Finck 
8614c2c66affSColin Finck         richedit = new_windowW(RICHEDIT_CLASS20W, align_style[i], NULL);
8615c2c66affSColin Finck         memset(&pf, 0, sizeof(pf));
8616c2c66affSColin Finck         pf.cbSize = sizeof(PARAFORMAT2);
8617c2c66affSColin Finck         pf.dwMask = -1;
8618c2c66affSColin Finck 
8619c2c66affSColin Finck         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8620c2c66affSColin Finck         ok(pf.wAlignment == align_mask[i], "(i = %d) got %d expected %d\n",
8621c2c66affSColin Finck            i, pf.wAlignment, align_mask[i]);
8622c2c66affSColin Finck         dwStyle = GetWindowLongW(richedit, GWL_STYLE);
8623c2c66affSColin Finck         ok((i ? (dwStyle & align_style[i]) : (!(dwStyle & 0x0000000f))) ,
8624c2c66affSColin Finck            "(i = %d) didn't set right align style: 0x%x\n", i, dwStyle);
8625c2c66affSColin Finck 
8626c2c66affSColin Finck 
8627c2c66affSColin Finck         /* Based on test_reset_default_para_fmt() */
8628c2c66affSColin Finck         new_align = (align_mask[i] == PFA_LEFT) ? PFA_RIGHT : PFA_LEFT;
8629c2c66affSColin Finck         simulate_typing_characters(richedit, "123");
8630c2c66affSColin Finck 
8631c2c66affSColin Finck         SendMessageW(richedit, EM_SETSEL, 0, -1);
8632c2c66affSColin Finck         pf.dwMask = PFM_ALIGNMENT;
8633c2c66affSColin Finck         pf.wAlignment = new_align;
8634c2c66affSColin Finck         SendMessageW(richedit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
8635c2c66affSColin Finck 
8636c2c66affSColin Finck         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8637c2c66affSColin Finck         ok(pf.wAlignment == new_align, "got %d expect %d\n", pf.wAlignment, new_align);
8638c2c66affSColin Finck 
8639c2c66affSColin Finck         SendMessageW(richedit, EM_SETSEL, 0, -1);
8640c2c66affSColin Finck         SendMessageW(richedit, WM_CUT, 0, 0);
8641c2c66affSColin Finck 
8642c2c66affSColin Finck         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8643c2c66affSColin Finck         ok(pf.wAlignment == align_mask[i], "got %d expect %d\n", pf.wAlignment, align_mask[i]);
8644c2c66affSColin Finck 
8645*40955b44SDoug Lyons         /* Test out of bounds tab count */
8646*40955b44SDoug Lyons         pf.dwMask = PFM_TABSTOPS;
8647*40955b44SDoug Lyons         pf.cTabCount = -25000;
8648*40955b44SDoug Lyons         SendMessageW(richedit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
8649*40955b44SDoug Lyons         ok(pf.cTabCount == -25000, "Got %d\n", pf.cTabCount);
8650*40955b44SDoug Lyons         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8651*40955b44SDoug Lyons         ok(pf.cTabCount == 0, "Got %d\n", pf.cTabCount);
8652*40955b44SDoug Lyons         pf.dwMask = PFM_TABSTOPS;
8653*40955b44SDoug Lyons         pf.cTabCount = 25000;
8654*40955b44SDoug Lyons         SendMessageW(richedit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
8655*40955b44SDoug Lyons         ok(pf.cTabCount == 25000, "Got %d\n", pf.cTabCount);
8656*40955b44SDoug Lyons         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8657*40955b44SDoug Lyons         ok(pf.cTabCount == 32, "Got %d\n", pf.cTabCount);
8658*40955b44SDoug Lyons         pf.dwMask = PFM_TABSTOPS;
8659*40955b44SDoug Lyons         pf.cTabCount = 32;
8660*40955b44SDoug Lyons         SendMessageW(richedit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
8661*40955b44SDoug Lyons         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8662*40955b44SDoug Lyons         ok(pf.cTabCount == 32, "Got %d\n", pf.cTabCount);
8663*40955b44SDoug Lyons         pf.dwMask = PFM_TABSTOPS;
8664*40955b44SDoug Lyons         pf.cTabCount = 33;
8665*40955b44SDoug Lyons         SendMessageW(richedit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
8666*40955b44SDoug Lyons         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8667*40955b44SDoug Lyons         ok(pf.cTabCount == 32, "Got %d\n", pf.cTabCount);
8668*40955b44SDoug Lyons         pf.dwMask = PFM_TABSTOPS;
8669*40955b44SDoug Lyons         pf.cTabCount = 1;
8670*40955b44SDoug Lyons         SendMessageW(richedit, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
8671*40955b44SDoug Lyons         SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
8672*40955b44SDoug Lyons         ok(pf.cTabCount == 1, "Got %d\n", pf.cTabCount);
8673*40955b44SDoug Lyons 
8674c2c66affSColin Finck         DestroyWindow(richedit);
8675c2c66affSColin Finck     }
8676c2c66affSColin Finck 
8677c2c66affSColin Finck     /* test with EM_STREAMIN */
8678c2c66affSColin Finck     richedit = new_windowW(RICHEDIT_CLASS20W, ES_CENTER, NULL);
8679c2c66affSColin Finck     simulate_typing_characters(richedit, "abc");
8680c2c66affSColin Finck     es.dwCookie = (DWORD_PTR)&streamtext;
8681c2c66affSColin Finck     es.dwError = 0;
8682c2c66affSColin Finck     es.pfnCallback = test_EM_STREAMIN_esCallback;
8683c2c66affSColin Finck     SendMessageW(richedit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
8684c2c66affSColin Finck     SendMessageW(richedit, EM_SETSEL, 0, -1);
8685c2c66affSColin Finck     memset(&pf, 0, sizeof(pf));
8686c2c66affSColin Finck     pf.cbSize = sizeof(PARAFORMAT2);
8687c2c66affSColin Finck     pf.dwMask = -1;
8688c2c66affSColin Finck     SendMessageW(richedit, EM_GETPARAFORMAT, SCF_SELECTION, (LPARAM)&pf);
8689c2c66affSColin Finck     ok(pf.wAlignment == PFA_LEFT, "got %d expected PFA_LEFT\n", pf.wAlignment);
8690c2c66affSColin Finck     DestroyWindow(richedit);
8691c2c66affSColin Finck }
8692c2c66affSColin Finck 
test_WM_GETTEXTLENGTH(void)8693c2c66affSColin Finck static void test_WM_GETTEXTLENGTH(void)
8694c2c66affSColin Finck {
8695c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
8696c2c66affSColin Finck     static const char text1[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee";
8697c2c66affSColin Finck     static const char text2[] = "aaa\r\nbbb\r\nccc\r\nddd\r\neee\r\n";
8698c2c66affSColin Finck     static const char text3[] = "abcdef\x8e\xf0";
8699c2c66affSColin Finck     int result;
8700c2c66affSColin Finck 
8701c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text1);
8702c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
8703c2c66affSColin Finck     ok(result == lstrlenA(text1), "WM_GETTEXTLENGTH returned %d, expected %d\n",
8704c2c66affSColin Finck        result, lstrlenA(text1));
8705c2c66affSColin Finck 
8706c2c66affSColin Finck     SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text2);
8707c2c66affSColin Finck     result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
8708c2c66affSColin Finck     ok(result == lstrlenA(text2), "WM_GETTEXTLENGTH returned %d, expected %d\n",
8709c2c66affSColin Finck        result, lstrlenA(text2));
8710c2c66affSColin Finck 
8711c2c66affSColin Finck     /* Test with multibyte character */
8712c2c66affSColin Finck     if (!is_lang_japanese)
8713c2c66affSColin Finck         skip("Skip multibyte character tests on non-Japanese platform\n");
8714c2c66affSColin Finck     else
8715c2c66affSColin Finck     {
8716c2c66affSColin Finck         SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text3);
8717c2c66affSColin Finck         result = SendMessageA(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0);
8718c2c66affSColin Finck         todo_wine ok(result == 8, "WM_GETTEXTLENGTH returned %d, expected 8\n", result);
8719c2c66affSColin Finck     }
8720c2c66affSColin Finck 
8721c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
8722c2c66affSColin Finck }
8723c2c66affSColin Finck 
test_rtf(void)8724c2c66affSColin Finck static void test_rtf(void)
8725c2c66affSColin Finck {
8726c2c66affSColin Finck     const char *specials = "{\\rtf1\\emspace\\enspace\\bullet\\lquote"
8727c2c66affSColin Finck         "\\rquote\\ldblquote\\rdblquote\\ltrmark\\rtlmark\\zwj\\zwnj}";
8728c2c66affSColin Finck     const WCHAR expect_specials[] = {' ',' ',0x2022,0x2018,0x2019,0x201c,
8729c2c66affSColin Finck                                      0x201d,0x200e,0x200f,0x200d,0x200c};
8730c2c66affSColin Finck     const char *pard = "{\\rtf1 ABC\\rtlpar\\par DEF\\par HIJ\\pard\\par}";
8731c2c66affSColin Finck     const char *highlight = "{\\rtf1{\\colortbl;\\red0\\green0\\blue0;\\red128\\green128\\blue128;\\red192\\green192\\blue192;}\\cf2\\highlight3 foo\\par}";
8732c2c66affSColin Finck 
8733c2c66affSColin Finck     HWND edit = new_richeditW( NULL );
8734c2c66affSColin Finck     EDITSTREAM es;
8735c2c66affSColin Finck     WCHAR buf[80];
8736c2c66affSColin Finck     LRESULT result;
8737c2c66affSColin Finck     PARAFORMAT2 fmt;
8738c2c66affSColin Finck     CHARFORMAT2W cf;
8739c2c66affSColin Finck 
8740c2c66affSColin Finck     /* Test rtf specials */
8741c2c66affSColin Finck     es.dwCookie = (DWORD_PTR)&specials;
8742c2c66affSColin Finck     es.dwError = 0;
8743c2c66affSColin Finck     es.pfnCallback = test_EM_STREAMIN_esCallback;
8744c2c66affSColin Finck     result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
8745c2c66affSColin Finck     ok( result == 11, "got %ld\n", result );
8746c2c66affSColin Finck 
874776cf09cfSAmine Khaldi     result = SendMessageW( edit, WM_GETTEXT, ARRAY_SIZE(buf), (LPARAM)buf );
874876cf09cfSAmine Khaldi     ok( result == ARRAY_SIZE(expect_specials), "got %ld\n", result );
8749c2c66affSColin Finck     ok( !memcmp( buf, expect_specials, sizeof(expect_specials) ), "got %s\n", wine_dbgstr_w(buf) );
8750c2c66affSColin Finck 
8751c2c66affSColin Finck     /* Show that \rtlpar propagates to the second paragraph and is
8752c2c66affSColin Finck        reset by \pard in the third. */
8753c2c66affSColin Finck     es.dwCookie = (DWORD_PTR)&pard;
8754c2c66affSColin Finck     result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
8755c2c66affSColin Finck     ok( result == 11, "got %ld\n", result );
8756c2c66affSColin Finck 
8757c2c66affSColin Finck     fmt.cbSize = sizeof(fmt);
8758c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 1, 1 );
8759c2c66affSColin Finck     SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8760c2c66affSColin Finck     ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" );
8761c2c66affSColin Finck     ok( fmt.wEffects & PFE_RTLPARA, "rtl para not set\n" );
8762c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 5, 5 );
8763c2c66affSColin Finck     SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8764c2c66affSColin Finck     ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" );
8765c2c66affSColin Finck     ok( fmt.wEffects & PFE_RTLPARA, "rtl para not set\n" );
8766c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 9, 9 );
8767c2c66affSColin Finck     SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8768c2c66affSColin Finck     ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" );
8769c2c66affSColin Finck     ok( !(fmt.wEffects & PFE_RTLPARA), "rtl para set\n" );
8770c2c66affSColin Finck 
8771c2c66affSColin Finck     /* Test \highlight */
8772c2c66affSColin Finck     es.dwCookie = (DWORD_PTR)&highlight;
8773c2c66affSColin Finck     result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
8774c2c66affSColin Finck     ok( result == 3, "got %ld\n", result );
8775c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 1, 1 );
8776c2c66affSColin Finck     memset( &cf, 0, sizeof(cf) );
8777c2c66affSColin Finck     cf.cbSize = sizeof(cf);
8778c2c66affSColin Finck     SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
8779c2c66affSColin Finck     ok( (cf.dwEffects & (CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR)) == 0, "got %08x\n", cf.dwEffects );
8780c2c66affSColin Finck     ok( cf.crTextColor == RGB(128,128,128), "got %08x\n", cf.crTextColor );
8781c2c66affSColin Finck     ok( cf.crBackColor == RGB(192,192,192), "got %08x\n", cf.crBackColor );
8782c2c66affSColin Finck 
8783c2c66affSColin Finck     DestroyWindow( edit );
8784c2c66affSColin Finck }
8785c2c66affSColin Finck 
test_background(void)8786c2c66affSColin Finck static void test_background(void)
8787c2c66affSColin Finck {
8788c2c66affSColin Finck     HWND hwndRichEdit = new_richedit(NULL);
8789c2c66affSColin Finck 
8790c2c66affSColin Finck     /* set the background color to black */
8791c2c66affSColin Finck     ValidateRect(hwndRichEdit, NULL);
8792c2c66affSColin Finck     SendMessageA(hwndRichEdit, EM_SETBKGNDCOLOR, FALSE, RGB(0, 0, 0));
8793c2c66affSColin Finck     ok(GetUpdateRect(hwndRichEdit, NULL, FALSE), "Update rectangle is empty!\n");
8794c2c66affSColin Finck 
8795c2c66affSColin Finck     DestroyWindow(hwndRichEdit);
8796c2c66affSColin Finck }
8797c2c66affSColin Finck 
test_eop_char_fmt(void)8798c2c66affSColin Finck static void test_eop_char_fmt(void)
8799c2c66affSColin Finck {
8800c2c66affSColin Finck     HWND edit = new_richedit( NULL );
8801c2c66affSColin Finck     const char *rtf = "{\\rtf1{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Arial;}{\\f1\\fnil\\fcharset2 Symbol;}}"
8802c2c66affSColin Finck         "{\\fs10{\\pard\\fs16\\fi200\\li360\\f0 First\\par"
8803c2c66affSColin Finck         "\\f0\\fs25 Second\\par"
8804c2c66affSColin Finck         "{\\f0\\fs26 Third}\\par"
8805c2c66affSColin Finck         "{\\f0\\fs22 Fourth}\\par}}}";
8806c2c66affSColin Finck     EDITSTREAM es;
8807c2c66affSColin Finck     CHARFORMAT2W cf;
8808c2c66affSColin Finck     int i, num, expect_height;
8809c2c66affSColin Finck 
8810c2c66affSColin Finck     es.dwCookie = (DWORD_PTR)&rtf;
8811c2c66affSColin Finck     es.dwError = 0;
8812c2c66affSColin Finck     es.pfnCallback = test_EM_STREAMIN_esCallback;
8813c2c66affSColin Finck     num = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
8814c2c66affSColin Finck     ok( num == 25, "got %d\n", num );
8815c2c66affSColin Finck 
8816c2c66affSColin Finck     for (i = 0; i <= num; i++)
8817c2c66affSColin Finck     {
8818c2c66affSColin Finck         SendMessageW( edit, EM_SETSEL, i, i + 1 );
8819c2c66affSColin Finck         cf.cbSize = sizeof(cf);
8820c2c66affSColin Finck         cf.dwMask = CFM_SIZE;
8821c2c66affSColin Finck         SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
8822c2c66affSColin Finck         ok( cf.dwMask & CFM_SIZE, "%d: got %08x\n", i, cf.dwMask );
8823c2c66affSColin Finck         if (i < 6) expect_height = 160;
8824c2c66affSColin Finck         else if (i < 13) expect_height = 250;
8825c2c66affSColin Finck         else if (i < 18) expect_height = 260;
8826c2c66affSColin Finck         else if (i == 18 || i == 25) expect_height = 250;
8827c2c66affSColin Finck         else expect_height = 220;
8828c2c66affSColin Finck         ok( cf.yHeight == expect_height, "%d: got %d\n", i, cf.yHeight );
8829c2c66affSColin Finck     }
8830c2c66affSColin Finck 
8831c2c66affSColin Finck     DestroyWindow( edit );
8832c2c66affSColin Finck }
8833c2c66affSColin Finck 
test_para_numbering(void)8834c2c66affSColin Finck static void test_para_numbering(void)
8835c2c66affSColin Finck {
8836c2c66affSColin Finck     HWND edit = new_richeditW( NULL );
8837c2c66affSColin Finck     const char *numbers = "{\\rtf1{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Arial;}{\\f1\\fnil\\fcharset2 Symbol;}}"
8838c2c66affSColin Finck         "\\pard{\\pntext\\f0 3.\\tab}{\\*\\pn\\pnlvlbody\\pnfs32\\pnf0\\pnindent1000\\pnstart2\\pndec{\\pntxta.}}"
8839c2c66affSColin Finck         "\\fs20\\fi200\\li360\\f0 First\\par"
8840c2c66affSColin Finck         "{\\pntext\\f0 4.\\tab}\\f0 Second\\par"
8841c2c66affSColin Finck         "{\\pntext\\f0 6.\\tab}\\f0 Third\\par}";
8842c2c66affSColin Finck     const WCHAR expect_numbers_txt[] = {'F','i','r','s','t','\r','S','e','c','o','n','d','\r','T','h','i','r','d',0};
8843c2c66affSColin Finck     EDITSTREAM es;
8844c2c66affSColin Finck     WCHAR buf[80];
8845c2c66affSColin Finck     LRESULT result;
8846c2c66affSColin Finck     PARAFORMAT2 fmt, fmt2;
8847c2c66affSColin Finck     GETTEXTEX get_text;
8848c2c66affSColin Finck     CHARFORMAT2W cf;
8849c2c66affSColin Finck 
8850c2c66affSColin Finck     get_text.cb = sizeof(buf);
8851c2c66affSColin Finck     get_text.flags = GT_RAWTEXT;
8852c2c66affSColin Finck     get_text.codepage = 1200;
8853c2c66affSColin Finck     get_text.lpDefaultChar = NULL;
8854c2c66affSColin Finck     get_text.lpUsedDefChar = NULL;
8855c2c66affSColin Finck 
8856c2c66affSColin Finck     es.dwCookie = (DWORD_PTR)&numbers;
8857c2c66affSColin Finck     es.dwError = 0;
8858c2c66affSColin Finck     es.pfnCallback = test_EM_STREAMIN_esCallback;
8859c2c66affSColin Finck     result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
8860c2c66affSColin Finck     ok( result == lstrlenW( expect_numbers_txt ), "got %ld\n", result );
8861c2c66affSColin Finck 
8862c2c66affSColin Finck     result = SendMessageW( edit, EM_GETTEXTEX, (WPARAM)&get_text, (LPARAM)buf );
8863c2c66affSColin Finck     ok( result == lstrlenW( expect_numbers_txt ), "got %ld\n", result );
8864c2c66affSColin Finck     ok( !lstrcmpW( buf, expect_numbers_txt ), "got %s\n", wine_dbgstr_w(buf) );
8865c2c66affSColin Finck 
8866c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 1, 1 );
8867c2c66affSColin Finck     memset( &fmt, 0, sizeof(fmt) );
8868c2c66affSColin Finck     fmt.cbSize = sizeof(fmt);
8869c2c66affSColin Finck     fmt.dwMask = PFM_ALL2;
8870c2c66affSColin Finck     SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
8871c2c66affSColin Finck     ok( fmt.wNumbering == PFN_ARABIC, "got %d\n", fmt.wNumbering );
8872c2c66affSColin Finck     ok( fmt.wNumberingStart == 2, "got %d\n", fmt.wNumberingStart );
8873c2c66affSColin Finck     ok( fmt.wNumberingStyle == PFNS_PERIOD, "got %04x\n", fmt.wNumberingStyle );
8874c2c66affSColin Finck     ok( fmt.wNumberingTab == 1000, "got %d\n", fmt.wNumberingTab );
8875c2c66affSColin Finck     ok( fmt.dxStartIndent == 560, "got %d\n", fmt.dxStartIndent );
8876c2c66affSColin Finck     ok( fmt.dxOffset == -200, "got %d\n", fmt.dxOffset );
8877c2c66affSColin Finck 
8878c2c66affSColin Finck     /* Second para should have identical fmt */
8879c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 10, 10 );
8880c2c66affSColin Finck     memset( &fmt2, 0, sizeof(fmt2) );
8881c2c66affSColin Finck     fmt2.cbSize = sizeof(fmt2);
8882c2c66affSColin Finck     fmt2.dwMask = PFM_ALL2;
8883c2c66affSColin Finck     SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt2 );
8884c2c66affSColin Finck     ok( !memcmp( &fmt, &fmt2, sizeof(fmt) ), "format mismatch\n" );
8885c2c66affSColin Finck 
8886c2c66affSColin Finck     /* Check the eop heights - this determines the label height */
8887c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 12, 13 );
8888c2c66affSColin Finck     cf.cbSize = sizeof(cf);
8889c2c66affSColin Finck     cf.dwMask = CFM_SIZE;
8890c2c66affSColin Finck     SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
8891c2c66affSColin Finck     ok( cf.yHeight == 200, "got %d\n", cf.yHeight );
8892c2c66affSColin Finck 
8893c2c66affSColin Finck     SendMessageW( edit, EM_SETSEL, 18, 19 );
8894c2c66affSColin Finck     cf.cbSize = sizeof(cf);
8895c2c66affSColin Finck     cf.dwMask = CFM_SIZE;
8896c2c66affSColin Finck     SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
8897c2c66affSColin Finck     ok( cf.yHeight == 200, "got %d\n", cf.yHeight );
8898c2c66affSColin Finck 
8899c2c66affSColin Finck     DestroyWindow( edit );
8900c2c66affSColin Finck }
8901c2c66affSColin Finck 
fill_reobject_struct(REOBJECT * reobj,LONG cp,LPOLEOBJECT poleobj,LPSTORAGE pstg,LPOLECLIENTSITE polesite,LONG sizel_cx,LONG sizel_cy,DWORD aspect,DWORD flags,DWORD user)89029e90c368SAmine Khaldi static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
89039e90c368SAmine Khaldi                                  LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
89049e90c368SAmine Khaldi                                  LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
89059e90c368SAmine Khaldi {
89069e90c368SAmine Khaldi     reobj->cbStruct = sizeof(*reobj);
89079e90c368SAmine Khaldi     reobj->clsid = CLSID_NULL;
89089e90c368SAmine Khaldi     reobj->cp = cp;
89099e90c368SAmine Khaldi     reobj->poleobj = poleobj;
89109e90c368SAmine Khaldi     reobj->pstg = pstg;
89119e90c368SAmine Khaldi     reobj->polesite = polesite;
89129e90c368SAmine Khaldi     reobj->sizel.cx = sizel_cx;
89139e90c368SAmine Khaldi     reobj->sizel.cy = sizel_cy;
89149e90c368SAmine Khaldi     reobj->dvaspect = aspect;
89159e90c368SAmine Khaldi     reobj->dwFlags = flags;
89169e90c368SAmine Khaldi     reobj->dwUser = user;
89179e90c368SAmine Khaldi }
89189e90c368SAmine Khaldi 
test_EM_SELECTIONTYPE(void)89199e90c368SAmine Khaldi static void test_EM_SELECTIONTYPE(void)
89209e90c368SAmine Khaldi {
89219e90c368SAmine Khaldi     HWND hwnd = new_richedit(NULL);
89229e90c368SAmine Khaldi     IRichEditOle *reole = NULL;
89239e90c368SAmine Khaldi     static const char text1[] = "abcdefg\n";
89249e90c368SAmine Khaldi     int result;
89259e90c368SAmine Khaldi     REOBJECT reo1, reo2;
89269e90c368SAmine Khaldi     IOleClientSite *clientsite;
89279e90c368SAmine Khaldi     HRESULT hr;
89289e90c368SAmine Khaldi 
89299e90c368SAmine Khaldi     SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text1);
89309e90c368SAmine Khaldi     SendMessageA(hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&reole);
89319e90c368SAmine Khaldi 
89329e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 1, 1);
89339e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89349e90c368SAmine Khaldi     ok(result == SEL_EMPTY, "got wrong selection type: %x.\n", result);
89359e90c368SAmine Khaldi 
89369e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 1, 2);
89379e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89389e90c368SAmine Khaldi     ok(result == SEL_TEXT, "got wrong selection type: %x.\n", result);
89399e90c368SAmine Khaldi 
89409e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 2, 5);
89419e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89429e90c368SAmine Khaldi     ok(result == (SEL_TEXT | SEL_MULTICHAR), "got wrong selection type: %x.\n", result);
89439e90c368SAmine Khaldi 
89449e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 1);
89459e90c368SAmine Khaldi     hr = IRichEditOle_GetClientSite(reole, &clientsite);
89469e90c368SAmine Khaldi     ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
89479e90c368SAmine Khaldi     fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10,
89489e90c368SAmine Khaldi                          DVASPECT_CONTENT, 0, 1);
89499e90c368SAmine Khaldi     hr = IRichEditOle_InsertObject(reole, &reo1);
89509e90c368SAmine Khaldi     ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
89519e90c368SAmine Khaldi     IOleClientSite_Release(clientsite);
89529e90c368SAmine Khaldi 
89539e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 1);
89549e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89559e90c368SAmine Khaldi     ok(result == SEL_OBJECT, "got wrong selection type: %x.\n", result);
89569e90c368SAmine Khaldi 
89579e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 2);
89589e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89599e90c368SAmine Khaldi     ok(result == (SEL_TEXT | SEL_OBJECT), "got wrong selection type: %x.\n", result);
89609e90c368SAmine Khaldi 
89619e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 3);
89629e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89639e90c368SAmine Khaldi     ok(result == (SEL_TEXT | SEL_MULTICHAR | SEL_OBJECT), "got wrong selection type: %x.\n", result);
89649e90c368SAmine Khaldi 
89659e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 2, 3);
89669e90c368SAmine Khaldi     hr = IRichEditOle_GetClientSite(reole, &clientsite);
89679e90c368SAmine Khaldi     ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
89689e90c368SAmine Khaldi     fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10,
89699e90c368SAmine Khaldi                          DVASPECT_CONTENT, 0, 2);
89709e90c368SAmine Khaldi     hr = IRichEditOle_InsertObject(reole, &reo2);
89719e90c368SAmine Khaldi     ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
89729e90c368SAmine Khaldi     IOleClientSite_Release(clientsite);
89739e90c368SAmine Khaldi 
89749e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 2);
89759e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89769e90c368SAmine Khaldi     ok(result == (SEL_OBJECT | SEL_TEXT), "got wrong selection type: %x.\n", result);
89779e90c368SAmine Khaldi 
89789e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 3);
89799e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89809e90c368SAmine Khaldi     ok(result == (SEL_OBJECT | SEL_MULTIOBJECT | SEL_TEXT), "got wrong selection type: %x.\n", result);
89819e90c368SAmine Khaldi 
89829e90c368SAmine Khaldi     SendMessageA(hwnd, EM_SETSEL, 0, 4);
89839e90c368SAmine Khaldi     result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
89849e90c368SAmine Khaldi     ok(result == (SEL_TEXT| SEL_MULTICHAR | SEL_OBJECT | SEL_MULTIOBJECT), "got wrong selection type: %x.\n", result);
89859e90c368SAmine Khaldi 
89869e90c368SAmine Khaldi     IRichEditOle_Release(reole);
89879e90c368SAmine Khaldi     DestroyWindow(hwnd);
89889e90c368SAmine Khaldi }
89899e90c368SAmine Khaldi 
test_window_classes(void)899034838171SAmine Khaldi static void test_window_classes(void)
899134838171SAmine Khaldi {
899234838171SAmine Khaldi     static const struct
899334838171SAmine Khaldi     {
899434838171SAmine Khaldi         const char *class;
899534838171SAmine Khaldi         BOOL success;
899634838171SAmine Khaldi     } test[] =
899734838171SAmine Khaldi     {
899834838171SAmine Khaldi         { "RichEdit", FALSE },
899934838171SAmine Khaldi         { "RichEdit20A", TRUE },
900034838171SAmine Khaldi         { "RichEdit20W", TRUE },
900134838171SAmine Khaldi         { "RichEdit50A", FALSE },
900234838171SAmine Khaldi         { "RichEdit50W", FALSE }
900334838171SAmine Khaldi     };
900434838171SAmine Khaldi     int i;
900534838171SAmine Khaldi     HWND hwnd;
900634838171SAmine Khaldi 
900734838171SAmine Khaldi     for (i = 0; i < sizeof(test)/sizeof(test[0]); i++)
900834838171SAmine Khaldi     {
900934838171SAmine Khaldi         SetLastError(0xdeadbeef);
901034838171SAmine Khaldi         hwnd = CreateWindowExA(0, test[i].class, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL);
901134838171SAmine Khaldi todo_wine_if(!strcmp(test[i].class, "RichEdit50A") || !strcmp(test[i].class, "RichEdit50W"))
901234838171SAmine Khaldi         ok(!hwnd == !test[i].success, "CreateWindow(%s) should %s\n",
901334838171SAmine Khaldi            test[i].class, test[i].success ? "succeed" : "fail");
901434838171SAmine Khaldi         if (!hwnd)
901534838171SAmine Khaldi todo_wine
901634838171SAmine Khaldi             ok(GetLastError() == ERROR_CANNOT_FIND_WND_CLASS, "got %d\n", GetLastError());
901734838171SAmine Khaldi         else
901834838171SAmine Khaldi             DestroyWindow(hwnd);
901934838171SAmine Khaldi     }
902034838171SAmine Khaldi }
902134838171SAmine Khaldi 
START_TEST(editor)9022c2c66affSColin Finck START_TEST( editor )
9023c2c66affSColin Finck {
9024c2c66affSColin Finck   BOOL ret;
9025c2c66affSColin Finck   /* Must explicitly LoadLibrary(). The test has no references to functions in
9026c2c66affSColin Finck    * RICHED20.DLL, so the linker doesn't actually link to it. */
9027c2c66affSColin Finck   hmoduleRichEdit = LoadLibraryA("riched20.dll");
9028c2c66affSColin Finck   ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
9029c2c66affSColin Finck   is_lang_japanese = (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE);
9030c2c66affSColin Finck 
903134838171SAmine Khaldi   test_window_classes();
9032c2c66affSColin Finck   test_WM_CHAR();
9033c2c66affSColin Finck   test_EM_FINDTEXT(FALSE);
9034c2c66affSColin Finck   test_EM_FINDTEXT(TRUE);
9035c2c66affSColin Finck   test_EM_GETLINE();
9036c2c66affSColin Finck   test_EM_POSFROMCHAR();
9037c2c66affSColin Finck   test_EM_SCROLLCARET();
9038c2c66affSColin Finck   test_EM_SCROLL();
9039c2c66affSColin Finck   test_scrollbar_visibility();
9040c2c66affSColin Finck   test_WM_SETTEXT();
9041c2c66affSColin Finck   test_EM_LINELENGTH();
9042c2c66affSColin Finck   test_EM_SETCHARFORMAT();
9043c2c66affSColin Finck   test_EM_SETTEXTMODE();
9044c2c66affSColin Finck   test_TM_PLAINTEXT();
9045c2c66affSColin Finck   test_EM_SETOPTIONS();
9046c2c66affSColin Finck   test_WM_GETTEXT();
9047c2c66affSColin Finck   test_EM_GETTEXTRANGE();
9048c2c66affSColin Finck   test_EM_GETSELTEXT();
9049c2c66affSColin Finck   test_EM_SETUNDOLIMIT();
9050c2c66affSColin Finck   test_ES_PASSWORD();
9051c2c66affSColin Finck   test_EM_SETTEXTEX();
9052c2c66affSColin Finck   test_EM_LIMITTEXT();
9053c2c66affSColin Finck   test_EM_EXLIMITTEXT();
9054c2c66affSColin Finck   test_EM_GETLIMITTEXT();
9055c2c66affSColin Finck   test_WM_SETFONT();
9056c2c66affSColin Finck   test_EM_GETMODIFY();
9057c2c66affSColin Finck   test_EM_SETSEL();
9058c2c66affSColin Finck   test_EM_EXSETSEL();
9059c2c66affSColin Finck   test_WM_PASTE();
9060c2c66affSColin Finck   test_EM_STREAMIN();
9061c2c66affSColin Finck   test_EM_STREAMOUT();
9062c2c66affSColin Finck   test_EM_STREAMOUT_FONTTBL();
9063c2c66affSColin Finck   test_EM_STREAMOUT_empty_para();
9064c2c66affSColin Finck   test_EM_StreamIn_Undo();
9065c2c66affSColin Finck   test_EM_FORMATRANGE();
9066c2c66affSColin Finck   test_unicode_conversions();
9067c2c66affSColin Finck   test_EM_GETTEXTLENGTHEX();
9068c2c66affSColin Finck   test_WM_GETTEXTLENGTH();
9069c2c66affSColin Finck   test_EM_REPLACESEL(1);
9070c2c66affSColin Finck   test_EM_REPLACESEL(0);
9071c2c66affSColin Finck   test_WM_NOTIFY();
9072c2c66affSColin Finck   test_EN_LINK();
9073c2c66affSColin Finck   test_EM_AUTOURLDETECT();
9074c2c66affSColin Finck   test_eventMask();
9075c2c66affSColin Finck   test_undo_coalescing();
9076c2c66affSColin Finck   test_word_movement();
9077c2c66affSColin Finck   test_EM_CHARFROMPOS();
9078c2c66affSColin Finck   test_SETPARAFORMAT();
9079c2c66affSColin Finck   test_word_wrap();
9080c2c66affSColin Finck   test_autoscroll();
9081c2c66affSColin Finck   test_format_rect();
9082c2c66affSColin Finck   test_WM_GETDLGCODE();
9083c2c66affSColin Finck   test_zoom();
9084c2c66affSColin Finck   test_dialogmode();
9085c2c66affSColin Finck   test_EM_FINDWORDBREAK_W();
9086c2c66affSColin Finck   test_EM_FINDWORDBREAK_A();
9087c2c66affSColin Finck   test_enter();
9088c2c66affSColin Finck   test_WM_CREATE();
9089c2c66affSColin Finck   test_reset_default_para_fmt();
9090c2c66affSColin Finck   test_EM_SETREADONLY();
9091c2c66affSColin Finck   test_EM_SETFONTSIZE();
9092c2c66affSColin Finck   test_alignment_style();
9093c2c66affSColin Finck   test_rtf();
9094c2c66affSColin Finck   test_background();
9095c2c66affSColin Finck   test_eop_char_fmt();
9096c2c66affSColin Finck   test_para_numbering();
90979e90c368SAmine Khaldi   test_EM_SELECTIONTYPE();
9098c2c66affSColin Finck 
9099c2c66affSColin Finck   /* Set the environment variable WINETEST_RICHED20 to keep windows
9100c2c66affSColin Finck    * responsive and open for 30 seconds. This is useful for debugging.
9101c2c66affSColin Finck    */
9102c2c66affSColin Finck   if (getenv( "WINETEST_RICHED20" )) {
9103c2c66affSColin Finck     keep_responsive(30);
9104c2c66affSColin Finck   }
9105c2c66affSColin Finck 
9106c2c66affSColin Finck   OleFlushClipboard();
9107c2c66affSColin Finck   ret = FreeLibrary(hmoduleRichEdit);
9108c2c66affSColin Finck   ok(ret, "error: %d\n", (int) GetLastError());
9109c2c66affSColin Finck }
9110