user32: Make the edit tests pass on Vista.
[wine] / dlls / user32 / tests / edit.c
1 /* Unit test suite for edit control.
2  *
3  * Copyright 2004 Vitaliy Margolen
4  * Copyright 2005 C. Scott Ananian
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <windows.h>
23 #include <commctrl.h>
24
25 #include "wine/test.h"
26
27 #ifndef ES_COMBO
28 #define ES_COMBO 0x200
29 #endif
30
31 #define ID_EDITTEST2 99
32 #define MAXLEN 200
33
34 struct edit_notify {
35     int en_change, en_maxtext, en_update;
36 };
37
38 static struct edit_notify notifications;
39
40 static HINSTANCE hinst;
41 static HWND hwndET2;
42 static const char szEditTest2Class[] = "EditTest2Class";
43 static const char szEditTest3Class[] = "EditTest3Class";
44 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
45
46 static HWND create_editcontrol (DWORD style, DWORD exstyle)
47 {
48     HWND handle;
49
50     handle = CreateWindowEx(exstyle,
51                           "EDIT",
52                           "Test Text",
53                           style,
54                           10, 10, 300, 300,
55                           NULL, NULL, hinst, NULL);
56     assert (handle);
57     if (winetest_interactive)
58         ShowWindow (handle, SW_SHOW);
59     return handle;
60 }
61
62 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
63 {
64     HWND parentWnd;
65     HWND editWnd;
66     RECT rect;
67     
68     rect.left = 0;
69     rect.top = 0;
70     rect.right = 300;
71     rect.bottom = 300;
72     assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
73     
74     parentWnd = CreateWindowEx(0,
75                             szEditTextPositionClass,
76                             "Edit Test",
77                             WS_OVERLAPPEDWINDOW,
78                             CW_USEDEFAULT, CW_USEDEFAULT,
79                             rect.right - rect.left, rect.bottom - rect.top,
80                             NULL, NULL, hinst, NULL);
81     assert(parentWnd);
82
83     editWnd = CreateWindowEx(exstyle,
84                             "EDIT",
85                             "Test Text",
86                             WS_CHILD | style,
87                             0, 0, 300, 300,
88                             parentWnd, NULL, hinst, NULL);
89     assert(editWnd);
90     if (winetest_interactive)
91         ShowWindow (parentWnd, SW_SHOW);
92     return editWnd;
93 }
94
95 static void destroy_child_editcontrol (HWND hwndEdit)
96 {
97     if (GetParent(hwndEdit))
98         DestroyWindow(GetParent(hwndEdit));
99     else {
100         trace("Edit control has no parent!\n");
101         DestroyWindow(hwndEdit);
102     }
103 }
104
105 static LONG get_edit_style (HWND hwnd)
106 {
107     return GetWindowLongA( hwnd, GWL_STYLE ) & (
108         ES_LEFT |
109 /* FIXME: not implemented
110         ES_CENTER |
111         ES_RIGHT |
112         ES_OEMCONVERT |
113 */
114         ES_MULTILINE |
115         ES_UPPERCASE |
116         ES_LOWERCASE |
117         ES_PASSWORD |
118         ES_AUTOVSCROLL |
119         ES_AUTOHSCROLL |
120         ES_NOHIDESEL |
121         ES_COMBO |
122         ES_READONLY |
123         ES_WANTRETURN |
124         ES_NUMBER
125         );
126 }
127
128 static void set_client_height(HWND Wnd, unsigned Height)
129 {
130     RECT ClientRect, WindowRect;
131
132     GetWindowRect(Wnd, &WindowRect);
133     GetClientRect(Wnd, &ClientRect);
134     SetWindowPos(Wnd, NULL, 0, 0,
135                  WindowRect.right - WindowRect.left,
136                  Height + (WindowRect.bottom - WindowRect.top) -
137                  (ClientRect.bottom - ClientRect.top),
138                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
139
140     /* Workaround for a bug in Windows' edit control
141        (multi-line mode) */
142     GetWindowRect(Wnd, &WindowRect);             
143     SetWindowPos(Wnd, NULL, 0, 0,
144                  WindowRect.right - WindowRect.left + 1,
145                  WindowRect.bottom - WindowRect.top + 1,
146                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
147     SetWindowPos(Wnd, NULL, 0, 0,
148                  WindowRect.right - WindowRect.left,
149                  WindowRect.bottom - WindowRect.top,
150                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
151
152     GetClientRect(Wnd, &ClientRect);
153     ok(ClientRect.bottom - ClientRect.top == Height,
154         "The client height should be %ld, but is %ld\n",
155         (long)Height, (long)(ClientRect.bottom - ClientRect.top));
156 }
157
158 static void test_edit_control_1(void)
159 {
160     HWND hwEdit;
161     MSG msMessage;
162     int i;
163     LONG r;
164
165     msMessage.message = WM_KEYDOWN;
166
167     trace("EDIT: Single line\n");
168     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
169     r = get_edit_style(hwEdit);
170     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
171     for (i=0;i<65535;i++)
172     {
173         msMessage.wParam = i;
174         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
175         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
176             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
177     }
178     DestroyWindow (hwEdit);
179
180     trace("EDIT: Single line want returns\n");
181     hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
182     r = get_edit_style(hwEdit);
183     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
184     for (i=0;i<65535;i++)
185     {
186         msMessage.wParam = i;
187         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
188         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
189             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
190     }
191     DestroyWindow (hwEdit);
192
193     trace("EDIT: Multiline line\n");
194     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
195     r = get_edit_style(hwEdit);
196     ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
197     for (i=0;i<65535;i++)
198     {
199         msMessage.wParam = i;
200         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
201         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
202             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
203     }
204     DestroyWindow (hwEdit);
205
206     trace("EDIT: Multi line want returns\n");
207     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
208     r = get_edit_style(hwEdit);
209     ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
210     for (i=0;i<65535;i++)
211     {
212         msMessage.wParam = i;
213         r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
214         ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
215             "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
216     }
217     DestroyWindow (hwEdit);
218 }
219
220 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
221  * selection.  This test checks that the first 'select all' doesn't generate
222  * an UPDATE message which can escape and (via a handler) change the
223  * selection, which would cause WM_SETTEXT to break.  This old bug
224  * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
225  */
226 static void test_edit_control_2(void)
227 {
228     HWND hwndMain;
229     char szLocalString[MAXLEN];
230
231     /* Create main and edit windows. */
232     hwndMain = CreateWindow(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
233                             0, 0, 200, 200, NULL, NULL, hinst, NULL);
234     assert(hwndMain);
235     if (winetest_interactive)
236         ShowWindow (hwndMain, SW_SHOW);
237
238     hwndET2 = CreateWindow("EDIT", NULL,
239                            WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
240                            0, 0, 150, 50, /* important this not be 0 size. */
241                            hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
242     assert(hwndET2);
243     if (winetest_interactive)
244         ShowWindow (hwndET2, SW_SHOW);
245
246     trace("EDIT: SETTEXT atomicity\n");
247     /* Send messages to "type" in the word 'foo'. */
248     SendMessage(hwndET2, WM_CHAR, 'f', 1);
249     SendMessage(hwndET2, WM_CHAR, 'o', 1);
250     SendMessage(hwndET2, WM_CHAR, 'o', 1);
251     /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
252     GetWindowText(hwndET2, szLocalString, MAXLEN);
253     ok(lstrcmp(szLocalString, "bar")==0,
254        "Wrong contents of edit: %s\n", szLocalString);
255
256     /* OK, done! */
257     DestroyWindow (hwndET2);
258     DestroyWindow (hwndMain);
259 }
260
261 static void ET2_check_change(void) {
262    char szLocalString[MAXLEN];
263    /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
264    GetWindowText(hwndET2, szLocalString, MAXLEN);
265    if (lstrcmp(szLocalString, "foo")==0) {
266        lstrcpy(szLocalString, "bar");
267        SendMessage(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
268    }
269    /* always leave the cursor at the end. */
270    SendMessage(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
271 }
272 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
273 {
274     if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
275         ET2_check_change();
276 }
277 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
278 {
279     switch (iMsg) {
280     case WM_COMMAND:
281         ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
282         break;
283     }
284     return DefWindowProc(hwnd, iMsg, wParam, lParam);
285 }
286
287 static void zero_notify(void)
288 {
289     notifications.en_change = 0;
290     notifications.en_maxtext = 0;
291     notifications.en_update = 0;
292 }
293
294 #define test_notify(enchange, enmaxtext, enupdate) \
295     ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
296     "got %d\n", enchange, notifications.en_change); \
297     ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
298     "got %d\n", enmaxtext, notifications.en_maxtext); \
299     ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
300     "got %d\n", enupdate, notifications.en_update)
301
302
303 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
304 {
305     switch (msg) {
306         case WM_COMMAND:
307             switch (HIWORD(wParam)) {
308                 case EN_MAXTEXT:
309                     notifications.en_maxtext++;
310                     break;
311                 case EN_UPDATE:
312                     notifications.en_update++;
313                     break;
314                 case EN_CHANGE:
315                     notifications.en_change++;
316                     break;
317             }
318             break;
319     }
320     return DefWindowProcA(hWnd, msg, wParam, lParam);
321 }
322
323 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
324  * to these messages.
325  */
326 static void test_edit_control_3(void)
327 {
328     HWND hWnd;
329     HWND hParent;
330     int len;
331     static const char *str = "this is a long string.";
332     static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string.";
333
334     trace("EDIT: Test notifications\n");
335
336     hParent = CreateWindowExA(0,
337               szEditTest3Class,
338               NULL,
339               0,
340               CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
341               NULL, NULL, NULL, NULL);
342     assert(hParent);
343
344     trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
345     hWnd = CreateWindowExA(0,
346               "EDIT",
347               NULL,
348               0,
349               10, 10, 50, 50,
350               hParent, NULL, NULL, NULL);
351     assert(hWnd);
352
353     zero_notify();
354     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
355     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
356     ok(lstrlenA(str) > len, "text should have been truncated\n");
357     test_notify(1, 1, 1);
358
359     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
360     zero_notify();
361     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
362     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
363     ok(1 == len, "wrong text length, expected 1, got %d\n", len);
364     test_notify(1, 0, 1);
365
366     zero_notify();
367     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
368     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
369     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
370     test_notify(1, 0, 1);
371
372     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
373
374     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
375     zero_notify();
376     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
377     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
378     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
379     test_notify(1, 1, 1);
380
381     zero_notify();
382     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
383     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
384     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
385     test_notify(1, 0, 1);
386
387     DestroyWindow(hWnd);
388
389     trace("EDIT: Single line, ES_AUTOHSCROLL\n");
390     hWnd = CreateWindowExA(0,
391               "EDIT",
392               NULL,
393               ES_AUTOHSCROLL,
394               10, 10, 50, 50,
395               hParent, NULL, NULL, NULL);
396     assert(hWnd);
397
398     zero_notify();
399     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
400     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
401     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
402     test_notify(1, 0, 1);
403
404     zero_notify();
405     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
406     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
407     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
408     test_notify(1, 0, 1);
409
410     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
411
412     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
413     zero_notify();
414     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
415     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
416     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
417     test_notify(1, 1, 1);
418
419     zero_notify();
420     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
421     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
422     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
423     test_notify(1, 0, 1);
424
425     DestroyWindow(hWnd);
426
427     trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
428     hWnd = CreateWindowExA(0,
429               "EDIT",
430               NULL,
431               ES_MULTILINE,
432               10, 10, 50, 50,
433               hParent, NULL, NULL, NULL);
434     assert(hWnd);
435
436     zero_notify();
437     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
438     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
439     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
440     test_notify(1, 1, 1);
441
442     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
443     zero_notify();
444     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
445     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
446     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
447     test_notify(1, 0, 1);
448
449     zero_notify();
450     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
451     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
452     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
453     test_notify(0, 0, 0);
454
455     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
456
457     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
458     zero_notify();
459     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
460     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
461     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
462     test_notify(1, 1, 1);
463
464     zero_notify();
465     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
466     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
467     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
468     test_notify(0, 0, 0);
469
470     DestroyWindow(hWnd);
471
472     trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
473     hWnd = CreateWindowExA(0,
474               "EDIT",
475               NULL,
476               ES_MULTILINE | ES_AUTOHSCROLL,
477               10, 10, 50, 50,
478               hParent, NULL, NULL, NULL);
479     assert(hWnd);
480
481     zero_notify();
482     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
483     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
484     ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
485     test_notify(1, 1, 1);
486
487     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
488     zero_notify();
489     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
490     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
491     ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
492     test_notify(1, 0, 1);
493
494     zero_notify();
495     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
496     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
497     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
498     test_notify(0, 0, 0);
499
500     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
501
502     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
503     zero_notify();
504     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
505     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
506     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
507     test_notify(1, 1, 1);
508
509     zero_notify();
510     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
511     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
512     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
513     test_notify(0, 0, 0);
514
515     DestroyWindow(hWnd);
516
517     trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
518     hWnd = CreateWindowExA(0,
519               "EDIT",
520               NULL,
521               ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
522               10, 10, 50, 50,
523               hParent, NULL, NULL, NULL);
524     assert(hWnd);
525
526     zero_notify();
527     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
528     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
529     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
530     test_notify(1, 0, 1);
531
532     zero_notify();
533     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
534     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
535     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
536     test_notify(0, 0, 0);
537
538     SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
539
540     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
541     zero_notify();
542     SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
543     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
544     ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
545     test_notify(1, 1, 1);
546
547     zero_notify();
548     SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
549     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
550     ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
551     test_notify(0, 0, 0);
552
553     DestroyWindow(hWnd);
554 }
555
556 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
557  */
558 static void test_edit_control_4(void)
559 {
560     HWND hwEdit;
561     int lo, hi, mid;
562     int ret;
563     int i;
564
565     trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
566     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
567     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
568     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
569     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
570     mid = lo + (hi - lo) / 2;
571
572     for (i = lo; i < mid; i++) {
573        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
574        ok(0 == ret, "expected 0 got %d\n", ret);
575     }
576     for (i = mid; i <= hi; i++) {
577        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
578        ok(1 == ret, "expected 1 got %d\n", ret);
579     }
580     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
581     ok(-1 == ret, "expected -1 got %d\n", ret);
582     DestroyWindow(hwEdit);
583
584     hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
585     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
586     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
587     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
588     mid = lo + (hi - lo) / 2;
589
590     for (i = lo; i < mid; i++) {
591        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
592        ok(0 == ret, "expected 0 got %d\n", ret);
593     }
594     for (i = mid; i <= hi; i++) {
595        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
596        ok(1 == ret, "expected 1 got %d\n", ret);
597     }
598     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
599     ok(-1 == ret, "expected -1 got %d\n", ret);
600     DestroyWindow(hwEdit);
601
602     hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
603     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
604     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
605     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
606     mid = lo + (hi - lo) / 2;
607
608     for (i = lo; i < mid; i++) {
609        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
610        ok(0 == ret, "expected 0 got %d\n", ret);
611     }
612     for (i = mid; i <= hi; i++) {
613        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
614        ok(1 == ret, "expected 1 got %d\n", ret);
615     }
616     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
617     ok(-1 == ret, "expected -1 got %d\n", ret);
618     DestroyWindow(hwEdit);
619
620     hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
621     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
622     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
623     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
624     mid = lo + (hi - lo) / 2 +1;
625
626     for (i = lo; i < mid; i++) {
627        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
628        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
629     }
630     for (i = mid; i <= hi; i++) {
631        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
632        ok(1 == ret, "expected 1 got %d\n", ret);
633     }
634     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
635     ok(-1 == ret, "expected -1 got %d\n", ret);
636     DestroyWindow(hwEdit);
637
638     hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
639     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
640     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
641     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
642     mid = lo + (hi - lo) / 2 +1;
643
644     for (i = lo; i < mid; i++) {
645        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
646        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
647     }
648     for (i = mid; i <= hi; i++) {
649        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
650        ok(1 == ret, "expected 1 got %d\n", ret);
651     }
652     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
653     ok(-1 == ret, "expected -1 got %d\n", ret);
654     DestroyWindow(hwEdit);
655
656     hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
657     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
658     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
659     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
660     mid = lo + (hi - lo) / 2 +1;
661
662     for (i = lo; i < mid; i++) {
663        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
664        ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
665     }
666     for (i = mid; i <= hi; i++) {
667        ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, (LPARAM) i));
668        ok(1 == ret, "expected 1 got %d\n", ret);
669     }
670     ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
671     ok(-1 == ret, "expected -1 got %d\n", ret);
672     DestroyWindow(hwEdit);
673 }
674
675 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
676  * truncates text that doesn't fit.
677  */
678 static void test_edit_control_5(void)
679 {
680     static const char *str = "test\r\ntest";
681     HWND hWnd;
682     int len;
683
684     hWnd = CreateWindowEx(0,
685               "EDIT",
686               str,
687               0,
688               10, 10, 1, 1,
689               NULL, NULL, NULL, NULL);
690     assert(hWnd);
691
692     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
693     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
694     DestroyWindow(hWnd);
695
696     hWnd = CreateWindowEx(0,
697               "EDIT",
698               str,
699               ES_MULTILINE,
700               10, 10, 1, 1,
701               NULL, NULL, NULL, NULL);
702     assert(hWnd);
703
704     len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
705     ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
706     DestroyWindow(hWnd);
707 }
708
709 static void test_edit_control_limittext(void)
710 {
711     HWND hwEdit;
712     DWORD r;
713
714     /* Test default limit for single-line control */
715     trace("EDIT: buffer limit for single-line\n");
716     hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
717     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
718     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
719     SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
720     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
721     /* Win9x+ME: 32766; WinNT: 2147483646UL */
722     ok( (r == 32766) || (r == 2147483646UL),
723         "got limit %u (expected 32766 or 2147483646)\n", r);
724     DestroyWindow(hwEdit);
725
726     /* Test default limit for multi-line control */
727     trace("EDIT: buffer limit for multi-line\n");
728     hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
729     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
730     ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
731     SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
732     r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
733     /* Win9x+ME: 65535; WinNT: 4294967295UL */
734     ok( (r == 65535) || (r == 4294967295UL),
735         "got limit %u (expected 65535 or 4294967295)\n", r);
736     DestroyWindow(hwEdit);
737 }
738
739 static void test_margins(void)
740 {
741     HWND hwEdit;
742     RECT old_rect, new_rect;
743     INT old_left_margin, old_right_margin;
744     DWORD old_margins, new_margins;
745
746     hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
747     
748     old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
749     old_left_margin = LOWORD(old_margins);
750     old_right_margin = HIWORD(old_margins);
751     
752     /* Check if setting the margins works */
753     
754     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
755     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
756     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
757     ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
758     
759     SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
760     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
761     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
762     ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
763     
764     
765     /* The size of the rectangle must decrease if we increase the margin */
766     
767     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
768     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
769     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
770     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
771     ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
772     ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
773     ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
774     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
775     
776     
777     /* If we set the margin to same value as the current margin,
778        the rectangle must not change */
779     
780     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
781     old_rect.left = 1;
782     old_rect.right = 99;
783     old_rect.top = 1;
784     old_rect.bottom = 99;
785     SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);    
786     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
787     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
788     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
789     ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
790     ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
791     ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
792     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
793
794     DestroyWindow (hwEdit);
795 }
796
797 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
798 {
799     return 0;
800 }
801
802 static void test_margins_font_change(void)
803 {
804     HWND hwEdit;
805     DWORD margins, font_margins;
806     LOGFONT lf;
807     HFONT hfont, hfont2;
808     HDC hdc = GetDC(0);
809
810     if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
811     {
812         trace("Arial not found - skipping font change margin tests\n");
813         ReleaseDC(0, hdc);
814         return;
815     }
816     ReleaseDC(0, hdc);
817
818     hwEdit = create_child_editcontrol(0, 0);
819
820     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
821
822     memset(&lf, 0, sizeof(lf));
823     strcpy(lf.lfFaceName, "Arial");
824     lf.lfHeight = 16;
825     lf.lfCharSet = DEFAULT_CHARSET;
826     hfont = CreateFontIndirectA(&lf);
827     lf.lfHeight = 30;
828     hfont2 = CreateFontIndirectA(&lf);
829
830     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
831     font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
832     ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
833     ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
834
835     /* With 'small' edit controls, test that the margin doesn't get set */
836     SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
837     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
838     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
839     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
840     ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins));
841     ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
842  
843     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
844     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
845     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
846     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
847     ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));  
848
849     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
850     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
851     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
852     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
853     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));  
854
855     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
856     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
857     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
858     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); 
859     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
860     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
861     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
862     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); 
863  
864     /* Above a certain size threshold then the margin is updated */
865     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
866     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
867     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
868     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
869     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
870     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
871
872     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
873     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
874     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
875     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
876     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
877
878     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
879     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
880     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
881     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
882     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
883     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
884     ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins));
885     ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
886
887     SendMessageA(hwEdit, WM_SETFONT, 0, 0);
888     
889     DeleteObject(hfont2);
890     DeleteObject(hfont);
891     destroy_child_editcontrol(hwEdit);
892
893 }
894
895 #define edit_pos_ok(exp, got, txt) \
896     ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
897
898 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
899 do { \
900     RECT format_rect; \
901     int left_margin; \
902     set_client_height(hwEdit, set_height); \
903     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
904     left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
905     edit_pos_ok(test_top, format_rect.top, vertical position); \
906     edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
907     edit_pos_ok(test_left, format_rect.left - left_margin, left); \
908 } while(0)
909
910 static void test_text_position_style(DWORD style)
911 {
912     HWND hwEdit;
913     HFONT font, oldFont;
914     HDC dc;
915     TEXTMETRIC metrics;
916     INT b, bm, b2, b3;
917     BOOL single_line = !(style & ES_MULTILINE);
918
919     b = GetSystemMetrics(SM_CYBORDER) + 1;
920     b2 = 2 * b;
921     b3 = 3 * b;
922     bm = b2 - 1;
923     
924     /* Get a stock font for which we can determine the metrics */
925     assert(font = GetStockObject(SYSTEM_FONT));
926     assert(dc = GetDC(NULL));
927     oldFont = SelectObject(dc, font);
928     assert(GetTextMetrics(dc, &metrics));    
929     SelectObject(dc, oldFont);
930     ReleaseDC(NULL, dc);
931     
932     /* Windows' edit control has some bugs in multi-line mode:
933      * - Sometimes the format rectangle doesn't get updated
934      *   (see workaround in set_client_height())
935      * - If the height of the control is smaller than the height of a text
936      *   line, the format rectangle is still as high as a text line
937      *   (higher than the client rectangle) and the caret is not shown
938      */
939     
940     /* Edit controls that are in a parent window */
941        
942     hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
943     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
944     if (single_line)
945     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
946     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
947     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
948     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
949     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
950     destroy_child_editcontrol(hwEdit);
951
952     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
953     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
954     if (single_line)
955     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
956     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
957     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
958     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
959     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
960     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
961     destroy_child_editcontrol(hwEdit);
962
963     hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
964     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
965     if (single_line)
966     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
967     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
968     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
969     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
970     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
971     destroy_child_editcontrol(hwEdit);
972
973     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
974     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
975     if (single_line)
976     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
977     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
978     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
979     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
980     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
981     destroy_child_editcontrol(hwEdit);
982
983
984     /* Edit controls that are popup windows */
985     
986     hwEdit = create_editcontrol(style | WS_POPUP, 0);
987     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
988     if (single_line)
989     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
990     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
991     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
992     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
993     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
994     DestroyWindow(hwEdit);
995
996     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
997     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
998     if (single_line)
999     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
1000     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
1001     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
1002     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
1003     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
1004     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
1005     DestroyWindow(hwEdit);
1006
1007     hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1008     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1009     if (single_line)
1010     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1011     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1012     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1013     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1014     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1015     DestroyWindow(hwEdit);
1016
1017     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1018     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
1019     if (single_line)
1020     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
1021     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
1022     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
1023     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
1024     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
1025     DestroyWindow(hwEdit);
1026 }
1027
1028 static void test_text_position(void)
1029 {
1030     trace("EDIT: Text position (Single line)\n");
1031     test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1032     trace("EDIT: Text position (Multi line)\n");
1033     test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1034 }
1035
1036 static void test_espassword(void)
1037 {
1038     HWND hwEdit;
1039     LONG r;
1040     char buffer[1024];
1041     const char* password = "secret";
1042
1043     hwEdit = create_editcontrol(ES_PASSWORD, 0);
1044     r = get_edit_style(hwEdit);
1045     ok(r == ES_PASSWORD, "Wrong style expected 0x%x got: 0x%x\n", ES_PASSWORD, r);
1046     /* set text */
1047     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1048     ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1049
1050     /* select all, cut (ctrl-x) */
1051     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1052     SendMessage(hwEdit, WM_CHAR, 24, 0);
1053
1054     /* get text */
1055     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1056     ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1057     ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1058
1059     r = OpenClipboard(hwEdit);
1060     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1061     r = EmptyClipboard();
1062     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1063     r = CloseClipboard();
1064     ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1065
1066     /* select all, copy (ctrl-c) and paste (ctrl-v) */
1067     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1068     SendMessage(hwEdit, WM_CHAR, 3, 0);
1069     SendMessage(hwEdit, WM_CHAR, 22, 0);
1070
1071     /* get text */
1072     buffer[0] = 0;
1073     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1074     ok(r == 0, "Expected: 0, got: %d\n", r);
1075     ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1076
1077     DestroyWindow (hwEdit);
1078 }
1079
1080 static void test_undo(void)
1081 {
1082     HWND hwEdit;
1083     LONG r;
1084     DWORD cpMin, cpMax;
1085     char buffer[1024];
1086     const char* text = "undo this";
1087
1088     hwEdit = create_editcontrol(0, 0);
1089     r = get_edit_style(hwEdit);
1090     ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1091
1092     /* set text */
1093     r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1094     ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1095
1096     /* select all, */
1097     cpMin = cpMax = 0xdeadbeef;
1098     SendMessage(hwEdit, EM_SETSEL, 0, -1);
1099     r = SendMessage(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1100     ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1101     ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1102     ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1103
1104     /* cut (ctrl-x) */
1105     r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1106     todo_wine { ok(1 == r, "Expected: %d, got: %d\n", 1, r); }
1107
1108     /* get text */
1109     buffer[0] = 0;
1110     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1111     ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1112     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1113
1114     /* undo (ctrl-z) */
1115     r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1116     todo_wine { ok(1 == r, "Expected: %d, got: %d\n", 1, r); }
1117
1118     /* get text */
1119     buffer[0] = 0;
1120     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1121     ok(strlen(text) == r, "Unexpected length %d\n", r);
1122     ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1123
1124     /* undo again (ctrl-z) */
1125     r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1126     todo_wine { ok(1 == r, "Expected: %d, got: %d\n", 1, r); }
1127
1128     /* get text */
1129     buffer[0] = 0;
1130     r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1131     ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1132     ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1133
1134     DestroyWindow (hwEdit);
1135 }
1136
1137 static BOOL RegisterWindowClasses (void)
1138 {
1139     WNDCLASSA test2;
1140     WNDCLASSA test3;
1141     WNDCLASSA text_position;
1142     
1143     test2.style = 0;
1144     test2.lpfnWndProc = ET2_WndProc;
1145     test2.cbClsExtra = 0;
1146     test2.cbWndExtra = 0;
1147     test2.hInstance = hinst;
1148     test2.hIcon = NULL;
1149     test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
1150     test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1151     test2.lpszMenuName = NULL;
1152     test2.lpszClassName = szEditTest2Class;
1153     if (!RegisterClassA(&test2)) return FALSE;
1154
1155     test3.style = 0;
1156     test3.lpfnWndProc = edit3_wnd_procA;
1157     test3.cbClsExtra = 0;
1158     test3.cbWndExtra = 0;
1159     test3.hInstance = hinst;
1160     test3.hIcon = 0;
1161     test3.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1162     test3.hbrBackground = GetStockObject(WHITE_BRUSH);
1163     test3.lpszMenuName = NULL;
1164     test3.lpszClassName = szEditTest3Class;
1165     if (!RegisterClassA(&test3)) return FALSE;
1166
1167     text_position.style = CS_HREDRAW | CS_VREDRAW;
1168     text_position.cbClsExtra = 0;
1169     text_position.cbWndExtra = 0;
1170     text_position.hInstance = hinst;
1171     text_position.hIcon = NULL;
1172     text_position.hCursor = LoadCursorA(NULL, IDC_ARROW);
1173     text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1174     text_position.lpszMenuName = NULL;
1175     text_position.lpszClassName = szEditTextPositionClass;
1176     text_position.lpfnWndProc = DefWindowProc;
1177     if (!RegisterClassA(&text_position)) return FALSE;
1178
1179     return TRUE;
1180 }
1181
1182 static void UnregisterWindowClasses (void)
1183 {
1184     UnregisterClassA(szEditTest2Class, hinst);
1185     UnregisterClassA(szEditTest3Class, hinst);
1186     UnregisterClassA(szEditTextPositionClass, hinst);
1187 }
1188
1189 START_TEST(edit)
1190 {
1191     hinst = GetModuleHandleA(NULL);
1192     assert(RegisterWindowClasses());
1193
1194     test_edit_control_1();
1195     test_edit_control_2();
1196     test_edit_control_3();
1197     test_edit_control_4();
1198     test_edit_control_5();
1199     test_edit_control_limittext();
1200     test_margins();
1201     test_margins_font_change();
1202     test_text_position();
1203     test_espassword();
1204     test_undo();
1205
1206     UnregisterWindowClasses();
1207 }