riched20: Added tests for EM_FINDTEXT and EM_FINDTEXTEX messages.
[wine] / dlls / riched20 / tests / editor.c
1 /*
2 * Unit test suite for rich edit control
3 *
4 * Copyright 2006 Google (Thomas Kho)
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <wine/test.h>
22 #include <windows.h>
23 #include <richedit.h>
24 #include <time.h>
25
26 static HMODULE hmoduleRichEdit;
27 static const char haystack[] = "Think of Wine as a compatibility layer for "
28   "running Windows programs. Wine does not require Microsoft Windows, as it "
29   "is a completely free alternative implementation of the Windows API "
30   "consisting of 100% non-Microsoft code, however Wine can optionally use "
31   "native Windows DLLs if they are available. Wine provides both a "
32   "development toolkit for porting Windows source code to Unix as well as a "
33   "program loader, allowing many unmodified Windows programs to run on "
34   "x86-based Unixes, including Linux, FreeBSD, and Solaris.";
35
36 static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
37   HWND hwnd;
38   hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
39                       |WS_VISIBLE, 0, 0, 200, 50, parent, NULL,
40                       hmoduleRichEdit, NULL);
41   ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
42   return hwnd;
43 }
44
45 static HWND new_richedit(HWND parent) {
46   return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent);
47 }
48
49 static void check_EM_FINDTEXT(HWND hwnd, int start, int end, char needle[],
50                               int flags, int expected_start) {
51   int findloc;
52   FINDTEXT ft;
53   memset(&ft, 0, sizeof(ft));
54   ft.chrg.cpMin = start;
55   ft.chrg.cpMax = end;
56   ft.lpstrText = needle;
57   findloc = SendMessage(hwnd, EM_FINDTEXT, flags, (LPARAM) &ft);
58   ok(findloc == expected_start,
59      "EM_FINDTEXT '%s' in range (%d,%d), flags %08x, got start at %d\n",
60      needle, start, end, flags, findloc);
61 }
62
63 static void test_EM_FINDTEXT(void)
64 {
65   CHARRANGE cr;
66   GETTEXTLENGTHEX gtl;
67   int size;
68
69   HWND hwndRichEdit = new_richedit(NULL);
70
71   SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
72   SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
73   ok(cr.cpMin == cr.cpMax, "(%ld,%ld)\n", cr.cpMin, cr.cpMax);
74
75   gtl.flags = GTL_NUMCHARS;
76   gtl.codepage = CP_ACP;
77   size = SendMessage(hwndRichEdit, EM_GETTEXTLENGTHEX, (WPARAM) &gtl, 0);
78   ok(size == sizeof(haystack) - 1, "size=%d, sizeof haystack=%d\n",
79      size, sizeof(haystack)); /* sizeof counts '\0' */
80
81   check_EM_FINDTEXT(hwndRichEdit, 0, size, "Wine", FR_DOWN | FR_MATCHCASE, 9);
82   check_EM_FINDTEXT(hwndRichEdit, 10, size, "Wine", FR_DOWN | FR_MATCHCASE, 69);
83   check_EM_FINDTEXT(hwndRichEdit, 298, size, "Wine", FR_DOWN | FR_MATCHCASE,
84                     -1);
85   check_EM_FINDTEXT(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_MATCHCASE, -1);
86   todo_wine {
87     check_EM_FINDTEXT(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_WHOLEWORD, 9);
88     check_EM_FINDTEXT(hwndRichEdit, 0, size, "win", FR_DOWN | FR_WHOLEWORD, -1);
89   }
90
91   /* Check the case noted in bug 4479 */
92   SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "blahblah");
93   check_EM_FINDTEXT(hwndRichEdit, 0, 8, "blah", FR_DOWN | FR_MATCHCASE, 0);
94   check_EM_FINDTEXT(hwndRichEdit, 4, 8, "blah", FR_DOWN | FR_MATCHCASE, 4);
95   check_EM_FINDTEXT(hwndRichEdit, 4, 9, "blah", FR_DOWN | FR_MATCHCASE, 4);
96   check_EM_FINDTEXT(hwndRichEdit, 0, 8, "blahblah", FR_DOWN | FR_MATCHCASE, 0);
97
98   DestroyWindow(hwndRichEdit);
99 }
100
101 static void check_EM_FINDTEXTEX(HWND hwnd, int start, int end, char needle[],
102                                 int flags, int expected_start,
103                                 int expected_end) {
104   int findloc;
105   FINDTEXTEX ft;
106   memset(&ft, 0, sizeof(ft));
107   ft.chrg.cpMin = start;
108   ft.chrg.cpMax = end;
109   ft.lpstrText = needle;
110   findloc = SendMessage(hwnd, EM_FINDTEXTEX, flags, (LPARAM) &ft);
111   ok(findloc == expected_start,
112      "EM_FINDTEXTEX '%s' in range (%d,%d), flags %08x, got start at %d\n",
113      needle, start, end, flags, findloc);
114   if(findloc != -1) {
115     ok(ft.chrgText.cpMin == expected_start,
116        "EM_FINDTEXTEX '%s' in range (%d,%d), flags %08x, got start at %ld\n",
117        needle, start, end, flags, ft.chrgText.cpMin);
118     ok(ft.chrgText.cpMax == expected_end,
119        "EM_FINDTEXTEX '%s' in range (%d,%d), flags %08x, got end at %ld\n",
120        needle, start, end, flags, ft.chrgText.cpMax);
121   }
122 }
123
124 static void test_EM_FINDTEXTEX(void)
125 {
126   CHARRANGE cr;
127   GETTEXTLENGTHEX gtl;
128   int size;
129
130   HWND hwndRichEdit = new_richedit(NULL);
131
132   SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
133   SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM) &cr);
134   ok(cr.cpMin == cr.cpMax, "(%ld,%ld)\n", cr.cpMin, cr.cpMax);
135
136   gtl.flags = GTL_NUMCHARS;
137   gtl.codepage = CP_ACP;
138   size = SendMessage(hwndRichEdit, EM_GETTEXTLENGTHEX, (WPARAM) &gtl, 0);
139   ok(size == sizeof(haystack) - 1, "size=%d, sizeof haystack=%d\n", size,
140      sizeof(haystack)); /* sizeof counts '\0' */
141
142   check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "Wine", FR_DOWN | FR_MATCHCASE,
143                       9, 13);
144   check_EM_FINDTEXTEX(hwndRichEdit, 10, size, "Wine", FR_DOWN | FR_MATCHCASE,
145                       69, 73);
146   check_EM_FINDTEXTEX(hwndRichEdit, 298, size, "Wine", FR_DOWN | FR_MATCHCASE,
147                       -1, -1);
148   check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_MATCHCASE,
149                       -1, -1);
150   todo_wine {
151     check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_WHOLEWORD,
152                         9, 13);
153     check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "win", FR_DOWN | FR_WHOLEWORD,
154                         -1, -1);
155   }
156
157   DestroyWindow(hwndRichEdit);
158 }
159
160 START_TEST( editor )
161 {
162   MSG msg;
163   time_t end;
164
165   /* Must explicitly LoadLibrary(). The test has no references to functions in
166    * RICHED20.DLL, so the linker doesn't actually link to it. */
167   hmoduleRichEdit = LoadLibrary("RICHED20.DLL");
168   ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
169
170   test_EM_FINDTEXT();
171   test_EM_FINDTEXTEX();
172
173   /* Set the environment variable WINETEST_RICHED20 to keep windows
174    * responsive and open for 30 seconds. This is useful for debugging.
175    *
176    * The message pump uses PeekMessage() to empty the queue and then sleeps for
177    * 50ms before retrying the queue. */
178   end = time(NULL) + 30;
179   if (getenv( "WINETEST_RICHED20" )) {
180     while (time(NULL) < end) {
181       if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
182         TranslateMessage(&msg);
183         DispatchMessage(&msg);
184       } else {
185         Sleep(50);
186       }
187     }
188   }
189
190   ok(FreeLibrary(hmoduleRichEdit) != 0, "error: %d\n", (int) GetLastError());
191 }