user: Simplify 16-bit mappings of the WM_GETDLGCODE message.
[wine] / dlls / user / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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%lx\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 %lx\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%lx\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 %lx\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%lx\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 %lx\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%lx\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 %lx\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, "expected 0 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, "expected 0 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, "expected 0 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_margins(void)
710 {
711     HWND hwEdit;
712     RECT old_rect, new_rect;
713     INT old_left_margin, old_right_margin;
714     DWORD old_margins, new_margins;
715
716     hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
717     
718     old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
719     old_left_margin = LOWORD(old_margins);
720     old_right_margin = HIWORD(old_margins);
721     
722     /* Check if setting the margins works */
723     
724     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
725     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
726     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
727     ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
728     
729     SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
730     new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
731     ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
732     ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
733     
734     
735     /* The size of the rectangle must decrease if we increase the margin */
736     
737     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
738     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
739     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
740     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
741     ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
742     ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
743     ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
744     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
745     
746     
747     /* If we set the margin to same value as the current margin,
748        the rectangle must not change */
749     
750     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
751     old_rect.left = 1;
752     old_rect.right = 99;
753     old_rect.top = 1;
754     old_rect.bottom = 99;
755     SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);    
756     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
757     SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
758     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
759     ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
760     ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
761     ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
762     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
763
764     DestroyWindow (hwEdit);
765 }
766
767 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
768 {
769     return 0;
770 }
771
772 static void test_margins_font_change(void)
773 {
774     HWND hwEdit;
775     DWORD margins, font_margins;
776     LOGFONT lf;
777     HFONT hfont, hfont2;
778     HDC hdc = GetDC(0);
779
780     if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
781     {
782         trace("Arial not found - skipping font change margin tests\n");
783         ReleaseDC(0, hdc);
784         return;
785     }
786     ReleaseDC(0, hdc);
787
788     hwEdit = create_child_editcontrol(0, 0);
789
790     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
791
792     memset(&lf, 0, sizeof(lf));
793     strcpy(lf.lfFaceName, "Arial");
794     lf.lfHeight = 16;
795     lf.lfCharSet = DEFAULT_CHARSET;
796     hfont = CreateFontIndirectA(&lf);
797     lf.lfHeight = 30;
798     hfont2 = CreateFontIndirectA(&lf);
799
800     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
801     font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
802     ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
803     ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
804
805     /* With 'small' edit controls, test that the margin doesn't get set */
806     SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
807     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
808     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
809     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
810     ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins));
811     ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
812  
813     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
814     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
815     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
816     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
817     ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));  
818
819     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
820     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
821     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
822     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
823     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));  
824
825     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
826     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
827     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
828     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); 
829     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
830     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
831     ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
832     ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); 
833  
834     /* Above a certain size threshold then the margin is updated */
835     SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
836     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
837     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
838     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
839     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
840     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
841
842     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
843     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
844     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
845     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
846     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
847
848     SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
849     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
850     ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
851     ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
852     SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
853     margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
854     ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins));
855     ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
856
857     SendMessageA(hwEdit, WM_SETFONT, 0, 0);
858     
859     DeleteObject(hfont2);
860     DeleteObject(hfont);
861     destroy_child_editcontrol(hwEdit);
862
863 }
864
865 #define edit_pos_ok(exp, got, txt) \
866     ok(exp == got, "wrong " #txt " expected %d got %ld\n", exp, got);
867
868 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
869 do { \
870     RECT format_rect; \
871     int left_margin; \
872     set_client_height(hwEdit, set_height); \
873     SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
874     left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
875     edit_pos_ok(test_top, format_rect.top, vertical position); \
876     edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
877     edit_pos_ok(test_left, format_rect.left - left_margin, left); \
878 } while(0)
879
880 void test_text_position_style(DWORD style)
881 {
882     HWND hwEdit;
883     HFONT font, oldFont;
884     HDC dc;
885     TEXTMETRIC metrics;
886     INT b, bm, b2, b3;
887     BOOL single_line = !(style & ES_MULTILINE);
888
889     b = GetSystemMetrics(SM_CYBORDER) + 1;
890     b2 = 2 * b;
891     b3 = 3 * b;
892     bm = b2 - 1;
893     
894     /* Get a stock font for which we can determine the metrics */
895     assert(font = GetStockObject(SYSTEM_FONT));
896     assert(dc = GetDC(NULL));
897     oldFont = SelectObject(dc, font);
898     assert(GetTextMetrics(dc, &metrics));    
899     SelectObject(dc, oldFont);
900     ReleaseDC(NULL, dc);
901     
902     /* Windows' edit control has some bugs in multi-line mode:
903      * - Sometimes the format rectangle doesn't get updated
904      *   (see workaround in set_client_height())
905      * - If the height of the control is smaller than the height of a text
906      *   line, the format rectangle is still as high as a text line
907      *   (higher than the client rectangle) and the caret is not shown
908      */
909     
910     /* Edit controls that are in a parent window */
911        
912     hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
913     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
914     if (single_line)
915     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
916     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
917     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
918     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
919     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
920     destroy_child_editcontrol(hwEdit);
921
922     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
923     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
924     if (single_line)
925     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
926     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
927     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
928     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
929     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
930     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
931     destroy_child_editcontrol(hwEdit);
932
933     hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
934     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
935     if (single_line)
936     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
937     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
938     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
939     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
940     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
941     destroy_child_editcontrol(hwEdit);
942
943     hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
944     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
945     if (single_line)
946     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
947     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
948     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
949     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
950     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
951     destroy_child_editcontrol(hwEdit);
952
953
954     /* Edit controls that are popup windows */
955     
956     hwEdit = create_editcontrol(style | WS_POPUP, 0);
957     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
958     if (single_line)
959     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
960     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
961     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
962     check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
963     check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
964     DestroyWindow(hwEdit);
965
966     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
967     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
968     if (single_line)
969     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
970     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
971     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
972     check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
973     check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
974     check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
975     DestroyWindow(hwEdit);
976
977     hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
978     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
979     if (single_line)
980     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
981     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
982     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
983     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
984     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
985     DestroyWindow(hwEdit);
986
987     hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
988     SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
989     if (single_line)
990     check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
991     check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
992     check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
993     check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
994     check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
995     DestroyWindow(hwEdit);
996 }
997
998 void test_text_position(void)
999 {
1000     trace("EDIT: Text position (Single line)\n");
1001     test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1002     trace("EDIT: Text position (Multi line)\n");
1003     test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1004 }
1005
1006 static BOOL RegisterWindowClasses (void)
1007 {
1008     WNDCLASSA test2;
1009     WNDCLASSA test3;
1010     WNDCLASSA text_position;
1011     
1012     test2.style = 0;
1013     test2.lpfnWndProc = ET2_WndProc;
1014     test2.cbClsExtra = 0;
1015     test2.cbWndExtra = 0;
1016     test2.hInstance = hinst;
1017     test2.hIcon = NULL;
1018     test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
1019     test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1020     test2.lpszMenuName = NULL;
1021     test2.lpszClassName = szEditTest2Class;
1022     if (!RegisterClassA(&test2)) return FALSE;
1023
1024     test3.style = 0;
1025     test3.lpfnWndProc = edit3_wnd_procA;
1026     test3.cbClsExtra = 0;
1027     test3.cbWndExtra = 0;
1028     test3.hInstance = hinst;
1029     test3.hIcon = 0;
1030     test3.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1031     test3.hbrBackground = GetStockObject(WHITE_BRUSH);
1032     test3.lpszMenuName = NULL;
1033     test3.lpszClassName = szEditTest3Class;
1034     if (!RegisterClassA(&test3)) return FALSE;
1035
1036     text_position.style = CS_HREDRAW | CS_VREDRAW;
1037     text_position.cbClsExtra = 0;
1038     text_position.cbWndExtra = 0;
1039     text_position.hInstance = hinst;
1040     text_position.hIcon = NULL;
1041     text_position.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
1042     text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1043     text_position.lpszMenuName = NULL;
1044     text_position.lpszClassName = szEditTextPositionClass;
1045     text_position.lpfnWndProc = DefWindowProc;
1046     if (!RegisterClassA(&text_position)) return FALSE;
1047
1048     return TRUE;
1049 }
1050
1051 static void UnregisterWindowClasses (void)
1052 {
1053     UnregisterClassA(szEditTest2Class, hinst);
1054     UnregisterClassA(szEditTest3Class, hinst);
1055     UnregisterClassA(szEditTextPositionClass, hinst);
1056 }
1057
1058 START_TEST(edit)
1059 {
1060     hinst = GetModuleHandleA(NULL);
1061     assert(RegisterWindowClasses());
1062
1063     test_edit_control_1();
1064     test_edit_control_2();
1065     test_edit_control_3();
1066     test_edit_control_4();
1067     test_edit_control_5();
1068     test_margins();
1069     test_margins_font_change();
1070     test_text_position();
1071
1072     UnregisterWindowClasses();
1073 }