Put in place a proper tab model within DrawText (also includes
simplifying TEXT_NextLineW to remove duplicate code).
This commit is contained in:
parent
48a87e6107
commit
cabe8ca580
202
dlls/user/text.c
202
dlls/user/text.c
|
@ -75,15 +75,9 @@ DEFAULT_DEBUG_CHANNEL(text);
|
||||||
#define FORWARD_SLASH '/'
|
#define FORWARD_SLASH '/'
|
||||||
#define BACK_SLASH '\\'
|
#define BACK_SLASH '\\'
|
||||||
|
|
||||||
static const WCHAR SPACEW[] = {' ', 0};
|
|
||||||
static const WCHAR oW[] = {'o', 0};
|
|
||||||
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
|
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
|
||||||
static const WCHAR FORWARD_SLASHW[] = {'/', 0};
|
|
||||||
static const WCHAR BACK_SLASHW[] = {'\\', 0};
|
|
||||||
|
|
||||||
static int tabstop;
|
|
||||||
static int tabwidth;
|
static int tabwidth;
|
||||||
static int spacewidth;
|
|
||||||
static int prefix_offset;
|
static int prefix_offset;
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
@ -349,23 +343,24 @@ static int TEXT_Reprefix (const WCHAR *str, unsigned int n1, unsigned int n2,
|
||||||
static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
||||||
WCHAR *dest, int *len, int width, WORD format)
|
WCHAR *dest, int *len, int width, WORD format)
|
||||||
{
|
{
|
||||||
int i = 0, j = 0, k;
|
int i = 0, j = 0;
|
||||||
int plen = 0;
|
int plen = 0;
|
||||||
int numspaces;
|
|
||||||
SIZE size;
|
SIZE size;
|
||||||
int lasttab = 0;
|
|
||||||
int wb_i = 0, wb_j = 0, wb_count = 0;
|
int wb_i = 0, wb_j = 0, wb_count = 0;
|
||||||
int maxl = *len;
|
int maxl = *len;
|
||||||
|
int normal_char;
|
||||||
|
|
||||||
while (*count && j < maxl)
|
while (*count && j < maxl)
|
||||||
{
|
{
|
||||||
|
normal_char = 1;
|
||||||
switch (str[i])
|
switch (str[i])
|
||||||
{
|
{
|
||||||
case CR:
|
case CR:
|
||||||
case LF:
|
case LF:
|
||||||
if (!(format & DT_SINGLELINE))
|
if (!(format & DT_SINGLELINE))
|
||||||
{
|
{
|
||||||
if ((*count > 1) && (str[i] == CR) && (str[i+1] == LF))
|
if ((*count > 1) && (((str[i] == CR) && (str[i+1] == LF)) ||
|
||||||
|
((str[i] == LF) && (str[i+1] == CR))))
|
||||||
{
|
{
|
||||||
(*count)--;
|
(*count)--;
|
||||||
i++;
|
i++;
|
||||||
|
@ -375,89 +370,61 @@ static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
||||||
(*count)--;
|
(*count)--;
|
||||||
return (&str[i]);
|
return (&str[i]);
|
||||||
}
|
}
|
||||||
dest[j++] = str[i++];
|
/* else it's just another character */
|
||||||
if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
|
|
||||||
(format & DT_WORDBREAK))
|
|
||||||
{
|
|
||||||
if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
|
|
||||||
return NULL;
|
|
||||||
plen += size.cx;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PREFIX:
|
case PREFIX:
|
||||||
if (!(format & DT_NOPREFIX) && *count > 1)
|
if (!(format & DT_NOPREFIX) && *count > 1)
|
||||||
{
|
{
|
||||||
if (str[++i] == PREFIX)
|
if (str[++i] == PREFIX)
|
||||||
(*count)--;
|
(*count)--; /* and treat it as just another character */
|
||||||
else {
|
else {
|
||||||
prefix_offset = j;
|
prefix_offset = j;
|
||||||
|
normal_char = 0; /* we are skipping the PREFIX itself */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dest[j++] = str[i++];
|
|
||||||
if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
|
|
||||||
(format & DT_WORDBREAK))
|
|
||||||
{
|
|
||||||
if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
|
|
||||||
return NULL;
|
|
||||||
plen += size.cx;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAB:
|
case TAB:
|
||||||
if (format & DT_EXPANDTABS)
|
if (format & DT_EXPANDTABS)
|
||||||
{
|
{
|
||||||
wb_i = ++i;
|
if ((format & DT_WORDBREAK))
|
||||||
wb_j = j;
|
{
|
||||||
wb_count = *count;
|
wb_i = i+1;
|
||||||
|
wb_j = j;
|
||||||
|
wb_count = *count;
|
||||||
|
}
|
||||||
|
|
||||||
if (!GetTextExtentPointW(hdc, &dest[lasttab], j - lasttab, &size))
|
normal_char = 0;
|
||||||
return NULL;
|
dest[j++] = str[i++];
|
||||||
|
if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
|
||||||
numspaces = (tabwidth - size.cx) / spacewidth;
|
plen = ((plen/tabwidth)+1)*tabwidth;
|
||||||
for (k = 0; k < numspaces; k++)
|
|
||||||
dest[j++] = SPACE;
|
|
||||||
plen += tabwidth - size.cx;
|
|
||||||
lasttab = wb_j + numspaces;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dest[j++] = str[i++];
|
|
||||||
if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
|
|
||||||
(format & DT_WORDBREAK))
|
|
||||||
{
|
|
||||||
if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
|
|
||||||
return NULL;
|
|
||||||
plen += size.cx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPACE:
|
case SPACE:
|
||||||
dest[j++] = str[i++];
|
if ((format & DT_WORDBREAK))
|
||||||
if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
|
|
||||||
(format & DT_WORDBREAK))
|
|
||||||
{
|
{
|
||||||
wb_i = i;
|
wb_i = i+1;
|
||||||
wb_j = j - 1;
|
wb_j = j;
|
||||||
wb_count = *count;
|
wb_count = *count;
|
||||||
if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
|
}
|
||||||
return NULL;
|
|
||||||
plen += size.cx;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
if (normal_char)
|
||||||
|
{
|
||||||
dest[j++] = str[i++];
|
dest[j++] = str[i++];
|
||||||
if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
|
if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
|
||||||
(format & DT_WORDBREAK))
|
|
||||||
{
|
{
|
||||||
if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
|
if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
|
||||||
return NULL;
|
return NULL;
|
||||||
plen += size.cx;
|
plen += size.cx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(*count)--;
|
(*count)--;
|
||||||
if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
|
if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
|
||||||
|
@ -523,6 +490,39 @@ static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int of
|
||||||
DeleteObject (hpen);
|
DeleteObject (hpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are only going to need this until we correct the measuring in
|
||||||
|
* TEXT_NextLineW (coming soon)
|
||||||
|
*/
|
||||||
|
static int TEXT_TextExtent (HDC hdc, UINT flags, const WCHAR *line, int len, SIZE *size)
|
||||||
|
{
|
||||||
|
if ((flags & DT_EXPANDTABS))
|
||||||
|
{
|
||||||
|
SIZE tsize;
|
||||||
|
const WCHAR *p;
|
||||||
|
size->cx = 0;
|
||||||
|
size->cy = 0;
|
||||||
|
while (len)
|
||||||
|
{
|
||||||
|
p = line; while (p < line+len && *p != TAB) p++;
|
||||||
|
if (!GetTextExtentPointW (hdc, line, p-line, &tsize)) return 0;
|
||||||
|
size->cx += tsize.cx;
|
||||||
|
if (tsize.cy > size->cy) size->cy = tsize.cy;
|
||||||
|
len -= (p-line);
|
||||||
|
line=p;
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
assert (*line == TAB);
|
||||||
|
len--;
|
||||||
|
line++;
|
||||||
|
size->cx = ((size->cx/tabwidth)+1)*tabwidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return GetTextExtentPointW(hdc, line, len, size);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DrawTextExW (USER32.@)
|
* DrawTextExW (USER32.@)
|
||||||
*
|
*
|
||||||
|
@ -573,14 +573,10 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
||||||
dtp->uiLengthDrawn = 0; /* This param RECEIVES number of chars processed */
|
dtp->uiLengthDrawn = 0; /* This param RECEIVES number of chars processed */
|
||||||
}
|
}
|
||||||
|
|
||||||
tabstop = ((flags & DT_TABSTOP) && dtp) ? dtp->iTabLength : 8;
|
|
||||||
|
|
||||||
if (flags & DT_EXPANDTABS)
|
if (flags & DT_EXPANDTABS)
|
||||||
{
|
{
|
||||||
GetTextExtentPointW(hdc, SPACEW, 1, &size);
|
int tabstop = ((flags & DT_TABSTOP) && dtp) ? dtp->iTabLength : 8;
|
||||||
spacewidth = size.cx;
|
tabwidth = tm.tmAveCharWidth * tabstop;
|
||||||
GetTextExtentPointW(hdc, oW, 1, &size);
|
|
||||||
tabwidth = size.cx * tabstop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
|
if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
|
||||||
|
@ -591,7 +587,7 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
||||||
len = MAX_STATIC_BUFFER;
|
len = MAX_STATIC_BUFFER;
|
||||||
strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags);
|
strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags);
|
||||||
|
|
||||||
if (!GetTextExtentPointW(hdc, line, len, &size)) return 0;
|
if (!TEXT_TextExtent(hdc, flags, line, len, &size)) return 0;
|
||||||
if (flags & DT_CENTER) x = (rect->left + rect->right -
|
if (flags & DT_CENTER) x = (rect->left + rect->right -
|
||||||
size.cx) / 2;
|
size.cx) / 2;
|
||||||
else if (flags & DT_RIGHT) x = rect->right - size.cx;
|
else if (flags & DT_RIGHT) x = rect->right - size.cx;
|
||||||
|
@ -611,6 +607,22 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
||||||
int len_ellipsis;
|
int len_ellipsis;
|
||||||
int len_after_ellipsis;
|
int len_after_ellipsis;
|
||||||
|
|
||||||
|
if ((flags & DT_EXPANDTABS))
|
||||||
|
{
|
||||||
|
/* If there are tabs then we must only ellipsify the last
|
||||||
|
* segment. That will become trivial when we move the
|
||||||
|
* ellipsification into the TEXT_NextLineW (coming soon)
|
||||||
|
*/
|
||||||
|
const WCHAR *p;
|
||||||
|
p = line + len;
|
||||||
|
while (p > line)
|
||||||
|
if (*(--p) == TAB)
|
||||||
|
{
|
||||||
|
FIXME ("Ellipsification of single line tabbed strings will be fixed shortly\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & DT_PATH_ELLIPSIS)
|
if (flags & DT_PATH_ELLIPSIS)
|
||||||
{
|
{
|
||||||
/* We may need to remeasure the string because it was clipped */
|
/* We may need to remeasure the string because it was clipped */
|
||||||
|
@ -637,12 +649,54 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
||||||
}
|
}
|
||||||
if (!(flags & DT_CALCRECT))
|
if (!(flags & DT_CALCRECT))
|
||||||
{
|
{
|
||||||
if (!ExtTextOutW( hdc, x, y,
|
const WCHAR *str = line;
|
||||||
((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
|
int xseg = x;
|
||||||
((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
|
while (len)
|
||||||
rect, line, len, NULL )) return 0;
|
{
|
||||||
if (prefix_offset != -1)
|
int len_seg;
|
||||||
TEXT_DrawUnderscore (hdc, x, y + tm.tmAscent + 1, line, prefix_offset);
|
SIZE size;
|
||||||
|
if ((flags & DT_EXPANDTABS))
|
||||||
|
{
|
||||||
|
const WCHAR *p;
|
||||||
|
p = str; while (p < str+len && *p != TAB) p++;
|
||||||
|
len_seg = p - str;
|
||||||
|
if (len_seg != len && !GetTextExtentPointW(hdc, str, len_seg, &size))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len_seg = len;
|
||||||
|
|
||||||
|
if (!ExtTextOutW( hdc, xseg, y,
|
||||||
|
((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
|
||||||
|
((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
|
||||||
|
rect, str, len_seg, NULL )) return 0;
|
||||||
|
if (prefix_offset != -1 && prefix_offset < len_seg)
|
||||||
|
{
|
||||||
|
TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset);
|
||||||
|
}
|
||||||
|
len -= len_seg;
|
||||||
|
str += len_seg;
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
assert ((flags & DT_EXPANDTABS) && *str == TAB);
|
||||||
|
len--; str++;
|
||||||
|
xseg += ((size.cx/tabwidth)+1)*tabwidth;
|
||||||
|
if (prefix_offset != -1)
|
||||||
|
{
|
||||||
|
if (prefix_offset < len_seg)
|
||||||
|
{
|
||||||
|
/* We have just drawn an underscore; we ought to
|
||||||
|
* figure out where the next one is. I am going
|
||||||
|
* to leave it for now until I have a better model
|
||||||
|
* for the line, which will make reprefixing easier
|
||||||
|
*/
|
||||||
|
prefix_offset = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prefix_offset -= len_seg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (size.cx > max_width)
|
else if (size.cx > max_width)
|
||||||
max_width = size.cx;
|
max_width = size.cx;
|
||||||
|
|
Loading…
Reference in New Issue