mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-07 22:06:33 +00:00
384 lines
14 KiB
Diff
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;
|
|
}
|
|
|