Author: cwittich
Date: Mon Dec 29 02:27:52 2008
New Revision: 38441
URL:
http://svn.reactos.org/svn/reactos?rev=38441&view=rev
Log:
sync riched20 winetest to wine 1.1.11
Added:
trunk/rostests/winetests/riched20/txtsrv.c (with props)
Modified:
trunk/rostests/winetests/riched20/editor.c
trunk/rostests/winetests/riched20/riched20.rbuild
trunk/rostests/winetests/riched20/testlist.c
Modified: trunk/rostests/winetests/riched20/editor.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/riched20/editor…
==============================================================================
--- trunk/rostests/winetests/riched20/editor.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/riched20/editor.c [iso-8859-1] Mon Dec 29 02:27:52 2008
@@ -21,6 +21,7 @@
*/
#include <stdarg.h>
+#include <stdio.h>
#include <assert.h>
#include <windef.h>
#include <winbase.h>
@@ -32,7 +33,18 @@
#include <time.h>
#include <wine/test.h>
+static CHAR string1[MAX_PATH], string2[MAX_PATH], string3[MAX_PATH];
+
+#define ok_w3(format, szString1, szString2, szString3) \
+ WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \
+ WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \
+ WideCharToMultiByte(CP_ACP, 0, szString3, -1, string3, MAX_PATH, NULL, NULL); \
+ ok(!lstrcmpW(szString3, szString1) || !lstrcmpW(szString3, szString2), \
+ format, string1, string2, string3);
+
static HMODULE hmoduleRichEdit;
+
+static int is_win9x = 0;
static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
HWND hwnd;
@@ -45,6 +57,26 @@
static HWND new_richedit(HWND parent) {
return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent);
+}
+
+/* Keeps the window reponsive for the deley_time in seconds.
+ * This is useful for debugging a test to see what is happening. */
+static void keep_responsive(time_t delay_time)
+{
+ MSG msg;
+ time_t end;
+
+ /* The message pump uses PeekMessage() to empty the queue and then
+ * sleeps for 50ms before retrying the queue. */
+ end = time(NULL) + delay_time;
+ while (time(NULL) < end) {
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ } else {
+ Sleep(50);
+ }
+ }
}
static void processPendingMessages(void)
@@ -81,6 +113,34 @@
}
}
+static BOOL hold_key(int vk)
+{
+ BYTE key_state[256];
+ BOOL result;
+
+ result = GetKeyboardState(key_state);
+ ok(result, "GetKeyboardState failed.\n");
+ if (!result) return FALSE;
+ key_state[vk] |= 0x80;
+ result = SetKeyboardState(key_state);
+ ok(result, "SetKeyboardState failed.\n");
+ return result != 0;
+}
+
+static BOOL release_key(int vk)
+{
+ BYTE key_state[256];
+ BOOL result;
+
+ result = GetKeyboardState(key_state);
+ ok(result, "GetKeyboardState failed.\n");
+ if (!result) return FALSE;
+ key_state[vk] &= ~0x80;
+ result = SetKeyboardState(key_state);
+ ok(result, "SetKeyboardState failed.\n");
+ return result != 0;
+}
+
static const char haystack[] = "WINEWine wineWine wine WineWine";
/* ^0 ^10 ^20 ^30 */
@@ -90,80 +150,79 @@
const char *needle;
int flags;
int expected_loc;
- int _todo_wine;
};
struct find_s find_tests[] = {
/* Find in empty text */
- {0, -1, "foo", FR_DOWN, -1, 0},
- {0, -1, "foo", 0, -1, 0},
- {0, -1, "", FR_DOWN, -1, 0},
- {20, 5, "foo", FR_DOWN, -1, 0},
- {5, 20, "foo", FR_DOWN, -1, 0}
+ {0, -1, "foo", FR_DOWN, -1},
+ {0, -1, "foo", 0, -1},
+ {0, -1, "", FR_DOWN, -1},
+ {20, 5, "foo", FR_DOWN, -1},
+ {5, 20, "foo", FR_DOWN, -1}
};
struct find_s find_tests2[] = {
/* No-result find */
- {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1, 0},
- {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1, 0},
+ {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1},
+ {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1},
/* Subsequent finds */
- {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4, 0},
- {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13, 0},
- {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
- {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
+ {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4},
+ {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13},
+ {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
+ {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
/* Find backwards */
- {19, 20, "Wine", FR_MATCHCASE, 13, 0},
- {10, 20, "Wine", FR_MATCHCASE, 4, 0},
- {20, 10, "Wine", FR_MATCHCASE, 13, 0},
+ {19, 20, "Wine", FR_MATCHCASE, 13},
+ {10, 20, "Wine", FR_MATCHCASE, 4},
+ {20, 10, "Wine", FR_MATCHCASE, 13},
/* Case-insensitive */
- {1, 31, "wInE", FR_DOWN, 4, 0},
- {1, 31, "Wine", FR_DOWN, 4, 0},
+ {1, 31, "wInE", FR_DOWN, 4},
+ {1, 31, "Wine", FR_DOWN, 4},
/* High-to-low ranges */
- {20, 5, "Wine", FR_DOWN, -1, 0},
- {2, 1, "Wine", FR_DOWN, -1, 0},
- {30, 29, "Wine", FR_DOWN, -1, 0},
- {20, 5, "Wine", 0, 13, 0},
+ {20, 5, "Wine", FR_DOWN, -1},
+ {2, 1, "Wine", FR_DOWN, -1},
+ {30, 29, "Wine", FR_DOWN, -1},
+ {20, 5, "Wine", 0, 13},
/* Find nothing */
- {5, 10, "", FR_DOWN, -1, 0},
- {10, 5, "", FR_DOWN, -1, 0},
- {0, -1, "", FR_DOWN, -1, 0},
- {10, 5, "", 0, -1, 0},
+ {5, 10, "", FR_DOWN, -1},
+ {10, 5, "", FR_DOWN, -1},
+ {0, -1, "", FR_DOWN, -1},
+ {10, 5, "", 0, -1},
/* Whole-word search */
- {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 0},
- {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1, 0},
- {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 0},
- {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0, 0},
- {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23, 0},
- {11, -1, "winewine", FR_WHOLEWORD, 0, 0},
- {31, -1, "winewine", FR_WHOLEWORD, 23, 0},
+ {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
+ {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1},
+ {13, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18},
+ {0, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 0},
+ {10, -1, "winewine", FR_DOWN | FR_WHOLEWORD, 23},
+ {11, -1, "winewine", FR_WHOLEWORD, 0},
+ {31, -1, "winewine", FR_WHOLEWORD, 23},
/* Bad ranges */
- {5, 200, "XXX", FR_DOWN, -1, 0},
- {-20, 20, "Wine", FR_DOWN, -1, 0},
- {-20, 20, "Wine", FR_DOWN, -1, 0},
- {-15, -20, "Wine", FR_DOWN, -1, 0},
- {1<<12, 1<<13, "Wine", FR_DOWN, -1, 0},
+ {5, 200, "XXX", FR_DOWN, -1},
+ {-20, 20, "Wine", FR_DOWN, -1},
+ {-20, 20, "Wine", FR_DOWN, -1},
+ {-15, -20, "Wine", FR_DOWN, -1},
+ {1<<12, 1<<13, "Wine", FR_DOWN, -1},
/* Check the case noted in bug 4479 where matches at end aren't recognized */
- {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
- {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
- {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
- {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
- {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
+ {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23},
+ {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27},
+ {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27},
+ {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
+ {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23},
/* The backwards case of bug 4479; bounds look right
* Fails because backward find is wrong */
- {19, 20, "WINE", FR_MATCHCASE, 0, 0},
- {0, 20, "WINE", FR_MATCHCASE, -1, 0},
-
- {0, -1, "wineWine wine", 0, -1, 0},
+ {19, 20, "WINE", FR_MATCHCASE, 0},
+ {0, 20, "WINE", FR_MATCHCASE, -1},
+
+ {0, -1, "wineWine wine", 0, -1},
};
static void check_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *f, int id) {
@@ -209,15 +268,8 @@
int i;
for (i = 0; i < num_tests; i++) {
- if (find[i]._todo_wine) {
- todo_wine {
- check_EM_FINDTEXT(hwnd, name, &find[i], i);
- check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
- }
- } else {
- check_EM_FINDTEXT(hwnd, name, &find[i], i);
- check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
- }
+ check_EM_FINDTEXT(hwnd, name, &find[i], i);
+ check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
}
}
@@ -296,7 +348,7 @@
{
int nCopied;
int expected_nCopied = min(gl[i].buffer_len, strlen(gl[i].text));
- int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text) + 1);
+ int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text));
memset(dest, 0xBB, nBuf);
*(WORD *) dest = gl[i].buffer_len;
@@ -314,11 +366,37 @@
!strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
else
{
+ /* Prepare hex strings of buffers to dump on failure. */
+ char expectedbuf[1024];
+ char resultbuf[1024];
+ int j;
+ resultbuf[0] = '\0';
+ for (j = 0; j < 32; j++)
+ sprintf(resultbuf+strlen(resultbuf), "%02x", dest[j] & 0xFF);
+ expectedbuf[0] = '\0';
+ for (j = 0; j < expected_bytes_written; j++) /* Written bytes */
+ sprintf(expectedbuf+strlen(expectedbuf), "%02x", gl[i].text[j] &
0xFF);
+ for (; j < gl[i].buffer_len; j++) /* Ignored bytes */
+ sprintf(expectedbuf+strlen(expectedbuf), "??");
+ for (; j < 32; j++) /* Bytes after declared buffer size */
+ sprintf(expectedbuf+strlen(expectedbuf), "%02x", origdest[j] &
0xFF);
+
+ /* Test the part of the buffer that is expected to be written according
+ * to the MSDN documentation fo EM_GETLINE, which does not state that
+ * a NULL terminating character will be added unless no text is copied.
+ *
+ * Windows 95, 98 & NT do not append a NULL terminating character, but
+ * Windows 2000 and up do append a NULL terminating character if there
+ * is space in the buffer. The test will ignore this difference. */
ok(!strncmp(dest, gl[i].text, expected_bytes_written),
- "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
- ok(!strncmp(dest + expected_bytes_written, origdest
- + expected_bytes_written, nBuf - expected_bytes_written),
- "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
+ "%d: expected_bytes_written=%d\n" "expected=0x%s\n"
"but got= 0x%s\n",
+ i, expected_bytes_written, expectedbuf, resultbuf);
+ /* Test the part of the buffer after the declared length to make sure
+ * there are no buffer overruns. */
+ ok(!strncmp(dest + gl[i].buffer_len, origdest + gl[i].buffer_len,
+ nBuf - gl[i].buffer_len),
+ "%d: expected_bytes_written=%d\n" "expected=0x%s\n"
"but got= 0x%s\n",
+ i, expected_bytes_written, expectedbuf, resultbuf);
}
}
@@ -383,7 +461,6 @@
static void test_EM_SCROLLCARET(void)
{
int prevY, curY;
- HWND hwndRichEdit = new_richedit(NULL);
const char text[] = "aa\n"
"this is a long line of text that should be longer than the "
"control's width\n"
@@ -393,6 +470,14 @@
"ff\n"
"gg\n"
"hh\n";
+ /* The richedit window height needs to be large enough vertically to fit in
+ * more than two lines of text, so the new_richedit function can't be used
+ * since a height of 60 was not large enough on some systems.
+ */
+ HWND hwndRichEdit = CreateWindow(RICHEDIT_CLASS, NULL,
+
ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
+ 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwndRichEdit != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int)
GetLastError());
/* Can't verify this */
SendMessage(hwndRichEdit, EM_SCROLLCARET, 0, 0);
@@ -438,6 +523,7 @@
LRESULT result;
unsigned int height = 0;
int xpos = 0;
+ POINTL pt;
static const char text[] = "aa\n"
"this is a long line of text that should be longer than the "
"control's width\n"
@@ -475,9 +561,7 @@
if (i == 0)
{
ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n",
HIWORD(result));
- todo_wine {
ok(LOWORD(result) == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n",
LOWORD(result));
- }
xpos = LOWORD(result);
}
else if (i == 1)
@@ -531,9 +615,7 @@
result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 0, 0);
ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n",
HIWORD(result));
- todo_wine {
ok(LOWORD(result) == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n",
LOWORD(result));
- }
xpos = LOWORD(result);
SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0);
@@ -545,6 +627,26 @@
"EM_POSFROMCHAR reports x=%hd, expected value less than %d\n",
(signed short)(LOWORD(result)), xpos);
}
+ SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINELEFT, 0);
+
+ /* Test around end of text that doesn't end in a newline. */
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "12345678901234");
+ SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt,
+ SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0)-1);
+ ok(pt.x > 1, "pt.x = %d\n", pt.x);
+ xpos = pt.x;
+ SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt,
+ SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0));
+ ok(pt.x > xpos, "pt.x = %d\n", pt.x);
+ xpos = pt.x;
+ SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt,
+ SendMessage(hwndRichEdit, WM_GETTEXTLENGTH, 0, 0)+1);
+ ok(pt.x == xpos, "pt.x = %d\n", pt.x);
+
+ /* Try a negative position. */
+ SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, -1);
+ ok(pt.x == 1, "pt.x = %d\n", pt.x);
+
DestroyWindow(hwndRichEdit);
}
@@ -659,7 +761,7 @@
cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects;
/* wParam==0 is default char format, does not set modify */
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
ok(rc == 0, "Text marked as modified, expected not modified!\n");
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, 0, (LPARAM) &cf2);
@@ -668,7 +770,7 @@
ok(rc == 0, "Text marked as modified, expected not modified!\n");
/* wParam==SCF_SELECTION sets modify if nonempty selection */
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
ok(rc == 0, "Text marked as modified, expected not modified!\n");
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf2);
@@ -690,7 +792,7 @@
ok(rc == -1, "Text not marked as modified, expected modified! (%d)\n", rc);
/* wParam==SCF_ALL sets modify regardless of whether text is present */
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
rc = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
ok(rc == 0, "Text marked as modified, expected not modified!\n");
rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2);
@@ -1092,6 +1194,7 @@
HWND hwndRichEdit = new_richedit(NULL);
PARAFORMAT2 fmt;
HRESULT ret;
+ LONG expectedMask = PFM_ALL2 & ~PFM_TABLEROWDELIMITER;
fmt.cbSize = sizeof(PARAFORMAT2);
fmt.dwMask = PFM_ALIGNMENT;
fmt.wAlignment = PFA_LEFT;
@@ -1102,8 +1205,14 @@
fmt.cbSize = sizeof(PARAFORMAT2);
fmt.dwMask = -1;
ret = SendMessage(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM) &fmt);
- ok(ret == PFM_ALL2, "expected %x got %x\n", PFM_ALL2, ret);
- ok(fmt.dwMask == PFM_ALL2, "expected %x got %x\n", PFM_ALL2, fmt.dwMask);
+ /* Ignore the PFM_TABLEROWDELIMITER bit because it changes
+ * between richedit different native builds of riched20.dll
+ * used on different Windows versions. */
+ ret &= ~PFM_TABLEROWDELIMITER;
+ fmt.dwMask &= ~PFM_TABLEROWDELIMITER;
+
+ ok(ret == expectedMask, "expected %x got %x\n", expectedMask, ret);
+ ok(fmt.dwMask == expectedMask, "expected %x got %x\n", expectedMask,
fmt.dwMask);
DestroyWindow(hwndRichEdit);
}
@@ -2253,7 +2362,7 @@
unsigned int recursionLevel = 0;
unsigned int WM_SIZE_recursionLevel = 0;
BOOL bailedOutOfRecursion = FALSE;
-LRESULT WINAPI (*richeditProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+LRESULT (WINAPI *richeditProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT WINAPI RicheditStupidOverrideProcA(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
@@ -2307,8 +2416,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
@@ -2318,8 +2427,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
@@ -2584,8 +2693,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
@@ -2595,8 +2704,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
@@ -2606,8 +2715,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
@@ -2617,8 +2726,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
@@ -2732,8 +2841,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
"Vertical scrollbar is invisible, should be visible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
/* Ditto, see above */
@@ -2744,8 +2853,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
"Vertical scrollbar is invisible, should be visible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
/* Ditto, see above */
@@ -2756,8 +2865,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
"Vertical scrollbar is invisible, should be visible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
/* Ditto, see above */
@@ -2768,8 +2877,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
"Vertical scrollbar is invisible, should be visible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
/* Ditto, see above */
@@ -2780,8 +2889,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0),
"Vertical scrollbar is invisible, should be visible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
@@ -2807,8 +2916,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
@@ -2818,8 +2927,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a");
@@ -2829,8 +2938,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
@@ -2840,8 +2949,8 @@
GetScrollInfo(hwndRichEdit, SB_VERT, &si);
ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) == 0),
"Vertical scrollbar is visible, should be invisible.\n");
- ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 0,
- "reported page/range is %d (%d..%d) expected all 0\n",
+ ok(si.nPage == 0 && si.nMin == 0 && (si.nMax == 0 || si.nMax == 100),
+ "reported page/range is %d (%d..%d) expected all 0 or nMax=100\n",
si.nPage, si.nMin, si.nMax);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text);
@@ -3207,6 +3316,8 @@
't', 't', 'S', 'o',
'm', 'e', 'T', 'e',
'x', 't', 0};
+ WCHAR TestItem1altn[] =
{'T','T','e','s','t','S','o','m','e','T','e','x','t',
+
'\r','t','S','o','m','e','T','e','x','t',0};
WCHAR TestItem2[] = {'T', 'e', 's', 't',
'S', 'o', 'm', 'e',
'T', 'e', 'x', 't',
@@ -3341,8 +3452,7 @@
"EM_SETTEXTEX did not convert properly\n");
/* !ST_SELECTION && Unicode && !\rtf */
- result = SendMessage(hwndRichEdit, EM_SETTEXTEX,
- (WPARAM)&setText, (LPARAM) NULL);
+ result = SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, 0);
SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf);
ok (result == 1,
@@ -3359,8 +3469,7 @@
SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
/* replace current selection: ST_SELECTION && Unicode && !\rtf */
setText.flags = ST_SELECTION;
- result = SendMessage(hwndRichEdit, EM_SETTEXTEX,
- (WPARAM)&setText, (LPARAM) NULL);
+ result = SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, 0);
ok(result == 0,
"EM_SETTEXTEX with NULL lParam to replace selection"
" with no text should return 0. Got %i\n",
@@ -3439,9 +3548,7 @@
setText.flags = ST_SELECTION;
SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) buf);
SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf);
- ok(lstrcmpW(buf, TestItem1alt) == 0,
- "EM_GETTEXTEX results not what was set by EM_SETTEXTEX when"
- " using ST_SELECTION on an RTF string and non-Unicode\n");
+ ok_w3("Expected \"%s\" or \"%s\", got
\"%s\"\n", TestItem1alt, TestItem1altn, buf);
/* The following test demonstrates that EM_SETTEXTEX replacing a selection */
setText.codepage = 1200; /* no constant for unicode */
@@ -3472,6 +3579,28 @@
"EM_GETTEXTEX results not what was set by EM_SETTEXTEX when"
" using ST_SELECTION and non-Unicode\n");
+ /* Test setting text using rich text format */
+ setText.flags = 0;
+ setText.codepage = CP_ACP;
+ SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"{\\rtf
richtext}");
+ getText.codepage = CP_ACP;
+ getText.cb = MAX_BUF_LEN;
+ getText.flags = GT_DEFAULT;
+ getText.lpDefaultChar = NULL;
+ getText.lpUsedDefChar = NULL;
+ SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) bufACP);
+ ok(!strcmp(bufACP, "richtext"), "expected 'richtext' but got
'%s'\n", bufACP);
+
+ setText.flags = 0;
+ setText.codepage = CP_ACP;
+ SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM)"{\\urtf
morerichtext}");
+ getText.codepage = CP_ACP;
+ getText.cb = MAX_BUF_LEN;
+ getText.flags = GT_DEFAULT;
+ getText.lpDefaultChar = NULL;
+ getText.lpUsedDefChar = NULL;
+ SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) bufACP);
+ ok(!strcmp(bufACP, "morerichtext"), "expected 'morerichtext' but
got '%s'\n", bufACP);
DestroyWindow(hwndRichEdit);
}
@@ -3686,7 +3815,7 @@
returnedCF2A.cbSize = sizeof(returnedCF2A);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "x");
- SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont1,(LPARAM) MAKELONG((WORD) TRUE,
0));
+ SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont1, MAKELPARAM(TRUE, 0));
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)
&returnedCF2A);
GetObjectA(testFont1, sizeof(LOGFONTA), &sentLogFont);
@@ -3694,14 +3823,14 @@
"EM_GETCHARFORMAT: Returned wrong font on test 1. Sent: %s, Returned:
%s\n",
sentLogFont.lfFaceName,returnedCF2A.szFaceName);
- SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont2,(LPARAM) MAKELONG((WORD) TRUE,
0));
+ SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont2, MAKELPARAM(TRUE, 0));
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)
&returnedCF2A);
GetObjectA(testFont2, sizeof(LOGFONTA), &sentLogFont);
ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
"EM_GETCHARFORMAT: Returned wrong font on test 2. Sent: %s, Returned:
%s\n",
sentLogFont.lfFaceName,returnedCF2A.szFaceName);
- SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont3,(LPARAM) MAKELONG((WORD) TRUE,
0));
+ SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont3, MAKELPARAM(TRUE, 0));
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)
&returnedCF2A);
GetObjectA(testFont3, sizeof(LOGFONTA), &sentLogFont);
ok (!strcmp(sentLogFont.lfFaceName,returnedCF2A.szFaceName),
@@ -3714,7 +3843,7 @@
ZeroMemory(&sentLogFont,sizeof(sentLogFont));
returnedCF2A.cbSize = sizeof(returnedCF2A);
- SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)NULL,(LPARAM) MAKELONG((WORD) TRUE, 0));
+ SendMessage(hwndRichEdit, WM_SETFONT, 0, MAKELPARAM((WORD) TRUE, 0));
SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)
&returnedCF2A);
GetObjectA(NULL, sizeof(LOGFONTA), &sentLogFont);
ok (!strcmp("System",returnedCF2A.szFaceName),
@@ -3788,7 +3917,7 @@
/* setting font doesn't change modify flag */
SendMessage(hwndRichEdit, EM_SETMODIFY, FALSE, 0);
- SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont,(LPARAM) MAKELONG((WORD) TRUE,
0));
+ SendMessage(hwndRichEdit, WM_SETFONT, (WPARAM)testFont, MAKELPARAM(TRUE, 0));
result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0);
ok (result == 0,
"EM_GETMODIFY returned non-zero, instead of zero on setting font\n");
@@ -4007,7 +4136,7 @@
/* FIXME add more tests */
SendMessage(hwndRichEdit, EM_SETSEL, 7, 17);
- r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) NULL);
+ r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, 0);
ok(0 == r, "EM_REPLACESEL returned %d, expected 0\n", r);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
r = strcmp(buffer, "testing");
@@ -4021,7 +4150,7 @@
SendMessage(hwndRichEdit, WM_SETREDRAW, redraw, 0);
/* Test behavior with carriage returns and newlines */
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "RichEdit1");
ok(9 == r, "EM_REPLACESEL returned %d, expected 9\n", r);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
@@ -4040,7 +4169,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 1, "EM_GETLINECOUNT returned %d, expected 1\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "RichEdit1\r");
ok(10 == r, "EM_REPLACESEL returned %d, expected 10\n", r);
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
@@ -4066,7 +4195,7 @@
characters interpreted from the original lParam. Wine's builtin riched20
implements the WinXP behavior.
*/
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "RichEdit1\r\n");
ok(11 == r /* WinXP */ || 10 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 11 or 10\n", r);
@@ -4103,7 +4232,7 @@
string.
*/
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r");
ok(2 == r, "EM_REPLACESEL returned %d, expected 4\n", r);
r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
@@ -4125,7 +4254,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n");
ok(3 == r /* WinXP */ || 1 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 3 or 1\n", r);
@@ -4148,7 +4277,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 1, "EM_GETLINECOUNT returned %d, expected 1\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)
"\r\r\r\r\r\n\r\r\r");
ok(9 == r /* WinXP */ || 7 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 9 or 7\n", r);
@@ -4171,7 +4300,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 7, "EM_GETLINECOUNT returned %d, expected 7\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n\r\n");
ok(5 == r /* WinXP */ || 2 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 5 or 2\n", r);
@@ -4194,7 +4323,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 2, "EM_GETLINECOUNT returned %d, expected 2\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\r\r\n\r\r");
ok(5 == r /* WinXP */ || 3 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 5 or 3\n", r);
@@ -4217,7 +4346,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\rX\r\n\r\r");
ok(6 == r /* WinXP */ || 5 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 6 or 5\n", r);
@@ -4240,7 +4369,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 5, "EM_GETLINECOUNT returned %d, expected 5\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM) "\n\n");
ok(2 == r, "EM_REPLACESEL returned %d, expected 2\n", r);
r = SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
@@ -4262,7 +4391,7 @@
r = SendMessage(hwndRichEdit, EM_GETLINECOUNT, 0, 0);
ok(r == 3, "EM_GETLINECOUNT returned %d, expected 3\n", r);
- SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)NULL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
r = SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)
"\n\n\n\n\r\r\r\r\n");
ok(9 == r /* WinXP */ || 7 == r /* Win98 */,
"EM_REPLACESEL returned %d, expected 9 or 7\n", r);
@@ -4305,11 +4434,15 @@
const char* text3 = "testing paste\r\npaste\r\ntesting paste";
HWND hwndRichEdit = new_richedit(NULL);
- /* Native riched20 won't obey WM_CHAR messages or WM_KEYDOWN/WM_KEYUP
- messages, probably because it inspects the keyboard state itself.
- Therefore, native requires this in order to obey Ctrl-<key> keystrokes.
+ /* Native riched20 inspects the keyboard state (e.g. GetKeyState)
+ * to test the state of the modifiers (Ctrl/Alt/Shift).
+ *
+ * Therefore Ctrl-<key> keystrokes need to be simulated with
+ * keybd_event or by using SetKeyboardState to set the modifiers
+ * and SendMessage to simulate the keystrokes.
*/
+ /* Sent keystrokes with keybd_event */
#define SEND_CTRL_C(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'C')
#define SEND_CTRL_X(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'X')
#define SEND_CTRL_V(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, 'V')
@@ -4326,13 +4459,14 @@
/* Pasted text should be visible at this step */
result = strcmp(text1_step1, buffer);
ok(result == 0,
- "test paste: strcmp = %i\n", result);
+ "test paste: strcmp = %i, text='%s'\n", result, buffer);
+
SEND_CTRL_Z(hwndRichEdit); /* Undo */
SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
/* Text should be the same as before (except for \r -> \r\n conversion) */
result = strcmp(text1_after, buffer);
ok(result == 0,
- "test paste: strcmp = %i\n", result);
+ "test paste: strcmp = %i, text='%s'\n", result, buffer);
SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text2);
SendMessage(hwndRichEdit, EM_SETSEL, 8, 13);
@@ -4357,6 +4491,87 @@
ok(result == 0,
"test paste: strcmp = %i\n", result);
+#undef SEND_CTRL_C
+#undef SEND_CTRL_X
+#undef SEND_CTRL_V
+#undef SEND_CTRL_Z
+#undef SEND_CTRL_Y
+
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
+ /* Send WM_CHAR to simulates Ctrl-V */
+ SendMessage(hwndRichEdit, WM_CHAR, 22,
+ (MapVirtualKey('V', MAPVK_VK_TO_VSC) << 16) & 1);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ /* Shouldn't paste because pasting is handled by WM_KEYDOWN */
+ result = strcmp(buffer,"");
+ ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+
+ /* Send keystrokes with WM_KEYDOWN after setting the modifiers
+ * with SetKeyboard state. */
+
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
+ /* Simulates paste (Ctrl-V) */
+ hold_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_KEYDOWN, 'V',
+ (MapVirtualKey('V', MAPVK_VK_TO_VSC) << 16) & 1);
+ release_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ result = strcmp(buffer,"paste");
+ ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1);
+ SendMessage(hwndRichEdit, EM_SETSEL, 0, 7);
+ /* Simulates copy (Ctrl-C) */
+ hold_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_KEYDOWN, 'C',
+ (MapVirtualKey('C', MAPVK_VK_TO_VSC) << 16) & 1);
+ release_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
+ SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ result = strcmp(buffer,"testing");
+ ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+
+ /* Cut with WM_KEYDOWN to simulate Ctrl-X */
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "cut");
+ /* Simulates select all (Ctrl-A) */
+ hold_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_KEYDOWN, 'A',
+ (MapVirtualKey('A', MAPVK_VK_TO_VSC) << 16) & 1);
+ /* Simulates select cut (Ctrl-X) */
+ SendMessage(hwndRichEdit, WM_KEYDOWN, 'X',
+ (MapVirtualKey('X', MAPVK_VK_TO_VSC) << 16) & 1);
+ release_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ result = strcmp(buffer,"");
+ ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, 0);
+ SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ result = strcmp(buffer,"cut\r\n");
+ todo_wine ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+ /* Simulates undo (Ctrl-Z) */
+ hold_key(VK_CONTROL);
+ SendMessage(hwndRichEdit, WM_KEYDOWN, 'Z',
+ (MapVirtualKey('Z', MAPVK_VK_TO_VSC) << 16) & 1);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ result = strcmp(buffer,"");
+ ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+ /* Simulates redo (Ctrl-Y) */
+ SendMessage(hwndRichEdit, WM_KEYDOWN, 'Y',
+ (MapVirtualKey('Y', MAPVK_VK_TO_VSC) << 16) & 1);
+ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
+ result = strcmp(buffer,"cut\r\n");
+ todo_wine ok(result == 0,
+ "test paste: strcmp = %i, actual = '%s'\n", result, buffer);
+ release_key(VK_CONTROL);
+
DestroyWindow(hwndRichEdit);
}
@@ -4379,14 +4594,14 @@
fr.chrg.cpMin = 0;
fr.chrg.cpMax = 20;
- r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) NULL);
+ r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, 0);
todo_wine {
ok(r == 31, "EM_FORMATRANGE expect %d, got %d\n", 31, r);
}
r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) &fr);
todo_wine {
- ok(r == 20, "EM_FORMATRANGE expect %d, got %d\n", 20, r);
+ ok(r == 20 || r == 9, "EM_FORMATRANGE expect 20 or 9, got %d\n", r);
}
fr.chrg.cpMin = 0;
@@ -4397,7 +4612,7 @@
ok(r == 10, "EM_FORMATRANGE expect %d, got %d\n", 10, r);
}
- r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, (LPARAM) NULL);
+ r = SendMessage(hwndRichEdit, EM_FORMATRANGE, TRUE, 0);
todo_wine {
ok(r == 31, "EM_FORMATRANGE expect %d, got %d\n", 31, r);
}
@@ -4486,26 +4701,26 @@
const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
const char * streamText1 =
-
"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0
System;}}\r\n" \
- "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n" \
+
"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang12298{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0
System;}}\r\n"
+ "\\viewkind4\\uc1\\pard\\f0\\fs17 TestSomeText\\par\r\n"
"}\r\n";
/* In richedit 2.0 mode, this should NOT be accepted, unlike 1.0 */
const char * streamText2 =
- "{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;" \
- "\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255"
\
- "\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 " \
- "\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 "
\
- "\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 "
\
- "\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 " \
+ "{{\\colortbl;\\red0\\green255\\blue102;\\red255\\green255\\blue255;"
+ "\\red170\\green255\\blue255;\\red255\\green238\\blue0;\\red51\\green255"
+ "\\blue221;\\red238\\green238\\blue238;}\\tx0 \\tx424 \\tx848 \\tx1272 "
+ "\\tx1696 \\tx2120 \\tx2544 \\tx2968 \\tx3392 \\tx3816 \\tx4240 \\tx4664 "
+ "\\tx5088 \\tx5512 \\tx5936 \\tx6360 \\tx6784 \\tx7208 \\tx7632 \\tx8056 "
+ "\\tx8480 \\tx8904 \\tx9328 \\tx9752 \\tx10176 \\tx10600 \\tx11024 "
"\\tx11448 \\tx11872 \\tx12296 \\tx12720 \\tx13144 \\cf2 RichEdit1\\line
}";
const char * streamText3 = "RichEdit1";
struct StringWithLength cookieForStream4;
const char * streamText4 =
- "This text just needs to be long enough to cause run to be split onto "\
- "two separate lines and make sure the null terminating character is "\
+ "This text just needs to be long enough to cause run to be split onto "
+ "two separate lines and make sure the null terminating character is "
"handled properly.\0";
int length4 = strlen(streamText4) + 1;
cookieForStream4.buffer = (char *)streamText4;
@@ -4698,9 +4913,7 @@
char bufA[64];
WCHAR bufW[64];
HWND hwnd;
- int is_win9x, em_settextex_supported, ret;
-
- is_win9x = GetVersion() & 0x80000000;
+ int em_settextex_supported, ret;
#define set_textA(hwnd, wm_set_text, txt) \
do { \
@@ -4933,8 +5146,12 @@
char buffer[64] = {0};
/* single line */
- hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
- 0, 0, 200, 60, 0, 0, 0, 0);
+ if (!is_win9x)
+ hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP,
+ 0, 0, 200, 60, 0, 0, 0, 0);
+ else
+ hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP,
+ 0, 0, 200, 60, 0, 0, 0, 0);
ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
@@ -4978,8 +5195,12 @@
DestroyWindow(hwnd);
/* multi line */
- hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP | ES_MULTILINE,
- 0, 0, 200, 60, 0, 0, 0, 0);
+ if (!is_win9x)
+ hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP |
ES_MULTILINE,
+ 0, 0, 200, 60, 0, 0, 0, 0);
+ else
+ hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP |
ES_MULTILINE,
+ 0, 0, 200, 60, 0, 0, 0, 0);
ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
gtl.flags = GTL_NUMCHARS | GTL_PRECISE | GTL_USECRLF;
@@ -5051,7 +5272,7 @@
static void test_eventMask(void)
{
HWND parent;
- int ret;
+ int ret, style;
WNDCLASSA cls;
const char text[] = "foo bar\n";
int eventMask;
@@ -5092,6 +5313,38 @@
ok(queriedEventMask == (eventMask & ~ENM_CHANGE),
"wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
+ /* check to see if EN_CHANGE is sent when redraw is turned off */
+ SendMessage(eventMaskEditHwnd, WM_CLEAR, 0, 0);
+ ok(IsWindowVisible(eventMaskEditHwnd), "Window should be visible.\n");
+ SendMessage(eventMaskEditHwnd, WM_SETREDRAW, FALSE, 0);
+ /* redraw is disabled by making the window invisible. */
+ ok(!IsWindowVisible(eventMaskEditHwnd), "Window shouldn't be
visible.\n");
+ queriedEventMask = 0; /* initialize to something other than we expect */
+ SendMessage(eventMaskEditHwnd, EM_REPLACESEL, 0, (LPARAM) text);
+ ok(queriedEventMask == (eventMask & ~ENM_CHANGE),
+ "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
+ SendMessage(eventMaskEditHwnd, WM_SETREDRAW, TRUE, 0);
+ ok(IsWindowVisible(eventMaskEditHwnd), "Window should be visible.\n");
+
+ /* check to see if EN_UPDATE is sent when the editor isn't visible */
+ SendMessage(eventMaskEditHwnd, WM_CLEAR, 0, 0);
+ style = GetWindowLong(eventMaskEditHwnd, GWL_STYLE);
+ SetWindowLong(eventMaskEditHwnd, GWL_STYLE, style & ~WS_VISIBLE);
+ ok(!IsWindowVisible(eventMaskEditHwnd), "Window shouldn't be
visible.\n");
+ watchForEventMask = EN_UPDATE;
+ queriedEventMask = 0; /* initialize to something other than we expect */
+ SendMessage(eventMaskEditHwnd, EM_REPLACESEL, 0, (LPARAM) text);
+ ok(queriedEventMask == 0,
+ "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
+ SetWindowLong(eventMaskEditHwnd, GWL_STYLE, style);
+ ok(IsWindowVisible(eventMaskEditHwnd), "Window should be visible.\n");
+ queriedEventMask = 0; /* initialize to something other than we expect */
+ SendMessage(eventMaskEditHwnd, EM_REPLACESEL, 0, (LPARAM) text);
+ ok(queriedEventMask == eventMask,
+ "wrong event mask (0x%x) during WM_COMMAND\n", queriedEventMask);
+
+
+ DestroyWindow(parent);
}
static int received_WM_NOTIFY = 0;
@@ -5167,6 +5420,14 @@
ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
ok(modify_at_WM_NOTIFY == 0, "WM_NOTIFY callback saw text flagged as
modified!\n");
+ /* Test for WM_NOTIFY messages with redraw disabled. */
+ SendMessage(hwndRichedit_WM_NOTIFY, EM_SETSEL, 0, 0);
+ SendMessage(hwndRichedit_WM_NOTIFY, WM_SETREDRAW, FALSE, 0);
+ received_WM_NOTIFY = 0;
+ SendMessage(hwndRichedit_WM_NOTIFY, EM_REPLACESEL, FALSE,
(LPARAM)"inserted");
+ ok(received_WM_NOTIFY == 1, "Expected WM_NOTIFY was NOT sent!\n");
+ SendMessage(hwndRichedit_WM_NOTIFY, WM_SETREDRAW, TRUE, 0);
+
DestroyWindow(hwndRichedit_WM_NOTIFY);
DestroyWindow(parent);
}
@@ -5178,8 +5439,12 @@
char buffer[64] = {0};
/* multi-line control inserts CR normally */
- hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE,
- 0, 0, 200, 60, 0, 0, 0, 0);
+ if (!is_win9x)
+ hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE,
+ 0, 0, 200, 60, 0, 0, 0, 0);
+ else
+ hwnd = CreateWindowExA(0, "RichEdit20A", NULL, WS_POPUP|ES_MULTILINE,
+ 0, 0, 200, 60, 0, 0, 0, 0);
ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
result = SendMessage(hwnd, EM_CANUNDO, 0, 0);
@@ -5221,8 +5486,8 @@
simulate_typing_characters(hwnd, "one two three");
result = SendMessage(hwnd, EM_CANREDO, 0, 0);
ok (result == FALSE, "Redo buffer should have been cleared by typing.\n");
- SendMessage(hwnd, WM_KILLFOCUS, (WPARAM)NULL, 0);
- SendMessage(hwnd, WM_SETFOCUS, (WPARAM)NULL, 0);
+ SendMessage(hwnd, WM_KILLFOCUS, 0, 0);
+ SendMessage(hwnd, WM_SETFOCUS, 0, 0);
simulate_typing_characters(hwnd, " four five six");
result = SendMessage(hwnd, EM_UNDO, 0, 0);
ok (result == TRUE, "Failed to undo typed characters.\n");
@@ -5289,6 +5554,43 @@
DestroyWindow(hwnd);
}
+static LONG CALLBACK customWordBreakProc(WCHAR *text, int pos, int bytes, int code)
+{
+ int length;
+
+ /* MSDN lied, length is actually the number of bytes. */
+ length = bytes / sizeof(WCHAR);
+ switch(code)
+ {
+ case WB_ISDELIMITER:
+ return text[pos] == 'X';
+ case WB_LEFT:
+ case WB_MOVEWORDLEFT:
+ if (customWordBreakProc(text, pos, bytes, WB_ISDELIMITER))
+ return pos-1;
+ return min(customWordBreakProc(text, pos, bytes, WB_LEFTBREAK)-1, 0);
+ case WB_LEFTBREAK:
+ pos--;
+ while (pos > 0 && !customWordBreakProc(text, pos, bytes,
WB_ISDELIMITER))
+ pos--;
+ return pos;
+ case WB_RIGHT:
+ case WB_MOVEWORDRIGHT:
+ if (customWordBreakProc(text, pos, bytes, WB_ISDELIMITER))
+ return pos+1;
+ return min(customWordBreakProc(text, pos, bytes, WB_RIGHTBREAK)+1, length);
+ case WB_RIGHTBREAK:
+ pos++;
+ while (pos < length && !customWordBreakProc(text, pos, bytes,
WB_ISDELIMITER))
+ pos++;
+ return pos;
+ default:
+ ok(FALSE, "Unexpected code %d\n", code);
+ break;
+ }
+ return 0;
+}
+
#define SEND_CTRL_LEFT(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, VK_LEFT)
#define SEND_CTRL_RIGHT(hwnd) pressKeyWithModifier(hwnd, VK_CONTROL, VK_RIGHT)
@@ -5297,6 +5599,7 @@
HWND hwnd;
int result;
int sel_start, sel_end;
+ const WCHAR textW[] = {'o','n','e','
','t','w','o','X','t','h','r','e','e',0};
/* multi-line control inserts CR normally */
hwnd = new_richedit(NULL);
@@ -5346,6 +5649,42 @@
ok(sel_start == sel_end, "Selection should be empty\n");
ok(sel_start == 9, "Cursor is at %d instead of %d\n", sel_start, 9);
+ /* Test with a custom word break procedure that uses X as the delimiter. */
+ result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"one twoXthree");
+ ok (result == TRUE, "Failed to clear the text.\n");
+ SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)customWordBreakProc);
+ /* |one twoXthree */
+ SEND_CTRL_RIGHT(hwnd);
+ /* one twoX|three */
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
+ ok(sel_start == sel_end, "Selection should be empty\n");
+ ok(sel_start == 8, "Cursor is at %d instead of %d\n", sel_start, 8);
+
+ DestroyWindow(hwnd);
+
+ /* Make sure the behaviour is the same with a unicode richedit window,
+ * and using unicode functions. */
+ if (is_win9x)
+ {
+ skip("Cannot test with unicode richedit window\n");
+ return;
+ }
+
+ hwnd = CreateWindowW(RICHEDIT_CLASS20W, NULL,
+ ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
+ 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
+
+ /* Test with a custom word break procedure that uses X as the delimiter. */
+ result = SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW);
+ ok (result == TRUE, "Failed to clear the text.\n");
+ SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)customWordBreakProc);
+ /* |one twoXthree */
+ SEND_CTRL_RIGHT(hwnd);
+ /* one twoX|three */
+ SendMessageW(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end);
+ ok(sel_start == sel_end, "Selection should be empty\n");
+ ok(sel_start == 8, "Cursor is at %d instead of %d\n", sel_start, 8);
+
DestroyWindow(hwnd);
}
@@ -5368,15 +5707,318 @@
DestroyWindow(hwnd);
}
+static void test_word_wrap(void)
+{
+ HWND hwnd;
+ POINTL point = {0, 60}; /* This point must be below the first line */
+ const char *text = "Must be long enough to test line wrapping";
+ DWORD dwCommonStyle = WS_VISIBLE|WS_POPUP|WS_VSCROLL|ES_MULTILINE;
+ int res, pos, lines;
+
+ /* Test the effect of WS_HSCROLL and ES_AUTOHSCROLL styles on wrapping
+ * when specified on window creation and set later. */
+ hwnd = CreateWindow(RICHEDIT_CLASS, NULL, dwCommonStyle,
+ 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
+ res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
+ ok(res, "WM_SETTEXT failed.\n");
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
+ lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
+ ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
+
+ SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL);
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
+ DestroyWindow(hwnd);
+
+ hwnd = CreateWindow(RICHEDIT_CLASS, NULL, dwCommonStyle|WS_HSCROLL,
+ 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
+
+ res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
+ ok(res, "WM_SETTEXT failed.\n");
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+ lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
+ ok(lines == 1, "Line wasn't expected to wrap (lines=%d).\n", lines);
+
+ SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle);
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+ DestroyWindow(hwnd);
+
+ hwnd = CreateWindow(RICHEDIT_CLASS, NULL, dwCommonStyle|ES_AUTOHSCROLL,
+ 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
+ res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
+ ok(res, "WM_SETTEXT failed.\n");
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+
+ SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle);
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+ DestroyWindow(hwnd);
+
+ hwnd = CreateWindow(RICHEDIT_CLASS, NULL,
+ dwCommonStyle|WS_HSCROLL|ES_AUTOHSCROLL,
+ 0, 0, 200, 80, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
+ res = SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) text);
+ ok(res, "WM_SETTEXT failed.\n");
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+
+ SetWindowLongW(hwnd, GWL_STYLE, dwCommonStyle);
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+
+ /* Test the effect of EM_SETTARGETDEVICE on word wrap. */
+ res = SendMessage(hwnd, EM_SETTARGETDEVICE, 0, 1);
+ todo_wine ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(!pos, "pos=%d indicating word wrap when none is expected.\n", pos);
+
+ res = SendMessage(hwnd, EM_SETTARGETDEVICE, 0, 0);
+ todo_wine ok(res, "EM_SETTARGETDEVICE failed (returned %d).\n", res);
+ pos = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM) &point);
+ ok(pos, "pos=%d indicating no word wrap when it is expected.\n", pos);
+ DestroyWindow(hwnd);
+
+ /* Test to see if wrapping happens with redraw disabled. */
+ hwnd = CreateWindow(RICHEDIT_CLASS, NULL, dwCommonStyle,
+ 0, 0, 400, 80, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "error: %d\n", (int) GetLastError());
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ res = SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) text);
+ ok(res, "EM_REPLACESEL failed.\n");
+ lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
+ ok(lines == 1, "Line wasn't expected to wrap (lines=%d).\n", lines);
+ MoveWindow(hwnd, 0, 0, 200, 80, FALSE);
+ lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
+ ok(lines > 1, "Line was expected to wrap (lines=%d).\n", lines);
+
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ DestroyWindow(hwnd);
+}
+
+static void test_auto_yscroll(void)
+{
+ HWND hwnd = new_richedit(NULL);
+ int lines, ret, redraw;
+ POINT pt;
+
+ for (redraw = 0; redraw <= 1; redraw++) {
+ trace("testing with WM_SETREDRAW=%d\n", redraw);
+ SendMessage(hwnd, WM_SETREDRAW, redraw, 0);
+ SendMessage(hwnd, EM_REPLACESEL, 0, (LPARAM)"1\n2\n3\n4\n5\n6\n7\n8");
+ lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
+ ok(lines == 8, "%d lines instead of 8\n", lines);
+ ret = SendMessage(hwnd, EM_GETSCROLLPOS, 0, (LPARAM)&pt);
+ ok(ret == 1, "EM_GETSCROLLPOS returned %d instead of 1\n", ret);
+ ok(pt.y != 0, "Didn't scroll down after replacing text.\n");
+ ret = GetWindowLong(hwnd, GWL_STYLE);
+ ok(ret & WS_VSCROLL, "Scrollbar was not shown yet (style=%x).\n",
(UINT)ret);
+
+ SendMessage(hwnd, WM_SETTEXT, 0, 0);
+ lines = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
+ ok(lines == 1, "%d lines instead of 1\n", lines);
+ ret = SendMessage(hwnd, EM_GETSCROLLPOS, 0, (LPARAM)&pt);
+ ok(ret == 1, "EM_GETSCROLLPOS returned %d instead of 1\n", ret);
+ ok(pt.y == 0, "y scroll position is %d after clearing text.\n", pt.y);
+ ret = GetWindowLong(hwnd, GWL_STYLE);
+ ok(!(ret & WS_VSCROLL), "Scrollbar is still shown (style=%x).\n",
(UINT)ret);
+ }
+
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ DestroyWindow(hwnd);
+}
+
+
+static void test_format_rect(void)
+{
+ HWND hwnd;
+ RECT rc, expected, clientRect;
+ int n;
+ DWORD options;
+
+ hwnd = CreateWindowEx(0, RICHEDIT_CLASS, NULL,
+ ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
+ 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int)
GetLastError());
+
+ GetClientRect(hwnd, &clientRect);
+
+ expected = clientRect;
+ expected.left += 1;
+ expected.right -= 1;
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ for (n = -3; n <= 3; n++)
+ {
+ rc = clientRect;
+ rc.top += n;
+ rc.left += n;
+ rc.bottom -= n;
+ rc.right -= n;
+ SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
+
+ expected = rc;
+ expected.top = max(0, rc.top);
+ expected.left = max(0, rc.left);
+ expected.bottom = min(clientRect.bottom, rc.bottom);
+ expected.right = min(clientRect.right, rc.right);
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "[n=%d] rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d,
r=%d)\n",
+ n, rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+ }
+
+ rc = clientRect;
+ SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
+ expected = clientRect;
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ /* Adding the selectionbar adds the selectionbar width to the left side. */
+ SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR);
+ options = SendMessageA(hwnd, EM_GETOPTIONS, 0, 0);
+ ok(options & ECO_SELECTIONBAR, "EM_SETOPTIONS failed to add
selectionbar.\n");
+ expected.left += 8; /* selection bar width */
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ rc = clientRect;
+ SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
+ expected = clientRect;
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ /* Removing the selectionbar subtracts the selectionbar width from the left side,
+ * even if the left side is already 0. */
+ SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_AND, ~ECO_SELECTIONBAR);
+ options = SendMessageA(hwnd, EM_GETOPTIONS, 0, 0);
+ ok(!(options & ECO_SELECTIONBAR), "EM_SETOPTIONS failed to remove
selectionbar.\n");
+ expected.left -= 8; /* selection bar width */
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ /* Set the absolute value of the formatting rectangle. */
+ rc = clientRect;
+ SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
+ expected = clientRect;
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "[n=%d] rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ n, rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ /* MSDN documents the EM_SETRECT message as using the rectangle provided in
+ * LPARAM as being a relative offset when the WPARAM value is 1, but these
+ * tests show that this isn't true. */
+ rc.top = 15;
+ rc.left = 15;
+ rc.bottom = clientRect.bottom - 15;
+ rc.right = clientRect.right - 15;
+ expected = rc;
+ SendMessageA(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ /* For some reason it does not limit the values to the client rect with
+ * a WPARAM value of 1. */
+ rc.top = -15;
+ rc.left = -15;
+ rc.bottom = clientRect.bottom + 15;
+ rc.right = clientRect.right + 15;
+ expected = rc;
+ SendMessageA(hwnd, EM_SETRECT, 1, (LPARAM)&rc);
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ DestroyWindow(hwnd);
+
+ /* The extended window style affects the formatting rectangle. */
+ hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, NULL,
+ ES_MULTILINE|WS_POPUP|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE,
+ 0, 0, 200, 60, NULL, NULL, hmoduleRichEdit, NULL);
+ ok(hwnd != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS, (int)
GetLastError());
+
+ GetClientRect(hwnd, &clientRect);
+
+ expected = clientRect;
+ expected.left += 1;
+ expected.top += 1;
+ expected.right -= 1;
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ rc = clientRect;
+ rc.top += 5;
+ rc.left += 5;
+ rc.bottom -= 5;
+ rc.right -= 5;
+ expected = rc;
+ expected.top -= 1;
+ expected.left -= 1;
+ expected.right += 1;
+ SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
+ SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc);
+ ok(rc.top == expected.top && rc.left == expected.left &&
+ rc.bottom == expected.bottom && rc.right == expected.right,
+ "rect a(t=%d, l=%d, b=%d, r=%d) != e(t=%d, l=%d, b=%d, r=%d)\n",
+ rc.top, rc.left, rc.bottom, rc.right,
+ expected.top, expected.left, expected.bottom, expected.right);
+
+ DestroyWindow(hwnd);
+}
+
START_TEST( editor )
{
- MSG msg;
- time_t end;
-
/* Must explicitly LoadLibrary(). The test has no references to functions in
* RICHED20.DLL, so the linker doesn't actually link to it. */
hmoduleRichEdit = LoadLibrary("RICHED20.DLL");
ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
+
+ is_win9x = GetVersion() & 0x80000000;
+
test_WM_CHAR();
test_EM_FINDTEXT();
test_EM_GETLINE();
@@ -5418,22 +6060,15 @@
test_word_movement();
test_EM_CHARFROMPOS();
test_SETPARAFORMAT();
+ test_word_wrap();
+ test_auto_yscroll();
+ test_format_rect();
/* Set the environment variable WINETEST_RICHED20 to keep windows
* responsive and open for 30 seconds. This is useful for debugging.
- *
- * The message pump uses PeekMessage() to empty the queue and then sleeps for
- * 50ms before retrying the queue. */
- end = time(NULL) + 30;
+ */
if (getenv( "WINETEST_RICHED20" )) {
- while (time(NULL) < end) {
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- } else {
- Sleep(50);
- }
- }
+ keep_responsive(30);
}
OleFlushClipboard();
Modified: trunk/rostests/winetests/riched20/riched20.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/riched20/riched…
==============================================================================
--- trunk/rostests/winetests/riched20/riched20.rbuild [iso-8859-1] (original)
+++ trunk/rostests/winetests/riched20/riched20.rbuild [iso-8859-1] Mon Dec 29 02:27:52
2008
@@ -7,6 +7,7 @@
<file>editor.c</file>
<file>richole.c</file>
<file>testlist.c</file>
+ <file>txtsrv.c</file>
<library>wine</library>
<library>uuid</library>
<library>ole32</library>
Modified: trunk/rostests/winetests/riched20/testlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/riched20/testli…
==============================================================================
--- trunk/rostests/winetests/riched20/testlist.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/riched20/testlist.c [iso-8859-1] Mon Dec 29 02:27:52 2008
@@ -6,8 +6,12 @@
#define STANDALONE
#include "wine/test.h"
+extern void func_editor(void);
+extern void func_txtsrv(void);
const struct test winetest_testlist[] =
{
+ { "editor", func_editor },
+ { "txtsrv", func_txtsrv },
{ 0, 0 }
};
Added: trunk/rostests/winetests/riched20/txtsrv.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/riched20/txtsrv…
==============================================================================
--- trunk/rostests/winetests/riched20/txtsrv.c (added)
+++ trunk/rostests/winetests/riched20/txtsrv.c [iso-8859-1] Mon Dec 29 02:27:52 2008
@@ -1,0 +1,662 @@
+/*
+ * Unit test suite for windowless rich edit controls
+ *
+ * Copyright 2008 Maarten Lankhorst
+ * Copyright 2008 Austin Lund
+ * Copyright 2008 Dylan Smith
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <windef.h>
+#include <winbase.h>
+#include <objbase.h>
+#include <richedit.h>
+#include <initguid.h>
+#include <textserv.h>
+#include <wine/test.h>
+
+static HMODULE hmoduleRichEdit;
+
+/* Define C Macros for ITextServices calls. */
+
+/* Use a special table for x86 machines to convert the thiscall
+ * calling convention. This isn't needed on other platforms. */
+#ifdef __i386__
+#define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl)
+#else /* __i386__ */
+#define TXTSERV_VTABLE(This) (This)->lpVtbl
+#endif /* __i386__ */
+
+#define ITextServices_TxSendMessage(This,a,b,c,d)
TXTSERV_VTABLE(This)->TxSendMessage(This,a,b,c,d)
+#define ITextServices_TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l)
TXTSERV_VTABLE(This)->TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l)
+#define ITextServices_TxGetHScroll(This,a,b,c,d,e)
TXTSERV_VTABLE(This)->TxGetHScroll(This,a,b,c,d,e)
+#define ITextServices_TxGetVScroll(This,a,b,c,d,e)
TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e)
+#define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i)
TXTSERV_VTABLE(This)->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i)
+#define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j)
TXTSERV_VTABLE(This)->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j)
+#define ITextServices_OnTxInplaceActivate(This,a)
TXTSERV_VTABLE(This)->OnTxInplaceActivate(This,a)
+#define ITextServices_OnTxInplaceDeactivate(This)
TXTSERV_VTABLE(This)->OnTxInplaceDeactivate(This)
+#define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This)
+#define ITextServices_OnTxUIDeactivate(This)
TXTSERV_VTABLE(This)->OnTxUIDeactivate(This)
+#define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a)
+#define ITextServices_TxSetText(This,a) TXTSERV_VTABLE(This)->TxSetText(This,a)
+#define ITextServices_TxGetCurrentTargetX(This,a)
TXTSERV_VTABLE(This)->TxGetCurrentTargetX(This,a)
+#define ITextServices_TxGetBaseLinePos(This,a)
TXTSERV_VTABLE(This)->TxGetBaseLinePos(This,a)
+#define ITextServices_TxGetNaturalSize(This,a,b,c,d,e,f,g,h)
TXTSERV_VTABLE(This)->TxGetNaturalSize(This,a,b,c,d,e,f,g,h)
+#define ITextServices_TxGetDropTarget(This,a)
TXTSERV_VTABLE(This)->TxGetDropTarget(This,a)
+#define ITextServices_OnTxPropertyBitsChange(This,a,b)
TXTSERV_VTABLE(This)->OnTxPropertyBitsChange(This,a,b)
+#define ITextServices_TxGetCachedSize(This,a,b)
TXTSERV_VTABLE(This)->TxGetCachedSize(This,a,b)
+
+/* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
+ * function call traces of ITextHost. */
+#define TRACECALL if(winetest_debug > 1) trace
+
+/************************************************************************/
+/* ITextHost implementation for conformance testing. */
+
+typedef struct ITextHostTestImpl
+{
+ ITextHostVtbl *lpVtbl;
+ LONG refCount;
+} ITextHostTestImpl;
+
+static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface,
+ REFIID riid,
+ LPVOID *ppvObject)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ITextHost)) {
+ *ppvObject = This;
+ ITextHost_AddRef((ITextHost *)*ppvObject);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ITextHostImpl_AddRef(ITextHost *iface)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ ULONG refCount = InterlockedIncrement(&This->refCount);
+ return refCount;
+}
+
+static ULONG WINAPI ITextHostImpl_Release(ITextHost *iface)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ ULONG refCount = InterlockedDecrement(&This->refCount);
+
+ if (!refCount)
+ {
+ CoTaskMemFree(This);
+ return 0;
+ } else {
+ return refCount;
+ }
+}
+
+static HDC WINAPI ITextHostImpl_TxGetDC(ITextHost *iface)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetDC(%p)\n", This);
+ return NULL;
+}
+
+static INT WINAPI ITextHostImpl_TxReleaseDC(ITextHost *iface,
+ HDC hdc)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxReleaseDC(%p)\n", This);
+ return 0;
+}
+
+static BOOL WINAPI ITextHostImpl_TxShowScrollBar(ITextHost *iface,
+ INT fnBar,
+ BOOL fShow)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxShowScrollBar(%p, fnBar=%d, fShow=%d)\n",
+ This, fnBar, fShow);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxEnableScrollBar(ITextHost *iface,
+ INT fuSBFlags,
+ INT fuArrowflags)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxEnableScrollBar(%p, fuSBFlags=%d,
fuArrowflags=%d)\n",
+ This, fuSBFlags, fuArrowflags);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxSetScrollRange(ITextHost *iface,
+ INT fnBar,
+ LONG nMinPos,
+ INT nMaxPos,
+ BOOL fRedraw)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetScrollRange(%p, fnBar=%d, nMinPos=%d, nMaxPos=%d,
fRedraw=%d)\n",
+ This, fnBar, nMinPos, nMaxPos, fRedraw);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxSetScrollPos(ITextHost *iface,
+ INT fnBar,
+ INT nPos,
+ BOOL fRedraw)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetScrollPos(%p, fnBar=%d, nPos=%d, fRedraw=%d)\n",
+ This, fnBar, nPos, fRedraw);
+ return FALSE;
+}
+
+static void WINAPI ITextHostImpl_TxInvalidateRect(ITextHost *iface,
+ LPCRECT prc,
+ BOOL fMode)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxInvalidateRect(%p, prc=%p, fMode=%d)\n",
+ This, prc, fMode);
+}
+
+static void WINAPI ITextHostImpl_TxViewChange(ITextHost *iface, BOOL fUpdate)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxViewChange(%p, fUpdate=%d)\n",
+ This, fUpdate);
+}
+
+static BOOL WINAPI ITextHostImpl_TxCreateCaret(ITextHost *iface,
+ HBITMAP hbmp,
+ INT xWidth, INT yHeight)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxCreateCaret(%p, nbmp=%p, xWidth=%d, yHeight=%d)\n",
+ This, hbmp, xWidth, yHeight);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxShowCaret(ITextHost *iface, BOOL fShow)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxShowCaret(%p, fShow=%d)\n",
+ This, fShow);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxSetCaretPos(ITextHost *iface,
+ INT x, INT y)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetCaretPos(%p, x=%d, y=%d)\n", This, x, y);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxSetTimer(ITextHost *iface,
+ UINT idTimer, UINT uTimeout)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetTimer(%p, idTimer=%u, uTimeout=%u)\n",
+ This, idTimer, uTimeout);
+ return FALSE;
+}
+
+static void WINAPI ITextHostImpl_TxKillTimer(ITextHost *iface, UINT idTimer)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxKillTimer(%p, idTimer=%u)\n", This, idTimer);
+}
+
+static void WINAPI ITextHostImpl_TxScrollWindowEx(ITextHost *iface,
+ INT dx, INT dy,
+ LPCRECT lprcScroll,
+ LPCRECT lprcClip,
+ HRGN hRgnUpdate,
+ LPRECT lprcUpdate,
+ UINT fuScroll)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxScrollWindowEx(%p, %d, %d, %p, %p, %p, %p, %d)\n",
+ This, dx, dy, lprcScroll, lprcClip, hRgnUpdate, lprcUpdate, fuScroll);
+}
+
+static void WINAPI ITextHostImpl_TxSetCapture(ITextHost *iface, BOOL fCapture)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetCapture(%p, fCapture=%d)\n", This, fCapture);
+}
+
+static void WINAPI ITextHostImpl_TxSetFocus(ITextHost *iface)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetFocus(%p)\n", This);
+}
+
+static void WINAPI ITextHostImpl_TxSetCursor(ITextHost *iface,
+ HCURSOR hcur,
+ BOOL fText)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxSetCursor(%p, hcur=%p, fText=%d)\n",
+ This, hcur, fText);
+}
+
+static BOOL WINAPI ITextHostImpl_TxScreenToClient(ITextHost *iface,
+ LPPOINT lppt)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxScreenToClient(%p, lppt=%p)\n", This, lppt);
+ return FALSE;
+}
+
+static BOOL WINAPI ITextHostImpl_TxClientToScreen(ITextHost *iface,
+ LPPOINT lppt)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxClientToScreen(%p, lppt=%p)\n", This, lppt);
+ return FALSE;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxActivate(ITextHost *iface,
+ LONG *plOldState)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxActivate(%p, plOldState=%p)\n", This, plOldState);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxDeactivate(ITextHost *iface,
+ LONG lNewState)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxDeactivate(%p, lNewState=%d)\n", This, lNewState);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetClientRect(ITextHost *iface,
+ LPRECT prc)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetClientRect(%p, prc=%p)\n", This, prc);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetViewInset(ITextHost *iface,
+ LPRECT prc)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetViewInset(%p, prc=%p)\n", This, prc);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetCharFormat(ITextHost *iface,
+ const CHARFORMATW **ppCF)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetCharFormat(%p, ppCF=%p)\n", This, ppCF);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetParaFormat(ITextHost *iface,
+ const PARAFORMAT **ppPF)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetParaFormat(%p, ppPF=%p)\n", This, ppPF);
+ return E_NOTIMPL;
+}
+
+static COLORREF WINAPI ITextHostImpl_TxGetSysColor(ITextHost *iface,
+ int nIndex)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetSysColor(%p, nIndex=%d)\n", This, nIndex);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetBackStyle(ITextHost *iface,
+ TXTBACKSTYLE *pStyle)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetBackStyle(%p, pStyle=%p)\n", This, pStyle);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetMaxLength(ITextHost *iface,
+ DWORD *pLength)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetMaxLength(%p, pLength=%p)\n", This, pLength);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetScrollBars(ITextHost *iface,
+ DWORD *pdwScrollBar)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetScrollBars(%p, pdwScrollBar=%p)\n",
+ This, pdwScrollBar);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetPasswordChar(ITextHost *iface,
+ WCHAR *pch)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetPasswordChar(%p, pch=%p)\n", This, pch);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetAcceleratorPos(ITextHost *iface,
+ LONG *pch)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetAcceleratorPos(%p, pch=%p)\n", This, pch);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetExtent(ITextHost *iface,
+ LPSIZEL lpExtent)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetExtent(%p, lpExtent=%p)\n", This, lpExtent);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_OnTxCharFormatChange(ITextHost *iface,
+ const CHARFORMATW *pcf)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to OnTxCharFormatChange(%p, pcf=%p)\n", This, pcf);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextHostImpl_OnTxParaFormatChange(ITextHost *iface,
+ const PARAFORMAT *ppf)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to OnTxParaFormatChange(%p, ppf=%p)\n", This, ppf);
+ return E_NOTIMPL;
+}
+
+/* This must return S_OK for the native ITextServices object to
+ initialize. */
+static HRESULT WINAPI ITextHostImpl_TxGetPropertyBits(ITextHost *iface,
+ DWORD dwMask,
+ DWORD *pdwBits)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetPropertyBits(%p, dwMask=0x%08x, pdwBits=%p)\n",
+ This, dwMask, pdwBits);
+ *pdwBits = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, DWORD iNotify,
+ void *pv)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This, iNotify, pv);
+ return E_NOTIMPL;
+}
+
+static HIMC WINAPI ITextHostImpl_TxImmGetContext(ITextHost *iface)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxImmGetContext(%p)\n", This);
+ return 0;
+}
+
+static void WINAPI ITextHostImpl_TxImmReleaseContext(ITextHost *iface, HIMC himc)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxImmReleaseContext(%p, himc=%p)\n", This, himc);
+}
+
+static HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface,
+ LONG *lSelBarWidth)
+{
+ ITextHostTestImpl *This = (ITextHostTestImpl *)iface;
+ TRACECALL("Call to TxGetSelectionBarWidth(%p, lSelBarWidth=%p)\n",
+ This, lSelBarWidth);
+ return E_NOTIMPL;
+}
+
+static ITextServicesVtbl itextServicesStdcallVtbl;
+
+static ITextHostVtbl itextHostVtbl = {
+ ITextHostImpl_QueryInterface,
+ ITextHostImpl_AddRef,
+ ITextHostImpl_Release,
+ ITextHostImpl_TxGetDC,
+ ITextHostImpl_TxReleaseDC,
+ ITextHostImpl_TxShowScrollBar,
+ ITextHostImpl_TxEnableScrollBar,
+ ITextHostImpl_TxSetScrollRange,
+ ITextHostImpl_TxSetScrollPos,
+ ITextHostImpl_TxInvalidateRect,
+ ITextHostImpl_TxViewChange,
+ ITextHostImpl_TxCreateCaret,
+ ITextHostImpl_TxShowCaret,
+ ITextHostImpl_TxSetCaretPos,
+ ITextHostImpl_TxSetTimer,
+ ITextHostImpl_TxKillTimer,
+ ITextHostImpl_TxScrollWindowEx,
+ ITextHostImpl_TxSetCapture,
+ ITextHostImpl_TxSetFocus,
+ ITextHostImpl_TxSetCursor,
+ ITextHostImpl_TxScreenToClient,
+ ITextHostImpl_TxClientToScreen,
+ ITextHostImpl_TxActivate,
+ ITextHostImpl_TxDeactivate,
+ ITextHostImpl_TxGetClientRect,
+ ITextHostImpl_TxGetViewInset,
+ ITextHostImpl_TxGetCharFormat,
+ ITextHostImpl_TxGetParaFormat,
+ ITextHostImpl_TxGetSysColor,
+ ITextHostImpl_TxGetBackStyle,
+ ITextHostImpl_TxGetMaxLength,
+ ITextHostImpl_TxGetScrollBars,
+ ITextHostImpl_TxGetPasswordChar,
+ ITextHostImpl_TxGetAcceleratorPos,
+ ITextHostImpl_TxGetExtent,
+ ITextHostImpl_OnTxCharFormatChange,
+ ITextHostImpl_OnTxParaFormatChange,
+ ITextHostImpl_TxGetPropertyBits,
+ ITextHostImpl_TxNotify,
+ ITextHostImpl_TxImmGetContext,
+ ITextHostImpl_TxImmReleaseContext,
+ ITextHostImpl_TxGetSelectionBarWidth
+};
+
+static ITextServices *txtserv = NULL;
+static ITextHostTestImpl *dummyTextHost;
+static void *wrapperCodeMem = NULL;
+
+#include "pshpack1.h"
+
+/* Code structure for x86 byte code */
+typedef struct
+{
+ BYTE pop_eax; /* popl %eax */
+ BYTE push_ecx; /* pushl %ecx */
+ BYTE push_eax; /* pushl %eax */
+ BYTE jmp_func; /* jmp $func */
+ DWORD func;
+} THISCALL_TO_STDCALL_THUNK;
+
+typedef struct
+{
+ BYTE pop_eax; /* popl %eax */
+ BYTE pop_ecx; /* popl %ecx */
+ BYTE push_eax; /* pushl %eax */
+ BYTE mov_vtable_eax[2]; /* movl (%ecx), %eax */
+ BYTE jmp_eax[2]; /* jmp *$vtablefunc_offset(%eax) */
+ int vtablefunc_offset;
+} STDCALL_TO_THISCALL_THUNK;
+
+#include "poppack.h"
+
+static void setup_thiscall_wrappers(void)
+{
+#ifdef __i386__
+ void** pVtable;
+ void** pVtableEnd;
+ THISCALL_TO_STDCALL_THUNK *thunk;
+ STDCALL_TO_THISCALL_THUNK *thunk2;
+
+ wrapperCodeMem = VirtualAlloc(NULL,
+ (sizeof(ITextHostVtbl)/sizeof(void*) - 3)
+ * sizeof(THISCALL_TO_STDCALL_THUNK)
+ +(sizeof(ITextServicesVtbl)/sizeof(void*) - 3)
+ * sizeof(STDCALL_TO_THISCALL_THUNK),
+ MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ thunk = wrapperCodeMem;
+
+ /* Wrap all ITextHostImpl methods with code to perform a thiscall to
+ * stdcall conversion. The thiscall calling convention places the This
+ * pointer in ecx on the x86 platform, and the stdcall calling convention
+ * pushes the This pointer on the stack as the first argument.
+ *
+ * The byte code does the conversion then jumps to the real function.
+ *
+ * Each wrapper needs to be modified so that the function to jump to is
+ * modified in the byte code. */
+
+ /* Skip QueryInterface, AddRef, and Release native actually
+ * defined them with the stdcall calling convention. */
+ pVtable = (void**)&itextHostVtbl + 3;
+ pVtableEnd = (void**)(&itextHostVtbl + 1);
+ while (pVtable != pVtableEnd) {
+ /* write byte code to executable memory */
+ thunk->pop_eax = 0x58; /* popl %eax */
+ thunk->push_ecx = 0x51; /* pushl %ecx */
+ thunk->push_eax = 0x50; /* pushl %eax */
+ thunk->jmp_func = 0xe9; /* jmp $func */
+ /* The address needs to be relative to the end of the jump instructions. */
+ thunk->func = (char*)*pVtable - (char*)(&thunk->func + 1);
+ *pVtable = thunk;
+ pVtable++;
+ thunk++;
+ }
+
+ /* Setup an ITextServices standard call vtable that will call the
+ * native thiscall vtable when the methods are called. */
+
+ /* QueryInterface, AddRef, and Release should be called directly on the
+ * real vtable since they use the stdcall calling convention. */
+ thunk2 = (STDCALL_TO_THISCALL_THUNK *)thunk;
+ pVtable = (void**)&itextServicesStdcallVtbl + 3;
+ pVtableEnd = (void**)(&itextServicesStdcallVtbl + 1);
+ while (pVtable != pVtableEnd) {
+ /* write byte code to executable memory */
+ thunk2->pop_eax = 0x58; /* popl %eax */
+ thunk2->pop_ecx = 0x59; /* popl %ecx */
+ thunk2->push_eax = 0x50; /* pushl %eax */
+ thunk2->mov_vtable_eax[0] = 0x8b; /* movl (%ecx), %eax */
+ thunk2->mov_vtable_eax[1] = 0x01;
+ thunk2->jmp_eax[0] = 0xff; /* jmp *$vtablefunc_offset(%eax) */
+ thunk2->jmp_eax[1] = 0xa0;
+ thunk2->vtablefunc_offset = (char*)pVtable -
(char*)&itextServicesStdcallVtbl;
+ *pVtable = thunk2;
+ pVtable++;
+ thunk2++;
+ }
+#endif /* __i386__ */
+}
+
+/*************************************************************************/
+/* Conformance test functions. */
+
+/* Initialize the test texthost structure */
+static BOOL init_texthost(void)
+{
+ IUnknown *init;
+ HRESULT result;
+ PCreateTextServices pCreateTextServices;
+
+ dummyTextHost = CoTaskMemAlloc(sizeof(*dummyTextHost));
+ if (dummyTextHost == NULL) {
+ skip("Insufficient memory to create ITextHost interface\n");
+ return FALSE;
+ }
+ dummyTextHost->lpVtbl = &itextHostVtbl;
+ dummyTextHost->refCount = 1;
+
+ /* MSDN states that an IUnknown object is returned by
+ CreateTextServices which is then queried to obtain a
+ ITextServices object. */
+ pCreateTextServices = (void*)GetProcAddress(hmoduleRichEdit,
"CreateTextServices");
+ result = (*pCreateTextServices)(NULL,(ITextHost*)dummyTextHost, &init);
+ ok(result == S_OK, "Did not return OK when created. Returned %x\n",
result);
+ if (result != S_OK) {
+ CoTaskMemFree(dummyTextHost);
+ skip("CreateTextServices failed.\n");
+ return FALSE;
+ }
+
+ result = IUnknown_QueryInterface(init, &IID_ITextServices,
+ (void **)&txtserv);
+ ok((result == S_OK) && (txtserv != NULL), "Querying interface
failed\n");
+ IUnknown_Release(init);
+ if (!((result == S_OK) && (txtserv != NULL))) {
+ CoTaskMemFree(dummyTextHost);
+ skip("Could not retrieve ITextServices interface\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void test_TxGetText(void)
+{
+ HRESULT hres;
+ BSTR rettext;
+
+ if (!init_texthost())
+ return;
+
+ hres = ITextServices_TxGetText(txtserv, &rettext);
+ todo_wine ok(hres == S_OK, "ITextServices_TxGetText failed\n");
+
+ IUnknown_Release(txtserv);
+ CoTaskMemFree(dummyTextHost);
+}
+
+START_TEST( txtsrv )
+{
+ setup_thiscall_wrappers();
+
+ /* Must explicitly LoadLibrary(). The test has no references to functions in
+ * RICHED20.DLL, so the linker doesn't actually link to it. */
+ hmoduleRichEdit = LoadLibrary("RICHED20.DLL");
+ ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
+
+ if (init_texthost())
+ {
+ IUnknown_Release(txtserv);
+ CoTaskMemFree(dummyTextHost);
+
+ test_TxGetText();
+ }
+ if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE);
+}
Propchange: trunk/rostests/winetests/riched20/txtsrv.c
------------------------------------------------------------------------------
svn:eol-style = native