Put in place a proper tab model within DrawText (also includes

simplifying TEXT_NextLineW to remove duplicate code).
This commit is contained in:
Bill Medland 2002-02-12 18:40:36 +00:00 committed by Alexandre Julliard
parent 48a87e6107
commit cabe8ca580
1 changed files with 128 additions and 74 deletions

View File

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