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());
|
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)
|
START_TEST(text)
|
||||||
{
|
{
|
||||||
|
test_TabbedText();
|
||||||
test_DrawTextCalcRect();
|
test_DrawTextCalcRect();
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -1214,17 +1215,13 @@ static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCWSTR lpstr,
|
|||||||
{
|
{
|
||||||
INT defWidth;
|
INT defWidth;
|
||||||
SIZE extent;
|
SIZE extent;
|
||||||
int i;
|
int i, j;
|
||||||
int start = x;
|
int start = x;
|
||||||
BOOL first = TRUE;
|
|
||||||
|
|
||||||
extent.cx = 0;
|
|
||||||
extent.cy = 0;
|
|
||||||
|
|
||||||
if (!lpTabPos)
|
if (!lpTabPos)
|
||||||
cTabStops=0;
|
cTabStops=0;
|
||||||
|
|
||||||
if (cTabStops == 1 && *lpTabPos >= /* sic */ 0)
|
if (cTabStops == 1)
|
||||||
{
|
{
|
||||||
defWidth = *lpTabPos;
|
defWidth = *lpTabPos;
|
||||||
cTabStops = 0;
|
cTabStops = 0;
|
||||||
@ -1234,66 +1231,70 @@ static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCWSTR lpstr,
|
|||||||
TEXTMETRICA tm;
|
TEXTMETRICA tm;
|
||||||
GetTextMetricsA( hdc, &tm );
|
GetTextMetricsA( hdc, &tm );
|
||||||
defWidth = 8 * tm.tmAveCharWidth;
|
defWidth = 8 * tm.tmAveCharWidth;
|
||||||
if (cTabStops == 1)
|
|
||||||
cTabStops = 0; /* on negative *lpTabPos */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count > 0)
|
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++)
|
for (i = 0; i < count; i++)
|
||||||
if (lpstr[i] == '\t') break;
|
if (lpstr[i] != '\t') break;
|
||||||
|
for (j = i; j < count; j++)
|
||||||
GetTextExtentPointW( hdc, lpstr, i, &extent );
|
if (lpstr[j] == '\t') break;
|
||||||
|
/* get the extent of the normal character part */
|
||||||
/* the first time round the loop we should use the value of x
|
GetTextExtentPointW( hdc, lpstr + i, j - i , &extent );
|
||||||
* passed into the function.
|
/* and if there is a <tab>, calculate its position */
|
||||||
* all other times, we calculate it here */
|
if( i) {
|
||||||
if (!first)
|
|
||||||
{
|
|
||||||
/* get x coordinate for the drawing of this string */
|
/* get x coordinate for the drawing of this string */
|
||||||
for (; cTabStops > 0; lpTabPos++, cTabStops--)
|
for (; cTabStops > i; lpTabPos++, cTabStops--)
|
||||||
{
|
{
|
||||||
if (*lpTabPos >= 0)
|
if( nTabOrg + abs( *lpTabPos) > x) {
|
||||||
{
|
if( lpTabPos[ i - 1] >= 0) {
|
||||||
if (nTabOrg + *lpTabPos >= x)
|
/* a left aligned tab */
|
||||||
{
|
x = nTabOrg + lpTabPos[ i-1] + extent.cx;
|
||||||
x = nTabOrg + *lpTabPos;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* if tab pos is negative then text is right-aligned to tab
|
/* if tab pos is negative then text is right-aligned
|
||||||
* stop meaning that the string extends to the left, so we
|
* to tab stop meaning that the string extends to the
|
||||||
* must subtract the width of the string */
|
* left, so we must subtract the width of the string */
|
||||||
if (nTabOrg + -*lpTabPos -extent.cx >= x)
|
if (nTabOrg - lpTabPos[ i - 1] - extent.cx > x)
|
||||||
{
|
{
|
||||||
x = nTabOrg + -*lpTabPos - extent.cx;
|
x = nTabOrg - lpTabPos[ i - 1];
|
||||||
|
x0 = x - extent.cx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* if we have run out of tab stops and we have a valid default tab
|
/* if we have run out of tab stops and we have a valid default tab
|
||||||
* stop width then round x up to that width */
|
* stop width then round x up to that width */
|
||||||
if ((cTabStops <= 0) && (defWidth > 0))
|
if ((cTabStops <= i) && (defWidth > 0)) {
|
||||||
x = nTabOrg + ((x - nTabOrg) / defWidth + 1) * defWidth;
|
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 first = FALSE;
|
} else
|
||||||
|
x += extent.cx;
|
||||||
|
|
||||||
if (fDisplayText)
|
if (fDisplayText)
|
||||||
{
|
{
|
||||||
RECT r;
|
|
||||||
r.left = x;
|
|
||||||
r.top = y;
|
r.top = y;
|
||||||
r.right = x + extent.cx;
|
r.right = x;
|
||||||
r.bottom = y + extent.cy;
|
r.bottom = y + extent.cy;
|
||||||
ExtTextOutW( hdc, x, y, GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
|
ExtTextOutW( hdc, x0, y, GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
|
||||||
&r, lpstr, i, NULL );
|
&r, lpstr + i, j - i, NULL );
|
||||||
}
|
}
|
||||||
x += extent.cx;
|
count -= j;
|
||||||
count -= i+1;
|
lpstr += j;
|
||||||
lpstr += i+1;
|
|
||||||
}
|
}
|
||||||
return MAKELONG(x - start, extent.cy);
|
return MAKELONG(x - start, extent.cy);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user