Files
raven/native/upstream/reactos-text/failure-propagation.patch
T

384 lines
14 KiB
Diff

--- a/win32ss/user/rtl/text.c
+++ b/win32ss/user/rtl/text.c
@@ -128,7 +128,7 @@
} ellipsis_data;
/*********************************************************************
- * TEXT_Ellipsify (static)
+ * TEXT_Ellipsify (static, failure)
*
* Add an ellipsis to the end of the given string whilst ensuring it fits.
*
@@ -156,10 +156,36 @@
* For now we will simply use three dots rather than worrying about whether
* the font contains an explicit ellipsis character.
*/
+typedef struct
+{
+ BOOL failed;
+ DWORD error;
+} layout_failure;
+
+static BOOL layout_extent_ex(layout_failure *failure, HDC dc, LPCWSTR text,
+ int count, int maximum, LPINT fit, LPINT widths, LPSIZE size)
+{
+ if (GetTextExtentExPointW(dc, text, count, maximum, fit, widths, size)) return TRUE;
+ if (!failure->failed) failure->error = GetLastError();
+ failure->failed = TRUE;
+ size->cx = size->cy = 0;
+ if (fit) *fit = 0;
+ return FALSE;
+}
+
+static BOOL layout_extent(layout_failure *failure, HDC dc, LPCWSTR text, int count, LPSIZE size)
+{
+ if (GetTextExtentPointW(dc, text, count, size)) return TRUE;
+ if (!failure->failed) failure->error = GetLastError();
+ failure->failed = TRUE;
+ size->cx = size->cy = 0;
+ return FALSE;
+}
+
static void TEXT_Ellipsify (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_before, int *len_ellip, layout_failure *failure)
{
unsigned int len_ellipsis;
unsigned int lo, mid, hi;
@@ -173,7 +199,7 @@
#ifdef _WIN32K_
GreGetTextExtentExW(hdc, str, *len_str, width, NULL, NULL, size, 0) &&
#else
- GetTextExtentExPointW(hdc, str, *len_str, width, NULL, NULL, size) &&
+ layout_extent_ex(failure, hdc, str, *len_str, width, NULL, NULL, size) &&
#endif
size->cx > width)
{
@@ -183,7 +209,7 @@
#ifdef _WIN32K_
if (!GreGetTextExtentExW(hdc, str, mid, width, NULL, NULL, size, 0))
#else
- if (!GetTextExtentExPointW(hdc, str, mid, width, NULL, NULL, size))
+ if (!layout_extent_ex(failure, hdc, str, mid, width, NULL, NULL, size))
#endif
break;
if (size->cx > width)
@@ -201,7 +227,7 @@
if (!GreGetTextExtentExW (hdc, str, *len_str + len_ellipsis, width,
NULL, NULL, size, 0)) break;
#else
- if (!GetTextExtentExPointW (hdc, str, *len_str + len_ellipsis, width,
+ if (!layout_extent_ex(failure, hdc, str, *len_str + len_ellipsis, width,
NULL, NULL, size)) break;
#endif
if (!*len_str || size->cx <= width) break;
@@ -220,7 +246,7 @@
}
/*********************************************************************
- * TEXT_PathEllipsify (static)
+ * TEXT_PathEllipsify (static, failure)
*
* Add an ellipsis to the provided string in order to make it fit within
* the width. The ellipsis is added as specified for the DT_PATH_ELLIPSIS
@@ -264,7 +290,7 @@
*/
static void TEXT_PathEllipsify (HDC hdc, WCHAR *str, unsigned int max_len,
unsigned int *len_str, int width, SIZE *size,
- WCHAR *modstr, ellipsis_data *pellip)
+ WCHAR *modstr, ellipsis_data *pellip, layout_failure *failure)
{
int len_ellipsis;
int len_trailing;
@@ -309,7 +335,7 @@
if (!GreGetTextExtentExW (hdc, str, *len_str + len_ellipsis, width,
NULL, NULL, size, 0)) break;
#else
- if (!GetTextExtentExPointW (hdc, str, *len_str + len_ellipsis, width,
+ if (!layout_extent_ex(failure, hdc, str, *len_str + len_ellipsis, width,
NULL, NULL, size)) break;
#endif
if (lastSlash == str || size->cx <= width) break;
@@ -368,7 +394,7 @@
};
/*********************************************************************
- * TEXT_WordBreak (static)
+ * TEXT_WordBreak (static, failure)
*
* Perform wordbreak processing on the given string
*
@@ -430,7 +456,7 @@
static void TEXT_WordBreak (HDC hdc, WCHAR *str, unsigned int max_str,
unsigned int *len_str,
int width, int format, unsigned int chars_fit,
- unsigned int *chars_used, SIZE *size)
+ unsigned int *chars_used, SIZE *size, layout_failure *failure)
{
WCHAR *p;
int word_fits;
@@ -508,7 +534,7 @@
#ifdef _WIN32K_
GreGetTextExtentExW (hdc, str, *len_str, 0, NULL, NULL, size, 0);
#else
- GetTextExtentExPointW (hdc, str, *len_str, 0, NULL, NULL, size);
+ layout_extent_ex(failure, hdc, str, *len_str, 0, NULL, NULL, size);
#endif
}
@@ -671,7 +697,7 @@
WCHAR *dest, int *len, int width, DWORD format,
SIZE *retsize, int last_line, WCHAR **p_retstr,
int tabwidth, int *pprefix_offset,
- ellipsis_data *pellip)
+ ellipsis_data *pellip, layout_failure *failure)
{
int i = 0, j = 0;
int plen = 0;
@@ -760,8 +786,9 @@
#ifdef _WIN32K_
GreGetTextExtentExW (hdc, dest + seg_j, j_in_seg, max_seg_width, (PULONG)&num_fit, NULL, &size, 0);
#else
- GetTextExtentExPointW (hdc, dest + seg_j, j_in_seg, max_seg_width, &num_fit, NULL, &size);
-#endif
+ layout_extent_ex(failure, hdc, dest + seg_j, j_in_seg, max_seg_width, &num_fit, NULL, &size);
+#endif
+ if (failure->failed) return NULL;
/* The Microsoft handling of various combinations of formats is weird.
* The following may very easily be incorrect if several formats are
@@ -775,7 +802,8 @@
const WCHAR *s;
unsigned int chars_used;
TEXT_WordBreak (hdc, dest+seg_j, maxl-seg_j, &j_in_seg,
- max_seg_width, format, num_fit, &chars_used, &size);
+ max_seg_width, format, num_fit, &chars_used, &size, failure);
+ if (failure->failed) return NULL;
line_fits = (size.cx <= max_seg_width);
/* and correct the counts */
TEXT_SkipChars (count, &s, seg_count, str+seg_i, i-seg_i,
@@ -791,7 +819,8 @@
if (!line_fits && (format & DT_PATH_ELLIPSIS))
{
TEXT_PathEllipsify (hdc, dest + seg_j, maxl-seg_j, &j_in_seg,
- max_seg_width, &size, *p_retstr, pellip);
+ max_seg_width, &size, *p_retstr, pellip, failure);
+ if (failure->failed) return NULL;
line_fits = (size.cx <= max_seg_width);
ellipsified = 1;
}
@@ -804,7 +833,8 @@
{
int before, len_ellipsis;
TEXT_Ellipsify (hdc, dest + seg_j, maxl-seg_j, &j_in_seg,
- max_seg_width, &size, *p_retstr, &before, &len_ellipsis);
+ max_seg_width, &size, *p_retstr, &before, &len_ellipsis, failure);
+ if (failure->failed) return NULL;
if (before > pellip->before)
{
/* We must have done a path ellipsis too */
@@ -895,7 +925,7 @@
* rect [in] Clipping rectangle (if not NULL)
*/
/* Synced with wine 1.1.32 */
-static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int offset, const RECT *rect)
+static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int offset, const RECT *rect, layout_failure *failure)
{
int prefix_x;
int prefix_end;
@@ -905,14 +935,16 @@
#ifdef _WIN32K_
GreGetTextExtentW (hdc, str, offset, &size, 0);
#else
- GetTextExtentPointW (hdc, str, offset, &size);
-#endif
+ layout_extent(failure, hdc, str, offset, &size);
+#endif
+ if (failure->failed) return;
prefix_x = x + size.cx;
#ifdef _WIN32K_
GreGetTextExtentW (hdc, str, offset+1, &size, 0);
#else
- GetTextExtentPointW (hdc, str, offset+1, &size);
-#endif
+ layout_extent(failure, hdc, str, offset+1, &size);
+#endif
+ if (failure->failed) return;
prefix_end = x + size.cx - 1;
/* The above method may eventually be slightly wrong due to kerning etc. */
@@ -935,10 +967,11 @@
GreDeleteObject (hpen);
#else
hpen = CreatePen (PS_SOLID, 1, GetTextColor (hdc));
+ if (!hpen) { failure->failed = TRUE; failure->error = GetLastError(); return; }
oldPen = SelectObject (hdc, hpen);
- MoveToEx (hdc, prefix_x, y, NULL);
- LineTo (hdc, prefix_end, y);
- SelectObject (hdc, oldPen);
+ if (!oldPen || !MoveToEx(hdc, prefix_x, y, NULL) || !LineTo(hdc, prefix_end, y))
+ { failure->failed = TRUE; failure->error = GetLastError(); }
+ if (oldPen) SelectObject (hdc, oldPen);
DeleteObject (hpen);
#endif
}
@@ -1096,7 +1129,11 @@
ellipsis_data ellip;
BOOL invert_y=FALSE;
- HRGN hrgn = 0;
+ HRGN hrgn = 0;
+ BOOL clipped = FALSE, has_clip = FALSE, succeeded = FALSE;
+ layout_failure state = {FALSE, 0}, *failure = &state;
+ DWORD error = 0;
+ retstr = NULL;
#ifdef _WIN32K_
TRACE("%S, %d, %08x\n", str, count, flags);
@@ -1116,7 +1153,7 @@
#ifdef _WIN32K_
GreGetTextMetricsW(hdc, &tm);
#else
- GetTextMetricsW(hdc, &tm);
+ if (!GetTextMetricsW(hdc, &tm)) return 0;
#endif
if (flags & DT_EXTERNALLEADING)
lh = tm.tmHeight + tm.tmExternalLeading;
@@ -1187,19 +1224,14 @@
#ifndef _WIN32K_ ///// Fix CORE-2201.
if (!(flags & DT_NOCLIP) )
{
- int hasClip;
+ int clip_result;
hrgn = CreateRectRgn(0,0,0,0);
- if (hrgn)
- {
- hasClip = GetClipRgn(hdc, hrgn);
- // If the region to be retrieved is NULL, the return value is 0.
- if (hasClip != 1)
- {
- DeleteObject(hrgn);
- hrgn = NULL;
- }
- IntersectClipRect(hdc, rect->left, rect->top, rect->right, rect->bottom);
- }
+ if (!hrgn) goto cleanup;
+ clip_result = GetClipRgn(hdc, hrgn);
+ if (clip_result < 0) goto cleanup;
+ has_clip = clip_result == 1;
+ if (!IntersectClipRect(hdc, rect->left, rect->top, rect->right, rect->bottom)) goto cleanup;
+ clipped = TRUE;
}
#else
if (!(flags & DT_NOCLIP) )
@@ -1226,7 +1258,7 @@
#else
retstr = HeapAlloc(GetProcessHeap(), 0, size_retstr);
#endif
- if (!retstr) return 0;
+ if (!retstr) goto cleanup;
memcpy (retstr, str, size_retstr);
}
else
@@ -1243,7 +1275,8 @@
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, &p_retstr, tabwidth, &prefix_offset, &ellip);
+ strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size, last_line, &p_retstr, tabwidth, &prefix_offset, &ellip, failure);
+ if (failure->failed) goto cleanup;
#ifdef __REACTOS__
if (flags & DT_CENTER)
@@ -1294,15 +1327,10 @@
#ifdef _WIN32K_
!GreGetTextExtentW(hdc, str, len_seg, &size, 0))
#else
- !GetTextExtentPointW(hdc, str, len_seg, &size))
+ !layout_extent(failure, hdc, str, len_seg, &size))
#endif
{
-#ifdef _WIN32K_
- ExFreePoolWithTag(retstr, USERTAG_RTL);
-#else
- HeapFree (GetProcessHeap(), 0, retstr);
-#endif
- return 0;
+goto cleanup;
}
}
else
@@ -1319,16 +1347,12 @@
rect, str, len_seg, NULL ))
#endif
{
-#ifdef _WIN32K_
- ExFreePoolWithTag(retstr, USERTAG_RTL);
-#else
- HeapFree (GetProcessHeap(), 0, retstr);
-#endif
- return 0;
+goto cleanup;
}
if (prefix_offset != -1 && prefix_offset < len_seg)
{
- TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect);
+ TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect, failure);
+ if (failure->failed) goto cleanup;
}
len -= len_seg;
str += len_seg;
@@ -1364,27 +1388,6 @@
}
while (strPtr && !last_line);
-#ifndef _WIN32K_
- if (!(flags & DT_NOCLIP) )
- {
- SelectClipRgn(hdc, hrgn); // This should be NtGdiExtSelectClipRgn, but due to ReactOS build rules this option is next:
- GdiFlush(); // Flush the batch and level up! See CORE-16498.
- if (hrgn)
- {
- DeleteObject(hrgn);
- }
- }
-#else
- if (!(flags & DT_NOCLIP) )
- {
- NtGdiExtSelectClipRgn(hdc, hrgn, RGN_COPY);
- if (hrgn)
- {
- GreDeleteObject(hrgn);
- }
- }
-#endif
-
if (flags & DT_CALCRECT)
{
rect->right = rect->left + max_width;
@@ -1395,12 +1398,16 @@
if (retstr)
{
memcpy (str, retstr, size_retstr);
-#ifdef _WIN32K_
- ExFreePoolWithTag(retstr, USERTAG_RTL);
-#else
- HeapFree (GetProcessHeap(), 0, retstr);
-#endif
- }
+
+ }
+ succeeded = TRUE;
+cleanup:
+ error = failure->failed ? failure->error : GetLastError();
+ if (clipped && !SelectClipRgn(hdc, has_clip ? hrgn : NULL))
+ { if (succeeded) error = GetLastError(); succeeded = FALSE; }
+ if (hrgn) DeleteObject(hrgn);
+ if (retstr) HeapFree(GetProcessHeap(), 0, retstr);
+ if (!succeeded) { SetLastError(error); return 0; }
return y - rect->top;
}