POINTL pt;
LOCALESIGNATURE sig;
BOOL rtl;
+ PARAFORMAT2 fmt;
static const char text[] = "aa\n"
"this is a long line of text that should be longer than the "
"control's width\n"
SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, -1);
ok(pt.x == 1, "pt.x = %d\n", pt.x);
+ /* test negative indentation */
+ SendMessageA(hwndRichEdit, WM_SETTEXT, 0,
+ (LPARAM)"{\\rtf1\\pard\\fi-200\\li-200\\f1 TestSomeText\\par}");
+ SendMessageA(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, 0);
+ ok(pt.x == 1, "pt.x = %d\n", pt.x);
+
+ fmt.cbSize = sizeof(fmt);
+ SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
+ ok(fmt.dxStartIndent == -400, "got %d\n", fmt.dxStartIndent);
+ ok(fmt.dxOffset == 200, "got %d\n", fmt.dxOffset);
+ ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment);
+
DestroyWindow(hwndRichEdit);
}
{
HWND hwndRichEdit = new_richedit(NULL);
CHARFORMAT2A cf2;
+ CHARFORMAT2W cfW;
int rc = 0;
int tested_effects[] = {
CFE_BOLD,
CHARRANGE cr;
LOCALESIGNATURE sig;
BOOL rtl;
+ DWORD expect_effects;
rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE,
(LPSTR) &sig, sizeof(LOCALESIGNATURE)) &&
(sig.lsUsb[3] & 0x08000000) != 0);
+ /* check charformat defaults */
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok(cf2.dwMask == CFM_ALL2, "got %08x\n", cf2.dwMask);
+ expect_effects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
+ if (cf2.wWeight > 550) expect_effects |= CFE_BOLD;
+ ok(cf2.dwEffects == expect_effects, "got %08x\n", cf2.dwEffects);
+ ok(cf2.yOffset == 0, "got %d\n", cf2.yOffset);
+ ok(cf2.sSpacing == 0, "got %d\n", cf2.sSpacing);
+ ok(cf2.lcid == GetSystemDefaultLCID(), "got %x\n", cf2.lcid);
+ ok(cf2.sStyle == 0, "got %d\n", cf2.sStyle);
+ ok(cf2.wKerning == 0, "got %d\n", cf2.wKerning);
+ ok(cf2.bAnimation == 0, "got %d\n", cf2.bAnimation);
+ ok(cf2.bRevAuthor == 0, "got %d\n", cf2.bRevAuthor);
+
/* Invalid flags, CHARFORMAT2 structure blanked out */
memset(&cf2, 0, sizeof(cf2));
rc = SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM)0xfffffff0, (LPARAM)&cf2);
/* Set two effects on an empty selection */
SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
+ /* first clear bold, italic */
+ SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ cf2.dwMask = CFM_BOLD | CFM_ITALIC;
+ cf2.dwEffects = 0;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
memset(&cf2, 0, sizeof(CHARFORMAT2A));
/* Setting the (empty) selection to exactly the same place as before should
NOT clear the insertion style! */
SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
+ /* first clear bold, italic */
+ SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ cf2.dwMask = CFM_BOLD | CFM_ITALIC;
+ cf2.dwEffects = 0;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
memset(&cf2, 0, sizeof(CHARFORMAT2A));
ok((cf2.dwEffects & CFE_BOLD) == CFE_BOLD,
"%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
+ /* Moving the selection will clear the insertion style */
+ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
+ /* first clear bold, italic */
+ SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ cf2.dwMask = CFM_BOLD | CFM_ITALIC;
+ cf2.dwEffects = 0;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
+ SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
+
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ cf2.dwMask = CFM_BOLD;
+ cf2.dwEffects = CFE_BOLD;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
+ /* Move selection and then put it back, insert style should be forgotten here. */
+ SendMessageA(hwndRichEdit, EM_SETSEL, 3, 3);
+ SendMessageA(hwndRichEdit, EM_SETSEL, 2, 2); /* Empty selection */
+
+ /* Selection is now nonempty */
+ SendMessageA(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"newi");
+
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_SETSEL, 2, 6);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
+ ok(((cf2.dwMask & CFM_BOLD) == CFM_BOLD),
+ "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, CFM_BOLD);
+ ok((cf2.dwEffects & CFE_BOLD) == 0,
+ "%d, cf2.dwEffects == 0x%08x not expecting effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
+
/* Ditto with EM_EXSETSEL */
SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine");
+ /* first clear bold, italic */
+ SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ cf2.dwMask = CFM_BOLD | CFM_ITALIC;
+ cf2.dwEffects = 0;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
cr.cpMin = 2; cr.cpMax = 2;
SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr); /* Empty selection */
ok((cf2.dwEffects & CFE_BOLD) == CFE_BOLD,
"%d, cf2.dwEffects == 0x%08x expected effect 0x%08x\n", i, cf2.dwEffects, CFE_BOLD);
+ /* show that wWeight is at the correct offset in CHARFORMAT2A */
+ memset(&cf2, 0, sizeof(cf2));
+ cf2.cbSize = sizeof(cf2);
+ cf2.dwMask = CFM_WEIGHT;
+ cf2.wWeight = 100;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(cf2));
+ cf2.cbSize = sizeof(cf2);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok(cf2.wWeight == 100, "got %d\n", cf2.wWeight);
+
+ memset(&cf2, 0, sizeof(cf2));
+ cf2.cbSize = sizeof(cf2);
+ cf2.dwMask = CFM_SPACING;
+ cf2.sSpacing = 10;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(cf2));
+ cf2.cbSize = sizeof(cf2);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok(cf2.sSpacing == 10, "got %d\n", cf2.sSpacing);
+
+ /* show that wWeight is at the correct offset in CHARFORMAT2W */
+ memset(&cfW, 0, sizeof(cfW));
+ cfW.cbSize = sizeof(cfW);
+ cfW.dwMask = CFM_WEIGHT;
+ cfW.wWeight = 100;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
+ memset(&cfW, 0, sizeof(cfW));
+ cfW.cbSize = sizeof(cfW);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
+ ok(cfW.wWeight == 100, "got %d\n", cfW.wWeight);
+
+ memset(&cfW, 0, sizeof(cfW));
+ cfW.cbSize = sizeof(cfW);
+ cfW.dwMask = CFM_SPACING;
+ cfW.sSpacing = 10;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
+ memset(&cfW, 0, sizeof(cfW));
+ cfW.cbSize = sizeof(cfW);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
+ ok(cfW.sSpacing == 10, "got %d\n", cfW.sSpacing);
+
+ /* test CFE_UNDERLINE and bUnderlineType interaction */
+ /* clear bold, italic */
+ SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ cf2.dwMask = CFM_BOLD | CFM_ITALIC;
+ cf2.dwEffects = 0;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+
+ /* check CFE_UNDERLINE is clear and bUnderlineType is CFU_UNDERLINE */
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
+ "got %08x\n", cf2.dwMask);
+ ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects);
+ ok(cf2.bUnderlineType == CFU_UNDERLINE, "got %x\n", cf2.bUnderlineType);
+
+ /* simply touching bUnderlineType will toggle CFE_UNDERLINE */
+ cf2.dwMask = CFM_UNDERLINETYPE;
+ cf2.bUnderlineType = CFU_UNDERLINE;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
+ "got %08x\n", cf2.dwMask);
+ ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects);
+ ok(cf2.bUnderlineType == CFU_UNDERLINE, "got %x\n", cf2.bUnderlineType);
+
+ /* setting bUnderline to CFU_UNDERLINENONE clears CFE_UNDERLINE */
+ cf2.dwMask = CFM_UNDERLINETYPE;
+ cf2.bUnderlineType = CFU_UNDERLINENONE;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
+ "got %08x\n", cf2.dwMask);
+ ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects);
+ ok(cf2.bUnderlineType == CFU_UNDERLINENONE, "got %x\n", cf2.bUnderlineType);
+
+ /* another underline type also sets CFE_UNDERLINE */
+ cf2.dwMask = CFM_UNDERLINETYPE;
+ cf2.bUnderlineType = CFU_UNDERLINEDOUBLE;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
+ "got %08x\n", cf2.dwMask);
+ ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects);
+ ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType);
+
+ /* However explicitly clearing CFE_UNDERLINE results in it remaining cleared */
+ cf2.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
+ cf2.bUnderlineType = CFU_UNDERLINEDOUBLE;
+ cf2.dwEffects = 0;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
+ "got %08x\n", cf2.dwMask);
+ ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects);
+ ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType);
+
+ /* And turing it back on again by just setting CFE_UNDERLINE */
+ cf2.dwMask = CFM_UNDERLINE;
+ cf2.dwEffects = CFE_UNDERLINE;
+ SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ memset(&cf2, 0, sizeof(CHARFORMAT2A));
+ cf2.cbSize = sizeof(CHARFORMAT2A);
+ SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE),
+ "got %08x\n", cf2.dwMask);
+ ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects);
+ ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType);
+
DestroyWindow(hwndRichEdit);
}
ok(ret == expectedMask, "expected %x got %x\n", expectedMask, ret);
ok(fmt.dwMask == expectedMask, "expected %x got %x\n", expectedMask, fmt.dwMask);
+ /* Test some other paraformat field defaults */
+ ok( fmt.wNumbering == 0, "got %d\n", fmt.wNumbering );
+ ok( fmt.wNumberingStart == 0, "got %d\n", fmt.wNumberingStart );
+ ok( fmt.wNumberingStyle == 0, "got %04x\n", fmt.wNumberingStyle );
+ ok( fmt.wNumberingTab == 0, "got %d\n", fmt.wNumberingTab );
+
DestroyWindow(hwndRichEdit);
}
"This is some text with #X on it",
"This is some text with @X on it",
"This is some text with \\X on it",
+ "This is some text with _X on it",
};
/* All of these cause the URL detection to be extended by one more byte,
thus demonstrating that the tested character is considered as part
"This is some text with X# on it",
"This is some text with X@ on it",
"This is some text with X\\ on it",
+ "This is some text with X_ on it",
+ };
+ /* These delims act as neutral breaks. Whether the url is ended
+ or not depends on the next non-neutral character. We'll test
+ with Y unchanged, in which case the url should include the
+ deliminator and the Y. We'll also test with the Y changed
+ to a space, in which case the url stops before the
+ deliminator. */
+ const char * templates_neutral_delim[] = {
+ "This is some text with X-Y on it",
+ "This is some text with X--Y on it",
+ "This is some text with X!Y on it",
+ "This is some text with X[Y on it",
+ "This is some text with X]Y on it",
+ "This is some text with X{Y on it",
+ "This is some text with X}Y on it",
+ "This is some text with X(Y on it",
+ "This is some text with X)Y on it",
+ "This is some text with X\"Y on it",
+ "This is some text with X;Y on it",
+ "This is some text with X:Y on it",
+ "This is some text with X'Y on it",
+ "This is some text with X?Y on it",
+ "This is some text with X<Y on it",
+ "This is some text with X>Y on it",
+ "This is some text with X.Y on it",
+ "This is some text with X,Y on it",
};
char buffer[1024];
}
}
+ for (j = 0; j < sizeof(templates_neutral_delim) / sizeof(const char *); j++) {
+ char * at_pos, * end_pos;
+ int at_offset;
+ int end_offset;
+
+ if (!urls[i].is_url) continue;
+
+ at_pos = strchr(templates_neutral_delim[j], 'X');
+ at_offset = at_pos - templates_neutral_delim[j];
+ memcpy(buffer, templates_neutral_delim[j], at_offset);
+ buffer[at_offset] = '\0';
+ strcat(buffer, urls[i].text);
+ strcat(buffer, templates_neutral_delim[j] + at_offset + 1);
+
+ end_pos = strchr(buffer, 'Y');
+ end_offset = end_pos - buffer;
+
+ SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
+ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
+
+ /* This assumes no templates start with the URL itself, and that they
+ have at least two characters before the URL text */
+ ok(!check_CFE_LINK_selection(hwndRichEdit, 0, 1),
+ "CFE_LINK incorrectly set in (%d-%d), text: %s\n", 0, 1, buffer);
+ ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -2, at_offset -1),
+ "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -2, at_offset -1, buffer);
+ ok(!check_CFE_LINK_selection(hwndRichEdit, at_offset -1, at_offset),
+ "CFE_LINK incorrectly set in (%d-%d), text: %s\n", at_offset -1, at_offset, buffer);
+
+ ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
+ "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
+ ok(check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
+ "CFE_LINK not set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
+ ok(check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
+ "CFE_LINK not set in (%d-%d), text: %s\n", end_offset, end_offset +1, buffer);
+
+ *end_pos = ' ';
+
+ SendMessageA(hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0);
+ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)buffer);
+
+ ok(check_CFE_LINK_selection(hwndRichEdit, at_offset, at_offset +1),
+ "CFE_LINK not set in (%d-%d), text: %s\n", at_offset, at_offset +1, buffer);
+ ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset -1, end_offset),
+ "CFE_LINK set in (%d-%d), text: %s\n", end_offset -1, end_offset, buffer);
+ ok(!check_CFE_LINK_selection(hwndRichEdit, end_offset, end_offset +1),
+ "CFE_LINK set in (%d-%d), text: %s\n", end_offset, end_offset +1, buffer);
+ }
+
DestroyWindow(hwndRichEdit);
hwndRichEdit = NULL;
}
SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"x");
cr.cpMin = 0;
- cr.cpMax = 1;
+ cr.cpMax = -1;
+ SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
+
SendMessageA(hwndRichEdit, WM_COPY, 0, 0);
/*Load "x" into the clipboard. Paste is an easy, undo'able operation.
also, multiple pastes don't combine like WM_CHAR would */
- SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&cr);
/* first case - check the default */
SendMessageA(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
DestroyWindow(hwndRichEdit);
}
+static void test_EM_STREAMOUT_empty_para(void)
+{
+ HWND hwnd = new_richedit(NULL);
+ char buf[1024], *p = buf;
+ EDITSTREAM es;
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+
+ memset(buf, 0, sizeof(buf));
+ es.dwCookie = (DWORD_PTR)&p;
+ es.dwError = 0;
+ es.pfnCallback = test_WM_SETTEXT_esCallback;
+
+ SendMessageA(hwnd, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
+ ok((p = strstr(buf, "\\pard")) != NULL, "missing \\pard\n");
+ ok(((p = strstr(p, "\\fs")) && isdigit(p[3])), "missing \\fs\n");
+
+ DestroyWindow(hwnd);
+}
static void test_EM_SETTEXTEX(void)
{
getText.flags = GT_DEFAULT;
getText.lpDefaultChar = NULL;
getText.lpUsedDefChar = NULL;
- memset(buf, 0, MAX_BUF_LEN);
+ memset(buf, 0, sizeof(buf));
SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
ok(lstrcmpW(buf, TestItem2) == 0,
"EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
getText.flags = GT_USECRLF; /* <-- asking for CR -> CRLF conversion */
getText.lpDefaultChar = NULL;
getText.lpUsedDefChar = NULL;
- memset(buf, 0, MAX_BUF_LEN);
+ memset(buf, 0, sizeof(buf));
SendMessageA(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM)buf);
ok(lstrcmpW(buf, TestItem1) == 0,
"EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n");
todo_wine ok(!strcmp(buffer, "WTestSomeTextne"), "WM_GETTEXT returned incorrect string\n");
if (!redraw)
- /* This is needed to avoid interferring with keybd_event calls
+ /* This is needed to avoid interfering with keybd_event calls
* on other tests that simulate keyboard events. */
SendMessageA(hwndRichEdit, WM_SETREDRAW, TRUE, 0);
EDITSTREAM es;
char buffer[1024] = {0}, tmp[16];
CHARRANGE range;
+ PARAFORMAT2 fmt;
- const char * streamText0 = "{\\rtf1 TestSomeText}";
- const char * streamText0a = "{\\rtf1 TestSomeText\\par}";
+ const char * streamText0 = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText}";
+ const char * streamText0a = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText\\par}";
const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}";
const char * ptr;
ok (result == 0,
"EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer);
ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0);
+ /* Show that para fmts are ignored */
+ range.cpMin = 2;
+ range.cpMax = 2;
+ result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range);
+ memset(&fmt, 0xcc, sizeof(fmt));
+ fmt.cbSize = sizeof(fmt);
+ result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
+ ok(fmt.dxStartIndent == 0, "got %d\n", fmt.dxStartIndent);
+ ok(fmt.dxOffset == 0, "got %d\n", fmt.dxOffset);
+ ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment);
+ ok((fmt.wEffects & PFE_RTLPARA) == 0, "got %x\n", fmt.wEffects);
/* Native richedit 2.0 ignores last \par */
ptr = streamText0a;
ok (result == 0,
"EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer);
ok(es.dwError == 0, "EM_STREAMIN: Test 0-a set error %d, expected %d\n", es.dwError, 0);
+ /* This time para fmts are processed */
+ range.cpMin = 2;
+ range.cpMax = 2;
+ result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range);
+ memset(&fmt, 0xcc, sizeof(fmt));
+ fmt.cbSize = sizeof(fmt);
+ result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt);
+ ok(fmt.dxStartIndent == 300, "got %d\n", fmt.dxStartIndent);
+ ok(fmt.dxOffset == -100, "got %d\n", fmt.dxOffset);
+ ok(fmt.wAlignment == PFA_RIGHT, "got %d\n", fmt.wAlignment);
+ ok((fmt.wEffects & PFE_RTLPARA) == PFE_RTLPARA, "got %x\n", fmt.wEffects);
/* Native richedit 2.0 ignores last \par, next-to-last \par appears */
es.dwCookie = (DWORD_PTR)&streamText0b;
GetClientRect(hwnd, &clientRect);
expected = clientRect;
- expected.left += 1;
- expected.right -= 1;
+ InflateRect(&expected, -1, 0);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
for (n = -3; n <= 3; n++)
{
rc = clientRect;
- rc.top += n;
- rc.left += n;
- rc.bottom -= n;
- rc.right -= n;
+ InflateRect(&rc, -n, -n);
SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
expected = rc;
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);
+ ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
}
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
/* Adding the selectionbar adds the selectionbar width to the left side. */
SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
/* Removing the selectionbar subtracts the selectionbar width from the left side,
* even if the left side is already 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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
/* 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);
+ ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
/* 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
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
/* For some reason it does not limit the values to the client rect with
* a WPARAM value of 1. */
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
/* Reset to default rect and check how the format rect adjusts to window
* resize and how it copes with very small windows */
GetClientRect(hwnd, &clientRect);
expected = clientRect;
- expected.left += 1;
- expected.right -= 1;
+ InflateRect(&expected, -1, 0);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
MoveWindow(hwnd, 0, 0, 0, 30, FALSE);
GetClientRect(hwnd, &clientRect);
expected = clientRect;
- expected.left += 1;
- expected.right -= 1;
+ InflateRect(&expected, -1, 0);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
MoveWindow(hwnd, 0, 0, 100, 0, FALSE);
GetClientRect(hwnd, &clientRect);
expected = clientRect;
- expected.left += 1;
- expected.right -= 1;
+ InflateRect(&expected, -1, 0);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
DestroyWindow(hwnd);
GetClientRect(hwnd, &clientRect);
expected = clientRect;
- expected.left += 1;
expected.top += 1;
- expected.right -= 1;
+ InflateRect(&expected, -1, 0);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
rc = clientRect;
- rc.top += 5;
- rc.left += 5;
- rc.bottom -= 5;
- rc.right -= 5;
+ InflateRect(&rc, -5, -5);
expected = rc;
expected.top -= 1;
- expected.left -= 1;
- expected.right += 1;
+ InflateRect(&expected, 1, 0);
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);
+ ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc),
+ wine_dbgstr_rect(&expected));
DestroyWindow(hwnd);
}
SendMessageA( richedit, WM_CUT, 0, 0 );
SendMessageA( richedit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
- ok( fmt.wAlignment == def_align, "got %d exppect %d\n", fmt.wAlignment, def_align );
+ ok( fmt.wAlignment == def_align, "got %d expect %d\n", fmt.wAlignment, def_align );
DestroyWindow( richedit );
}
SendMessageW(richedit, WM_CUT, 0, 0);
SendMessageW(richedit, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
- ok(pf.wAlignment == align_mask[i], "got %d exppect %d\n", pf.wAlignment, align_mask[i]);
+ ok(pf.wAlignment == align_mask[i], "got %d expect %d\n", pf.wAlignment, align_mask[i]);
DestroyWindow(richedit);
}
pf.cbSize = sizeof(PARAFORMAT2);
pf.dwMask = -1;
SendMessageW(richedit, EM_GETPARAFORMAT, SCF_SELECTION, (LPARAM)&pf);
- ok(pf.wAlignment == ES_CENTER, "got %d expected ES_CENTER\n", pf.wAlignment);
+ ok(pf.wAlignment == PFA_LEFT, "got %d expected PFA_LEFT\n", pf.wAlignment);
DestroyWindow(richedit);
}
DestroyWindow(hwndRichEdit);
}
+static void test_rtf(void)
+{
+ const char *specials = "{\\rtf1\\emspace\\enspace\\bullet\\lquote"
+ "\\rquote\\ldblquote\\rdblquote\\ltrmark\\rtlmark\\zwj\\zwnj}";
+ const WCHAR expect_specials[] = {' ',' ',0x2022,0x2018,0x2019,0x201c,
+ 0x201d,0x200e,0x200f,0x200d,0x200c};
+ const char *pard = "{\\rtf1 ABC\\rtlpar\\par DEF\\par HIJ\\pard\\par}";
+ const char *highlight = "{\\rtf1{\\colortbl;\\red0\\green0\\blue0;\\red128\\green128\\blue128;\\red192\\green192\\blue192;}\\cf2\\highlight3 foo\\par}";
+
+ HWND edit = new_richeditW( NULL );
+ EDITSTREAM es;
+ WCHAR buf[80];
+ LRESULT result;
+ PARAFORMAT2 fmt;
+ CHARFORMAT2W cf;
+
+ /* Test rtf specials */
+ es.dwCookie = (DWORD_PTR)&specials;
+ es.dwError = 0;
+ es.pfnCallback = test_EM_STREAMIN_esCallback;
+ result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
+ ok( result == 11, "got %ld\n", result );
+
+ result = SendMessageW( edit, WM_GETTEXT, sizeof(buf)/sizeof(buf[0]), (LPARAM)buf );
+ ok( result == sizeof(expect_specials)/sizeof(expect_specials[0]), "got %ld\n", result );
+ ok( !memcmp( buf, expect_specials, sizeof(expect_specials) ), "got %s\n", wine_dbgstr_w(buf) );
+
+ /* Show that \rtlpar propagates to the second paragraph and is
+ reset by \pard in the third. */
+ es.dwCookie = (DWORD_PTR)&pard;
+ result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
+ ok( result == 11, "got %ld\n", result );
+
+ fmt.cbSize = sizeof(fmt);
+ SendMessageW( edit, EM_SETSEL, 1, 1 );
+ SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
+ ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" );
+ ok( fmt.wEffects & PFE_RTLPARA, "rtl para not set\n" );
+ SendMessageW( edit, EM_SETSEL, 5, 5 );
+ SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
+ ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" );
+ ok( fmt.wEffects & PFE_RTLPARA, "rtl para not set\n" );
+ SendMessageW( edit, EM_SETSEL, 9, 9 );
+ SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
+ ok( fmt.dwMask & PFM_RTLPARA, "rtl para mask not set\n" );
+ ok( !(fmt.wEffects & PFE_RTLPARA), "rtl para set\n" );
+
+ /* Test \highlight */
+ es.dwCookie = (DWORD_PTR)&highlight;
+ result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
+ ok( result == 3, "got %ld\n", result );
+ SendMessageW( edit, EM_SETSEL, 1, 1 );
+ memset( &cf, 0, sizeof(cf) );
+ cf.cbSize = sizeof(cf);
+ SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
+ ok( (cf.dwEffects & (CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR)) == 0, "got %08x\n", cf.dwEffects );
+ ok( cf.crTextColor == RGB(128,128,128), "got %08x\n", cf.crTextColor );
+ ok( cf.crBackColor == RGB(192,192,192), "got %08x\n", cf.crBackColor );
+
+ DestroyWindow( edit );
+}
+
+static void test_background(void)
+{
+ HWND hwndRichEdit = new_richedit(NULL);
+
+ /* set the background color to black */
+ ValidateRect(hwndRichEdit, NULL);
+ SendMessageA(hwndRichEdit, EM_SETBKGNDCOLOR, FALSE, RGB(0, 0, 0));
+ ok(GetUpdateRect(hwndRichEdit, NULL, FALSE), "Update rectangle is empty!\n");
+
+ DestroyWindow(hwndRichEdit);
+}
+
+static void test_eop_char_fmt(void)
+{
+ HWND edit = new_richedit( NULL );
+ const char *rtf = "{\\rtf1{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Arial;}{\\f1\\fnil\\fcharset2 Symbol;}}"
+ "{\\fs10{\\pard\\fs16\\fi200\\li360\\f0 First\\par"
+ "\\f0\\fs25 Second\\par"
+ "{\\f0\\fs26 Third}\\par"
+ "{\\f0\\fs22 Fourth}\\par}}}";
+ EDITSTREAM es;
+ CHARFORMAT2W cf;
+ int i, num, expect_height;
+
+ es.dwCookie = (DWORD_PTR)&rtf;
+ es.dwError = 0;
+ es.pfnCallback = test_EM_STREAMIN_esCallback;
+ num = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
+ ok( num == 25, "got %d\n", num );
+
+ for (i = 0; i <= num; i++)
+ {
+ SendMessageW( edit, EM_SETSEL, i, i + 1 );
+ cf.cbSize = sizeof(cf);
+ cf.dwMask = CFM_SIZE;
+ SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
+ ok( cf.dwMask & CFM_SIZE, "%d: got %08x\n", i, cf.dwMask );
+ if (i < 6) expect_height = 160;
+ else if (i < 13) expect_height = 250;
+ else if (i < 18) expect_height = 260;
+ else if (i == 18 || i == 25) expect_height = 250;
+ else expect_height = 220;
+ ok( cf.yHeight == expect_height, "%d: got %d\n", i, cf.yHeight );
+ }
+
+ DestroyWindow( edit );
+}
+
+static void test_para_numbering(void)
+{
+ HWND edit = new_richeditW( NULL );
+ const char *numbers = "{\\rtf1{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Arial;}{\\f1\\fnil\\fcharset2 Symbol;}}"
+ "\\pard{\\pntext\\f0 3.\\tab}{\\*\\pn\\pnlvlbody\\pnfs32\\pnf0\\pnindent1000\\pnstart2\\pndec{\\pntxta.}}"
+ "\\fs20\\fi200\\li360\\f0 First\\par"
+ "{\\pntext\\f0 4.\\tab}\\f0 Second\\par"
+ "{\\pntext\\f0 6.\\tab}\\f0 Third\\par}";
+ const WCHAR expect_numbers_txt[] = {'F','i','r','s','t','\r','S','e','c','o','n','d','\r','T','h','i','r','d',0};
+ EDITSTREAM es;
+ WCHAR buf[80];
+ LRESULT result;
+ PARAFORMAT2 fmt, fmt2;
+ GETTEXTEX get_text;
+ CHARFORMAT2W cf;
+
+ get_text.cb = sizeof(buf);
+ get_text.flags = GT_RAWTEXT;
+ get_text.codepage = 1200;
+ get_text.lpDefaultChar = NULL;
+ get_text.lpUsedDefChar = NULL;
+
+ es.dwCookie = (DWORD_PTR)&numbers;
+ es.dwError = 0;
+ es.pfnCallback = test_EM_STREAMIN_esCallback;
+ result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
+ ok( result == lstrlenW( expect_numbers_txt ), "got %ld\n", result );
+
+ result = SendMessageW( edit, EM_GETTEXTEX, (WPARAM)&get_text, (LPARAM)buf );
+ ok( result == lstrlenW( expect_numbers_txt ), "got %ld\n", result );
+ ok( !lstrcmpW( buf, expect_numbers_txt ), "got %s\n", wine_dbgstr_w(buf) );
+
+ SendMessageW( edit, EM_SETSEL, 1, 1 );
+ memset( &fmt, 0, sizeof(fmt) );
+ fmt.cbSize = sizeof(fmt);
+ fmt.dwMask = PFM_ALL2;
+ SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt );
+ ok( fmt.wNumbering == PFN_ARABIC, "got %d\n", fmt.wNumbering );
+ ok( fmt.wNumberingStart == 2, "got %d\n", fmt.wNumberingStart );
+ ok( fmt.wNumberingStyle == PFNS_PERIOD, "got %04x\n", fmt.wNumberingStyle );
+ ok( fmt.wNumberingTab == 1000, "got %d\n", fmt.wNumberingTab );
+ ok( fmt.dxStartIndent == 560, "got %d\n", fmt.dxStartIndent );
+ ok( fmt.dxOffset == -200, "got %d\n", fmt.dxOffset );
+
+ /* Second para should have identical fmt */
+ SendMessageW( edit, EM_SETSEL, 10, 10 );
+ memset( &fmt2, 0, sizeof(fmt2) );
+ fmt2.cbSize = sizeof(fmt2);
+ fmt2.dwMask = PFM_ALL2;
+ SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt2 );
+ ok( !memcmp( &fmt, &fmt2, sizeof(fmt) ), "format mismatch\n" );
+
+ /* Check the eop heights - this determines the label height */
+ SendMessageW( edit, EM_SETSEL, 12, 13 );
+ cf.cbSize = sizeof(cf);
+ cf.dwMask = CFM_SIZE;
+ SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
+ ok( cf.yHeight == 200, "got %d\n", cf.yHeight );
+
+ SendMessageW( edit, EM_SETSEL, 18, 19 );
+ cf.cbSize = sizeof(cf);
+ cf.dwMask = CFM_SIZE;
+ SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
+ ok( cf.yHeight == 200, "got %d\n", cf.yHeight );
+
+ DestroyWindow( edit );
+}
+
+static void test_window_classes(void)
+{
+ static const struct
+ {
+ const char *class;
+ BOOL success;
+ } test[] =
+ {
+ { "RichEdit", FALSE },
+ { "RichEdit20A", TRUE },
+ { "RichEdit20W", TRUE },
+ { "RichEdit50A", FALSE },
+ { "RichEdit50W", FALSE }
+ };
+ int i;
+ HWND hwnd;
+
+ for (i = 0; i < sizeof(test)/sizeof(test[0]); i++)
+ {
+ SetLastError(0xdeadbeef);
+ hwnd = CreateWindowExA(0, test[i].class, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL);
+todo_wine_if(!strcmp(test[i].class, "RichEdit50A") || !strcmp(test[i].class, "RichEdit50W"))
+ ok(!hwnd == !test[i].success, "CreateWindow(%s) should %s\n",
+ test[i].class, test[i].success ? "succeed" : "fail");
+ if (!hwnd)
+todo_wine
+ ok(GetLastError() == ERROR_CANNOT_FIND_WND_CLASS, "got %d\n", GetLastError());
+ else
+ DestroyWindow(hwnd);
+ }
+}
+
START_TEST( editor )
{
BOOL ret;
ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
is_lang_japanese = (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE);
+ test_window_classes();
test_WM_CHAR();
test_EM_FINDTEXT(FALSE);
test_EM_FINDTEXT(TRUE);
test_EM_STREAMIN();
test_EM_STREAMOUT();
test_EM_STREAMOUT_FONTTBL();
+ test_EM_STREAMOUT_empty_para();
test_EM_StreamIn_Undo();
test_EM_FORMATRANGE();
test_unicode_conversions();
test_EM_SETREADONLY();
test_EM_SETFONTSIZE();
test_alignment_style();
+ test_rtf();
+ test_background();
+ test_eop_char_fmt();
+ test_para_numbering();
/* Set the environment variable WINETEST_RICHED20 to keep windows
* responsive and open for 30 seconds. This is useful for debugging.