From: chenjiangyi chenjiangyi@uniontech.com
uiLengthDrawn should represent the number of characters that have been processed. However, the original implementation uses len (the count of displayed characters in the current line), which is not accurate.
When text requires line breaks or special processing (such as adding an ellipsis), the actual number of processed characters may differ from the number of displayed characters.
When the DT_CALCRECT flag is absent, len gets decremented to 0 during the drawing loop.
Consequently, uiLengthDrawn becomes inaccurate since it relies on len's value for statistics. --- dlls/user32/text.c | 128 +++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 63 deletions(-)
diff --git a/dlls/user32/text.c b/dlls/user32/text.c index 1896627c893..6c05d1067e5 100644 --- a/dlls/user32/text.c +++ b/dlls/user32/text.c @@ -871,7 +871,7 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, WCHAR *retstr; size_t size_retstr; WCHAR line[MAX_BUFFER]; - int len, lh, count=i_count; + int len, lh, old_count, count=i_count; TEXTMETRICW tm; int lmargin = 0, rmargin = 0; int x, y, width; @@ -974,85 +974,87 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, do { len = ARRAY_SIZE(line); - if (invert_y) - last_line = !(flags & DT_NOCLIP) && y - ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) < rect->bottom; - else - 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, last_line, retstr, tabwidth, &prefix_offset, &ellip); + if (invert_y) + last_line = !(flags & DT_NOCLIP) && y - ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) < rect->bottom; + else + last_line = !(flags & DT_NOCLIP) && y + ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) > rect->bottom; + + old_count = count; + strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size, last_line, retstr, tabwidth, &prefix_offset, &ellip); + if (dtp) + dtp->uiLengthDrawn += old_count - count;
if (flags & DT_CENTER) x = (rect->left + lmargin + rect->right - rmargin - size.cx) / 2; else if (flags & DT_RIGHT) x = rect->right - size.cx - rmargin;
- if (flags & DT_SINGLELINE) - { - if (flags & DT_VCENTER) y = rect->top + - (rect->bottom - rect->top) / 2 - size.cy / 2; - else if (flags & DT_BOTTOM) y = rect->bottom - size.cy; + if (flags & DT_SINGLELINE) + { + if (flags & DT_VCENTER) y = rect->top + + (rect->bottom - rect->top) / 2 - size.cy / 2; + else if (flags & DT_BOTTOM) y = rect->bottom - size.cy; }
- if (!(flags & DT_CALCRECT)) - { - const WCHAR *str = line; - int xseg = x; - while (len) - { - int len_seg; - 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)) goto done; - } - 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 )) - goto done; - if (prefix_offset != -1 && prefix_offset < len_seg) - { - TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect); - } - len -= len_seg; - str += len_seg; - if (len) + if (!(flags & DT_CALCRECT)) + { + const WCHAR *str = line; + int xseg = x; + while (len) { - assert ((flags & DT_EXPANDTABS) && *str == TAB); - len--; str++; - xseg += ((size.cx/tabwidth)+1)*tabwidth; - if (prefix_offset != -1) + int len_seg; + 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)) goto done; + } + 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 )) + goto done; + if (prefix_offset != -1 && prefix_offset < len_seg) { - if (prefix_offset < len_seg) + TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect); + } + 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) { - /* 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. - * This is where ellip would be used. - */ - 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. + * This is where ellip would be used. + */ + prefix_offset = -1; + } + else + prefix_offset -= len_seg; } - else - prefix_offset -= len_seg; } } - } - } - else if (size.cx > max_width) - max_width = size.cx; + } + else if (size.cx > max_width) + max_width = size.cx;
if (invert_y) - y -= lh; + y -= lh; else - y += lh; - if (dtp) - dtp->uiLengthDrawn += len; + y += lh; } while (strPtr && !last_line);