Drawtext tidying up ready for the next big change:
- Fix brainfade in previous delta - Move ellipsification results to static memory; they are going to have to be referenced inside NextLineW and the arg list is too big already. - Add the missing ellipsification result (len_under) to simplify coding. - Slight correction to prefix tracking for when there are several underlined characters on a single line (DT_EXPANDTABS only). - Allocate and free the temporary copy required for DT_MODIFYSTRING rather than using a fixed size stack array. - Introduce lastline into the main loop; it simplifies the code and we are going to need it.
This commit is contained in:
parent
8777effb78
commit
8513907f2c
|
@ -76,8 +76,13 @@ DEFAULT_DEBUG_CHANNEL(text);
|
|||
|
||||
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
|
||||
|
||||
/* These will have to go into a structure to be passed around rather than
|
||||
* sitting in static memory
|
||||
*/
|
||||
static int tabwidth;
|
||||
static int prefix_offset;
|
||||
static int len_before_ellipsis, len_ellipsis, len_under_ellipsis,
|
||||
len_after_ellipsis;
|
||||
|
||||
/*********************************************************************
|
||||
* TEXT_Ellipsify (static)
|
||||
|
@ -165,6 +170,7 @@ static void TEXT_Ellipsify (HDC hdc, WCHAR *str, unsigned int max_len,
|
|||
* the modified string is not required.
|
||||
* len_before [out] The number of characters before the ellipsis.
|
||||
* len_ellip [out] The number of characters in the ellipsis.
|
||||
* len_under [out] The number of characters replaced by the ellipsis.
|
||||
* len_after [out] The number of characters after the ellipsis.
|
||||
*
|
||||
* For now we will simply use three dots rather than worrying about whether
|
||||
|
@ -190,7 +196,8 @@ static void TEXT_Ellipsify (HDC hdc, WCHAR *str, unsigned int max_len,
|
|||
static void TEXT_PathEllipsify (HDC hdc, WCHAR *str, unsigned int max_len,
|
||||
unsigned int *len_str, int width, SIZE *size,
|
||||
WCHAR *modstr,
|
||||
int *len_before, int *len_ellip, int *len_after)
|
||||
int *len_before, int *len_ellip, int *len_under,
|
||||
int *len_after)
|
||||
{
|
||||
int len_ellipsis;
|
||||
int len_trailing;
|
||||
|
@ -220,6 +227,7 @@ static void TEXT_PathEllipsify (HDC hdc, WCHAR *str, unsigned int max_len,
|
|||
* of the last slash and len_trailing includes the ellipsis
|
||||
*/
|
||||
|
||||
*len_under = 0;
|
||||
for ( ; ; )
|
||||
{
|
||||
if (!GetTextExtentExPointW (hdc, str, *len_str + len_ellipsis, width,
|
||||
|
@ -230,6 +238,7 @@ static void TEXT_PathEllipsify (HDC hdc, WCHAR *str, unsigned int max_len,
|
|||
/* overlap-safe movement to the left */
|
||||
memmove (lastSlash-1, lastSlash, len_trailing * sizeof(WCHAR));
|
||||
lastSlash--;
|
||||
(*len_under)++;
|
||||
|
||||
assert (*len_str);
|
||||
(*len_str)--;
|
||||
|
@ -533,6 +542,8 @@ static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
|||
int max_seg_width;
|
||||
int num_fit;
|
||||
int word_broken;
|
||||
int line_fits;
|
||||
int j_in_seg;
|
||||
|
||||
|
||||
/* For each text segment in the line */
|
||||
|
@ -573,10 +584,14 @@ static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
|||
/* Swallow it before we see it again */
|
||||
(*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
|
||||
}
|
||||
else
|
||||
else if (prefix_offset == -1 || prefix_offset >= seg_j)
|
||||
{
|
||||
prefix_offset = j;
|
||||
}
|
||||
/* else the previous prefix was in an earlier segment of the
|
||||
* line; we will leave it to the drawing code to catch this
|
||||
* one.
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -587,25 +602,28 @@ static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
|||
|
||||
/* Measure the whole text segment and possibly WordBreak it */
|
||||
|
||||
j_in_seg = j - seg_j;
|
||||
max_seg_width = width - plen;
|
||||
GetTextExtentExPointW (hdc, dest + seg_j, j - seg_j, max_seg_width, &num_fit, NULL, &size);
|
||||
GetTextExtentExPointW (hdc, dest + seg_j, j_in_seg, max_seg_width, &num_fit, NULL, &size);
|
||||
|
||||
word_broken = 0;
|
||||
if (num_fit < j-seg_j && (format & DT_WORDBREAK))
|
||||
line_fits = (num_fit >= j_in_seg);
|
||||
if (!line_fits && (format & DT_WORDBREAK))
|
||||
{
|
||||
const WCHAR *s;
|
||||
int chars_used;
|
||||
int j_in_seg = j-seg_j;
|
||||
TEXT_WordBreak (hdc, dest+seg_j, maxl-seg_j, &j_in_seg,
|
||||
max_seg_width, format, num_fit, &chars_used, &size);
|
||||
line_fits = (size.cx <= max_seg_width);
|
||||
/* and correct the counts */
|
||||
j = seg_j + j_in_seg;
|
||||
TEXT_SkipChars (count, &s, seg_count, str+seg_i, i-seg_i,
|
||||
chars_used, !(format & DT_NOPREFIX));
|
||||
i = s - str;
|
||||
word_broken = 1;
|
||||
}
|
||||
|
||||
j = seg_j + j_in_seg;
|
||||
|
||||
plen += size.cx;
|
||||
if (size.cy > retsize->cy)
|
||||
retsize->cy = size.cy;
|
||||
|
@ -616,10 +634,10 @@ static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
|
|||
break;
|
||||
else if (str[i] == CR || str[i] == LF)
|
||||
{
|
||||
count--, i++;
|
||||
if (count && (str[i] == CR || str[i] == LF) && str[i] != str[i-1])
|
||||
(*count)--, i++;
|
||||
if (*count && (str[i] == CR || str[i] == LF) && str[i] != str[i-1])
|
||||
{
|
||||
count--, i++;
|
||||
(*count)--, i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -687,6 +705,8 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
{
|
||||
SIZE size;
|
||||
const WCHAR *strPtr;
|
||||
WCHAR *retstr, *p_retstr;
|
||||
size_t size_retstr;
|
||||
static WCHAR line[MAX_STATIC_BUFFER];
|
||||
int len, lh, count=i_count;
|
||||
TEXTMETRICW tm;
|
||||
|
@ -694,6 +714,7 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
int x = rect->left, y = rect->top;
|
||||
int width = rect->right - rect->left;
|
||||
int max_width = 0;
|
||||
int last_line;
|
||||
|
||||
TRACE("%s, %d , [(%d,%d),(%d,%d)]\n", debugstr_wn (str, count), count,
|
||||
rect->left, rect->top, rect->right, rect->bottom);
|
||||
|
@ -732,10 +753,25 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
|
||||
if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
|
||||
|
||||
if (flags & DT_MODIFYSTRING)
|
||||
{
|
||||
size_retstr = (count + 4) * sizeof (WCHAR);
|
||||
retstr = HeapAlloc(GetProcessHeap(), 0, size_retstr);
|
||||
if (!retstr) return 0;
|
||||
memcpy (retstr, str, size_retstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_retstr = 0;
|
||||
retstr = NULL;
|
||||
}
|
||||
p_retstr = retstr;
|
||||
|
||||
do
|
||||
{
|
||||
prefix_offset = -1;
|
||||
len = MAX_STATIC_BUFFER;
|
||||
last_line = !(flags & DT_NOCLIP) && y + ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) > rect->bottom;
|
||||
strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size);
|
||||
|
||||
if (flags & DT_CENTER) x = (rect->left + rect->right -
|
||||
|
@ -752,11 +788,6 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
if ((flags & DT_SINGLELINE) && size.cx > width &&
|
||||
(flags & (DT_PATH_ELLIPSIS | DT_END_ELLIPSIS | DT_WORD_ELLIPSIS)))
|
||||
{
|
||||
WCHAR tmpstr[countof(line)];
|
||||
int len_before_ellipsis;
|
||||
int len_ellipsis;
|
||||
int len_after_ellipsis;
|
||||
|
||||
if ((flags & DT_EXPANDTABS))
|
||||
{
|
||||
/* If there are tabs then we must only ellipsify the last
|
||||
|
@ -778,23 +809,20 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
/* We may need to remeasure the string because it was clipped */
|
||||
if ((flags & DT_WORDBREAK) || !(flags & DT_NOCLIP))
|
||||
TEXT_CopySansPrefix ((flags & DT_NOPREFIX), line, &len, str, i_count >= 0 ? i_count : strlenW(str));
|
||||
TEXT_PathEllipsify (hdc, line, countof(line), &len, width, &size, tmpstr, &len_before_ellipsis, &len_ellipsis, &len_after_ellipsis);
|
||||
TEXT_PathEllipsify (hdc, line, countof(line), &len, width, &size, retstr, &len_before_ellipsis, &len_ellipsis, &len_under_ellipsis, &len_after_ellipsis);
|
||||
}
|
||||
else
|
||||
{
|
||||
TEXT_Ellipsify (hdc, line, countof(line), &len, width, &size, tmpstr, &len_before_ellipsis, &len_ellipsis);
|
||||
TEXT_Ellipsify (hdc, line, countof(line), &len, width, &size, retstr, &len_before_ellipsis, &len_ellipsis);
|
||||
len_after_ellipsis = 0;
|
||||
len_under_ellipsis = 0; /* It is under the path ellipsis */
|
||||
}
|
||||
|
||||
strPtr = NULL;
|
||||
|
||||
if (prefix_offset >= 0 &&
|
||||
prefix_offset >= len_before_ellipsis)
|
||||
prefix_offset = TEXT_Reprefix (str, len_before_ellipsis, strlenW(str)-len_ellipsis-len_before_ellipsis-len_after_ellipsis, len_ellipsis, len_after_ellipsis);
|
||||
|
||||
if (flags & DT_MODIFYSTRING)
|
||||
strcpyW(str, tmpstr);
|
||||
|
||||
prefix_offset = TEXT_Reprefix (str, len_before_ellipsis, len_under_ellipsis, len_ellipsis, len_after_ellipsis);
|
||||
|
||||
}
|
||||
if (!(flags & DT_CALCRECT))
|
||||
|
@ -852,18 +880,10 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
max_width = size.cx;
|
||||
|
||||
y += lh;
|
||||
if (strPtr)
|
||||
{
|
||||
if (!(flags & DT_NOCLIP))
|
||||
{
|
||||
if (y > rect->bottom - lh)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dtp)
|
||||
dtp->uiLengthDrawn += len;
|
||||
}
|
||||
while (strPtr);
|
||||
while (strPtr && !last_line);
|
||||
|
||||
if (flags & DT_CALCRECT)
|
||||
{
|
||||
|
@ -872,6 +892,11 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
|
|||
if (dtp)
|
||||
rect->right += lmargin + rmargin;
|
||||
}
|
||||
if (retstr)
|
||||
{
|
||||
memcpy (str, retstr, size_retstr);
|
||||
HeapFree (GetProcessHeap(), 0, retstr);
|
||||
}
|
||||
return y - rect->top;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue