Fixed a lot of bugs in TEXT_TabbedTextOut. With the test cases used to

find them.
This commit is contained in:
Rein Klazes 2005-10-26 10:04:21 +00:00 committed by Alexandre Julliard
parent ca025e2245
commit 16a5c4fbca
2 changed files with 137 additions and 46 deletions

View File

@ -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();
}

View File

@ -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);
}