mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 04:39:45 +00:00
Fixed a lot of bugs in TEXT_TabbedTextOut. With the test cases used to
find them.
This commit is contained in:
parent
ca025e2245
commit
16a5c4fbca
@ -111,7 +111,97 @@ static void test_DrawTextCalcRect(void)
|
||||
ok( ret, "DestroyWindow error %lu\n", GetLastError());
|
||||
}
|
||||
|
||||
/* replace tabs by \t */
|
||||
static void strfmt( char *str, char *strout)
|
||||
{
|
||||
unsigned int i,j ;
|
||||
for(i=0,j=0;i<=strlen(str);i++,j++)
|
||||
if((strout[j]=str[i])=='\t') {
|
||||
strout[j++]='\\';
|
||||
strout[j]='t';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TABTEST( tabval, tabcount, string, _exp) \
|
||||
{ int i,x_act, x_exp; char strdisp[64];\
|
||||
for(i=0;i<8;i++) tabs[i]=(i+1)*(tabval); \
|
||||
extent = GetTabbedTextExtentA( hdc, string, strlen( string), (tabcount), tabs); \
|
||||
strfmt( string, strdisp); \
|
||||
/* trace( "Extent is %08lx\n", extent); */\
|
||||
x_act = LOWORD( extent); \
|
||||
x_exp = (_exp); \
|
||||
ok( x_act == x_exp, "Test case \"%s\". Text extent is %d, expected %d tab %d tabcount %d\n", \
|
||||
strdisp, x_act, x_exp, tabval, tabcount); \
|
||||
} \
|
||||
|
||||
|
||||
static void test_TabbedText()
|
||||
{
|
||||
HWND hwnd;
|
||||
HDC hdc;
|
||||
BOOL ret;
|
||||
TEXTMETRICA tm;
|
||||
DWORD extent;
|
||||
INT tabs[8], cx, cy, tab, tabcount,t,align;
|
||||
|
||||
/* Initialization */
|
||||
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
|
||||
0, 0, 200, 200, 0, 0, 0, NULL);
|
||||
ok(hwnd != 0, "CreateWindowExA error %lu\n", GetLastError());
|
||||
hdc = GetDC(hwnd);
|
||||
ok(hdc != 0, "GetDC error %lu\n", GetLastError());
|
||||
|
||||
ret = GetTextMetricsA( hdc, &tm);
|
||||
ok( ret, "GetTextMetrics error %lu\n", GetLastError());
|
||||
|
||||
extent = GetTabbedTextExtentA( hdc, "x", 1, 1, tabs);
|
||||
cx = LOWORD( extent);
|
||||
cy = HIWORD( extent);
|
||||
trace( "cx is %d cy is %d\n", cx, cy);
|
||||
|
||||
align=1;
|
||||
for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to
|
||||
catch the one off errors */
|
||||
tab = (cx *4 + t);
|
||||
/* test the special case tabcount =1 and the general array (80 of tabs */
|
||||
for( tabcount = 1; tabcount <= 8; tabcount +=7) {
|
||||
TABTEST( align * tab, tabcount, "\t", tab)
|
||||
TABTEST( align * tab, tabcount, "xxx\t", tab)
|
||||
TABTEST( align * tab, tabcount, "\tx", tab+cx)
|
||||
TABTEST( align * tab, tabcount, "\t\t", tab*2)
|
||||
TABTEST( align * tab, tabcount, "\tx\t", tab*2)
|
||||
TABTEST( align * tab, tabcount, "x\tx", tab+cx)
|
||||
TABTEST( align * tab, tabcount, "xx\tx", tab+cx)
|
||||
TABTEST( align * tab, tabcount, "xxx\tx", tab+cx)
|
||||
TABTEST( align * tab, tabcount, "xxxx\tx", t>0 ? tab + cx : 2*tab+cx)
|
||||
TABTEST( align * tab, tabcount, "xxxxx\tx", 2*tab+cx)
|
||||
}
|
||||
}
|
||||
align=-1;
|
||||
for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to
|
||||
catch the one off errors */
|
||||
tab = (cx *4 + t);
|
||||
/* test the special case tabcount =1 and the general array (8) of tabs */
|
||||
for( tabcount = 1; tabcount <= 8; tabcount +=7) {
|
||||
TABTEST( align * tab, tabcount, "\t", tab)
|
||||
TABTEST( align * tab, tabcount, "xxx\t", tab)
|
||||
TABTEST( align * tab, tabcount, "\tx", tab)
|
||||
TABTEST( align * tab, tabcount, "\t\t", tab*2)
|
||||
TABTEST( align * tab, tabcount, "\tx\t", tab*2)
|
||||
TABTEST( align * tab, tabcount, "x\tx", tab)
|
||||
TABTEST( align * tab, tabcount, "xx\tx", tab)
|
||||
TABTEST( align * tab, tabcount, "xxx\tx", 4 * cx >= tab ? 2*tab :tab)
|
||||
TABTEST( align * tab, tabcount, "xxxx\tx", 2*tab)
|
||||
TABTEST( align * tab, tabcount, "xxxxx\tx", 2*tab)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
START_TEST(text)
|
||||
{
|
||||
test_TabbedText();
|
||||
test_DrawTextCalcRect();
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@ -1214,17 +1215,13 @@ static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCWSTR lpstr,
|
||||
{
|
||||
INT defWidth;
|
||||
SIZE extent;
|
||||
int i;
|
||||
int i, j;
|
||||
int start = x;
|
||||
BOOL first = TRUE;
|
||||
|
||||
extent.cx = 0;
|
||||
extent.cy = 0;
|
||||
|
||||
if (!lpTabPos)
|
||||
cTabStops=0;
|
||||
|
||||
if (cTabStops == 1 && *lpTabPos >= /* sic */ 0)
|
||||
if (cTabStops == 1)
|
||||
{
|
||||
defWidth = *lpTabPos;
|
||||
cTabStops = 0;
|
||||
@ -1234,66 +1231,70 @@ static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCWSTR lpstr,
|
||||
TEXTMETRICA tm;
|
||||
GetTextMetricsA( hdc, &tm );
|
||||
defWidth = 8 * tm.tmAveCharWidth;
|
||||
if (cTabStops == 1)
|
||||
cTabStops = 0; /* on negative *lpTabPos */
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
/* tokenize string by tabs */
|
||||
RECT r;
|
||||
INT x0;
|
||||
x0 = x;
|
||||
r.left = x0;
|
||||
/* chop the string into substrings of 0 or more <tabs>
|
||||
* possibly followed by 1 or more normal characters */
|
||||
for (i = 0; i < count; i++)
|
||||
if (lpstr[i] == '\t') break;
|
||||
|
||||
GetTextExtentPointW( hdc, lpstr, i, &extent );
|
||||
|
||||
/* the first time round the loop we should use the value of x
|
||||
* passed into the function.
|
||||
* all other times, we calculate it here */
|
||||
if (!first)
|
||||
{
|
||||
if (lpstr[i] != '\t') break;
|
||||
for (j = i; j < count; j++)
|
||||
if (lpstr[j] == '\t') break;
|
||||
/* get the extent of the normal character part */
|
||||
GetTextExtentPointW( hdc, lpstr + i, j - i , &extent );
|
||||
/* and if there is a <tab>, calculate its position */
|
||||
if( i) {
|
||||
/* get x coordinate for the drawing of this string */
|
||||
for (; cTabStops > 0; lpTabPos++, cTabStops--)
|
||||
for (; cTabStops > i; lpTabPos++, cTabStops--)
|
||||
{
|
||||
if (*lpTabPos >= 0)
|
||||
{
|
||||
if (nTabOrg + *lpTabPos >= x)
|
||||
{
|
||||
x = nTabOrg + *lpTabPos;
|
||||
if( nTabOrg + abs( *lpTabPos) > x) {
|
||||
if( lpTabPos[ i - 1] >= 0) {
|
||||
/* a left aligned tab */
|
||||
x = nTabOrg + lpTabPos[ i-1] + extent.cx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if tab pos is negative then text is right-aligned to tab
|
||||
* stop meaning that the string extends to the left, so we
|
||||
* must subtract the width of the string */
|
||||
if (nTabOrg + -*lpTabPos -extent.cx >= x)
|
||||
else
|
||||
{
|
||||
x = nTabOrg + -*lpTabPos - extent.cx;
|
||||
break;
|
||||
/* if tab pos is negative then text is right-aligned
|
||||
* to tab stop meaning that the string extends to the
|
||||
* left, so we must subtract the width of the string */
|
||||
if (nTabOrg - lpTabPos[ i - 1] - extent.cx > x)
|
||||
{
|
||||
x = nTabOrg - lpTabPos[ i - 1];
|
||||
x0 = x - extent.cx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if we have run out of tab stops and we have a valid default tab
|
||||
* stop width then round x up to that width */
|
||||
if ((cTabStops <= 0) && (defWidth > 0))
|
||||
x = nTabOrg + ((x - nTabOrg) / defWidth + 1) * defWidth;
|
||||
}
|
||||
else first = FALSE;
|
||||
|
||||
if ((cTabStops <= i) && (defWidth > 0)) {
|
||||
x0 = nTabOrg + ((x - nTabOrg) / defWidth + i) * defWidth;
|
||||
x = x0 + extent.cx;
|
||||
} else if ((cTabStops <= i) && (defWidth < 0)) {
|
||||
x = nTabOrg + ((x - nTabOrg + extent.cx) / -defWidth + i)
|
||||
* -defWidth;
|
||||
x0 = x - extent.cx;
|
||||
}
|
||||
} else
|
||||
x += extent.cx;
|
||||
|
||||
if (fDisplayText)
|
||||
{
|
||||
RECT r;
|
||||
r.left = x;
|
||||
r.top = y;
|
||||
r.right = x + extent.cx;
|
||||
r.right = x;
|
||||
r.bottom = y + extent.cy;
|
||||
ExtTextOutW( hdc, x, y, GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
|
||||
&r, lpstr, i, NULL );
|
||||
ExtTextOutW( hdc, x0, y, GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
|
||||
&r, lpstr + i, j - i, NULL );
|
||||
}
|
||||
x += extent.cx;
|
||||
count -= i+1;
|
||||
lpstr += i+1;
|
||||
count -= j;
|
||||
lpstr += j;
|
||||
}
|
||||
return MAKELONG(x - start, extent.cy);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user