riched20: Implement EM_SCROLLCARET and EM_GETSCROLLPOS.
[wine/dcerpc.git] / dlls / riched20 / tests / editor.c
blob908bb90ffd25d0306c1ac8d06fc2ebd2dd163341
1 /*
2 * Unit test suite for rich edit control
4 * Copyright 2006 Google (Thomas Kho)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <wine/test.h>
22 #include <windows.h>
23 #include <richedit.h>
24 #include <time.h>
26 static HMODULE hmoduleRichEdit;
28 static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
29 HWND hwnd;
30 hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
31 |WS_VISIBLE, 0, 0, 200, 60, parent, NULL,
32 hmoduleRichEdit, NULL);
33 ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
34 return hwnd;
37 static HWND new_richedit(HWND parent) {
38 return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent);
41 static const char haystack[] = "WINEWine wineWine wine WineWine";
42 /* ^0 ^10 ^20 ^30 */
44 struct find_s {
45 int start;
46 int end;
47 char *needle;
48 int flags;
49 int expected_loc;
50 int _todo_wine;
53 struct find_s find_tests[] = {
54 /* Find in empty text */
55 {0, -1, "foo", FR_DOWN, -1, 0},
56 {0, -1, "foo", 0, -1, 0},
57 {0, -1, "", FR_DOWN, -1, 0},
58 {20, 5, "foo", FR_DOWN, -1, 0},
59 {5, 20, "foo", FR_DOWN, -1, 0}
62 struct find_s find_tests2[] = {
63 /* No-result find */
64 {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1, 0},
65 {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1, 0},
67 /* Subsequent finds */
68 {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4, 0},
69 {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13, 0},
70 {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
71 {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
73 /* Find backwards */
74 {19, 20, "Wine", FR_MATCHCASE, 13, 1},
75 {10, 20, "Wine", FR_MATCHCASE, 4, 1},
76 {20, 10, "Wine", FR_MATCHCASE, 13, 0},
78 /* Case-insensitive */
79 {1, 31, "wInE", FR_DOWN, 4, 1},
80 {1, 31, "Wine", FR_DOWN, 4, 0},
82 /* High-to-low ranges */
83 {20, 5, "Wine", FR_DOWN, -1, 1},
84 {2, 1, "Wine", FR_DOWN, -1, 0},
85 {30, 29, "Wine", FR_DOWN, -1, 0},
86 {20, 5, "Wine", 0, 13, 0},
88 /* Find nothing */
89 {5, 10, "", FR_DOWN, -1, 0},
90 {10, 5, "", FR_DOWN, -1, 0},
91 {0, -1, "", FR_DOWN, -1, 0},
92 {10, 5, "", 0, -1, 0},
94 /* Whole-word search */
95 {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 1},
96 {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1, 1},
98 /* Bad ranges */
99 {-20, 20, "Wine", FR_DOWN, -1, 0},
100 {-20, 20, "Wine", FR_DOWN, -1, 0},
101 {-15, -20, "Wine", FR_DOWN, -1, 0},
102 {1<<12, 1<<13, "Wine", FR_DOWN, -1, 0},
104 /* Check the case noted in bug 4479 where matches at end aren't recognized */
105 {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
106 {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
107 {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
108 {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
109 {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
111 /* The backwards case of bug 4479; bounds look right
112 * Fails because backward find is wrong */
113 {19, 20, "WINE", FR_MATCHCASE, 0, 1},
114 {0, 20, "WINE", FR_MATCHCASE, -1, 1}
117 static void check_EM_FINDTEXT(HWND hwnd, char *name, struct find_s *f, int id) {
118 int findloc;
119 FINDTEXT ft;
120 memset(&ft, 0, sizeof(ft));
121 ft.chrg.cpMin = f->start;
122 ft.chrg.cpMax = f->end;
123 ft.lpstrText = f->needle;
124 findloc = SendMessage(hwnd, EM_FINDTEXT, f->flags, (LPARAM) &ft);
125 ok(findloc == f->expected_loc,
126 "EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d\n",
127 name, id, f->needle, f->start, f->end, f->flags, findloc);
130 static void check_EM_FINDTEXTEX(HWND hwnd, char *name, struct find_s *f,
131 int id) {
132 int findloc;
133 FINDTEXTEX ft;
134 memset(&ft, 0, sizeof(ft));
135 ft.chrg.cpMin = f->start;
136 ft.chrg.cpMax = f->end;
137 ft.lpstrText = f->needle;
138 findloc = SendMessage(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM) &ft);
139 ok(findloc == f->expected_loc,
140 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
141 name, id, f->needle, f->start, f->end, f->flags, findloc);
142 ok(ft.chrgText.cpMin == f->expected_loc,
143 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %ld\n",
144 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin);
145 ok(ft.chrgText.cpMax == ((f->expected_loc == -1) ? -1
146 : f->expected_loc + strlen(f->needle)),
147 "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %ld\n",
148 name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax);
151 static void run_tests_EM_FINDTEXT(HWND hwnd, char *name, struct find_s *find,
152 int num_tests)
154 int i;
156 for (i = 0; i < num_tests; i++) {
157 if (find[i]._todo_wine) {
158 todo_wine {
159 check_EM_FINDTEXT(hwnd, name, &find[i], i);
160 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
162 } else {
163 check_EM_FINDTEXT(hwnd, name, &find[i], i);
164 check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
169 static void test_EM_FINDTEXT(void)
171 HWND hwndRichEdit = new_richedit(NULL);
173 /* Empty rich edit control */
174 run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests,
175 sizeof(find_tests)/sizeof(struct find_s));
177 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
179 /* Haystack text */
180 run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2,
181 sizeof(find_tests2)/sizeof(struct find_s));
183 DestroyWindow(hwndRichEdit);
186 static int get_scroll_pos_y(HWND hwnd)
188 POINT p = {-1, -1};
189 SendMessage(hwnd, EM_GETSCROLLPOS, 0, (LPARAM) &p);
190 ok(p.x != -1 && p.y != -1, "p.x:%ld p.y:%ld\n", p.x, p.y);
191 return p.y;
194 static void move_cursor(HWND hwnd, long charindex)
196 CHARRANGE cr;
197 cr.cpMax = charindex;
198 cr.cpMin = charindex;
199 SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) &cr);
202 static void line_scroll(HWND hwnd, int amount)
204 SendMessage(hwnd, EM_LINESCROLL, 0, amount);
207 static void test_EM_SCROLLCARET(void)
209 int prevY, curY;
210 HWND hwndRichEdit = new_richedit(NULL);
211 const char text[] = "aa\n"
212 "this is a long line of text that should be longer than the "
213 "control's width\n"
214 "cc\n"
215 "dd\n"
216 "ee\n"
217 "ff\n"
218 "gg\n"
219 "hh\n";
221 /* Can't verify this */
222 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
224 SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
226 /* Caret above visible window */
227 line_scroll(hwndRichEdit, 3);
228 prevY = get_scroll_pos_y(hwndRichEdit);
229 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
230 curY = get_scroll_pos_y(hwndRichEdit);
231 ok(prevY != curY, "%d == %d\n", prevY, curY);
233 /* Caret below visible window */
234 move_cursor(hwndRichEdit, sizeof(text) - 1);
235 line_scroll(hwndRichEdit, -3);
236 prevY = get_scroll_pos_y(hwndRichEdit);
237 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
238 curY = get_scroll_pos_y(hwndRichEdit);
239 ok(prevY != curY, "%d == %d\n", prevY, curY);
241 /* Caret in visible window */
242 move_cursor(hwndRichEdit, sizeof(text) - 2);
243 prevY = get_scroll_pos_y(hwndRichEdit);
244 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
245 curY = get_scroll_pos_y(hwndRichEdit);
246 ok(prevY == curY, "%d != %d\n", prevY, curY);
248 /* Caret still in visible window */
249 line_scroll(hwndRichEdit, -1);
250 prevY = get_scroll_pos_y(hwndRichEdit);
251 SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
252 curY = get_scroll_pos_y(hwndRichEdit);
253 ok(prevY == curY, "%d != %d\n", prevY, curY);
255 DestroyWindow(hwndRichEdit);
258 START_TEST( editor )
260 MSG msg;
261 time_t end;
263 /* Must explicitly LoadLibrary(). The test has no references to functions in
264 * RICHED20.DLL, so the linker doesn't actually link to it. */
265 hmoduleRichEdit = LoadLibrary("RICHED20.DLL");
266 ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
268 test_EM_FINDTEXT();
269 test_EM_SCROLLCARET();
271 /* Set the environment variable WINETEST_RICHED20 to keep windows
272 * responsive and open for 30 seconds. This is useful for debugging.
274 * The message pump uses PeekMessage() to empty the queue and then sleeps for
275 * 50ms before retrying the queue. */
276 end = time(NULL) + 30;
277 if (getenv( "WINETEST_RICHED20" )) {
278 while (time(NULL) < end) {
279 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
280 TranslateMessage(&msg);
281 DispatchMessage(&msg);
282 } else {
283 Sleep(50);
288 ok(FreeLibrary(hmoduleRichEdit) != 0, "error: %d\n", (int) GetLastError());